Add particle background toggle & optimize accent color caching
This commit is contained in:
parent
2c6f2adce1
commit
f9bdabc0e4
3 changed files with 58 additions and 5 deletions
|
|
@ -4195,6 +4195,13 @@
|
||||||
</select>
|
</select>
|
||||||
<small style="color: #888;">Audio-reactive visualizer on the sidebar edge when music is playing</small>
|
<small style="color: #888;">Audio-reactive visualizer on the sidebar edge when music is playing</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="checkbox-label">
|
||||||
|
<input type="checkbox" id="particles-enabled" checked>
|
||||||
|
Background Particles
|
||||||
|
</label>
|
||||||
|
<small style="color: #888;">Animated particle effects behind each page. Disable to reduce GPU usage.</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Database Settings -->
|
<!-- Database Settings -->
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,15 @@
|
||||||
|
|
||||||
// ── Helpers ──
|
// ── Helpers ──
|
||||||
|
|
||||||
|
let _cachedAccent = '29, 185, 84';
|
||||||
|
let _accentCheckFrame = 0;
|
||||||
function getAccentRGB() {
|
function getAccentRGB() {
|
||||||
const s = getComputedStyle(document.documentElement).getPropertyValue('--accent-rgb').trim();
|
// Only re-read CSS variable every 60 frames (~1s) to avoid getComputedStyle overhead
|
||||||
return s || '29, 185, 84';
|
if (_accentCheckFrame++ % 60 === 0) {
|
||||||
|
const s = getComputedStyle(document.documentElement).getPropertyValue('--accent-rgb').trim();
|
||||||
|
if (s) _cachedAccent = s;
|
||||||
|
}
|
||||||
|
return _cachedAccent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift an "r, g, b" accent string by a hue offset (degrees), cached per base color
|
// Shift an "r, g, b" accent string by a hue offset (degrees), cached per base color
|
||||||
|
|
@ -2286,8 +2292,9 @@
|
||||||
stop
|
stop
|
||||||
};
|
};
|
||||||
|
|
||||||
// Auto-start for initial page
|
// Auto-start for initial page (respect particles toggle)
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
|
if (window._particlesEnabled === false) return;
|
||||||
const activePage = document.querySelector('.page.active');
|
const activePage = document.querySelector('.page.active');
|
||||||
if (activePage) {
|
if (activePage) {
|
||||||
const pageId = activePage.id.replace('-page', '');
|
const pageId = activePage.id.replace('-page', '');
|
||||||
|
|
|
||||||
|
|
@ -706,6 +706,23 @@ function applyAccentColor(hex) {
|
||||||
if (swatch) swatch.style.background = hex;
|
if (swatch) swatch.style.background = hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyParticlesSetting(enabled) {
|
||||||
|
const canvas = document.getElementById('page-particles-canvas');
|
||||||
|
if (canvas) canvas.style.display = enabled ? '' : 'none';
|
||||||
|
if (window.pageParticles) {
|
||||||
|
if (enabled) {
|
||||||
|
const activePage = document.querySelector('.page.active');
|
||||||
|
if (activePage) {
|
||||||
|
window.pageParticles.setPage(activePage.id.replace('-page', ''));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window.pageParticles.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window._particlesEnabled = enabled;
|
||||||
|
localStorage.setItem('soulsync-particles', String(enabled));
|
||||||
|
}
|
||||||
|
|
||||||
function initAccentColorListeners() {
|
function initAccentColorListeners() {
|
||||||
const presetSelect = document.getElementById('accent-preset');
|
const presetSelect = document.getElementById('accent-preset');
|
||||||
const customGroup = document.getElementById('custom-color-group');
|
const customGroup = document.getElementById('custom-color-group');
|
||||||
|
|
@ -728,12 +745,27 @@ function initAccentColorListeners() {
|
||||||
applyAccentColor(customPicker.value);
|
applyAccentColor(customPicker.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Particles toggle — apply immediately on change
|
||||||
|
const particlesCheckbox = document.getElementById('particles-enabled');
|
||||||
|
if (particlesCheckbox) {
|
||||||
|
particlesCheckbox.addEventListener('change', () => {
|
||||||
|
applyParticlesSetting(particlesCheckbox.checked);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bootstrap accent from localStorage instantly (prevents default-color flash)
|
// Bootstrap accent from localStorage instantly (prevents default-color flash)
|
||||||
(function() {
|
(function() {
|
||||||
const saved = localStorage.getItem('soulsync-accent');
|
const saved = localStorage.getItem('soulsync-accent');
|
||||||
if (saved) applyAccentColor(saved);
|
if (saved) applyAccentColor(saved);
|
||||||
|
// Bootstrap particles setting from localStorage
|
||||||
|
const particlesSaved = localStorage.getItem('soulsync-particles');
|
||||||
|
if (particlesSaved === 'false') {
|
||||||
|
window._particlesEnabled = false;
|
||||||
|
const canvas = document.getElementById('page-particles-canvas');
|
||||||
|
if (canvas) canvas.style.display = 'none';
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// ── Profile System ─────────────────────────────────────────────
|
// ── Profile System ─────────────────────────────────────────────
|
||||||
|
|
@ -1819,7 +1851,7 @@ function navigateToPage(pageId) {
|
||||||
loadPageData(pageId);
|
loadPageData(pageId);
|
||||||
|
|
||||||
// Update page background particles
|
// Update page background particles
|
||||||
if (window.pageParticles) window.pageParticles.setPage(pageId);
|
if (window.pageParticles && window._particlesEnabled !== false) window.pageParticles.setPage(pageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// REPLACE your old loadPageData function with this one:
|
// REPLACE your old loadPageData function with this one:
|
||||||
|
|
@ -4641,6 +4673,12 @@ async function loadSettingsData() {
|
||||||
if (vizSelect) vizSelect.value = vizType;
|
if (vizSelect) vizSelect.value = vizType;
|
||||||
sidebarVisualizerType = vizType;
|
sidebarVisualizerType = vizType;
|
||||||
|
|
||||||
|
// Background particles toggle
|
||||||
|
const particlesEnabled = settings.ui_appearance?.particles_enabled !== false; // default true
|
||||||
|
const particlesCheckbox = document.getElementById('particles-enabled');
|
||||||
|
if (particlesCheckbox) particlesCheckbox.checked = particlesEnabled;
|
||||||
|
applyParticlesSetting(particlesEnabled);
|
||||||
|
|
||||||
// Populate Logging information (read-only)
|
// Populate Logging information (read-only)
|
||||||
document.getElementById('log-level-display').textContent = settings.logging?.level || 'INFO';
|
document.getElementById('log-level-display').textContent = settings.logging?.level || 'INFO';
|
||||||
document.getElementById('log-path-display').textContent = settings.logging?.path || 'logs/app.log';
|
document.getElementById('log-path-display').textContent = settings.logging?.path || 'logs/app.log';
|
||||||
|
|
@ -5383,7 +5421,8 @@ async function saveSettings(quiet = false) {
|
||||||
ui_appearance: {
|
ui_appearance: {
|
||||||
accent_preset: document.getElementById('accent-preset')?.value || '#1db954',
|
accent_preset: document.getElementById('accent-preset')?.value || '#1db954',
|
||||||
accent_color: document.getElementById('accent-custom-color')?.value || '#1db954',
|
accent_color: document.getElementById('accent-custom-color')?.value || '#1db954',
|
||||||
sidebar_visualizer: document.getElementById('sidebar-visualizer-type')?.value || 'bars'
|
sidebar_visualizer: document.getElementById('sidebar-visualizer-type')?.value || 'bars',
|
||||||
|
particles_enabled: document.getElementById('particles-enabled')?.checked !== false
|
||||||
},
|
},
|
||||||
youtube: {
|
youtube: {
|
||||||
cookies_browser: document.getElementById('youtube-cookies-browser').value,
|
cookies_browser: document.getElementById('youtube-cookies-browser').value,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue