fix: unblock watch together resume

close #961
This commit is contained in:
edde746
2026-05-02 22:36:49 +02:00
parent afdec05dbf
commit 45770e1ad6
3 changed files with 256 additions and 9 deletions
@@ -432,6 +432,7 @@ class WatchTogetherProvider with ChangeNotifier {
final disconnectedName = _participants.where((p) => p.peerId == peerId).map((p) => p.displayName).firstOrNull;
_participants.removeWhere((p) => p.peerId == peerId);
unawaited(_syncManager?.handlePeerDisconnected(peerId));
// If host disconnected unexpectedly, start grace period for reconnection.
// Skip if the host already sent a deliberate leave message.
@@ -121,6 +121,9 @@ class WatchTogetherSyncManager {
_player = player;
_lastKnownPlaying = player.state.playing;
_lastKnownRate = player.state.rate;
if (player.state.playing) {
_firstPlayCompleted = true;
}
_setupPlayerSubscriptions();
_setupMessageSubscription();
@@ -174,6 +177,14 @@ class WatchTogetherSyncManager {
appLogger.d('WatchTogether: Initialized $otherCount existing participants (host=${_session.isHost})');
}
/// Remove readiness tracking for a peer that dropped at the relay level.
Future<void> handlePeerDisconnected(String peerId) async {
if (_peerReady.remove(peerId) != null) {
appLogger.d('WatchTogether: Removed disconnected peer readiness: $peerId');
await _resumeDeferredPlayIfReady(_playerAttachmentGeneration);
}
}
/// Detach the player and stop sync
void detachPlayer() {
_playerAttachmentGeneration++;
@@ -631,6 +642,7 @@ class WatchTogetherSyncManager {
case SyncMessageType.leave:
if (message.peerId != null) {
_peerReady.remove(message.peerId);
await _resumeDeferredPlayIfReady(queuedAttachmentGeneration);
}
break;
@@ -668,15 +680,7 @@ class WatchTogetherSyncManager {
_peerReady[message.peerId!] = message.bufferingState ?? false;
appLogger.d('WatchTogether: Peer ${message.peerId} player ready: ${message.bufferingState}');
if (_deferredPlay && isAllReady) {
_setDeferredPlay(false);
_firstPlayCompleted = true;
final pos = _deferredPlayPosition;
_deferredPlayPosition = null;
await _applyRemotePlay(position: pos, expectedAttachmentGeneration: queuedAttachmentGeneration);
// Broadcast play to all peers now that everyone is ready
_broadcastPlayPause(true);
}
await _resumeDeferredPlayIfReady(queuedAttachmentGeneration);
}
break;
@@ -714,12 +718,25 @@ class WatchTogetherSyncManager {
);
if (!didPlay) return false;
_firstPlayCompleted = true;
_lastKnownPlaying = true;
return true;
},
);
}
Future<void> _resumeDeferredPlayIfReady(int expectedAttachmentGeneration) async {
if (!_deferredPlay || !isAllReady) return;
_setDeferredPlay(false);
_firstPlayCompleted = true;
final pos = _deferredPlayPosition;
_deferredPlayPosition = null;
await _applyRemotePlay(position: pos, expectedAttachmentGeneration: expectedAttachmentGeneration);
// Broadcast play to all peers now that everyone is ready.
_broadcastPlayPause(true);
}
/// Apply remote pause command
Future<bool> _applyRemotePause({int? expectedAttachmentGeneration}) async {
return _runGuardedRemoteAction(