fix: suppress position sync when app backgrounded

This commit is contained in:
edde746
2026-04-16 15:43:08 +02:00
parent 34815f22ee
commit f055759c7a
3 changed files with 25 additions and 1 deletions
+5
View File
@@ -472,6 +472,10 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
return;
}
// Suppress Watch Together heartbeats while backgrounded so App Nap
// doesn't cause stale position broadcasts that make guests loop.
_watchTogetherProvider?.setBackgrounded(true);
final currentPlayer = player;
if (currentPlayer == null || !_isPlayerInitialized) {
_recordLifecycleState('hidden', action: 'skipped_no_player');
@@ -511,6 +515,7 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
Future<void> _handleAppResumed() async {
_recordLifecycleState('resumed', action: 'begin');
_watchTogetherProvider?.setBackgrounded(false);
if (Platform.isAndroid && _androidAutoPipTransitionInFlight && !PipService().isPipActive.value) {
_setAndroidAutoPipTransitionInFlight(false, reason: 'resume_without_pip');
@@ -402,6 +402,11 @@ class WatchTogetherProvider with ChangeNotifier {
appLogger.d('WatchTogether: Player detached from sync manager');
}
/// Suppress position sync while the app is backgrounded.
void setBackgrounded(bool value) {
_syncManager?.setBackgrounded(value);
}
/// Set up listeners for peer service events
void _setupPeerServiceListeners() {
_peerConnectedSubscription = _peerService!.onPeerConnected.listen((peerId) {
@@ -79,6 +79,9 @@ class WatchTogetherSyncManager {
// Whether we've announced our player as ready (first buffering: false)
bool _hasAnnouncedReady = false;
// Whether the app is backgrounded (suppress heartbeats to avoid stale positions)
bool _backgrounded = false;
// Callbacks
SessionConfigCallback? onSessionConfigReceived;
SyncStateCallback? onSyncStateChanged;
@@ -204,6 +207,7 @@ class WatchTogetherSyncManager {
}
_positionSyncTimer?.cancel();
_positionSyncTimer = null;
_backgrounded = false;
appLogger.d('WatchTogether: Player detached');
}
@@ -313,7 +317,7 @@ class WatchTogetherSyncManager {
void _startPositionSync() {
_positionSyncTimer?.cancel();
_positionSyncTimer = Timer.periodic(positionSyncInterval, (_) {
if (_player != null && _session.isHost) {
if (_player != null && _session.isHost && !_backgrounded) {
_peerService.broadcast(
SyncMessage.positionSync(
_player!.state.position,
@@ -956,6 +960,16 @@ class WatchTogetherSyncManager {
}
}
/// Suppress heartbeats while the app is backgrounded.
///
/// macOS App Nap can throttle the event loop, causing stale position reads.
/// Guests would drift-correct to the stale position every heartbeat, making
/// playback loop. Pausing heartbeats avoids this; drift correction catches
/// up when the app returns to the foreground.
void setBackgrounded(bool value) {
_backgrounded = value;
}
/// Re-announce player readiness after reconnect.
///
/// During reconnect the host resets our _peerReady entry to false via