diff --git a/js/app.js b/js/app.js index 93022c1..1e5b799 100644 --- a/js/app.js +++ b/js/app.js @@ -500,7 +500,7 @@ document.addEventListener('DOMContentLoaded', async () => { // Initialize tracker initTracker().catch(console.error); - fetchcontributors(); + await fetchcontributors(); const castBtn = document.getElementById('cast-btn'); initializeCasting(audioPlayer, castBtn); diff --git a/js/player.js b/js/player.js index f39bc67..5b779a0 100644 --- a/js/player.js +++ b/js/player.js @@ -487,7 +487,7 @@ export class Player { const timeRemaining = duration - currentTime; // Preload if we are in last 30 seconds of song - const shouldPreload = (duration > 0 && timeRemaining <= 30); + const shouldPreload = duration > 0 && timeRemaining <= 30; if (shouldPreload) { this._pendingPreload = false; @@ -537,7 +537,7 @@ export class Player { albumPeakAmplitude: trackData.info.albumPeakAmplitude, }; } - } catch(e) {} // Fail silently + } catch (_e) {} // Fail silently } this.preloadCache.set(track.id, streamInfo); @@ -546,30 +546,45 @@ export class Player { // Warm connection and pre-fetch if (!streamUrl.startsWith('blob:')) { if (streamUrl.includes('.mpd') || streamUrl.includes('.m3u8')) { - if (this.shakaInitialized && this.shakaPlayer && typeof this.shakaPlayer.preload === 'function') { + if ( + this.shakaInitialized && + this.shakaPlayer && + typeof this.shakaPlayer.preload === 'function' + ) { try { let preloadConfig = undefined; if (typeof this.shakaPlayer.getConfiguration === 'function') { preloadConfig = this.shakaPlayer.getConfiguration(); - const stats = typeof this.shakaPlayer.getStats === 'function' ? this.shakaPlayer.getStats() : null; + const stats = + typeof this.shakaPlayer.getStats === 'function' + ? this.shakaPlayer.getStats() + : null; if (stats && stats.estimatedBandwidth) { preloadConfig.abr.defaultBandwidthEstimate = stats.estimatedBandwidth; } - + // Lock the preload to the exact current audio codec to prevent ABR mismatch, // which forces the player to discard and re-fetch chunks on slow connections. preloadConfig.abr.enabled = false; try { - const variants = typeof this.shakaPlayer.getVariantTracks === 'function' ? this.shakaPlayer.getVariantTracks() : []; - const activeVariant = variants.find(v => v.active); + const variants = + typeof this.shakaPlayer.getVariantTracks === 'function' + ? this.shakaPlayer.getVariantTracks() + : []; + const activeVariant = variants.find((v) => v.active); if (activeVariant && activeVariant.audioCodec) { preloadConfig.preferredAudioCodecs = [activeVariant.audioCodec]; } - } catch (e) {} + } catch (_e) {} } - const preloadManager = await this.shakaPlayer.preload(streamUrl, null, null, preloadConfig); + const preloadManager = await this.shakaPlayer.preload( + streamUrl, + null, + null, + preloadConfig + ); streamInfo.preloadManager = preloadManager; - } catch (e) { + } catch (_e) { // Ignore preload errors, will just load fresh } } else { @@ -801,7 +816,7 @@ export class Player { this.hls.destroy(); this.hls = null; } - + // Retain the initialized Shaka player if we are remaining on the same HTMLMediaElement if (this.shakaInitialized && this.shakaPlayer) { if (this.shakaPlayer.getMediaElement() !== activeElement) { @@ -1015,14 +1030,17 @@ export class Player { } else if (streamUrl.startsWith('blob:') || streamUrl.includes('.mpd')) { await this.shakaPlayer.attach(activeElement); - const loadTarget = track.type == 'video' && this.preloadCache.has(track.id) ? - (this.preloadCache.get(track.id).preloadManager || streamUrl) : streamUrl; + const loadTarget = + track.type == 'video' && this.preloadCache.has(track.id) + ? this.preloadCache.get(track.id).preloadManager || streamUrl + : streamUrl; try { await this.shakaPlayer.load(loadTarget); } catch (e) { - console.error("PreloadManager load Error:", e); if (loadTarget !== streamUrl) await this.shakaPlayer.load(streamUrl); - else throw e; + console.error('PreloadManager load Error:', e); + if (loadTarget !== streamUrl) await this.shakaPlayer.load(streamUrl); + else throw e; } this.shakaInitialized = true; @@ -1097,8 +1115,9 @@ export class Player { await this.shakaPlayer.load(loadTarget); } } catch (e) { - console.error("PreloadManager load Error:", e); if (loadTarget !== streamUrl) await this.shakaPlayer.load(streamUrl); - else throw e; + console.error('PreloadManager load Error:', e); + if (loadTarget !== streamUrl) await this.shakaPlayer.load(streamUrl); + else throw e; } this.shakaInitialized = true; @@ -1109,7 +1128,7 @@ export class Player { this.updateAdaptiveQualityBadge(); - // Instantly trigger playback rather than explicitly waiting for 'canplay' + // Instantly trigger playback rather than explicitly waiting for 'canplay' // which delays the event loop and natively adds gap/latency await this.safePlay(activeElement); } else { diff --git a/styles.css b/styles.css index ce49775..2d3d2e4 100644 --- a/styles.css +++ b/styles.css @@ -1763,6 +1763,10 @@ input[type='search']::-webkit-search-cancel-button { .settings-tab-content { display: none; + max-width: 100%; + min-width: 0; + overflow-x: auto; + overflow-y: visible; } .settings-tab-content.active { @@ -1770,14 +1774,6 @@ input[type='search']::-webkit-search-cancel-button { animation: fade-in-slide-up 0.4s var(--ease-out-back); } -/* Prevent settings tab content from overflowing on small displays (fixes #313) */ -.settings-tab-content { - max-width: 100%; - min-width: 0; - overflow-x: auto; - overflow-y: visible; -} - .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); @@ -4301,6 +4297,7 @@ input:checked + .slider::before { justify-content: center; gap: 1rem; margin-top: 1rem; + position: relative; } .fs-volume-btn { @@ -5910,10 +5907,6 @@ img[src=''] { color: white; } -#fullscreen-cover-overlay.is-video-mode .fullscreen-volume-container { - margin-top: 0.5rem; -} - #fullscreen-cover-overlay.ui-hidden .fullscreen-main-view, #fullscreen-cover-overlay.ui-hidden .fullscreen-controls, #fullscreen-cover-overlay.ui-hidden #fullscreen-next-track, @@ -9881,10 +9874,10 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { .chat-msg { margin-bottom: 0.5rem; - animation: fadeIn 0.2s ease-out; + animation: fade-in 0.2s ease-out; } -@keyframes fadeIn { +@keyframes fade-in { from { opacity: 0; transform: translateY(5px);