window.App = window.App || {}; // Centralized runtime state for pagination, player, and UI behavior. App.state = { currentPage: 1, perPage: 12, renderedVideoIds: new Set(), hasNextPage: true, isLoading: false, hlsPlayer: null, currentLoadController: null, errorToastTimer: null, playerMode: 'modal', playerHome: null, onFullscreenChange: null, onWebkitEndFullscreen: null, loadedVideos: [], feedOpen: false, feedMuted: true, feedActiveIndex: -1, groupCursors: null }; // Local storage keys used across modules. App.constants = { FAVORITES_KEY: 'favorites', FAVORITES_VISIBILITY_KEY: 'favoritesVisible', PREFERRED_QUALITY_KEY: 'preferredQuality' }; // Lazily injects hls.js the first time a stream actually needs it. Sessions // that only browse thumbnails, or that play native/MP4, never download it. // Resolves with window.Hls (or null if loading failed). App.ensureHls = function() { if (window.Hls) return Promise.resolve(window.Hls); if (App._hlsPromise) return App._hlsPromise; App._hlsPromise = new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/hls.js@1.5'; script.async = true; script.onload = () => resolve(window.Hls || null); script.onerror = () => { App._hlsPromise = null; reject(new Error('Failed to load hls.js')); }; document.head.appendChild(script); }); return App._hlsPromise; };