Capture app context at start to avoid mismatches if the user switches apps mid-session
()
| 3094 | |
| 3095 | /// Capture app context at start to avoid mismatches if the user switches apps mid-session |
| 3096 | private func startRecording() { |
| 3097 | let model = SettingsStore.shared.selectedSpeechModel |
| 3098 | DebugLogger.shared.info( |
| 3099 | "ContentView: startRecording() for model=\(model.displayName), supportsStreaming=\(model.supportsStreaming)", |
| 3100 | source: "ContentView" |
| 3101 | ) |
| 3102 | guard !self.asr.isRunningOrStarting else { |
| 3103 | DebugLogger.shared.debug("ContentView: start ignored because capture is already active", source: "ContentView") |
| 3104 | return |
| 3105 | } |
| 3106 | |
| 3107 | self.advanceOverlayLifecycle() |
| 3108 | self.setActiveRecordingMode(.dictate) |
| 3109 | let shouldShowDictationOverlay = !self.isRecordingForCommand |
| 3110 | && !self.isRecordingForRewrite |
| 3111 | && self.asr.micStatus == .authorized |
| 3112 | let shouldPlayStartSound = !self.isRecordingForCommand |
| 3113 | && !self.isRecordingForRewrite |
| 3114 | && self.asr.micStatus == .authorized |
| 3115 | |
| 3116 | // Ensure normal dictation mode is set (command/rewrite modes set their own) |
| 3117 | if shouldShowDictationOverlay { |
| 3118 | self.menuBarManager.setOverlayMode(.dictation) |
| 3119 | self.menuBarManager.showRecordingOverlayImmediately() |
| 3120 | DebugLogger.shared.benchmark( |
| 3121 | "APP_BENCH", |
| 3122 | message: "overlay_phase phase=connecting", |
| 3123 | source: "AppBenchmark" |
| 3124 | ) |
| 3125 | } |
| 3126 | |
| 3127 | Task { |
| 3128 | let startOutcome = await self.asr.start(onCaptureStarted: { |
| 3129 | if shouldPlayStartSound { |
| 3130 | TranscriptionSoundPlayer.shared.playStartSound() |
| 3131 | } |
| 3132 | self.captureRecordingContext() |
| 3133 | self.prewarmPrivateAIDictationIfNeeded(for: .primary) |
| 3134 | DebugLogger.shared.benchmark( |
| 3135 | "APP_BENCH", |
| 3136 | message: "overlay_phase phase=recording trigger=first_pcm", |
| 3137 | source: "AppBenchmark" |
| 3138 | ) |
| 3139 | }) |
| 3140 | if startOutcome == .failed { |
| 3141 | self.menuBarManager.hideRecordingOverlayImmediately(reason: "asr_start_failed") |
| 3142 | } |
| 3143 | } |
| 3144 | |
| 3145 | // Pre-load model in background while recording (avoids 10s freeze on stop) |
| 3146 | Task { |
| 3147 | do { |
| 3148 | DebugLogger.shared.debug("ContentView: pre-load model task started", source: "ContentView") |
| 3149 | try await self.asr.ensureAsrReady() |
| 3150 | DebugLogger.shared.debug("Model pre-loaded during recording", source: "ContentView") |
| 3151 | } catch { |
| 3152 | DebugLogger.shared.error("Failed to pre-load model: \(error)", source: "ContentView") |
| 3153 | } |
no test coverage detected