Prompt to start blocked synced YouTube playback
This commit is contained in:
@@ -13,6 +13,7 @@ const statusText = document.querySelector("#status");
|
||||
const youtubeForm = document.querySelector("#youtube-form");
|
||||
const youtubeInput = document.querySelector("#youtube-input");
|
||||
const youtubeShell = document.querySelector("#youtube-shell");
|
||||
const youtubeStartButton = document.querySelector("#youtube-start-button");
|
||||
const watchPanel = document.querySelector(".watch-panel");
|
||||
const watchResizeHandle = document.querySelector("#watch-resize-handle");
|
||||
const watchCollapseButton = document.querySelector("#watch-collapse-button");
|
||||
@@ -376,9 +377,14 @@ function loadYoutubeVideo(player, videoId, position) {
|
||||
});
|
||||
}
|
||||
|
||||
function setYoutubeStartPromptVisible(visible) {
|
||||
youtubeStartButton.hidden = !visible;
|
||||
}
|
||||
|
||||
function requestYoutubePlayback(player, videoId, position) {
|
||||
const requestId = ++youtubePlaybackRequestId;
|
||||
const startedAt = Date.now();
|
||||
setYoutubeStartPromptVisible(false);
|
||||
|
||||
for (const delay of [0, 150, 750, 1500, 3000]) {
|
||||
setTimeout(() => {
|
||||
@@ -408,6 +414,17 @@ function requestYoutubePlayback(player, videoId, position) {
|
||||
player.playVideo();
|
||||
}, delay);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (
|
||||
requestId === youtubePlaybackRequestId &&
|
||||
desiredYoutubePlaying &&
|
||||
currentYoutubeVideoId === videoId &&
|
||||
player.getPlayerState?.() !== YT.PlayerState.PLAYING
|
||||
) {
|
||||
setYoutubeStartPromptVisible(true);
|
||||
}
|
||||
}, 3300);
|
||||
}
|
||||
|
||||
async function sendWatchState({
|
||||
@@ -462,6 +479,9 @@ function handleYoutubeStateChange(event) {
|
||||
requestYoutubePlayback(youtubePlayer, currentYoutubeVideoId, currentYoutubeSnapshot().position);
|
||||
return;
|
||||
}
|
||||
if (event.data === YT.PlayerState.PLAYING) {
|
||||
setYoutubeStartPromptVisible(false);
|
||||
}
|
||||
|
||||
if (![YT.PlayerState.PLAYING, YT.PlayerState.PAUSED, YT.PlayerState.ENDED].includes(event.data)) {
|
||||
return;
|
||||
@@ -480,6 +500,9 @@ function handleYoutubeStateChange(event) {
|
||||
desiredYoutubePlaying = action === "play";
|
||||
if (desiredYoutubePlaying) {
|
||||
syncedPlaybackRetryUntil = 0;
|
||||
setYoutubeStartPromptVisible(false);
|
||||
} else {
|
||||
setYoutubeStartPromptVisible(false);
|
||||
}
|
||||
const state = currentWatchState(action === "play");
|
||||
if (state) {
|
||||
@@ -517,6 +540,7 @@ async function applyWatchState(state, { suppressEvents = true } = {}) {
|
||||
desiredYoutubePlaying = false;
|
||||
youtubePlaybackRequestId++;
|
||||
syncedPlaybackRetryUntil = 0;
|
||||
setYoutubeStartPromptVisible(false);
|
||||
youtubePlayer?.stopVideo?.();
|
||||
youtubeShell.classList.remove("is-active");
|
||||
setWatchCollapsed(true);
|
||||
@@ -548,6 +572,7 @@ async function applyWatchState(state, { suppressEvents = true } = {}) {
|
||||
} else {
|
||||
youtubePlaybackRequestId++;
|
||||
syncedPlaybackRetryUntil = 0;
|
||||
setYoutubeStartPromptVisible(false);
|
||||
pauseEnforcementUntil = Math.max(pauseEnforcementUntil, Date.now() + 3000);
|
||||
}
|
||||
|
||||
@@ -1119,6 +1144,21 @@ announcementForm.addEventListener("submit", (event) => {
|
||||
});
|
||||
});
|
||||
|
||||
youtubeStartButton.addEventListener("click", () => {
|
||||
if (!youtubePlayer || !currentYoutubeVideoId) return;
|
||||
|
||||
const position = currentYoutubeSnapshot().position;
|
||||
if (youtubePlayer.getVideoData?.().video_id !== currentYoutubeVideoId) {
|
||||
loadYoutubeVideo(youtubePlayer, currentYoutubeVideoId, position);
|
||||
} else {
|
||||
youtubePlayer.seekTo?.(position, true);
|
||||
}
|
||||
youtubePlayer.unMute?.();
|
||||
youtubePlayer.playVideo?.();
|
||||
requestYoutubePlayback(youtubePlayer, currentYoutubeVideoId, position);
|
||||
setYoutubeStartPromptVisible(false);
|
||||
});
|
||||
|
||||
cameraButton.addEventListener("click", () => {
|
||||
const enabled = cameraButton.getAttribute("aria-pressed") !== "true";
|
||||
updateToggleButton(cameraButton, enabled, "Turn camera off", "Turn camera on");
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
<div class="watch-main">
|
||||
<div class="youtube-shell" id="youtube-shell">
|
||||
<div id="youtube-player"></div>
|
||||
<button
|
||||
id="youtube-start-button"
|
||||
class="youtube-start-button"
|
||||
type="button"
|
||||
hidden
|
||||
>
|
||||
Start synced playback
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<aside class="playlist-panel">
|
||||
|
||||
@@ -199,6 +199,7 @@ button[aria-pressed="false"] {
|
||||
}
|
||||
|
||||
.youtube-shell {
|
||||
position: relative;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
@@ -217,6 +218,17 @@ button[aria-pressed="false"] {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.youtube-start-button {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 18px;
|
||||
z-index: 2;
|
||||
width: auto;
|
||||
min-width: 180px;
|
||||
transform: translateX(-50%);
|
||||
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.38);
|
||||
}
|
||||
|
||||
.watch-resize-handle {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
|
||||
Reference in New Issue
Block a user