diff --git a/public/app.js b/public/app.js index 8f1026b..10425c7 100644 --- a/public/app.js +++ b/public/app.js @@ -323,17 +323,20 @@ function loadYoutubeApi() { }); } -async function ensureYoutubePlayer() { +async function ensureYoutubePlayer(initialState = {}) { await loadYoutubeApi(); if (youtubePlayer) return youtubePlayer; - youtubePlayer = new YT.Player("youtube-player", { + const initialVideoId = initialState.videoId || ""; + const initialPosition = Math.max(0, Number(initialState.position) || 0); + const shouldAutoplay = Boolean(initialState.autoplay && initialVideoId); + const options = { playerVars: { controls: 1, disablekb: 0, modestbranding: 1, playsinline: 1, - autoplay: 1, + autoplay: shouldAutoplay ? 1 : 0, origin: window.location.origin, rel: 0 }, @@ -342,17 +345,27 @@ async function ensureYoutubePlayer() { youtubeReady = true; const iframe = youtubePlayer?.getIframe?.(); iframe?.setAttribute("allow", "autoplay; encrypted-media; fullscreen; picture-in-picture"); + if (shouldAutoplay) { + requestYoutubePlayback(youtubePlayer, initialVideoId, initialPosition); + } if (pendingWatchState) { const state = pendingWatchState; - const options = pendingWatchStateOptions || {}; + const pendingOptions = pendingWatchStateOptions || {}; pendingWatchState = null; pendingWatchStateOptions = null; - applyWatchState(state, options).catch(console.error); + applyWatchState(state, pendingOptions).catch(console.error); } }, onStateChange: handleYoutubeStateChange } - }); + }; + + if (initialVideoId) { + options.videoId = initialVideoId; + options.playerVars.start = Math.floor(initialPosition); + } + + youtubePlayer = new YT.Player("youtube-player", options); return youtubePlayer; } @@ -514,8 +527,16 @@ async function applyWatchState(state, { suppressEvents = true } = {}) { setWatchCollapsed(false); } + const updatedAt = Number(state.updatedAt) || Date.now(); + const elapsed = shouldPlay ? Math.max(0, (Date.now() - updatedAt) / 1000) : 0; + const position = Math.max(0, Number(state.position || 0) + elapsed); + youtubeShell.classList.add("is-active"); - const player = await ensureYoutubePlayer(); + const player = await ensureYoutubePlayer({ + videoId: currentYoutubeVideoId, + position, + autoplay: shouldPlay + }); if (suppressEvents) { applyingWatchStateUntil = Date.now() + 3000; } @@ -530,9 +551,6 @@ async function applyWatchState(state, { suppressEvents = true } = {}) { pauseEnforcementUntil = Math.max(pauseEnforcementUntil, Date.now() + 3000); } - const elapsed = shouldPlay ? Math.max(0, (Date.now() - state.updatedAt) / 1000) : 0; - const position = Math.max(0, Number(state.position || 0) + elapsed); - if (youtubeReady) { if (shouldPlay) { const sameVideo = player.getVideoData?.().video_id === currentYoutubeVideoId;