|
|
|
|
@ -64,6 +64,7 @@ class Conductor: ObservableObject { |
|
|
|
|
func removeLiveTimer(id: TimerID) { |
|
|
|
|
// Logger.log("removeLiveTimer") |
|
|
|
|
self.liveTimers.removeAll(where: { $0.id == id }) |
|
|
|
|
self.currentStopwatches.removeValue(forKey: id) |
|
|
|
|
self.cancelledCountdowns.removeAll(where: { $0 == id }) |
|
|
|
|
if let soundPlayer = self._delayedSoundPlayers[id] { |
|
|
|
|
soundPlayer.stop() |
|
|
|
|
@ -93,7 +94,7 @@ class Conductor: ObservableObject { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let liveStopwatches: [LiveTimer] = self.currentStopwatches.map { |
|
|
|
|
return LiveTimer(id: $0, date: $1.start) |
|
|
|
|
return LiveTimer(id: $0, date: $1.start, endDate: $1.end) |
|
|
|
|
} |
|
|
|
|
for liveStopwatch in liveStopwatches { |
|
|
|
|
if let index = self.liveTimers.firstIndex(where: { $0.id == liveStopwatch.id }) { |
|
|
|
|
@ -167,7 +168,8 @@ class Conductor: ObservableObject { |
|
|
|
|
if Preferences.playConfirmationSound { |
|
|
|
|
self._playConfirmationSound(timer: countdown) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
self._launchLiveActivity(timer: countdown, date: date) |
|
|
|
|
|
|
|
|
|
handler(.success(date)) |
|
|
|
|
} catch { |
|
|
|
|
Logger.error(error) |
|
|
|
|
@ -181,13 +183,19 @@ class Conductor: ObservableObject { |
|
|
|
|
func startStopwatch(_ stopwatch: Stopwatch) { |
|
|
|
|
DispatchQueue.main.async { |
|
|
|
|
let lsw = LiveStopWatch(start: Date()) |
|
|
|
|
Conductor.maestro.currentStopwatches[stopwatch.stringId] = lsw |
|
|
|
|
|
|
|
|
|
// if let liveTimer = liveTimers.first(where: { $0.id == stopwatch.stringId }) { |
|
|
|
|
// liveTimer. |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
self.currentStopwatches[stopwatch.stringId] = lsw |
|
|
|
|
|
|
|
|
|
if Preferences.playConfirmationSound { |
|
|
|
|
self._playSound(Const.confirmationSound.rawValue) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
self._launchLiveActivity(stopwatch: stopwatch, start: lsw.start) |
|
|
|
|
self._endLiveActivity(timerId: stopwatch.stringId) |
|
|
|
|
self._launchLiveActivity(timer: stopwatch, date: lsw.start) |
|
|
|
|
|
|
|
|
|
// self._createTimerIntent(stopwatch) |
|
|
|
|
|
|
|
|
|
@ -200,7 +208,9 @@ class Conductor: ObservableObject { |
|
|
|
|
if lsw.end == nil { |
|
|
|
|
let end = Date() |
|
|
|
|
lsw.end = end |
|
|
|
|
// Conductor.maestro.currentStopwatches.removeValue(forKey: stopwatch.stringId) |
|
|
|
|
|
|
|
|
|
Conductor.maestro.currentStopwatches[stopwatch.stringId] = lsw |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
try CoreDataRequests.recordActivity(timer: stopwatch, dateInterval: DateInterval(start: lsw.start, end: end)) |
|
|
|
|
} catch { |
|
|
|
|
@ -238,6 +248,7 @@ class Conductor: ObservableObject { |
|
|
|
|
|
|
|
|
|
func cleanup() { |
|
|
|
|
self._cleanupCountdowns() |
|
|
|
|
self.cleanupLiveActivities() |
|
|
|
|
|
|
|
|
|
withAnimation { |
|
|
|
|
self._cleanupLiveTimers() |
|
|
|
|
@ -368,19 +379,19 @@ class Conductor: ObservableObject { |
|
|
|
|
|
|
|
|
|
// MARK: - Live Activity |
|
|
|
|
|
|
|
|
|
fileprivate func _launchLiveActivity(stopwatch: Stopwatch, start: Date) { |
|
|
|
|
fileprivate func _launchLiveActivity(timer: AbstractTimer, date: Date) { |
|
|
|
|
|
|
|
|
|
if #available(iOS 16.2, *) { |
|
|
|
|
|
|
|
|
|
if ActivityAuthorizationInfo().areActivitiesEnabled { |
|
|
|
|
|
|
|
|
|
let contentState = LaunchWidgetAttributes.ContentState(ended: false) |
|
|
|
|
let attributes = LaunchWidgetAttributes(id: stopwatch.stringId, name: stopwatch.displayName, date: start) |
|
|
|
|
let attributes = LaunchWidgetAttributes(id: timer.stringId, name: timer.displayName, date: date, isTimer: timer is Countdown) |
|
|
|
|
|
|
|
|
|
let activityContent = ActivityContent(state: contentState, staleDate: nil) |
|
|
|
|
do { |
|
|
|
|
let liveActivity = try ActivityKit.Activity.request(attributes: attributes, content: activityContent) |
|
|
|
|
print("Requested a Live Activity: \(String(describing: liveActivity.id)).") |
|
|
|
|
print("Requested a Live Activity: \(String(describing: liveActivity.id))") |
|
|
|
|
} catch (let error) { |
|
|
|
|
Logger.error(error) |
|
|
|
|
} |
|
|
|
|
@ -392,41 +403,36 @@ class Conductor: ObservableObject { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _liveActivity(timerId: String) -> ActivityKit.Activity<LaunchWidgetAttributes>? { |
|
|
|
|
return ActivityKit.Activity<LaunchWidgetAttributes>.activities.first(where: { $0.attributes.id == timerId } ) |
|
|
|
|
fileprivate func _liveActivity(timerId: String) -> [ActivityKit.Activity<LaunchWidgetAttributes>] { |
|
|
|
|
return ActivityKit.Activity<LaunchWidgetAttributes>.activities.filter { $0.id == timerId } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _liveActivityIds() -> [String] { |
|
|
|
|
return ActivityKit.Activity<LaunchWidgetAttributes>.activities.map { $0.id } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func cleanupLiveActivities() { |
|
|
|
|
for id in self._liveActivityIds() { |
|
|
|
|
if self.liveTimers.first(where: { $0.id == id} ) == nil { |
|
|
|
|
self._endLiveActivity(timerId: id) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func updateLiveActivities() { |
|
|
|
|
print("update live activity...") |
|
|
|
|
|
|
|
|
|
for (countdownId, interval) in self.currentCountdowns { |
|
|
|
|
|
|
|
|
|
if interval.end < Date() { |
|
|
|
|
self._endLiveActivity(timerId: countdownId) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// if let activity = self._liveActivity(countdownId: countdownId) { |
|
|
|
|
// |
|
|
|
|
// Task { |
|
|
|
|
// |
|
|
|
|
// if ended { |
|
|
|
|
// self._endLiveActivity(countdownId: countdownId) |
|
|
|
|
// } |
|
|
|
|
// |
|
|
|
|
//// let state = LaunchWidgetAttributes.ContentState(ended: ended) |
|
|
|
|
//// let content = ActivityContent(state: state, staleDate: interval.end) |
|
|
|
|
//// await activity.update(content) |
|
|
|
|
//// print("Ending the Live Activity: \(activity.id)") |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _endLiveActivity(timerId: String) { |
|
|
|
|
if #available(iOS 16.2, *) { |
|
|
|
|
print("Try to end the Live Activity: \(timerId)") |
|
|
|
|
if let activity = self._liveActivity(timerId: timerId) { |
|
|
|
|
for activity in self._liveActivity(timerId: timerId) { |
|
|
|
|
Task { |
|
|
|
|
let state = LaunchWidgetAttributes.ContentState(ended: true) |
|
|
|
|
let content = ActivityContent(state: state, staleDate: Date()) |
|
|
|
|
|