Add Reduce Visual Effects toggle for low-end devices

New toggle in Settings > Appearance disables backdrop blur (220
instances), animations (238), transitions (961), and box shadows
(804) across the entire UI via a single body class. Significantly
reduces GPU/CPU usage on low-end devices. Default off — no change
for existing users. Applied from localStorage on load to prevent
flash.
This commit is contained in:
Broque Thomas 2026-04-10 06:34:21 -07:00
parent d9e2e129b0
commit e83ee23990
3 changed files with 49 additions and 2 deletions

View file

@ -5640,6 +5640,13 @@
</label>
<small class="settings-hint">Dashboard header buttons animate as floating orbs. Hover the header to expand. Desktop only.</small>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="reduce-effects-enabled">
Reduce Visual Effects
</label>
<small class="settings-hint">Disables backdrop blur, animations, transitions, and shadows. Significantly reduces GPU/CPU usage on low-end devices.</small>
</div>
</div>
<!-- Database Settings -->

View file

@ -892,10 +892,30 @@ function initAccentColorListeners() {
applyWorkerOrbsSetting(workerOrbsCheckbox.checked);
});
}
// Reduce effects toggle — apply immediately on change
const reduceEffectsCheckbox = document.getElementById('reduce-effects-enabled');
if (reduceEffectsCheckbox) {
reduceEffectsCheckbox.addEventListener('change', () => {
applyReduceEffects(reduceEffectsCheckbox.checked);
});
}
}
// Bootstrap accent from localStorage instantly (prevents default-color flash)
function applyReduceEffects(enabled) {
if (enabled) {
document.body.classList.add('reduce-effects');
} else {
document.body.classList.remove('reduce-effects');
}
localStorage.setItem('soulsync-reduce-effects', enabled ? '1' : '0');
}
// Bootstrap accent and reduce-effects from localStorage instantly (prevents flash)
(function() {
if (localStorage.getItem('soulsync-reduce-effects') === '1') {
document.body.classList.add('reduce-effects');
}
const saved = localStorage.getItem('soulsync-accent');
if (saved) applyAccentColor(saved);
// Bootstrap particles setting from localStorage
@ -6024,6 +6044,12 @@ async function loadSettingsData() {
if (workerOrbsCheckbox) workerOrbsCheckbox.checked = workerOrbsEnabled;
applyWorkerOrbsSetting(workerOrbsEnabled);
// Reduce effects toggle
const reduceEffects = settings.ui_appearance?.reduce_effects === true; // default false
const reduceCheckbox = document.getElementById('reduce-effects-enabled');
if (reduceCheckbox) reduceCheckbox.checked = reduceEffects;
applyReduceEffects(reduceEffects);
// Populate Logging information (read-only)
document.getElementById('log-level-display').textContent = settings.logging?.level || 'INFO';
document.getElementById('log-path-display').textContent = settings.logging?.path || 'logs/app.log';
@ -7154,7 +7180,8 @@ async function saveSettings(quiet = false) {
accent_color: document.getElementById('accent-custom-color')?.value || '#1db954',
sidebar_visualizer: document.getElementById('sidebar-visualizer-type')?.value || 'bars',
particles_enabled: document.getElementById('particles-enabled')?.checked !== false,
worker_orbs_enabled: document.getElementById('worker-orbs-enabled')?.checked !== false
worker_orbs_enabled: document.getElementById('worker-orbs-enabled')?.checked !== false,
reduce_effects: document.getElementById('reduce-effects-enabled')?.checked === true
},
youtube: {
cookies_browser: document.getElementById('youtube-cookies-browser').value,

View file

@ -54967,3 +54967,16 @@ tr:hover .enhanced-track-actions-group { opacity: 1; }
font-size: 12px; flex-shrink: 0; transition: all 0.15s;
}
.blacklist-entry-remove:hover { background: rgba(239, 83, 80, 0.12); color: #ef5350; }
/* ── Reduce Visual Effects ── Disables GPU-heavy properties globally */
body.reduce-effects *,
body.reduce-effects *::before,
body.reduce-effects *::after {
animation-duration: 0s !important;
animation-delay: 0s !important;
transition-duration: 0s !important;
transition-delay: 0s !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
box-shadow: none !important;
}