import Commanding import SwiftUI import WidgetKit /// The Lock Screen banner of the recording Live Activity: a centered stack of the timer of the elapsed recording time, the label /// naming the current state, and the control buttons. struct RecordingLiveActivityView: View { // MARK: Properties /// The dynamic content of the Live Activity to render. let state: RecordingActivityAttributes.ContentState // MARK: Body var body: some View { VStack( alignment: .center, spacing: Constant.Spacing.stack ) { RecordingTimerText(state: state) .font(.largeTitle) .fontWeight(.bold) .monospacedDigit() RecordingStateLabel(state: state) RecordingControls(state: state) } } } // MARK: - Constants /// The constant values used across the recording Live Activity. private enum Constant { /// The size constants. enum Size { /// The maximum width of the timer in the compact trailing presentation of the Dynamic Island. static let compactTimer: CGFloat = 44 } /// The spacing constants. enum Spacing { /// The spacing between the elements of a stack. static let stack: CGFloat = 8 } /// The system symbol constants. enum Symbol { /// The symbol of the discard button. static let discard = "trash" /// The symbol marking the recording flow. static let microphone = "mic.fill" /// The symbol of the main button while recording. static let pause = "pause.fill" /// The symbol of the main button while paused. static let record = "record.circle" } /// The time constants. enum Time { /// The span of the running timer, comfortably beyond the maximum lifetime of a Live Activity. static let span: TimeInterval = 24 * 60 * 60 } } // MARK: - Previews #Preview( "Recording Live Activity view", as: .content, using: RecordingActivityAttributes() ) { RecordingLiveActivity() } contentStates: { RecordingActivityAttributes.ContentState( state: .recording, anchor: .now, elapsed: 0 ) RecordingActivityAttributes.ContentState( state: .paused, anchor: nil, elapsed: 42 ) RecordingActivityAttributes.ContentState( state: .processing, anchor: nil, elapsed: 42 ) }