diff --git a/VoiceDiary/Views/RecordingView.swift b/VoiceDiary/Views/RecordingView.swift index 61209ec..b40864b 100644 --- a/VoiceDiary/Views/RecordingView.swift +++ b/VoiceDiary/Views/RecordingView.swift @@ -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 {