From 0ff73333c067af96bcb829c900026d6b12fcff4e Mon Sep 17 00:00:00 2001 From: Zhuohao Zheng <2200296024@qq.com> Date: Sun, 22 Mar 2026 22:40:56 +0800 Subject: [PATCH] Add hide menu bar icon option with reopen restore logic --- BLEUnlock/AppDelegate.swift | 48 ++++++++++++++++++++- BLEUnlock/Base.lproj/Localizable.strings | 1 + BLEUnlock/Info.plist | 2 +- BLEUnlock/ja.lproj/Localizable.strings | 1 + BLEUnlock/zh-Hans.lproj/Localizable.strings | 1 + 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/BLEUnlock/AppDelegate.swift b/BLEUnlock/AppDelegate.swift index 4ee9c91..7fd2801 100644 --- a/BLEUnlock/AppDelegate.swift +++ b/BLEUnlock/AppDelegate.swift @@ -9,6 +9,8 @@ func t(_ key: String) -> String { @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, NSMenuItemValidation, NSUserNotificationCenterDelegate, BLEDelegate { let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + // Stores whether the menu bar icon is hidden. + let hideStatusItemPreferenceKey = "hideStatusItemFromMenuBar" let ble = BLE() let mainMenu = NSMenu() let deviceMenu = NSMenu() @@ -117,6 +119,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, NSMenuItemVa } func updateRSSI(rssi: Int?, active: Bool) { + // Keep updating the status item even when it is hidden. if let r = rssi { lastRSSI = r monitorMenuItem?.title = String(format:"%ddBm", r) + (active ? " (Active)" : "") @@ -552,6 +555,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, NSMenuItemVa menuItem.state = wakeWithoutUnlocking ? .on : .off } + @objc func toggleHideMenuBarIcon(_ menuItem: NSMenuItem) { + let hideMenuBarIcon = !prefs.bool(forKey: hideStatusItemPreferenceKey) + prefs.set(hideMenuBarIcon, forKey: hideStatusItemPreferenceKey) + menuItem.state = hideMenuBarIcon ? .on : .off + + // Apply the visibility change immediately. + statusItem.isVisible = !hideMenuBarIcon + } + @objc func lockNow() { guard !isScreenLocked() else { return } manualLock = true @@ -650,6 +662,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, NSMenuItemVa item = mainMenu.addItem(withTitle: t("launch_at_login"), action: #selector(toggleLaunchAtLogin), keyEquivalent: "") item.state = prefs.bool(forKey: "launchAtLogin") ? .on : .off + + item = mainMenu.addItem(withTitle: t("hide_menu_bar_icon"), action: #selector(toggleHideMenuBarIcon), keyEquivalent: "") + item.state = prefs.bool(forKey: hideStatusItemPreferenceKey) ? .on : .off mainMenu.addItem(withTitle: t("set_rssi_threshold"), action: #selector(setRSSIThreshold), keyEquivalent: "") @@ -658,6 +673,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, NSMenuItemVa mainMenu.addItem(withTitle: t("about"), action: #selector(showAboutBox), keyEquivalent: "") mainMenu.addItem(NSMenuItem.separator()) mainMenu.addItem(withTitle: t("quit"), action: #selector(NSApplication.terminate(_:)), keyEquivalent: "") + // Keep the menu attached to the status item. statusItem.menu = mainMenu } @@ -673,11 +689,29 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, NSMenuItemVa } } + func resetHiddenMenuBarIconState() { + guard prefs.bool(forKey: hideStatusItemPreferenceKey) else { return } + + // Show the icon again when the app is reopened. + prefs.set(false, forKey: hideStatusItemPreferenceKey) + statusItem.isVisible = true + + if let item = mainMenu.items.first(where: { $0.action == #selector(toggleHideMenuBarIcon) }) { + item.state = .off + } + } + func applicationDidFinishLaunching(_ aNotification: Notification) { if let button = statusItem.button { button.image = NSImage(named: "StatusBarDisconnected") - constructMenu() } + constructMenu() + + let hideMenuBarIcon = prefs.bool(forKey: hideStatusItemPreferenceKey) + + // Restore the saved visibility state on launch. + statusItem.isVisible = !hideMenuBarIcon + ble.delegate = self if let str = prefs.string(forKey: "device") { if let uuid = UUID(uuidString: str) { @@ -730,7 +764,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, NSMenuItemVa // otherwise CBCentralManager.scanForPeripherals won't work. NSApp.setActivationPolicy(.accessory) } + + func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { + // Restore the icon when the running app is reopened. + resetHiddenMenuBarIconState() + return false + } + + func applicationDidBecomeActive(_ notification: Notification) { + // Also restore the icon when the app becomes active again. + resetHiddenMenuBarIconState() + } + func applicationWillTerminate(_ aNotification: Notification) { } } diff --git a/BLEUnlock/Base.lproj/Localizable.strings b/BLEUnlock/Base.lproj/Localizable.strings index 4e75488..6b3c705 100644 --- a/BLEUnlock/Base.lproj/Localizable.strings +++ b/BLEUnlock/Base.lproj/Localizable.strings @@ -10,6 +10,7 @@ "enter_rssi_threshold_info" = "Device whose RSSI is less than this value will be ignored while scanning."; "farther" = "⬇Farther"; "launch_at_login" = "Launch at Login"; +"hide_menu_bar_icon" = "Hide Menu Bar Icon"; "lock_delay" = "Delay to Lock"; "lock_now" = "Lock Screen Now"; "lock_rssi" = "Lock RSSI"; diff --git a/BLEUnlock/Info.plist b/BLEUnlock/Info.plist index a871345..d75447d 100644 --- a/BLEUnlock/Info.plist +++ b/BLEUnlock/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.12.2 CFBundleVersion - 796 + 805 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/BLEUnlock/ja.lproj/Localizable.strings b/BLEUnlock/ja.lproj/Localizable.strings index 39910a7..81262df 100644 --- a/BLEUnlock/ja.lproj/Localizable.strings +++ b/BLEUnlock/ja.lproj/Localizable.strings @@ -10,6 +10,7 @@ "enter_rssi_threshold_info" = "この値よりRSSIが小さいデバイスはスキャンに表示されません。"; "farther" = "⬇遠い"; "launch_at_login" = "ログイン時に起動"; +"hide_menu_bar_icon" = "メニューバーアイコンを非表示"; "lock_delay" = "ロックするまでの遅延"; "lock_now" = "今すぐロック"; "lock_rssi" = "ロック信号強度"; diff --git a/BLEUnlock/zh-Hans.lproj/Localizable.strings b/BLEUnlock/zh-Hans.lproj/Localizable.strings index c8a0303..40e2bee 100644 --- a/BLEUnlock/zh-Hans.lproj/Localizable.strings +++ b/BLEUnlock/zh-Hans.lproj/Localizable.strings @@ -10,6 +10,7 @@ "enter_rssi_threshold_info" = "扫描设备时会忽略RSSI值低于该值的设备。"; "farther" = "⬇远离"; "launch_at_login" = "开机启动"; +"hide_menu_bar_icon" = "隐藏菜单栏图标"; "lock_delay" = "延迟锁定"; "lock_now" = "立刻锁定屏幕"; "lock_rssi" = "锁定 RSSI";