diff --git a/BusyMirror.xcodeproj/project.pbxproj b/BusyMirror.xcodeproj/project.pbxproj index b977040..a10fa63 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 = 28; + CURRENT_PROJECT_VERSION = 29; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = BusyMirror/Info.plist; @@ -421,7 +421,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.9.0; + MARKETING_VERSION = 1.9.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 = 28; + CURRENT_PROJECT_VERSION = 29; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = BusyMirror/Info.plist; @@ -451,7 +451,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.9.0; + MARKETING_VERSION = 1.9.1; PRODUCT_BUNDLE_IDENTIFIER = com.cqrenet.BusyMirror; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; diff --git a/BusyMirror/ContentView.swift b/BusyMirror/ContentView.swift index 87e5f1b..5b8c853 100644 --- a/BusyMirror/ContentView.swift +++ b/BusyMirror/ContentView.swift @@ -568,22 +568,25 @@ struct ContentView: View { @ViewBuilder private var sidebarView: some View { - List(SidebarSection.allCases, selection: $selectedSection) { section in - Label { - HStack { - Text(section.title) - if section == .routes && !routes.isEmpty { - Spacer() - Text("\(routes.count)") - .font(.caption) - .foregroundStyle(.secondary) + List(selection: $selectedSection) { + ForEach(SidebarSection.allCases) { section in + Label { + HStack { + Text(section.title) + if section == .routes && !routes.isEmpty { + Spacer() + Text("\(routes.count)") + .font(.caption) + .foregroundStyle(.secondary) + } } + } icon: { + Image(systemName: section.icon) } - } icon: { - Image(systemName: section.icon) + .tag(section) } - .tag(section as SidebarSection?) } + .listStyle(.sidebar) .navigationSplitViewColumnWidth(min: 180, ideal: 200) } @@ -727,6 +730,12 @@ struct ContentView: View { } } + private var statusSubtitle: String { + if let progressText { return progressText } + if isRunning { return "Running…" } + return hasAccess ? "\(calendars.count) calendars" : "No calendar access" + } + @ToolbarContentBuilder private var toolbarContent: some ToolbarContent { ToolbarItemGroup { @@ -737,15 +746,7 @@ struct ContentView: View { .pickerStyle(.segmented) .frame(width: 150) .disabled(isRunning) - - HStack(spacing: 6) { - Circle() - .fill(isRunning ? Color.orange : (appController.lastRunFailed ? Color.red : Color.secondary)) - .frame(width: 7, height: 7) - Text(progressText ?? (isRunning ? "Running…" : (hasAccess ? "\(calendars.count) calendars" : "No access"))) - .font(.caption) - .foregroundStyle(.secondary) - } + .help("Dry Run previews changes without writing. Write actually creates/updates/deletes events.") if isRunning { Button("Cancel") { cancelMirror() } @@ -813,6 +814,7 @@ struct ContentView: View { } } .navigationTitle((selectedSection ?? .routes).title) + .navigationSubtitle(statusSubtitle) .toolbar { toolbarContent } } .confirmationDialog( diff --git a/CHANGELOG.md b/CHANGELOG.md index e0ec014..7c13038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to BusyMirror will be documented in this file. +## [1.9.1] - 2026-08-27 + +### Fixed +- **Sidebar not clickable.** `sidebarView` used `List(SidebarSection.allCases, selection:)` (the data-driven initializer), which ties selection to `Identifiable`'s `id` — a `String` for `SidebarSection` — while the binding was typed `SidebarSection?`. Rebuilt with the standard `List(selection:) { ForEach(...) { ... .tag(section) } }` pattern, which binds selection directly to the (`Hashable`) section value with no ambiguity. Also added `.listStyle(.sidebar)`, the standard modifier for a `NavigationSplitView` sidebar (vibrancy, selection color) that was missing. +- **"Write to calendars" hard to find.** It was still there as the Dry Run/Write segmented control in the toolbar, but likely lost to toolbar overflow alongside a status readout, Sync Now, and the overflow menu all crammed into one `ToolbarItemGroup`. Moved the calendar-count/status text out of the toolbar entirely into `.navigationSubtitle` (always visible, native, never subject to overflow), leaving the toolbar to just Dry Run/Write, Sync Now/Cancel, and the overflow menu. + +Not independently confirmed by clicking through the UI (no GUI automation available in this environment) — the `List(selection:)` fix follows SwiftUI's standard, unambiguous sidebar-selection pattern. + ## [1.9.0] - 2026-08-27 ### Added