diff --git a/plugins/radiant-lyrics-luna/src/index.ts b/plugins/radiant-lyrics-luna/src/index.ts index 63fda73..4ef5493 100644 --- a/plugins/radiant-lyrics-luna/src/index.ts +++ b/plugins/radiant-lyrics-luna/src/index.ts @@ -35,13 +35,44 @@ const updateButtonStates = function(): void { const unhideButton = document.querySelector('.unhide-ui-button') as HTMLElement; if (hideButton) { - hideButton.style.display = (settings.hideUIEnabled && !isHidden) ? 'flex' : 'none'; + if (settings.hideUIEnabled && !isHidden) { + hideButton.style.display = 'flex'; + // Small delay to ensure display is set first, then fade in + setTimeout(() => { + hideButton.style.opacity = '1'; + hideButton.style.visibility = 'visible'; + hideButton.style.pointerEvents = 'auto'; + }, 50); + } else { + // Hide UI button immediately when clicked - (couldn't get the fade to work) + hideButton.style.display = 'none'; + hideButton.style.opacity = '0'; + hideButton.style.visibility = 'hidden'; + hideButton.style.pointerEvents = 'none'; + } } if (unhideButton) { - unhideButton.style.display = (settings.hideUIEnabled && isHidden) ? 'flex' : 'none'; - // Remove the immediate hide class when button should be visible if (settings.hideUIEnabled && isHidden) { + unhideButton.style.display = 'flex'; + // Remove the hide-immediately class and let it fade in smoothly unhideButton.classList.remove('hide-immediately'); + // Small delay to ensure display is set first, then fade in - (Works for unhide button.. but not hide button.. because uhh idk) + setTimeout(() => { + unhideButton.style.opacity = '1'; + unhideButton.style.visibility = 'visible'; + unhideButton.style.pointerEvents = 'auto'; + }, 50); + } else { + // Smooth fade out for Unhide UI button + unhideButton.style.opacity = '0'; + unhideButton.style.visibility = 'hidden'; + unhideButton.style.pointerEvents = 'none'; + // Keep display: flex to maintain transitions, then hide after fade + setTimeout(() => { + if (unhideButton.style.opacity === '0') { + unhideButton.style.display = 'none'; + } + }, 500); // Wait for transition to complete } } }; @@ -89,7 +120,7 @@ const applyGlobalSpinningBackground = (coverArtImageSrc: string): void => { return; } - // Add StyleTag if not present + // Add StyleTag if not present (Don't know if this is needed.. But it's here) if (!globalSpinningBgStyleTag) { globalSpinningBgStyleTag = new StyleTag("RadiantLyrics-global-spinning-bg", unloads, coverEverywhereCss); } @@ -196,11 +227,11 @@ const toggleRadiantLyrics = function(): void { const nowPlayingContainer = document.querySelector('[class*="_nowPlayingContainer"]') as HTMLElement; if (isHidden) { - // We're currently hidden, so we're about to show UI + // currently hidden, so we're about to show UI // Add a class to immediately hide the unhide button with CSS const unhideButton = document.querySelector('.unhide-ui-button') as HTMLElement; if (unhideButton) { - unhideButton.classList.add('hide-immediately'); + unhideButton.classList.add('hide-immediately'); // actually uses fade out but.. still } // Toggle the state @@ -211,7 +242,7 @@ const toggleRadiantLyrics = function(): void { nowPlayingContainer.classList.remove('radiant-lyrics-ui-hidden'); } document.body.classList.remove('radiant-lyrics-ui-hidden'); - // Remove styles after animation completes + // Remove styles after animation completes (I think this is needed.. but not sure) setTimeout(() => { if (!isHidden) { lyricsStyleTag.remove(); @@ -227,16 +258,19 @@ const toggleRadiantLyrics = function(): void { // Toggle the state first isHidden = !isHidden; - // Apply clean view styles - updateRadiantLyricsStyles(); - // Add a class to the container to trigger CSS animations - if (nowPlayingContainer) { - nowPlayingContainer.classList.add('radiant-lyrics-ui-hidden'); - } - document.body.classList.add('radiant-lyrics-ui-hidden'); - - // Update button states immediately for hiding + // Update button states immediately to start Hide UI button fade-out updateButtonStates(); + + // Delay adding the CSS class to allow Hide UI button to fade out first - (Had issues with the fade out.. so I removed it) + setTimeout(() => { + // Apply clean view styles + updateRadiantLyricsStyles(); + // Add a class to the container to trigger CSS animations + if (nowPlayingContainer) { + nowPlayingContainer.classList.add('radiant-lyrics-ui-hidden'); + } + document.body.classList.add('radiant-lyrics-ui-hidden'); + }, 50); // Small delay to let Hide UI button start its fade transition - (Had issues with the fade out.. so I removed it) } }; @@ -266,23 +300,24 @@ const createHideUIButton = function(): void { hideUIButton.textContent = 'Hide UI'; // Style to match Tidal's buttons - hideUIButton.style.cssText = ` - background-color: var(--wave-color-solid-accent-fill); - color: black; - border: none; - border-radius: 12px; - height: 40px; - padding: 0 12px; - margin-left: 8px; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: background-color 0.2s ease; - font-size: 12px; - font-weight: 600; - white-space: nowrap; - `; + hideUIButton.style.backgroundColor = 'var(--wave-color-solid-accent-fill)'; + hideUIButton.style.color = 'black'; + hideUIButton.style.border = 'none'; + hideUIButton.style.borderRadius = '12px'; + hideUIButton.style.height = '40px'; + hideUIButton.style.padding = '0 12px'; + hideUIButton.style.marginLeft = '8px'; + hideUIButton.style.cursor = 'pointer'; + hideUIButton.style.display = 'flex'; + hideUIButton.style.alignItems = 'center'; + hideUIButton.style.justifyContent = 'center'; + hideUIButton.style.fontSize = '12px'; + hideUIButton.style.fontWeight = '600'; + hideUIButton.style.whiteSpace = 'nowrap'; + hideUIButton.style.transition = 'opacity 0.5s ease-in-out, visibility 0.5s ease-in-out, background-color 0.2s ease-in-out'; + hideUIButton.style.opacity = '0'; + hideUIButton.style.visibility = 'hidden'; + hideUIButton.style.pointerEvents = 'none'; // Add hover effect hideUIButton.addEventListener('mouseenter', () => { @@ -298,8 +333,16 @@ const createHideUIButton = function(): void { // Insert after the fullscreen button buttonContainer.insertBefore(hideUIButton, fullscreenButton.nextSibling); + // Fade in the button after a small delay + setTimeout(() => { + if (settings.hideUIEnabled && !isHidden) { + hideUIButton.style.opacity = '1'; + hideUIButton.style.visibility = 'visible'; + hideUIButton.style.pointerEvents = 'auto'; + } + }, 100); // Small delay to ensure DOM insertion is complete + //trace.msg.log("Hide UI button added next to fullscreen button"); - updateButtonStates(); }, 1000); }; @@ -319,14 +362,14 @@ const createUnhideUIButton = function(): void { return; } - // Create our unhide UI button + // Create unhide UI button const unhideUIButton = document.createElement("button"); unhideUIButton.className = 'unhide-ui-button'; unhideUIButton.setAttribute('aria-label', 'Unhide UI'); unhideUIButton.setAttribute('title', 'Unhide UI'); unhideUIButton.textContent = 'Unhide'; - // Style for top-right positioning within the Now Playing container (with safe margin) + // Style for top-right positioning within the Now Playing container (is a pain) unhideUIButton.style.cssText = ` position: absolute; top: 10px; @@ -341,7 +384,7 @@ const createUnhideUIButton = function(): void { display: none; align-items: center; justify-content: center; - transition: all 0.3s ease; + transition: all 0.5s ease-in-out; font-size: 12px; font-weight: 600; white-space: nowrap; @@ -349,6 +392,9 @@ const createUnhideUIButton = function(): void { -webkit-backdrop-filter: blur(10px); z-index: 1000; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + opacity: 0; + visibility: hidden; + pointer-events: none; `; // Add hover effect @@ -415,6 +461,15 @@ function observeForButtons(): void { if (!document.querySelector('.unhide-ui-button')) { createUnhideUIButton(); } + + // Fix unhide button visibility if UI is hidden but button isn't showing + if (isHidden) { + const unhideButton = document.querySelector('.unhide-ui-button') as HTMLElement; + if (unhideButton && (unhideButton.style.display === 'none' || unhideButton.style.opacity === '0')) { + // Force update button states to fix visibility + updateButtonStates(); + } + } }, 500); // Check every 500ms (much more efficient than MutationObserver) unloads.add(() => clearInterval(buttonCheckInterval)); diff --git a/plugins/radiant-lyrics-luna/src/styles.css b/plugins/radiant-lyrics-luna/src/styles.css index 876b480..4de0de9 100644 --- a/plugins/radiant-lyrics-luna/src/styles.css +++ b/plugins/radiant-lyrics-luna/src/styles.css @@ -9,13 +9,15 @@ transition: opacity 0.4s ease-in-out; } -/* Remove image container positioning - let it stay where it is */ +/* Tab items stay hidden - no hover functionality (if the song changes and it doesnt have lyrics.. and ya want them back.. you can unhide the UI <3) */ -.radiant-lyrics-ui-hidden [class*="_tabItems"]:hover { - opacity: 1 !important; +.radiant-lyrics-ui-hidden [data-test="header-container"]:not(:has(.hide-ui-button)) { + opacity: 0 !important; + transition: opacity 0.4s ease-in-out; } -.radiant-lyrics-ui-hidden [data-test="header-container"] { +/* Keep header visible if it contains the Hide UI button, but hide its other children */ +.radiant-lyrics-ui-hidden [data-test="header-container"]:has(.hide-ui-button) > *:not(.hide-ui-button) { opacity: 0 !important; transition: opacity 0.4s ease-in-out; } @@ -34,38 +36,50 @@ transform: none !important; } -/* Remove all layout-changing rules - only fade buttons, keep everything else in place */ - -/* Immediate hide class for unhide button */ +/* Immediate hide class for unhide button with smooth transition (had issues with the fade out.. so I removed it) */ .hide-immediately { opacity: 0 !important; visibility: hidden !important; pointer-events: none !important; - transition: none !important; } [class^="_bar"] { background-color: transparent; } -.radiant-lyrics-ui-hidden [class^="_bar"]>* { +.radiant-lyrics-ui-hidden [class^="_bar"]>*:not(.hide-ui-button) { opacity: 0 !important; + pointer-events: none !important; transition: opacity 0.4s ease-in-out; } -/* Show bar elements on hover */ -.radiant-lyrics-ui-hidden [class^="_bar"]:hover>*, -.radiant-lyrics-ui-hidden [class^="_bar"]>*:hover { - opacity: 1 !important; -} - /* Default state for bar elements */ [class^="_bar"]>* { transition: opacity 0.4s ease-in-out; } -/* Hide bottom left controls with smooth fade animation - keep space to prevent UI shifting */ -/* But exclude heart buttons in player bar */ +/* Hide search box and make it non-interactive */ +.radiant-lyrics-ui-hidden [data-test="search-input"], +.radiant-lyrics-ui-hidden [class*="_searchInput"], +.radiant-lyrics-ui-hidden [class*="searchInput"], +.radiant-lyrics-ui-hidden [class*="_search"], +.radiant-lyrics-ui-hidden [class*="search"], +.radiant-lyrics-ui-hidden input[type="search"], +.radiant-lyrics-ui-hidden input[type="text"], +.radiant-lyrics-ui-hidden input[placeholder*="Search"], +.radiant-lyrics-ui-hidden input[placeholder*="search"], +.radiant-lyrics-ui-hidden [placeholder*="Search"], +.radiant-lyrics-ui-hidden [data-test="main-layout-header"] input, +.radiant-lyrics-ui-hidden [data-test="main-layout-header"] [class*="input"], +.radiant-lyrics-ui-hidden header input, +.radiant-lyrics-ui-hidden nav input { + pointer-events: none !important; + cursor: default !important; + user-select: none !important; +} + +/* Hide bottom left controls completely - no hover functionality */ +/* Exclude heart button in player bar and make sure hidden buttons can't be clicked */ .radiant-lyrics-ui-hidden [data-test="add-to-playlist"]:not([data-test="footer-player"] *), .radiant-lyrics-ui-hidden [data-test="remove-from-playlist"]:not([data-test="footer-player"] *), .radiant-lyrics-ui-hidden [data-test="like-toggle"]:not([data-test="footer-player"] *), @@ -91,54 +105,18 @@ .radiant-lyrics-ui-hidden button[aria-label*="Like"]:not([data-test="footer-player"] *), .radiant-lyrics-ui-hidden button[aria-label*="Favorite"]:not([data-test="footer-player"] *), .radiant-lyrics-ui-hidden button[aria-label*="Heart"]:not([data-test="footer-player"] *), -/* Target buttons in bottom left area specifically */ +/* Target buttons in bottom left area specifically - (idk if this is needed.. but it's here) */ .radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] button[class*="_button"]:not(.unhide-ui-button), .radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] [class*="_iconButton"]:not(.unhide-ui-button), -/* Additional catch-all for bottom left area buttons */ +/* Additional catch-all for bottom left area buttons - (idk if this is needed.. but it's here) */ .radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] > div > div:first-child button:not(.unhide-ui-button), .radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] > div:first-child button:not(.unhide-ui-button) { opacity: 0 !important; + pointer-events: none !important; transition: opacity 0.5s ease-in-out !important; } -/* Show buttons on hover for accessibility */ -.radiant-lyrics-ui-hidden [data-test="add-to-playlist"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [data-test="remove-from-playlist"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [data-test="like-toggle"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [data-test="dislike-toggle"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [data-test="favorite-toggle"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [data-test="heart-button"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [data-test="playlist-add"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [class*="_trackActions"]:hover, -.radiant-lyrics-ui-hidden [class*="_bottomLeftControls"]:hover, -.radiant-lyrics-ui-hidden [class*="_actionButtons"]:hover, -.radiant-lyrics-ui-hidden [class*="_favoriteButton"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden [class*="_addToPlaylist"]:hover, -.radiant-lyrics-ui-hidden [class*="_lowerLeft"]:hover, -.radiant-lyrics-ui-hidden [class*="_bottomActions"]:hover, -.radiant-lyrics-ui-hidden [class*="_mediaControls"] > div:first-child:hover, -.radiant-lyrics-ui-hidden button[title*="Add to"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[title*="Remove from"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[title*="Like"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[title*="Favorite"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[title*="Heart"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[aria-label*="Add to"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[aria-label*="Remove from"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[aria-label*="Like"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[aria-label*="Favorite"]:hover:not([data-test="footer-player"] *), -.radiant-lyrics-ui-hidden button[aria-label*="Heart"]:hover:not([data-test="footer-player"] *), -/* Show buttons on hover in bottom left area */ -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] button[class*="_button"]:hover:not(.unhide-ui-button), -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] [class*="_iconButton"]:hover:not(.unhide-ui-button), -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] > div > div:first-child button:hover:not(.unhide-ui-button), -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"] > div:first-child button:hover:not(.unhide-ui-button), -/* Show buttons when hovering over their parent containers */ -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"]:hover button[class*="_button"]:not(.unhide-ui-button), -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"]:hover [class*="_iconButton"]:not(.unhide-ui-button), -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"]:hover > div > div:first-child button:not(.unhide-ui-button), -.radiant-lyrics-ui-hidden [class*="_nowPlayingContainer"]:hover > div:first-child button:not(.unhide-ui-button) { - opacity: 1 !important; -} +/* No hover functionality in Hide UI Mode - buttons stay hidden.. yea thats right, you heard me */ /* Default state for control buttons */ [data-test="add-to-playlist"], @@ -173,8 +151,52 @@ button[aria-label*="Heart"], transition: opacity 0.5s ease-in-out; } -/* Keep the Unhide button always visible with special styling */ -.unhide-ui-button { - opacity: 1 !important; - display: flex !important; -} \ No newline at end of file +/* Smooth cover art movement when UI is hidden */ +[class*="_albumImage"], +[class*="_coverArt"], +figure[class*="_albumImage"] { + transition: transform 0.6s ease-in-out; +} + +.radiant-lyrics-ui-hidden [class*="_albumImage"], +.radiant-lyrics-ui-hidden [class*="_coverArt"], +.radiant-lyrics-ui-hidden figure[class*="_albumImage"] { + transform: translateX(80px) !important; +} + +/* Smooth track info wrapper movement when UI is hidden (Arists & Track Title) */ +[class*="_infoWrapper"], +[class*="_textContainer"] { + transition: transform 0.6s ease-in-out; +} + +.radiant-lyrics-ui-hidden [class*="_infoWrapper"], +.radiant-lyrics-ui-hidden [class*="_textContainer"] { + transform: translateX(40px) !important; +} + +/* Move parent containers instead of lyrics container directly to preserve gradient fade */ +[data-test="stream-metadata"], +[class*="_rightColumn"], +[class*="_rightSide"], +[class*="_contentRight"], +[class*="_sidePanel"], +[class*="_lyricsSection"], +[class*="_lyricsWrapper"] { + transition: transform 0.6s ease-in-out; +} + +.radiant-lyrics-ui-hidden [data-test="stream-metadata"], +.radiant-lyrics-ui-hidden [class*="_rightColumn"], +.radiant-lyrics-ui-hidden [class*="_rightSide"], +.radiant-lyrics-ui-hidden [class*="_contentRight"], +.radiant-lyrics-ui-hidden [class*="_sidePanel"], +.radiant-lyrics-ui-hidden [class*="_lyricsSection"], +.radiant-lyrics-ui-hidden [class*="_lyricsWrapper"] { + transform: translateX(60px) translateY(-70px) !important; +} + +/* Hide UI button base styling - just the transition */ +.hide-ui-button { + transition: opacity 0.5s ease-in-out, visibility 0.5s ease-in-out, background-color 0.2s ease-in-out, transform 0.2s ease-in-out !important; +} \ No newline at end of file