diff --git a/apps/web/src/stores/playback-store.ts b/apps/web/src/stores/playback-store.ts index a4794b7..f887a08 100644 --- a/apps/web/src/stores/playback-store.ts +++ b/apps/web/src/stores/playback-store.ts @@ -10,7 +10,7 @@ let playbackTimer: number | null = null; const startTimer = (store: any) => { if (playbackTimer) cancelAnimationFrame(playbackTimer); - + // Use requestAnimationFrame for smoother updates const updateTime = () => { const state = store(); @@ -18,14 +18,16 @@ const startTimer = (store: any) => { const now = performance.now(); const delta = (now - lastUpdate) / 1000; // Convert to seconds lastUpdate = now; - - const newTime = state.currentTime + (delta * state.speed); + + const newTime = state.currentTime + delta * state.speed; if (newTime >= state.duration) { state.pause(); } else { state.setCurrentTime(newTime); // Notify video elements to sync - window.dispatchEvent(new CustomEvent('playback-update', { detail: { time: newTime } })); + window.dispatchEvent( + new CustomEvent("playback-update", { detail: { time: newTime } }) + ); } } playbackTimer = requestAnimationFrame(updateTime); @@ -47,6 +49,8 @@ export const usePlaybackStore = create((set, get) => ({ currentTime: 0, duration: 0, volume: 1, + muted: false, + previousVolume: 1, speed: 1.0, play: () => { @@ -72,22 +76,49 @@ export const usePlaybackStore = create((set, get) => ({ const { duration } = get(); const clampedTime = Math.max(0, Math.min(duration, time)); set({ currentTime: clampedTime }); - - // Notify video elements to seek - const event = new CustomEvent('playback-seek', { detail: { time: clampedTime } }); + + const event = new CustomEvent("playback-seek", { + detail: { time: clampedTime }, + }); window.dispatchEvent(event); }, - - setVolume: (volume: number) => set({ volume: Math.max(0, Math.min(1, volume)) }), - + + setVolume: (volume: number) => + set((state) => ({ + volume: Math.max(0, Math.min(1, volume)), + muted: volume === 0, + previousVolume: volume > 0 ? volume : state.previousVolume, + })), + setSpeed: (speed: number) => { const newSpeed = Math.max(0.1, Math.min(2.0, speed)); set({ speed: newSpeed }); - - const event = new CustomEvent('playback-speed', { detail: { speed: newSpeed } }); + + const event = new CustomEvent("playback-speed", { + detail: { speed: newSpeed }, + }); window.dispatchEvent(event); }, setDuration: (duration: number) => set({ duration }), setCurrentTime: (time: number) => set({ currentTime: time }), -})); \ No newline at end of file + + mute: () => { + const { volume } = get(); + set({ muted: true, previousVolume: volume, volume: 0 }); + }, + + unmute: () => { + const { previousVolume } = get(); + set({ muted: false, volume: previousVolume ?? 1 }); + }, + + toggleMute: () => { + const { muted } = get(); + if (muted) { + get().unmute(); + } else { + get().mute(); + } + }, +}));