Files
yattee/Yattee/Utilities/ObservationChange.swift
Arkadiusz Fal 21a6238a16 Stop re-rendering hidden player UI during background playback
Every mpv time-pos tick updated PlayerState.currentTime and bufferedTime,
re-rendering the invisible player controls, progress bar and chapter
segments several times per second while the app played in the
background, which drained the battery during long audio-only sessions.

- PlayerState keeps currentTime/bufferedTime current for readers but
  stops notifying observers while publishesTimeUpdates is off;
  PlayerService turns it off on entering the background and back on
  (with one catch-up notification) before returning to the foreground
- MarqueeText pauses its animation timeline outside the active scene
- Replace the 100 ms polling loops in RemoteControlCoordinator and
  ToastManager (iOS/tvOS) with observation-driven waits

Main-thread samples during 30 s of background audio-only playback on an
iPhone 12 mini went from 1289 to 248.
2026-10-24 17:32:34 +02:00

22 lines
572 B
Swift

//
// ObservationChange.swift
// Yattee
//
import Foundation
import Observation
/// Suspends until a property read in `track` changes, or the task is cancelled.
///
/// Use in an observer loop instead of polling with `Task.sleep`, which keeps
/// waking the main thread for as long as the app runs.
@MainActor
func observationChange(_ track: () -> Void) async {
let (changes, continuation) = AsyncStream<Void>.makeStream()
withObservationTracking(track) {
continuation.yield()
continuation.finish()
}
for await _ in changes { break }
}