#if os(macOS) import AppKit import BurrowConfiguration import BurrowCore import BurrowUI import SwiftUI import libburrow @MainActor class AppDelegate: NSObject, NSApplicationDelegate { private var windowController: NSWindowController? private let logger = Logger.logger(for: AppDelegate.self) private let quitItem = AppDelegate.makeQuitItem() private lazy var openItem: NSMenuItem = { let item = NSMenuItem( title: "Open Burrow", action: #selector(openWindow), keyEquivalent: "o" ) item.target = self item.keyEquivalentModifierMask = .command return item }() private let toggleItem: NSMenuItem = { let toggleView = NSHostingView(rootView: MenuItemToggleView()) toggleView.frame.size = CGSize(width: 300, height: 32) toggleView.autoresizingMask = [.width] let toggleItem = NSMenuItem() toggleItem.view = toggleView return toggleItem }() private lazy var menu: NSMenu = { let menu = NSMenu() menu.items = [ toggleItem, openItem, .separator(), quitItem ] return menu }() private lazy var statusItem: NSStatusItem = { let statusBar = NSStatusBar.system let statusItem = statusBar.statusItem(withLength: NSStatusItem.squareLength) if let button = statusItem.button { button.image = NSImage(systemSymbolName: "pipe.and.drop.fill", accessibilityDescription: nil) } return statusItem }() func applicationDidFinishLaunching(_ notification: Notification) { installMainMenu() startDaemon() statusItem.menu = menu } private func startDaemon() { do { libburrow.spawnInProcess( socketPath: try Constants.socketURL.path(percentEncoded: false), databasePath: try Constants.databaseURL.path(percentEncoded: false) ) } catch { logger.error("Failed to spawn daemon thread: \(error)") } } private func installMainMenu() { let mainMenu = NSMenu(title: "Burrow") let appItem = NSMenuItem(title: "Burrow", action: nil, keyEquivalent: "") let appMenu = NSMenu(title: "Burrow") let aboutItem = NSMenuItem( title: "About Burrow", action: #selector(NSApplication.orderFrontStandardAboutPanel(_:)), keyEquivalent: "" ) aboutItem.target = NSApplication.shared appMenu.addItem(aboutItem) appMenu.addItem(.separator()) appMenu.addItem(Self.makeQuitItem()) appItem.submenu = appMenu mainMenu.addItem(appItem) let editItem = NSMenuItem(title: "Edit", action: nil, keyEquivalent: "") editItem.submenu = makeEditMenu() mainMenu.addItem(editItem) NSApplication.shared.mainMenu = mainMenu } private static func makeQuitItem() -> NSMenuItem { let quitItem = NSMenuItem( title: "Quit Burrow", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q" ) quitItem.target = NSApplication.shared quitItem.keyEquivalentModifierMask = .command return quitItem } private func makeEditMenu() -> NSMenu { let editMenu = NSMenu(title: "Edit") editMenu.addItem(NSMenuItem(title: "Undo", action: Selector(("undo:")), keyEquivalent: "z")) editMenu.addItem(NSMenuItem(title: "Redo", action: Selector(("redo:")), keyEquivalent: "Z")) editMenu.addItem(.separator()) editMenu.addItem(NSMenuItem(title: "Cut", action: #selector(NSText.cut(_:)), keyEquivalent: "x")) editMenu.addItem(NSMenuItem(title: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c")) editMenu.addItem(NSMenuItem(title: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v")) let pastePlainItem = NSMenuItem( title: "Paste and Match Style", action: #selector(NSTextView.pasteAsPlainText(_:)), keyEquivalent: "V" ) pastePlainItem.keyEquivalentModifierMask = [.command, .option, .shift] editMenu.addItem(pastePlainItem) editMenu.addItem(NSMenuItem(title: "Delete", action: #selector(NSText.delete(_:)), keyEquivalent: "")) editMenu.addItem(.separator()) editMenu.addItem(NSMenuItem(title: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a")) return editMenu } @objc private func openWindow() { if let window = windowController?.window { window.makeKeyAndOrderFront(nil) NSApplication.shared.activate(ignoringOtherApps: true) return } let contentView = BurrowView() let hostingController = NSHostingController(rootView: contentView) if #available(macOS 13.0, *) { hostingController.sizingOptions = [] } let window = NSWindow(contentViewController: hostingController) window.title = "Burrow" window.setContentSize(NSSize(width: 820, height: 720)) window.contentMinSize = NSSize(width: 640, height: 560) window.styleMask.insert([.titled, .closable, .miniaturizable, .resizable]) window.center() let controller = NSWindowController(window: window) controller.shouldCascadeWindows = true controller.showWindow(nil) windowController = controller NSApplication.shared.activate(ignoringOtherApps: true) } } @main enum BurrowApplication { @MainActor private static let delegate = AppDelegate() @MainActor static func main() { let application = NSApplication.shared application.delegate = delegate application.setActivationPolicy(.accessory) application.finishLaunching() application.run() } } #endif