fix: Dynamic Island, Live Activity errors, background audio stop, CFBundleVersion
Some checks failed
CI / Deploy (pull_request) Has been skipped
PR → Build → WiFi/USB Deploy → LGTM / Wait for LGTM comment (pull_request) Failing after 8m7s
CI / Detect Changes (pull_request) Successful in 3s
CI / Admin Web CI (pull_request) Has been skipped
CI / YouTube Worker (pull_request) Has been skipped
PR → Build → WiFi/USB Deploy → LGTM / Build & Deploy to iPhone (WiFi/USB) (pull_request) Successful in 2m58s

Phase 1 — Audio background resilience:
- Remove .mixWithOthers, app takes audio focus for coach cues
- Add AVAudioSession.interruptionNotification handler (re-activates after calls/Siri)
- Add AVAudioSession.routeChangeNotification handler (re-activates on headphone changes)

Phase 2 — Live Activity error surfacing:
- PlayerViewModel: @Published liveActivityError captures auth-denied + request errors
- PlayerView: translucent error banner with dismiss button (non-blocking)

Phase 3 — CFBundleVersion 1→2 in all 4 Info.plist files (match project.yml CURRENT_PROJECT_VERSION: 2)
This commit is contained in:
Millian Lamiaux
2026-07-04 17:54:09 +02:00
parent 560b056dc9
commit 40ffb04f31
7 changed files with 89 additions and 6 deletions

View File

@@ -39,6 +39,7 @@ final class PlayerViewModel: ObservableObject {
@Published var isComplete: Bool = false
@Published var showExitConfirmation: Bool = false
@Published private(set) var completedSession: WorkoutSession? = nil
@Published var liveActivityError: String? = nil
// Track info for Live Activity set by View when music changes
var currentTrackTitle = ""
@@ -382,7 +383,10 @@ final class PlayerViewModel: ObservableObject {
// Dynamic Island / Live Activity
func syncActivity(shouldAlert: Bool = false) {
guard ActivityAuthorizationInfo().areActivitiesEnabled else { return }
guard ActivityAuthorizationInfo().areActivitiesEnabled else {
liveActivityError = "Live Activities are disabled in Settings"
return
}
guard isRunning else { return }
let isPlayingMusic = (phase == .work || phase == .rest) && isRunning && !isPaused
@@ -449,8 +453,10 @@ final class PlayerViewModel: ObservableObject {
attributes: attrs,
content: ActivityContent(state: state, staleDate: staleDate)
)
liveActivityError = nil
observeActivityState()
} catch {
liveActivityError = error.localizedDescription
print("❌ Failed to start Live Activity: \(error.localizedDescription)")
}
}