diff --git a/Notes Watch App/Services/WatchAudioRecorder.swift b/Notes Watch App/Services/WatchAudioRecorder.swift index 3d13a21..b5057aa 100644 --- a/Notes Watch App/Services/WatchAudioRecorder.swift +++ b/Notes Watch App/Services/WatchAudioRecorder.swift @@ -71,7 +71,13 @@ final class WatchAudioRecorder { guard !isRecording else { return } let session = AVAudioSession.sharedInstance() - try session.setCategory(.record, mode: .spokenAudio) + do { + try session.setCategory(.record, mode: .spokenAudio) + } catch { + // .spokenAudio isn't guaranteed compatible with .record on every + // route — fall back rather than refuse to record at all. + try session.setCategory(.record, mode: .default) + } try session.setActive(true) let dir = Self.recordingsDirectory diff --git a/Notes Watch App/Views/RecordView.swift b/Notes Watch App/Views/RecordView.swift index aeeb7ad..0473ad8 100644 --- a/Notes Watch App/Views/RecordView.swift +++ b/Notes Watch App/Views/RecordView.swift @@ -17,6 +17,12 @@ struct RecordView: View { Text(Self.elapsedString(recorder.elapsed)) .font(.system(.title3, design: .rounded).monospacedDigit()) .foregroundStyle(.secondary) + } else if let error = services.lastError { + Text(error) + .font(.caption2) + .foregroundStyle(.red) + .multilineTextAlignment(.center) + .lineLimit(3) } else { Text("Tap to record") .font(.footnote) @@ -24,6 +30,7 @@ struct RecordView: View { } pendingFooter } + buildFooter } .padding() .containerBackground(.red.gradient, for: .navigation) @@ -76,6 +83,16 @@ struct RecordView: View { } } + /// Version + build stamped by update_build_number.sh, so a tester can tell + /// at a glance which build the watch actually installed. + private var buildFooter: some View { + let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "?" + let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "?" + return Text("v\(version) (\(build))") + .font(.system(size: 10)) + .foregroundStyle(.tertiary) + } + /// mm:ss for the elapsed readout. static func elapsedString(_ interval: TimeInterval) -> String { let total = Int(interval) diff --git a/Notes Watch App/WatchAppServices.swift b/Notes Watch App/WatchAppServices.swift index 654e624..9274741 100644 --- a/Notes Watch App/WatchAppServices.swift +++ b/Notes Watch App/WatchAppServices.swift @@ -34,6 +34,11 @@ final class WatchAppServices { private let logger = Logger(subsystem: "dev.rzen.indie.Notes.watchkitapp", category: "recording") + /// Why the last start attempt failed, surfaced in the UI — on a real watch + /// there's no console, so a silent failure is indistinguishable from a dead + /// button. Cleared when a recording starts successfully. + private(set) var lastError: String? + /// Request permission (once) then begin recording. A no-op if already /// recording or permission is refused. func startRecording() async { @@ -44,8 +49,10 @@ final class WatchAppServices { } do { try recorder.startRecording() + lastError = nil } catch { logger.error("could not start recording: \(error, privacy: .public)") + lastError = error.localizedDescription } }