Files
MLBApp/mlbTVOS/mlbTVOSApp.swift
Trey t bf44a7b7eb 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>
2026-04-12 12:21:21 -05:00

53 lines
1.7 KiB
Swift

import AVFoundation
import SwiftUI
@main
struct mlbTVOSApp: App {
@State private var viewModel = GamesViewModel()
@Environment(\.scenePhase) private var scenePhase
init() {
configureAudioSession()
}
var body: some Scene {
WindowGroup {
ContentView()
.environment(viewModel)
.onChange(of: scenePhase) { _, newPhase in
if newPhase == .active {
Task { await viewModel.refreshIfDayChanged() }
}
}
}
}
private func configureAudioSession() {
// Start with .ambient so we don't interrupt other audio on launch
// Switch to .playback when user starts a stream
do {
try AVAudioSession.sharedInstance().setCategory(.ambient)
} catch {
print("Failed to set audio session: \(error)")
}
NotificationCenter.default.addObserver(
forName: AVAudioSession.interruptionNotification,
object: AVAudioSession.sharedInstance(),
queue: .main
) { notification in
guard let info = notification.userInfo,
let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSession.InterruptionType(rawValue: typeValue) else { return }
if type == .ended {
let options = (info[AVAudioSessionInterruptionOptionKey] as? UInt)
.flatMap(AVAudioSession.InterruptionOptions.init) ?? []
if options.contains(.shouldResume) {
try? AVAudioSession.sharedInstance().setActive(true)
}
}
}
}
}