diff --git a/index.html b/index.html index 6d91859..67b59d8 100644 --- a/index.html +++ b/index.html @@ -293,12 +293,7 @@ - diff --git a/js/app.js b/js/app.js index a61aff2..311d15c 100644 --- a/js/app.js +++ b/js/app.js @@ -299,6 +299,13 @@ function initializeKeyboardShortcuts(player, _audioPlayer) { }, lyrics: () => { trackKeyboardShortcut('L'); + const overlay = document.getElementById('fullscreen-cover-overlay'); + const isFullscreenOpen = overlay && getComputedStyle(overlay).display !== 'none'; + + if (isFullscreenOpen && UIRenderer.instance?.toggleFullscreenLyrics(overlay)) { + return; + } + document.getElementById('toggle-lyrics-btn')?.click(); }, search: () => { @@ -361,6 +368,19 @@ function initializeKeyboardShortcuts(player, _audioPlayer) { }); } +async function closeFullscreenOverlay() { + if (UIRenderer.instance?.dismissFullscreenCover) { + await UIRenderer.instance.dismissFullscreenCover({ animate: false }); + return; + } + + if (window.location.hash === '#fullscreen') { + window.history.back(); + } else { + UIRenderer.instance?.closeFullscreenCover(); + } +} + function showOfflineNotification() { const notification = document.createElement('div'); notification.className = 'offline-notification'; @@ -736,11 +756,7 @@ document.addEventListener('DOMContentLoaded', async () => { } else if (mode === 'cover') { const overlay = document.getElementById('fullscreen-cover-overlay'); if (overlay && overlay.style.display === 'flex') { - if (window.location.hash === '#fullscreen') { - window.history.back(); - } else { - UIRenderer.instance.closeFullscreenCover(); - } + await closeFullscreenOverlay(); } else { const nextTrack = Player.instance.getNextTrack(); UIRenderer.instance.showFullscreenCover( @@ -764,13 +780,9 @@ document.addEventListener('DOMContentLoaded', async () => { if (shareBtn) shareBtn.style.display = e.target.checked ? 'flex' : 'none'; }); - document.getElementById('close-fullscreen-cover-btn')?.addEventListener('click', () => { + document.getElementById('close-fullscreen-cover-btn')?.addEventListener('click', async () => { trackCloseFullscreenCover(); - if (window.location.hash === '#fullscreen') { - window.history.back(); - } else { - UIRenderer.instance.closeFullscreenCover(); - } + await closeFullscreenOverlay(); }); document.getElementById('fullscreen-cover-overlay')?.addEventListener('click', (e) => { @@ -785,11 +797,7 @@ document.addEventListener('DOMContentLoaded', async () => { switch (action) { case 'exit': - if (window.location.hash === '#fullscreen') { - window.history.back(); - } else { - UIRenderer.instance.closeFullscreenCover(); - } + closeFullscreenOverlay(); break; case 'hide-ui': if (overlay) { @@ -831,11 +839,7 @@ document.addEventListener('DOMContentLoaded', async () => { case 'nothing': break; default: - if (window.location.hash === '#fullscreen') { - window.history.back(); - } else { - UIRenderer.instance.closeFullscreenCover(); - } + closeFullscreenOverlay(); } }); diff --git a/js/ui.js b/js/ui.js index bd9db3f..225b908 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1336,9 +1336,7 @@ export class UIRenderer { nextTrackEl.classList.remove('animate-in'); } - const canRenderLyrics = Boolean( - lyricsManager && activeElement && lyricsPane && lyricsContent && track.type !== 'video' - ); + const canRenderLyrics = Boolean(lyricsManager && activeElement && lyricsPane && lyricsContent && track.type !== 'video'); if (canRenderLyrics) { this.fullscreenLyricsVisible = true; if (lyricsToggleBtn) lyricsToggleBtn.style.removeProperty('display'); @@ -1351,8 +1349,7 @@ export class UIRenderer { overlay.classList.add('lyrics-unavailable'); if (lyricsContent) { clearFullscreenLyricsSync(lyricsContent); - lyricsContent.innerHTML = - '
Lyrics are not available for this track.
'; + lyricsContent.innerHTML = '
Lyrics are not available for this track.
'; } } this.updateFullscreenLyricsVisibility(overlay); @@ -1364,8 +1361,15 @@ export class UIRenderer { } const mainContent = document.querySelector('.main-content'); if (mainContent instanceof HTMLElement) { - this.fullscreenMainContentOverflow = mainContent.style.overflowY; - mainContent.style.overflowY = 'hidden'; + const computedStyles = window.getComputedStyle(mainContent); + this.fullscreenMainContentOverflow = { + overflow: mainContent.style.overflow, + overflowX: mainContent.style.overflowX, + overflowY: mainContent.style.overflowY, + computedOverflowX: computedStyles.overflowX, + computedOverflowY: computedStyles.overflowY, + }; + mainContent.style.overflow = 'hidden'; } this.setupFullscreenControls(); @@ -1416,6 +1420,14 @@ export class UIRenderer { }); } + toggleFullscreenLyrics(overlay = document.getElementById('fullscreen-cover-overlay')) { + if (!overlay || overlay.classList.contains('lyrics-unavailable')) return false; + + this.fullscreenLyricsVisible = !this.fullscreenLyricsVisible; + this.updateFullscreenLyricsVisibility(overlay); + return true; + } + updateFullscreenQualityBadgePlacement(track, overlay = document.getElementById('fullscreen-cover-overlay')) { if (!track || !overlay) return; @@ -1492,12 +1504,32 @@ export class UIRenderer { if (playerBar) playerBar.style.removeProperty('display'); const mainContent = document.querySelector('.main-content'); if (mainContent instanceof HTMLElement) { - if ( - typeof this.fullscreenMainContentOverflow === 'string' && - this.fullscreenMainContentOverflow.length > 0 - ) { - mainContent.style.overflowY = this.fullscreenMainContentOverflow; + const previousOverflow = this.fullscreenMainContentOverflow; + if (previousOverflow && typeof previousOverflow === 'object') { + if (previousOverflow.overflow) { + mainContent.style.overflow = previousOverflow.overflow; + } else { + mainContent.style.removeProperty('overflow'); + } + + if (previousOverflow.overflowX) { + mainContent.style.overflowX = previousOverflow.overflowX; + } else if (previousOverflow.computedOverflowX && previousOverflow.computedOverflowX !== 'visible') { + mainContent.style.overflowX = previousOverflow.computedOverflowX; + } else { + mainContent.style.removeProperty('overflow-x'); + } + + if (previousOverflow.overflowY) { + mainContent.style.overflowY = previousOverflow.overflowY; + } else if (previousOverflow.computedOverflowY && previousOverflow.computedOverflowY !== 'visible') { + mainContent.style.overflowY = previousOverflow.computedOverflowY; + } else { + mainContent.style.removeProperty('overflow-y'); + } } else { + mainContent.style.removeProperty('overflow'); + mainContent.style.removeProperty('overflow-x'); mainContent.style.removeProperty('overflow-y'); } this.fullscreenMainContentOverflow = null; @@ -1574,7 +1606,6 @@ export class UIRenderer { } if (this.visualizer) { - this.visualizer.applyPresetOverride('kawarp'); await this.visualizer.start(); overlay.classList.add('visualizer-active'); } @@ -1905,9 +1936,7 @@ export class UIRenderer { const handleToggle = (event) => { event.preventDefault(); event.stopPropagation(); - if (overlay.classList.contains('lyrics-unavailable')) return; - this.fullscreenLyricsVisible = !this.fullscreenLyricsVisible; - this.updateFullscreenLyricsVisibility(overlay); + this.toggleFullscreenLyrics(overlay); }; toggleButtons.forEach((toggleBtn) => toggleBtn.addEventListener('click', handleToggle)); diff --git a/styles.css b/styles.css index 5f78852..9f66f1d 100644 --- a/styles.css +++ b/styles.css @@ -3924,7 +3924,6 @@ input:checked + .slider::before { /* Reserve space above taskbar / system UI so volume controls stay visible (fixes #322) */ padding-bottom: max(env(safe-area-inset-bottom), 1.5rem); - --fullscreen-drag-progress: 0; --fs-accent-rgb: var(--highlight-rgb); } @@ -3993,7 +3992,7 @@ input:checked + .slider::before { position: relative; padding: 1rem; overflow: hidden; - transform: translateY(var(--fullscreen-drag-offset, 0)); + transform: translateY(var(--fullscreen-drag-offset, 0px)); opacity: calc(1 - (var(--fullscreen-drag-progress, 0) * 0.16)); transition: transform 0.26s cubic-bezier(0.22, 1, 0.36, 1), @@ -4263,7 +4262,6 @@ input:checked + .slider::before { #fullscreen-cover-overlay.controls-idle { cursor: none; } - #fullscreen-cover-image { max-width: 55vw; max-height: 45vh; @@ -10126,7 +10124,6 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { #fullscreen-cover-overlay .fullscreen-main-view { --fs-media-column-size: minmax(340px, 430px); --fs-lyrics-column-size: minmax(520px, 760px); - width: min(1480px, 100%); height: 100%; flex: 1; @@ -10169,7 +10166,7 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { aspect-ratio: 1 / 1; border-radius: 18px; overflow: hidden; - box-shadow: 0 28px 80px rgb(0, 0, 0, 0.26); + box-shadow: 0 28px 80px rgba(0, 0, 0, 0.26); } #fullscreen-cover-overlay #fullscreen-cover-image { @@ -10336,7 +10333,7 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { #fullscreen-cover-overlay #toggle-ui-btn { top: 1.25rem; - left: calc(9.9rem + env(safe-area-inset-left)); + left: calc(1.5rem + env(safe-area-inset-left) + (40px * 3) + (0.4rem * 3)); right: auto; width: 40px; height: 40px; @@ -10530,16 +10527,16 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { --lyrics-scroll-padding-top: 18%; --lyplus-blur-amount: 0.16em; --lyplus-blur-amount-near: 0.085em; - height: 100%; width: 100%; - font-family: 'SF Pro Display', Inter, sans-serif; - + font-family: + 'SF Pro Display', + Inter, + sans-serif; --lyplus-font-size-base: clamp(34px, 3vw, 52px); --lyplus-padding-line: 8px; - --lyplus-text-color: rgb(246, 244, 239, 0.08); + --lyplus-text-color: rgba(246, 244, 239, 0.08); --lyplus-active-color: #f6f4ef; - line-height: 1.32; letter-spacing: -0.04em; font-weight: 600; @@ -10565,7 +10562,6 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { #fullscreen-cover-overlay.lyrics-hidden .fullscreen-main-view { --fs-media-column-size: minmax(420px, 760px); --fs-lyrics-column-size: minmax(0, 0fr); - width: min(760px, 100%); gap: 0; } @@ -10612,8 +10608,11 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { width: min(760px, 100%); gap: 1.25rem; align-items: stretch; - padding: calc(5rem + env(safe-area-inset-top)) clamp(1rem, 4vw, 1.75rem) - calc(1.5rem + env(safe-area-inset-bottom)); + padding: + calc(5rem + env(safe-area-inset-top)) + clamp(1rem, 4vw, 1.75rem) + calc(1.5rem + env(safe-area-inset-bottom)) + clamp(1rem, 4vw, 1.75rem); } #fullscreen-cover-overlay .fullscreen-media-column { @@ -10682,7 +10681,11 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { 'lyrics lyrics' 'controls controls'; gap: 1rem 0.9rem; - padding: calc(4.45rem + env(safe-area-inset-top)) 0 calc(0.8rem + env(safe-area-inset-bottom)); + padding: + calc(4.45rem + env(safe-area-inset-top)) + 0 + calc(0.8rem + env(safe-area-inset-bottom)) + 0; } #fullscreen-cover-overlay .fullscreen-media-column { @@ -10771,10 +10774,9 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { --lyrics-scroll-padding-top: 18%; --lyplus-font-size-base: clamp(1.75rem, 7vw, 2.35rem); --lyplus-padding-line: 6px; - --lyplus-text-color: rgb(246, 244, 239, 0.16); + --lyplus-text-color: rgba(246, 244, 239, 0.16); --lyplus-blur-amount: 0.16em; --lyplus-blur-amount-near: 0.08em; - line-height: 1.2; } @@ -10831,8 +10833,11 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { align-items: center; justify-items: center; gap: 0; - padding: calc(4.45rem + env(safe-area-inset-top)) clamp(1rem, 4vw, 1.4rem) - calc(0.8rem + env(safe-area-inset-bottom)); + padding: + calc(4.45rem + env(safe-area-inset-top)) + clamp(1rem, 4vw, 1.4rem) + calc(0.8rem + env(safe-area-inset-bottom)) + clamp(1rem, 4vw, 1.4rem); height: 100%; width: 100%; max-width: 100%;