From 27fd88037e0b1c69a7a291898e086a1c11b86832 Mon Sep 17 00:00:00 2001 From: Szymon Sypniewicz Date: Fri, 20 Mar 2026 19:00:14 +0000 Subject: [PATCH] Derive isRecording from coordinator state machine isRecording was a writable stored property set by ContentView's 100ms polling loop. Any consumer outside that loop saw stale values when the main window was hidden. Replace with a computed property that reads directly from the coordinator's authoritative MeetingState. Also add MeetingMetadata.manual() factory to eliminate duplicate inline construction of manual session metadata. --- .../Sources/OpenOats/App/AppCoordinator.swift | 6 ++---- .../Sources/OpenOats/Meeting/MeetingTypes.swift | 12 ++++++++++++ OpenOats/Sources/OpenOats/Views/ContentView.swift | 15 +-------------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/OpenOats/Sources/OpenOats/App/AppCoordinator.swift b/OpenOats/Sources/OpenOats/App/AppCoordinator.swift index ee5b947b..24b784ff 100644 --- a/OpenOats/Sources/OpenOats/App/AppCoordinator.swift +++ b/OpenOats/Sources/OpenOats/App/AppCoordinator.swift @@ -67,11 +67,9 @@ final class AppCoordinator { set { withMutation(keyPath: \.requestedSessionSelectionID) { _requestedSessionSelectionID = newValue } } } - /// Reflects whether a transcription session is currently active (set by ContentView). - @ObservationIgnored nonisolated(unsafe) private var _isRecording = false var isRecording: Bool { - get { access(keyPath: \.isRecording); return _isRecording } - set { withMutation(keyPath: \.isRecording) { _isRecording = newValue } } + if case .recording = state { return true } + return false } @ObservationIgnored nonisolated(unsafe) private var _sessionHistory: [SessionIndex] = [] diff --git a/OpenOats/Sources/OpenOats/Meeting/MeetingTypes.swift b/OpenOats/Sources/OpenOats/Meeting/MeetingTypes.swift index dc4b2ba5..fff4f50c 100644 --- a/OpenOats/Sources/OpenOats/Meeting/MeetingTypes.swift +++ b/OpenOats/Sources/OpenOats/Meeting/MeetingTypes.swift @@ -67,4 +67,16 @@ struct MeetingMetadata: Sendable, Equatable, Codable { let title: String? let startedAt: Date var endedAt: Date? + + static func manual() -> MeetingMetadata { + let now = Date() + return MeetingMetadata( + detectionContext: DetectionContext( + signal: .manual, detectedAt: now, + meetingApp: nil, calendarEvent: nil + ), + calendarEvent: nil, title: nil, + startedAt: now, endedAt: nil + ) + } } diff --git a/OpenOats/Sources/OpenOats/Views/ContentView.swift b/OpenOats/Sources/OpenOats/Views/ContentView.swift index 5874fb95..5b9a4e45 100644 --- a/OpenOats/Sources/OpenOats/Views/ContentView.swift +++ b/OpenOats/Sources/OpenOats/Views/ContentView.swift @@ -328,19 +328,7 @@ struct ContentView: View { } suggestionEngine?.clear() - let metadata = MeetingMetadata( - detectionContext: DetectionContext( - signal: .manual, - detectedAt: Date(), - meetingApp: nil, - calendarEvent: nil - ), - calendarEvent: nil, - title: nil, - startedAt: Date(), - endedAt: nil - ) - coordinator.handle(.userStarted(metadata), settings: settings) + coordinator.handle(.userStarted(.manual()), settings: settings) } private func stopSession() { @@ -548,7 +536,6 @@ struct ContentView: View { if currentViewState.isRunning != observedIsRunning { observedIsRunning = currentViewState.isRunning - coordinator.isRecording = currentViewState.isRunning } let pendingExternalCommandID = coordinator.pendingExternalCommand?.id