I'm trying to update a dynamic property of a live activity but I can only get it to work when using a button inside the app, not with a button inside the LiveActivity. Can you help me understand where I'm going wrong?
Given these Activity Attributes:
struct MyWidgetsAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here!
var startedAt: Date
var timerRuns: Bool
var remainingTime: Double
}
// Fixed non-changing properties about your activity go here!
var name: String
}
The following code inside the app works perfectly and after tapping it timerRuns gets set to false:
Button {
let state = MyWidgetsAttributes.ContentState(startedAt: goal.startedAt, timerRuns: false, remainingTime: goal.remainingTime)
let content = ActivityContent(state: state, staleDate: Date().addingTimeInterval(60))
Task{
await activity?.update(content)
}
} label: {
Text("Pause/Resume")
.foregroundStyle(.white)
.padding()
.background(.primary)
.clipShape(RoundedRectangle(cornerRadius: 10))
}
}
However I would like to have a button that does the same inside the live activity so I created the following AppIntent:
struct PauseResume: AppIntent {
static var title: LocalizedStringResource = .init(stringLiteral: "Pause/Resume Timer")
@Parameter(title: "ID")
var id: String
init() {
}
init(id:String) {
self.id = id
}
func perform() async throws -> some IntentResult {
if let activity = Activity<MyWidgetsAttributes>.activities.first(where: { $0.attributes.name == id }) {
let state = MyWidgetsAttributes.ContentState(startedAt: activity.content.state.startedAt, timerRuns: false, remainingTime: activity.content.state.remainingTime)
let content = ActivityContent(state: state, staleDate: Date().addingTimeInterval(60))
Task{
await activity.update(content)
}
}
WidgetCenter.shared.reloadAllTimelines()
return .result()
}
}
and this button inside the liveActivity:
struct MyWidgetsLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: MyWidgetsAttributes.self) { context in
// Lock screen/banner UI goes here
HStack {
HStack {
Text(context.attributes.name)
.font(.title2)
.bold()
.multilineTextAlignment(.leading)
Text(String(context.state.timerRuns))
Button (intent: PauseResume(id: context.attributes.name)) {
Image(systemName: "pause.circle.fill")
}
.buttonBorderShape(.circle)
...
The button inside the app works just fine but this one does nothing and on the lock screen I keep seeing the name of the activity followed by "true" as if it didn't update or the variable never got updated in the first place
Happy to provide any additional info if it helps
If it can help anyone in the future, I just solved this by adding the LiveActivityIntent Protocol
So from this:
struct PauseResume: AppIntent
To this:
struct PauseResume: AppIntent, LiveActivityIntent
And now the button works just fine!