import SwiftUI struct RecordingView: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) private var dismiss @Bindable var viewModel: RecordingViewModel var body: some View { NavigationStack { VStack(spacing: 40) { Spacer() timerDisplay recordButton Spacer() if let error = viewModel.error { Text(error.localizedDescription) .font(.caption) .foregroundStyle(.red) .multilineTextAlignment(.center) .padding(.horizontal) } } .padding() .navigationTitle(String(localized: "recording.title")) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button(String(localized: "general.done")) { if viewModel.isRecording { viewModel.stopRecording(context: modelContext) } dismiss() } } } } } private var timerDisplay: some View { Text(viewModel.formattedDuration) .font(.system(size: 64, weight: .light, design: .monospaced)) .foregroundStyle(viewModel.isRecording ? .primary : .secondary) .contentTransition(.numericText()) .animation(.default, value: viewModel.formattedDuration) .accessibilityLabel(String(localized: "recording.duration")) } private var recordButton: some View { Button { if viewModel.isRecording { viewModel.stopRecording(context: modelContext) } else { viewModel.startRecording() } } label: { ZStack { Circle() .fill(viewModel.isRecording ? .red : .red.opacity(0.15)) .frame(width: 88, height: 88) if viewModel.isRecording { RoundedRectangle(cornerRadius: 6) .fill(.white) .frame(width: 28, height: 28) } else { Circle() .fill(.red) .frame(width: 72, height: 72) } } } .accessibilityLabel( viewModel.isRecording ? String(localized: "recording.stop") : String(localized: "recording.start") ) .sensoryFeedback(.impact, trigger: viewModel.isRecording) } } #Preview { RecordingView(viewModel: RecordingViewModel()) }