import AppIntents import Commanding import Recording import SwiftUI import WidgetKit /// The buttons controlling the recording flow through the App Intents the app executes, matching the current state: a pause /// button while recording; discard, resume, and send buttons while paused; and only a discard button while the recorded input /// is being processed. struct RecordingControls: View { // MARK: Properties /// The dynamic content of the Live Activity to render. let state: RecordingActivityAttributes.ContentState // MARK: Body var body: some View { HStack( spacing: Constant.Spacing.stack ) { switch state.state { case .recording: pauseButton case .paused: discardButton recordButton processButton case .processing: discardButton } } } } // MARK: - Subviews private extension RecordingControls { // MARK: Computed /// The discard button, shown while the recording is paused or being processed, that throws the recording away. var discardButton: some View { Button(intent: DiscardRecordingIntent()) { Image.Symbol.discard .resizable() } .buttonStyle(.action( type: .destructive )) .accessibilityLabel(Text("view.recording-controls.button.discard")) } /// The pause button, shown while recording, that pauses the ongoing recording. var pauseButton: some View { Button(intent: ToggleRecordingIntent()) { Image.Symbol.pause .resizable() } .buttonStyle(.action( type: .default )) .accessibilityLabel(Text("view.recording-controls.button.pause")) } /// The send button, shown while the recording is paused, that sends it for processing. var processButton: some View { Button(intent: ProcessRecordingIntent()) { Image.Symbol.send .resizable() } .buttonStyle(.action( type: .confirmative )) .accessibilityLabel(Text("view.recording-controls.button.send")) } /// The resume button, shown while the recording is paused, that resumes it. var recordButton: some View { Button(intent: ToggleRecordingIntent()) { Image.Symbol.microphone .resizable() } .buttonStyle(.action( type: .default )) .accessibilityLabel(Text("view.recording-controls.button.resume")) } } // MARK: - Constants /// The constant values used across the recording Live Activity. private enum Constant { /// The spacing constants. enum Spacing { /// The spacing between the elements of a stack. static let stack: CGFloat = 16 } } // MARK: - Previews #Preview( "Recording Controls 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 ) }