Player: N/P next-prev keys + global mute + persist volume across reloads
- Keyboard: added N (next) / P (previous) track shortcuts; 'm' mute now works whether or not the modal is open (was modal-only). Space/seek/volume/escape unchanged. - Volume persistence: volume now saved to localStorage on every change (slider + arrow keys, via npPersistVolume) and restored on load instead of always resetting to 70%. npLoadSavedVolume validates the stored 0..100 value. initializeMediaPlayer applies it + syncs both slider UIs. Frontend-only; init runs from init.js after full parse so the module consts are defined. JS syntax clean.
This commit is contained in:
parent
3c123958ca
commit
65f49ccecd
1 changed files with 36 additions and 4 deletions
|
|
@ -23,9 +23,13 @@ function initializeMediaPlayer() {
|
||||||
audioPlayer.addEventListener('loadstart', onAudioLoadStart);
|
audioPlayer.addEventListener('loadstart', onAudioLoadStart);
|
||||||
audioPlayer.addEventListener('canplay', onAudioCanPlay);
|
audioPlayer.addEventListener('canplay', onAudioCanPlay);
|
||||||
|
|
||||||
// Set initial volume
|
// Set initial volume — restore the saved level (Spotify-style), else 70%.
|
||||||
audioPlayer.volume = 0.7; // 70%
|
const _savedVol = npLoadSavedVolume();
|
||||||
if (volumeSlider) volumeSlider.value = 70;
|
const _initialVol = _savedVol === null ? 70 : _savedVol;
|
||||||
|
audioPlayer.volume = _initialVol / 100;
|
||||||
|
if (volumeSlider) volumeSlider.value = _initialVol;
|
||||||
|
// Sync the modal slider/fill too once DOM is ready.
|
||||||
|
syncVolumeUI(_initialVol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track title click handled by initExpandedPlayer's media-player click handler
|
// Track title click handled by initExpandedPlayer's media-player click handler
|
||||||
|
|
@ -313,6 +317,7 @@ async function handleStop() {
|
||||||
function handleVolumeChange(event) {
|
function handleVolumeChange(event) {
|
||||||
const volume = event.target.value;
|
const volume = event.target.value;
|
||||||
updateVolumeSliderAppearance();
|
updateVolumeSliderAppearance();
|
||||||
|
npPersistVolume(volume);
|
||||||
|
|
||||||
// Update HTML5 audio player volume
|
// Update HTML5 audio player volume
|
||||||
if (audioPlayer) {
|
if (audioPlayer) {
|
||||||
|
|
@ -2011,6 +2016,7 @@ function handleNpProgressBarChange(event) {
|
||||||
function handleNpVolumeChange(event) {
|
function handleNpVolumeChange(event) {
|
||||||
const volume = parseInt(event.target.value);
|
const volume = parseInt(event.target.value);
|
||||||
if (audioPlayer) audioPlayer.volume = volume / 100;
|
if (audioPlayer) audioPlayer.volume = volume / 100;
|
||||||
|
npPersistVolume(volume);
|
||||||
|
|
||||||
// Sync sidebar volume slider
|
// Sync sidebar volume slider
|
||||||
const sidebarVol = document.getElementById('volume-slider');
|
const sidebarVol = document.getElementById('volume-slider');
|
||||||
|
|
@ -2520,7 +2526,18 @@ function handlePlayerKeyboardShortcuts(event) {
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
case 'M':
|
case 'M':
|
||||||
if (npModalOpen) handleNpMuteToggle();
|
event.preventDefault();
|
||||||
|
handleNpMuteToggle(); // works whether or not the modal is open
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
event.preventDefault();
|
||||||
|
if (npQueue.length > 0) playNextInQueue();
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
event.preventDefault();
|
||||||
|
playPreviousInQueue();
|
||||||
break;
|
break;
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
if (npModalOpen) closeNowPlayingModal();
|
if (npModalOpen) closeNowPlayingModal();
|
||||||
|
|
@ -2542,6 +2559,21 @@ function syncVolumeUI(volumePercent) {
|
||||||
}
|
}
|
||||||
if (npVol) npVol.value = volumePercent;
|
if (npVol) npVol.value = volumePercent;
|
||||||
if (npFill) npFill.style.width = volumePercent + '%';
|
if (npFill) npFill.style.width = volumePercent + '%';
|
||||||
|
npPersistVolume(volumePercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember volume across reloads (Spotify-style). Stored 0..100.
|
||||||
|
const NP_VOLUME_STORAGE_KEY = 'soulsync-volume';
|
||||||
|
function npPersistVolume(percent) {
|
||||||
|
try { localStorage.setItem(NP_VOLUME_STORAGE_KEY, String(Math.round(percent))); } catch (e) {}
|
||||||
|
}
|
||||||
|
function npLoadSavedVolume() {
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(NP_VOLUME_STORAGE_KEY);
|
||||||
|
if (raw === null) return null;
|
||||||
|
const v = parseInt(raw, 10);
|
||||||
|
return (isFinite(v) && v >= 0 && v <= 100) ? v : null;
|
||||||
|
} catch (e) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNpAlbumArtUrl() {
|
function getNpAlbumArtUrl() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue