feat: Dynamic Island pause state, Apple-aligned spacing, and UI polish
- Add isPaused to WorkoutActivityAttributes.ContentState - Show PAUSED badge, freeze timer to static text, dim content when paused - Prevent stale spinner on pause by extending staleDate to 1 hour - Add 6s timer warning color, progress bar, compact heavy timer - Pulsing compact indicator during WORK phase - Lock Screen margins aligned to Apple's 14pt HIG spec
This commit is contained in:
@@ -152,6 +152,7 @@ final class PlayerViewModel: ObservableObject {
|
||||
timer?.invalidate()
|
||||
stopActivitySyncTimer()
|
||||
liveSession.pause()
|
||||
syncActivity()
|
||||
softHaptics.impactOccurred()
|
||||
}
|
||||
|
||||
@@ -380,7 +381,8 @@ final class PlayerViewModel: ObservableObject {
|
||||
heartRate: heartRate,
|
||||
trackTitle: currentTrackTitle,
|
||||
trackArtist: currentTrackArtist,
|
||||
isPlaying: isPlayingMusic
|
||||
isPlaying: isPlayingMusic,
|
||||
isPaused: isPaused
|
||||
)
|
||||
|
||||
// Discard stale reference — user may have dismissed the Dynamic Island
|
||||
@@ -390,8 +392,9 @@ final class PlayerViewModel: ObservableObject {
|
||||
|
||||
if let existing = workoutActivity {
|
||||
nonisolated(unsafe) let safeExisting = existing
|
||||
let staleDate = Date().addingTimeInterval(isPaused ? 3600 : 120)
|
||||
Task { @MainActor in
|
||||
await safeExisting.update(ActivityContent(state: state, staleDate: Date().addingTimeInterval(120)))
|
||||
await safeExisting.update(ActivityContent(state: state, staleDate: staleDate))
|
||||
}
|
||||
} else {
|
||||
createOrUpdateActivity(with: state)
|
||||
@@ -401,9 +404,10 @@ final class PlayerViewModel: ObservableObject {
|
||||
private func createOrUpdateActivity(with state: WorkoutActivityAttributes.ContentState) {
|
||||
let attrs = WorkoutActivityAttributes()
|
||||
do {
|
||||
let staleDate = Date().addingTimeInterval(isPaused ? 3600 : 120)
|
||||
workoutActivity = try Activity.request(
|
||||
attributes: attrs,
|
||||
content: ActivityContent(state: state, staleDate: Date().addingTimeInterval(120))
|
||||
content: ActivityContent(state: state, staleDate: staleDate)
|
||||
)
|
||||
observeActivityState()
|
||||
} catch {
|
||||
@@ -427,7 +431,8 @@ final class PlayerViewModel: ObservableObject {
|
||||
heartRate: safeActivity.content.state.heartRate,
|
||||
trackTitle: safeActivity.content.state.trackTitle,
|
||||
trackArtist: safeActivity.content.state.trackArtist,
|
||||
isPlaying: false
|
||||
isPlaying: false,
|
||||
isPaused: false
|
||||
)
|
||||
await safeActivity.end(ActivityContent(state: finalState, staleDate: nil), dismissalPolicy: .immediate)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user