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>
53 lines
1.7 KiB
Swift
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|