diff options
author | lonkaars <loek@pipeframe.xyz> | 2021-07-26 11:44:06 +0200 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2021-07-26 11:44:06 +0200 |
commit | 9186cfc2f8da936f4d5c08515e8a2d6b1b1b1f3a (patch) | |
tree | 2b549d6405c2810e0dbb42e0e7abad568bfdfbde | |
parent | 6fa23dc86b290c87051b96caf8a352e702b82399 (diff) |
timecode input working more-ish (prevent page scroll on wheel event)
-rw-r--r-- | components/slideprops.tsx | 48 | ||||
-rw-r--r-- | components/timeinput.tsx | 44 |
2 files changed, 55 insertions, 37 deletions
diff --git a/components/slideprops.tsx b/components/slideprops.tsx index ca357b3..aba5c07 100644 --- a/components/slideprops.tsx +++ b/components/slideprops.tsx @@ -8,7 +8,7 @@ import TextField from '@material-ui/core/TextField'; import TimecodeInput from '../components/timeinput'; import { globalState, slideAPIprops } from '../pages/editor'; import { TimedVideoPlayer } from '../pages/present'; -import { anySlide, delaySlide, loopSlide } from '../timeline'; +import { anySlide, delaySlide, loopBeginSlide, loopSlide, speedChangeSlide } from '../timeline'; interface SlidePropertiesPropsType { slide: State<anySlide>; @@ -18,33 +18,35 @@ interface SlidePropertiesPropsType { select: (slides: anySlide[]) => void; } -function SlideTimestamp(props: SlidePropertiesPropsType) { - return <TimecodeInput - label='Timestamp' - value={props.slide.frame.get()} - update={(newValue: number) => { - props.slide.frame.set(newValue); - props.api.start({ frame: newValue }); - props.select([props.slide.attach(Downgraded).value]); - props.global.update.refreshLiveTimeline.value(); - }} - player={props.player} - />; -} - export default function SlideProperties(props: SlidePropertiesPropsType) { - function updateProp<slideType extends anySlide>(key: keyof slideType) { + function updateProp<slideType extends anySlide>(key: keyof slideType, springKey?: keyof slideAPIprops) { return (newValue: any) => { // TODO: better typing here props.slide[key as keyof State<anySlide>].set(newValue); + var sel = [props.slide.attach(Downgraded).value]; + if (springKey) props.api.start({ [springKey]: newValue }); + if (sel[0].type == 'loop') { + sel.push(new loopBeginSlide(sel[0] as loopSlide)); + sel.reverse(); + } + props.select(sel); props.global.update.refreshLiveTimeline.value(); }; } + function SlideTimestamp() { + return <TimecodeInput + label='Timestamp' + value={props.slide.frame.get()} + update={updateProp('frame', 'frame')} + player={props.player} + />; + } + return <div className='section'> <span className='title'>Properties</span> {{ 'default': <> - <SlideTimestamp {...props} /> + <SlideTimestamp /> </>, 'loop': <> <TextField @@ -58,18 +60,18 @@ export default function SlideProperties(props: SlidePropertiesPropsType) { <TimecodeInput label='Start timestamp' value={(props.slide as State<loopSlide>).beginFrame.get()} - update={updateProp<loopSlide>('beginFrame')} + update={updateProp<loopSlide>('beginFrame', 'begin')} player={props.player} /> <TimecodeInput label='End timestamp' value={(props.slide as State<loopSlide>).frame.get()} - update={updateProp<loopSlide>('frame')} + update={updateProp<loopSlide>('frame', 'frame')} player={props.player} /> </>, 'delay': <> - <SlideTimestamp {...props} /> + <SlideTimestamp /> <div className='spacer' /> <TextField variant='filled' @@ -82,7 +84,7 @@ export default function SlideProperties(props: SlidePropertiesPropsType) { /> </>, 'speedChange': <> - <SlideTimestamp {...props} /> + <SlideTimestamp /> <div className='spacer' /> <TextField variant='filled' @@ -90,8 +92,8 @@ export default function SlideProperties(props: SlidePropertiesPropsType) { type='number' InputLabelProps={{ shrink: true }} InputProps={{ endAdornment: <InputAdornment position='end' children='fps' /> }} - value={(props.slide as State<delaySlide>).delay.get()} - onChange={event => updateProp<delaySlide>('delay')(Number(event.target.value))} + value={(props.slide as State<speedChangeSlide>).newFramerate.get()} + onChange={event => updateProp<speedChangeSlide>('newFramerate')(Number(event.target.value))} /> <div className='spacer' /> <TextField diff --git a/components/timeinput.tsx b/components/timeinput.tsx index 86f3060..d4079f1 100644 --- a/components/timeinput.tsx +++ b/components/timeinput.tsx @@ -1,4 +1,5 @@ import TextField from '@material-ui/core/TextField'; +import { useEffect, useRef } from 'react'; import { TimedVideoPlayer } from '../pages/present'; export default function TimecodeInput(props: { @@ -8,6 +9,32 @@ export default function TimecodeInput(props: { label: string; className?: string; }) { + var ref = useRef(null); + + function handleMod(e: KeyboardEvent | WheelEvent) { + var mod = 1; + if (e.shiftKey) mod = 10; + var dir = 0; + + if (e instanceof KeyboardEvent) { + if (e.key == 'ArrowUp') dir = 1; + if (e.key == 'ArrowDown') dir = -1; + } else if (e instanceof WheelEvent) { + if (e.deltaY < 0) dir = 1; + if (e.deltaY > 0) dir = -1; + } + + var updateVal = mod * dir; + if (updateVal == 0) return; + props.update(props.value + updateVal); + } + + var stopScroll = (e: WheelEvent) => e.preventDefault(); + useEffect(() => { + (ref.current as HTMLDivElement).addEventListener('wheel', stopScroll, { passive: false }); + return () => (ref.current as HTMLDivElement)?.removeEventListener('wheel', stopScroll); + }); + return <TextField className={'time-input ' + (props.className || '')} variant='filled' @@ -15,19 +42,8 @@ export default function TimecodeInput(props: { value={props.player.frameToTimestampString(props.value, false)} spellCheck={false} onChange={e => e.preventDefault()} - onKeyDown={e => { - var mod = 1; - if (e.shiftKey) mod = 10; - - if (e.key == 'ArrowUp') props.update(props.value + mod); - if (e.key == 'ArrowDown') props.update(props.value - mod); - }} - onWheel={e => { - var mod = 1; - if (e.shiftKey) mod = 10; - - if (e.deltaY < 0) props.update(props.value + mod); - if (e.deltaY > 0) props.update(props.value - mod); - }} + onKeyDown={e => handleMod(e.nativeEvent)} + onWheel={e => handleMod(e.nativeEvent)} + ref={ref} />; } |