Watch: show version/build on screen, surface recording errors in UI
A tester on real hardware has no console, so a failed start looked like a dead button and there was no way to tell which build the watch had actually installed. Show the stamped version/build under the record button, display the last start error in place of the hint text, and fall back to the default audio session mode if .spokenAudio is rejected with the .record category. Claude-Session: https://claude.ai/code/session_01GKfAiKiQKLDTmbiGva4FGE
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user