Refactor video thumbnail handling and improve overlay positioning for enhanced user experience

This commit is contained in:
Sebastiaan de Schaetzen 2025-06-17 16:00:10 +02:00
parent f226d1f402
commit f22ff5c1a4

View File

@ -52,7 +52,9 @@
background-color: #444; background-color: #444;
aspect-ratio: 16/9; aspect-ratio: 16/9;
width: 20vw; 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 { .video-thumbnail.focussed {
@ -104,6 +106,7 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block; display: block;
position: fixed;
} }
#video-overlay-container #back-button { /* Back button is now inside the container */ #video-overlay-container #back-button { /* Back button is now inside the container */
@ -299,7 +302,7 @@
} }
} }
let videoThumbnails = []; let videoInfo = [];
let selectedThumbnailIndex = 0; let selectedThumbnailIndex = 0;
/** /**
@ -314,12 +317,19 @@
let index; let index;
if (append) { if (append) {
$("#video-container").append(thumbnail); $("#video-container").append(thumbnail);
index = videoThumbnails.length; index = videoInfo.length;
videoThumbnails.push(thumbnail) videoInfo.push({
thumbnail,
data
})
} else { } else {
$("#video-container").prepend(thumbnail); $("#video-container").prepend(thumbnail);
index = 0; index = 0;
videoThumbnails.unshift(thumbnail); videoInfo.unshift({
thumbnail,
data
});
selectedThumbnailIndex++;
} }
if (selected) { if (selected) {
thumbnail.classList.add("focussed"); thumbnail.classList.add("focussed");
@ -332,62 +342,35 @@
* @param index The index of the thumbnail to select. * @param index The index of the thumbnail to select.
*/ */
function selectThumbnail(index) { function selectThumbnail(index) {
if (index < 0 || index >= videoThumbnails.length) return; // Out of bounds check if (index < 0 || index >= videoInfo.length) return; // Out of bounds check
if (selectedThumbnailIndex !== -1 && videoThumbnails[selectedThumbnailIndex]) { if (selectedThumbnailIndex !== -1 && videoInfo[selectedThumbnailIndex]) {
videoThumbnails[selectedThumbnailIndex].classList.remove("focussed"); videoInfo[selectedThumbnailIndex].thumbnail.classList.remove("focussed");
} }
selectedThumbnailIndex = index; selectedThumbnailIndex = index;
videoThumbnails[selectedThumbnailIndex].classList.add("focussed"); videoInfo[selectedThumbnailIndex].thumbnail.classList.add("focussed");
// $("#video-container")[0].style.position = "relative"; for (let i = 0; i < videoInfo.length; i++) {
// $("#video-container")[0].style.left = (-index * 5) + "vw"; 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%";
}
}
} }
$(document).ready(function() { /**
// Initialize global selectors for static elements * Starts the currently selected video.
overlayContainer = $("#video-overlay-container"); */
videoElement = overlayContainer.find(".video-player")[0]; function startVideo() {
backButton = overlayContainer.find("#back-button");
customControls = overlayContainer.find("#custom-video-controls");
playPauseButton = customControls.find("#custom-play-pause-button");
seekBar = customControls.find("#custom-seek-bar");
// Spinner is visible by default (CSS). Video container is hidden (CSS).
// Pre-set all thumbnails to a placeholder state
$(".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) {
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();
}).fail(function(jqXHR, textStatus, errorThrown) {
console.error("Failed to load homepage data:", textStatus, errorThrown);
hideSpinner();
// Display a user-friendly error message
if (!$('#init-error-msg').length) { // Prevent multiple error messages
$('body').append('<div id="init-error-msg" style="color:white; text-align:center; padding:20px; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); background-color:rgba(0,0,0,0.8); border-radius:8px; z-index: 10002;">Failed to load content. Please try again later.</div>');
}
});
// Attach event listeners that can be set up once for static controls
if (playPauseButton) playPauseButton.click(handlePlayPauseClick);
if (seekBar) seekBar.on('input', handleSeekBarInput);
if (backButton) backButton.click(exitVideoPlayback);
$("#play-button").click(function() {
if (currentVideo && currentVideo.url && videoElement && overlayContainer) {
showSpinner(); showSpinner();
let currentVideo = videoInfo[selectedThumbnailIndex].data
// Clear previous handlers and set new ones for this specific load attempt // Clear previous handlers and set new ones for this specific load attempt
videoElement.oncanplaythrough = null; videoElement.oncanplaythrough = null;
videoElement.onerror = null; videoElement.onerror = null;
@ -435,9 +418,52 @@
if (playPauseButton && playPauseButton.length) { if (playPauseButton && playPauseButton.length) {
playPauseButton.focus(); playPauseButton.focus();
} }
updatePlayPauseButtonState()
}
$(document).ready(function() {
// Initialize global selectors for static elements
overlayContainer = $("#video-overlay-container");
videoElement = overlayContainer.find(".video-player")[0];
backButton = overlayContainer.find("#back-button");
customControls = overlayContainer.find("#custom-video-controls");
playPauseButton = customControls.find("#custom-play-pause-button");
seekBar = customControls.find("#custom-seek-bar");
// Spinner is visible by default (CSS). Video container is hidden (CSS).
// Pre-set all thumbnails to a placeholder state
$(".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) {
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);
// $("#next-thumb").attr("src", nextVideo.thumbnail);
// Consider populating prev-thumb and next-thumb here if data provides them
hideSpinner();
showVideoContainer();
selectThumbnail(selectedThumbnailIndex);
}).fail(function(jqXHR, textStatus, errorThrown) {
console.error("Failed to load homepage data:", textStatus, errorThrown);
hideSpinner();
// Display a user-friendly error message
if (!$('#init-error-msg').length) { // Prevent multiple error messages
$('body').append('<div id="init-error-msg" style="color:white; text-align:center; padding:20px; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); background-color:rgba(0,0,0,0.8); border-radius:8px; z-index: 10002;">Failed to load content. Please try again later.</div>');
} }
}); });
// Attach event listeners that can be set up once for static controls
if (playPauseButton) playPauseButton.click(handlePlayPauseClick);
if (seekBar) seekBar.on('input', handleSeekBarInput);
if (backButton) backButton.click(exitVideoPlayback);
// --- Setup Custom Video Controls Events (session-specific for video element) --- // --- Setup Custom Video Controls Events (session-specific for video element) ---
$(videoElement).on('play.currentVideo', updatePlayPauseButtonState); $(videoElement).on('play.currentVideo', updatePlayPauseButtonState);
$(videoElement).on('pause.currentVideo', updatePlayPauseButtonState); $(videoElement).on('pause.currentVideo', updatePlayPauseButtonState);
@ -519,16 +545,14 @@
case 'ArrowRight': case 'ArrowRight':
case 39: // ArrowRight case 39: // ArrowRight
nextIndex = Math.min(selectedThumbnailIndex + 1, videoThumbnails.length - 1); nextIndex = Math.min(selectedThumbnailIndex + 1, videoInfo.length - 1);
selectThumbnail(nextIndex); selectThumbnail(nextIndex);
keyHandled = true; keyHandled = true;
break; break;
case 'Enter': case 'Enter':
case 13: // Enter case 13: // Enter
if (currentIndex !== -1) { startVideo();
activeFocusableSet[currentIndex].click();
}
keyHandled = true; keyHandled = true;
break; break;