Limit YouTube start prompt to join sync

This commit is contained in:
codex
2026-06-10 20:44:28 +02:00
parent abf23213cd
commit f3d08fbf9e
+26 -8
View File
@@ -52,6 +52,7 @@ let currentYoutubeVideoId = "";
let applyingWatchStateUntil = 0;
let pauseEnforcementUntil = 0;
let syncedPlaybackRetryUntil = 0;
let youtubeStartPromptAllowedUntil = 0;
let desiredYoutubePlaying = false;
let youtubeReadyResolvers = [];
let watchApplySequence = 0;
@@ -348,7 +349,12 @@ async function ensureYoutubePlayer(initialState = {}) {
iframe?.setAttribute("allow", "autoplay; encrypted-media; fullscreen; picture-in-picture");
youtubeReadyResolvers.splice(0).forEach((resolve) => resolve());
if (shouldAutoplay) {
requestYoutubePlayback(youtubePlayer, initialVideoId, initialPosition);
requestYoutubePlayback(
youtubePlayer,
initialVideoId,
initialPosition,
Boolean(initialState.allowStartPrompt)
);
}
},
onStateChange: handleYoutubeStateChange
@@ -382,7 +388,7 @@ function setYoutubeStartPromptVisible(visible) {
youtubeStartButton.hidden = !visible;
}
function requestYoutubePlayback(player, videoId, position) {
function requestYoutubePlayback(player, videoId, position, allowStartPrompt = false) {
const requestId = ++youtubePlaybackRequestId;
const startedAt = Date.now();
@@ -420,6 +426,8 @@ function requestYoutubePlayback(player, videoId, position) {
requestId === youtubePlaybackRequestId &&
desiredYoutubePlaying &&
currentYoutubeVideoId === videoId &&
allowStartPrompt &&
Date.now() < youtubeStartPromptAllowedUntil &&
player.getPlayerState?.() !== YT.PlayerState.PLAYING
) {
setYoutubeStartPromptVisible(true);
@@ -476,7 +484,12 @@ function handleYoutubeStateChange(event) {
now < syncedPlaybackRetryUntil &&
[YT.PlayerState.UNSTARTED, YT.PlayerState.CUED, YT.PlayerState.PAUSED].includes(event.data)
) {
requestYoutubePlayback(youtubePlayer, currentYoutubeVideoId, currentYoutubeSnapshot().position);
requestYoutubePlayback(
youtubePlayer,
currentYoutubeVideoId,
currentYoutubeSnapshot().position,
Date.now() < youtubeStartPromptAllowedUntil
);
return;
}
if (event.data === YT.PlayerState.PLAYING) {
@@ -500,6 +513,7 @@ function handleYoutubeStateChange(event) {
desiredYoutubePlaying = action === "play";
if (desiredYoutubePlaying) {
syncedPlaybackRetryUntil = 0;
youtubeStartPromptAllowedUntil = 0;
setYoutubeStartPromptVisible(false);
} else {
setYoutubeStartPromptVisible(false);
@@ -523,7 +537,7 @@ function handleYoutubeStateChange(event) {
}
}
async function applyWatchState(state, { suppressEvents = true } = {}) {
async function applyWatchState(state, { suppressEvents = true, allowStartPrompt = false } = {}) {
const applySequence = ++watchApplySequence;
const shouldPlay = state?.action === "play" || (!state?.action && Boolean(state?.playing));
watchPlaylist = normalizedPlaylist(state?.playlist);
@@ -541,6 +555,7 @@ async function applyWatchState(state, { suppressEvents = true } = {}) {
desiredYoutubePlaying = false;
youtubePlaybackRequestId++;
syncedPlaybackRetryUntil = 0;
youtubeStartPromptAllowedUntil = 0;
setYoutubeStartPromptVisible(false);
youtubePlayer?.stopVideo?.();
youtubeShell.classList.remove("is-active");
@@ -560,7 +575,8 @@ async function applyWatchState(state, { suppressEvents = true } = {}) {
const player = await ensureYoutubePlayer({
videoId: currentYoutubeVideoId,
position,
autoplay: shouldPlay
autoplay: shouldPlay,
allowStartPrompt
});
await whenYoutubeReady();
if (applySequence !== watchApplySequence) return;
@@ -572,15 +588,17 @@ async function applyWatchState(state, { suppressEvents = true } = {}) {
if (suppressEvents) {
syncedPlaybackRetryUntil = Date.now() + 8000;
}
youtubeStartPromptAllowedUntil = allowStartPrompt ? Date.now() + 10000 : 0;
} else {
youtubePlaybackRequestId++;
syncedPlaybackRetryUntil = 0;
youtubeStartPromptAllowedUntil = 0;
setYoutubeStartPromptVisible(false);
pauseEnforcementUntil = Math.max(pauseEnforcementUntil, Date.now() + 3000);
}
if (shouldPlay) {
setYoutubeStartPromptVisible(true);
setYoutubeStartPromptVisible(allowStartPrompt);
const sameVideo = player.getVideoData?.().video_id === currentYoutubeVideoId;
const playerState = player.getPlayerState?.();
if (sameVideo && ![YT.PlayerState.UNSTARTED, YT.PlayerState.CUED].includes(playerState)) {
@@ -591,7 +609,7 @@ async function applyWatchState(state, { suppressEvents = true } = {}) {
if (playerState !== YT.PlayerState.PLAYING) {
player.playVideo();
}
requestYoutubePlayback(player, currentYoutubeVideoId, position);
requestYoutubePlayback(player, currentYoutubeVideoId, position, allowStartPrompt);
} else {
if (player.getVideoData?.().video_id !== currentYoutubeVideoId) {
player.cueVideoById(currentYoutubeVideoId, position);
@@ -871,7 +889,7 @@ async function handleSignal(message) {
peerId = message.peerId;
setStatus(`Joined the call as ${displayName}. ${message.peers.length} other participant(s).`);
if (message.watchState) {
await applyWatchState(message.watchState);
await applyWatchState(message.watchState, { allowStartPrompt: true });
}
if (message.presentationState?.sharing) {
setTimeout(() => {