Update live activity

release
Laurent 3 years ago
parent 3f60675775
commit e56e89aa34
  1. 1
      LaunchWidget/LaunchWidget.swift
  2. 65
      LaunchWidget/LaunchWidgetLiveActivity.swift
  3. 2
      LeCountdown.xcodeproj/project.pbxproj
  4. 2
      LeCountdown/AppDelegate.swift
  5. 55
      LeCountdown/CountdownScheduler.swift
  6. 2
      LeCountdown/Info.plist
  7. 16
      LeCountdown/Model/Model+Extensions.swift
  8. 5
      LeCountdown/Utils/CoolPic.swift

@ -118,7 +118,6 @@ struct LaunchWidgetEntryView : View {
}
default:
MultiCountdownView(countdowns: entry.countdowns)
}
}

@ -12,20 +12,50 @@ import SwiftUI
struct LaunchWidgetAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here!
var value: Int
var ended: Bool
}
// Fixed non-changing properties about your activity go here!
var id: String
var name: String
var endDate: Date
}
struct LiveActivityView: View {
var name: String
var endDate: Date
var body: some View {
HStack {
Text(name)
Spacer()
Text(endDate, style: .timer)
.monospaced()
}.padding()
.font(.title)
}
}
struct LaunchWidgetLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: LaunchWidgetAttributes.self) { context in
// Lock screen/banner UI goes here
VStack {
Text("Hello")
}
HStack {
Text(context.attributes.name)
Spacer()
if !context.state.ended {
Text(context.attributes.endDate, style: .timer)
.monospaced()
} else {
Text("It's time!")
}
}.padding()
.font(.title)
.activityBackgroundTint(Color.cyan)
.activitySystemActionForegroundColor(Color.black)
@ -34,14 +64,18 @@ struct LaunchWidgetLiveActivity: Widget {
// Expanded UI goes here. Compose the expanded UI through
// various regions, like leading/trailing/center/bottom
DynamicIslandExpandedRegion(.leading) {
Text("Leading")
Text(context.attributes.name)
}
DynamicIslandExpandedRegion(.trailing) {
Text("Trailing")
Text(context.attributes.endDate, style: .timer)
.monospaced()
}
DynamicIslandExpandedRegion(.bottom) {
Text("Bottom")
// more content
Button {
self._stop()
} label: {
Text("Stop")
}
}
} compactLeading: {
Text("L")
@ -50,15 +84,24 @@ struct LaunchWidgetLiveActivity: Widget {
} minimal: {
Text("Min")
}
.widgetURL(URL(string: "http://www.apple.com"))
.widgetURL(URL(string: context.attributes.id))
.keylineTint(Color.red)
}
}
fileprivate func _stop() {
}
}
struct LaunchWidgetLiveActivity_Previews: PreviewProvider {
static let attributes = LaunchWidgetAttributes(name: "Me")
static let contentState = LaunchWidgetAttributes.ContentState(value: 3)
static let attributes = LaunchWidgetAttributes(
id: "",
name: "Tea",
endDate: Date().addingTimeInterval(3600.0))
static let contentState = LaunchWidgetAttributes.ContentState(ended: false)
static var previews: some View {
attributes

@ -62,6 +62,7 @@
C4742B59298411E800D5D950 /* CountdownFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4742B58298411E800D5D950 /* CountdownFormView.swift */; };
C4742B5B298414B000D5D950 /* ImageSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4742B5A298414B000D5D950 /* ImageSelectionView.swift */; };
C4742B5F2984205000D5D950 /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4742B5E2984205000D5D950 /* ViewModifiers.swift */; };
C4F8B1532987FE6F005C86A5 /* LaunchWidgetLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -572,6 +573,7 @@
C438C7C12980228B00BF3EF9 /* CountdownScheduler.swift in Sources */,
C445FA8F2987B83B0054D761 /* SoundPlayer.swift in Sources */,
C438C7C929803CA000BF3EF9 /* AppDelegate.swift in Sources */,
C4F8B1532987FE6F005C86A5 /* LaunchWidgetLiveActivity.swift in Sources */,
C4060DF5297AE9A7003FAB80 /* TimeInterval+Extensions.swift in Sources */,
C4060DF7297AFEF2003FAB80 /* NewCountdownView.swift in Sources */,
C4060DCC297AE73D003FAB80 /* LeCountdown.xcdatamodeld in Sources */,

@ -23,6 +23,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
print("didReceive notification")
AppEnvironment.sun.stopSoundIfNecessary()
}

@ -7,6 +7,7 @@
import Foundation
import UserNotifications
import ActivityKit
class CountdownScheduler {
@ -88,6 +89,8 @@ class AppEnvironment : ObservableObject {
DispatchQueue.main.async {
let dateInterval = DateInterval(start: Date(), end: date)
self.notificationDates[countdown.stringId] = dateInterval
self._launchLiveActivity(countdown: countdown, endDate: date)
}
}
@ -102,6 +105,9 @@ class AppEnvironment : ObservableObject {
self._recordActivity(countdownId: countdownId)
}
self.notificationDates.removeValue(forKey: countdownId)
// self._updateLiveActivity(countdownId: countdownId, endDate: <#T##Date#>)
self._endLiveActivity(countdownId: countdownId)
}
}
@ -149,4 +155,53 @@ class AppEnvironment : ObservableObject {
self.soundPlayer?.stop()
}
// MARK: - Live Activity
fileprivate func _launchLiveActivity(countdown: Countdown, endDate: Date) {
if ActivityAuthorizationInfo().areActivitiesEnabled {
let contentState = LaunchWidgetAttributes.ContentState(ended: false)
let attributes = LaunchWidgetAttributes(id: countdown.stringId, name: countdown.displayName, endDate: endDate)
let activityContent = ActivityContent(state: contentState, staleDate: endDate.addingTimeInterval(30.0))
do {
let liveActivity = try ActivityKit.Activity.request(attributes: attributes, content: activityContent)
print("Requested a countdown Live Activity \(String(describing: liveActivity.id)).")
} catch (let error) {
print("Error requesting countdown Live Activity \(error.localizedDescription).")
}
}
}
fileprivate func _liveActivity(countdownId: String) -> ActivityKit.Activity<LaunchWidgetAttributes>? {
return ActivityKit.Activity<LaunchWidgetAttributes>.activities.first(where: { $0.attributes.id == countdownId } )
}
// fileprivate func _updateLiveActivity(countdownId: String, endDate: Date) {
// if let activity = self._liveActivity(countdownId: countdownId) {
// Task {
// let state = LaunchWidgetAttributes.ContentState(ended: true)
// let content = ActivityContent(state: state, staleDate: endDate)
// await activity.update(content)
// print("Ending the Live Activity: \(activity.id)")
// }
// }
// }
fileprivate func _endLiveActivity(countdownId: String) {
print("Trt to end the Live Activity: \(countdownId)")
if let activity = self._liveActivity(countdownId: countdownId) {
Task {
let state = LaunchWidgetAttributes.ContentState(ended: true)
let content = ActivityContent(state: state, staleDate: Date())
await activity.end(content, dismissalPolicy: .immediate)
print("Ending the Live Activity: \(activity.id)")
}
}
}
}

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSSupportsLiveActivities</key>
<true/>
<key>NSUserActivityTypes</key>
<array>
<string>SelectCountdownIntent</string>

@ -11,6 +11,10 @@ import CoreData
extension Countdown {
var displayName: String {
return self.name ?? self.coolpic.emoji
}
var name: String? {
return self.activity?.name
}
@ -23,11 +27,15 @@ extension Countdown {
}
}
var imageName: String {
if let image {
return image
var coolpic: CoolPic {
if let image, let coolpic = CoolPic(rawValue: image) {
return coolpic
}
return CoolPic.allCases[0].rawValue
return CoolPic.allCases[0]
}
var imageName: String {
return self.coolpic.rawValue
}
var soundFile: SoundFile {

@ -20,4 +20,9 @@ enum CoolPic : String, CaseIterable, Identifiable {
case pic7
case pic8
case pic9
var emoji: String {
return ""
}
}

Loading…
Cancel
Save