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.
This commit is contained in:
Arkadiusz Fal
2026-10-24 17:32:34 +02:00
parent 2a49a5db68
commit 21a6238a16
6 changed files with 106 additions and 23 deletions

View File

@@ -229,16 +229,11 @@ final class RemoteControlCoordinator {
private func startIncognitoObserver() {
incognitoObserverTask?.cancel()
incognitoObserverTask = Task { [weak self] in
guard let settings = self?.settingsManager else { return }
while !Task.isCancelled {
guard let self, let settings = self.settingsManager else { break }
let wasIncognito = settings.incognitoModeEnabled
_ = withObservationTracking {
settings.incognitoModeEnabled
} onChange: { }
try? await Task.sleep(for: .milliseconds(100))
guard !Task.isCancelled else { break }
await observationChange { _ = settings.incognitoModeEnabled }
guard let self, !Task.isCancelled else { break }
let isIncognito = settings.incognitoModeEnabled
if isIncognito != wasIncognito {