From 31ccec3ab3c482bae6257fe2e933da59e5195bb4 Mon Sep 17 00:00:00 2001 From: Zach Ross-Clyne <78486554+IAmParadox27@users.noreply.github.com> Date: Mon, 10 Feb 2025 15:39:41 +0000 Subject: [PATCH] Update slideshowpure.js --- .../Inject/slideshowpure.js | 941 +++++++++--------- 1 file changed, 481 insertions(+), 460 deletions(-) diff --git a/src/Jellyfin.Plugin.MediaBar/Inject/slideshowpure.js b/src/Jellyfin.Plugin.MediaBar/Inject/slideshowpure.js index 95609be..548c8de 100644 --- a/src/Jellyfin.Plugin.MediaBar/Inject/slideshowpure.js +++ b/src/Jellyfin.Plugin.MediaBar/Inject/slideshowpure.js @@ -1,466 +1,487 @@ -const slidesInit = () => { - const shuffleInterval = 8000; - let isTransitioning = false; - const listFileName = `${window.location.origin}/web/avatars/list.txt`; - const jsonCredentials = sessionStorage.getItem("json-credentials"); - let userId = null; - let token = null; - const deviceId = localStorage.getItem("_deviceId2"); - console.log(deviceId); - if (jsonCredentials) { - const credentials = JSON.parse(jsonCredentials); - userId = credentials.Servers[0].UserId; - token = credentials.Servers[0].AccessToken; +const slidesInit = () => { + const shuffleInterval = 8000; + let isTransitioning = false; + const listFileName = `${window.location.origin}/web/avatars/list.txt`; + const jsonCredentials = sessionStorage.getItem("json-credentials"); + let userId = null; + let token = null; + //const deviceId = localStorage.getItem("_deviceId2"); + //console.log(deviceId); + if (jsonCredentials) { + const credentials = JSON.parse(jsonCredentials); + userId = credentials.Servers[0].UserId; + token = credentials.Servers[0].AccessToken; + } + const shuffleArray = (array) => array.sort(() => Math.random() - 0.5); + const truncateText = (element, maxLength) => { + let text = element.innerText; + if (text.length > maxLength) + element.innerText = text.substring(0, maxLength) + "..."; + }; + const createSlideElement = (item, title) => { + const itemId = item.Id; + const plot = item.Overview || "No overview available"; + const rating = item.CommunityRating; + const tomato = item.CriticRating; + const runtime = item.RunTimeTicks; + const genre = item.Genres; + const youtube = item.RemoteTrailers; + const age = item.OfficialRating; + const date = item.PremiereDate; + const season = item.ChildCount; + function createSeparator() { + const separatorHtml = + ''; + const tempDiv = document.createElement("div"); + tempDiv.innerHTML = separatorHtml; + return tempDiv.firstChild; } - const shuffleArray = (array) => array.sort(() => Math.random() - 0.5); - const truncateText = (element, maxLength) => { - let text = element.innerText; - if (text.length > maxLength) - element.innerText = text.substring(0, maxLength) + "..."; + const slide = document.createElement("a"); + slide.className = "slide"; + slide.target = "_top"; + slide.rel = "noreferrer"; + slide.tabIndex = 0; + slide.style.display = "none"; + const backdrop = document.createElement("img"); + backdrop.className = "backdrop"; + backdrop.src = `${window.location.origin}/Items/${itemId}/Images/Backdrop/0`; + backdrop.alt = "Backdrop"; + const backdropOverlay = document.createElement("div"); + backdropOverlay.className = "backdrop-overlay"; + const backdropContainer = document.createElement("div"); + backdropContainer.className = "backdrop-container"; + backdropContainer.appendChild(backdrop); + backdropContainer.appendChild(backdropOverlay); + const logo = document.createElement("img"); + logo.className = "logo"; + logo.src = `${window.location.origin}/Items/${itemId}/Images/Logo`; + logo.alt = "Logo"; + const logoContainer = document.createElement("div"); + logoContainer.className = "logo-container"; + logoContainer.appendChild(logo); + const featuredContent = document.createElement("div"); + featuredContent.className = "featured-content"; + featuredContent.textContent = title; + const plotElement = document.createElement("div"); + plotElement.className = "plot"; + plotElement.textContent = plot; + truncateText(plotElement, 360); + const plotContainer = document.createElement("div"); + plotContainer.className = "plot-container"; + plotContainer.appendChild(plotElement); + const gradientOverlay = document.createElement("div"); + gradientOverlay.className = "gradient-overlay"; + const runTimeElement = document.createElement("div"); + runTimeElement.className = "runTime"; + if (season === undefined) { + const milliseconds = runtime / 10000; + const currentTime = new Date(); + const endTime = new Date(currentTime.getTime() + milliseconds); + const options = { hour: "2-digit", minute: "2-digit", hour12: !0 }; + const formattedEndTime = endTime.toLocaleTimeString([], options); + runTimeElement.textContent = `Ends at ${formattedEndTime}`; + } else { + runTimeElement.textContent = `${season} Season${season > 1 ? "s" : ""}`; + } + const ratingTest = document.createElement("div"); + ratingTest.className = "rating-value"; + const imdbLogo = document.createElement("img"); + imdbLogo.className = "imdb-logo"; + imdbLogo.src = + "https://upload.wikimedia.org/wikipedia/commons/6/69/IMDB_Logo_2016.svg"; + imdbLogo.alt = "IMDb Logo"; + imdbLogo.style.width = "30px"; + imdbLogo.style.height = "30px"; + ratingTest.appendChild(imdbLogo); + if (typeof rating === "number") { + const formattedRating = rating.toFixed(1); + ratingTest.innerHTML += `${formattedRating} ⭐`; + } else { + console.error("Rating is undefined or not a number:", rating); + ratingTest.innerHTML += `N/A ⭐`; + } + ratingTest.appendChild(createSeparator()); + const tomatoRatingDiv = document.createElement("div"); + tomatoRatingDiv.className = "tomato-rating"; + const criticRating = item.CriticRating; + const tomatoLogo = document.createElement("img"); + tomatoLogo.className = "tomato-logo"; + const criticLogo = document.createElement("img"); + criticLogo.className = "critic-logo"; + tomatoLogo.src = + "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Rotten_Tomatoes_positive_audience.svg/1920px-Rotten_Tomatoes_positive_audience.svg.png"; + let valueElement; + if (typeof criticRating === "number") { + valueElement = document.createTextNode(`${criticRating}% `); + } else { + valueElement = document.createTextNode(`N/A `); + } + if (criticRating === undefined || criticRating <= 59) { + criticLogo.src = + "https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Rotten_Tomatoes_rotten.svg/1024px-Rotten_Tomatoes_rotten.svg.png"; + criticLogo.alt = "Rotten Tomato"; + } else { + criticLogo.src = "https://i.imgur.com/iMfwDk7.png"; + criticLogo.alt = "Fresh Tomato"; + } + tomatoLogo.style.width = "15px"; + tomatoLogo.style.height = "17px"; + criticLogo.style.width = "15px"; + criticLogo.style.height = "15px"; + tomatoRatingDiv.appendChild(tomatoLogo); + tomatoRatingDiv.appendChild(valueElement); + tomatoRatingDiv.appendChild(criticLogo); + tomatoRatingDiv.appendChild(createSeparator()); + const ageRatingDiv = document.createElement("div"); + ageRatingDiv.className = "age-rating"; + if (item.OfficialRating) { + ageRatingDiv.innerHTML = `${item.OfficialRating}`; + } else { + ageRatingDiv.innerHTML = `N/A`; + } + const calender = "📅"; + const premiereDate = document.createElement("div"); + premiereDate.className = "date"; + const year = date ? new Date(date).getFullYear() : "N/A"; + premiereDate.textContent = isNaN(year) ? "N/A" : year; + ratingTest.appendChild(tomatoRatingDiv); + ratingTest.appendChild(document.createTextNode(calender)); + ratingTest.appendChild(premiereDate); + ratingTest.appendChild(createSeparator()); + ratingTest.appendChild(ageRatingDiv); + ratingTest.appendChild(createSeparator()); + ratingTest.appendChild(runTimeElement); + const genresArray = item.Genres; + function parseGenres(genresArray) { + if (genresArray && genresArray.length > 0) { + return genresArray.slice(0, 3).join(" 🔹 "); + } else { + return "No Genre Available"; + } + } + const genreElement = document.createElement("div"); + genreElement.className = "genre"; + genreElement.innerHTML = parseGenres(genresArray); + const infoContainer = document.createElement("div"); + infoContainer.className = "info-container"; + infoContainer.appendChild(ratingTest); + // Create a container for the buttons +const buttonContainer = document.createElement("div"); +buttonContainer.className = "button-container"; // Add a class for styling + +// Create the Play button +const playButton = document.createElement("button"); +playButton.className = "play-button"; +playButton.innerHTML = ` + + Play Now +`; +playButton.onclick = async () => { + if (!window.ApiClient) { + console.error("Jellyfin API client is not available."); + return; + } + const apiClient = window.ApiClient; + const userId = apiClient.getCurrentUserId(); + if (!userId) { + console.error("User not found."); + return; + } + try { + const sessions = await apiClient.getJSON(apiClient.serverAddress() + "/Sessions"); + if (!sessions.length) { + console.error("No active Jellyfin sessions found."); + return; + } + + // Find the session matching the current user + const userSession = sessions.find(session => session.UserId === userId); + if (!userSession) { + console.error("No active session found for the current user."); + return; + } + + const sessionId = userSession.Id; + const playbackUrl = `${apiClient.serverAddress()}/Sessions/${sessionId}/Playing?StartPositionTicks=0&PlayCommand=PlayNow&StartIndex=0&ItemIds=${itemId}&api_key=${token}`; + + const response = await fetch(playbackUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `DeviceId="unique-device-id", Token="${token}"`, + }, + }); + + if (response.status === 204) { + console.log("Playback started successfully."); + } else { + const errorData = await response.json(); + console.error("Failed to start playback:", errorData); + } + } catch (error) { + console.error("Error fetching sessions:", error); + } +}; + +// Create the Details button +const detailButton = document.createElement("button"); +detailButton.className = "detail-button"; +detailButton.innerHTML = ` + + More Info +`; +detailButton.onclick = () => { + window.top.location.href = `/#!/details?id=${itemId}`; +}; + +// Append buttons to the button container +buttonContainer.appendChild(playButton); +buttonContainer.appendChild(detailButton); + +// Append all elements to the slide +slide.append( + logoContainer, + backdropContainer, + gradientOverlay, + featuredContent, + plotContainer, + infoContainer, + genreElement, + buttonContainer // Add button container instead of individual buttons +); + +return slide; + }; + const createSlideForItem = async (item, title) => { + const container = document.getElementById("slides-container"); + const itemId = item.Id; + const backdropUrl = `${window.location.origin}/Items/${itemId}/Images/Backdrop/0`; + const logoUrl = `${window.location.origin}/Items/${itemId}/Images/Logo`; + const [backdropExists, logoExists] = await Promise.all([ + fetch(backdropUrl, { method: "HEAD" }).then((res) => res.ok), + fetch(logoUrl, { method: "HEAD" }).then((res) => res.ok), + ]); + if (backdropExists && logoExists) { + const slideElement = createSlideElement(item, title); + container.appendChild(slideElement); + console.log(`Added slide for item ${itemId}`); + if (container.children.length === 1) { + showSlide(0); + } + } else { + console.warn(`Skipping item ${itemId}: Missing backdrop or logo.`); + } + }; + const fetchItemDetails = async (itemId) => { + const response = await fetch( + `${window.location.origin}/Users/${userId}/Items/${itemId}`, + { + headers: { + Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"`, + }, + } + ); + const item = await response.json(); + console.log("Item Title:", item.Name); + return item; + }; + const fetchItemIdsFromList = async () => { + try { + const response = await fetch(listFileName); + if (!response.ok) { + throw new Error("Failed to fetch list.txt"); + } + const text = await response.text(); + return text + .split("\n") + .map((id) => id.trim()) + .filter((id) => id); + } catch (error) { + console.error("Error fetching list.txt:", error); + return []; + } + }; + const fetchItemsFromServer = async () => { + try { + const response = await fetch( + `${window.location.origin}/Users/${userId}/Items?IncludeItemTypes=Movie,Series&Recursive=true&hasOverview=true&imageTypes=Logo,Backdrop&isPlayed=False&Limit=150`, + { + headers: { + Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"`, + }, + } + ); + const data = await response.json(); + const items = data.Items; + const movies = items.filter((item) => item.Type === "Movie"); + const tvShows = items.filter((item) => item.Type === "Series"); + const shuffledMovies = shuffleArray(movies); + const shuffledTvShows = shuffleArray(tvShows); + const selectedMovies = shuffledMovies.slice(0, 15); + const selectedTvShows = shuffledTvShows.slice(0, 15); + const allItems = []; + const maxLength = Math.max(selectedMovies.length, selectedTvShows.length); + for (let i = 0; i < maxLength; i++) { + if (i < selectedMovies.length) allItems.push(selectedMovies[i]); + if (i < selectedTvShows.length) allItems.push(selectedTvShows[i]); + } + return allItems; + } catch (error) { + console.error("Error fetching items:", error); + return []; + } + }; + const createSlidesForItems = async (items) => { + await Promise.all( + items.map((item) => + createSlideForItem(item, item.Type === "Movie" ? "Movie" : "TV Show") + ) + ); + }; + const createPaginationDots = () => { + const dotsContainer = document.createElement("div"); + dotsContainer.className = "dots-container"; + for (let i = 0; i < 5; i++) { + const dot = document.createElement("span"); + dot.className = "dot"; + dotsContainer.appendChild(dot); + } + const container = document.getElementById("slides-container"); + container.appendChild(dotsContainer); + }; + const showSlide = (index) => { + const slides = document.querySelectorAll(".slide"); + const dots = document.querySelectorAll(".dot"); + slides.forEach((slide, i) => { + if (i === index) { + slide.style.display = "block"; + slide.offsetHeight; + slide.style.opacity = "1"; + slide.classList.add("active"); + } else { + slide.style.opacity = "0"; + slide.classList.remove("active"); + setTimeout(() => { + slide.style.display = "none"; + }, 500); + } + }); + dots.forEach((dot, i) => { + dot.classList.toggle("active", i === index % 5); + }); + }; + const initializeSlideshow = () => { + const slides = document.querySelectorAll(".slide"); + createPaginationDots(); + const container = document.getElementById("slides-container"); + let currentSlideIndex = 0; + let focusedSlide = null; + let containerFocused = !1; + const updateCurrentSlide = (index) => { + if (isTransitioning) return; + isTransitioning = true; + currentSlideIndex = (index + slides.length) % slides.length; + showSlide(currentSlideIndex); + setTimeout(() => { + isTransitioning = false; + }, 500); }; - const createSlideElement = (item, title) => { - const itemId = item.Id; - const plot = item.Overview || "No overview available"; - const rating = item.CommunityRating; - const tomato = item.CriticRating; - const runtime = item.RunTimeTicks; - const genre = item.Genres; - const youtube = item.RemoteTrailers; - const age = item.OfficialRating; - const date = item.PremiereDate; - const season = item.ChildCount; - function createSeparator() { - const separatorHtml = - ''; - const tempDiv = document.createElement("div"); - tempDiv.innerHTML = separatorHtml; - return tempDiv.firstChild; - } - const slide = document.createElement("a"); - slide.className = "slide"; - slide.target = "_top"; - slide.rel = "noreferrer"; - slide.tabIndex = 0; - slide.style.display = "none"; - const backdrop = document.createElement("img"); - backdrop.className = "backdrop"; - backdrop.src = `${window.location.origin}/Items/${itemId}/Images/Backdrop/0`; - backdrop.alt = "Backdrop"; - const backdropOverlay = document.createElement("div"); - backdropOverlay.className = "backdrop-overlay"; - const backdropContainer = document.createElement("div"); - backdropContainer.className = "backdrop-container"; - backdropContainer.appendChild(backdrop); - backdropContainer.appendChild(backdropOverlay); - const logo = document.createElement("img"); - logo.className = "logo"; - logo.src = `${window.location.origin}/Items/${itemId}/Images/Logo`; - logo.alt = "Logo"; - const logoContainer = document.createElement("div"); - logoContainer.className = "logo-container"; - logoContainer.appendChild(logo); - const featuredContent = document.createElement("div"); - featuredContent.className = "featured-content"; - featuredContent.textContent = title; - const plotElement = document.createElement("div"); - plotElement.className = "plot"; - plotElement.textContent = plot; - truncateText(plotElement, 360); - const plotContainer = document.createElement("div"); - plotContainer.className = "plot-container"; - plotContainer.appendChild(plotElement); - const gradientOverlay = document.createElement("div"); - gradientOverlay.className = "gradient-overlay"; - const runTimeElement = document.createElement("div"); - runTimeElement.className = "runTime"; - if (season === undefined) { - const milliseconds = runtime / 10000; - const currentTime = new Date(); - const endTime = new Date(currentTime.getTime() + milliseconds); - const options = { hour: "2-digit", minute: "2-digit", hour12: !0 }; - const formattedEndTime = endTime.toLocaleTimeString([], options); - runTimeElement.textContent = `Ends at ${formattedEndTime}`; - } else { - runTimeElement.textContent = `${season} Season${season > 1 ? "s" : ""}`; - } - const ratingTest = document.createElement("div"); - ratingTest.className = "rating-value"; - const imdbLogo = document.createElement("img"); - imdbLogo.className = "imdb-logo"; - imdbLogo.src = - "https://upload.wikimedia.org/wikipedia/commons/6/69/IMDB_Logo_2016.svg"; - imdbLogo.alt = "IMDb Logo"; - imdbLogo.style.width = "30px"; - imdbLogo.style.height = "30px"; - ratingTest.appendChild(imdbLogo); - if (typeof rating === "number") { - const formattedRating = rating.toFixed(1); - ratingTest.innerHTML += `${formattedRating} ⭐`; - } else { - console.error("Rating is undefined or not a number:", rating); - ratingTest.innerHTML += `N/A ⭐`; - } - ratingTest.appendChild(createSeparator()); - const tomatoRatingDiv = document.createElement("div"); - tomatoRatingDiv.className = "tomato-rating"; - const criticRating = item.CriticRating; - const tomatoLogo = document.createElement("img"); - tomatoLogo.className = "tomato-logo"; - const criticLogo = document.createElement("img"); - criticLogo.className = "critic-logo"; - tomatoLogo.src = - "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Rotten_Tomatoes_positive_audience.svg/1920px-Rotten_Tomatoes_positive_audience.svg.png"; - let valueElement; - if (typeof criticRating === "number") { - valueElement = document.createTextNode(`${criticRating}% `); - } else { - valueElement = document.createTextNode(`N/A `); - } - if (criticRating === undefined || criticRating <= 59) { - criticLogo.src = - "https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Rotten_Tomatoes_rotten.svg/1024px-Rotten_Tomatoes_rotten.svg.png"; - criticLogo.alt = "Rotten Tomato"; - } else { - criticLogo.src = "https://i.imgur.com/iMfwDk7.png"; - criticLogo.alt = "Fresh Tomato"; - } - tomatoLogo.style.width = "15px"; - tomatoLogo.style.height = "17px"; - criticLogo.style.width = "15px"; - criticLogo.style.height = "15px"; - tomatoRatingDiv.appendChild(tomatoLogo); - tomatoRatingDiv.appendChild(valueElement); - tomatoRatingDiv.appendChild(criticLogo); - tomatoRatingDiv.appendChild(createSeparator()); - const ageRatingDiv = document.createElement("div"); - ageRatingDiv.className = "age-rating"; - if (item.OfficialRating) { - ageRatingDiv.innerHTML = `${item.OfficialRating}`; - } else { - ageRatingDiv.innerHTML = `N/A`; - } - const calender = "📅"; - const premiereDate = document.createElement("div"); - premiereDate.className = "date"; - const year = date ? new Date(date).getFullYear() : "N/A"; - premiereDate.textContent = isNaN(year) ? "N/A" : year; - ratingTest.appendChild(tomatoRatingDiv); - ratingTest.appendChild(document.createTextNode(calender)); - ratingTest.appendChild(premiereDate); - ratingTest.appendChild(createSeparator()); - ratingTest.appendChild(ageRatingDiv); - ratingTest.appendChild(createSeparator()); - ratingTest.appendChild(runTimeElement); - const genresArray = item.Genres; - function parseGenres(genresArray) { - if (genresArray && genresArray.length > 0) { - return genresArray.slice(0, 3).join(" 🔹 "); - } else { - return "No Genre Available"; - } - } - const genreElement = document.createElement("div"); - genreElement.className = "genre"; - genreElement.innerHTML = parseGenres(genresArray); - const infoContainer = document.createElement("div"); - infoContainer.className = "info-container"; - infoContainer.appendChild(ratingTest); - const playButton = document.createElement("button"); - playButton.className = "play-button"; - playButton.innerHTML = ` - - Play Now - `; - playButton.onclick = async () => { - if (!window.ApiClient) { - console.error("Jellyfin API client is not available."); - return; - } - const apiClient = window.ApiClient; - const userId = apiClient.getCurrentUserId(); - if (!userId) { - console.error("User not found."); - return; - } - try { - const sessions = await apiClient.getJSON( - apiClient.serverAddress() + "/Sessions" - ); - if (!sessions.length) { - console.error("No active Jellyfin sessions found."); - return; - } - const sessionId = sessions[0].Id; - const playbackUrl = `${apiClient.serverAddress()}/Sessions/${sessionId}/Playing?StartPositionTicks=0&PlayCommand=PlayNow&StartIndex=0&ItemIds=${itemId}&api_key=${token}`; - const response = await fetch(playbackUrl, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDevice", DeviceId="YourDeviceId", Version="YourVersion", Token="${token}"`, - }, - }); - if (response.status === 204) { - console.log("Playback started successfully."); - } else { - const errorData = await response.json(); - console.error("Failed to start playback:", errorData); - } - } catch (error) { - console.error("Error fetching sessions:", error); - } - }; - const detailButton = document.createElement("button"); - detailButton.className = "detail-button"; - detailButton.innerHTML = ` - - More Details - `; - detailButton.onclick = () => { - window.top.location.href = `/#!/details?id=${itemId}`; - }; - slide.append( - logoContainer, - backdropContainer, - gradientOverlay, - featuredContent, - plotContainer, - infoContainer, - genreElement, - playButton, - detailButton - ); - return slide; + const openActiveSlide = () => { + if (focusedSlide) { + window.location.href = focusedSlide.href; + } }; - const createSlideForItem = async (item, title) => { - const container = document.getElementById("slides-container"); - const itemId = item.Id; - const backdropUrl = `${window.location.origin}/Items/${itemId}/Images/Backdrop/0`; - const logoUrl = `${window.location.origin}/Items/${itemId}/Images/Logo`; - const [backdropExists, logoExists] = await Promise.all([ - fetch(backdropUrl, { method: "HEAD" }).then((res) => res.ok), - fetch(logoUrl, { method: "HEAD" }).then((res) => res.ok), - ]); - if (backdropExists && logoExists) { - const slideElement = createSlideElement(item, title); - container.appendChild(slideElement); - console.log(`Added slide for item ${itemId}`); - if (container.children.length === 1) { - showSlide(0); - } - } else { - console.warn(`Skipping item ${itemId}: Missing backdrop or logo.`); + if (slides.length > 0) { + showSlide(currentSlideIndex); + container.style.display = "block"; + setTimeout(() => { + setInterval(() => { + updateCurrentSlide(currentSlideIndex + 1); + }, shuffleInterval); + }, 8000); + } + slides.forEach((slide) => { + slide.addEventListener( + "focus", + () => { + focusedSlide = slide; + container.classList.remove("disable-interaction"); + }, + !0 + ); + slide.addEventListener( + "blur", + () => { + if (focusedSlide === slide) { + focusedSlide = null; + } + }, + !0 + ); + }); + document.addEventListener("keydown", (event) => { + if (containerFocused) { + switch (event.keyCode) { + case 37: + updateCurrentSlide(currentSlideIndex - 1); + break; + case 39: + updateCurrentSlide(currentSlideIndex + 1); + break; + case 13: + case 32: + openActiveSlide(); + break; } - }; - const fetchItemDetails = async (itemId) => { - const response = await fetch( - `${window.location.origin}/Users/${userId}/Items/${itemId}`, - { - headers: { - Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"`, - }, - } - ); - const item = await response.json(); - console.log("Item Title:", item.Name); - return item; - }; - const fetchItemIdsFromList = async () => { - try { - const response = await fetch(listFileName); - if (!response.ok) { - throw new Error("Failed to fetch list.txt"); - } - const text = await response.text(); - return text - .split("\n") - .map((id) => id.trim()) - .filter((id) => id); - } catch (error) { - console.error("Error fetching list.txt:", error); - return []; - } - }; - const fetchItemsFromServer = async () => { - try { - const response = await fetch( - `${window.location.origin}/Users/${userId}/Items?IncludeItemTypes=Movie,Series&Recursive=true&hasOverview=true&imageTypes=Logo,Backdrop&isPlayed=False&Limit=150`, - { - headers: { - Authorization: `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"`, - }, - } - ); - const data = await response.json(); - const items = data.Items; - const movies = items.filter((item) => item.Type === "Movie"); - const tvShows = items.filter((item) => item.Type === "Series"); - const shuffledMovies = shuffleArray(movies); - const shuffledTvShows = shuffleArray(tvShows); - const selectedMovies = shuffledMovies.slice(0, 15); - const selectedTvShows = shuffledTvShows.slice(0, 15); - const allItems = []; - const maxLength = Math.max(selectedMovies.length, selectedTvShows.length); - for (let i = 0; i < maxLength; i++) { - if (i < selectedMovies.length) allItems.push(selectedMovies[i]); - if (i < selectedTvShows.length) allItems.push(selectedTvShows[i]); - } - return allItems; - } catch (error) { - console.error("Error fetching items:", error); - return []; - } - }; - const createSlidesForItems = async (items) => { - await Promise.all( - items.map((item) => - createSlideForItem(item, item.Type === "Movie" ? "Movie" : "TV Show") - ) - ); - }; - const createPaginationDots = () => { - const dotsContainer = document.createElement("div"); - dotsContainer.className = "dots-container"; - for (let i = 0; i < 5; i++) { - const dot = document.createElement("span"); - dot.className = "dot"; - dotsContainer.appendChild(dot); - } - const container = document.getElementById("slides-container"); - container.appendChild(dotsContainer); - }; - const showSlide = (index) => { - const slides = document.querySelectorAll(".slide"); - const dots = document.querySelectorAll(".dot"); - slides.forEach((slide, i) => { - if (i === index) { - slide.style.display = "block"; - slide.offsetHeight; - slide.style.opacity = "1"; - slide.classList.add("active"); - } else { - slide.style.opacity = "0"; - slide.classList.remove("active"); - setTimeout(() => { - slide.style.display = "none"; - }, 500); - } - }); - dots.forEach((dot, i) => { - dot.classList.toggle("active", i === index % 5); - }); - }; - const initializeSlideshow = () => { - const slides = document.querySelectorAll(".slide"); - createPaginationDots(); - const container = document.getElementById("slides-container"); - let currentSlideIndex = 0; - let focusedSlide = null; - let containerFocused = !1; - const updateCurrentSlide = (index) => { - if (isTransitioning) return; - isTransitioning = true; - currentSlideIndex = (index + slides.length) % slides.length; - showSlide(currentSlideIndex); - setTimeout(() => { - isTransitioning = false; - }, 500); - }; - const openActiveSlide = () => { - if (focusedSlide) { - window.location.href = focusedSlide.href; - } - }; - if (slides.length > 0) { - showSlide(currentSlideIndex); - container.style.display = "block"; - setTimeout(() => { - setInterval(() => { - updateCurrentSlide(currentSlideIndex + 1); - }, shuffleInterval); - }, 8000); - } - slides.forEach((slide) => { - slide.addEventListener( - "focus", - () => { - focusedSlide = slide; - container.classList.remove("disable-interaction"); - }, - !0 - ); - slide.addEventListener( - "blur", - () => { - if (focusedSlide === slide) { - focusedSlide = null; - } - }, - !0 - ); - }); - document.addEventListener("keydown", (event) => { - if (containerFocused) { - switch (event.keyCode) { - case 37: - updateCurrentSlide(currentSlideIndex - 1); - break; - case 39: - updateCurrentSlide(currentSlideIndex + 1); - break; - case 13: - case 32: - openActiveSlide(); - break; - } - } - }); - const leftArrow = document.createElement("div"); - const rightArrow = document.createElement("div"); - leftArrow.classList.add("arrow", "left-arrow"); - rightArrow.classList.add("arrow", "right-arrow"); - leftArrow.innerHTML = ''; - rightArrow.innerHTML = ''; - container.appendChild(leftArrow); - container.appendChild(rightArrow); - leftArrow.addEventListener("click", () => - updateCurrentSlide(currentSlideIndex - 1) - ); - rightArrow.addEventListener("click", () => - updateCurrentSlide(currentSlideIndex + 1) - ); - container.addEventListener("focus", () => { - containerFocused = !0; - }); - container.addEventListener("blur", () => { - containerFocused = !1; - }); - }; - const initializeSlides = async () => { - const itemIds = await fetchItemIdsFromList(); - let items; - if (itemIds.length > 0) { - const itemPromises = itemIds.map((id) => fetchItemDetails(id)); - items = await Promise.all(itemPromises); - } else { - const allItems = await fetchItemsFromServer(); - const itemPromises = allItems.map((item) => fetchItemDetails(item.Id)); - items = await Promise.all(itemPromises); - } - items = shuffleArray(items); - await createSlidesForItems(items); - initializeSlideshow(); - }; - initializeSlides(); + } + }); + const leftArrow = document.createElement("div"); + const rightArrow = document.createElement("div"); + leftArrow.classList.add("arrow", "left-arrow"); + rightArrow.classList.add("arrow", "right-arrow"); + leftArrow.innerHTML = ''; + rightArrow.innerHTML = ''; + container.appendChild(leftArrow); + container.appendChild(rightArrow); + leftArrow.addEventListener("click", () => + updateCurrentSlide(currentSlideIndex - 1) + ); + rightArrow.addEventListener("click", () => + updateCurrentSlide(currentSlideIndex + 1) + ); + container.addEventListener("focus", () => { + containerFocused = !0; + }); + container.addEventListener("blur", () => { + containerFocused = !1; + }); + }; + const initializeSlides = async () => { + const itemIds = await fetchItemIdsFromList(); + let items; + if (itemIds.length > 0) { + const itemPromises = itemIds.map((id) => fetchItemDetails(id)); + items = await Promise.all(itemPromises); + } else { + const allItems = await fetchItemsFromServer(); + const itemPromises = allItems.map((item) => fetchItemDetails(item.Id)); + items = await Promise.all(itemPromises); + } + items = shuffleArray(items); + await createSlidesForItems(items); + initializeSlideshow(); + }; + initializeSlides(); }; document.addEventListener("DOMContentLoaded", () => { - document.body.addEventListener("click", (event) => { - const homeButton = event.target.matches( - ".headerHomeButton, .css-17c09up, .mainDrawer-scrollContainer > a:nth-child(2)" - ); - if (homeButton) { - event.preventDefault(); - window.location.href = "/web/index.html#/home.html"; - setTimeout(handleHomeNavigation, 300); - } - }); -}); \ No newline at end of file + document.body.addEventListener("click", (event) => { + const homeButton = event.target.matches( + ".headerHomeButton, .css-17c09up, .mainDrawer-scrollContainer > a:nth-child(2)" + ); + if (homeButton) { + event.preventDefault(); + window.location.href = "/web/index.html#/home.html"; + setTimeout(handleHomeNavigation, 300); + } + }); +});