diff --git a/static/index.html b/static/index.html index 96dc821..4ba1b43 100644 --- a/static/index.html +++ b/static/index.html @@ -38,7 +38,7 @@ 100% { transform: rotate(360deg); } } - .video-container { + #video-container { display: none; width: 100%; justify-content: center; @@ -51,20 +51,15 @@ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5); background-color: #444; aspect-ratio: 16/9; - object-fit: cover; - transition: transform 0.3s ease, box-shadow 0.3s ease; + width: 20vw; + transition: width 0.3s ease, box-shadow 0.3s ease; } - .video-thumbnail:focus { + .video-thumbnail.focussed { outline: 3px solid #557; /* Existing focus outline */ box-shadow: 0 0 400px -10px #446; /* Existing focus shadow */ - transform: scale(1.05); - z-index: 3; /* Ensure focused thumbnail is on top */ - } - - .current-video { width: 50vw; - z-index: 2; + z-index: 3; /* Ensure focused thumbnail is on top */ } .side-video { @@ -186,7 +181,7 @@ } function showVideoContainer() { - $(".video-container").css("display", "flex"); + $("#video-container").css("display", "flex"); } let currentVideo = null; @@ -235,7 +230,7 @@ } } // FOCUS: Return focus to the main view's play button - if ($(".video-container").is(":visible") && $('#play-button').length) { + if ($("#video-container").is(":visible") && $('#play-button').length) { $('#play-button').focus(); } } @@ -304,6 +299,49 @@ } } + let videoThumbnails = []; + let selectedThumbnailIndex = 0; + + /** + * Creates a new video thumbnail element. + * + * @param data The video data returned by the server. + * @param selected Set to true if this is the currently selected video thumbnail. + * @param append Set to true if this thumbnail should be appended to the video container, false if it should be prepended. + */ + function createVideoThumbnailElement(data, selected, append) { + let thumbnail = $(`Video Thumbnail`)[0]; + let index; + if (append) { + $("#video-container").append(thumbnail); + index = videoThumbnails.length; + videoThumbnails.push(thumbnail) + } else { + $("#video-container").prepend(thumbnail); + index = 0; + videoThumbnails.unshift(thumbnail); + } + if (selected) { + thumbnail.classList.add("focussed"); + selectedThumbnailIndex = index; + } + } + + /** + * Selects a video thumbnail by its index into the videoThumbnails array. + * @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"); + } + selectedThumbnailIndex = index; + videoThumbnails[selectedThumbnailIndex].classList.add("focussed"); + // $("#video-container")[0].style.position = "relative"; + // $("#video-container")[0].style.left = (-index * 5) + "vw"; + } + $(document).ready(function() { // Initialize global selectors for static elements overlayContainer = $("#video-overlay-container"); @@ -318,19 +356,19 @@ $(".video-thumbnail").attr("src", "data:image/svg+xml,%3Csvg xmlns=\\\'http://www.w3.org/2000/svg\\\' width=\\\'100%25\\\' height=\\\'100%25\\\' viewBox=\\\'0 0 16 9\\\'%3E%3C/svg%3E"); $.getJSON("/api/homepage", function(data) { - currentVideo = data.currentVideo; - nextVideo = data.nextVideo; - $("#current-thumb").attr("src", currentVideo.thumbnail); - $("#next-thumb").attr("src", nextVideo.thumbnail); + createVideoThumbnailElement(data.currentVideo, true, true); + for (let i = 0; i < 10; i++) + { + createVideoThumbnailElement(data.nextVideo, false, true); + } + // currentVideo = data.currentVideo; + // nextVideo = data.nextVideo; + // $("#current-thumb").attr("src", currentVideo.thumbnail); + // $("#next-thumb").attr("src", nextVideo.thumbnail); // Consider populating prev-thumb and next-thumb here if data provides them hideSpinner(); showVideoContainer(); - - // FOCUS: Set initial focus on the main screen - if ($(".video-container").is(":visible")) { - $('#current-thumb').focus(); - } }).fail(function(jqXHR, textStatus, errorThrown) { console.error("Failed to load homepage data:", textStatus, errorThrown); hideSpinner(); @@ -397,12 +435,6 @@ if (playPauseButton && playPauseButton.length) { playPauseButton.focus(); } - - // The oncanplaythrough is now set before load() - // videoElement.oncanplaythrough = function() { - // hideSpinner(); // Changed from hideLoader() - // videoElement.play().catch(err => console.error("Error attempting to play video:", err)); - // } } }); @@ -420,7 +452,6 @@ overlayContainer.on('mousemove.inactivityControls', showControlsAndResetTimer); // --- TV Remote/Keyboard Navigation --- - const mainViewFocusable = [$('#prev-thumb'), $('#current-thumb'), $('#next-thumb')].filter(el => el && el.length > 0); const getOverlayViewFocusableElements = () => [backButton, playPauseButton, seekBar].filter(el => el && el.length > 0 && el.is(':visible')); $(document).on('keydown', function(e) { @@ -429,19 +460,15 @@ if (isOverlayVisible) { activeFocusableSet = getOverlayViewFocusableElements(); - } else { - activeFocusableSet = mainViewFocusable; - } - if (!activeFocusableSet || activeFocusableSet.length === 0) return; + const focusedElement = $(document.activeElement); + let currentIndex = -1; - const focusedElement = $(document.activeElement); - let currentIndex = -1; - - for (let i = 0; i < activeFocusableSet.length; i++) { - if (focusedElement.is(activeFocusableSet[i])) { - currentIndex = i; - break; + for (let i = 0; i < activeFocusableSet.length; i++) { + if (focusedElement.is(activeFocusableSet[i])) { + currentIndex = i; + break; + } } } @@ -480,33 +507,20 @@ } } - // If focus is not on a managed element, and not body/html, usually let it be. - // However, for certain keys like Enter, we might want a default action. - if (currentIndex === -1 && !focusedElement.is('body') && !focusedElement.is('html')) { - return; - } - let keyHandled = false; + let nextIndex; switch (e.key || e.keyCode) { case 'ArrowLeft': case 37: // ArrowLeft - if (currentIndex !== -1) { - let nextIndex = (currentIndex - 1 + activeFocusableSet.length) % activeFocusableSet.length; - activeFocusableSet[nextIndex].focus(); - } else if (activeFocusableSet.length > 0) { // If nothing specific focused, focus last - $("#current-thumb").focus(); - } + nextIndex = Math.max(selectedThumbnailIndex - 1, 0); + selectThumbnail(nextIndex); keyHandled = true; break; case 'ArrowRight': case 39: // ArrowRight - if (currentIndex !== -1) { - let nextIndex = (currentIndex + 1) % activeFocusableSet.length; - activeFocusableSet[nextIndex].focus(); - } else if (activeFocusableSet.length > 0) { // If nothing specific focused, focus first - $("#current-thumb").focus(); - } + nextIndex = Math.min(selectedThumbnailIndex + 1, videoThumbnails.length - 1); + selectThumbnail(nextIndex); keyHandled = true; break; @@ -535,11 +549,11 @@
-
- Previous Video - Current Video - Next Video -
+
+ + + +