add transcription back after stop recording

Transcription runs in the View via Task after saving the memo.
Speech authorization is requested when the recording sheet opens.
Shows transcribing indicator. Record button disabled during transcription.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 23:26:16 +01:00
parent 05cc93f3c3
commit 3f723942d4

View File

@@ -5,6 +5,8 @@ struct RecordingView: View {
@Environment(\.modelContext) private var modelContext
@Environment(\.dismiss) private var dismiss
var viewModel: RecordingViewModel
@State private var transcriptionService = TranscriptionService()
@State private var isTranscribing = false
var body: some View {
NavigationStack {
@@ -15,6 +17,16 @@ struct RecordingView: View {
recordButton
if isTranscribing {
HStack(spacing: 8) {
ProgressView()
.controlSize(.small)
Text(String(localized: "memo.transcribing"))
.font(.subheadline)
.foregroundStyle(.secondary)
}
}
Spacer()
if let error = viewModel.error {
@@ -33,13 +45,18 @@ struct RecordingView: View {
Button(String(localized: "general.done")) {
if viewModel.isRecording {
viewModel.stopRecording()
saveAndTranscribe()
}
saveRecordingIfNeeded()
dismiss()
}
}
}
}
.task {
if transcriptionService.authorizationStatus == .notDetermined {
await transcriptionService.requestAuthorization()
}
}
}
private var timerDisplay: some View {
@@ -55,7 +72,7 @@ struct RecordingView: View {
Button {
if viewModel.isRecording {
viewModel.stopRecording()
saveRecordingIfNeeded()
saveAndTranscribe()
} else {
viewModel.startRecording()
}
@@ -76,6 +93,7 @@ struct RecordingView: View {
}
}
}
.disabled(isTranscribing)
.accessibilityLabel(
viewModel.isRecording
? String(localized: "recording.stop")
@@ -84,7 +102,7 @@ struct RecordingView: View {
.sensoryFeedback(.impact, trigger: viewModel.isRecording)
}
private func saveRecordingIfNeeded() {
private func saveAndTranscribe() {
guard let recorded = viewModel.lastRecordedFile else { return }
let today = Calendar.current.startOfDay(for: .now)
@@ -93,8 +111,26 @@ struct RecordingView: View {
let memo = VoiceMemo(audioFileName: recorded.fileName, duration: recorded.duration)
memo.entry = entry
modelContext.insert(memo)
viewModel.lastRecordedFile = nil
let audioURL = recorded.url
Task {
await transcribe(memo: memo, audioURL: audioURL)
}
}
private func transcribe(memo: VoiceMemo, audioURL: URL) async {
guard transcriptionService.authorizationStatus == .authorized else { return }
isTranscribing = true
defer { isTranscribing = false }
do {
let transcript = try await transcriptionService.transcribe(audioURL: audioURL)
memo.transcript = transcript
} catch {
viewModel.error = error
}
}
private func fetchOrCreateEntry(for date: Date) -> DiaryEntry {