diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/Timeline.tsx | 275 |
1 files changed, 140 insertions, 135 deletions
diff --git a/src/client/views/nodes/Timeline.tsx b/src/client/views/nodes/Timeline.tsx index 4e3f63c57..17f3e9382 100644 --- a/src/client/views/nodes/Timeline.tsx +++ b/src/client/views/nodes/Timeline.tsx @@ -1,25 +1,18 @@ import * as React from "react"; import "./Timeline.scss"; import { CollectionSubView } from "../collections/CollectionSubView"; -import { Document, listSpec, createSchema, makeInterface, defaultSpec } from "../../../new_fields/Schema"; +import { Document, listSpec} from "../../../new_fields/Schema"; import { observer } from "mobx-react"; import { Track } from "./Track"; import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS, Reaction, IObservableObject, trace, autorun, runInAction } from "mobx"; import { Cast, NumCast, FieldValue } from "../../../new_fields/Types"; -import { SelectionManager } from "../../util/SelectionManager"; import { List } from "../../../new_fields/List"; -import { Self } from "../../../new_fields/FieldSymbols"; import { Doc, DocListCast } from "../../../new_fields/Doc"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faCircle, faPlayCircle, faBackward, faForward, faGripLines } from "@fortawesome/free-solid-svg-icons"; -import { DocumentContentsView } from "./DocumentContentsView"; +import { faPlayCircle, faBackward, faForward, faGripLines } from "@fortawesome/free-solid-svg-icons"; import { ContextMenuProps } from "../ContextMenuItem"; import { ContextMenu } from "../ContextMenu"; -import { string } from "prop-types"; -import { checkIfStateModificationsAreAllowed } from "mobx/lib/internal"; -import { SelectorContextMenu } from "../collections/ParentDocumentSelector"; import { DocumentManager } from "../../util/DocumentManager"; -import { CollectionVideoView } from "../collections/CollectionVideoView"; export interface FlyoutProps { @@ -37,20 +30,20 @@ export class Timeline extends CollectionSubView(Document) { private readonly DEFAULT_TICK_SPACING: number = 50; private readonly MIN_CONTAINER_HEIGHT: number = 205; private readonly MAX_CONTAINER_HEIGHT: number = 800; + private readonly DEFAULT_TICK_INCREMENT:number = 1000; @observable private _isMinimized = false; @observable private _tickSpacing = this.DEFAULT_TICK_SPACING; + @observable private _tickIncrement = this.DEFAULT_TICK_INCREMENT; @observable private _scrubberbox = React.createRef<HTMLDivElement>(); @observable private _scrubber = React.createRef<HTMLDivElement>(); @observable private _trackbox = React.createRef<HTMLDivElement>(); @observable private _titleContainer = React.createRef<HTMLDivElement>(); @observable private _timelineContainer = React.createRef<HTMLDivElement>(); - @observable private _timeInput = React.createRef<HTMLInputElement>(); - @observable private _durationInput = React.createRef<HTMLInputElement>(); - @observable private _fadeInInput = React.createRef<HTMLInputElement>(); - @observable private _fadeOutInput = React.createRef<HTMLInputElement>(); + @observable private _timelineWrapper = React.createRef<HTMLDivElement>(); + @observable private _infoContainer = React.createRef<HTMLDivElement>(); @observable private _currentBarX: number = 0; @@ -59,80 +52,38 @@ export class Timeline extends CollectionSubView(Document) { @observable private _boxLength: number = 0; @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT; @observable private _time = 100000; //DEFAULT - - @observable private _infoContainer = React.createRef<HTMLDivElement>(); @observable private _ticks: number[] = []; + @observable private flyoutInfo:FlyoutProps = {x: 0, y: 0, display: "block", regiondata: new Doc(), regions: new List<Doc>()}; - @observable private flyoutInfo: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>() }; - - private block = false; @computed private get children(){ return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>; } - componentWillMount() { - console.log(this._ticks.length); - runInAction(() => { - //check if this is a video frame - for (let i = 0; i < this._time;) { - this._ticks.push(i); - i += 1000; - } - }); - } componentDidMount() { - this.initialize(); - - console.log(DocumentManager.Instance.getDocumentView(this.props.Document)); - console.log(toJS(this.props.Document.data)); - } - - - - componentDidUpdate() { - runInAction(() => this._time = 100001); - } - - componentWillUnmount() { - document.removeEventListener("pointerdown", this.closeFlyout); - } - initialize = action(() => { - let scrubber = this._scrubberbox.current!; - this._boxLength = scrubber.getBoundingClientRect().width; - - reaction(() => this._time, time => { - let infoContainer = this._infoContainer.current!; - let trackbox = this._trackbox.current!; - this._boxLength = infoContainer.scrollWidth; - trackbox.style.width = `${this._boxLength}`; + runInAction(() => { + reaction(() => { + this._time; + }, () =>{ + this._ticks = []; + for (let i = 0; i < this._time;) { + this._ticks.push(i); + i += this._tickIncrement; + } + let trackbox = this._trackbox.current!; + this._boxLength = this._tickIncrement / 1000 * this._tickSpacing * this._ticks.length; + trackbox.style.width = `${this._boxLength}`; + }, {fireImmediately: true}); }); - - document.addEventListener("pointerdown", this.closeFlyout); - }); + } @action changeCurrentBarX = (x: number) => { this._currentBarX = x; } - @action - onFlyoutDown = (e: React.PointerEvent) => { - this.flyoutInfo.display = "block"; - this.block = true; - } - - @action - closeFlyout = (e: PointerEvent) => { - if (this.block) { - this.block = false; - return; - } - this.flyoutInfo.display = "none"; - } - - + //for playing @action onPlay = async (e: React.MouseEvent) => { @@ -296,13 +247,7 @@ export class Timeline extends CollectionSubView(Document) { return `${min}:${sec}`; } - @action - getFlyout = (props: FlyoutProps) => { - for (const [k, v] of Object.entries(props)) { - (this.flyoutInfo as any)[k] = v; - } - } timelineContextMenu = (e: React.MouseEvent): void => { let subitems: ContextMenuProps[] = []; @@ -312,37 +257,127 @@ export class Timeline extends CollectionSubView(Document) { timelineContainer.style.left = "0px"; timelineContainer.style.top = "0px"; timelineContainer.style.transition = "none"; - - }), icon: "pinterest" }); subitems.push({ description: "Pin to Bottom", event: action(() => { - console.log(timelineContainer.getBoundingClientRect().bottom); timelineContainer.style.transform = `translate(0px, ${e.pageY - this._containerHeight}px)`; }), icon: "pinterest" }); ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems }); } + + private setPlacementHighlight = (x = 0, y = 0, height:(string| number) = 0, width:(string | number) = 0):JSX.Element => { + return <div className="placement-highlight" style ={{height: `${height}px`, width: `${width}px`, transform:`translate(${x}px, ${y}px)`}}></div>; + } + + @action + getFlyout = (props: FlyoutProps) => { + for (const [k, v] of Object.entries(props)) { + (this.flyoutInfo as any)[k] = v; + } + } + + render() { + return ( + <div style={{left:"0px", top: "0px", position:"absolute", width:"100%", transform:"translate(0px, 0px)"}} ref = {this._timelineWrapper}> + {this.setPlacementHighlight(0,0,300,400)} + <button className="minimize" onClick={this.minimize}>Minimize</button> + <div className="timeline-container" style={{ height: `${this._containerHeight}px`, left:"0px", top:"0px" }} ref={this._timelineContainer}onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}> + <TimelineFlyout flyoutInfo={this.flyoutInfo} tickSpacing={this._tickSpacing}/> + <div className="toolbox"> + <div onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div> + <div onClick={this.onPlay}> <FontAwesomeIcon icon={faPlayCircle} size="2x" /> </div> + <div onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div> + </div> + <div className="info-container" ref={this._infoContainer}> + <div className="scrubberbox" ref={this._scrubberbox} onClick={this.onScrubberClick}> + {this._ticks.map(element => { + return <div className="tick" style={{ transform: `translate(${element / 1000 * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toTime(element)}</p></div>; + })} + </div> + <div className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}> + <div className="scrubberhead"></div> + </div> + <div className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown}> + {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} setFlyout={this.getFlyout} />)} + </div> + </div> + <div className="title-container" ref={this._titleContainer}> + {DocListCast(this.children).map(doc => <div className="datapane"><p>{doc.title}</p></div>)} + </div> + <div onPointerDown={this.onResizeDown}> + <FontAwesomeIcon className="resize" icon={faGripLines} /> + </div> + </div> + </div> + ); + } + +} + + +interface TimelineFlyoutProps { + flyoutInfo:FlyoutProps; + tickSpacing:number; + +} + +class TimelineOverview extends React.Component{ + +} + +class TimelineFlyout extends React.Component<TimelineFlyoutProps>{ + @observable private _timeInput = React.createRef<HTMLInputElement>(); + @observable private _durationInput = React.createRef<HTMLInputElement>(); + @observable private _fadeInInput = React.createRef<HTMLInputElement>(); + @observable private _fadeOutInput = React.createRef<HTMLInputElement>(); + private block = false; + + componentDidMount() { + document.addEventListener("pointerdown", this.closeFlyout); + } + componentWillUnmount(){ + document.removeEventListener("pointerdown", this.closeFlyout); + } + + componentDidUpdate(){ + console.log(this.props.flyoutInfo); + } + + @action changeTime = (e: React.KeyboardEvent) => { let time = this._timeInput.current!; if (e.keyCode === 13) { if (!Number.isNaN(Number(time.value))) { - this.flyoutInfo.regiondata!.position = Number(time.value) / 1000 * this._tickSpacing; + this.props.flyoutInfo.regiondata!.position = Number(time.value) / 1000 * this.props.tickSpacing; time.placeholder = time.value + "ms"; time.value = ""; } } } + @action + onFlyoutDown = (e: React.PointerEvent) => { + this.props.flyoutInfo.display = "block"; + this.block = true; + } + @action + closeFlyout = (e: PointerEvent) => { + if (this.block) { + this.block = false; + return; + } + this.props.flyoutInfo.display = "none"; + } @action changeDuration = (e: React.KeyboardEvent) => { let duration = this._durationInput.current!; if (e.keyCode === 13) { if (!Number.isNaN(Number(duration.value))) { - this.flyoutInfo.regiondata!.duration = Number(duration.value) / 1000 * this._tickSpacing; + this.props.flyoutInfo.regiondata!.duration = Number(duration.value) / 1000 * this.props.tickSpacing; duration.placeholder = duration.value + "ms"; duration.value = ""; } @@ -354,7 +389,7 @@ export class Timeline extends CollectionSubView(Document) { let fadeIn = this._fadeInInput.current!; if (e.keyCode === 13) { if (!Number.isNaN(Number(fadeIn.value))) { - this.flyoutInfo.regiondata!.fadeIn = Number(fadeIn.value); + this.props.flyoutInfo.regiondata!.fadeIn = Number(fadeIn.value); fadeIn.placeholder = fadeIn.value + "ms"; fadeIn.value = ""; } @@ -366,22 +401,17 @@ export class Timeline extends CollectionSubView(Document) { let fadeOut = this._fadeOutInput.current!; if (e.keyCode === 13) { if (!Number.isNaN(Number(fadeOut.value))) { - this.flyoutInfo.regiondata!.fadeOut = Number(fadeOut.value); + this.props.flyoutInfo.regiondata!.fadeOut = Number(fadeOut.value); fadeOut.placeholder = fadeOut.value + "ms"; fadeOut.value = ""; } } } - private setPlacementHighlight = (x = 0, y = 0, height:(string| number) = 0, width:(string | number) = 0):JSX.Element => { - return <div className="placement-highlight" style ={{height: `${height}px`, width: `${width}px`, transform:`translate(${x}px, ${y}px)`}}></div>; - } - render() { + render(){ return ( - <div style={{left:"0px", top: "0px", position:"absolute", width:"100%", transform:"translate(0px, 0px)"}} ref = {this._timelineWrapper}> - {this.setPlacementHighlight(0,0,300,400)} - <button className="minimize" onClick={this.minimize}>Minimize</button> - <div className="flyout-container" style={{ left: `${this.flyoutInfo.x}px`, top: `${this.flyoutInfo.y}px`, display: `${this.flyoutInfo.display!}` }} onPointerDown={this.onFlyoutDown}> + <div> + <div className="flyout-container" style={{ left: `${this.props.flyoutInfo.x}px`, top: `${this.props.flyoutInfo.y}px`, display: `${this.props.flyoutInfo.display!}` }} onPointerDown={this.onFlyoutDown}> <FontAwesomeIcon className="flyout" icon="comment-alt" color="grey" /> <div className="text-container"> <p>Time:</p> @@ -390,52 +420,27 @@ export class Timeline extends CollectionSubView(Document) { <p>Fade-out</p> </div> <div className="input-container"> - <input ref={this._timeInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.position) / this._tickSpacing * 1000)}ms`} onKeyDown={this.changeTime} /> - <input ref={this._durationInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.duration) / this._tickSpacing * 1000)}ms`} onKeyDown={this.changeDuration} /> - <input ref={this._fadeInInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeIn))}ms`} onKeyDown={this.changeFadeIn} /> - <input ref={this._fadeOutInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeOut))}ms`} onKeyDown={this.changeFadeOut} /> - </div> - <button onClick={action((e: React.MouseEvent) => { this.flyoutInfo.regions!.splice(this.flyoutInfo.regions!.indexOf(this.flyoutInfo.regiondata!), 1); this.flyoutInfo.display = "none"; })}>delete</button> - </div> - <div className="timeline-container" style={{ height: `${this._containerHeight}px`, left:"0px", top:"0px" }} ref={this._timelineContainer}onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}> - <div className="toolbox"> - <div onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div> - <div onClick={this.onPlay}> <FontAwesomeIcon icon={faPlayCircle} size="2x" /> </div> - <div onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div> - {/* <div> - <p>Timeline Overview</p> - <div className="overview"></div> - </div> */} - </div> - <div className="info-container" ref={this._infoContainer}> - <div className="scrubberbox" ref={this._scrubberbox} onClick={this.onScrubberClick}> - {this._ticks.map(element => { - return <div className="tick" style={{ transform: `translate(${element / 1000 * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toTime(element)}</p></div>; - })} - </div> - <div className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}> - <div className="scrubberhead"></div> - </div> - <div className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown}> - {DocListCast(this.children).map(doc => { - return <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} setFlyout={this.getFlyout} />; - })} - </div> - </div> - <div className="title-container" ref={this._titleContainer}> - {DocListCast(this.children).map(doc => { - return <div className="datapane"> - <p>{doc.title}</p> - </div>; - })} - </div> - <div onPointerDown={this.onResizeDown}> - <FontAwesomeIcon className="resize" icon={faGripLines} /> + <input ref={this._timeInput} type="text" placeholder={`${Math.round(NumCast(this.props.flyoutInfo.regiondata!.position) / this.props.tickSpacing * 1000)}ms`} onKeyDown={this.changeTime} /> + <input ref={this._durationInput} type="text" placeholder={`${Math.round(NumCast(this.props.flyoutInfo.regiondata!.duration) / this.props.tickSpacing * 1000)}ms`} onKeyDown={this.changeDuration} /> + <input ref={this._fadeInInput} type="text" placeholder={`${Math.round(NumCast(this.props.flyoutInfo.regiondata!.fadeIn))}ms`} onKeyDown={this.changeFadeIn} /> + <input ref={this._fadeOutInput} type="text" placeholder={`${Math.round(NumCast(this.props.flyoutInfo.regiondata!.fadeOut))}ms`} onKeyDown={this.changeFadeOut} /> </div> + <button onClick={action((e: React.MouseEvent) => { this.props.flyoutInfo.regions!.splice(this.props.flyoutInfo.regions!.indexOf(this.props.flyoutInfo.regiondata!), 1); this.props.flyoutInfo.display = "none"; })}>delete</button> </div> - </div> - ); + ); } +} + +class TimelineZoom extends React.Component{ + componentDidMount() { + } + render(){ + return ( + <div> + + </div> + ); + } }
\ No newline at end of file |