diff --git a/static/index.html b/static/index.html index 4ba1b43..b20cd82 100644 --- a/static/index.html +++ b/static/index.html @@ -52,7 +52,9 @@ background-color: #444; aspect-ratio: 16/9; width: 20vw; - transition: width 0.3s ease, box-shadow 0.3s ease; + transition: width 0.3s ease, box-shadow 0.3s ease, left 0.3s ease; + transform: translate(-50%, 0); + position: fixed; } .video-thumbnail.focussed { @@ -104,6 +106,7 @@ width: 100%; height: 100%; display: block; + position: fixed; } #video-overlay-container #back-button { /* Back button is now inside the container */ @@ -299,7 +302,7 @@ } } - let videoThumbnails = []; + let videoInfo = []; let selectedThumbnailIndex = 0; /** @@ -314,12 +317,19 @@ let index; if (append) { $("#video-container").append(thumbnail); - index = videoThumbnails.length; - videoThumbnails.push(thumbnail) + index = videoInfo.length; + videoInfo.push({ + thumbnail, + data + }) } else { $("#video-container").prepend(thumbnail); index = 0; - videoThumbnails.unshift(thumbnail); + videoInfo.unshift({ + thumbnail, + data + }); + selectedThumbnailIndex++; } if (selected) { thumbnail.classList.add("focussed"); @@ -332,14 +342,83 @@ * @param index The index of the thumbnail to select. */ function selectThumbnail(index) { - if (index < 0 || index >= videoThumbnails.length) return; // Out of bounds check - if (selectedThumbnailIndex !== -1 && videoThumbnails[selectedThumbnailIndex]) { - videoThumbnails[selectedThumbnailIndex].classList.remove("focussed"); + if (index < 0 || index >= videoInfo.length) return; // Out of bounds check + if (selectedThumbnailIndex !== -1 && videoInfo[selectedThumbnailIndex]) { + videoInfo[selectedThumbnailIndex].thumbnail.classList.remove("focussed"); } selectedThumbnailIndex = index; - videoThumbnails[selectedThumbnailIndex].classList.add("focussed"); - // $("#video-container")[0].style.position = "relative"; - // $("#video-container")[0].style.left = (-index * 5) + "vw"; + videoInfo[selectedThumbnailIndex].thumbnail.classList.add("focussed"); + for (let i = 0; i < videoInfo.length; i++) { + if (i < selectedThumbnailIndex - 1) { + videoInfo[i].thumbnail.style.left = "-20%"; + } else if (i === selectedThumbnailIndex - 1) { + videoInfo[i].thumbnail.style.left = "15%"; + } else if (i === selectedThumbnailIndex) { + videoInfo[i].thumbnail.style.left = "50%"; + } else if (i === selectedThumbnailIndex + 1) { + videoInfo[i].thumbnail.style.left = "85%"; + } else { + videoInfo[i].thumbnail.style.left = "120%"; + } + } + } + + /** + * Starts the currently selected video. + */ + function startVideo() { + showSpinner(); + + let currentVideo = videoInfo[selectedThumbnailIndex].data + + // Clear previous handlers and set new ones for this specific load attempt + videoElement.oncanplaythrough = null; + videoElement.onerror = null; + + videoElement.oncanplaythrough = function() { + hideSpinner(); + videoElement.oncanplaythrough = null; // Clean up handler + videoElement.onerror = null; // Clean up handler + videoElement.play().catch(err => { + console.error("Error attempting to play video:", err); + exitVideoPlayback(); // Exit overlay on play error + }); + }; + + videoElement.onerror = function() { + console.error("Error loading video."); + hideSpinner(); + videoElement.oncanplaythrough = null; // Clean up handler + videoElement.onerror = null; // Clean up handler + exitVideoPlayback(); // Exit overlay on load error + }; + + videoElement.src = currentVideo.url; + videoElement.load(); + + // --- Setup Inactivity Controls (session-specific) --- + showControlsAndResetTimer(); // Initial call + + updatePlayPauseButtonState(); // Initial state for the button + + + // Show overlay and request fullscreen + overlayContainer.css('display', 'flex'); + const containerEl = overlayContainer[0]; + if (containerEl.requestFullscreen) { + containerEl.requestFullscreen().catch(err => console.error("Error attempting to enable full-screen mode:", err)); + } else if (containerEl.mozRequestFullScreen) { + containerEl.mozRequestFullScreen(); + } else if (containerEl.webkitRequestFullscreen) { + containerEl.webkitRequestFullscreen(); + } else if (containerEl.msRequestFullscreen) { + containerEl.msRequestFullscreen(); + } + // FOCUS: Set focus in the video overlay + if (playPauseButton && playPauseButton.length) { + playPauseButton.focus(); + } + updatePlayPauseButtonState() } $(document).ready(function() { @@ -358,9 +437,9 @@ $.getJSON("/api/homepage", function(data) { createVideoThumbnailElement(data.currentVideo, true, true); for (let i = 0; i < 10; i++) - { createVideoThumbnailElement(data.nextVideo, false, true); - } + for (let i = 0; i < 10; i++) + createVideoThumbnailElement(data.nextVideo, false, false); // currentVideo = data.currentVideo; // nextVideo = data.nextVideo; // $("#current-thumb").attr("src", currentVideo.thumbnail); @@ -369,6 +448,7 @@ hideSpinner(); showVideoContainer(); + selectThumbnail(selectedThumbnailIndex); }).fail(function(jqXHR, textStatus, errorThrown) { console.error("Failed to load homepage data:", textStatus, errorThrown); hideSpinner(); @@ -384,60 +464,6 @@ if (backButton) backButton.click(exitVideoPlayback); - $("#play-button").click(function() { - if (currentVideo && currentVideo.url && videoElement && overlayContainer) { - showSpinner(); - - // Clear previous handlers and set new ones for this specific load attempt - videoElement.oncanplaythrough = null; - videoElement.onerror = null; - - videoElement.oncanplaythrough = function() { - hideSpinner(); - videoElement.oncanplaythrough = null; // Clean up handler - videoElement.onerror = null; // Clean up handler - videoElement.play().catch(err => { - console.error("Error attempting to play video:", err); - exitVideoPlayback(); // Exit overlay on play error - }); - }; - - videoElement.onerror = function() { - console.error("Error loading video."); - hideSpinner(); - videoElement.oncanplaythrough = null; // Clean up handler - videoElement.onerror = null; // Clean up handler - exitVideoPlayback(); // Exit overlay on load error - }; - - videoElement.src = currentVideo.url; - videoElement.load(); - - // --- Setup Inactivity Controls (session-specific) --- - showControlsAndResetTimer(); // Initial call - - updatePlayPauseButtonState(); // Initial state for the button - - - // Show overlay and request fullscreen - overlayContainer.css('display', 'flex'); - const containerEl = overlayContainer[0]; - if (containerEl.requestFullscreen) { - containerEl.requestFullscreen().catch(err => console.error("Error attempting to enable full-screen mode:", err)); - } else if (containerEl.mozRequestFullScreen) { - containerEl.mozRequestFullScreen(); - } else if (containerEl.webkitRequestFullscreen) { - containerEl.webkitRequestFullscreen(); - } else if (containerEl.msRequestFullscreen) { - containerEl.msRequestFullscreen(); - } - // FOCUS: Set focus in the video overlay - if (playPauseButton && playPauseButton.length) { - playPauseButton.focus(); - } - } - }); - // --- Setup Custom Video Controls Events (session-specific for video element) --- $(videoElement).on('play.currentVideo', updatePlayPauseButtonState); $(videoElement).on('pause.currentVideo', updatePlayPauseButtonState); @@ -519,16 +545,14 @@ case 'ArrowRight': case 39: // ArrowRight - nextIndex = Math.min(selectedThumbnailIndex + 1, videoThumbnails.length - 1); + nextIndex = Math.min(selectedThumbnailIndex + 1, videoInfo.length - 1); selectThumbnail(nextIndex); keyHandled = true; break; case 'Enter': case 13: // Enter - if (currentIndex !== -1) { - activeFocusableSet[currentIndex].click(); - } + startVideo(); keyHandled = true; break;