diff options
| author | Hyteq <DerpsDer.es@gmail.com> | 2025-06-23 14:40:34 +0300 |
|---|---|---|
| committer | Hyteq <DerpsDer.es@gmail.com> | 2025-06-23 14:40:34 +0300 |
| commit | 61c172c9cce27f7f062d3fb6fb82f4b040efb35f (patch) | |
| tree | 4314b2f6ecee5e04d4dfc7ffa3f0a104182a140a /apps/web/src/stores | |
| parent | 7b6ab8f1520ee91ae3504c4594f96a05fce13e9f (diff) | |
| download | opencut-61c172c9cce27f7f062d3fb6fb82f4b040efb35f.tar.gz | |
feat: proper video playback including images and videos on the timeline
Diffstat (limited to 'apps/web/src/stores')
| -rw-r--r-- | apps/web/src/stores/playback-store.ts | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/apps/web/src/stores/playback-store.ts b/apps/web/src/stores/playback-store.ts index 7db1fb93..3c0bfdec 100644 --- a/apps/web/src/stores/playback-store.ts +++ b/apps/web/src/stores/playback-store.ts @@ -6,24 +6,67 @@ interface PlaybackStore extends PlaybackState, PlaybackControls { setCurrentTime: (time: number) => void; } +let playbackTimer: NodeJS.Timeout | null = null; + +const startTimer = (store: any) => { + if (playbackTimer) clearInterval(playbackTimer); + + playbackTimer = setInterval(() => { + const state = store(); + if (state.isPlaying && state.currentTime < state.duration) { + const newTime = state.currentTime + 0.1; + if (newTime >= state.duration) { + state.pause(); + } else { + state.setCurrentTime(newTime); + // Notify video elements to sync + window.dispatchEvent(new CustomEvent('playback-update', { detail: { time: newTime } })); + } + } + }, 100); +}; + +const stopTimer = () => { + if (playbackTimer) { + clearInterval(playbackTimer); + playbackTimer = null; + } +}; + export const usePlaybackStore = create<PlaybackStore>((set, get) => ({ isPlaying: false, currentTime: 0, duration: 0, volume: 1, - play: () => set({ isPlaying: true }), - pause: () => set({ isPlaying: false }), - toggle: () => set((state) => ({ isPlaying: !state.isPlaying })), + play: () => { + set({ isPlaying: true }); + startTimer(get); + }, + + pause: () => { + set({ isPlaying: false }); + stopTimer(); + }, + + toggle: () => { + const { isPlaying } = get(); + if (isPlaying) { + get().pause(); + } else { + get().play(); + } + }, + seek: (time: number) => { const { duration } = get(); const clampedTime = Math.max(0, Math.min(duration, time)); set({ currentTime: clampedTime }); - // Notify video element to seek - const event = new CustomEvent('playback-seek', { detail: { time: clampedTime } }); - window.dispatchEvent(event); + // Notify video elements to seek + window.dispatchEvent(new CustomEvent('playback-seek', { detail: { time: clampedTime } })); }, + setVolume: (volume: number) => set({ volume: Math.max(0, Math.min(1, volume)) }), setDuration: (duration: number) => set({ duration }), setCurrentTime: (time: number) => set({ currentTime: time }), |
