del old files

This commit is contained in:
MLH
2024-12-27 00:33:57 +01:00
parent 8018010aae
commit 7b2f5acb21
4 changed files with 483 additions and 1988 deletions

View File

@@ -1,689 +0,0 @@
let title = 'Spotlight'; // Title of the slideshow TBD
let listFileName = 'list.txt'; // Name of the file containing the list of movie IDs
let token = 'YOURAPIKEYHERE'; // Your Jellyfin API key
let moviesSeriesBoth = 3; // 1 for movies, 2 for series, 3 for both
let shuffleInterval = 15000; // Time in milliseconds before the next slide is shown, unless trailer is playing
let useTrailers = true; // Set to false to disable trailers
let setRandomMovie = true; // Set to false to disable random movie selection from the list
let showOnOtherPages = false; // Set to true to show the slideshow on all pages eg. favorites tab, requests tab, etc.
//let showTitle = false; // Set to false to hide the title TBD
let disableTrailerControls = true; // Set to false to enable trailer controls
let setMuted = true; // Set to false to disable unmuting the video on hover
let umuteOnHover = true; // Set to false to disable unmuting the video on hover
let unmutedVolume = 20; // Set the volume level when the video is unmuted
let useSponsorBlock = true; // Set to true to use SponsorBlock data to skip intro/outro segments of trailers
let plotMaxLength = 550; // Maximum number of characters in the plot
let trailerMaxLength = 0; // Default value 0; length measured in ms, set to 0 to disable, could be used instead of SponsorBlock
let isMuted = true; // Default value true; set to false to start the video unmuted
// variables
let isChangingSlide = false, player = null, slideChangeTimeout = null, isHomePageActive = false;
let currentLocation = window.top.location.href;
let movieList = [], currentMovieIndex = 0;
let previousMovies = [];
let forwardMovies = [];
if (setMuted) {
const slidesContainer = document.getElementById('slides-container');
slidesContainer.addEventListener('mouseenter', () => {
if (player) {
player.unMute();
isMuted = false;
}
});
slidesContainer.addEventListener('mouseleave', () => {
if (player) {
player.mute();
isMuted = true;
}
});
}
// Get SponsorBlock-Data for the outro segment of the trailer
//function fetchSponsorBlockOutro(videoId) {
// @deprecated
const fetchSponsorBlockOutroOLD = (videoId) => {
return fetch(`https://sponsor.ajay.app/api/skipSegments?videoID=${videoId}&category=outro`)
.then(response => response.json())
.then(segments => {
return segments.length > 0 ? segments[0].segment : null;
})
.catch(error => {
console.error('Error fetching SponsorBlock data:', error);
return null;
});
};
const fetchSponsorBlockOutro = async (videoId) => {
try {
const response = await fetch(`https://sponsor.ajay.app/api/skipSegments?videoID=${videoId}&category=outro`);
const segments = await response.json();
if (segments.length > 0 && Array.isArray(segments[0].segment)) {
return segments[0].segment; // returns array: [start, end]
}
return null;
} catch (error) {
console.error('Error fetching SponsorBlock data:', error);
return null;
}
};
// Monitor the video player for the outro segment
let monitorOutroInterval = null; // Global interval variable
function monitorOutro(player, outroSegment) {
if (monitorOutroInterval) { // Clear the interval if it's already running
clearInterval(monitorOutroInterval);
}
monitorOutroInterval = setInterval(() => {
if (!outroSegment || !player) {
console.log('Invalid outro segment or player not initialized');
clearInterval(monitorOutroInterval);
return;
}
const currentTime = player.getCurrentTime();
if (currentTime >= outroSegment[0] && currentTime < outroSegment[1]) {
clearInterval(monitorOutroInterval);
player.stopVideo(); // stop video
setTimeout(fetchRandomMovie, 100); // fetch next movie
}
}, 500); // check every 500ms
}
const createElem = (tag, className, textContent, src, alt) => {
const elem = document.createElement(tag);
if (className) elem.className = className;
if (textContent) elem.textContent = textContent;
if (src) elem.src = src;
if (alt) elem.alt = alt;
return elem;
};
// Check for screen size below 1000px
function isMobile() {
return window.innerWidth <= 1000;
}
const truncateText = (text, maxLength) => text.length > maxLength ? text.substr(0, maxLength) + '...' : text;
const cleanup = () => {
if (player && typeof player.destroy === 'function') {
player.destroy();
}
player = null;
clearTimeout(slideChangeTimeout);
slideChangeTimeout = null;
const container = document.getElementById('slides-container');
if (container) container.innerHTML = '';
};
const createSlideElement = (movie, hasVideo = false) => {
cleanup();
const container = document.getElementById('slides-container');
const slide = createElem('div', 'slide');
if (movie && (!previousMovies.length || previousMovies[previousMovies.length - 1].Id !== movie.Id)) {
previousMovies.push(movie);
}
if (previousMovies.length > 50) {
previousMovies.shift();
}
['backdrop', 'logo'].forEach(type => slide.appendChild(createElem('img', type, null, `/Items/${movie.Id}/Images/${type.charAt(0).toUpperCase() + type.slice(1)}${type === 'backdrop' ? '/0' : ''}`, type)));
slide.appendChild(createElem('div', 'heading', title));
const textContainer = createElem('div', 'text-container');
const premiereYear = movie.PremiereDate ? new Date(movie.PremiereDate).getFullYear() : 'Unknown';
let additionalInfo;
if (movie.Type === 'Series') {
additionalInfo = movie.ChildCount
? `${movie.ChildCount} Season${movie.ChildCount > 1 ? 's' : ''}`
: 'Unknown Seasons';
} else if (movie.Type === 'BoxSet') {
additionalInfo = movie.ChildCount
? `${movie.ChildCount} Movie${movie.ChildCount > 1 ? 's' : ''}`
: 'Unknown Movies';
} else {
additionalInfo = movie.RunTimeTicks
? `${Math.round(movie.RunTimeTicks / 600000000)} min`
: 'Unknown Runtime';
}
let loremText = `
<span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;">${additionalInfo}</span>
<span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;">${premiereYear}</span> `;
if (movie.CommunityRating) {
loremText += `<span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;">
<i class="star-icon fas fa-star"></i> ${movie.CommunityRating.toFixed(1)}
</span> `;
}
if (movie.CriticRating) {
loremText += `<span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;">
<img src="https://i.imgur.com/aoLXyXx.png" alt="Rotten Tomatoes" style="width: 1.05em; height: 1.25em; font-size: 0.83em; padding-right: 0.4em; margin-left: -0.1em; vertical-align: middle; padding-bottom: 0.3em;">
${movie.CriticRating}%</span>`;
}
// Age Rating
const ageRating = movie.OfficialRating ? movie.OfficialRating : 'NR';
const ratingClass = ageRating.toLowerCase().replace(/ /g, '-');
const ageRatingDiv = createElem('div', 'age-rating');
const ageRatingSpan = createElem('span', ratingClass, ageRating);
ageRatingSpan.style.cssText = 'border: 0.09em solid currentColor; border-radius: .1em; padding: 0.2em; padding-top: 0.125em; padding-bottom: 0.26em; display: inline-block; text-align: center; line-height: 0.8em;';
ageRatingDiv.appendChild(ageRatingSpan);
slide.appendChild(ageRatingDiv);
// Genres Section
const genresDiv = createElem('div', 'genres');
if (movie.Genres && movie.Genres.length > 0) {
movie.Genres.forEach((genre, index) => {
const genreElem = createElem('span', 'genre-item');
genreElem.textContent = genre;
genreElem.style.backgroundColor = 'transparent';
genreElem.style.paddingLeft = '0.5em';
genreElem.style.paddingRight = '0.5em';
genreElem.style.paddingTop = '0.1em';
genreElem.style.paddingBottom = '0.1em';
genreElem.style.color = 'white';
genreElem.style.borderRadius = '0em';
genreElem.style.marginRight = '0em';
genresDiv.appendChild(genreElem);
if (index < movie.Genres.length - 1) {
const separator = createElem('span', 'material-symbols-outlined');
separator.textContent = 'stat_0'; // The separator symbol
genresDiv.appendChild(separator);
}
});
} else {
genresDiv.textContent = 'Genres: N/A';
}
slide.appendChild(genresDiv);
const loremDiv = createElem('div', 'lorem-ipsum');
loremDiv.innerHTML = loremText;
textContainer.appendChild(loremDiv);
textContainer.appendChild(createElem('div', 'plot', truncateText(movie.Overview, plotMaxLength)));
slide.appendChild(textContainer);
const backButton = createElem('div', 'back-button');
const backIcon = createElem('i', 'material-icons');
backIcon.textContent = 'chevron_left';
backButton.appendChild(backIcon);
backButton.onclick = (e) => {
e.stopPropagation();
navigateBack();
};
// Skip button logic
const skipButton = createElem('div', 'skip-button');
const skipIcon = createElem('i', 'material-icons');
skipIcon.textContent = 'chevron_right';
skipButton.appendChild(skipIcon);
skipButton.onclick = (e) => {
e.stopPropagation();
navigateForward();
};
slide.appendChild(backButton);
slide.appendChild(skipButton);
// Create Details buttons
const buttonsContainer = createElem('div', 'buttons-container');
// Details Button
const detailsButton = createElem('button', 'details-button');
const playIcon = createElem('i', 'fas fa-play');
detailsButton.appendChild(playIcon);
detailsButton.appendChild(document.createTextNode(' Play'));
detailsButton.onclick = (e) => {
e.stopPropagation();
window.top.location.href = `/#!/details?id=${movie.Id}`; // Navigate to details page
};
// Append buttons to the container
buttonsContainer.appendChild(detailsButton);
slide.appendChild(buttonsContainer);
const overlay = createElem('div', 'clickable-overlay');
overlay.onclick = () => window.top.location.href = `/#!/details?id=${movie.Id}`;
slide.appendChild(overlay);
if (hasVideo && movie.RemoteTrailers && movie.RemoteTrailers.length > 0) {
const trailerUrl = movie.RemoteTrailers[0].Url;
const watchTrailerButton = createElem('button', 'watch-trailer-button');
const trailerIcon = document.createElement('i');
trailerIcon.className = 'fas fa-film';
watchTrailerButton.appendChild(trailerIcon);
watchTrailerButton.appendChild(document.createTextNode('Trailer'));
watchTrailerButton.onclick = (e) => {
e.stopPropagation();
if (isMobile()) {
// Show the video in an overlay for mobile
showVideoOverlay(trailerUrl);
} else {
// Open the trailer in a new tab for desktop
window.open(trailerUrl, '_blank');
}
};
buttonsContainer.appendChild(watchTrailerButton);
}
if (useTrailers && hasVideo && movie.RemoteTrailers?.length > 0) {
const videoId = new URL(movie.RemoteTrailers[0].Url).searchParams.get('v');
const videoContainer = createElem('div', 'video-container');
const videoElement = createElem('div', 'video-player');
videoContainer.appendChild(videoElement);
slide.appendChild(videoContainer);
player = new YT.Player(videoElement, {
height: '100%',
width: '100%',
videoId,
playerVars: {
mute: isMuted ? 1 : 0, // CHeck if the video should start muted
controls: disableTrailerControls ? 0 : 1, // Hide the controls
disablekb: 1, // Disable keyboard controls
fs: 1, // Enavle fullscreen
iv_load_policy: 3, // Disable annotations
},
events: {
'onReady': event => {
if (useSponsorBlock) {
fetchSponsorBlockOutro(videoId).then(outroSegment => {
if (outroSegment) {
console.log(`SponsorBlock outro segment: Start - ${outroSegment[0]}s, End - ${outroSegment[1]}s`);
monitorOutro(player, outroSegment);
} else {
console.log('No outro segment found/provided');
}
}).catch(error => {
console.error('Error reading SponsorBlock outro segment:', error);
});
}
if (trailerMaxLength > 0) {
clearTimeout(slideChangeTimeout);
slideChangeTimeout = setTimeout(() => {
if (player) {
player.stopVideo();
player.destroy();
player = null;
}
fetchRandomMovie();
}, trailerMaxLength);
}
if (isMuted) {
event.target.setVolume(0); // Mute the video if the setting is MuteOn
} else {
event.target.setVolume(unmutedVolume); // Set the volume, value between 0 and 100
}
event.target.playVideo();
},
'onStateChange': event => {
if (event.data === YT.PlayerState.PLAYING) {
// Only show when YT video is successfully playing
const backdrop = document.querySelector('.backdrop');
if (backdrop) {
backdrop.style.width = 'calc(100% - 23vw)';
backdrop.style.left = '0vw';
}
const plot = document.querySelector('.plot');
if (plot) {
plot.style.left = '33vw';
plot.style.maxWidth = '63vw';
}
const genres = document.querySelector('.genres');
if (genres) {
genres.style.left = 'calc(50% - 17vw)';
}
const loremIpsum = document.querySelector('.lorem-ipsum');
if (loremIpsum) loremIpsum.style.left = 'calc(50% - 17vw)';
const logo = document.querySelector('.logo');
if (logo) logo.style.left = 'calc(50% - 17vw)';
videoContainer.style.width = '34.4vw';
} else if (event.data === YT.PlayerState.ENDED) {
setTimeout(fetchRandomMovie, 100);
}
},
'onError': () => {
console.error(`YouTube prevented playback of '${movie.Name}'`);
if (player) {
clearInterval(monitorOutroInterval);
player.destroy();
player = null;
}
// Reset style when a YT error occurs
const backdrop = document.querySelector('.backdrop');
if (backdrop) backdrop.style.width = '100%';
const plot = document.querySelector('.plot');
if (plot) plot.style.width = '98%';
const loremIpsum = document.querySelector('.lorem-ipsum');
if (loremIpsum) loremIpsum.style.paddingRight = '0';
const logo = document.querySelector('.logo');
if (logo) logo.style.left = '50%';
videoContainer.style.width = '0';
startSlideChangeTimer();
}
}
});
} else {
startSlideChangeTimer();
}
container.innerHTML = '';
container.appendChild(slide);
};
function addSwipeListeners(slide) {
let startX, startY, distX, distY;
const threshold = 50;
const restraint = 100;
slide.addEventListener('touchstart', e => {
const touch = e.touches[0];
startX = touch.clientX;
startY = touch.clientY;
});
slide.addEventListener('touchmove', e => {
const touch = e.touches[0];
distX = touch.clientX - startX;
distY = touch.clientY - startY;
});
slide.addEventListener('touchend', () => {
if (Math.abs(distX) > threshold && Math.abs(distY) < restraint) {
if (distX > 0) {
console.log('Swipe Right');
} else {
console.log('Swipe Left');
fetchRandomMovie();
}
}
distX = distY = 0;
});
}
const navigateBack = () => {
if (previousMovies.length < 2) {
console.log("No previous slides in history.");
return;
}
const currentMovie = previousMovies.pop();
forwardMovies.unshift(currentMovie);
const previousMovie = previousMovies[previousMovies.length - 1];
createSlideElement(previousMovie, true);
};
const navigateForward = () => {
if (forwardMovies.length === 0) {
console.log("No forward slides in history.");
fetchRandomMovie();
return;
}
const currentMovie = forwardMovies.shift();
previousMovies.push(currentMovie);
createSlideElement(currentMovie, true);
};
// Show the video overlay
function showVideoOverlay(trailerUrl) {
const videoOverlay = document.getElementById('video-overlay');
const videoFrame = document.getElementById('trailer-video');
const closeOverlay = document.getElementById('close-overlay');
// Extract video ID from trailer URL
const videoId = new URL(trailerUrl).searchParams.get('v');
const embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
// Set iframe's source to trailer URL
videoFrame.src = embedUrl;
// Show the overlay
videoOverlay.style.display = 'block';
// Pause the slide timer when the video overlay is open
clearSlideChangeTimeout();
// Close the overlay when the X is clicked
closeOverlay.onclick = () => {
videoOverlay.style.display = 'none';
videoFrame.src = ''; // Stop the video
};
// Close the overlay when clicking outside content
window.onclick = (event) => {
if (event.target === videoOverlay) {
videoOverlay.style.display = 'none';
videoFrame.src = '';
}
};
}
// Close video overlay and restart slide timer
function closeVideoOverlay() {
const videoOverlay = document.getElementById('video-overlay');
const videoFrame = document.getElementById('trailer-video');
// Hide overlay
videoOverlay.style.display = 'none';
// Reset the iframe source
videoFrame.src = '';
// Restart slide change timer when video overlay is closed
startSlideChangeTimer();
}
function clearSlideChangeTimeout() {
if (slideChangeTimeout) {
clearTimeout(slideChangeTimeout);
slideChangeTimeout = null;
}
}
const startSlideChangeTimer = () => { clearTimeout(slideChangeTimeout); slideChangeTimeout = setTimeout(fetchRandomMovie, shuffleInterval); };
const checkBackdropAndLogo = movie => {
Promise.all(['/Images/Backdrop/0', '/Images/Logo'].map(url =>
fetch(`/Items/${movie.Id}${url}`, { method: 'HEAD' }).then(response => response.ok)
)).then(([backdropExists, logoExists]) =>
backdropExists && logoExists ? createSlideElement(movie, true) : fetchRandomMovie()
).catch(() => fetchRandomMovie());
};
const readCustomList = () =>
fetch(listFileName + '?' + new Date().getTime())
.then(response => response.ok ? response.text() : null)
.then(text => {
if (!text || !text.trim()) {
console.warn('List.txt is empty or could not be loaded.');
return null; // Fallback to random selection
}
const lines = text.split('\n').filter(Boolean);
const firstLine = lines.shift().trim();
const [parsedTitle, muteSetting] = firstLine.split(/\s+/);
title = parsedTitle || title;
// Check for mute
// MARK: set mute
isMuted = muteSetting === "MuteOn";
// Remaining lines are media IDs
const mediaList = lines.map(line => line.trim().substring(0, 32));
if (setRandomMovie) {
return shuffleArray(mediaList); // Shuffle the list before returning it if set
}
return mediaList; // return exact list
})
.catch(() => {
console.error('Error reading List.txt. Falling back to random selection.');
return null;
});
const fetchRandomMovie = () => {
if (isChangingSlide) return;
isChangingSlide = true;
if (movieList.length === 0) {
readCustomList().then(list => {
if (list && list.length > 0) {
movieList = list;
currentMovieIndex = 0;
fetchNextMovie();
} else {
console.warn("Fallback to random selection.");
fetchNextMovie(true);
}
});
} else {
fetchNextMovie();
}
};
const shuffleArray = (array) => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
};
const fetchNextMovie = (useRandom = false) => {
const fetchCurrentUserId = () =>
fetch('/Sessions', { headers: { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` } })
.then(response => response.json())
.then(sessions => {
const currentSession = sessions.find(session => session.UserId);
return currentSession ? currentSession.UserId : null;
})
.catch(() => null);
fetchCurrentUserId().then(currentUserId => {
if (!currentUserId) {
console.error('Could not retrieve the current user ID.');
isChangingSlide = false;
return;
}
const headers = { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` };
if (!useRandom && movieList.length > 0) {
if (currentMovieIndex >= movieList.length) currentMovieIndex = 0;
const movieId = movieList[currentMovieIndex];
currentMovieIndex++;
fetch(`/Users/${currentUserId}/Items/${movieId}?Fields=Overview,RemoteTrailers,PremiereDate,RunTimeTicks,ChildCount,Genres`, { headers })
.then(response => response.json())
.then(checkBackdropAndLogo)
.catch(() => startSlideChangeTimer())
.finally(() => { isChangingSlide = false; });
} else {
const itemTypes = moviesSeriesBoth === 1 ? 'Movie' : (moviesSeriesBoth === 2 ? 'Series' : 'Movie,Series');
fetch(`/Users/${currentUserId}/Items?IncludeItemTypes=${itemTypes}&Recursive=true&Limit=1&SortBy=random&Fields=Id,Overview,RemoteTrailers,PremiereDate,RunTimeTicks,ChildCount,Genres`, { headers })
.then(response => response.json())
.then(data => { if (data.Items[0]) checkBackdropAndLogo(data.Items[0]); })
.catch(() => startSlideChangeTimer())
.finally(() => { isChangingSlide = false; });
}
});
};
const checkNavigation = () => {
const newLocation = window.top.location.href;
if (newLocation !== currentLocation) {
currentLocation = newLocation;
const isHomePage = url => url.includes('/home') || url.endsWith('/web/') || url.endsWith('/web/index.html');
if (!isHomePage(newLocation) && isHomePageActive) {
console.log("Leaving homepage, cleaning up slideshow and stopping video");
isHomePageActive = false;
stopBackgroundVideo();
cleanup();
}
if (isHomePage(newLocation) && !isHomePageActive) {
console.log("Returning to homepage, reactivating slideshow");
isHomePageActive = true;
fetchRandomMovie();
}
}
// Check if parent is available and if the iframe is in an embedded environment
if (!showOnOtherPages && window.parent && window.parent !== window) {
const homeTab = window.parent.document.getElementById('homeTab');
const isHomeTabActive = homeTab && homeTab.classList.contains('is-active');
// Check if the user is switching tabs while on the homepage to eg. favorites or requests, if so, stop the slideshow
if (isHomeTabActive && !isHomePageActive) {
console.log("HomeTab is active, reactivating slideshow");
isHomePageActive = true;
window.parent.document.querySelector('.featurediframe').style.display = 'block';
cleanup();
fetchRandomMovie();
} else if (!isHomeTabActive && isHomePageActive) {
console.log("Leaving HomeTab, cleaning up slideshow");
isHomePageActive = false;
window.parent.document.querySelector('.featurediframe').style.display = 'none';
cleanup();
}
} else {
console.error("Spotlight iframe is not in an embedded environment, has a different domain or showOnOtherPages is set to true");
}
};
const stopBackgroundVideo = () => {
if (player && typeof player.stopVideo === 'function') {
player.stopVideo();
player.destroy();
}
player = null;
};
setInterval(checkNavigation, 60);
document.addEventListener('DOMContentLoaded', () => {
if (window.innerWidth < 1001) useTrailers = false;
const isHomePage = url => url.includes('/home') || url.endsWith('/web/') || url.endsWith('/web/index.html');
if (isHomePage(window.top.location.href)) {
isHomePageActive = true;
readCustomList().then(list => {
if (list) { movieList = list; currentMovieIndex = 0; }
fetchRandomMovie();
});
}
});
window.addEventListener('unload', cleanup);
window.addEventListener('popstate', checkNavigation);

341
script.js
View File

@@ -1,4 +1,4 @@
let title = 'Spotlight'; // Title of the slideshow let title = 'Spotlight'; // Title of the slideshow TBD
let listFileName = 'list.txt'; // Name of the file containing the list of movie IDs let listFileName = 'list.txt'; // Name of the file containing the list of movie IDs
let token = 'YOURAPIKEYHERE'; // Your Jellyfin API key let token = 'YOURAPIKEYHERE'; // Your Jellyfin API key
let moviesSeriesBoth = 3; // 1 for movies, 2 for series, 3 for both let moviesSeriesBoth = 3; // 1 for movies, 2 for series, 3 for both
@@ -6,12 +6,94 @@ let shuffleInterval = 15000; // Time in milliseconds before the next slide is sh
let useTrailers = true; // Set to false to disable trailers let useTrailers = true; // Set to false to disable trailers
let setRandomMovie = true; // Set to false to disable random movie selection from the list let setRandomMovie = true; // Set to false to disable random movie selection from the list
let showOnOtherPages = false; // Set to true to show the slideshow on all pages eg. favorites tab, requests tab, etc. let showOnOtherPages = false; // Set to true to show the slideshow on all pages eg. favorites tab, requests tab, etc.
let showTitle = false; // Set to false to hide the title //let showTitle = false; // Set to false to hide the title TBD
let disableTrailerControls = true; // Set to false to enable trailer controls
let setMuted = true; // Set to false to disable unmuting the video on hover
let umuteOnHover = true; // Set to false to disable unmuting the video on hover
let unmutedVolume = 20; // Set the volume level when the video is unmuted
let useSponsorBlock = true; // Set to true to use SponsorBlock data to skip intro/outro segments of trailers
let plotMaxLength = 550; // Maximum number of characters in the plot let plotMaxLength = 550; // Maximum number of characters in the plot
let trailerMaxLength = 0; // Default value 0; length measured in ms, set to 0 to disable, could be used instead of SponsorBlock
let isMuted = true; // Default value true; set to false to start the video unmuted
// variables
let isChangingSlide = false, player = null, slideChangeTimeout = null, isHomePageActive = false; let isChangingSlide = false, player = null, slideChangeTimeout = null, isHomePageActive = false;
let currentLocation = window.top.location.href; let currentLocation = window.top.location.href;
let movieList = [], currentMovieIndex = 0; let movieList = [], currentMovieIndex = 0;
let previousMovies = [];
let forwardMovies = [];
if (setMuted) {
const slidesContainer = document.getElementById('slides-container');
slidesContainer.addEventListener('mouseenter', () => {
if (player) {
player.unMute();
isMuted = false;
}
});
slidesContainer.addEventListener('mouseleave', () => {
if (player) {
player.mute();
isMuted = true;
}
});
}
// Get SponsorBlock-Data for the outro segment of the trailer
//function fetchSponsorBlockOutro(videoId) {
// @deprecated
const fetchSponsorBlockOutroOLD = (videoId) => {
return fetch(`https://sponsor.ajay.app/api/skipSegments?videoID=${videoId}&category=outro`)
.then(response => response.json())
.then(segments => {
return segments.length > 0 ? segments[0].segment : null;
})
.catch(error => {
console.error('Error fetching SponsorBlock data:', error);
return null;
});
};
const fetchSponsorBlockOutro = async (videoId) => {
try {
const response = await fetch(`https://sponsor.ajay.app/api/skipSegments?videoID=${videoId}&category=outro`);
const segments = await response.json();
if (segments.length > 0 && Array.isArray(segments[0].segment)) {
return segments[0].segment; // returns array: [start, end]
}
return null;
} catch (error) {
console.error('Error fetching SponsorBlock data:', error);
return null;
}
};
// Monitor the video player for the outro segment
let monitorOutroInterval = null; // Global interval variable
function monitorOutro(player, outroSegment) {
if (monitorOutroInterval) { // Clear the interval if it's already running
clearInterval(monitorOutroInterval);
}
monitorOutroInterval = setInterval(() => {
if (!outroSegment || !player) {
console.log('Invalid outro segment or player not initialized');
clearInterval(monitorOutroInterval);
return;
}
const currentTime = player.getCurrentTime();
if (currentTime >= outroSegment[0] && currentTime < outroSegment[1]) {
clearInterval(monitorOutroInterval);
player.stopVideo(); // stop video
setTimeout(fetchRandomMovie, 100); // fetch next movie
}
}, 500); // check every 500ms
}
const createElem = (tag, className, textContent, src, alt) => { const createElem = (tag, className, textContent, src, alt) => {
const elem = document.createElement(tag); const elem = document.createElement(tag);
@@ -30,8 +112,12 @@ function isMobile() {
const truncateText = (text, maxLength) => text.length > maxLength ? text.substr(0, maxLength) + '...' : text; const truncateText = (text, maxLength) => text.length > maxLength ? text.substr(0, maxLength) + '...' : text;
const cleanup = () => { const cleanup = () => {
if (player) { player.destroy(); player = null; } if (player && typeof player.destroy === 'function') {
player.destroy();
}
player = null;
clearTimeout(slideChangeTimeout); clearTimeout(slideChangeTimeout);
slideChangeTimeout = null;
const container = document.getElementById('slides-container'); const container = document.getElementById('slides-container');
if (container) container.innerHTML = ''; if (container) container.innerHTML = '';
}; };
@@ -40,14 +126,35 @@ const createSlideElement = (movie, hasVideo = false) => {
cleanup(); cleanup();
const container = document.getElementById('slides-container'); const container = document.getElementById('slides-container');
const slide = createElem('div', 'slide'); const slide = createElem('div', 'slide');
if (movie && (!previousMovies.length || previousMovies[previousMovies.length - 1].Id !== movie.Id)) {
previousMovies.push(movie);
}
if (previousMovies.length > 50) {
previousMovies.shift();
}
['backdrop', 'logo'].forEach(type => slide.appendChild(createElem('img', type, null, `/Items/${movie.Id}/Images/${type.charAt(0).toUpperCase() + type.slice(1)}${type === 'backdrop' ? '/0' : ''}`, type))); ['backdrop', 'logo'].forEach(type => slide.appendChild(createElem('img', type, null, `/Items/${movie.Id}/Images/${type.charAt(0).toUpperCase() + type.slice(1)}${type === 'backdrop' ? '/0' : ''}`, type)));
slide.appendChild(createElem('div', 'heading', title)); slide.appendChild(createElem('div', 'heading', title));
const textContainer = createElem('div', 'text-container'); const textContainer = createElem('div', 'text-container');
const premiereYear = movie.PremiereDate ? new Date(movie.PremiereDate).getFullYear() : 'Unknown'; const premiereYear = movie.PremiereDate ? new Date(movie.PremiereDate).getFullYear() : 'Unknown';
const additionalInfo = movie.Type === 'Series' ?
(movie.ChildCount ? `${movie.ChildCount} Season${movie.ChildCount > 1 ? 's' : ''}` : 'Unknown Seasons') : let additionalInfo;
(movie.RunTimeTicks ? `${Math.round(movie.RunTimeTicks / 600000000)} min` : 'Unknown Runtime');
if (movie.Type === 'Series') {
additionalInfo = movie.ChildCount
? `${movie.ChildCount} Season${movie.ChildCount > 1 ? 's' : ''}`
: 'Unknown Seasons';
} else if (movie.Type === 'BoxSet') {
additionalInfo = movie.ChildCount
? `${movie.ChildCount} Movie${movie.ChildCount > 1 ? 's' : ''}`
: 'Unknown Movies';
} else {
additionalInfo = movie.RunTimeTicks
? `${Math.round(movie.RunTimeTicks / 600000000)} min`
: 'Unknown Runtime';
}
let loremText = ` let loremText = `
<span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;">${additionalInfo}</span> <span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;">${additionalInfo}</span>
@@ -60,7 +167,7 @@ const createSlideElement = (movie, hasVideo = false) => {
} }
if (movie.CriticRating) { if (movie.CriticRating) {
loremText += `<span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;"> loremText += `<span style="background: transparent; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.05em; padding-bottom: 0.05em; margin-left: 1em;">
<img src="https://i.imgur.com/rMvyQMt.png" alt="Rotten Tomatoes" style="width: 1.05em; height: 1.25em; font-size: 0.9em; padding-right: 0.1em; margin-left: -0.1em; vertical-align: bottom;"> <img src="https://i.imgur.com/aoLXyXx.png" alt="Rotten Tomatoes" style="width: 1.05em; height: 1.25em; font-size: 0.83em; padding-right: 0.4em; margin-left: -0.1em; vertical-align: middle; padding-bottom: 0.3em;">
${movie.CriticRating}%</span>`; ${movie.CriticRating}%</span>`;
} }
@@ -111,15 +218,22 @@ const createSlideElement = (movie, hasVideo = false) => {
const backButton = createElem('div', 'back-button'); const backButton = createElem('div', 'back-button');
const backIcon = createElem('i', 'material-icons'); const backIcon = createElem('i', 'material-icons');
backIcon.textContent = 'chevron_left'; backIcon.textContent = 'chevron_left';
backButton.appendChild(backIcon);
backButton.onclick = (e) => {
e.stopPropagation();
navigateBack();
};
// Skip button logic
const skipButton = createElem('div', 'skip-button'); const skipButton = createElem('div', 'skip-button');
const skipIcon = createElem('i', 'material-icons'); const skipIcon = createElem('i', 'material-icons');
skipIcon.textContent = 'chevron_right'; skipIcon.textContent = 'chevron_right';
backButton.appendChild(backIcon);
skipButton.appendChild(skipIcon); skipButton.appendChild(skipIcon);
skipButton.onclick = (e) => {
e.stopPropagation();
navigateForward();
};
skipIcon.onclick = (e) => { e.stopPropagation(); fetchRandomMovie(); };
backIcon.onclick = (e) => { e.stopPropagation(); previousMovie(); };
slide.appendChild(backButton); slide.appendChild(backButton);
slide.appendChild(skipButton); slide.appendChild(skipButton);
@@ -178,10 +292,42 @@ const createSlideElement = (movie, hasVideo = false) => {
width: '100%', width: '100%',
videoId, videoId,
playerVars: { playerVars: {
mute: 1 // Start the video muted mute: isMuted ? 1 : 0, // CHeck if the video should start muted
controls: disableTrailerControls ? 0 : 1, // Hide the controls
disablekb: 1, // Disable keyboard controls
fs: 1, // Enavle fullscreen
iv_load_policy: 3, // Disable annotations
}, },
events: { events: {
'onReady': event => { 'onReady': event => {
if (useSponsorBlock) {
fetchSponsorBlockOutro(videoId).then(outroSegment => {
if (outroSegment) {
console.log(`SponsorBlock outro segment: Start - ${outroSegment[0]}s, End - ${outroSegment[1]}s`);
monitorOutro(player, outroSegment);
} else {
console.log('No outro segment found/provided');
}
}).catch(error => {
console.error('Error reading SponsorBlock outro segment:', error);
});
}
if (trailerMaxLength > 0) {
clearTimeout(slideChangeTimeout);
slideChangeTimeout = setTimeout(() => {
if (player) {
player.stopVideo();
player.destroy();
player = null;
}
fetchRandomMovie();
}, trailerMaxLength);
}
if (isMuted) {
event.target.setVolume(0); // Mute the video if the setting is MuteOn
} else {
event.target.setVolume(unmutedVolume); // Set the volume, value between 0 and 100
}
event.target.playVideo(); event.target.playVideo();
}, },
'onStateChange': event => { 'onStateChange': event => {
@@ -192,15 +338,22 @@ const createSlideElement = (movie, hasVideo = false) => {
backdrop.style.width = 'calc(100% - 23vw)'; backdrop.style.width = 'calc(100% - 23vw)';
backdrop.style.left = '0vw'; backdrop.style.left = '0vw';
} }
const plot = document.querySelector('.plot'); const plot = document.querySelector('.plot');
if (plot) plot.style.width = 'calc(100% - 36.4vw)'; if (plot) {
plot.style.left = '33vw';
plot.style.maxWidth = '63vw';
}
const genres = document.querySelector('.genres');
if (genres) {
genres.style.left = 'calc(50% - 17vw)';
}
const loremIpsum = document.querySelector('.lorem-ipsum'); const loremIpsum = document.querySelector('.lorem-ipsum');
if (loremIpsum) loremIpsum.style.paddingRight = '32.4vw'; if (loremIpsum) loremIpsum.style.left = 'calc(50% - 17vw)';
const logo = document.querySelector('.logo'); const logo = document.querySelector('.logo');
if (logo) logo.style.left = 'calc(50% - 14.2vw)'; if (logo) logo.style.left = 'calc(50% - 17vw)';
videoContainer.style.width = '34.4vw'; videoContainer.style.width = '34.4vw';
} else if (event.data === YT.PlayerState.ENDED) { } else if (event.data === YT.PlayerState.ENDED) {
@@ -210,6 +363,7 @@ const createSlideElement = (movie, hasVideo = false) => {
'onError': () => { 'onError': () => {
console.error(`YouTube prevented playback of '${movie.Name}'`); console.error(`YouTube prevented playback of '${movie.Name}'`);
if (player) { if (player) {
clearInterval(monitorOutroInterval);
player.destroy(); player.destroy();
player = null; player = null;
} }
@@ -233,6 +387,7 @@ const createSlideElement = (movie, hasVideo = false) => {
} }
} }
}); });
} else { } else {
startSlideChangeTimer(); startSlideChangeTimer();
} }
@@ -242,17 +397,6 @@ const createSlideElement = (movie, hasVideo = false) => {
container.appendChild(slide); container.appendChild(slide);
}; };
// Fetch the previous movie in the list
function previousMovie() {
if (isChangingSlide) return;
isChangingSlide = true;
// Reset index or set to the end of the list if we are at the first element
currentMovieIndex = (currentMovieIndex - 2 + movieList.length) % movieList.length;
fetchNextMovie();
}
function addSwipeListeners(slide) { function addSwipeListeners(slide) {
let startX, startY, distX, distY; let startX, startY, distX, distY;
const threshold = 50; const threshold = 50;
@@ -283,6 +427,33 @@ function addSwipeListeners(slide) {
}); });
} }
const navigateBack = () => {
if (previousMovies.length < 2) {
console.log("No previous slides in history.");
return;
}
const currentMovie = previousMovies.pop();
forwardMovies.unshift(currentMovie);
const previousMovie = previousMovies[previousMovies.length - 1];
createSlideElement(previousMovie, true);
};
const navigateForward = () => {
if (forwardMovies.length === 0) {
console.log("No forward slides in history.");
fetchRandomMovie();
return;
}
const currentMovie = forwardMovies.shift();
previousMovies.push(currentMovie);
createSlideElement(currentMovie, true);
};
// Show the video overlay // Show the video overlay
function showVideoOverlay(trailerUrl) { function showVideoOverlay(trailerUrl) {
const videoOverlay = document.getElementById('video-overlay'); const videoOverlay = document.getElementById('video-overlay');
@@ -353,53 +524,65 @@ const readCustomList = () =>
fetch(listFileName + '?' + new Date().getTime()) fetch(listFileName + '?' + new Date().getTime())
.then(response => response.ok ? response.text() : null) .then(response => response.ok ? response.text() : null)
.then(text => { .then(text => {
if (!text) return null; if (!text || !text.trim()) {
console.warn('List.txt is empty or could not be loaded.');
return null; // Fallback to random selection
}
const lines = text.split('\n').filter(Boolean); const lines = text.split('\n').filter(Boolean);
title = lines.shift() || title;
return lines.map(line => line.trim().substring(0, 32)); const firstLine = lines.shift().trim();
const [parsedTitle, muteSetting] = firstLine.split(/\s+/);
title = parsedTitle || title;
// Check for mute
// MARK: set mute
isMuted = muteSetting === "MuteOn";
// Remaining lines are media IDs
const mediaList = lines.map(line => line.trim().substring(0, 32));
if (setRandomMovie) {
return shuffleArray(mediaList); // Shuffle the list before returning it if set
}
return mediaList; // return exact list
}) })
.catch(() => null); .catch(() => {
console.error('Error reading List.txt. Falling back to random selection.');
return null;
});
// using Fisher-Yates shuffle algorithm if list is available and setRandomMovie is set to true
const shuffleArray = (array) => {
for (let i = array.length - 1; i > 0; i--) {
// Generate a random index between 0 and i
const j = Math.floor(Math.random() * (i + 1));
// Swap elements at indices i and j
[array[i], array[j]] = [array[j], array[i]];
//var temp = array[i];
//array[i] = array[j];
//array[j] = temp;
}
return array;
};
//const shuffleArray = (array) => array.sort(() => Math.random() - 0.5); //better use Fisher-Yates shuffle algorithm
const fetchRandomMovie = () => { const fetchRandomMovie = () => {
if (isChangingSlide) return; if (isChangingSlide) return;
isChangingSlide = true; isChangingSlide = true;
if (movieList.length === 0) { if (movieList.length === 0) {
readCustomList().then(list => { readCustomList().then(list => {
if (list) { if (list && list.length > 0) {
movieList = list; movieList = list;
//// Shuffle the list if it was set by the user
//if (setRandomMovie) {
// shuffleArray(movieList);
//}
currentMovieIndex = 0; currentMovieIndex = 0;
fetchNextMovie();
} else {
console.warn("Fallback to random selection.");
fetchNextMovie(true);
} }
fetchNextMovie();
}); });
} else fetchNextMovie(); } else {
fetchNextMovie();
}
}; };
const fetchNextMovie = () => { const shuffleArray = (array) => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
};
const fetchNextMovie = (useRandom = false) => {
const fetchCurrentUserId = () => const fetchCurrentUserId = () =>
fetch('/Sessions', { fetch('/Sessions', { headers: { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` } })
headers: { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` }
})
.then(response => response.json()) .then(response => response.json())
.then(sessions => { .then(sessions => {
const currentSession = sessions.find(session => session.UserId); const currentSession = sessions.find(session => session.UserId);
@@ -410,12 +593,13 @@ const fetchNextMovie = () => {
fetchCurrentUserId().then(currentUserId => { fetchCurrentUserId().then(currentUserId => {
if (!currentUserId) { if (!currentUserId) {
console.error('Could not retrieve the current user ID.'); console.error('Could not retrieve the current user ID.');
isChangingSlide = false;
return; return;
} }
const headers = { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` }; const headers = { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` };
if (movieList.length > 0) { if (!useRandom && movieList.length > 0) {
if (currentMovieIndex >= movieList.length) currentMovieIndex = 0; if (currentMovieIndex >= movieList.length) currentMovieIndex = 0;
const movieId = movieList[currentMovieIndex]; const movieId = movieList[currentMovieIndex];
currentMovieIndex++; currentMovieIndex++;
@@ -438,22 +622,22 @@ const fetchNextMovie = () => {
const checkNavigation = () => { const checkNavigation = () => {
const newLocation = window.top.location.href; const newLocation = window.top.location.href;
// Check if the user is navigating to or from the homepage
if (newLocation !== currentLocation) { if (newLocation !== currentLocation) {
currentLocation = newLocation; currentLocation = newLocation;
const isHomePage = url => url.includes('/home') || url.endsWith('/web/') || url.endsWith('/web/index.html'); const isHomePage = url => url.includes('/home') || url.endsWith('/web/') || url.endsWith('/web/index.html');
if (isHomePage(newLocation)) {
if (!isHomePageActive) { if (!isHomePage(newLocation) && isHomePageActive) {
console.log("Returning to homepage, reactivating slideshow"); console.log("Leaving homepage, cleaning up slideshow and stopping video");
isHomePageActive = true;
cleanup();
fetchRandomMovie();
}
} else if (isHomePageActive) {
console.log("Leaving homepage, cleaning up slideshow");
isHomePageActive = false; isHomePageActive = false;
stopBackgroundVideo();
cleanup(); cleanup();
} }
if (isHomePage(newLocation) && !isHomePageActive) {
console.log("Returning to homepage, reactivating slideshow");
isHomePageActive = true;
fetchRandomMovie();
}
} }
// Check if parent is available and if the iframe is in an embedded environment // Check if parent is available and if the iframe is in an embedded environment
@@ -479,6 +663,14 @@ const checkNavigation = () => {
} }
}; };
const stopBackgroundVideo = () => {
if (player && typeof player.stopVideo === 'function') {
player.stopVideo();
player.destroy();
}
player = null;
};
setInterval(checkNavigation, 60); setInterval(checkNavigation, 60);
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
@@ -487,14 +679,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (isHomePage(window.top.location.href)) { if (isHomePage(window.top.location.href)) {
isHomePageActive = true; isHomePageActive = true;
readCustomList().then(list => { readCustomList().then(list => {
if (list) { if (list) { movieList = list; currentMovieIndex = 0; }
movieList = list;
// Shuffle the list if it was set by the user
if (setRandomMovie) {
shuffleArray(movieList);
}
currentMovieIndex = 0;
}
fetchRandomMovie(); fetchRandomMovie();
}); });
} }

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ body {
transition: width 0.5s ease, filter 0.8s ease, scale 2s ease; transition: width 0.5s ease, filter 0.8s ease, scale 2s ease;
transform-origin: top; transform-origin: top;
animation: objectPositionAnimation 45s ease-in-out infinite; animation: objectPositionAnimation 45s ease-in-out infinite;
border-radius: 1em; border-radius: 2.1em;
} }
.logo { .logo {
@@ -40,7 +40,7 @@ body {
max-height: 9em; max-height: 9em;
max-width: 29em; max-width: 29em;
width: auto; width: auto;
z-index: 3; z-index: 7;
text-shadow: -2px 2px 4px rgba(0, 0, 0, 0.5); text-shadow: -2px 2px 4px rgba(0, 0, 0, 0.5);
filter: drop-shadow(1px 1px 1px); filter: drop-shadow(1px 1px 1px);
pointer-events: none; pointer-events: none;
@@ -79,61 +79,19 @@ body {
text-shadow: 1px 1px 4px rgba(0, 0, 0, 1); text-shadow: 1px 1px 4px rgba(0, 0, 0, 1);
} }
.details-button {
display: none;
}
/* MARK: modified
css for back and skip button
*/
.back-button, .back-button,
.skip-button { .skip-button {
position: absolute; position: absolute;
color: #D3D3D3; color: #fff;
cursor: pointer; cursor: pointer;
z-index: 10; z-index: 10;
font-family: "Titillium Web", sans-serif; font-family: "Titillium Web", sans-serif;
text-shadow: 1px 1px 4px rgba(0, 0, 0, 1); text-shadow: 1px 1px 4px rgba(0, 0, 0, 1);
font-style: normal; font-size: 2em;
font-weight: 400;
letter-spacing: normal;
line-height: 1;
text-transform: none;
white-space: nowrap;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
-moz-osx-font-smoothing: grayscale;
-webkit-font-feature-settings: "liga";
font-feature-settings: "liga";
border-radius: 50%;
box-sizing: border-box;
opacity: 0.5;
transition: opacity 0.3s ease, background 0.3s ease;
font-size: 1.62em;
width: 1.7em;
height: 1.7em;
display: flex;
align-items: center;
justify-content: center;
} }
.back-button:hover, .details-button {
.skip-button:hover { display: none;
background: #ffffff70;
opacity: 1;
}
.skip-button {
right: 0.5em;
top: 50%;
transform: translateY(-50%);
}
.back-button {
left: 0.5em;
top: 50%;
transform: translateY(-50%);
/* display: none; */ /* Optional, if activated later */
} }
.material-icons { .material-icons {
@@ -203,7 +161,7 @@ css for back and skip button
.age-rating { .age-rating {
position: absolute; position: absolute;
top: 0.1em; top: 0.5em;
left: 2em; left: 2em;
text-align: left; text-align: left;
font-family: "Titillium Web", sans-serif; font-family: "Titillium Web", sans-serif;
@@ -226,9 +184,9 @@ css for back and skip button
.plot { .plot {
position: absolute; position: absolute;
bottom: 0.1em; top: -0.3em;
left: 2.2em; left: 50vw;
right: 0; transform: translateX(-50%);
color: #fff; color: #fff;
font-family: "Titillium Web", sans-serif; font-family: "Titillium Web", sans-serif;
font-size: 0.95em; font-size: 0.95em;
@@ -245,13 +203,14 @@ css for back and skip button
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
border-bottom-left-radius: 0.45em; border-bottom-left-radius: 0.45em;
transition: opacity 0.1s ease, max-height 0.8s ease, width 0.3s ease; transition: opacity 0.1s ease, max-height 0.8s ease, width 0.3s ease, left 0.3s ease;
opacity: 0; opacity: 0;
max-width: 96vw; max-width: 96vw;
opacity: 1; opacity: 1;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
line-clamp: 2; line-clamp: 2;
max-height: 7.8em; max-height: 7.8em;
text-align: center;
} }
.genres { .genres {
@@ -349,19 +308,17 @@ css for back and skip button
transform: scale(1); transform: scale(1);
} }
/* .slide:hover .clickable-overlay {} */ /*.slide:hover .clickable-overlay {}*/
.slide:hover .clickable-overlay::before { .slide:hover .clickable-overlay::before {
opacity: 0; opacity: 0;
backdrop-filter: blur(0px); backdrop-filter: blur(0px);
} }
/* /*
.slide:hover .logo {} .slide:hover .logo {}
.slide:hover .plot {} .slide:hover .plot {}
*/ */
.slide:hover .lorem-ipsum::before { .slide:hover .lorem-ipsum::before {
opacity: 1; opacity: 1;
backdrop-filter: blur(2px); backdrop-filter: blur(2px);
@@ -393,7 +350,7 @@ css for back and skip button
.logo { .logo {
transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%);
top: 10.5em; top: 6.5em;
left: 50% !important; left: 50% !important;
max-width: 70%; max-width: 70%;
max-height: 45%; max-height: 45%;
@@ -567,12 +524,13 @@ css for back and skip button
@media (max-width:1000px) and (orientation:portrait) { @media (max-width:1000px) and (orientation:portrait) {
.back-button { .back-button {
left: 0em; top: 5em !important;
left: 0.5em;
} }
.skip-button { .skip-button {
right: 0em; top: 5em !important;
/*top: 50% !important;*/ right: 0.5em;
} }
.genres { .genres {
@@ -593,6 +551,10 @@ css for back and skip button
} }
@media (max-width:1000px) and (orientation:landscape) { @media (max-width:1000px) and (orientation:landscape) {
.slide {
height: 70vh;
}
.community-rating { .community-rating {
left: 89vw !important; left: 89vw !important;
} }
@@ -602,12 +564,13 @@ css for back and skip button
} }
.back-button { .back-button {
left: 0em; top: 4em !important;
left: 0.5em;
} }
.skip-button { .skip-button {
right: 0em; top: 4em !important;
/*top: 50% !important;*/ right: 0.5em;
} }
.genres { .genres {
@@ -628,74 +591,124 @@ css for back and skip button
@media (min-width: 1001px) { @media (min-width: 1001px) {
.logo { .logo {
max-height: 45%; max-height: 45%;
top: 50vh; top: 34vh;
max-width: 47em; max-width: 47em;
left: 50%; left: 50%;
transition: transform 0.1s ease, max-height 0.3s ease; transition: transform 0.1s ease, left 0.3s ease, max-height 0.3s ease;
} }
}
.watch-trailer-button { .lorem-ipsum {
display: none; left: 50vw;
} transition: left 0.3s ease;
transform: translateX(-50%);
top: unset;
bottom: 3.2em;
padding-left: unset;
}
.backdrop { .watch-trailer-button {
left: 0em; display: none;
width: 100%; }
transition: width 0.5s ease, left 0.5s ease, filter 0.8s ease, transform 2s ease;
}
.genres { .backdrop {
left: 8em; left: 0em;
z-index: 9; width: 100%;
max-width: 39em; transition: width 0.5s ease, left 0.5s ease, filter 0.8s ease, transform 2s ease;
} }
.community-rating { .genres {
top: 16.45em; left: 50vw;
left: 31em; top: unset;
font-size: 1em; bottom: 5em;
} transition: left 0.3s;
z-index: 9;
max-width: 39em;
transform: translateX(-50%);
}
.critic-rating { .community-rating {
position: absolute; top: 16.45em;
top: 16.45em; left: 31em;
left: 26.5em; font-size: 1em;
font-size: 1em; }
}
.text-container::before { .critic-rating {
content: ''; position: absolute;
z-index: 5; top: 16.45em;
display: flex; left: 26.5em;
position: absolute; font-size: 1em;
width: 100vw; }
top: -19.3em;
height: 3em;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.7) 6.25%, rgba(0, 0, 0, 0.68) 12.5%, rgba(0, 0, 0, 0.66) 18.75%, rgba(0, 0, 0, 0.64) 25%, rgba(0, 0, 0, 0.6) 31.25%, rgba(0, 0, 0, 0.56) 37.5%, rgba(0, 0, 0, 0.51) 43.75%, rgba(0, 0, 0, 0.45) 50%, rgba(0, 0, 0, 0.38) 56.25%, rgba(0, 0, 0, 0.31) 62.5%, rgba(0, 0, 0, 0.22) 68.75%, rgba(0, 0, 0, 0.14) 75%, rgba(0, 0, 0, 0.13) 81.25%, rgba(0, 0, 0, 0) 100%);
opacity: 0.8;
backdrop-filter: blur(1px);
border-top-right-radius: 1em;
border-top-left-radius: 1em;
-webkit-mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%);
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%);
}
.text-container::after { .back-button {
content: ''; display: inline-flex;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.7) 6.25%, rgba(0, 0, 0, 0.68) 12.5%, rgba(0, 0, 0, 0.66) 18.75%, rgba(0, 0, 0, 0.64) 25%, rgba(0, 0, 0, 0.6) 31.25%, rgba(0, 0, 0, 0.56) 37.5%, rgba(0, 0, 0, 0.51) 43.75%, rgba(0, 0, 0, 0.45) 50%, rgba(0, 0, 0, 0.38) 56.25%, rgba(0, 0, 0, 0.31) 62.5%, rgba(0, 0, 0, 0.22) 68.75%, rgba(0, 0, 0, 0.14) 75%, rgba(0, 0, 0, 0.13) 81.25%, rgba(0, 0, 0, 0) 100%); justify-content: center;
z-index: 5; align-items: center;
display: flex; width: 1.2em;
position: absolute; height: 1.2em;
width: 100vw; border-radius: 50%;
border-top-right-radius: 1em; overflow: hidden;
border-top-left-radius: 1em; transition: background 0.3s, color 0.3s;
bottom: 0em; color: #ffffffa1;
height: 3em; left: 0.5em;
opacity: 0.8; top: 5em;
backdrop-filter: blur(1px); }
-webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%);
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%); .skip-button {
display: inline-flex;
justify-content: center;
align-items: center;
width: 1.2em;
height: 1.2em;
border-radius: 50%;
overflow: hidden;
transition: background 0.3s, color 0.3s;
color: #ffffffa1;
right: 0.5em;
top: 5em;
}
.text-container::before {
content: '';
z-index: 5;
display: flex;
position: absolute;
width: 100vw;
top: -19.3em;
height: 3em;
background: transparent;
backdrop-filter: blur(0px);
border-top-right-radius: 1em;
border-top-left-radius: 1em;
-webkit-mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%);
mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%);
}
.text-container::after {
content: '';
background: linear-gradient(0deg, rgb(0% 0% 0% / 0.98) 0%, rgb(0% 0% 0% / 0.9705847873975829) 6.25%, rgb(0% 0% 0% / 0.9427009709305305) 12.5%, rgb(0% 0% 0% / 0.8974201100282472) 18.75%, rgb(0% 0% 0% / 0.8364823227814083) 25%, rgb(0% 0% 0% / 0.7622294141796051) 31.25%, rgb(0% 0% 0% / 0.6775148818588941) 37.5%, rgb(0% 0% 0% / 0.5855942577879029) 43.75%, rgb(0% 0% 0% / 0.49000000000000005) 50%, rgb(0% 0% 0% / 0.39440574221209723) 56.25%, rgb(0% 0% 0% / 0.3024851181411061) 62.5%, rgb(0% 0% 0% / 0.217770585820395) 68.75%, rgb(0% 0% 0% / 0.14351767721859177) 75%, rgb(0% 0% 0% / 0.0825798899717528) 81.25%, rgb(0% 0% 0% / 0.03729902906946947) 87.5%, rgb(0% 0% 0% / 0.009415212602417067) 93.75%, rgb(0% 0% 0% / 0) 100%);
z-index: 5;
display: flex;
position: absolute;
width: 100vw;
border-bottom-left-radius: 1em;
bottom: 0em;
height: 22.5em;
opacity: 1;
backdrop-filter: blur(0px);
-webkit-mask-image: linear-gradient(0deg, rgb(0% 0% 0% / 0.98) 0%, rgb(0% 0% 0% / 0.9705847873975829) 6.25%, rgb(0% 0% 0% / 0.9427009709305305) 12.5%, rgb(0% 0% 0% / 0.8974201100282472) 18.75%, rgb(0% 0% 0% / 0.8364823227814083) 25%, rgb(0% 0% 0% / 0.7622294141796051) 31.25%, rgb(0% 0% 0% / 0.6775148818588941) 37.5%, rgb(0% 0% 0% / 0.5855942577879029) 43.75%, rgb(0% 0% 0% / 0.49000000000000005) 50%, rgb(0% 0% 0% / 0.39440574221209723) 56.25%, rgb(0% 0% 0% / 0.3024851181411061) 62.5%, rgb(0% 0% 0% / 0.217770585820395) 68.75%, rgb(0% 0% 0% / 0.14351767721859177) 75%, rgb(0% 0% 0% / 0.0825798899717528) 81.25%, rgb(0% 0% 0% / 0.03729902906946947) 87.5%, rgb(0% 0% 0% / 0.009415212602417067) 93.75%, rgb(0% 0% 0% / 0) 100%);
mask-image: linear-gradient(0deg, rgb(0% 0% 0% / 0.98) 0%, rgb(0% 0% 0% / 0.9705847873975829) 6.25%, rgb(0% 0% 0% / 0.9427009709305305) 12.5%, rgb(0% 0% 0% / 0.8974201100282472) 18.75%, rgb(0% 0% 0% / 0.8364823227814083) 25%, rgb(0% 0% 0% / 0.7622294141796051) 31.25%, rgb(0% 0% 0% / 0.6775148818588941) 37.5%, rgb(0% 0% 0% / 0.5855942577879029) 43.75%, rgb(0% 0% 0% / 0.49000000000000005) 50%, rgb(0% 0% 0% / 0.39440574221209723) 56.25%, rgb(0% 0% 0% / 0.3024851181411061) 62.5%, rgb(0% 0% 0% / 0.217770585820395) 68.75%, rgb(0% 0% 0% / 0.14351767721859177) 75%, rgb(0% 0% 0% / 0.0825798899717528) 81.25%, rgb(0% 0% 0% / 0.03729902906946947) 87.5%, rgb(0% 0% 0% / 0.009415212602417067) 93.75%, rgb(0% 0% 0% / 0) 100%);
pointer-events: none;
}
.skip-button:hover {
background: #101010a8;
color: #fff;
}
.back-button:hover {
background: #101010a8;
color: #fff;
}
} }
.age-rating { .age-rating {
@@ -876,18 +889,11 @@ css for back and skip button
font-size: 133%; font-size: 133%;
} }
/* .backdrop {} /*
.backdrop {}
.age-rating {} .age-rating {}
.back-button {
top: 38vh;
}
.skip-button {
top: 38vh;
}
.video-container {} .video-container {}
.text-container::before {} .text-container::before {}
@@ -896,9 +902,6 @@ css for back and skip button
.lorem-ipsum {} .lorem-ipsum {}
*/ */
.logo {
top: 38vh;
}
} }
@media (min-width: 3000px) { @media (min-width: 3000px) {
@@ -923,10 +926,11 @@ css for back and skip button
#video-overlay { #video-overlay {
position: fixed; position: fixed;
top: 13vh; top: 10vh;
border-radius: 1em;
left: 0vw; left: 0vw;
width: 100%; width: 94.5vw;
height: 140vh; height: 55vh;
background-color: rgb(0, 0, 0); background-color: rgb(0, 0, 0);
z-index: 1000; z-index: 1000;
display: flex; display: flex;
@@ -938,12 +942,30 @@ css for back and skip button
#video-overlay-content { #video-overlay-content {
position: relative; position: relative;
width: 90%; width: 100%;
max-width: 100%; max-width: 100%;
height: 60%; height: 100%;
background-color: #000; background-color: #000;
} }
@media (orientation: portrait) {
#video-overlay {
position: fixed;
top: 10vh;
border-radius: 1em;
left: 0vw;
width: 87.5vw;
height: 68vh;
background-color: rgb(0, 0, 0);
z-index: 1000;
display: flex;
background-size: cover;
padding: 6vh;
padding-top: 10vh;
margin-top: -10vh;
}
}
#close-overlay { #close-overlay {
position: absolute; position: absolute;
top: -1em; top: -1em;
@@ -998,4 +1020,64 @@ css for back and skip button
vertical-align: middle; vertical-align: middle;
font-size: 0.85em; font-size: 0.85em;
opacity: 0.75; opacity: 0.75;
}
.logo {
opacity: 0;
animation: fadeIn 1.5s ease-in forwards;
animation-delay: 1s;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}
.plot {
opacity: 0;
animation: fadeIn 1s ease-in forwards;
animation-delay: 2s;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}
.genres {
opacity: 0;
animation: fadeIn 1s ease-in forwards;
animation-delay: 1.5s;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}
.lorem-ipsum {
opacity: 0;
animation: fadeIn 1s ease-in forwards;
animation-delay: 1.5s;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}
.text-container::after {
opacity: 0.7;
animation: fadeIn 1.5s ease-in forwards;
animation-delay: 1s;
}
@keyframes fadeIn {
to {
opacity: 1;
}
} }