feat: add contextual actions and recoverable application uninstall

This commit is contained in:
2026-10-12 15:01:15 +02:00
parent 8d8e2278ab
commit 2598f6f1dd
10 changed files with 2361 additions and 12 deletions
+14 -2
View File
@@ -90,10 +90,12 @@ struct ConjureApp {
@MainActor
private final class ApplicationDelegate: NSObject, NSApplicationDelegate {
private lazy var launcher = LauncherWindowController()
private let uninstaller = ApplicationUninstaller()
private lazy var launcher = LauncherWindowController(uninstaller: uninstaller)
private lazy var shortcut = GlobalShortcut { [weak self] in self?.launcher.toggle() }
private lazy var settings = SettingsWindowController(shortcut: shortcut)
private var startupShortcutError: String?
private var startupRecoveryMessage: String?
private var isLoginLaunch: Bool {
let event = NSAppleEventManager.shared().currentAppleEvent
@@ -109,6 +111,15 @@ private final class ApplicationDelegate: NSObject, NSApplicationDelegate {
let quitItem = menu.addItem(withTitle: "Quit Conjure", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")
quitItem.target = NSApplication.shared
launcher.window?.contentView?.menu = menu
let loginLaunch = isLoginLaunch
settings.retryUninstallRecovery = { [uninstaller] in await uninstaller.recover() }
Task {
let report = await uninstaller.recover()
guard !report.messages.isEmpty else { return }
startupRecoveryMessage = report.messages.joined(separator: "\n")
settings.setUninstallRecoveryReport(report)
if !loginLaunch { showSettings(nil) }
}
if !isLoginLaunch {
launcher.present()
}
@@ -125,7 +136,7 @@ private final class ApplicationDelegate: NSObject, NSApplicationDelegate {
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows: Bool) -> Bool {
guard !isLoginLaunch else { return false }
launcher.present()
if startupShortcutError != nil {
if startupShortcutError != nil || startupRecoveryMessage != nil {
showSettings(nil)
}
return false
@@ -134,6 +145,7 @@ private final class ApplicationDelegate: NSObject, NSApplicationDelegate {
@objc func showSettings(_ sender: Any?) {
settings.present(error: startupShortcutError)
startupShortcutError = nil
startupRecoveryMessage = nil
}
func applicationWillTerminate(_ notification: Notification) {