diff --git a/tmp.js b/tmp.js
deleted file mode 100644
index 5da2a48..0000000
--- a/tmp.js
+++ /dev/null
@@ -1,3607 +0,0 @@
-/*
- * Jellyfin Slideshow by M0RPH3US v4.0.1
- * Modified by CodeDevMLH
- *
- * New features:
- * - optional Trailer background video support
- * - option to make video backdrops full width
- * - SponsorBlock support to skip intro/outro segments
- * - option to always show arrows
- * - option to disable/enable keyboard controls
- * - option to show/hide trailer button if trailer as backdrop is disabled (opens in a modal)
- * - option to wait for trailer to end before loading next slide
- * - option to set a maximum for the pagination dots (will turn into a counter style if exceeded)
- * - option to disable loading screen
- * - option to put collection (boxsets) IDs into the slideshow to display their items
- * - option to enable client-side settings (allow users to override settings locally on their device)
- * - option to enable seasonal content (only show items that are relevant to the current season/holiday)
- * - option to prefer local trailers (from the media item) over online sources
- * - options to sort the content by various criteria (PremiereDate, ProductionYear, Random, Original order, etc.)
- */
-
-//Core Module Configuration
-const CONFIG = {
- IMAGE_SVG: {
- freshTomato:
- '',
- rottenTomato:
- '',
- },
- shuffleInterval: 7000,
- retryInterval: 500,
- minSwipeDistance: 50,
- loadingCheckInterval: 100,
- maxPlotLength: 360,
- maxMovies: 15,
- maxTvShows: 15,
- maxItems: 500,
- preloadCount: 3,
- fadeTransitionDuration: 500,
- maxPaginationDots: 15,
- slideAnimationEnabled: true,
- enableVideoBackdrop: true,
- useSponsorBlock: true,
- preferLocalTrailers: false,
- waitForTrailerToEnd: true,
- startMuted: true,
- fullWidthVideo: true,
- enableMobileVideo: false,
- showTrailerButton: true,
- preferredVideoQuality: "Auto",
- enableKeyboardControls: true,
- alwaysShowArrows: false,
- enableCustomMediaIds: true,
- enableSeasonalContent: false,
- customMediaIds: "",
- enableLoadingScreen: true,
- enableClientSideSettings: false,
- sortBy: "Random",
- sortOrder: "Ascending",
-};
-
-// State management
-const STATE = {
- jellyfinData: {
- userId: null,
- appName: null,
- appVersion: null,
- deviceName: null,
- deviceId: null,
- accessToken: null,
- serverAddress: null,
- },
- slideshow: {
- hasInitialized: false,
- isTransitioning: false,
- isPaused: false,
- currentSlideIndex: 0,
- focusedSlide: null,
- containerFocused: false,
- slideInterval: null,
- itemIds: [],
- loadedItems: {},
- createdSlides: {},
- totalItems: 0,
- isLoading: false,
- videoPlayers: {},
- sponsorBlockInterval: null,
- isMuted: CONFIG.startMuted,
- customTrailerUrls: {},
- ytPromise: null,
- autoplayTimeouts: [],
- },
-};
-
-// Request throttling system
-const requestQueue = [];
-let isProcessingQueue = false;
-
-/**
- * Process the next request in the queue with throttling
- */
-const processNextRequest = () => {
- if (requestQueue.length === 0) {
- isProcessingQueue = false;
- return;
- }
-
- isProcessingQueue = true;
- const { url, callback } = requestQueue.shift();
-
- fetch(url)
- .then((response) => {
- if (response.ok) {
- return response;
- }
- throw new Error(`Failed to fetch: ${response.status}`);
- })
- .then(callback)
- .catch((error) => {
- console.error("Error in throttled request:", error);
- })
- .finally(() => {
- setTimeout(processNextRequest, 100);
- });
-};
-
-/**
- * Add a request to the throttled queue
- * @param {string} url - URL to fetch
- * @param {Function} callback - Callback to run on successful fetch
- */
-const addThrottledRequest = (url, callback) => {
- requestQueue.push({ url, callback });
- if (!isProcessingQueue) {
- processNextRequest();
- }
-};
-
-/**
- * Checks if the user is currently logged in
- * @returns {boolean} True if logged in, false otherwise
- */
-
-const isUserLoggedIn = () => {
- try {
- return (
- window.ApiClient &&
- window.ApiClient._currentUser &&
- window.ApiClient._currentUser.Id &&
- window.ApiClient._serverInfo &&
- window.ApiClient._serverInfo.AccessToken
- );
- } catch (error) {
- console.error("Error checking login status:", error);
- return false;
- }
-};
-
-/**
- * Initializes Jellyfin data from ApiClient
- * @param {Function} callback - Function to call once data is initialized
- */
-const initJellyfinData = (callback) => {
- if (!window.ApiClient) {
- console.warn("⏳ window.ApiClient is not available yet. Retrying...");
- setTimeout(() => initJellyfinData(callback), CONFIG.retryInterval);
- return;
- }
-
- try {
- const apiClient = window.ApiClient;
- STATE.jellyfinData = {
- userId: apiClient.getCurrentUserId() || "Not Found",
- appName: apiClient._appName || "Not Found",
- appVersion: apiClient._appVersion || "Not Found",
- deviceName: apiClient._deviceName || "Not Found",
- deviceId: apiClient._deviceId || "Not Found",
- accessToken: apiClient._serverInfo.AccessToken || "Not Found",
- serverId: apiClient._serverInfo.Id || "Not Found",
- serverAddress: apiClient._serverAddress || "Not Found",
- };
- if (callback && typeof callback === "function") {
- callback();
- }
- } catch (error) {
- console.error("Error initializing Jellyfin data:", error);
- setTimeout(() => initJellyfinData(callback), CONFIG.retryInterval);
- }
-};
-
-/**
- * Initializes localization by loading translation chunks
- */
-const initLocalization = async () => {
- try {
- const locale = await LocalizationUtils.getCurrentLocale();
- await LocalizationUtils.loadTranslations(locale);
- console.log("✅ Localization initialized");
- } catch (error) {
- console.error("Error initializing localization:", error);
- }
-};
-
-/**
- * Creates and displays loading screen
- */
-
-const initLoadingScreen = () => {
- const currentPath = window.location.href.toLowerCase().replace(window.location.origin, "");
- const isHomePage =
- currentPath.includes("/web/#/home.html") ||
- currentPath.includes("/web/#/home") ||
- currentPath.includes("/web/index.html#/home.html") ||
- currentPath === "/web/index.html#/home" ||
- currentPath.endsWith("/web/");
-
- if (!isHomePage) return;
-
- // Check LocalStorage for cached preference to avoid flash
- const cachedSetting = localStorage.getItem('mediaBarEnhanced-enableLoadingScreen');
- if (cachedSetting === 'false') {
- return;
- }
-
- const loadingDiv = document.createElement("div");
- loadingDiv.className = "bar-loading";
- loadingDiv.id = "page-loader";
- loadingDiv.innerHTML = `
-
- `;
- document.body.appendChild(loadingDiv);
-
- requestAnimationFrame(() => {
- document.querySelector(".bar-loading h1 div").style.opacity = "1";
- });
-
- const progressBar = document.getElementById("progress-bar");
- const unfilledBar = document.getElementById("unfilled-bar");
-
- let progress = 0;
- let lastIncrement = 5;
-
- const progressInterval = setInterval(() => {
- if (progress < 95) {
- lastIncrement = Math.max(0.5, lastIncrement * 0.98);
- const randomFactor = 0.8 + Math.random() * 0.4;
- const increment = lastIncrement * randomFactor;
- progress += increment;
- progress = Math.min(progress, 95);
-
- progressBar.style.width = `${progress}%`;
- unfilledBar.style.width = `${100 - progress}%`;
- }
- }, 150);
-
- const checkInterval = setInterval(() => {
- const loginFormLoaded = document.querySelector(".manualLoginForm");
- const activeTab = document.querySelector(".pageTabContent.is-active");
-
- if (loginFormLoaded) {
- finishLoading();
- return;
- }
-
- if (activeTab) {
- const tabIndex = activeTab.getAttribute("data-index");
-
- if (tabIndex === "0") {
- const homeSections = document.querySelector(".homeSectionsContainer");
- const slidesContainer = document.querySelector("#slides-container");
-
- if (homeSections && slidesContainer) {
- finishLoading();
- }
- } else {
- if (
- activeTab.children.length > 0 ||
- activeTab.innerText.trim().length > 0
- ) {
- finishLoading();
- }
- }
- }
- }, CONFIG.loadingCheckInterval);
-
- const finishLoading = () => {
- clearInterval(progressInterval);
- clearInterval(checkInterval);
- progressBar.style.transition = "width 300ms ease-in-out";
- progressBar.style.width = "100%";
- unfilledBar.style.width = "0%";
-
- progressBar.addEventListener("transitionend", () => {
- requestAnimationFrame(() => {
- const loader = document.querySelector(".bar-loading");
- if (loader) {
- loader.style.opacity = "0";
- setTimeout(() => {
- loader.remove();
- }, 300);
- }
- });
- });
- };
-};
-
-/**
- * Resets the slideshow state completely
- */
-const resetSlideshowState = () => {
- console.log("🔄 Resetting slideshow state...");
-
- if (STATE.slideshow.slideInterval) {
- STATE.slideshow.slideInterval.stop();
- }
-
- // Destroy all video players
- if (STATE.slideshow.videoPlayers) {
- Object.values(STATE.slideshow.videoPlayers).forEach(player => {
- if (player && typeof player.destroy === 'function') {
- player.destroy();
- }
- });
- STATE.slideshow.videoPlayers = {};
- }
-
- if (STATE.slideshow.sponsorBlockInterval) {
- clearInterval(STATE.slideshow.sponsorBlockInterval);
- STATE.slideshow.sponsorBlockInterval = null;
- }
-
- const container = document.getElementById("slides-container");
- if (container) {
- while (container.firstChild) {
- container.removeChild(container.firstChild);
- }
- }
-
- STATE.slideshow.hasInitialized = false;
- STATE.slideshow.isTransitioning = false;
- STATE.slideshow.isPaused = false;
- STATE.slideshow.currentSlideIndex = 0;
- STATE.slideshow.focusedSlide = null;
- STATE.slideshow.containerFocused = false;
- STATE.slideshow.slideInterval = null;
- STATE.slideshow.itemIds = [];
- STATE.slideshow.loadedItems = {};
- STATE.slideshow.createdSlides = {};
- STATE.slideshow.customTrailerUrls = {};
- STATE.slideshow.totalItems = 0;
- STATE.slideshow.isLoading = false;
-};
-
-/**
- * Watches for login status changes
- */
-const startLoginStatusWatcher = () => {
- let wasLoggedIn = false;
-
- setInterval(() => {
- const isLoggedIn = isUserLoggedIn();
-
- if (isLoggedIn !== wasLoggedIn) {
- if (isLoggedIn) {
- console.log("👤 User logged in. Initializing slideshow...");
- if (!STATE.slideshow.hasInitialized) {
- waitForApiClientAndInitialize();
- } else {
- console.log("🔄 Slideshow already initialized, skipping");
- }
- } else {
- console.log("👋 User logged out. Stopping slideshow...");
- resetSlideshowState();
- }
- wasLoggedIn = isLoggedIn;
- }
- }, 2000);
-};
-
-/**
- * Wait for ApiClient to initialize before starting the slideshow
- */
-const waitForApiClientAndInitialize = () => {
- if (window.slideshowCheckInterval) {
- clearInterval(window.slideshowCheckInterval);
- }
-
- window.slideshowCheckInterval = setInterval(() => {
- if (!window.ApiClient) {
- console.log("⏳ ApiClient not available yet. Waiting...");
- return;
- }
-
- if (
- window.ApiClient._currentUser &&
- window.ApiClient._currentUser.Id &&
- window.ApiClient._serverInfo &&
- window.ApiClient._serverInfo.AccessToken
- ) {
- console.log(
- "🔓 User is fully logged in. Starting slideshow initialization..."
- );
- clearInterval(window.slideshowCheckInterval);
-
- if (!STATE.slideshow.hasInitialized) {
- initJellyfinData(async () => {
- console.log("✅ Jellyfin API client initialized successfully");
- await initLocalization();
- await fetchPluginConfig();
- slidesInit();
- });
- } else {
- console.log("🔄 Slideshow already initialized, skipping");
- }
- } else {
- console.log(
- "🔒 Authentication incomplete. Waiting for complete login..."
- );
- }
- }, CONFIG.retryInterval);
-};
-
-const fetchPluginConfig = async () => {
- try {
- const response = await fetch('/MediaBarEnhanced/Config');
- if (response.ok) {
- const pluginConfig = await response.json();
- if (pluginConfig) {
- for (const key in pluginConfig) {
- const camelKey = key.charAt(0).toLowerCase() + key.slice(1);
- if (CONFIG.hasOwnProperty(camelKey)) {
- CONFIG[camelKey] = pluginConfig[key];
- }
- }
- STATE.slideshow.isMuted = CONFIG.startMuted;
-
- if (!CONFIG.enableLoadingScreen) {
- const loader = document.querySelector(".bar-loading");
- if (loader) {
- loader.remove();
- }
- }
-
- // Sync to LocalStorage for next load
- localStorage.setItem('mediaBarEnhanced-enableLoadingScreen', CONFIG.enableLoadingScreen);
-
- console.log("✅ MediaBarEnhanced config loaded", CONFIG);
- }
- }
- } catch (e) {
- console.error("Failed to load MediaBarEnhanced config", e);
- }
-};
-
-waitForApiClientAndInitialize();
-
-/**
- * Utility functions for slide creation and management
- */
-const SlideUtils = {
- /**
- * Sorts items based on configuration
- * @param {Array