Fix memory leaks, stale game data, and audio volume fluctuation

Memory: clean observers even during PiP, nil player on tile disappear,
track/cancel Werkout monitor tasks, add highlight player cleanup.
Data: add scenePhase-triggered reload on day change, unconditional
10-minute full schedule refresh, keep fast 60s score refresh for live games.
Audio: set mute state before playback starts, use consistent .moviePlayback
mode, add audio session interruption recovery handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-04-12 12:21:21 -05:00
parent 88308b46f5
commit bf44a7b7eb
5 changed files with 63 additions and 8 deletions

View File

@@ -53,6 +53,8 @@ final class GamesViewModel {
@ObservationIgnored
private var refreshTask: Task<Void, Never>?
@ObservationIgnored
private var lastLoadDateString: String?
@ObservationIgnored
private var authenticatedVideoFeedCache: [String: AuthenticatedVideoFeedCacheEntry] = [:]
@ObservationIgnored
private var videoShuffleBagsByModel: [String: [String: [URL]]] = [:]
@@ -105,12 +107,21 @@ final class GamesViewModel {
func startAutoRefresh() {
stopAutoRefresh()
refreshTask = Task { [weak self] in
var ticksSinceFullLoad = 0
while !Task.isCancelled {
try? await Task.sleep(for: .seconds(60))
guard !Task.isCancelled else { break }
guard let self else { break }
// Refresh if there are live games or active streams
if !self.liveGames.isEmpty || !self.activeStreams.isEmpty {
ticksSinceFullLoad += 1
// Full schedule reload every 10 minutes (or immediately on day change)
let today = Self.dateFormatter.string(from: Date())
let dayChanged = self.lastLoadDateString != nil && self.lastLoadDateString != today
if dayChanged || ticksSinceFullLoad >= 10 {
ticksSinceFullLoad = 0
await self.loadGames()
} else if !self.liveGames.isEmpty || !self.activeStreams.isEmpty {
// Fast score refresh every 60s when games are live
await self.refreshScores()
}
}
@@ -122,6 +133,14 @@ final class GamesViewModel {
refreshTask = nil
}
func refreshIfDayChanged() async {
let today = Self.dateFormatter.string(from: Date())
if lastLoadDateString != today {
logGamesViewModel("Day changed (\(lastLoadDateString ?? "nil")\(today)), reloading games")
await loadGames()
}
}
private func refreshScores() async {
let statsGames = await fetchStatsGames()
guard !statsGames.isEmpty else { return }
@@ -227,6 +246,7 @@ final class GamesViewModel {
errorMessage = "No games found"
}
lastLoadDateString = todayDateString
isLoading = false
}