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
@@ -1,11 +1,18 @@
import WidgetKit
import AppIntents
/// The configuration intent of the ``AttendiWidget`` placeholder, as scaffolded by the Xcode widget template.
struct ConfigurationAppIntent: WidgetConfigurationIntent {
// MARK: Constants
static var title: LocalizedStringResource { "Configuration" }
static var description: IntentDescription { "This is an example widget." }
// An example configurable parameter.
// MARK: Properties
/// An example configurable parameter.
@Parameter(title: "Favorite Emoji", default: "😃")
var favoriteEmoji: String
}
@@ -0,0 +1,29 @@
import Commanding
import AppIntents
/// The intent behind the discard button of the recording Live Activity, which throws the recording away.
///
/// The intent is compiled into both the app and the widget extension: the widget references it from the activity's buttons, and the
/// system executes it in the app's process where it sends ``RecordingCommand/discard`` through the process-wide
/// ``RecordingCommander``, mirroring a press of the feature's discard button.
struct DiscardRecordingIntent: LiveActivityIntent {
// MARK: Constants
static let title: LocalizedStringResource = "Discard Recording"
static let description = IntentDescription("Throws the paused recording away.")
static let openAppWhenRun = false
// MARK: Methods
/// Sends the discard command to the recording flow.
///
/// - Returns: An empty result, since the discard ends the Live Activity itself.
@MainActor
func perform() async throws -> some IntentResult {
RecordingCommander.shared.send(.discard)
return .result()
}
}
@@ -0,0 +1,29 @@
import Commanding
import AppIntents
/// The intent behind the send button of the recording Live Activity, which sends the paused recording for processing.
///
/// The intent is compiled into both the app and the widget extension: the widget references it from the activity's buttons, and the
/// system executes it in the app's process where it sends ``RecordingCommand/process`` through the process-wide
/// ``RecordingCommander``, mirroring a press of the feature's send button.
struct ProcessRecordingIntent: LiveActivityIntent {
// MARK: Constants
static let title: LocalizedStringResource = "Process Recording"
static let description = IntentDescription("Sends the paused recording for processing.")
static let openAppWhenRun = false
// MARK: Methods
/// Sends the process command to the recording flow.
///
/// - Returns: An empty result, since the outcome surfaces through the Live Activity's own content update.
@MainActor
func perform() async throws -> some IntentResult {
RecordingCommander.shared.send(.process)
return .result()
}
}
@@ -0,0 +1,29 @@
import Commanding
import AppIntents
/// The intent behind the main button of the recording Live Activity, which pauses or resumes the recording.
///
/// The intent is compiled into both the app and the widget extension: the widget references it from the activity's buttons, and the
/// system executes it in the app's process where it sends ``RecordingCommand/toggle`` through the process-wide
/// ``RecordingCommander``, mirroring a press of the feature's main button.
struct ToggleRecordingIntent: LiveActivityIntent {
// MARK: Constants
static let title: LocalizedStringResource = "Pause or Resume Recording"
static let description = IntentDescription("Pauses or resumes the ongoing recording.")
static let openAppWhenRun = false
// MARK: Methods
/// Sends the toggle command to the recording flow.
///
/// - Returns: An empty result, since the outcome surfaces through the Live Activity's own content update.
@MainActor
func perform() async throws -> some IntentResult {
RecordingCommander.shared.send(.toggle)
return .result()
}
}