Revert Overhaul + Spin in Performance Mode

This commit is contained in:
meowarex
2025-06-11 07:01:44 +10:00
parent 7136eda052
commit 1442f9e2cd
4 changed files with 61 additions and 269 deletions
-83
View File
@@ -1,83 +0,0 @@
# Radiant Lyrics Luna Plugin
A plugin for Luna (Tidal Desktop) that adds enhanced lyrics styling, cover art backgrounds, and UI management features.
## Features
### ✨ Lyrics Glow Effect
- Beautiful glowing effect for lyrics with custom font styling
- Can be toggled on/off in settings
### 🎨 Cover Everywhere (Performance Optimized)
- Apply spinning cover art background to the entire app
- **NEW: Ultra-performance mode** with significant optimizations:
- Reduced blur effects (max 20px in performance mode)
- Smaller image sizes (640x640 vs 1280x1280)
- Static backgrounds (no animations)
- Optimized GPU usage with hardware acceleration
- DOM element reuse to prevent memory leaks
- Throttled updates (max once per 500ms)
- Adaptive polling for track changes
### 🔧 Performance Mode Features
When enabled, Performance Mode provides:
- **Blur Reduction**: Caps blur at 20px instead of up to 200px
- **Image Optimization**: Uses 640x640 resolution instead of 1280x1280
- **Animation Disable**: Removes all CSS animations for static backgrounds
- **Memory Optimization**: Better DOM element management and cleanup
- **GPU Optimization**: Reduces `will-change` properties and backdrop-filter effects
- **Size Reduction**: Smaller background image dimensions (120vw vs 150vw for global, 80vw vs 90vw for Now Playing)
### 🎛️ UI Management
- Hide/unhide UI functionality with smooth transitions
- Player bar visibility control when UI is hidden
- Customizable background effects (blur, brightness, contrast, spin speed)
## Technical Improvements
### Performance Optimizations (Latest Update)
1. **DOM Element Reuse**: Background elements are created once and reused instead of being recreated on every track change
2. **Update Throttling**: Cover art updates are throttled to prevent excessive DOM manipulation
3. **Adaptive Polling**: Track change detection starts fast and slows down when no changes occur
4. **Hardware Acceleration**: Added GPU acceleration hints for smoother animations
5. **Memory Management**: Proper cleanup of cached DOM elements
6. **CSS Optimizations**: Better use of `transform3d` and `backface-visibility` for GPU rendering
### Normal Mode Performance Enhancements
Even without Performance Mode enabled, the plugin now includes significant optimizations:
- **Optimized Filter Order**: Reordered CSS filters for better GPU performance (`contrast``brightness``blur`)
- **CSS Custom Properties**: Dynamic filter updates use CSS variables to avoid style recalculation
- **Transform3D**: All transforms use `translate3d()` for better GPU acceleration
- **Image Caching**: LRU cache for cover art images (max 10 images) for instant loading
- **Preloading**: Smart image preloading with cache checking for smoother transitions
- **Enhanced GPU Layers**: Better use of `transform-style: preserve-3d` and `isolation: isolate`
- **Optimized Animations**: Improved keyframe animations with `cubic-bezier` timing
- **Backdrop-Filter Optimization**: More efficient backdrop-filter usage with hardware acceleration
- **Compositing Hints**: Added `contain: layout style paint` for better rendering isolation
### Browser Compatibility
- Respects `prefers-reduced-motion` for accessibility
- Optimized for modern browsers with hardware acceleration support
## Settings
- **Lyrics Glow Effect**: Toggle the enhanced lyrics styling
- **Hide UI Feature**: Enable hide/show UI functionality
- **Player Bar Visibility**: Keep player bar visible when UI is hidden
- **Cover Everywhere**: Apply cover art background to entire app
- **Performance Mode**: Enable ultra-light performance optimizations
- **Background Controls**: Adjust contrast (0-200), blur (0-200), brightness (0-100)
- **Spin Speed**: Control rotation speed (10-120 seconds per rotation)
- **Settings Affect Now Playing**: Apply background settings to Now Playing view
## Performance Recommendations
- Enable **Performance Mode** if you experience lag or high GPU usage
- Reduce **Background Blur** setting for better performance
- Use lower **Background Contrast** values on slower systems
- Consider disabling **Cover Everywhere** on very low-end systems
## Credits
- Heavily inspired by Cover-Theme by @Inrixia
- Thanks to the Luna development team for the plugin framework
+1 -1
View File
@@ -77,7 +77,7 @@ export const Settings = () => {
/> />
<LunaSwitchSetting <LunaSwitchSetting
title="Performance Mode" title="Performance Mode"
desc="Ultra-light performance mode: Reduces blur effects (max 20px), uses smaller image sizes, disables animations, and optimizes GPU usage for better performance" desc="Performance mode: Reduces blur effects (max 20px), uses smaller image sizes, and optimizes GPU usage while keeping spinning animations"
checked={performanceMode} checked={performanceMode}
onChange={(_, checked: boolean) => { onChange={(_, checked: boolean) => {
console.log("Performance Mode:", checked ? "enabled" : "disabled"); console.log("Performance Mode:", checked ? "enabled" : "disabled");
@@ -9,10 +9,9 @@
z-index: -3; z-index: -3;
pointer-events: none; pointer-events: none;
overflow: hidden; overflow: hidden;
/* Enhanced hardware acceleration */ /* Hardware acceleration */
transform: translate3d(0, 0, 0); transform: translateZ(0);
backface-visibility: hidden; backface-visibility: hidden;
perspective: 1000px;
} }
.global-spinning-black-bg { .global-spinning-black-bg {
@@ -24,35 +23,29 @@
background: #000; background: #000;
z-index: -2; z-index: -2;
pointer-events: none; pointer-events: none;
/* Force GPU layer */
transform: translateZ(0);
} }
.global-spinning-image { .global-spinning-image {
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 50%;
transform: translate3d(-50%, -50%, 0); transform: translate(-50%, -50%);
width: 150vw; width: 150vw;
height: 150vh; height: 150vh;
object-fit: cover; object-fit: cover;
z-index: -1; z-index: -1;
filter: blur(80px) brightness(0.4) contrast(1.2) saturate(1); filter: blur(80px) brightness(0.4) contrast(1.2) saturate(1);
opacity: 1; opacity: 1;
animation: spinGlobalOptimized 45s cubic-bezier(0, 0, 1, 1) infinite; animation: spinGlobal 45s linear infinite;
will-change: transform; will-change: transform;
/* Enhanced hardware acceleration for smooth animations */ /* Hardware acceleration */
transform-origin: center center; transform-origin: center center;
backface-visibility: hidden; backface-visibility: hidden;
/* Optimized compositing */
contain: layout style paint;
} }
/* Performance mode optimizations */ /* Performance mode optimizations - keep spinning but optimize other aspects */
.global-spinning-image.performance-mode-static { .global-spinning-image.performance-mode-static {
animation: none !important; /* Keep animation enabled in performance mode */
transform: translate3d(-50%, -50%, 0) !important;
will-change: auto !important;
/* Lighter blur for performance */ /* Lighter blur for performance */
filter: blur(20px) brightness(0.4) contrast(1.2) saturate(1) !important; filter: blur(20px) brightness(0.4) contrast(1.2) saturate(1) !important;
/* Smaller size for performance */ /* Smaller size for performance */
@@ -61,9 +54,7 @@
} }
.now-playing-background-image.performance-mode-static { .now-playing-background-image.performance-mode-static {
animation: none !important; /* Keep animation enabled in performance mode */
transform: translate3d(-50%, -50%, 0) !important;
will-change: auto !important;
/* Optimized size and effects for performance */ /* Optimized size and effects for performance */
width: 80vw !important; width: 80vw !important;
height: 80vh !important; height: 80vh !important;
@@ -79,38 +70,19 @@
z-index: -3; z-index: -3;
pointer-events: none; pointer-events: none;
overflow: hidden; overflow: hidden;
/* Enhanced hardware acceleration */ /* Hardware acceleration */
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
perspective: 1000px;
}
/* OPTIMIZED keyframe animations with better GPU acceleration */
@keyframes spinGlobalOptimized {
0% {
transform: translate3d(-50%, -50%, 0) rotate(0deg);
}
100% {
transform: translate3d(-50%, -50%, 0) rotate(360deg);
}
}
@keyframes spin {
0% {
transform: translate3d(-50%, -50%, 0) rotate(0deg);
}
100% {
transform: translate3d(-50%, -50%, 0) rotate(360deg);
}
}
/* Optimized backdrop-filter usage for better performance */
.optimized-backdrop {
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
/* Force GPU acceleration for backdrop filters */
transform: translateZ(0); transform: translateZ(0);
will-change: backdrop-filter; backface-visibility: hidden;
}
/* Optimized keyframe animations with GPU acceleration */
@keyframes spinGlobal {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
} }
/* Reduced motion for users who prefer it */ /* Reduced motion for users who prefer it */
@@ -118,35 +90,16 @@
.global-spinning-image, .global-spinning-image,
.now-playing-background-image { .now-playing-background-image {
animation: none !important; animation: none !important;
transform: translate3d(-50%, -50%, 0) !important; transform: translate(-50%, -50%) !important;
will-change: auto !important; will-change: auto !important;
} }
} }
/* Performance mode: disable heavy effects */ /* Performance mode: optimize effects but keep spinning */
.performance-mode .global-spinning-image, .performance-mode .global-spinning-image,
.performance-mode .now-playing-background-image { .performance-mode .now-playing-background-image {
/* Keep animations but optimize filter effects */
filter: blur(10px) brightness(0.4) contrast(1.1) !important; filter: blur(10px) brightness(0.4) contrast(1.1) !important;
animation: none !important;
will-change: auto !important;
}
/* OPTIMIZED Normal mode styles for better performance without quality loss */
body:not(.performance-mode) .global-spinning-image {
/* Use optimized filter order for better GPU performance */
filter: contrast(var(--bg-contrast, 1.2)) brightness(var(--bg-brightness, 0.4)) blur(var(--bg-blur, 80px)) saturate(1);
/* Enhanced GPU acceleration */
transform-style: preserve-3d;
/* Optimized compositing layer */
isolation: isolate;
}
body:not(.performance-mode) .now-playing-background-image {
/* Use optimized filter order */
filter: contrast(var(--bg-contrast, 1.2)) brightness(var(--bg-brightness, 0.4)) blur(var(--bg-blur, 80px));
/* Enhanced GPU acceleration */
transform-style: preserve-3d;
isolation: isolate;
} }
/* Make Notification Feed sidebar transparent */ /* Make Notification Feed sidebar transparent */
@@ -171,7 +124,7 @@ main,
background: unset !important; background: unset !important;
} }
/* OPTIMIZED sidebar and player bar with better backdrop-filter performance */ /* Make sidebar and player bar semi-transparent with optimized backdrop-filter */
[data-test="footer-player"], [data-test="footer-player"],
[data-test="main-layout-sidebar-wrapper"], [data-test="main-layout-sidebar-wrapper"],
[class^="_bar"], [class^="_bar"],
@@ -179,9 +132,6 @@ main,
background-color: rgba(0, 0, 0, 0.3) !important; background-color: rgba(0, 0, 0, 0.3) !important;
backdrop-filter: blur(10px) !important; backdrop-filter: blur(10px) !important;
-webkit-backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important;
/* Force GPU acceleration for backdrop filters */
transform: translateZ(0);
will-change: backdrop-filter;
} }
/* Performance mode: reduce backdrop blur */ /* Performance mode: reduce backdrop blur */
@@ -193,14 +143,11 @@ main,
-webkit-backdrop-filter: blur(5px) !important; -webkit-backdrop-filter: blur(5px) !important;
} }
/* OPTIMIZED Feed sidebar panel */ /* Feed sidebar panel - black tint background for readability */
[data-test="feed-sidebar"] { [data-test="feed-sidebar"] {
background-color: rgba(0, 0, 0, 0.5) !important; background-color: rgba(0, 0, 0, 0.5) !important;
backdrop-filter: blur(10px) !important; backdrop-filter: blur(10px) !important;
-webkit-backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important;
/* Enhanced GPU acceleration */
transform: translateZ(0);
will-change: backdrop-filter;
} }
/* Performance mode: reduce sidebar backdrop blur */ /* Performance mode: reduce sidebar backdrop blur */
+32 -104
View File
@@ -30,10 +30,6 @@ let currentGlobalCoverSrc: string | null = null;
let lastUpdateTime = 0; let lastUpdateTime = 0;
const UPDATE_THROTTLE = 500; // Throttle updates to max once per 500ms const UPDATE_THROTTLE = 500; // Throttle updates to max once per 500ms
// Image cache for better performance
const imageCache = new Map<string, HTMLImageElement>();
const MAX_CACHE_SIZE = 10; // Limit cache size to prevent memory leaks
// Apply lyrics glow styles if enabled // Apply lyrics glow styles if enabled
if (settings.lyricsGlowEnabled) { if (settings.lyricsGlowEnabled) {
lyricsGlowStyleTag.css = lyricsGlow; lyricsGlowStyleTag.css = lyricsGlow;
@@ -193,60 +189,30 @@ const applyGlobalSpinningBackground = (coverArtImageSrc: string): void => {
globalBackgroundContainer.appendChild(globalBackgroundImage); globalBackgroundContainer.appendChild(globalBackgroundImage);
} }
// Update image source efficiently with caching for smoother transitions // Update image source efficiently
if (globalBackgroundImage && globalBackgroundImage.src !== coverArtImageSrc) {
// Check cache first
if (imageCache.has(coverArtImageSrc)) {
globalBackgroundImage.src = coverArtImageSrc;
} else {
// Preload and cache the new image
const preloadImg = new Image();
preloadImg.onload = () => {
// Add to cache (with size limit)
if (imageCache.size >= MAX_CACHE_SIZE) {
const firstKey = imageCache.keys().next().value;
if (firstKey) {
imageCache.delete(firstKey);
}
}
imageCache.set(coverArtImageSrc, preloadImg);
if (globalBackgroundImage && globalBackgroundImage.src !== coverArtImageSrc) { if (globalBackgroundImage && globalBackgroundImage.src !== coverArtImageSrc) {
globalBackgroundImage.src = coverArtImageSrc; globalBackgroundImage.src = coverArtImageSrc;
} }
};
preloadImg.src = coverArtImageSrc;
}
}
// Apply performance-optimized settings // Apply performance-optimized settings
if (globalBackgroundImage) { if (globalBackgroundImage) {
// Performance mode optimizations // Performance mode optimizations
if (settings.performanceMode) { if (settings.performanceMode) {
// Ultra-light performance mode // Performance mode with spinning enabled
globalBackgroundImage.style.width = '120vw'; globalBackgroundImage.style.width = '120vw';
globalBackgroundImage.style.height = '120vh'; globalBackgroundImage.style.height = '120vh';
globalBackgroundImage.style.filter = `blur(${Math.min(settings.backgroundBlur, 20)}px) brightness(${settings.backgroundBrightness / 100}) contrast(${Math.min(settings.backgroundContrast, 150)}%)`; globalBackgroundImage.style.filter = `blur(${Math.min(settings.backgroundBlur, 20)}px) brightness(${settings.backgroundBrightness / 100}) contrast(${Math.min(settings.backgroundContrast, 150)}%)`;
globalBackgroundImage.style.animation = 'none'; globalBackgroundImage.style.animation = `spinGlobal ${settings.spinSpeed}s linear infinite`;
globalBackgroundImage.style.transform = 'translate(-50%, -50%)'; globalBackgroundImage.classList.remove('performance-mode-static');
globalBackgroundImage.classList.add('performance-mode-static'); globalBackgroundImage.style.willChange = 'transform';
// Remove will-change for better memory usage
globalBackgroundImage.style.willChange = 'auto';
} else { } else {
// OPTIMIZED Normal mode - Better performance while maintaining quality // Normal mode
globalBackgroundImage.style.width = '150vw'; globalBackgroundImage.style.width = '150vw';
globalBackgroundImage.style.height = '150vh'; globalBackgroundImage.style.height = '150vh';
// Use CSS custom properties for dynamic updates without style recalculation globalBackgroundImage.style.filter = `blur(${settings.backgroundBlur}px) brightness(${settings.backgroundBrightness / 100}) contrast(${settings.backgroundContrast}%)`;
globalBackgroundImage.style.setProperty('--bg-contrast', `${settings.backgroundContrast}%`); globalBackgroundImage.style.animation = `spinGlobal ${settings.spinSpeed}s linear infinite`;
globalBackgroundImage.style.setProperty('--bg-brightness', `${settings.backgroundBrightness / 100}`);
globalBackgroundImage.style.setProperty('--bg-blur', `${settings.backgroundBlur}px`);
globalBackgroundImage.style.animation = `spinGlobalOptimized ${settings.spinSpeed}s linear infinite`;
globalBackgroundImage.classList.remove('performance-mode-static'); globalBackgroundImage.classList.remove('performance-mode-static');
// Use transform3d for better GPU acceleration
globalBackgroundImage.style.willChange = 'transform'; globalBackgroundImage.style.willChange = 'transform';
globalBackgroundImage.style.transformOrigin = 'center center';
// Force GPU layer creation for smoother animations
globalBackgroundImage.style.transform = 'translate3d(-50%, -50%, 0)';
} }
} }
}; };
@@ -312,25 +278,19 @@ const updateRadiantLyricsNowPlayingBackground = function(): void {
// Performance mode optimizations // Performance mode optimizations
if (settings.performanceMode) { if (settings.performanceMode) {
// Reduce blur and effects for better performance // Reduce blur and effects for better performance, but keep spinning
blur = Math.min(blur, 20); blur = Math.min(blur, 20);
contrast = Math.min(contrast, 150); contrast = Math.min(contrast, 150);
imgElement.style.animation = 'none';
imgElement.style.transform = 'translate3d(-50%, -50%, 0)';
imgElement.classList.add('performance-mode-static');
imgElement.style.willChange = 'auto';
imgElement.style.filter = `blur(${blur}px) brightness(${brightness / 100}) contrast(${contrast}%)`;
} else {
// OPTIMIZED Normal mode updates using CSS custom properties
imgElement.style.animation = `spin ${spinSpeed}s linear infinite`; imgElement.style.animation = `spin ${spinSpeed}s linear infinite`;
imgElement.classList.remove('performance-mode-static'); imgElement.classList.remove('performance-mode-static');
imgElement.style.willChange = 'transform'; imgElement.style.willChange = 'transform';
imgElement.style.transform = 'translate3d(-50%, -50%, 0)'; } else {
// Use CSS custom properties for efficient updates imgElement.style.animation = `spin ${spinSpeed}s linear infinite`;
imgElement.style.setProperty('--bg-contrast', `${contrast}%`); imgElement.classList.remove('performance-mode-static');
imgElement.style.setProperty('--bg-brightness', `${brightness / 100}`); imgElement.style.willChange = 'transform';
imgElement.style.setProperty('--bg-blur', `${blur}px`);
} }
imgElement.style.filter = `blur(${blur}px) brightness(${brightness / 100}) contrast(${contrast}%)`;
}); });
}; };
@@ -756,62 +716,32 @@ const updateCoverArtBackground = function (method: number = 0): void {
nowPlayingBackgroundContainer.appendChild(nowPlayingGradientOverlay); nowPlayingBackgroundContainer.appendChild(nowPlayingGradientOverlay);
} }
// Update image source efficiently with caching // Update image source efficiently
if (nowPlayingBackgroundImage && nowPlayingBackgroundImage.src !== coverArtImageSrc) {
// Check cache first
if (imageCache.has(coverArtImageSrc)) {
nowPlayingBackgroundImage.src = coverArtImageSrc;
currentNowPlayingCoverSrc = coverArtImageSrc;
} else {
// Preload and cache the new image
const preloadImg = new Image();
preloadImg.onload = () => {
// Add to cache (with size limit)
if (imageCache.size >= MAX_CACHE_SIZE) {
const firstKey = imageCache.keys().next().value;
if (firstKey) {
imageCache.delete(firstKey);
}
}
imageCache.set(coverArtImageSrc, preloadImg);
if (nowPlayingBackgroundImage && nowPlayingBackgroundImage.src !== coverArtImageSrc) { if (nowPlayingBackgroundImage && nowPlayingBackgroundImage.src !== coverArtImageSrc) {
nowPlayingBackgroundImage.src = coverArtImageSrc; nowPlayingBackgroundImage.src = coverArtImageSrc;
currentNowPlayingCoverSrc = coverArtImageSrc; currentNowPlayingCoverSrc = coverArtImageSrc;
} }
};
preloadImg.src = coverArtImageSrc;
}
}
// Apply performance-optimized settings // Apply performance-optimized settings
if (nowPlayingBackgroundImage) { if (nowPlayingBackgroundImage) {
if (settings.performanceMode) { if (settings.performanceMode) {
// Ultra-light performance mode // Performance mode with spinning enabled
nowPlayingBackgroundImage.style.width = '80vw'; nowPlayingBackgroundImage.style.width = '80vw';
nowPlayingBackgroundImage.style.height = '80vh'; nowPlayingBackgroundImage.style.height = '80vh';
const blur = Math.min(settings.backgroundBlur, 20); const blur = Math.min(settings.backgroundBlur, 20);
const contrast = Math.min(settings.backgroundContrast, 150); const contrast = Math.min(settings.backgroundContrast, 150);
nowPlayingBackgroundImage.style.filter = `blur(${blur}px) brightness(${settings.backgroundBrightness / 100}) contrast(${contrast}%)`; nowPlayingBackgroundImage.style.filter = `blur(${blur}px) brightness(${settings.backgroundBrightness / 100}) contrast(${contrast}%)`;
nowPlayingBackgroundImage.style.animation = 'none';
nowPlayingBackgroundImage.style.transform = 'translate(-50%, -50%)';
nowPlayingBackgroundImage.classList.add('performance-mode-static');
nowPlayingBackgroundImage.style.willChange = 'auto';
} else {
// OPTIMIZED Normal mode - Better performance while maintaining quality
nowPlayingBackgroundImage.style.width = '90vw';
nowPlayingBackgroundImage.style.height = '90vh';
// Use CSS custom properties for efficient dynamic updates
nowPlayingBackgroundImage.style.setProperty('--bg-contrast', `${settings.backgroundContrast}%`);
nowPlayingBackgroundImage.style.setProperty('--bg-brightness', `${settings.backgroundBrightness / 100}`);
nowPlayingBackgroundImage.style.setProperty('--bg-blur', `${settings.backgroundBlur}px`);
nowPlayingBackgroundImage.style.animation = `spin ${settings.spinSpeed}s linear infinite`; nowPlayingBackgroundImage.style.animation = `spin ${settings.spinSpeed}s linear infinite`;
nowPlayingBackgroundImage.classList.remove('performance-mode-static'); nowPlayingBackgroundImage.classList.remove('performance-mode-static');
// Enhanced GPU acceleration for smoother animations
nowPlayingBackgroundImage.style.willChange = 'transform'; nowPlayingBackgroundImage.style.willChange = 'transform';
nowPlayingBackgroundImage.style.transformOrigin = 'center center'; } else {
// Force hardware acceleration with transform3d // Normal mode
nowPlayingBackgroundImage.style.transform = 'translate3d(-50%, -50%, 0)'; nowPlayingBackgroundImage.style.width = '90vw';
nowPlayingBackgroundImage.style.height = '90vh';
nowPlayingBackgroundImage.style.filter = `blur(${settings.backgroundBlur}px) brightness(${settings.backgroundBrightness / 100}) contrast(${settings.backgroundContrast}%)`;
nowPlayingBackgroundImage.style.animation = `spin ${settings.spinSpeed}s linear infinite`;
nowPlayingBackgroundImage.classList.remove('performance-mode-static');
nowPlayingBackgroundImage.style.willChange = 'transform';
} }
} }
@@ -864,16 +794,11 @@ if (settings.performanceMode) {
} }
updateCoverArtBackground(1); updateCoverArtBackground(1);
// Add cleanup to unloads // Add cleanup to unloads
unloads.add(() => { unloads.add(() => {
cleanUpDynamicArt(); cleanUpDynamicArt();
// Clean up spin animation style
const spinAnimationStyle = document.querySelector('#spinAnimation');
if (spinAnimationStyle && spinAnimationStyle.parentNode) {
spinAnimationStyle.parentNode.removeChild(spinAnimationStyle);
}
// Clean up auto-fade timeout // Clean up auto-fade timeout
if (unhideButtonAutoFadeTimeout) { if (unhideButtonAutoFadeTimeout) {
window.clearTimeout(unhideButtonAutoFadeTimeout); window.clearTimeout(unhideButtonAutoFadeTimeout);
@@ -891,9 +816,12 @@ unloads.add(() => {
unhideButton.parentNode.removeChild(unhideButton); unhideButton.parentNode.removeChild(unhideButton);
} }
// Clean up spin animations
const spinAnimationStyle = document.querySelector('#spinAnimation');
if (spinAnimationStyle && spinAnimationStyle.parentNode) {
spinAnimationStyle.parentNode.removeChild(spinAnimationStyle);
}
// Clean up global spinning backgrounds // Clean up global spinning backgrounds
cleanUpGlobalSpinningBackground(); cleanUpGlobalSpinningBackground();
// Clear image cache
imageCache.clear();
}); });