Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Sources/App/HAApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ struct HAApp: App {
.onOpenURL { handleIncoming(url: $0) }
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { handleIncoming(userActivity: $0) }
}
// Without this, `activateAnyScene(for: .webView)` (e.g. tapping the macOS menu-bar item) requests a
// new scene carrying `targetContentIdentifier == "ha.webview"`; with no `WindowGroup` advertising that
// identifier SwiftUI can't bind the scene to a group and no window appears. Matching it here — like the
// other groups below — routes the activation to this group so the window becomes visible.
.handlesExternalEvents(matching: [SceneActivity.webView.activityIdentifier])

// Mac Settings
WindowGroup {
Expand Down
2 changes: 2 additions & 0 deletions Sources/App/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,8 @@ This server requires a client certificate (mTLS) but the operation was cancelled
"menu.application.preferences" = "Preferences…";
"menu.file.update_sensors" = "Update Sensors";
"menu.help.help" = "%@ Help";
"menu.status_item.open" = "Open %1$@";
"menu.status_item.open_settings" = "Open Settings…";
"menu.status_item.quit" = "Quit";
"menu.status_item.toggle" = "Toggle %1$@";
"menu.view.find" = "Find";
Expand Down
38 changes: 17 additions & 21 deletions Sources/App/Utilities/MenuManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -286,17 +286,6 @@ class MenuManager {
)
}

private func preferencesMenu() -> AppMacBridgeStatusItemMenuItem {
.init(
name: L10n.Menu.Application.preferences,
keyEquivalentModifier: [.command],
keyEquivalent: ","
) { callbackInfo in
Current.sceneManager.activateAnyScene(for: .settings)
callbackInfo.activate()
}
}

private func helpMenus() -> [UIMenu] {
let title = L10n.Menu.Help.help(appName)

Expand Down Expand Up @@ -367,14 +356,21 @@ class MenuManager {
)
}

private func toggleMenu() -> AppMacBridgeStatusItemMenuItem {
.init(name: L10n.Menu.StatusItem.toggle(appName)) { callbackInfo in
if callbackInfo.isActive {
callbackInfo.deactivate()
} else {
Current.sceneManager.activateAnyScene(for: .webView)
callbackInfo.activate()
}
private func openAppMenu() -> AppMacBridgeStatusItemMenuItem {
.init(name: L10n.Menu.StatusItem.open(appName)) { callbackInfo in
Current.sceneManager.activateAnyScene(for: .webView)
callbackInfo.activate()
}
}

private func openSettingsMenu() -> AppMacBridgeStatusItemMenuItem {
.init(
name: L10n.Menu.StatusItem.openSettings,
keyEquivalentModifier: [.command],
keyEquivalent: ","
) { callbackInfo in
Current.sceneManager.activateAnyScene(for: .settings)
callbackInfo.activate()
}
}

Expand All @@ -397,10 +393,10 @@ class MenuManager {
}

var menuItems = [AppMacBridgeStatusItemMenuItem]()
menuItems.append(toggleMenu())
menuItems.append(openAppMenu())
menuItems.append(openSettingsMenu())
menuItems.append(.separator())
menuItems.append(contentsOf: aboutMenu())
menuItems.append(preferencesMenu())
menuItems.append(quitMenu())

Current.macBridge.configureStatusItem(using: AppMacBridgeStatusItemConfiguration(
Expand Down
12 changes: 11 additions & 1 deletion Sources/MacBridge/MacBridgeStatusItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,21 @@ class MacBridgeStatusItemCallbackInfoImpl: MacBridgeStatusItemCallbackInfo {
}

var isActive: Bool {
NSApp.isActive
// Only treat the app as "active" (and therefore something to hide on the next click) when it
// actually has a visible standard window. In menu-bar (`.accessory`) mode `NSApp.isActive` can be
// true with no visible window — which previously made the status-item click hide the app instead of
// showing it, so the icon appeared to do nothing.
NSApp.isActive && NSApp.windows.contains { $0.isVisible && !$0.isMiniaturized && $0.level == .normal }
}

func activate() {
NSApp.activate(ignoringOtherApps: true)
// `NSApp.activate` un-hides the app but doesn't reliably bring a closed/ordered-out window back in
// accessory mode, so surface an existing standard window here. A brand-new window (when none exists)
// is created by the scene-activation request in `SceneManager.activateAnyScene`.
NSApp.windows
.first { $0.level == .normal && !$0.isMiniaturized }?
.makeKeyAndOrderFront(nil)
}

func deactivate() {
Expand Down
6 changes: 6 additions & 0 deletions Sources/Shared/Resources/Swiftgen/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,12 @@ public enum L10n {
}
}
public enum StatusItem {
/// Open %1$@
public static func open(_ p1: Any) -> String {
return L10n.tr("Localizable", "menu.status_item.open", String(describing: p1))
}
/// Open Settings…
public static var openSettings: String { return L10n.tr("Localizable", "menu.status_item.open_settings") }
/// Quit
public static var quit: String { return L10n.tr("Localizable", "menu.status_item.quit") }
/// Toggle %1$@
Expand Down
Loading