import SwiftUI /// The watch app's single screen: a big record/stop button, an elapsed timer /// while recording, and a footer counting recordings still waiting to reach the /// iPhone. Shows a permission-denied state when the mic is refused. struct RecordView: View { @Environment(WatchAppServices.self) private var services var body: some View { let recorder = services.recorder VStack(spacing: 10) { if recorder.permissionDenied { permissionDenied } else { recordButton(isRecording: recorder.isRecording) if recorder.isRecording { Text(Self.elapsedString(recorder.elapsed)) .font(.system(.title3, design: .rounded).monospacedDigit()) .foregroundStyle(.secondary) } else { Text("Tap to record") .font(.footnote) .foregroundStyle(.secondary) } pendingFooter } } .padding() .containerBackground(.red.gradient, for: .navigation) .navigationTitle("Contextful") } private func recordButton(isRecording: Bool) -> some View { Button { services.toggleRecording() } label: { ZStack { Circle() .fill(.red) .frame(width: 96, height: 96) Image(systemName: isRecording ? "stop.fill" : "mic.fill") .font(.system(size: 40)) .foregroundStyle(.white) .contentTransition(.symbolEffect(.replace)) } } .buttonStyle(.plain) .accessibilityLabel(isRecording ? "Stop recording" : "Start recording") } @ViewBuilder private var pendingFooter: some View { let count = services.transfer.pendingCount if count > 0 { Label( count == 1 ? "1 waiting for iPhone" : "\(count) waiting for iPhone", systemImage: "arrow.up.circle" ) .font(.caption2) .foregroundStyle(.secondary) } } private var permissionDenied: some View { VStack(spacing: 8) { Image(systemName: "mic.slash.fill") .font(.title) .foregroundStyle(.secondary) Text("Microphone access is off") .font(.headline) .multilineTextAlignment(.center) Text("Enable it in the Watch app on iPhone under Contextful.") .font(.caption2) .foregroundStyle(.secondary) .multilineTextAlignment(.center) } } /// mm:ss for the elapsed readout. static func elapsedString(_ interval: TimeInterval) -> String { let total = Int(interval) return String(format: "%02d:%02d", total / 60, total % 60) } }