Implemented the (first version of the) Recording Live Activity in the Attendi widget target.

This commit is contained in:
2026-07-06 03:43:25 +02:00
parent ffa80d3b58
commit 874de398d2
15 changed files with 755 additions and 4 deletions
@@ -0,0 +1,93 @@
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
)
}