Watch party: guests stream instead of waiting on a device copy, one load per song, host seat and guest seats can't be taken over, host reload restores the song, real taps only detach, reconnect after background, keep invite code and chat draft

This commit is contained in:
Jonathan Sykes
2026-10-15 19:12:10 +08:00
parent 63cea89b68
commit 32d1f6891b
5 changed files with 127 additions and 23 deletions

View File

@@ -2462,7 +2462,9 @@ const Player = {
_currentBlobUrl = null;
}
try {
if (WEB && !cachedIds.has(videoObj.id) && window.DirectMedia?.hasSource(videoObj.id)) {
// Party guests follow the host in real time: never hold playback for a
// full device-to-device copy (and its accept prompt) — stream instead.
if (WEB && !cachedIds.has(videoObj.id) && !Party.guestActive() && window.DirectMedia?.hasSource(videoObj.id)) {
const received = await DirectMedia.obtain(videoObj.id);
if (seq !== this._loadSeq) return;
if (!received) { showSpinner(false); return; }
@@ -6214,7 +6216,7 @@ function updateProgress() {
// A-B loop: passing B behaves like the track ending. Loop the A-B segment only
// when "loop current" is on; otherwise B is the effective end of the track and
// we advance per the repeat settings (next track, or wrap when "repeat list").
if (!playFullMode && abA !== null && abB !== null && abB > abA && cur >= abB) {
if (!playFullMode && abA !== null && abB !== null && abB > abA && cur >= abB && !Party.guestActive()) {
if (data.settings.loopOne) {
Player.seek(abA);
} else if (!advanceQueue()) {
@@ -8652,7 +8654,8 @@ function saveAbMarkers() {
}
}
function restoreAbMarkers() {
if (!current || !current.meta) { abA = null; abB = null; updateAbUI(); return; }
// A party guest follows the host's timeline; their own practice loop would fight it.
if (!current || !current.meta || Party.guestActive()) { abA = null; abB = null; updateAbUI(); return; }
// Prefer a marker stored on the current playlist's copy of the video; fall
// back to the global per-video marker.
const entry = currentPlaylistEntry();