harden stopRecording with defensive error handling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,12 +6,10 @@ import SwiftData
|
||||
@MainActor
|
||||
final class RecordingViewModel {
|
||||
var isRecording = false
|
||||
var recordingDuration: TimeInterval = 0
|
||||
var error: Error?
|
||||
|
||||
private let recorder = AudioRecorderService()
|
||||
private let transcriptionService = TranscriptionService()
|
||||
private var currentRecordingURL: URL?
|
||||
|
||||
var formattedDuration: String {
|
||||
let minutes = Int(recorder.recordingDuration) / 60
|
||||
@@ -21,7 +19,7 @@ final class RecordingViewModel {
|
||||
|
||||
func startRecording() {
|
||||
do {
|
||||
currentRecordingURL = try recorder.startRecording()
|
||||
_ = try recorder.startRecording()
|
||||
isRecording = true
|
||||
error = nil
|
||||
} catch {
|
||||
@@ -30,23 +28,26 @@ final class RecordingViewModel {
|
||||
}
|
||||
|
||||
func stopRecording(context: ModelContext) {
|
||||
guard let result = recorder.stopRecording() else { return }
|
||||
guard let result = recorder.stopRecording() else {
|
||||
isRecording = false
|
||||
return
|
||||
}
|
||||
isRecording = false
|
||||
|
||||
let today = Calendar.current.startOfDay(for: .now)
|
||||
let entry = fetchOrCreateEntry(for: today, context: context)
|
||||
let fileName = result.url.lastPathComponent
|
||||
let duration = result.duration
|
||||
|
||||
let memo = VoiceMemo(
|
||||
audioFileName: result.url.lastPathComponent,
|
||||
duration: result.duration
|
||||
)
|
||||
context.insert(memo)
|
||||
let entry: DiaryEntry
|
||||
do {
|
||||
entry = try fetchOrCreateEntry(for: .now, context: context)
|
||||
} catch {
|
||||
self.error = error
|
||||
return
|
||||
}
|
||||
|
||||
let memo = VoiceMemo(audioFileName: fileName, duration: duration)
|
||||
memo.entry = entry
|
||||
if entry.memos == nil { entry.memos = [] }
|
||||
entry.memos?.append(memo)
|
||||
entry.updatedAt = .now
|
||||
|
||||
try? context.save()
|
||||
context.insert(memo)
|
||||
|
||||
let audioURL = memo.audioURL
|
||||
Task {
|
||||
@@ -54,17 +55,16 @@ final class RecordingViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchOrCreateEntry(for date: Date, context: ModelContext) -> DiaryEntry {
|
||||
private func fetchOrCreateEntry(for date: Date, context: ModelContext) throws -> DiaryEntry {
|
||||
let startOfDay = Calendar.current.startOfDay(for: date)
|
||||
let descriptor = FetchDescriptor<DiaryEntry>()
|
||||
let entries = try context.fetch(descriptor)
|
||||
|
||||
if let entries = try? context.fetch(descriptor) {
|
||||
let match = entries.first { entry in
|
||||
Calendar.current.isDate(entry.date, inSameDayAs: date)
|
||||
}
|
||||
if let match { return match }
|
||||
if let match = entries.first(where: { Calendar.current.isDate($0.date, inSameDayAs: startOfDay) }) {
|
||||
return match
|
||||
}
|
||||
|
||||
let entry = DiaryEntry(date: date)
|
||||
let entry = DiaryEntry(date: startOfDay)
|
||||
context.insert(entry)
|
||||
return entry
|
||||
}
|
||||
@@ -84,7 +84,6 @@ final class RecordingViewModel {
|
||||
let transcript = try await transcriptionService.transcribe(audioURL: audioURL)
|
||||
memo.transcript = transcript
|
||||
memo.isTranscribing = false
|
||||
memo.entry?.updatedAt = .now
|
||||
} catch {
|
||||
memo.isTranscribing = false
|
||||
self.error = error
|
||||
|
||||
@@ -3,7 +3,7 @@ import SwiftUI
|
||||
struct RecordingView: View {
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Bindable var viewModel: RecordingViewModel
|
||||
var viewModel: RecordingViewModel
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
|
||||
Reference in New Issue
Block a user