From f210e98c4d742f2eb8868aa6e8ef896f50c7b34c Mon Sep 17 00:00:00 2001 From: Sean Date: Wed, 1 May 2024 18:43:12 -0700 Subject: [PATCH] playback! --- src/App.tsx | 42 +++++++++++++++++++++++++++++++++++++----- src/global.css | 2 +- src/useNow.ts | 21 +++++++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 src/useNow.ts diff --git a/src/App.tsx b/src/App.tsx index 80acec4..3316045 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,11 @@ import { TextArea } from './components/TextArea' import { PlayIcon } from './components/PlayIcon' import { PauseIcon } from './components/PauseIcon' import { Part, strategize } from './video-strategy' +import { useNow } from './useNow' + +type PlayState = + | { playing: false; time: number } + | { playing: true; offset: number } export function App () { const nextId = useRef(0) @@ -35,10 +40,21 @@ export function App () { content: 'Today we will talk about things.' } ]) - const [playing, setPlaying] = useState(false) - const [time, setTime] = useState(0) + const [playState, setPlayState] = useState({ + playing: false, + time: 0 + }) + const now = useNow(playState.playing) const previewVideo = useMemo(() => strategize(parts), [parts]) + + const time = Math.max( + Math.min( + playState.playing ? now + playState.offset : playState.time, + previewVideo.length + ), + 0 + ) const caption = previewVideo.captions.findLast( caption => time >= caption.time ) ?? { content: '' } @@ -57,13 +73,29 @@ export function App () {
- setTime(e.currentTarget.valueAsNumber)} + onChange={e => { + const time = e.currentTarget.valueAsNumber + setPlayState( + playState.playing + ? { playing: true, offset: time - Date.now() } + : { playing: false, time } + ) + }} step='any' min={0} max={previewVideo.length} diff --git a/src/global.css b/src/global.css index 75808c1..badac90 100644 --- a/src/global.css +++ b/src/global.css @@ -66,7 +66,7 @@ button:not(:disabled) { left: 0; right: 0; bottom: 0; - margin: 10px; + margin: 15px; text-align: center; font-size: 12px; diff --git a/src/useNow.ts b/src/useNow.ts new file mode 100644 index 0000000..415ef19 --- /dev/null +++ b/src/useNow.ts @@ -0,0 +1,21 @@ +import { useEffect, useState } from 'react' + +export function useNow (enable = true) { + const [now, setNow] = useState(0) + + useEffect(() => { + let lastAnimationFrame = 0 + if (enable) { + const check = () => { + setNow(Date.now()) + lastAnimationFrame = window.requestAnimationFrame(check) + } + check() + } + return () => { + window.cancelAnimationFrame(lastAnimationFrame) + } + }, [enable]) + + return Date.now() +}