files: seek bar — the ball goes where the seek went and waits there; the seek is on release
Same fix as Ham Share's: a trailing change event read the bar's old position back as a drag in progress. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d1b3ef7efd
commit
1464e1f7a0
+19
-4
@@ -214,6 +214,23 @@ export default function Player({ path, sudo }: { path: string; sudo: boolean; na
|
|||||||
else v.pause()
|
else v.pause()
|
||||||
poke()
|
poke()
|
||||||
}, [poke])
|
}, [poke])
|
||||||
|
// The seek bar: while it is dragged the ball follows the finger (the input event); the seek
|
||||||
|
// itself is on release (the browser's own change event, which a click, a drag and the arrow
|
||||||
|
// keys all end with). The ball is put where the seek went at once, so it waits there while
|
||||||
|
// the piece is made rather than going back to where the film was.
|
||||||
|
const seekBar = useRef<HTMLInputElement>(null)
|
||||||
|
useEffect(() => {
|
||||||
|
const el = seekBar.current
|
||||||
|
if (!el) return
|
||||||
|
const commit = () => {
|
||||||
|
const x = Number(el.value), v = video.current
|
||||||
|
if (v && Math.abs(v.currentTime - x) > 0.05) v.currentTime = x
|
||||||
|
setTime(x)
|
||||||
|
setScrub(null)
|
||||||
|
}
|
||||||
|
el.addEventListener('change', commit)
|
||||||
|
return () => el.removeEventListener('change', commit)
|
||||||
|
})
|
||||||
const seekBy = useCallback((d: number) => {
|
const seekBy = useCallback((d: number) => {
|
||||||
const v = video.current
|
const v = video.current
|
||||||
if (!v) return
|
if (!v) return
|
||||||
@@ -314,10 +331,8 @@ export default function Player({ path, sudo }: { path: string; sudo: boolean; na
|
|||||||
|
|
||||||
<div className="vp-bottom">
|
<div className="vp-bottom">
|
||||||
<div className="vp-seek" style={{ ['--p' as string]: dur ? `${(shown / dur) * 100}%` : '0%', ['--b' as string]: dur ? `${(buffered / dur) * 100}%` : '0%' }}>
|
<div className="vp-seek" style={{ ['--p' as string]: dur ? `${(shown / dur) * 100}%` : '0%', ['--b' as string]: dur ? `${(buffered / dur) * 100}%` : '0%' }}>
|
||||||
<input type="range" min={0} max={dur || 1} step={0.1} value={shown} aria-label="Seek"
|
<input ref={seekBar} type="range" min={0} max={dur || 1} step={0.1} value={shown} aria-label="Seek"
|
||||||
onChange={(e) => { setScrub(Number(e.target.value)); poke() }}
|
onChange={(e) => { setScrub(Number(e.target.value)); poke() }} />
|
||||||
onPointerUp={(e) => { if (v) v.currentTime = Number((e.target as HTMLInputElement).value); setScrub(null) }}
|
|
||||||
onKeyUp={(e) => { if (v) v.currentTime = Number((e.target as HTMLInputElement).value); setScrub(null) }} />
|
|
||||||
</div>
|
</div>
|
||||||
<div className="vp-row">
|
<div className="vp-row">
|
||||||
<button className="vp-icon" onClick={toggle} aria-label={paused ? 'Play' : 'Pause'}>{paused ? <I d={PLAY} fill /> : <I d={PAUSE} />}</button>
|
<button className="vp-icon" onClick={toggle} aria-label={paused ? 'Play' : 'Pause'}>{paused ? <I d={PLAY} fill /> : <I d={PAUSE} />}</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user