diff --git a/BusyMirror.xcodeproj/project.pbxproj b/BusyMirror.xcodeproj/project.pbxproj index 4688a65..0520601 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 = 26; + CURRENT_PROJECT_VERSION = 27; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = BusyMirror/Info.plist; @@ -421,7 +421,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; 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 = 26; + CURRENT_PROJECT_VERSION = 27; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = BusyMirror/Info.plist; @@ -451,7 +451,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; 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 9049be1..1672d90 100644 --- a/BusyMirror/BusyMirrorApp.swift +++ b/BusyMirror/BusyMirrorApp.swift @@ -23,17 +23,14 @@ struct BusyMirrorApp: App { .environmentObject(appController) } - // A plain Window rather than a Settings scene: this was originally - // required because the app was LSUIElement (accessory) and got no - // standard app menu for Cmd+,/SettingsLink to hook into. Now that - // it's a standard app that menu exists, but openWindow(id:) already - // works reliably (same mechanism as the main window) so there's no - // reason to switch back. - Window("Preferences", id: BusyMirrorSceneID.preferencesWindow) { + // A real Settings scene: now that the app is standard (not + // LSUIElement), this gets the conventional Cmd+, and a "Preferences…" + // item in the app's own menu for free — the location people actually + // look, unlike a plain Window which only opens from wherever we + // explicitly put a button for it. + Settings { PreferencesView() .environmentObject(appController) } - .defaultSize(width: 480, height: 560) - .windowResizability(.contentSize) } } diff --git a/BusyMirror/ContentView.swift b/BusyMirror/ContentView.swift index 8c37170..2ce2cee 100644 --- a/BusyMirror/ContentView.swift +++ b/BusyMirror/ContentView.swift @@ -61,7 +61,6 @@ 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] = [] @@ -616,8 +615,8 @@ struct ContentView: View { Text("Mirroring defaults, filters, and work hours moved to Preferences.") .font(.footnote) .foregroundStyle(.secondary) - Button("Open Preferences…") { - appController.openPreferencesWindow(using: openWindow) + SettingsLink { + Text("Open Preferences…") } Spacer(minLength: 0) } diff --git a/BusyMirror/MenuBarSupport.swift b/BusyMirror/MenuBarSupport.swift index 7d5f3c7..09ce4d8 100644 --- a/BusyMirror/MenuBarSupport.swift +++ b/BusyMirror/MenuBarSupport.swift @@ -5,7 +5,6 @@ import ServiceManagement enum BusyMirrorSceneID { static let mainWindow = "main-window" - static let preferencesWindow = "preferences-window" } @MainActor @@ -67,11 +66,6 @@ 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 @@ -256,6 +250,7 @@ final class BusyMirrorAppController: ObservableObject { struct BusyMirrorMenuBarView: View { @Environment(\.openWindow) private var openWindow + @Environment(\.openSettings) private var openSettings @EnvironmentObject private var appController: BusyMirrorAppController var body: some View { @@ -287,7 +282,8 @@ struct BusyMirrorMenuBarView: View { } Button("Preferences…") { - appController.openPreferencesWindow(using: openWindow) + NSApp.activate(ignoringOtherApps: true) + openSettings() } Divider() diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b7ea5..88f07ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to BusyMirror will be documented in this file. +## [1.8.3] - 2026-08-27 + +### Fixed +- **Preferences missing from the standard app menu.** 1.8.1's fix for Preferences (a plain `Window` opened via `openWindow`) worked around `LSUIElement` having no app menu, but 1.8.2 removed `LSUIElement` and the workaround was never swapped back — so there was still no "Preferences…" in the app's own menu or Cmd+, response, only a button buried in the main window and a menu-bar-dropdown item. Restored a real `Settings { }` scene now that the app menu exists to host it; both the menu bar dropdown and the main window's button now call the standard `openSettings()` action (via `SettingsLink` in the main window) instead of a custom `openWindow(id:)`. ([BusyMirrorApp.swift](BusyMirror/BusyMirrorApp.swift), [MenuBarSupport.swift](BusyMirror/MenuBarSupport.swift), [ContentView.swift](BusyMirror/ContentView.swift)) + ## [1.8.2] - 2026-08-27 ### Changed