diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/collections/CollectionStackedTimeline.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.scss | 1 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 50 |
3 files changed, 42 insertions, 12 deletions
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 372629ddf..77ed83278 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -183,7 +183,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack @action keyEvents = (e: KeyboardEvent) => { if ( - !(e.target instanceof HTMLInputElement) && + // need to include range inputs because after dragging video time slider it becomes target element + !(e.target instanceof HTMLInputElement && !(e.target.type === "range")) && this.props.isSelected(true) ) { // if shift pressed scrub 1 second otherwise 1/10th diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index 47867b128..da29c291f 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -97,6 +97,7 @@ z-index: 2001; height: 40px; padding: 0 10px 0 7px; + transition: opacity 0.3s; .timecode-controls { display: flex; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index c8bea2a44..4c6680dcf 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -29,8 +29,8 @@ import { MarqueeAnnotator } from "../MarqueeAnnotator"; import { AnchorMenu } from "../pdf/AnchorMenu"; import { StyleProp } from "../StyleProvider"; import { FieldView, FieldViewProps } from './FieldView'; -import "./VideoBox.scss"; import { RecordingBox } from "./RecordingBox/RecordingBox"; +import "./VideoBox.scss"; const path = require('path'); /** @@ -104,6 +104,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @observable _muted: boolean = false; @observable _controlsTransform?: { X: number, Y: number }; @observable _controlsVisible: boolean = true; + @observable _scrubbing: boolean = false; @computed get links() { return DocListCast(this.dataDoc.links); } @computed get heightPercent() { return NumCast(this.layoutDoc._timelineHeightPercent, 100); } // current percent of video relative to VideoBox height @@ -148,14 +149,35 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp } } this.player && this.setPlayheadTime(0); + document.addEventListener("keydown", this.keyEvents, true); } componentWillUnmount() { this.removeCurrentlyPlaying(); this.Pause(); Object.keys(this._disposers).forEach(d => this._disposers[d]?.()); + document.removeEventListener("keydown", this.keyEvents, true); } + // handles key events, when timeline scrubs fade controls + @action + keyEvents = (e: KeyboardEvent) => { + if ( + // need to include range inputs because after dragging time slider it becomes target element + !(e.target instanceof HTMLInputElement && !(e.target.type === "range")) && + this.props.isSelected(true) + ) { + switch (e.key) { + case "ArrowLeft": + case "ArrowRight": + clearTimeout(this._controlsFadeTimer); + this._scrubbing = true; + this._controlsFadeTimer = setTimeout(action(() => this._scrubbing = false), 500); + e.stopPropagation(); + break; + } + } + } // plays video @action public Play = (update: boolean = true) => { @@ -168,11 +190,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // if presentation isn't null, call followmovements on the recording api if (this.presentation) { - console.log("presentation isn't null") + // console.log("presentation isn't null") const err = RecordingApi.Instance.playMovements(this.presentation, this.player?.currentTime || 0, this); err && console.log(err) } else { - console.log("presentation is null") + // console.log("presentation is null") } this._playing = true; @@ -262,9 +284,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // fades out controls in fullscreen after mouse stops moving @action controlsFade = (e: PointerEvent) => { e.stopPropagation(); - this._controlsVisible = true; - clearTimeout(this._controlsFadeTimer); - this._controlsFadeTimer = setTimeout(action(() => this._controlsVisible = false), 3000); + if (!this._scrubbing) { + clearTimeout(this._controlsFadeTimer); + this._controlsVisible = true; + this._controlsFadeTimer = setTimeout(action(() => this._controlsVisible = false), 3000); + } } @@ -447,10 +471,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp if (cref) { cref.onfullscreenchange = action((e) => { this._fullScreen = (document.fullscreenElement === cref); + this._controlsVisible = true; + this._scrubbing = false; + clearTimeout(this._controlsFadeTimer); if (this._fullScreen) { document.addEventListener('pointermove', this.controlsFade); - this._controlsVisible = true; - this._controlsFadeTimer = setTimeout(action(() => this._controlsVisible = false), 3000) } else { document.removeEventListener('pointermove', this.controlsFade); @@ -508,11 +533,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const field = Cast(this.dataDoc[this.fieldKey], VideoField); const interactive = CurrentUserUtils.ActiveTool !== InkTool.None || !this.props.isSelected() ? "" : "-interactive"; const classname = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive; + const opacity = this._scrubbing ? 0.5 : (this._controlsVisible ? 1 : 0); return !field ? <div key="loading">Loading</div> : <div className="videoBox-contentContainer" key="container" style={{ mixBlendMode: "multiply", cursor: this._fullScreen && !this._controlsVisible ? 'none' : 'pointer' }}> <div className={classname} ref={this.setContentRef} onPointerDown={(e) => this._fullScreen && e.stopPropagation()}> {this._fullScreen && <div className="videoBox-ui" onPointerDown={this.controlsDrag} - style={{ left: this._controlsTransform && this._controlsTransform.X, top: this._controlsTransform && this._controlsTransform.Y, visibility: this._controlsVisible ? 'visible' : 'hidden', opacity: this._controlsVisible ? 1 : 0 }}> + style={{ left: this._controlsTransform && this._controlsTransform.X, top: this._controlsTransform && this._controlsTransform.Y, visibility: this._controlsVisible || this._scrubbing ? 'visible' : 'hidden', opacity: opacity }}> {this.UIButtons} </div>} <video key="video" autoPlay={this._screenCapture} ref={this.setVideoRef} style={this._fullScreen ? this.fullScreenSize() : {}} @@ -836,8 +862,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const vidHeight = height * this.heightPercent / 100; const yPos = top + vidHeight - uiHeight - uiMargin; const xPos = uiHeight / vidHeight > 0.4 ? right + 10 : left + 10; + const opacity = this._scrubbing ? 0.5 : (this._controlsVisible ? 1 : 0); return this._fullScreen || (right - left) < 50 ? null : <div className="videoBox-ui-wrapper" style={{ clip: `rect(${boundsTop}px, 10000px, 10000px, ${boundsLeft}px)` }}> - <div className="videoBox-ui" style={{ left: xPos, top: yPos, height: uiHeight, width: width - 20, transition: this._clicking ? "top 0.5s" : "" }}> + <div className="videoBox-ui" style={{ left: xPos, top: yPos, height: uiHeight, width: width - 20, transition: this._clicking ? "top 0.5s" : "", opacity: opacity}}> {this.UIButtons} </div> </div> @@ -863,8 +890,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp <div className="timeline-slider"> <input type="range" step="0.1" min={this.timeline.clipStart} max={this.timeline.clipEnd} value={curTime} className="toolbar-slider time-progress" - onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); }} + onPointerDown={action((e: React.PointerEvent) => { e.stopPropagation(); this._scrubbing = true;})} onChange={(e: React.ChangeEvent<HTMLInputElement>) => this.setPlayheadTime(Number(e.target.value))} + onPointerUp={action((e: React.PointerEvent) => {e.stopPropagation(); this._scrubbing = false;})} /> </div> : |