diff --git a/BusyMirror.xcodeproj/project.pbxproj b/BusyMirror.xcodeproj/project.pbxproj index 14e740d..61a96d3 100644 --- a/BusyMirror.xcodeproj/project.pbxproj +++ b/BusyMirror.xcodeproj/project.pbxproj @@ -410,7 +410,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = BusyMirror/Info.plist; @@ -421,7 +421,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.1; PRODUCT_BUNDLE_IDENTIFIER = com.cqrenet.BusyMirror; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; @@ -440,7 +440,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = BusyMirror/Info.plist; @@ -451,7 +451,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.1; PRODUCT_BUNDLE_IDENTIFIER = com.cqrenet.BusyMirror; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; diff --git a/BusyMirror/BusyMirrorApp.swift b/BusyMirror/BusyMirrorApp.swift index 89a6894..4534134 100644 --- a/BusyMirror/BusyMirrorApp.swift +++ b/BusyMirror/BusyMirrorApp.swift @@ -23,9 +23,17 @@ struct BusyMirrorApp: App { .environmentObject(appController) } - Settings { + // A plain Window (not a Settings scene) — LSUIElement (accessory) + // apps don't get the standard app menu, so Cmd+, / the automatic + // "Settings…" command has no menu to live in and SettingsLink has + // nothing reliable to trigger. openWindow(id:) is the same mechanism + // that already reliably opens the main window from the menu bar, so + // reuse it here instead. + Window("Preferences", id: BusyMirrorSceneID.preferencesWindow) { PreferencesView() .environmentObject(appController) } + .defaultSize(width: 480, height: 560) + .windowResizability(.contentSize) } } diff --git a/BusyMirror/ContentView.swift b/BusyMirror/ContentView.swift index 2ce2cee..8c37170 100644 --- a/BusyMirror/ContentView.swift +++ b/BusyMirror/ContentView.swift @@ -61,6 +61,7 @@ struct Route: Identifiable, Hashable, Codable { struct ContentView: View { @EnvironmentObject private var appController: BusyMirrorAppController + @Environment(\.openWindow) private var openWindow @State private var store = EKEventStore() @State private var hasAccess = false @State private var calendars: [EKCalendar] = [] @@ -615,8 +616,8 @@ struct ContentView: View { Text("Mirroring defaults, filters, and work hours moved to Preferences.") .font(.footnote) .foregroundStyle(.secondary) - SettingsLink { - Text("Open Preferences…") + Button("Open Preferences…") { + appController.openPreferencesWindow(using: openWindow) } Spacer(minLength: 0) } diff --git a/BusyMirror/MenuBarSupport.swift b/BusyMirror/MenuBarSupport.swift index c767cfe..7d5f3c7 100644 --- a/BusyMirror/MenuBarSupport.swift +++ b/BusyMirror/MenuBarSupport.swift @@ -5,6 +5,7 @@ import ServiceManagement enum BusyMirrorSceneID { static let mainWindow = "main-window" + static let preferencesWindow = "preferences-window" } @MainActor @@ -66,6 +67,11 @@ final class BusyMirrorAppController: ObservableObject { openWindow(id: BusyMirrorSceneID.mainWindow) } + func openPreferencesWindow(using openWindow: OpenWindowAction) { + NSApp.activate(ignoringOtherApps: true) + openWindow(id: BusyMirrorSceneID.preferencesWindow) + } + // MARK: - Event-driven background sync // // Owned here (not by ContentView) because this controller lives for the @@ -280,6 +286,10 @@ struct BusyMirrorMenuBarView: View { appController.openMainWindow(using: openWindow) } + Button("Preferences…") { + appController.openPreferencesWindow(using: openWindow) + } + Divider() Button("Quit BusyMirror") { diff --git a/CHANGELOG.md b/CHANGELOG.md index 03f52e5..b7d6a09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to BusyMirror will be documented in this file. +## [1.8.1] - 2026-08-26 + +### Fixed +- **Preferences window unreachable**: 1.8.0's Settings scene (⌘,) and its `SettingsLink` button didn't work because BusyMirror is an `LSUIElement` (accessory) app — those don't get the standard app menu, so there's no menu for the automatic "Settings…" command or Cmd+, to live in. Replaced the `Settings { }` scene with a plain `Window(id: "preferences-window")`, opened via `openWindow(id:)` — the same mechanism that already reliably opens the main window from the menu bar. Also added a "Preferences…" item to the menu bar dropdown itself, so there are two direct routes in instead of one that depended on OS menu plumbing this app type doesn't get. ([BusyMirrorApp.swift](BusyMirror/BusyMirrorApp.swift), [MenuBarSupport.swift](BusyMirror/MenuBarSupport.swift), [ContentView.swift](BusyMirror/ContentView.swift)) + ## [1.8.0] - 2026-08-26 ### Added