diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-25 22:48:38 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-25 22:48:38 +0300 |
| commit | 2a75af9d78b18b33c9b329886464a20c11bd7a65 (patch) | |
| tree | 2c38836a2af87716b9ce79e1412c377d7c2757ca /internal | |
| parent | d926e5f9c7a2de85589047f93626c6348ab94555 (diff) | |
Add opt-in ambient music control (task o8)
- Change ambient playback hotkey from 'm' to 'p'
- Move flash effect hotkey from 'p' to 'f'
- Update nav button labels: '<kbd>p</kbd> music' and '<kbd>f</kbd> flash'
- Update splash hint to advertise 'p' music alongside 'w' wild
- Add 'p' and 'f' hotkey support in splash and modal states
- Persist ambient enabled/disabled state in localStorage (snonuxAmbientEnabled)
- Default off; restore preference on page load without overwriting via wild mode
- Improve accessibility with explicit aria-labels and aria-pressed state sync
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/generator/templates/shared/nav.tmpl | 4 | ||||
| -rw-r--r-- | internal/generator/templates/shared/shared.js | 35 |
2 files changed, 33 insertions, 6 deletions
diff --git a/internal/generator/templates/shared/nav.tmpl b/internal/generator/templates/shared/nav.tmpl index b22ae0a..4f620a5 100644 --- a/internal/generator/templates/shared/nav.tmpl +++ b/internal/generator/templates/shared/nav.tmpl @@ -58,8 +58,8 @@ <button type="button" class="nav-fx-button" data-sno-fx="wild" aria-pressed="false" aria-label="Toggle wild mode"><kbd>w</kbd> wild</button> <button type="button" class="nav-fx-button" data-sno-fx="crt" aria-pressed="false" aria-label="Toggle CRT effect"><kbd>c</kbd> crt</button> <button type="button" class="nav-fx-button" data-sno-fx="ghost" aria-pressed="false" aria-label="Toggle ghost mode"><kbd>g</kbd> ghost</button> - <button type="button" class="nav-fx-button" data-sno-fx="ambient" aria-pressed="false" aria-label="Toggle ambient sound"><kbd>m</kbd> ambient</button> - <button type="button" class="nav-fx-button" data-sno-fx="flash" aria-label="Trigger flash effect"><kbd>p</kbd> flash</button> + <button type="button" class="nav-fx-button" data-sno-fx="ambient" aria-pressed="false" aria-label="Start or pause ambient music"><kbd>p</kbd> music</button> + <button type="button" class="nav-fx-button" data-sno-fx="flash" aria-label="Trigger flash effect"><kbd>f</kbd> flash</button> <button type="button" class="nav-fx-button" data-sno-fx="scatter" aria-label="Trigger scatter effect"><kbd>x</kbd> scatter</button> <span class="nav-hints-spacer"><kbd>t</kbd> theme</span> <select id="sno-theme-select" class="nav-fx-button" aria-label="Theme"></select> diff --git a/internal/generator/templates/shared/shared.js b/internal/generator/templates/shared/shared.js index 31c19ed..eb7e8e5 100644 --- a/internal/generator/templates/shared/shared.js +++ b/internal/generator/templates/shared/shared.js @@ -1242,10 +1242,18 @@ syncFxButtonStates(); } + function snonuxAmbientSavePreference(enabled) { + try { localStorage.setItem('snonuxAmbientEnabled', enabled ? '1' : '0'); } catch (_) {} + } + function snonuxAmbientLoadPreference() { + try { return localStorage.getItem('snonuxAmbientEnabled') === '1'; } catch (_) { return false; } + } + function toggleAmbientMode() { if (window.snonuxAmbientToggle) window.snonuxAmbientToggle(); pulseFxButton('ambient'); syncFxButtonStates(); + snonuxAmbientSavePreference(window.snonuxAmbientIsPlaying && window.snonuxAmbientIsPlaying()); } function triggerFlashEffect() { @@ -1277,13 +1285,21 @@ syncFxButtonStates(); })(); + // Restore ambient preference on load (opt-in; default off). + (function initAmbientPreference() { + if (snonuxAmbientLoadPreference() && window.snonuxAmbientStart) { + window.snonuxAmbientStart('restore'); + } + syncFxButtonStates(); + })(); + // Inject keyboard controls hint into splash overlay (all themes) (function enhanceSplashHint() { var hint = document.querySelector('#splash-overlay .splash-hint'); if (!hint || document.querySelector('#splash-overlay .splash-controls')) return; var extra = document.createElement('div'); extra.className = 'splash-controls'; - extra.innerHTML = '<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> drift \u2022 <kbd>w</kbd> wild \u2022 <kbd>m</kbd> ambient \u2022 <kbd>Enter</kbd> open'; + extra.innerHTML = '<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> drift \u2022 <kbd>w</kbd> wild \u2022 <kbd>p</kbd> music \u2022 <kbd>Enter</kbd> open'; hint.appendChild(extra); })(); @@ -1350,9 +1366,12 @@ } else if (e.key === 'w' && !e.repeat) { e.preventDefault(); toggleWildMode({ splashMode: true, kickSplash: true }); - } else if (e.key === 'm' && !e.repeat) { + } else if (e.key === 'p' && !e.repeat) { e.preventDefault(); toggleAmbientMode(); + } else if (e.key === 'f' && !e.repeat) { + e.preventDefault(); + triggerFlashEffect(); } else if (e.key === 'c' && !e.repeat) { e.preventDefault(); toggleCrtMode(); @@ -1370,6 +1389,14 @@ } if (document.getElementById('post-modal').classList.contains('active')) { if (e.key === 'Escape') { closeModal(); e.preventDefault(); } + else if (e.key === 'p' && !e.repeat) { + e.preventDefault(); + toggleAmbientMode(); + } + else if (e.key === 'f' && !e.repeat) { + e.preventDefault(); + triggerFlashEffect(); + } else if (e.key === 't' && !e.repeat) { e.preventDefault(); var pick = snonuxRandomTheme(); @@ -1416,7 +1443,7 @@ toggleWildMode(); e.preventDefault(); break; } - case 'm': { + case 'p': { toggleAmbientMode(); e.preventDefault(); break; } @@ -1426,7 +1453,7 @@ case 'g': toggleGhostMode(); e.preventDefault(); break; - case 'p': + case 'f': triggerFlashEffect(); e.preventDefault(); break; case 'x': |
