From e47455b3f881a2092bbed0e49e7a78d265c6a8f7 Mon Sep 17 00:00:00 2001 From: maxsoch Date: Mon, 6 Jul 2026 21:29:23 +0200 Subject: [PATCH] fix: confirm before Upgrade All, warn that running apps may close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit brew upgrade also upgrades casks, and replacing a cask quits the running app (e.g. the browser) with no warning. Upgrade All now shows an NSAlert listing the outdated packages and warning that running apps may be closed, with a Cancel option. NSApp.activate is needed because BrewBar is an accessory app (no Dock icon) — without it the modal alert can appear behind other windows. Co-Authored-By: Claude Fable 5 --- BrewBar/BrewBarApp.swift | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/BrewBar/BrewBarApp.swift b/BrewBar/BrewBarApp.swift index 9df1548..793e41f 100644 --- a/BrewBar/BrewBarApp.swift +++ b/BrewBar/BrewBarApp.swift @@ -237,6 +237,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { } @objc func upgradeAll() { + guard confirmUpgrade() else { return } + statusMenuItem.title = "Upgrading..." runBrew("update") { _ in @@ -246,6 +248,30 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } + func confirmUpgrade() -> Bool { + let alert = NSAlert() + alert.alertStyle = .warning + + if cachedOutdated.isEmpty { + alert.messageText = "Upgrade all outdated packages?" + } else { + alert.messageText = "Upgrade \(cachedOutdated.count) package\(cachedOutdated.count == 1 ? "" : "s")?" + } + + var info = "Apps upgraded as casks (like a web browser) may be closed and replaced while running, without further warning. Save your work first." + if !cachedOutdated.isEmpty { + info += "\n\n" + cachedOutdated.joined(separator: "\n") + } + alert.informativeText = info + + alert.addButton(withTitle: "Upgrade") + alert.addButton(withTitle: "Cancel") + + // accessory app: bring the alert to the front, otherwise it can appear behind other windows + NSApp.activate(ignoringOtherApps: true) + return alert.runModal() == .alertFirstButtonReturn + } + /// ✅ SMART refresh (uses cache) @objc func refreshOutdatedList() { // if fetched in last 5s → uses cache