Files
voicediary/VoiceDiary/Views/RecordingView.swift
Felix Förtsch dca03214b0 initial VoiceDiary iOS app setup
SwiftUI + SwiftData + iCloud, Apple Speech transcription (German),
audio recording, summarization service protocol (LLM-ready),
localization scaffolding (EN/DE/ES/FR), basic tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:57:41 +01:00

88 lines
2.0 KiB
Swift

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())
}