From 962b31b9150b9904ef3b7e9d45ec8c0e5f979257 Mon Sep 17 00:00:00 2001 From: PathGao Date: Mon, 31 Aug 2026 21:44:37 +0800 Subject: [PATCH] A menu bar icon macOS will not draw no longer quits the app `statusItem.behavior` was `[.removalAllowed, .terminationOnRemoval]`, which reads as "dragging the icon out quits the app" and is also how macOS refusing to place the icon arrives. AppKit delivers both as the same removal, so a refusal quit the app about 180ms into launch, before any window, with no crash and nothing said. Double-clicking the app then did nothing at all. The refusal has nothing to do with the user. macOS 26 files a menu bar item under the process that launched it, so a build started once by another app inherits that app's menu bar permission for good, and a denied one leaves Nifro unlaunchable with no way to find out why. `.removalAllowed` goes with it: an icon the user can drag away from an app that no longer quits is an app with no interface and no way back. Quit is in the panel footer, and Hide menu bar icon is the setting for an icon somebody does not want. --- Nifro/App/AppState.swift | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Nifro/App/AppState.swift b/Nifro/App/AppState.swift index feed8cf..2415c67 100644 --- a/Nifro/App/AppState.swift +++ b/Nifro/App/AppState.swift @@ -13,7 +13,24 @@ final class AppState: ObservableObject { private(set) lazy var statusItem = with(NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)) { $0.isVisible = true - $0.behavior = [.removalAllowed, .terminationOnRemoval] + + // No behavior at all, where this used to be `[.removalAllowed, .terminationOnRemoval]`. + // + // `.terminationOnRemoval` reads as "dragging the icon out quits the app", and that is one of the + // two things it does. The other is that *macOS refusing to draw the icon* is delivered as the + // same removal, and the app then quits itself roughly 180ms into launch — before any window, + // with no crash and nothing said. It is refused for reasons that have nothing to do with the + // user: macOS 26 files a menu bar item under the app that launched the process, so a build + // started once by another app inherits that app's menu bar permission for good, and a denied + // one leaves Nifro unlaunchable by double-click with no way to find out why. + // + // A menu bar icon that will not appear is a bad state either way. Quitting is the wrong answer + // to it: the app is the icon, so the icon going is the whole of what the user can see, and the + // process staying up is what leaves Settings and the Shortcuts intents reachable to say so. + // `.removalAllowed` goes with it — an icon the user can drag away from an app that no longer + // quits is an app with no interface and no way back. Quit is in the panel's footer, and the + // setting for an icon somebody does not want is Hide menu bar icon. + $0.behavior = [] // A status item with a `menu` opens it on any click and never sends its action, so it has none: // the button handles the click itself and shows the panel.