feat: persist volume to localStorage

This commit is contained in:
2026-05-26 23:18:06 +02:00
parent 25bd91934c
commit 6450233fea

View File

@@ -1,5 +1,6 @@
import { state } from './state';
import { saveProgress } from './progress';
import { safeLocalStorage } from './storage';
export const formatTime = (seconds: number): string => {
if (!Number.isFinite(seconds) || seconds < 0) return '00:00';
@@ -78,6 +79,35 @@ export const syncVolumeUI = (): void => {
updateMuteIcons(state.video.muted || state.video.volume === 0);
};
const VOLUME_STORAGE_KEY = 'player-volume';
const parseStoredVolume = (raw: string | null): number | null => {
if (!raw) return null;
const v = Number.parseFloat(raw);
if (!Number.isFinite(v)) return null;
if (v < 0 || v > 1) return null;
return v;
};
const applyStoredVolume = (): void => {
const stored = parseStoredVolume(safeLocalStorage.getItem(VOLUME_STORAGE_KEY));
if (stored === null) return;
state.video.volume = stored;
state.video.muted = stored === 0;
if (stored > 0) state.lastKnownVolume = stored;
};
let volumeSaveTimer: number | undefined;
const schedulePersistVolume = (): void => {
window.clearTimeout(volumeSaveTimer);
volumeSaveTimer = window.setTimeout(() => {
if (!Number.isFinite(state.video.volume)) return;
const clamped = Math.max(0, Math.min(1, state.video.volume));
safeLocalStorage.setItem(VOLUME_STORAGE_KEY, clamped.toFixed(3));
}, 250);
};
interface Controls {
playPause: HTMLButtonElement | null;
muteBtn: HTMLButtonElement | null;
@@ -138,6 +168,8 @@ const updateMuteIcons = (isMuted: boolean): void => {
* Sets up video event listeners for icon sync.
*/
export const setupControls = (): void => {
applyStoredVolume();
const {
playPause,
muteBtn,
@@ -206,7 +238,10 @@ export const setupControls = (): void => {
showControls();
void saveProgress();
});
state.video.addEventListener('volumechange', syncVolumeUI);
state.video.addEventListener('volumechange', () => {
syncVolumeUI();
schedulePersistVolume();
});
// mouse move in container shows controls
state.container.addEventListener('mousemove', showControls);