From 63d08c0342ba4b5132de7b3098797a80eba8b757 Mon Sep 17 00:00:00 2001 From: Lukas <134181853+bo2themax@users.noreply.github.com> Date: Thu, 30 Jul 2026 10:21:27 +0200 Subject: [PATCH] macOS: show cancel update option when its actually cancellable `extracting` and `installing` state aren't cancellable by us --- .../TerminalCommandPalette.swift | 52 ++++++++++--------- .../Features/Update/UpdateViewModel.swift | 28 +++++++--- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift b/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift index 264e67cf8..4ad690c19 100644 --- a/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift +++ b/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift @@ -84,35 +84,39 @@ struct TerminalCommandPaletteView: View { private var updateOptions: [CommandOption] { var options: [CommandOption] = [] - guard let updateViewModel, updateViewModel.state.isInstallable else { + guard let updateViewModel else { return options } - // We override the update available one only because we want to properly - // convey it'll go all the way through. - let title: String - if case .updateAvailable = updateViewModel.state { - title = "Update Ghostty and Restart" - } else { - title = updateViewModel.text + if updateViewModel.state.isInstallable { + // We override the update available one only because we want to properly + // convey it'll go all the way through. + let title: String + if case .updateAvailable = updateViewModel.state { + title = "Update Ghostty and Restart" + } else { + title = updateViewModel.text + } + + options.append(CommandOption( + title: title, + description: updateViewModel.description, + leadingIcon: updateViewModel.iconName ?? "shippingbox.fill", + badge: updateViewModel.badge, + emphasis: true + ) { + (NSApp.delegate as? AppDelegate)?.updateController.viewModel.state.confirm() + }) } - options.append(CommandOption( - title: title, - description: updateViewModel.description, - leadingIcon: updateViewModel.iconName ?? "shippingbox.fill", - badge: updateViewModel.badge, - emphasis: true - ) { - (NSApp.delegate as? AppDelegate)?.updateController.viewModel.state.confirm() - }) - - options.append(CommandOption( - title: "Cancel or Skip Update", - description: "Dismiss the current update process" - ) { - updateViewModel.state.cancel() - }) + if updateViewModel.state.isCancellable { + options.append(CommandOption( + title: "Cancel or Skip Update", + description: "Dismiss the current update process" + ) { + updateViewModel.state.cancel() + }) + } return options } diff --git a/macos/Sources/Features/Update/UpdateViewModel.swift b/macos/Sources/Features/Update/UpdateViewModel.swift index 8e66f4a16..73e03d1df 100644 --- a/macos/Sources/Features/Update/UpdateViewModel.swift +++ b/macos/Sources/Features/Update/UpdateViewModel.swift @@ -205,20 +205,34 @@ enum UpdateState: Equatable { } } + var isCancellable: Bool { + cancelAction != nil + } + func cancel() { + cancelAction?() + } + + private var cancelAction: (() -> Void)? { switch self { + case .idle: + nil + case .permissionRequest: + nil case .checking(let checking): - checking.cancel() + checking.cancel case .updateAvailable(let available): - available.reply(.dismiss) + { available.reply(.dismiss) } case .downloading(let downloading): - downloading.cancel() + downloading.cancel case .notFound(let notFound): - notFound.acknowledgement() + notFound.acknowledgement case .error(let err): - err.dismiss() - default: - break + err.dismiss + case .extracting: + nil + case .installing: + nil } }