From bf3d45f8a16d23384a308f65adfa9a2baee495af Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Thu, 1 Aug 2019 17:00:10 -0400
Subject: prosemirror

---
 src/client/views/animationtimeline/Timeline.tsx | 530 ++++++++++++++++++++++++
 1 file changed, 530 insertions(+)
 create mode 100644 src/client/views/animationtimeline/Timeline.tsx

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
new file mode 100644
index 000000000..d2714592e
--- /dev/null
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -0,0 +1,530 @@
+import * as React from "react";
+import "./Timeline.scss";
+import { CollectionSubView } from "../collections/CollectionSubView";
+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, StrCast } from "../../../new_fields/Types";
+import { List } from "../../../new_fields/List";
+import { Doc, DocListCast } from "../../../new_fields/Doc";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle } from "@fortawesome/free-solid-svg-icons";
+import { ContextMenuProps } from "../ContextMenuItem";
+import { ContextMenu } from "../ContextMenu";
+import { DocumentManager } from "../../util/DocumentManager";
+import { VideoBox } from "../nodes/VideoBox";
+import { VideoField } from "../../../new_fields/URLField";
+import { CollectionVideoView } from "../collections/CollectionVideoView";
+import { Transform } from "../../util/Transform";
+import { faGrinTongueSquint } from "@fortawesome/free-regular-svg-icons";
+import { InkField } from "../../../new_fields/InkField";
+import { AddComparisonParameters } from "../../northstar/model/idea/idea";
+import { keepAlive } from "mobx-utils";
+
+
+export interface FlyoutProps {
+    x?: number;
+    y?: number;
+    display?: string;
+    regiondata?: Doc;
+    regions?: List<Doc>;
+}
+
+
+@observer
+export class Timeline extends CollectionSubView(Document) {
+    private readonly DEFAULT_CONTAINER_HEIGHT: number = 300;
+    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 _timelineWrapper = React.createRef<HTMLDivElement>();
+    @observable private _infoContainer = React.createRef<HTMLDivElement>();
+
+
+    @observable private _currentBarX: number = 0;
+    @observable private _windSpeed: number = 1;
+    @observable private _isPlaying: boolean = false; //scrubber playing
+    @observable private _isFrozen: boolean = false; //timeline freeze
+    @observable private _boxLength: number = 0;
+    @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT;
+    @observable private _time = 100000; //DEFAULT
+    @observable private _ticks: number[] = [];
+    @observable private _playButton = faPlayCircle; 
+    @observable private flyoutInfo: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>() };
+
+    @computed
+    private get children(): List<Doc> {
+        let extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type));
+       
+        if (extendedDocument) {
+            if (this.props.Document.data_ext) {
+                return Cast((Cast(this.props.Document.data_ext, Doc) as Doc).annotations, listSpec(Doc)) as List<Doc>;
+            } else {
+                return new List<Doc>();
+            }
+        }
+        return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
+    }
+
+    @computed
+    private get inks(){
+        if (this.props.Document.data_ext){        
+            let data_ext = Cast(this.props.Document.data_ext, Doc) as Doc; 
+            let ink = Cast(data_ext.ink, InkField) as InkField; 
+            if (ink){
+                return ink.inkData; 
+            }
+        }
+    }
+
+  
+    componentDidMount() {
+        if (StrCast(this.props.Document.type) === "video") {
+            console.log("ran");
+            console.log(this.props.Document.duration);
+            if (this.props.Document.duration) {
+                this._time = Math.round(NumCast(this.props.Document.duration)) * 1000;
+
+                reaction(() => {
+                    return NumCast(this.props.Document.curPage);
+                }, curPage => {
+                    this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
+                });
+
+            }
+
+        }
+        runInAction(() => {
+
+            reaction(() => {
+                return 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}`;
+                this._scrubberbox.current!.style.width = `${this._boxLength}`;
+            }, { fireImmediately: true });
+        });
+    }
+
+    @action
+    changeCurrentBarX = (x: number) => {
+        this._currentBarX = x;
+    }
+
+    //for playing
+    @action
+    onPlay = async (e: React.MouseEvent) => {
+        if (this._isPlaying) {
+            this._isPlaying = false;
+            this._playButton = faPlayCircle; 
+        } else {
+            this._isPlaying = true;
+            this._playButton = faPauseCircle; 
+            this.changeCurrentX();
+        }
+    }
+
+    @action
+    changeCurrentX = () => {
+        if (this._currentBarX === this._boxLength && this._isPlaying) {
+            this._currentBarX = 0;
+        }
+        if (this._currentBarX <= this._boxLength && this._isPlaying) {
+            this._currentBarX = this._currentBarX + this._windSpeed;
+            setTimeout(this.changeCurrentX, 15);
+        }
+    }
+
+    @action
+    windForward = (e: React.MouseEvent) => {
+        if (this._windSpeed < 64) { //max speed is 32
+            this._windSpeed = this._windSpeed * 2;
+        }
+    }
+
+    @action
+    windBackward = (e: React.MouseEvent) => {
+        if (this._windSpeed > 1 / 16) { // min speed is 1/8
+            this._windSpeed = this._windSpeed / 2;
+        }
+    }
+
+    //for scrubber action 
+    @action
+    onScrubberDown = (e: React.PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        document.addEventListener("pointermove", this.onScrubberMove);
+        document.addEventListener("pointerup", () => {
+            document.removeEventListener("pointermove", this.onScrubberMove);
+        });
+    }
+
+    @action
+    onScrubberMove = (e: PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        let scrubberbox = this._scrubberbox.current!;
+        let left = scrubberbox.getBoundingClientRect().left;
+        let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
+        this._currentBarX = offsetX;
+    }
+
+    @action
+    onScrubberClick = (e: React.MouseEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        let scrubberbox = this._scrubberbox.current!;
+        let offset = (e.clientX - scrubberbox.getBoundingClientRect().left) * this.props.ScreenToLocalTransform().Scale;
+        this._currentBarX = offset;
+    }
+
+
+
+    @action
+    onPanDown = (e: React.PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        document.addEventListener("pointermove", this.onPanMove);
+        document.addEventListener("pointerup", () => {
+            document.removeEventListener("pointermove", this.onPanMove);
+        });
+    }
+
+    @action
+    onPanMove = (e: PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        let infoContainer = this._infoContainer.current!;
+        let trackbox = this._trackbox.current!;
+        let titleContainer = this._titleContainer.current!;
+        infoContainer.scrollLeft = infoContainer.scrollLeft - e.movementX;
+        trackbox.scrollTop = trackbox.scrollTop - e.movementY;
+        titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;
+    }
+
+
+    @action
+    onResizeDown = (e: React.PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        document.addEventListener("pointermove", this.onResizeMove);
+        document.addEventListener("pointerup", () => {
+            document.removeEventListener("pointermove", this.onResizeMove);
+        });
+    }
+
+    @action
+    onResizeMove = (e: PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        let offset = e.clientY - this._timelineContainer.current!.getBoundingClientRect().bottom;
+        if (this._containerHeight + offset <= this.MIN_CONTAINER_HEIGHT) {
+            this._containerHeight = this.MIN_CONTAINER_HEIGHT;
+        } else if (this._containerHeight + offset >= this.MAX_CONTAINER_HEIGHT) {
+            this._containerHeight = this.MAX_CONTAINER_HEIGHT;
+        } else {
+            this._containerHeight += offset;
+        }
+    }
+
+    @action
+    onTimelineDown = (e: React.PointerEvent) => {
+        e.preventDefault();
+        if (e.nativeEvent.which === 1 && !this._isFrozen) {
+            document.addEventListener("pointermove", this.onTimelineMove);
+            document.addEventListener("pointerup", () => { document.removeEventListener("pointermove", this.onTimelineMove); });
+        }
+    }
+
+    @action
+    onTimelineMove = (e: PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        let timelineContainer = this._timelineWrapper.current!;
+        let left = parseFloat(timelineContainer.style.left!);
+        let top = parseFloat(timelineContainer.style.top!);
+        timelineContainer.style.left = `${left + e.movementX}px`;
+        timelineContainer.style.top = `${top + e.movementY}px`;
+    }
+
+    @action
+    minimize = (e: React.MouseEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        let timelineContainer = this._timelineContainer.current!;
+        if (this._isMinimized) {
+            this._isMinimized = false;
+            timelineContainer.style.visibility = "visible";
+        } else {
+            this._isMinimized = true;
+            timelineContainer.style.visibility = "hidden";
+        }
+    }
+
+    @action
+    toTime = (time: number): string => {
+        const inSeconds = time / 1000;
+        let min: (string | number) = Math.floor(inSeconds / 60);
+        let sec: (string | number) = inSeconds % 60;
+
+        if (Math.floor(sec / 10) === 0) {
+            sec = "0" + sec;
+        }
+        return `${min}:${sec}`;
+    }
+
+
+    private _freezeText = "Freeze Timeline";
+
+    timelineContextMenu = (e: React.MouseEvent): void => {
+        let subitems: ContextMenuProps[] = [];
+        let timelineContainer = this._timelineWrapper.current!;
+        subitems.push({
+            description: "Pin to Top", event: action(() => {
+                if (!this._isFrozen) {
+                    timelineContainer.style.transition = "top 1000ms ease-in, left 1000ms ease-in";  //?????
+                    timelineContainer.style.left = "0px";
+                    timelineContainer.style.top = "0px";
+                    timelineContainer.style.transition = "none";
+                }
+            }), icon: faArrowUp
+        });
+        subitems.push({
+            description: "Pin to Bottom", event: action(() => {
+                console.log(this.props.Document.y);
+
+                if (!this._isFrozen) {
+                    timelineContainer.style.transform = `translate(0px, ${e.pageY - this._containerHeight}px)`;
+                }
+            }), icon: faArrowDown
+        });
+        subitems.push({
+            description: this._freezeText, event: action(() => {
+                if (this._isFrozen) {
+                    this._isFrozen = false;
+                    this._freezeText = "Freeze Timeline";
+                } else {
+                    this._isFrozen = true;
+                    this._freezeText = "Unfreeze Timeline";
+                }
+            }), icon: "thumbtack"
+        });
+        ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems, icon: faClock });
+    }
+
+
+
+    @action
+    getFlyout = (props: FlyoutProps) => {
+        for (const [k, v] of Object.entries(props)) {
+            (this.flyoutInfo as any)[k] = v;
+        }
+        console.log(this.flyoutInfo); 
+    }
+
+    render() {
+        return (
+            <div style={{ left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }} ref={this._timelineWrapper}>
+                <button className="minimize" onClick={this.minimize}>Minimize</button>
+                <div className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} 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={this._playButton} 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} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
+                        </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;
+
+}
+
+interface TimelineOverviewProps {
+    currentBarX: number;
+}
+
+class TimelineOverview extends React.Component<TimelineOverviewProps>{
+
+    componentWillMount() {
+
+    }
+
+    render() {
+        return (
+            <div className="overview">
+                <div className="container">
+                    <div className="scrubber">
+                        <div className="scrubberhead"></div>
+                    </div>
+                </div>
+            </div>
+        );
+    }
+}
+
+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>();
+    @observable private  _data: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>() };
+
+    private block = false;
+
+    componentDidMount() {
+        
+        document.addEventListener("pointerdown", this.closeFlyout);
+    }
+
+
+    componentWillUnmount() {
+        document.removeEventListener("pointerdown", this.closeFlyout);
+    }
+
+   
+    @action
+    changeTime = (e: React.KeyboardEvent) => {
+        let time = this._timeInput.current!;
+        if (e.keyCode === 13) {
+            if (!Number.isNaN(Number(time.value))) {
+                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._data.display = "block";
+        this.block = true;
+    }
+
+    @action
+    closeFlyout = (e: PointerEvent) => {
+        if (this.block) {
+            this.block = false;
+            return;
+        }
+        this._data.display = "none";
+    }
+
+    @action
+    changeDuration = (e: React.KeyboardEvent) => {
+        let duration = this._durationInput.current!;
+        if (e.keyCode === 13) {
+            if (!Number.isNaN(Number(duration.value))) {
+                this.props.flyoutInfo.regiondata!.duration = Number(duration.value) / 1000 * this.props.tickSpacing;
+                duration.placeholder = duration.value + "ms";
+                duration.value = "";
+            }
+        }
+    }
+
+    @action
+    changeFadeIn = (e: React.KeyboardEvent) => {
+        let fadeIn = this._fadeInInput.current!;
+        if (e.keyCode === 13) {
+            if (!Number.isNaN(Number(fadeIn.value))) {
+                this.props.flyoutInfo.regiondata!.fadeIn = Number(fadeIn.value);
+                fadeIn.placeholder = fadeIn.value + "ms";
+                fadeIn.value = "";
+            }
+        }
+    }
+
+    @action
+    changeFadeOut = (e: React.KeyboardEvent) => {
+        let fadeOut = this._fadeOutInput.current!;
+        if (e.keyCode === 13) {
+            if (!Number.isNaN(Number(fadeOut.value))) {
+                this.props.flyoutInfo.regiondata!.fadeOut = Number(fadeOut.value);
+                fadeOut.placeholder = fadeOut.value + "ms";
+                fadeOut.value = "";
+            }
+        }
+    }
+
+    render() {
+        return (
+            <div>
+                <div className="flyout-container" style={{ left: `${this._data.x}px`, top: `${this._data.y}px`, display: `${this._data.display!}` }} onPointerDown={this.onFlyoutDown}>
+                    <FontAwesomeIcon className="flyout" icon="comment-alt" color="grey" />
+                    <div className="text-container">
+                        <p>Time:</p>
+                        <p>Duration:</p>
+                        <p>Fade-in</p>
+                        <p>Fade-out</p>
+                    </div>
+                    <div className="input-container">
+                        <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
-- 
cgit v1.2.3-70-g09d2


From 62a34043949f051533ca549be48b774696331d43 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Mon, 5 Aug 2019 17:37:43 -0400
Subject: richtext + buttons

---
 src/client/views/MainView.tsx                      |   1 +
 src/client/views/animationtimeline/Timeline.tsx    |   3 +
 .../views/animationtimeline/TimelineMenu.tsx       |  12 +-
 src/client/views/animationtimeline/Track.tsx       | 124 +++++++++++----------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   4 +-
 src/client/views/nodes/FormattedTextBox.tsx        |   2 -
 src/new_fields/RichTextField.ts                    |   1 +
 7 files changed, 85 insertions(+), 62 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f5a6715e5..669b8f018 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -400,6 +400,7 @@ export class MainView extends React.Component {
                 <ul id="add-options-list">
                     <li key="search"><button className="add-button round-button" title="Search" onClick={this.toggleSearch}><FontAwesomeIcon icon="search" size="sm" /></button></li>
                     <li key="presentation"><button className="add-button round-button" title="Open Presentation View" onClick={() => PresentationView.Instance.toggle(undefined)}><FontAwesomeIcon icon="table" size="sm" /></button></li>
+                    <li key="timeline"><button className="add-button round-button" title="Add Timeline"><FontAwesomeIcon icon="times" size="sm"/></button></li>
                     <li key="undo"><button className="add-button round-button" title="Undo" style={{ opacity: UndoManager.CanUndo() ? 1 : 0.5, transition: "0.4s ease all" }} onClick={() => UndoManager.Undo()}><FontAwesomeIcon icon="undo-alt" size="sm" /></button></li>
                     <li key="redo"><button className="add-button round-button" title="Redo" style={{ opacity: UndoManager.CanRedo() ? 1 : 0.5, transition: "0.4s ease all" }} onClick={() => UndoManager.Redo()}><FontAwesomeIcon icon="redo-alt" size="sm" /></button></li>
                     {btns.map(btn =>
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index d2714592e..7a6d9fa52 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -34,6 +34,9 @@ export interface FlyoutProps {
 
 @observer
 export class Timeline extends CollectionSubView(Document) {
+    static Instance:Timeline; 
+   
+
     private readonly DEFAULT_CONTAINER_HEIGHT: number = 300;
     private readonly DEFAULT_TICK_SPACING: number = 50;
     private readonly MIN_CONTAINER_HEIGHT: number = 205;
diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx
index e82075f6a..7768f51df 100644
--- a/src/client/views/animationtimeline/TimelineMenu.tsx
+++ b/src/client/views/animationtimeline/TimelineMenu.tsx
@@ -1,6 +1,6 @@
-
 import * as React from "react";
-
+import {observable, action, runInAction} from "mobx"; 
+import {observer} from "mobx-react"; 
 
 /**
  * TimelineMenu: 
@@ -27,9 +27,17 @@ import * as React from "react";
  *  - duration region 
  *  - 
  */
+
+@observer
 export class TimelineMenu extends React.Component {
     public static Instance:TimelineMenu; 
 
+    @observable private _opacity = 1; 
+    @observable private _x = 0; 
+    @observable private _y = 0; 
+    @observable private _type: "timeline" | "keyframe" | "region" | "" = ""; 
+
+
     constructor (props:Readonly<{}>){
         super(props); 
         TimelineMenu.Instance = this; 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 4f78f86b8..fc2cacba8 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -9,10 +9,6 @@ import { List } from "../../../new_fields/List";
 import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
 import { FlyoutProps } from "./Timeline";
 import { Transform } from "../../util/Transform";
-import { AddComparisonParameters } from "../../northstar/model/idea/idea";
-import { CollectionSchemaBooleanCell } from "../collections/CollectionSchemaCells";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DocumentView } from "../nodes/DocumentView";
 import { RichTextField } from "../../../new_fields/RichTextField";
 
 interface IProps {
@@ -28,8 +24,11 @@ interface IProps {
 export class Track extends React.Component<IProps> {
     @observable private _inner = React.createRef<HTMLDivElement>();
     @observable private _reactionDisposers: IReactionDisposer[] = [];
-    @observable private _keyReaction: any; //reaction that is used to dispose when necessary 
-    @observable private _currentBarXReaction: any;
+    @observable private _currentBarXReaction: any;   
+    @observable private _isOnKeyframe: boolean = false; 
+    @observable private _onKeyframe: (Doc | undefined) = undefined; 
+    @observable private _onRegionData : ( Doc | undefined) = undefined; 
+    @observable private _leftCurrKeyframe: (Doc | undefined) = undefined; 
 
     @computed
     private get regions() {
@@ -53,53 +52,44 @@ export class Track extends React.Component<IProps> {
 
     componentWillUnmount() {
         runInAction(() => {
-            if (this._keyReaction) this._keyReaction();
             if (this._currentBarXReaction) this._currentBarXReaction();
         });
     }
 
     @action
-    keyReaction = () => { 
-        return reaction( () => {
-            return Doc.allKeys(this.props.node).map(key => FieldValue(this.props.node[key]));
-        }, async () => {
-            console.log("rAN"); 
-            let regiondata: (Doc | undefined) = await this.findRegion(this.props.currentBarX) ;
-            if (regiondata) {
-                let keyframes = await DocListCastAsync((regiondata as Doc).keyframes!); 
-                keyframes!.forEach( async (kf) => {
-                    if (kf.type === KeyframeFunc.KeyframeType.default && kf.time === this.props.currentBarX) {
-                        console.log("full keychange triggered"); 
-                        //for this specific keyframe
-                        kf.key = Doc.MakeCopy(this.props.node, true);
-
-                        //for fades
-                        let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.props.currentBarX, kf); // lef keyframe, if it exists
-                        let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, this.props.currentBarX, kf); //right keyframe, if it exists
-                        if (leftkf!.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
-                            let edge:(Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.props.currentBarX, leftkf!);
-                            edge!.key = Doc.MakeCopy(kf.key as Doc, true);
-                            leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
-                            (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
-                            (Cast(leftkf!.key, Doc)! as Doc).opacity = 1;
-                        }
-                        if (rightkf!.type === KeyframeFunc.KeyframeType.fade) {
-                            let edge:(Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!,this.props.currentBarX, rightkf!);
-                            edge!.key = Doc.MakeCopy(kf.key as Doc, true);
-                            rightkf!.key = Doc.MakeCopy(kf.key as Doc, true);
-                            (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
-                            (Cast(rightkf!.key, Doc)! as Doc).opacity = 1;
-                        }
-                    }
-                });
+    saveKeyframe = async (ref:Doc, regiondata:Doc) => { 
+        let keyframes:List<Doc> = (Cast(regiondata.keyframes, listSpec(Doc)) as List<Doc>); 
+        let kfIndex:number = keyframes.indexOf(ref); 
+        let kf = keyframes[kfIndex] as Doc; 
+        if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for fades
+            console.log("full keychange triggered"); 
+            kf.key = Doc.MakeCopy(this.props.node, true);
+            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.props.currentBarX, kf); // lef keyframe, if it exists
+            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, this.props.currentBarX, kf); //right keyframe, if it exists
+            if (leftkf!.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
+                let edge:(Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.props.currentBarX, leftkf!);
+                edge!.key = Doc.MakeCopy(kf.key as Doc, true);
+                leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
+                (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
+                (Cast(leftkf!.key, Doc)! as Doc).opacity = 1;
             }
-        }, {fireImmediately: true});
+            if (rightkf!.type === KeyframeFunc.KeyframeType.fade) {
+                let edge:(Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!,this.props.currentBarX, rightkf!);
+                edge!.key = Doc.MakeCopy(kf.key as Doc, true);
+                rightkf!.key = Doc.MakeCopy(kf.key as Doc, true);
+                (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
+                (Cast(rightkf!.key, Doc)! as Doc).opacity = 1;
+            }   
+        }
+        keyframes[kfIndex] = kf; 
+        this._onKeyframe = undefined; 
+        this._onRegionData = undefined; 
+        this._isOnKeyframe = false; 
     }
-
+ 
     @action 
     currentBarXReaction = () => {
         return reaction(() => this.props.currentBarX, async () => {
-            if (this._keyReaction) this._keyReaction(); //dispose previous reaction first
             let regiondata: (Doc | undefined) = await this.findRegion(this.props.currentBarX);
             if (regiondata) {
                 this.props.node.hidden = false;
@@ -113,6 +103,10 @@ export class Track extends React.Component<IProps> {
 
     @action
     timeChange = async (time: number) => {
+        if (this._isOnKeyframe && this._onKeyframe && this._onRegionData) { 
+            console.log("saving"); 
+            await this.saveKeyframe(this._onKeyframe, this._onRegionData); 
+        }
         let regiondata = await this.findRegion(Math.round(time)); //finds a region that the scrubber is on
         if (regiondata) {
             let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata, this.props.currentBarX); // lef keyframe, if it exists
@@ -120,7 +114,10 @@ export class Track extends React.Component<IProps> {
             let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
             if (currentkf) {
                 await this.applyKeys(currentkf);
-                this._keyReaction = this.keyReaction(); //reactivates reaction. 
+                this._leftCurrKeyframe = currentkf; 
+                this._isOnKeyframe = true; 
+                this._onKeyframe = currentkf; 
+                this._onRegionData = regiondata; 
             } else if (leftkf && rightkf) {
                 await this.interpolate(leftkf, rightkf, regiondata);
             }
@@ -133,17 +130,21 @@ export class Track extends React.Component<IProps> {
         let docFromApply = kfNode; 
         if (this.filterKeys(Doc.allKeys(this.props.node)).length > this.filterKeys(Doc.allKeys(kfNode)).length) docFromApply = this.props.node; 
         this.filterKeys(Doc.allKeys(docFromApply)).forEach(key => {
-            if (key === "type") {
-                if (this.props.node[key] === "text") {
-                    this.props.node.dataDocTest = new RichTextField(StrCast(kfNode.stateData)); 
-                    console.log("updated"); 
-                }
-            }
             if (!kfNode[key]) {
                 this.props.node[key] = undefined; 
             } else {
-                this.props.node[key] = kfNode[key];
+                if (key === "data") {
+                    if (this.props.node.type === "text"){
+                        let nodeData = (kfNode[key] as RichTextField).Data; 
+                        this.props.node[key] = new RichTextField(nodeData); 
+                    }
+                } else if (key === "creationDate") {
+                }  else {
+                    this.props.node[key] = kfNode[key];
+                }
+
             }
+            
         });
     }
 
@@ -151,7 +152,7 @@ export class Track extends React.Component<IProps> {
     @action
     private filterKeys = (keys: string[]): string[] => {
         return keys.reduce((acc: string[], key: string) => {
-            if (key !== "regions" && key !== "data" && key !== "creationDate" && key !== "cursors" && key !== "hidden" && key !== "nativeHeight" && key !== "nativeWidth" && key !== "schemaColumns") acc.push(key);
+            if (key !== "regions" && key !== "cursors" && key !== "hidden" && key !== "nativeHeight" && key !== "nativeWidth" && key !== "schemaColumns") acc.push(key);
             return acc;
         }, []) as string[];
     }
@@ -205,22 +206,31 @@ export class Track extends React.Component<IProps> {
             }
            
         }
-
-        
         this.filterKeys(Doc.allKeys(leftNode)).forEach(key => {
             if (leftNode[key] && rightNode[key] && typeof (leftNode[key]) === "number" && typeof (rightNode[key]) === "number") { //if it is number, interpolate
                 if ((key === "x" || key === "y") && pathX.length !== 0){
                     if (key === "x") this.props.node[key] = proposedX; 
                     if (key === "y") this.props.node[key] = proposedY; 
-                    console.log(pathX.length); 
-                  
                 } else {
                     const diff = NumCast(rightNode[key]) - NumCast(leftNode[key]);
                     const adjusted = diff * finalRatio;
                     this.props.node[key] = NumCast(leftNode[key]) + adjusted;
                 }
             } else {
-                this.props.node[key] = leftNode[key];
+                if (key === "data") {
+                    if (this.props.node.type === "text"){
+                        let nodeData = StrCast((leftNode[key] as RichTextField).Data); 
+                        let currentNodeData = StrCast((this.props.node[key] as RichTextField).Data); 
+                        if (nodeData !== currentNodeData) {
+                            this.props.node[key] = new RichTextField(nodeData); 
+                        }
+                    }
+                    
+                } else if (key === "creationDate") {
+
+                } else {
+                    this.props.node[key] = leftNode[key];
+                }
             }
         });
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 676a49288..71329f166 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -573,7 +573,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             addOverlay("arrangeScript", { x: 400, y: 500, width: 400, height: 300, title: "Layout Script" }, { doc: "Doc", index: "number", collection: "Doc", state: "any", docs: "Doc[]" }, "{x: number, y: number, width?: number, height?: number}");
         };
     }
-
+    private _timeline = <Timeline {...this.props}/>; 
+    se = () => {
+    }
     render() {
         const easing = () => this.props.Document.panTransformType === "Ease";
         Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9b37a6491..03fa7f0cd 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -166,8 +166,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             if (this.extensionDoc) this.extensionDoc.text = state.doc.textBetween(0, state.doc.content.size, "\n\n");
             if (this.extensionDoc) this.extensionDoc.lastModified = new DateField(new Date(Date.now()));
             this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()));            
-            this.props.Document.stateData = JSON.stringify(state.toJSON());            
-            this.props.Document.dataDocTest = this.dataDoc[this.props.fieldKey]; 
             this._applyingChange = false;
             let title = StrCast(this.dataDoc.title);
             if (title && title.startsWith("-") && this._editorView && !this.Document.customTitle) {
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
index 78a3a4067..0095eb31f 100644
--- a/src/new_fields/RichTextField.ts
+++ b/src/new_fields/RichTextField.ts
@@ -15,6 +15,7 @@ export class RichTextField extends ObjectField {
         this.Data = data;
     }
 
+  
     [Copy]() {
         return new RichTextField(this.Data);
     }
-- 
cgit v1.2.3-70-g09d2


From c8cb602f06f1b6c325ce467eea8dfa405b673810 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Fri, 9 Aug 2019 17:10:49 -0400
Subject: some changes

---
 src/client/views/animationtimeline/Keyframe.tsx |  20 +----
 src/client/views/animationtimeline/Timeline.tsx | 114 ------------------------
 src/client/views/animationtimeline/Track.tsx    |   9 +-
 src/client/views/graph/Graph.tsx                |   5 +-
 4 files changed, 9 insertions(+), 139 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 3c0d17796..dbc26e3d4 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -11,7 +11,6 @@ import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new
 import { FlyoutProps } from "./Timeline";
 import { Transform } from "../../util/Transform";
 import { InkField, StrokeData } from "../../../new_fields/InkField";
-import { number } from "prop-types";
 import { TimelineMenu } from "./TimelineMenu";
 import { Docs } from "../../documents/Documents";
 import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
@@ -509,22 +508,6 @@ export class Keyframe extends React.Component<IProps> {
             document.removeEventListener("pointerup", this.onReactionListen); 
         }
     }
-
-
-
-    /**
-     * 
-     * 
-     * TEMPORARY
-     * let items = [
-                                        TimelineMenu.Instance.addItem("button", "Show Data", () => {console.log(toJS(this.props.node));}), 
-                                        TimelineMenu.Instance.addItem("button", "Delete", () => {}), 
-                                        TimelineMenu.Instance.addItem("input", "Move", (val) => {console.log(val);})  
-                                    ]; 
-                                    TimelineMenu.Instance.addMenu("Keyframe", items); 
-                                    TimelineMenu.Instance.openMenu(e.clientX, e.clientY);
-     * 
-     */
     render() {
         return (
             <div>
@@ -537,13 +520,14 @@ export class Keyframe extends React.Component<IProps> {
                         return this.createKeyframeJSX(kf as Doc, (kf! as Doc).type as KeyframeFunc.KeyframeType);
                     })}
                     {this.keyframes.map( kf => {
-                       if(this.keyframes.indexOf(kf) !== this.keyframes.length - 1) {
+                       if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
                             let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; 
                             let bodyRef = React.createRef<HTMLDivElement>(); 
                             return (
                                 <div ref={bodyRef}className="body-container" style={{left: `${NumCast(kf.time) - this.regiondata.position}px`, width:`${NumCast(left!.time) - NumCast(kf.time)}px`}}
                                 onPointerOver={(e) => { this.onContainerOver(e, bodyRef); }}
                                 onPointerOut={(e) => { this.onContainerOut(e, bodyRef); }}
+                                onPointerDown={(e) => { this.props.changeCurrentBarX(NumCast(kf.time) + (e.clientX - bodyRef.current!.getBoundingClientRect().left) * this.props.transform.Scale);}}
                                 onContextMenu={(e) => {
                                     let items = [
                                         TimelineMenu.Instance.addItem("button", "Add Ease", () => {this.onContainerDown(kf, "interpolate");}),
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 7a6d9fa52..052e6e925 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -350,7 +350,6 @@ export class Timeline extends CollectionSubView(Document) {
             <div style={{ left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }} ref={this._timelineWrapper}>
                 <button className="minimize" onClick={this.minimize}>Minimize</button>
                 <div className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} 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={this._playButton} size="2x" /> </div>
@@ -383,12 +382,6 @@ export class Timeline extends CollectionSubView(Document) {
 }
 
 
-interface TimelineFlyoutProps {
-    flyoutInfo: FlyoutProps;
-    tickSpacing: number;
-
-}
-
 interface TimelineOverviewProps {
     currentBarX: number;
 }
@@ -412,116 +405,9 @@ class TimelineOverview extends React.Component<TimelineOverviewProps>{
     }
 }
 
-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>();
-    @observable private  _data: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>() };
-
-    private block = false;
-
-    componentDidMount() {
-        
-        document.addEventListener("pointerdown", this.closeFlyout);
-    }
-
-
-    componentWillUnmount() {
-        document.removeEventListener("pointerdown", this.closeFlyout);
-    }
-
-   
-    @action
-    changeTime = (e: React.KeyboardEvent) => {
-        let time = this._timeInput.current!;
-        if (e.keyCode === 13) {
-            if (!Number.isNaN(Number(time.value))) {
-                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._data.display = "block";
-        this.block = true;
-    }
-
-    @action
-    closeFlyout = (e: PointerEvent) => {
-        if (this.block) {
-            this.block = false;
-            return;
-        }
-        this._data.display = "none";
-    }
-
-    @action
-    changeDuration = (e: React.KeyboardEvent) => {
-        let duration = this._durationInput.current!;
-        if (e.keyCode === 13) {
-            if (!Number.isNaN(Number(duration.value))) {
-                this.props.flyoutInfo.regiondata!.duration = Number(duration.value) / 1000 * this.props.tickSpacing;
-                duration.placeholder = duration.value + "ms";
-                duration.value = "";
-            }
-        }
-    }
-
-    @action
-    changeFadeIn = (e: React.KeyboardEvent) => {
-        let fadeIn = this._fadeInInput.current!;
-        if (e.keyCode === 13) {
-            if (!Number.isNaN(Number(fadeIn.value))) {
-                this.props.flyoutInfo.regiondata!.fadeIn = Number(fadeIn.value);
-                fadeIn.placeholder = fadeIn.value + "ms";
-                fadeIn.value = "";
-            }
-        }
-    }
-
-    @action
-    changeFadeOut = (e: React.KeyboardEvent) => {
-        let fadeOut = this._fadeOutInput.current!;
-        if (e.keyCode === 13) {
-            if (!Number.isNaN(Number(fadeOut.value))) {
-                this.props.flyoutInfo.regiondata!.fadeOut = Number(fadeOut.value);
-                fadeOut.placeholder = fadeOut.value + "ms";
-                fadeOut.value = "";
-            }
-        }
-    }
-
-    render() {
-        return (
-            <div>
-                <div className="flyout-container" style={{ left: `${this._data.x}px`, top: `${this._data.y}px`, display: `${this._data.display!}` }} onPointerDown={this.onFlyoutDown}>
-                    <FontAwesomeIcon className="flyout" icon="comment-alt" color="grey" />
-                    <div className="text-container">
-                        <p>Time:</p>
-                        <p>Duration:</p>
-                        <p>Fade-in</p>
-                        <p>Fade-out</p>
-                    </div>
-                    <div className="input-container">
-                        <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 (
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 363ab4074..64e94f0f1 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -61,8 +61,7 @@ export class Track extends React.Component<IProps> {
         let keyframes:List<Doc> = (Cast(regiondata.keyframes, listSpec(Doc)) as List<Doc>); 
         let kfIndex:number = keyframes.indexOf(ref); 
         let kf = keyframes[kfIndex] as Doc; 
-        if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for fades
-            console.log("full keychange triggered"); 
+        if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
             kf.key = Doc.MakeCopy(this.props.node, true);
             let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.props.currentBarX, kf); // lef keyframe, if it exists
             let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, this.props.currentBarX, kf); //right keyframe, if it exists
@@ -104,7 +103,6 @@ export class Track extends React.Component<IProps> {
     @action
     timeChange = async (time: number) => {
         if (this._isOnKeyframe && this._onKeyframe && this._onRegionData) { 
-            console.log("saving"); 
             await this.saveKeyframe(this._onKeyframe, this._onRegionData); 
         }
         let regiondata = await this.findRegion(Math.round(time)); //finds a region that the scrubber is on
@@ -169,9 +167,9 @@ export class Track extends React.Component<IProps> {
         return currentkf;
     }
 
+    
     @action
     interpolate = async (left: Doc, right: Doc, regiondata:Doc) => {
-        console.log("interpolating");
         let leftNode = left.key as Doc;
         let rightNode = right.key as Doc;
         const dif_time = NumCast(right.time) - NumCast(left.time);
@@ -226,8 +224,7 @@ export class Track extends React.Component<IProps> {
                         if (nodeData !== currentNodeData) {
                             this.props.node[key] = new RichTextField(nodeData); 
                         }
-                    }
-                    
+                    }    
                 } else if (key === "creationDate") {
 
                 } else {
diff --git a/src/client/views/graph/Graph.tsx b/src/client/views/graph/Graph.tsx
index 326f33358..d925cc32c 100644
--- a/src/client/views/graph/Graph.tsx
+++ b/src/client/views/graph/Graph.tsx
@@ -20,8 +20,11 @@ export class Graph extends CollectionSubView(Document) {
 
 
     render() {
+        let collection = <CollectionFreeFormView {...this.props}/>; 
+ 
         return (
-            <CollectionFreeFormView {...this.props}/>
+            <div>
+            </div>
             
         ); 
     }
-- 
cgit v1.2.3-70-g09d2


From c7e258d9d56990daec490b239e4103f9ca9d521a Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Mon, 12 Aug 2019 15:17:20 -0400
Subject: playmode / authoring mode

---
 src/client/views/animationtimeline/Timeline.scss |  66 ++-----------
 src/client/views/animationtimeline/Timeline.tsx  | 121 +++++++++--------------
 src/client/views/nodes/DocumentView.tsx          |   3 +-
 3 files changed, 57 insertions(+), 133 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 47f448adb..e5d898502 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -6,72 +6,24 @@
     height: 30px; 
     width: 100px; 
 }
-.flyout-container{
-    background-color: transparent; 
-    position:absolute; 
-            
-    z-index:9999; 
-    height: 150px; 
-    width: 150px; 
 
-    .flyout{
-        background-color: transparent; 
-        transform: rotate(180deg); 
-        left:0px; 
-        top:0px; 
-        width: 100%; 
-        height: 100%; 
-    }
-    .input-container{
-        position: absolute; 
-        right:0px; 
-        top: 30px; 
-        width: 70px; 
-        input{
-            width: 100%; 
-        }
+.timeline-toolbox{
+     position:absolute; 
+    display:flex;
+    align-items: flex-start; 
+    flex-direction: row;  
+    top: 10px;
+    div{
+        margin-left:10px; 
     }
-    .text-container{
-        position:absolute; 
-        top:30px; 
-        left:0px; 
-        color:white
-    }
-}
-
-.placement-highlight{
-    background-color:blue; 
-    transform: translate(0px, 0px); 
-    transition: width 1000ms ease-in-out; 
-    transition: height 1000ms ease-in-out;
-    position: absolute; 
 }
-
 .timeline-container{
     width:100%;
     height:300px; 
     position:absolute;
     background-color: $light-color-secondary;
     box-shadow: 0px 10px 20px; 
-    //transition: transform 1000ms ease-in-out; 
-    
-    .toolbox{
-        position:absolute; 
-        width: 100%;   
-        top: 10px; 
-        left: 20px; 
-        div{
-            float:left; 
-            margin-left: 10px; 
-            position:relative; 
-            .overview{
-                width: 200px; 
-                height: 100%; 
-                background-color: black; 
-                position:absolute; 
-            }
-        }
-    }
+
     .info-container{ 
         margin-top: 50px; 
         right:20px; 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 052e6e925..c8f11db5b 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -5,7 +5,7 @@ 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, StrCast } from "../../../new_fields/Types";
+import { Cast, NumCast, FieldValue, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -82,51 +82,48 @@ export class Timeline extends CollectionSubView(Document) {
         return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
     }
 
-    @computed
-    private get inks(){
-        if (this.props.Document.data_ext){        
-            let data_ext = Cast(this.props.Document.data_ext, Doc) as Doc; 
-            let ink = Cast(data_ext.ink, InkField) as InkField; 
-            if (ink){
-                return ink.inkData; 
-            }
-        }
+    componentWillMount() {
+        this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false; 
     }
 
-  
     componentDidMount() {
         if (StrCast(this.props.Document.type) === "video") {
             console.log("ran");
             console.log(this.props.Document.duration);
             if (this.props.Document.duration) {
                 this._time = Math.round(NumCast(this.props.Document.duration)) * 1000;
-
                 reaction(() => {
                     return NumCast(this.props.Document.curPage);
                 }, curPage => {
                     this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
                 });
-
             }
 
         }
         runInAction(() => {
-
             reaction(() => {
-                return 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}`;
-                this._scrubberbox.current!.style.width = `${this._boxLength}`;
-            }, { fireImmediately: true });
+                return this.props.Document.isAnimating; 
+            }, async isAnimating => {
+               if (isAnimating){
+                   this._ticks = [];
+                    for (let i = 0; i < this._time;) {
+                        this._ticks.push(i);
+                        i += this._tickIncrement;
+                    }
+                    observe(this._trackbox, change => {if (change.type === "update"){
+                        if (this.props.Document.isAnimating){
+                             let trackbox = this._trackbox.current!;
+                            this._boxLength = this._tickIncrement / 1000 * this._tickSpacing * this._ticks.length;
+                            trackbox.style.width = `${this._boxLength}`;
+                            this._scrubberbox.current!.style.width = `${this._boxLength}`;
+                        }
+                    }}); 
+               }
+                    
+            });
         });
     }
+   
 
     @action
     changeCurrentBarX = (x: number) => {
@@ -346,73 +343,47 @@ export class Timeline extends CollectionSubView(Document) {
     }
 
     render() {
-        return (
-            <div style={{ left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }} ref={this._timelineWrapper}>
-                <button className="minimize" onClick={this.minimize}>Minimize</button>
-                <div className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} 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={this._playButton} size="2x" /> </div>
-                        <div onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div>
+        let timeline:JSX.Element[] = []; 
+        BoolCast(this.props.Document.isAnimating) ? timeline = [
+            <div key="timeline_wrapper" style={{ left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }} ref={this._timelineWrapper}>
+                <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
+                <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}>
+                    <div key ="timeline_toolbox" className="timeline-toolbox">
+                        <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div>
+                        <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="2x" /> </div>
+                        <div key = "timeline_windForward" 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}>
+                    <div key ="timeline_info"className="info-container" ref={this._infoContainer}>
+                        <div key="timeline_scrubberbox" 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 key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
+                            <div key="timeline_scrubberhead" className="scrubberhead"></div>
                         </div>
-                        <div className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown}>
+                        <div key="timeline_trackbox" 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} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
                         </div>
                     </div>
-                    <div className="title-container" ref={this._titleContainer}>
+                    <div key="timeline_title"className="title-container" ref={this._titleContainer}>
                         {DocListCast(this.children).map(doc => <div className="datapane"><p>{doc.title}</p></div>)}
                     </div>
-                    <div onPointerDown={this.onResizeDown}>
+                    <div key="timeline_resize" onPointerDown={this.onResizeDown}>
                         <FontAwesomeIcon className="resize" icon={faGripLines} />
                     </div>
                 </div>
             </div>
-        );
-    }
-
-}
-
-
-interface TimelineOverviewProps {
-    currentBarX: number;
-}
-
-class TimelineOverview extends React.Component<TimelineOverviewProps>{
-
-    componentWillMount() {
-
-    }
-
-    render() {
-        return (
-            <div className="overview">
-                <div className="container">
-                    <div className="scrubber">
-                        <div className="scrubberhead"></div>
-                    </div>
-                </div>
-            </div>
-        );
-    }
-}
-
+         ] : timeline = [
+            <div key="timeline_toolbox" className="timeline-toolbox">
+                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div>
+                <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="2x" /> </div>
+                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div>
+            </div>];
 
-class TimelineZoom extends React.Component {
-    componentDidMount() {
-    }
-    render() {
         return (
             <div>
-
+                {timeline}
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a7b4f33db..95970cb81 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -107,7 +107,7 @@ const schema = createSchema({
     nativeHeight: "number",
     backgroundColor: "string",
     opacity: "number",
-    hidden: "boolean"
+    hidden: "boolean", 
 });
 
 export const positionSchema = createSchema({
@@ -565,6 +565,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         cm.addItem({ description: "Pin to Presentation", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
         cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
         cm.addItem({ description: "Transcribe Speech", event: this.listen, icon: "microphone" });
+        cm.addItem({ description: BoolCast(this.props.Document.isAnimating) ? "Enter Play Mode" : "Enter Authoring Mode", event: () => {BoolCast(this.props.Document.isAnimating) ? this.props.Document.isAnimating = false : this.props.Document.isAnimating = true;}, icon:BoolCast(this.props.Document.isAnimating) ? "play" : "edit"}); 
         let makes: ContextMenuProps[] = [];
         makes.push({ description: this.props.Document.isBackground ? "Remove Background" : "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
         makes.push({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" });
-- 
cgit v1.2.3-70-g09d2


From eab360d4c415163e4bfe14f167c84b58902971b5 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Mon, 12 Aug 2019 17:04:36 -0400
Subject: authoring/play mode and timeline overview

---
 src/client/views/animationtimeline/Timeline.tsx    | 100 ++++++++++-----------
 .../views/animationtimeline/TimelineOverview.scss  |  13 +++
 .../views/animationtimeline/TimelineOverview.tsx   |  33 +++++++
 3 files changed, 92 insertions(+), 54 deletions(-)
 create mode 100644 src/client/views/animationtimeline/TimelineOverview.scss
 create mode 100644 src/client/views/animationtimeline/TimelineOverview.tsx

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index c8f11db5b..97b9ad4db 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -21,6 +21,7 @@ import { faGrinTongueSquint } from "@fortawesome/free-regular-svg-icons";
 import { InkField } from "../../../new_fields/InkField";
 import { AddComparisonParameters } from "../../northstar/model/idea/idea";
 import { keepAlive } from "mobx-utils";
+import { TimelineOverview } from "./TimelineOverview";
 
 
 export interface FlyoutProps {
@@ -102,24 +103,17 @@ export class Timeline extends CollectionSubView(Document) {
         }
         runInAction(() => {
             reaction(() => {
-                return this.props.Document.isAnimating; 
-            }, async isAnimating => {
-               if (isAnimating){
-                   this._ticks = [];
-                    for (let i = 0; i < this._time;) {
-                        this._ticks.push(i);
-                        i += this._tickIncrement;
-                    }
-                    observe(this._trackbox, change => {if (change.type === "update"){
-                        if (this.props.Document.isAnimating){
-                             let trackbox = this._trackbox.current!;
-                            this._boxLength = this._tickIncrement / 1000 * this._tickSpacing * this._ticks.length;
-                            trackbox.style.width = `${this._boxLength}`;
-                            this._scrubberbox.current!.style.width = `${this._boxLength}`;
-                        }
-                    }}); 
-               }
-                    
+                return 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}`;
+                this._scrubberbox.current!.style.width = `${this._boxLength}`;
             });
         });
     }
@@ -343,47 +337,45 @@ export class Timeline extends CollectionSubView(Document) {
     }
 
     render() {
-        let timeline:JSX.Element[] = []; 
-        BoolCast(this.props.Document.isAnimating) ? timeline = [
-            <div key="timeline_wrapper" style={{ left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }} ref={this._timelineWrapper}>
-                <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
-                <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}>
-                    <div key ="timeline_toolbox" className="timeline-toolbox">
-                        <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div>
-                        <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="2x" /> </div>
-                        <div key = "timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div>
-                    </div>
-                    <div key ="timeline_info"className="info-container" ref={this._infoContainer}>
-                        <div key="timeline_scrubberbox" 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>;
-                            })}
+           
+
+        return (
+            <div>
+                <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}} ref={this._timelineWrapper}>
+                    <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
+                    <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}>
+                        <div key ="timeline_toolbox" className="timeline-toolbox">
+                            <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="4x" /> </div>
+                            <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="4x" /> </div>
+                            <div key = "timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="4x" /> </div>
                         </div>
-                        <div key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
-                            <div key="timeline_scrubberhead" className="scrubberhead"></div>
+                        <div key ="timeline_info"className="info-container" ref={this._infoContainer}>
+                            <div key="timeline_scrubberbox" 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 key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
+                                <div key="timeline_scrubberhead" className="scrubberhead"></div>
+                            </div>
+                            <div key="timeline_trackbox" 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} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
+                            </div>
                         </div>
-                        <div key="timeline_trackbox" 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} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
+                        <div key="timeline_title"className="title-container" ref={this._titleContainer}>
+                            {DocListCast(this.children).map(doc => <div className="datapane"><p>{doc.title}</p></div>)}
+                        </div>
+                        <div key="timeline_resize" onPointerDown={this.onResizeDown}>
+                            <FontAwesomeIcon className="resize" icon={faGripLines} />
                         </div>
-                    </div>
-                    <div key="timeline_title"className="title-container" ref={this._titleContainer}>
-                        {DocListCast(this.children).map(doc => <div className="datapane"><p>{doc.title}</p></div>)}
-                    </div>
-                    <div key="timeline_resize" onPointerDown={this.onResizeDown}>
-                        <FontAwesomeIcon className="resize" icon={faGripLines} />
                     </div>
                 </div>
-            </div>
-         ] : timeline = [
-            <div key="timeline_toolbox" className="timeline-toolbox">
-                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div>
-                <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="2x" /> </div>
-                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div>
-            </div>];
-
-        return (
-            <div>
-                {timeline}
+                <div key="timeline_toolbox" className="timeline-toolbox" style={{visibility: BoolCast(this.props.Document.isAnimating) ? "hidden" :"visible"}}>
+                    <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="4x" /> </div>
+                    <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="4x" /> </div>
+                    <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="4x" /> </div>
+                    <TimelineOverview totalLength={this._time} visibleLength={20} visibleStart={0} changeCurrentBarX={this.changeCurrentBarX}/>
+                </div>
             </div>
         );
     }
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
new file mode 100644
index 000000000..a71abf348
--- /dev/null
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -0,0 +1,13 @@
+.timeline-overview-container{
+    width: 300px; 
+    height: 40px;
+    margin-top: 10px; 
+    margin-left: 20px;  
+    background: white; 
+    border: 1px solid black; 
+    .timeline-overview-visible{
+        height: 100%; 
+        background: green; 
+        border: 1px solid black; 
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
new file mode 100644
index 000000000..0e10e655d
--- /dev/null
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -0,0 +1,33 @@
+import * as React from "react"; 
+import {observable} from "mobx"; 
+import {observer} from "mobx-react";
+import "./TimelineOverview.scss"; 
+
+
+
+interface TimelineOverviewProps{
+    totalLength: number; 
+    visibleLength:number; 
+    visibleStart:number;
+    changeCurrentBarX: (x:number) => any; 
+}
+
+
+export class TimelineOverview extends React.Component<TimelineOverviewProps>{
+
+
+    render(){
+        return(
+            <div key="timeline-overview-container" className="timeline-overview-container">
+                <div key="timeline-overview-visible" className="timeline-overview-visible" style={{left:`${this.props.visibleStart}px`, width:`${this.props.visibleLength}px`}}></div>
+                <div key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container">
+                    <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
+                    <div key="timeline-overview-scrubber-tail" className="tiemline-overview-scrubber-tail"></div>
+                </div>
+            </div>
+        ); 
+    }
+
+}
+
+
-- 
cgit v1.2.3-70-g09d2


From 91335b57dafdeda7a1feb703b0839337fcbbfecd Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 13 Aug 2019 17:26:32 -0400
Subject: timeline overview completed!

---
 src/client/views/animationtimeline/Keyframe.tsx    |  2 +
 src/client/views/animationtimeline/Timeline.tsx    | 77 ++++++++++++++--------
 .../views/animationtimeline/TimelineOverview.scss  | 24 +++++++
 .../views/animationtimeline/TimelineOverview.tsx   | 61 +++++++++++++++--
 src/client/views/animationtimeline/Track.tsx       |  1 +
 5 files changed, 134 insertions(+), 31 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index dbc26e3d4..f6c04d43e 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -91,6 +91,8 @@ export namespace KeyframeFunc {
         regiondata.functions = new List<Doc>(); 
         return regiondata;
     };
+
+    
 }
 
 export const RegionDataSchema = createSchema({
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 97b9ad4db..a29758694 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -1,6 +1,6 @@
 import * as React from "react";
 import "./Timeline.scss";
-import { CollectionSubView } from "../collections/CollectionSubView";
+import { CollectionSubView, SubCollectionViewProps } from "../collections/CollectionSubView";
 import { Document, listSpec } from "../../../new_fields/Schema";
 import { observer } from "mobx-react";
 import { Track } from "./Track";
@@ -35,8 +35,6 @@ export interface FlyoutProps {
 
 @observer
 export class Timeline extends CollectionSubView(Document) {
-    static Instance:Timeline; 
-   
 
     private readonly DEFAULT_CONTAINER_HEIGHT: number = 300;
     private readonly DEFAULT_TICK_SPACING: number = 50;
@@ -53,16 +51,16 @@ export class Timeline extends CollectionSubView(Document) {
     @observable private _trackbox = React.createRef<HTMLDivElement>();
     @observable private _titleContainer = React.createRef<HTMLDivElement>();
     @observable private _timelineContainer = React.createRef<HTMLDivElement>();
-
     @observable private _timelineWrapper = React.createRef<HTMLDivElement>();
     @observable private _infoContainer = React.createRef<HTMLDivElement>();
 
-
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
     @observable private _isPlaying: boolean = false; //scrubber playing
     @observable private _isFrozen: boolean = false; //timeline freeze
-    @observable private _boxLength: number = 0;
+    @observable private _totalLength: number = 0;
+    @observable private _visibleLength: number = 0; 
+    @observable private _visibleStart: number = 0; 
     @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT;
     @observable private _time = 100000; //DEFAULT
     @observable private _ticks: number[] = [];
@@ -83,8 +81,10 @@ export class Timeline extends CollectionSubView(Document) {
         return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
     }
 
+
     componentWillMount() {
         this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false; 
+        console.log(this._currentBarX); 
     }
 
     componentDidMount() {
@@ -99,11 +99,10 @@ export class Timeline extends CollectionSubView(Document) {
                     this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
                 });
             }
-
         }
         runInAction(() => {
             reaction(() => {
-                return this._time; 
+                return this._time;  
             }, () => {
                 this._ticks = [];
                 for (let i = 0; i < this._time;) {
@@ -111,17 +110,22 @@ export class Timeline extends CollectionSubView(Document) {
                     i += this._tickIncrement;
                 }
                 let trackbox = this._trackbox.current!;
-                this._boxLength = this._tickIncrement / 1000 * this._tickSpacing * this._ticks.length;
-                trackbox.style.width = `${this._boxLength}`;
-                this._scrubberbox.current!.style.width = `${this._boxLength}`;
-            });
+                this._totalLength = this._tickSpacing * this._ticks.length;
+                trackbox.style.width = `${this._totalLength}`;
+                this._scrubberbox.current!.style.width = `${this._totalLength}`;
+            }, {fireImmediately:true}); 
+            this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; 
+            this._visibleStart = this._infoContainer.current!.scrollLeft; 
         });
+       
     }
+
+    
    
 
     @action
-    changeCurrentBarX = (x: number) => {
-        this._currentBarX = x;
+    changeCurrentBarX = (pixel: number) => {
+        this._currentBarX = pixel;
     }
 
     //for playing
@@ -139,10 +143,10 @@ export class Timeline extends CollectionSubView(Document) {
 
     @action
     changeCurrentX = () => {
-        if (this._currentBarX === this._boxLength && this._isPlaying) {
+        if (this._currentBarX === this._totalLength && this._isPlaying) {
             this._currentBarX = 0;
         }
-        if (this._currentBarX <= this._boxLength && this._isPlaying) {
+        if (this._currentBarX <= this._totalLength && this._isPlaying) {
             this._currentBarX = this._currentBarX + this._windSpeed;
             setTimeout(this.changeCurrentX, 15);
         }
@@ -208,13 +212,18 @@ export class Timeline extends CollectionSubView(Document) {
     onPanMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let infoContainer = this._infoContainer.current!;
         let trackbox = this._trackbox.current!;
         let titleContainer = this._titleContainer.current!;
-        infoContainer.scrollLeft = infoContainer.scrollLeft - e.movementX;
+        this.movePanX(this._visibleStart - e.movementX);
         trackbox.scrollTop = trackbox.scrollTop - e.movementY;
         titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;
     }
+    @action 
+    movePanX = (pixel:number) => {
+        let infoContainer = this._infoContainer.current!;
+        infoContainer.scrollLeft = pixel; 
+        this._visibleStart = infoContainer.scrollLeft;
+    }
 
 
     @action
@@ -276,7 +285,7 @@ export class Timeline extends CollectionSubView(Document) {
     }
 
     @action
-    toTime = (time: number): string => {
+    toReadTime = (time: number): string => {
         const inSeconds = time / 1000;
         let min: (string | number) = Math.floor(inSeconds / 60);
         let sec: (string | number) = inSeconds % 60;
@@ -288,6 +297,23 @@ export class Timeline extends CollectionSubView(Document) {
     }
 
 
+    convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time") => {
+        let time = dir === "pixel" ?  pos / this._tickSpacing * this._tickIncrement : pos * this._tickSpacing / this._tickIncrement; 
+        switch (unit) {
+            case "mili":
+                return time; 
+            case "sec":
+                return dir === "pixel" ? time / 1000 : time * 1000; 
+            case "min":
+                return dir === "pixel" ? time / 60000 : time * 60000; 
+            case "hr":
+                return dir === "pixel" ? time / 3600000 : time * 3600000; 
+            default: 
+                return time; 
+        }
+    }
+
+
     private _freezeText = "Freeze Timeline";
 
     timelineContextMenu = (e: React.MouseEvent): void => {
@@ -337,22 +363,21 @@ export class Timeline extends CollectionSubView(Document) {
     }
 
     render() {
-           
-
         return (
             <div>
                 <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}} ref={this._timelineWrapper}>
                     <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
                     <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}>
                         <div key ="timeline_toolbox" className="timeline-toolbox">
-                            <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="4x" /> </div>
-                            <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="4x" /> </div>
-                            <div key = "timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="4x" /> </div>
+                            <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div>
+                            <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="2x" /> </div>
+                            <div key = "timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div>
+                            <TimelineOverview currentBarX = { this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> 
                         </div>
                         <div key ="timeline_info"className="info-container" ref={this._infoContainer}>
                             <div key="timeline_scrubberbox" 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>;
+                                    return <div className="tick" style={{ transform: `translate(${element / 1000 * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>;
                                 })}
                             </div>
                             <div key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
@@ -374,7 +399,7 @@ export class Timeline extends CollectionSubView(Document) {
                     <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="4x" /> </div>
                     <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="4x" /> </div>
                     <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="4x" /> </div>
-                    <TimelineOverview totalLength={this._time} visibleLength={20} visibleStart={0} changeCurrentBarX={this.changeCurrentBarX}/>
+                    <TimelineOverview currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> 
                 </div>
             </div>
         );
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index a71abf348..21988927d 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -5,9 +5,33 @@
     margin-left: 20px;  
     background: white; 
     border: 1px solid black; 
+    padding: 0px; 
+    display:inline-block; 
     .timeline-overview-visible{
         height: 100%; 
         background: green; 
         border: 1px solid black; 
+        margin: 0px; 
+    }
+    .timeline-overview-scrubber-container{
+        height: 100%;
+        margin-top: -40px;  
+        margin-left: 0px; 
+        width: 2px; 
+        z-index: 1001;
+        background-color:black; 
+        display: inline-block; 
+        .timeline-overview-scrubber-head{
+            position:absolute; 
+            height: 30px; 
+            width: 30px;
+            background-color:transparent; 
+            border-radius: 50%; 
+            border: 5px solid black; 
+            margin-left: -15px; 
+            top: -15px; 
+
+        }
+        
     }
 }
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 0e10e655d..1ad7d20e5 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -1,5 +1,5 @@
 import * as React from "react"; 
-import {observable} from "mobx"; 
+import {observable, action} from "mobx"; 
 import {observer} from "mobx-react";
 import "./TimelineOverview.scss"; 
 
@@ -9,20 +9,71 @@ interface TimelineOverviewProps{
     totalLength: number; 
     visibleLength:number; 
     visibleStart:number;
-    changeCurrentBarX: (x:number) => any; 
+    currentBarX:number; 
+    changeCurrentBarX: (pixel:number) => void; 
+    movePanX: (pixel:number) => any;
 }
 
 
+@observer
 export class TimelineOverview extends React.Component<TimelineOverviewProps>{
+    @observable private _visibleRef = React.createRef<HTMLDivElement>(); 
+    @observable private _scrubberRef = React.createRef<HTMLDivElement>(); 
+    
+    @action
+    onPointerDown = (e:React.PointerEvent) => {
+        document.removeEventListener("pointermove", this.onPanX); 
+        document.removeEventListener("pointerup", this.onPointerUp); 
+        document.addEventListener("pointermove", this.onPanX); 
+        document.addEventListener("pointerup", this.onPointerUp); 
+    }
+
+    @action
+    onPanX = (e: PointerEvent) => {
+        let movX = (this.props.visibleStart / this.props.totalLength)* 300 + e.movementX; 
+        this.props.movePanX((movX / 300) * this.props.totalLength); 
+    }
+
+    @action
+    onPointerUp = (e: PointerEvent) => {
+        document.removeEventListener("pointermove", this.onPanX); 
+        document.removeEventListener("pointerup", this.onPointerUp); 
+    }
 
+    @action
+    onScrubberDown = ( e:React.PointerEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
+        document.removeEventListener("pointermove", this.onScrubberMove); 
+        document.removeEventListener("pointerup", this.onScrubberUp); 
+        document.addEventListener("pointermove", this.onScrubberMove); 
+        document.addEventListener("pointerup", this.onScrubberUp);
+    }
+
+    @action
+    onScrubberMove = (e: PointerEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
+        let scrubberRef = this._scrubberRef.current!; 
+        let left = scrubberRef.getBoundingClientRect().left; 
+        let offsetX = Math.round(e.clientX - left); 
+        this.props.changeCurrentBarX(((offsetX / 300) * this.props.totalLength) + this.props.currentBarX); 
+    }
+
+    @action
+    onScrubberUp = (e:PointerEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
+        document.removeEventListener("pointermove", this.onScrubberMove); 
+        document.removeEventListener("pointerup", this.onScrubberUp);
+    }
 
     render(){
         return(
             <div key="timeline-overview-container" className="timeline-overview-container">
-                <div key="timeline-overview-visible" className="timeline-overview-visible" style={{left:`${this.props.visibleStart}px`, width:`${this.props.visibleLength}px`}}></div>
-                <div key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container">
+                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{marginLeft:`${(this.props.visibleStart / this.props.totalLength)* 300}px`, width:`${(this.props.visibleLength / this.props.totalLength) * 300}px`}} onPointerDown={this.onPointerDown}></div>
+                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{marginLeft:`${(this.props.currentBarX / this.props.totalLength) * 300}px`}} onPointerDown={this.onScrubberDown}>
                     <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
-                    <div key="timeline-overview-scrubber-tail" className="tiemline-overview-scrubber-tail"></div>
                 </div>
             </div>
         ); 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 64e94f0f1..6bdabeb93 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -94,6 +94,7 @@ export class Track extends React.Component<IProps> {
                 this.props.node.hidden = false;
                 await this.timeChange(this.props.currentBarX);
             } else {
+                console.log("heuulloo"); 
                 this.props.node.hidden = true;
             }
         }, { fireImmediately: true });
-- 
cgit v1.2.3-70-g09d2


From f43509c132b5302b9983667aaf99251051b38b59 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Wed, 14 Aug 2019 11:52:33 -0400
Subject: bug fix with currentBarX

---
 src/client/views/animationtimeline/Keyframe.tsx | 4 ++--
 src/client/views/animationtimeline/Timeline.tsx | 8 ++++----
 src/client/views/animationtimeline/Track.tsx    | 4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index f6c04d43e..6a0525eb8 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -183,8 +183,8 @@ export class Keyframe extends React.Component<IProps> {
         let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!;
         (fadeIn.key! as Doc).opacity = 1;
         (fadeOut.key! as Doc).opacity = 1;
-        (start.key! as Doc).opacity = 0.1;
-        (finish.key! as Doc).opacity = 0.1;
+        (start.key! as Doc).opacity = 0;
+        (finish.key! as Doc).opacity = 0;
 
         observe(this.regiondata, change => {
             if (change.type === "update") {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index a29758694..29787fa03 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -125,7 +125,7 @@ export class Timeline extends CollectionSubView(Document) {
 
     @action
     changeCurrentBarX = (pixel: number) => {
-        this._currentBarX = pixel;
+        pixel <= 0 ? this._currentBarX = 0 : pixel >= this._totalLength ? this._currentBarX = this._totalLength : this._currentBarX = pixel;
     }
 
     //for playing
@@ -184,7 +184,7 @@ export class Timeline extends CollectionSubView(Document) {
         let scrubberbox = this._scrubberbox.current!;
         let left = scrubberbox.getBoundingClientRect().left;
         let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
-        this._currentBarX = offsetX;
+        this.changeCurrentBarX(offsetX); 
     }
 
     @action
@@ -192,8 +192,8 @@ export class Timeline extends CollectionSubView(Document) {
         e.preventDefault();
         e.stopPropagation();
         let scrubberbox = this._scrubberbox.current!;
-        let offset = (e.clientX - scrubberbox.getBoundingClientRect().left) * this.props.ScreenToLocalTransform().Scale;
-        this._currentBarX = offset;
+        let offsetX = (e.clientX - scrubberbox.getBoundingClientRect().left) * this.props.ScreenToLocalTransform().Scale;
+        this.changeCurrentBarX(offsetX); 
     }
 
 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 6bdabeb93..288a1d2ad 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -94,8 +94,8 @@ export class Track extends React.Component<IProps> {
                 this.props.node.hidden = false;
                 await this.timeChange(this.props.currentBarX);
             } else {
-                console.log("heuulloo"); 
-                this.props.node.hidden = true;
+                  this.props.node.hidden = true;
+                  this.props.node.opacity = 0; 
             }
         }, { fireImmediately: true });
     }
-- 
cgit v1.2.3-70-g09d2


From e04277caf25be1c657a2f779a64eb5fcb4e19461 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Wed, 14 Aug 2019 16:08:01 -0400
Subject: UI improvements, pointerevents, and improved overview

---
 src/client/views/animationtimeline/Keyframe.tsx    |  51 +++++++----
 src/client/views/animationtimeline/Timeline.scss   |   2 +-
 src/client/views/animationtimeline/Timeline.tsx    | 100 ++++++++-------------
 .../views/animationtimeline/TimelineOverview.scss  |   5 +-
 .../views/animationtimeline/TimelineOverview.tsx   |  19 ++--
 src/client/views/animationtimeline/Track.tsx       |   5 +-
 src/client/views/graph/GraphManager.ts             |   2 +-
 src/client/views/nodes/DocumentView.tsx            |   2 +-
 8 files changed, 90 insertions(+), 96 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 6a0525eb8..784765318 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -2,10 +2,10 @@ import * as React from "react";
 import "./Keyframe.scss";
 import "./Timeline.scss";
 import "../globalCssVariables.scss";
-import { observer, Observer } from "mobx-react";
-import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS, isComputedProp, runInAction } from "mobx";
+import { observer} from "mobx-react";
+import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction } from "mobx";
 import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
-import { Cast, FieldValue, StrCast, NumCast } from "../../../new_fields/Types";
+import { Cast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new_fields/Schema";
 import { FlyoutProps } from "./Timeline";
@@ -13,7 +13,6 @@ import { Transform } from "../../util/Transform";
 import { InkField, StrokeData } from "../../../new_fields/InkField";
 import { TimelineMenu } from "./TimelineMenu";
 import { Docs } from "../../documents/Documents";
-import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 
 export namespace KeyframeFunc {
@@ -111,7 +110,6 @@ interface IProps {
     RegionData: Doc;
     collection: Doc;
     changeCurrentBarX: (x: number) => void;
-    setFlyout: (props: FlyoutProps) => any;
     transform: Transform;
 }
 
@@ -183,8 +181,8 @@ export class Keyframe extends React.Component<IProps> {
         let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!;
         (fadeIn.key! as Doc).opacity = 1;
         (fadeOut.key! as Doc).opacity = 1;
-        (start.key! as Doc).opacity = 0;
-        (finish.key! as Doc).opacity = 0;
+        (start.key! as Doc).opacity = 0.1;
+        (finish.key! as Doc).opacity = 0.1;
 
         observe(this.regiondata, change => {
             if (change.type === "update") {
@@ -238,14 +236,32 @@ export class Keyframe extends React.Component<IProps> {
         return TK;
     }
 
+    @observable private _mouseToggled = false; 
+    @observable private _doubleClickEnabled = false; 
     @action
     onBarPointerDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        document.addEventListener("pointermove", this.onBarPointerMove);
-        document.addEventListener("pointerup", (e: PointerEvent) => {
+       
+        let clientX = e.clientX;  
+        if (this._doubleClickEnabled){
+            this.createKeyframe(clientX); 
+            this._doubleClickEnabled = false; 
+        } else {
+            setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled)this.props.changeCurrentBarX(this.regiondata.position + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale); 
+                this._mouseToggled = false;            
+                this._doubleClickEnabled = false; }, 200); 
+            this._doubleClickEnabled = true; 
+            document.addEventListener("pointermove", this.onBarPointerMove);
+            document.addEventListener("pointerup", (e: PointerEvent) => {
             document.removeEventListener("pointermove", this.onBarPointerMove);
         });
+        
+        }
+        
+        
+
+        
     }
 
 
@@ -253,6 +269,9 @@ export class Keyframe extends React.Component<IProps> {
     onBarPointerMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
+        if (e.movementX !== 0) {
+            this._mouseToggled = true; 
+        }
         let left = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions)!;
         let right = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions!);
         let prevX = this.regiondata.position;
@@ -351,11 +370,10 @@ export class Keyframe extends React.Component<IProps> {
     }
 
     @action
-    createKeyframe = async (e: React.MouseEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
+    createKeyframe = async (clientX:number) => {
+        this._mouseToggled = true; 
         let bar = this._bar.current!;
-        let offset = Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale);
+        let offset = Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale);
         if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
             let position = NumCast(this.regiondata.position);
             await this.makeKeyData(Math.round(position + offset));
@@ -514,8 +532,7 @@ export class Keyframe extends React.Component<IProps> {
         return (
             <div>
                 <div className="bar" ref={this._bar} style={{ transform: `translate(${this.regiondata.position}px)`, width: `${this.regiondata.duration}px`, background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.regiondata.fadeIn / this.regiondata.duration * 100}%, rgba(77, 153, 0, 1) ${(this.regiondata.duration - this.regiondata.fadeOut) / this.regiondata.duration * 100}%, rgba(77, 153, 0, 0) 100% )` }}
-                    onPointerDown={this.onBarPointerDown}
-                    onDoubleClick={this.createKeyframe}>
+                    onPointerDown={this.onBarPointerDown}>
                     <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
                     <div className="rightResize" onPointerDown={this.onResizeRight}></div>
                     {this.regiondata.keyframes!.map(kf => {
@@ -529,8 +546,10 @@ export class Keyframe extends React.Component<IProps> {
                                 <div ref={bodyRef}className="body-container" style={{left: `${NumCast(kf.time) - this.regiondata.position}px`, width:`${NumCast(left!.time) - NumCast(kf.time)}px`}}
                                 onPointerOver={(e) => { this.onContainerOver(e, bodyRef); }}
                                 onPointerOut={(e) => { this.onContainerOut(e, bodyRef); }}
-                                onPointerDown={(e) => { this.props.changeCurrentBarX(NumCast(kf.time) + (e.clientX - bodyRef.current!.getBoundingClientRect().left) * this.props.transform.Scale);}}
                                 onContextMenu={(e) => {
+                                    e.preventDefault(); 
+                                    e.stopPropagation(); 
+                                    this._mouseToggled = true; 
                                     let items = [
                                         TimelineMenu.Instance.addItem("button", "Add Ease", () => {this.onContainerDown(kf, "interpolate");}),
                                         TimelineMenu.Instance.addItem("button", "Add Path", () => {this.onContainerDown(kf, "path");}), 
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index e5d898502..1457d5a84 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -8,7 +8,7 @@
 }
 
 .timeline-toolbox{
-     position:absolute; 
+    position:absolute; 
     display:flex;
     align-items: flex-start; 
     flex-direction: row;  
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 29787fa03..3d878660d 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -1,26 +1,17 @@
 import * as React from "react";
 import "./Timeline.scss";
-import { CollectionSubView, SubCollectionViewProps } from "../collections/CollectionSubView";
+import { CollectionSubView } from "../collections/CollectionSubView";
 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, StrCast, BoolCast } from "../../../new_fields/Types";
+import { observable, reaction, action, IReactionDisposer, computed, runInAction } from "mobx";
+import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle } from "@fortawesome/free-solid-svg-icons";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ContextMenu } from "../ContextMenu";
-import { DocumentManager } from "../../util/DocumentManager";
-import { VideoBox } from "../nodes/VideoBox";
-import { VideoField } from "../../../new_fields/URLField";
-import { CollectionVideoView } from "../collections/CollectionVideoView";
-import { Transform } from "../../util/Transform";
-import { faGrinTongueSquint } from "@fortawesome/free-regular-svg-icons";
-import { InkField } from "../../../new_fields/InkField";
-import { AddComparisonParameters } from "../../northstar/model/idea/idea";
-import { keepAlive } from "mobx-utils";
 import { TimelineOverview } from "./TimelineOverview";
 
 
@@ -57,7 +48,7 @@ export class Timeline extends CollectionSubView(Document) {
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
     @observable private _isPlaying: boolean = false; //scrubber playing
-    @observable private _isFrozen: boolean = false; //timeline freeze
+    @observable private _isFrozen: boolean = true; //timeline freeze
     @observable private _totalLength: number = 0;
     @observable private _visibleLength: number = 0; 
     @observable private _visibleStart: number = 0; 
@@ -65,7 +56,6 @@ export class Timeline extends CollectionSubView(Document) {
     @observable private _time = 100000; //DEFAULT
     @observable private _ticks: number[] = [];
     @observable private _playButton = faPlayCircle; 
-    @observable private flyoutInfo: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>() };
 
     @computed
     private get children(): List<Doc> {
@@ -130,30 +120,33 @@ export class Timeline extends CollectionSubView(Document) {
 
     //for playing
     @action
-    onPlay = async (e: React.MouseEvent) => {
+    onPlay = (e: React.MouseEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
         if (this._isPlaying) {
             this._isPlaying = false;
             this._playButton = faPlayCircle; 
         } else {
             this._isPlaying = true;
             this._playButton = faPauseCircle; 
-            this.changeCurrentX();
-        }
-    }
-
-    @action
-    changeCurrentX = () => {
-        if (this._currentBarX === this._totalLength && this._isPlaying) {
-            this._currentBarX = 0;
-        }
-        if (this._currentBarX <= this._totalLength && this._isPlaying) {
-            this._currentBarX = this._currentBarX + this._windSpeed;
-            setTimeout(this.changeCurrentX, 15);
+            const playTimeline = () => {
+                if (this._isPlaying){
+                    if (this._currentBarX >= this._totalLength) {
+                        this.changeCurrentBarX(0); 
+                    } else {
+                        this.changeCurrentBarX(this._currentBarX + this._windSpeed);
+                        setTimeout(playTimeline, 15);  
+                    }
+                }
+            }; 
+            playTimeline(); 
         }
     }
 
     @action
     windForward = (e: React.MouseEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
         if (this._windSpeed < 64) { //max speed is 32
             this._windSpeed = this._windSpeed * 2;
         }
@@ -161,6 +154,8 @@ export class Timeline extends CollectionSubView(Document) {
 
     @action
     windBackward = (e: React.MouseEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
         if (this._windSpeed > 1 / 16) { // min speed is 1/8
             this._windSpeed = this._windSpeed / 2;
         }
@@ -313,16 +308,12 @@ export class Timeline extends CollectionSubView(Document) {
         }
     }
 
-
-    private _freezeText = "Freeze Timeline";
-
     timelineContextMenu = (e: React.MouseEvent): void => {
         let subitems: ContextMenuProps[] = [];
         let timelineContainer = this._timelineWrapper.current!;
         subitems.push({
             description: "Pin to Top", event: action(() => {
                 if (!this._isFrozen) {
-                    timelineContainer.style.transition = "top 1000ms ease-in, left 1000ms ease-in";  //?????
                     timelineContainer.style.left = "0px";
                     timelineContainer.style.top = "0px";
                     timelineContainer.style.transition = "none";
@@ -330,22 +321,11 @@ export class Timeline extends CollectionSubView(Document) {
             }), icon: faArrowUp
         });
         subitems.push({
-            description: "Pin to Bottom", event: action(() => {
-                console.log(this.props.Document.y);
-
-                if (!this._isFrozen) {
-                    timelineContainer.style.transform = `translate(0px, ${e.pageY - this._containerHeight}px)`;
-                }
-            }), icon: faArrowDown
-        });
-        subitems.push({
-            description: this._freezeText, event: action(() => {
+            description: this._isFrozen ? "Unfreeze Timeline" : "Freeze Timeline", event: action(() => {
                 if (this._isFrozen) {
                     this._isFrozen = false;
-                    this._freezeText = "Freeze Timeline";
                 } else {
                     this._isFrozen = true;
-                    this._freezeText = "Unfreeze Timeline";
                 }
             }), icon: "thumbtack"
         });
@@ -353,27 +333,24 @@ export class Timeline extends CollectionSubView(Document) {
     }
 
 
-
-    @action
-    getFlyout = (props: FlyoutProps) => {
-        for (const [k, v] of Object.entries(props)) {
-            (this.flyoutInfo as any)[k] = v;
-        }
-        console.log(this.flyoutInfo); 
+    private timelineToolBox = (scale:number) => {
+        let size = 50 * scale; //50 is default
+        return (
+        <div key="timeline_toolbox" className="timeline-toolbox" style={{height:`${size}px`}}>
+                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{height:`${size}px`, width: `${size}px`}} /> </div>
+                <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
+                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
+                <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> 
+        </div>
+        );
     }
-
     render() {
         return (
             <div>
                 <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}} ref={this._timelineWrapper}>
                     <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
                     <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}>
-                        <div key ="timeline_toolbox" className="timeline-toolbox">
-                            <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div>
-                            <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="2x" /> </div>
-                            <div key = "timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div>
-                            <TimelineOverview currentBarX = { this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> 
-                        </div>
+                        {this.timelineToolBox(0.5)}
                         <div key ="timeline_info"className="info-container" ref={this._infoContainer}>
                             <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} onClick={this.onScrubberClick}>
                                 {this._ticks.map(element => {
@@ -384,7 +361,7 @@ export class Timeline extends CollectionSubView(Document) {
                                 <div key="timeline_scrubberhead" className="scrubberhead"></div>
                             </div>
                             <div key="timeline_trackbox" 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} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
+                                {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
                             </div>
                         </div>
                         <div key="timeline_title"className="title-container" ref={this._titleContainer}>
@@ -395,12 +372,7 @@ export class Timeline extends CollectionSubView(Document) {
                         </div>
                     </div>
                 </div>
-                <div key="timeline_toolbox" className="timeline-toolbox" style={{visibility: BoolCast(this.props.Document.isAnimating) ? "hidden" :"visible"}}>
-                    <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="4x" /> </div>
-                    <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="4x" /> </div>
-                    <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="4x" /> </div>
-                    <TimelineOverview currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> 
-                </div>
+                {BoolCast(this.props.Document.isAnimating) ? <div></div>: this.timelineToolBox(1) }
             </div>
         );
     }
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index 21988927d..9e69c2adf 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -1,16 +1,17 @@
+@import "./../globalCssVariables.scss"; 
+
 .timeline-overview-container{
     width: 300px; 
     height: 40px;
     margin-top: 10px; 
     margin-left: 20px;  
     background: white; 
-    border: 1px solid black; 
+    border: 2px solid black; 
     padding: 0px; 
     display:inline-block; 
     .timeline-overview-visible{
         height: 100%; 
         background: green; 
-        border: 1px solid black; 
         margin: 0px; 
     }
     .timeline-overview-scrubber-container{
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 1ad7d20e5..4fdf1381e 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -6,6 +6,7 @@ import "./TimelineOverview.scss";
 
 
 interface TimelineOverviewProps{
+    scale: number; 
     totalLength: number; 
     visibleLength:number; 
     visibleStart:number;
@@ -19,7 +20,9 @@ interface TimelineOverviewProps{
 export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     @observable private _visibleRef = React.createRef<HTMLDivElement>(); 
     @observable private _scrubberRef = React.createRef<HTMLDivElement>(); 
-    
+    private readonly DEFAULT_HEIGHT = 50; 
+    private readonly DEFAULT_WIDTH = 300; 
+
     @action
     onPointerDown = (e:React.PointerEvent) => {
         document.removeEventListener("pointermove", this.onPanX); 
@@ -30,8 +33,8 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
     @action
     onPanX = (e: PointerEvent) => {
-        let movX = (this.props.visibleStart / this.props.totalLength)* 300 + e.movementX; 
-        this.props.movePanX((movX / 300) * this.props.totalLength); 
+        let movX = (this.props.visibleStart / this.props.totalLength)* (this.DEFAULT_WIDTH * this.props.scale) + e.movementX; 
+        this.props.movePanX((movX / (this.DEFAULT_WIDTH * this.props.scale)) * this.props.totalLength); 
     }
 
     @action
@@ -57,7 +60,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         let scrubberRef = this._scrubberRef.current!; 
         let left = scrubberRef.getBoundingClientRect().left; 
         let offsetX = Math.round(e.clientX - left); 
-        this.props.changeCurrentBarX(((offsetX / 300) * this.props.totalLength) + this.props.currentBarX); 
+        this.props.changeCurrentBarX(((offsetX / (this.DEFAULT_WIDTH * this.props.scale)) * this.props.totalLength) + this.props.currentBarX); 
     }
 
     @action
@@ -70,10 +73,10 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
     render(){
         return(
-            <div key="timeline-overview-container" className="timeline-overview-container">
-                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{marginLeft:`${(this.props.visibleStart / this.props.totalLength)* 300}px`, width:`${(this.props.visibleLength / this.props.totalLength) * 300}px`}} onPointerDown={this.onPointerDown}></div>
-                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{marginLeft:`${(this.props.currentBarX / this.props.totalLength) * 300}px`}} onPointerDown={this.onScrubberDown}>
-                    <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
+            <div key="timeline-overview-container" className="timeline-overview-container" style={{height: `${this.DEFAULT_HEIGHT * this.props.scale * 0.8}px` ,width:`${this.DEFAULT_WIDTH * this.props.scale}`}}>
+                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{marginLeft:`${(this.props.visibleStart / this.props.totalLength)* this.DEFAULT_WIDTH * this.props.scale}px`, width:`${(this.props.visibleLength / this.props.totalLength) * this.DEFAULT_WIDTH * this.props.scale}px`}} onPointerDown={this.onPointerDown}></div>
+                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{marginLeft:`${(this.props.currentBarX / this.props.totalLength) * this.DEFAULT_WIDTH * this.props.scale}px`, marginTop: `${-this.DEFAULT_HEIGHT * this.props.scale * 0.8}px`}} onPointerDown={this.onScrubberDown}>
+                    <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head" style={{}}></div>
                 </div>
             </div>
         ); 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 288a1d2ad..d91954022 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -17,7 +17,6 @@ interface IProps {
     transform: Transform;
     collection: Doc; 
     changeCurrentBarX: (x: number) => void;
-    setFlyout: (props: FlyoutProps) => any;
 }
 
 @observer
@@ -177,7 +176,7 @@ export class Track extends React.Component<IProps> {
         const timeratio = (this.props.currentBarX - NumCast(left.time)) / dif_time; //linear 
         let keyframes = (await DocListCastAsync(regiondata.keyframes!))!; 
         let indexLeft = keyframes.indexOf(left); 
-        let interY:List<number> = await ((regiondata.functions as List<Doc>)[indexLeft] as Doc).interpolationY as List<number>;  
+        let interY:List<number> = (await ((regiondata.functions as List<Doc>)[indexLeft] as Doc).interpolationY as List<number>)!;  
         let realIndex = (interY.length - 1) * timeratio; 
         let xIndex = Math.floor(realIndex);  
         let yValue = interY[xIndex]; 
@@ -276,7 +275,7 @@ export class Track extends React.Component<IProps> {
                 <div className="track">
                     <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick}>
                         {DocListCast(this.regions).map((region) => {
-                            return <Keyframe node={this.props.node} RegionData={region} changeCurrentBarX={this.props.changeCurrentBarX} setFlyout={this.props.setFlyout} transform={this.props.transform} collection={this.props.collection}/>;
+                            return <Keyframe node={this.props.node} RegionData={region} changeCurrentBarX={this.props.changeCurrentBarX} transform={this.props.transform} collection={this.props.collection}/>;
                         })}
                     </div>
                 </div>
diff --git a/src/client/views/graph/GraphManager.ts b/src/client/views/graph/GraphManager.ts
index 9d62b1ef8..b62f2337b 100644
--- a/src/client/views/graph/GraphManager.ts
+++ b/src/client/views/graph/GraphManager.ts
@@ -32,7 +32,7 @@ export class GraphManager {
 
     
     defaultGraphs = ()  => {
-        this.GraphData.linear = ; 
+        
     }
 
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f2be7097a..28af39fb3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -729,7 +729,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
 
     render() {
-        trace();
+        // trace();
         let backgroundColor = this.layoutDoc.isBackground || (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground && this.layoutDoc.backgroundColor === this.layoutDoc.defaultBackgroundColor) ?
             this.props.backgroundColor(this.layoutDoc) || StrCast(this.layoutDoc.backgroundColor) :
             StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc);
-- 
cgit v1.2.3-70-g09d2


From 3d99b990b95edd6481a6c12bc994cdac87e6c8dc Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Thu, 15 Aug 2019 12:48:06 -0400
Subject: uiux

---
 src/client/views/animationtimeline/Keyframe.tsx    |  8 +----
 src/client/views/animationtimeline/Timeline.tsx    | 30 +++++++++++++----
 .../views/animationtimeline/TimelineMenu.tsx       | 39 ++++++----------------
 3 files changed, 36 insertions(+), 41 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 784765318..4e58b07d8 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -242,7 +242,6 @@ export class Keyframe extends React.Component<IProps> {
     onBarPointerDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-       
         let clientX = e.clientX;  
         if (this._doubleClickEnabled){
             this.createKeyframe(clientX); 
@@ -254,14 +253,9 @@ export class Keyframe extends React.Component<IProps> {
             this._doubleClickEnabled = true; 
             document.addEventListener("pointermove", this.onBarPointerMove);
             document.addEventListener("pointerup", (e: PointerEvent) => {
-            document.removeEventListener("pointermove", this.onBarPointerMove);
+                document.removeEventListener("pointermove", this.onBarPointerMove);
         });
-        
         }
-        
-        
-
-        
     }
 
 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 3d878660d..10034263c 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -135,8 +135,8 @@ export class Timeline extends CollectionSubView(Document) {
                         this.changeCurrentBarX(0); 
                     } else {
                         this.changeCurrentBarX(this._currentBarX + this._windSpeed);
-                        setTimeout(playTimeline, 15);  
-                    }
+                    }                        
+                    setTimeout(playTimeline, 15);  
                 }
             }; 
             playTimeline(); 
@@ -193,20 +193,38 @@ export class Timeline extends CollectionSubView(Document) {
 
 
 
+    @observable private _mouseToggled = false; 
+    @observable private _doubleClickEnabled = false; 
     @action
     onPanDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        document.addEventListener("pointermove", this.onPanMove);
-        document.addEventListener("pointerup", () => {
-            document.removeEventListener("pointermove", this.onPanMove);
-        });
+        let clientX = e.clientX; 
+        if (this._doubleClickEnabled){
+            this._doubleClickEnabled = false; 
+        } else {
+            setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled) this.changeCurrentBarX(this._trackbox.current!.scrollLeft + clientX -  this._trackbox.current!.getBoundingClientRect().left); 
+                this._mouseToggled = false;
+                this._doubleClickEnabled = false;}, 200); 
+            this._doubleClickEnabled = true; 
+            document.addEventListener("pointermove", this.onPanMove);
+            document.addEventListener("pointerup", () => {
+                document.removeEventListener("pointermove", this.onPanMove);
+                if (!this._doubleClickEnabled) {
+                    this._mouseToggled = false; 
+                }
+            });
+
+        }
     }
 
     @action
     onPanMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
+        if (e.movementX !== 0 || e.movementY !== 0) {
+            this._mouseToggled = true; 
+        }
         let trackbox = this._trackbox.current!;
         let titleContainer = this._titleContainer.current!;
         this.movePanX(this._visibleStart - e.movementX);
diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx
index 4223ee099..3e63eec61 100644
--- a/src/client/views/animationtimeline/TimelineMenu.tsx
+++ b/src/client/views/animationtimeline/TimelineMenu.tsx
@@ -19,28 +19,6 @@ export class TimelineMenu extends React.Component {
         super(props); 
         TimelineMenu.Instance = this; 
     }
-
-    @action
-    pointerDown = (e: React.PointerEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        document.removeEventListener("pointerup", this.pointerUp); 
-        document.addEventListener("pointerup", this.pointerUp); 
-        document.removeEventListener("pointermove", this.pointerMove); 
-        document.addEventListener("pointermove", this.pointerMove);     
-    }
-
-    @action
-    pointerMove = (e: PointerEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
-    }
-
-    @action
-    pointerUp = (e: PointerEvent) => {
-        document.removeEventListener("pointermove", this.pointerMove); 
-        document.removeEventListener("pointerup", this.pointerUp); 
-    }
     
     @action
     openMenu = (x?:number, y?:number) => {
@@ -52,16 +30,20 @@ export class TimelineMenu extends React.Component {
     @action
     closeMenu = () => {
         this._opacity = 0; 
+        this._currentMenu = []; 
     }
 
     addItem = (type: "input" | "button", title: string, event: (e:any) => void) => {
         if (type === "input"){
             let ref = React.createRef<HTMLInputElement>(); 
-            let text = ""; 
-            return <div className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {ref} placeholder={title} onChange={(e) => {text = e.target.value;}} onKeyDown={(e:React.KeyboardEvent) => {
-                if(e.keyCode === 13){
-                    event(text); 
-                }}}/></div>; 
+            return <div className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {ref} placeholder={title} onChange={(e) => {
+                let text = e.target.value;
+                document.addEventListener("keypress", (e:KeyboardEvent) => {
+                    if (e.keyCode === 13) {
+                        event(text); 
+                    }
+                });
+            }}/></div>; 
         } else if (type === "button") {
             let ref = React.createRef<HTMLDivElement>(); 
             return <div className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={event}>{title}</p></div>; 
@@ -72,7 +54,8 @@ export class TimelineMenu extends React.Component {
     @action 
     addMenu = (title:string, items: JSX.Element[]) => {
         items.unshift(<div className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>); 
-        this._currentMenu = items;  
+        this._currentMenu = items;
+    
     }
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From 02f5eed127280a6827ed57e86663291ce184495b Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Thu, 15 Aug 2019 17:05:53 -0400
Subject: Timeline visibility

---
 src/client/views/animationtimeline/Timeline.tsx    | 46 ++++++++++++++++------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  6 +--
 src/client/views/nodes/DocumentView.tsx            |  1 -
 3 files changed, 36 insertions(+), 17 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 10034263c..be1ae1773 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -4,15 +4,18 @@ import { CollectionSubView } from "../collections/CollectionSubView";
 import { Document, listSpec } from "../../../new_fields/Schema";
 import { observer } from "mobx-react";
 import { Track } from "./Track";
-import { observable, reaction, action, IReactionDisposer, computed, runInAction } from "mobx";
+import { observable, reaction, action, IReactionDisposer, computed, runInAction, observe } from "mobx";
 import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle } from "@fortawesome/free-solid-svg-icons";
+import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
+import { playcustomapp } from "googleapis/build/src/apis/playcustomapp";
+import { FieldView, FieldViewProps } from "../nodes/FieldView";
+
 
 
 export interface FlyoutProps {
@@ -25,7 +28,7 @@ export interface FlyoutProps {
 
 
 @observer
-export class Timeline extends CollectionSubView(Document) {
+export class Timeline extends React.Component<FieldViewProps> {
 
     private readonly DEFAULT_CONTAINER_HEIGHT: number = 300;
     private readonly DEFAULT_TICK_SPACING: number = 50;
@@ -56,6 +59,7 @@ export class Timeline extends CollectionSubView(Document) {
     @observable private _time = 100000; //DEFAULT
     @observable private _ticks: number[] = [];
     @observable private _playButton = faPlayCircle; 
+    @observable private _timelineVisible = false; 
 
     @computed
     private get children(): List<Doc> {
@@ -74,6 +78,7 @@ export class Timeline extends CollectionSubView(Document) {
 
     componentWillMount() {
         this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false; 
+        document.addEventListener("contextmenu", (e) => {this.timelineContextMenu(e);});
         console.log(this._currentBarX); 
     }
 
@@ -86,7 +91,12 @@ export class Timeline extends CollectionSubView(Document) {
                 reaction(() => {
                     return NumCast(this.props.Document.curPage);
                 }, curPage => {
-                    this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
+                    if (!this._isPlaying) {
+                        this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
+                        this.props.Document.curPage = this._currentBarX; 
+                        this.play(); 
+                    }
+                   
                 });
             }
         }
@@ -123,6 +133,10 @@ export class Timeline extends CollectionSubView(Document) {
     onPlay = (e: React.MouseEvent) => {
         e.preventDefault(); 
         e.stopPropagation(); 
+        this.play(); 
+    }
+
+    play = () => {
         if (this._isPlaying) {
             this._isPlaying = false;
             this._playButton = faPlayCircle; 
@@ -143,6 +157,8 @@ export class Timeline extends CollectionSubView(Document) {
         }
     }
 
+
+
     @action
     windForward = (e: React.MouseEvent) => {
         e.preventDefault(); 
@@ -326,7 +342,7 @@ export class Timeline extends CollectionSubView(Document) {
         }
     }
 
-    timelineContextMenu = (e: React.MouseEvent): void => {
+    timelineContextMenu = (e:MouseEvent): void => {
         let subitems: ContextMenuProps[] = [];
         let timelineContainer = this._timelineWrapper.current!;
         subitems.push({
@@ -340,13 +356,17 @@ export class Timeline extends CollectionSubView(Document) {
         });
         subitems.push({
             description: this._isFrozen ? "Unfreeze Timeline" : "Freeze Timeline", event: action(() => {
-                if (this._isFrozen) {
-                    this._isFrozen = false;
-                } else {
-                    this._isFrozen = true;
-                }
+                this._isFrozen = !this._isFrozen; 
             }), icon: "thumbtack"
         });
+        subitems.push({
+            description: this._timelineVisible ? "Hide Timeline" : "Show Timeline", event: action(() => {
+                this._timelineVisible = !this._timelineVisible; 
+            }), icon: this._timelineVisible ? faEyeSlash : "eye"
+        }); 
+        subitems.push({ description: BoolCast(this.props.Document.isAnimating) ? "Enter Play Mode" : "Enter Authoring Mode", event: () => {
+            BoolCast(this.props.Document.isAnimating) ? this.props.Document.isAnimating = false : this.props.Document.isAnimating = true;}
+            , icon:BoolCast(this.props.Document.isAnimating) ? "play" : "edit"}); 
         ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems, icon: faClock });
     }
 
@@ -364,10 +384,10 @@ export class Timeline extends CollectionSubView(Document) {
     }
     render() {
         return (
-            <div>
-                <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}} ref={this._timelineWrapper}>
+            <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}>
+                <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}} ref={this._timelineWrapper}>
                     <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
-                    <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}>
+                    <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown}>
                         {this.timelineToolBox(0.5)}
                         <div key ="timeline_info"className="info-container" ref={this._infoContainer}>
                             <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} onClick={this.onScrubberClick}>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d01e5cadc..d10150f30 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -742,7 +742,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         }
         let docviews = docs.filter(doc => doc instanceof Doc).reduce((prev, doc) => {
             var page = NumCast(doc.page, -1);
-            if ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1) {
+          //  if ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1) {
                 let minim = BoolCast(doc.isMinimized);
                 if (minim === undefined || !minim) {
                     const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) :
@@ -755,7 +755,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                         bounds: (pos.x !== undefined && pos.y !== undefined) ? { x: pos.x, y: pos.y, z: pos.z, width: NumCast(pos.width), height: NumCast(pos.height) } : undefined
                     });
                 }
-            }
+           // }
             return prev;
         }, elements);
 
@@ -902,7 +902,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                         <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />
                     </CollectionFreeFormViewPannableContents>
                 </MarqueeView>
-                <Timeline {...this.props} />
+                <Timeline {...this.props}/>
                 {this.overlayChildViews()}
                 <CollectionFreeFormOverlayView  {...this.props} {...this.getDocumentViewProps(this.props.Document)} />
             </div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 28af39fb3..8d33c4570 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -570,7 +570,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" });
         subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" });
         cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" });
-        cm.addItem({ description: BoolCast(this.props.Document.isAnimating) ? "Enter Play Mode" : "Enter Authoring Mode", event: () => {BoolCast(this.props.Document.isAnimating) ? this.props.Document.isAnimating = false : this.props.Document.isAnimating = true;}, icon:BoolCast(this.props.Document.isAnimating) ? "play" : "edit"}); 
         let existingMake = ContextMenu.Instance.findByDescription("Make...");
         let makes: ContextMenuProps[] = existingMake && "subitems" in existingMake ? existingMake.subitems : [];
         makes.push({ description: this.props.Document.isBackground ? "Remove Background" : "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
-- 
cgit v1.2.3-70-g09d2


From 078abf5548a18945527f12dde1a79095bd30e50e Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Fri, 16 Aug 2019 00:08:45 -0400
Subject: partially working zoom

---
 src/client/views/animationtimeline/Timeline.tsx    | 61 +++++++++++++++-------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  9 ++--
 src/client/views/nodes/VideoBox.tsx                |  2 +
 3 files changed, 49 insertions(+), 23 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index be1ae1773..d0f83676b 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -60,6 +60,9 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _ticks: number[] = [];
     @observable private _playButton = faPlayCircle; 
     @observable private _timelineVisible = false; 
+    @observable private _mouseToggled = false; 
+    @observable private _doubleClickEnabled = false; 
+
 
     @computed
     private get children(): List<Doc> {
@@ -78,8 +81,6 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     componentWillMount() {
         this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false; 
-        document.addEventListener("contextmenu", (e) => {this.timelineContextMenu(e);});
-        console.log(this._currentBarX); 
     }
 
     componentDidMount() {
@@ -92,7 +93,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                     return NumCast(this.props.Document.curPage);
                 }, curPage => {
                     if (!this._isPlaying) {
-                        this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
+                        this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing); 
                         this.props.Document.curPage = this._currentBarX; 
                         this.play(); 
                     }
@@ -107,21 +108,17 @@ export class Timeline extends React.Component<FieldViewProps> {
                 this._ticks = [];
                 for (let i = 0; i < this._time;) {
                     this._ticks.push(i);
-                    i += this._tickIncrement;
+                    i += 1000;
                 }
-                let trackbox = this._trackbox.current!;
-                this._totalLength = this._tickSpacing * this._ticks.length;
-                trackbox.style.width = `${this._totalLength}`;
-                this._scrubberbox.current!.style.width = `${this._totalLength}`;
+                this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); 
             }, {fireImmediately:true}); 
+            this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); 
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; 
-            this._visibleStart = this._infoContainer.current!.scrollLeft; 
+            this._visibleStart = this._infoContainer.current!.scrollLeft;   
         });
        
-    }
 
-    
-   
+    }
 
     @action
     changeCurrentBarX = (pixel: number) => {
@@ -136,6 +133,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         this.play(); 
     }
 
+    @action
     play = () => {
         if (this._isPlaying) {
             this._isPlaying = false;
@@ -209,8 +207,6 @@ export class Timeline extends React.Component<FieldViewProps> {
 
 
 
-    @observable private _mouseToggled = false; 
-    @observable private _doubleClickEnabled = false; 
     @action
     onPanDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -370,6 +366,35 @@ export class Timeline extends React.Component<FieldViewProps> {
         ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems, icon: faClock });
     }
 
+    @action
+    onWheelZoom = (e: React.WheelEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
+        e.deltaY < 0 ? this.zoom(true) : this.zoom(false); 
+    }
+
+    @action
+    zoom = (dir: boolean) => {
+        if (dir){
+            if (!(this._tickSpacing === 100 && this._tickIncrement === 1000)){
+                if (this._tickSpacing >= 100) {
+                    this._tickIncrement /= 2; 
+                    this._tickSpacing = 50; 
+                    this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); //CONSIDER THIS MUST CHANGE
+                } else {
+                    this._tickSpacing += 10; 
+                }
+            } 
+        } else {
+            if (this._tickSpacing <= 50) {
+                this._tickSpacing = 100; 
+                this._tickIncrement *= 2; 
+                this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); //CONSIDER THIS MUST CHANGE
+            } else {
+                this._tickSpacing -= 10; 
+            }
+        }
+    }
 
     private timelineToolBox = (scale:number) => {
         let size = 50 * scale; //50 is default
@@ -389,16 +414,16 @@ export class Timeline extends React.Component<FieldViewProps> {
                     <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
                     <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown}>
                         {this.timelineToolBox(0.5)}
-                        <div key ="timeline_info"className="info-container" ref={this._infoContainer}>
-                            <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} onClick={this.onScrubberClick}>
+                        <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
+                            <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} 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.toReadTime(element)}</p></div>;
+                                    if(element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement)* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>;
                                 })}
                             </div>
                             <div key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
                                 <div key="timeline_scrubberhead" className="scrubberhead"></div>
                             </div>
-                            <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown}>
+                            <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}>
                                 {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
                             </div>
                         </div>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d10150f30..b932db424 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -194,6 +194,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private _lastY: number = 0;
     private get _pwidth() { return this.props.PanelWidth(); }
     private get _pheight() { return this.props.PanelHeight(); }
+    private _timelineRef = React.createRef<Timeline>(); 
     private inkKey = "ink";
 
     constructor(props: any) {
@@ -842,6 +843,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         let analyzers: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : [];
         analyzers.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
         !existingAnalyze && ContextMenu.Instance.addItem({ description: "Analyzers...", subitems: analyzers, icon: "hand-point-right" });
+        this._timelineRef.current!.timelineContextMenu(e.nativeEvent); 
     }
 
 
@@ -879,10 +881,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             addOverlay("arrangeInit", { x: 400, y: 100, width: 400, height: 300, title: "Layout Initialization" }, { collection: "Doc", docs: "Doc[]" }, undefined);
             addOverlay("arrangeScript", { x: 400, y: 500, width: 400, height: 300, title: "Layout Script" }, { doc: "Doc", index: "number", collection: "Doc", state: "any", docs: "Doc[]" }, "{x: number, y: number, width?: number, height?: number}");
         };
-    }
-    private _timeline = <Timeline {...this.props}/>; 
-    se = () => {
-    }
+    }  
     render() {
         const easing = () => this.props.Document.panTransformType === "Ease";
         Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
@@ -902,7 +901,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                         <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />
                     </CollectionFreeFormViewPannableContents>
                 </MarqueeView>
-                <Timeline {...this.props}/>
+                <Timeline ref={this._timelineRef} {...this.props}/>
                 {this.overlayChildViews()}
                 <CollectionFreeFormOverlayView  {...this.props} {...this.getDocumentViewProps(this.props.Document)} />
             </div>
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 704030d85..a33155fff 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -166,6 +166,8 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
                 this.Document.height = FieldValue(this.Document.width, 0) / youtubeaspect;
             }
         }
+        
+        this.player && (this.player.style.transform = ""); 
     }
 
     componentWillUnmount() {
-- 
cgit v1.2.3-70-g09d2


From 8ab017ac1928db4a9a9f8eb6b579245814cde725 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Fri, 16 Aug 2019 17:26:43 -0400
Subject: zooming fixes

---
 src/client/views/animationtimeline/Keyframe.tsx | 169 +++++++++++++-----------
 src/client/views/animationtimeline/Timeline.tsx |  35 ++---
 src/client/views/animationtimeline/Track.tsx    |  49 +++++--
 3 files changed, 139 insertions(+), 114 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 4e58b07d8..b02d89bf0 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -82,16 +82,30 @@ export namespace KeyframeFunc {
     };
 
     export const defaultKeyframe = () => {
-        let regiondata = new Doc(); //creating regiondata
-        regiondata.duration = 200;
+        let regiondata = new Doc(); //creating regiondata in MILI
+        regiondata.duration = 4000;
         regiondata.position = 0;
-        regiondata.fadeIn = 20;
-        regiondata.fadeOut = 20;
+        regiondata.fadeIn = 1000;
+        regiondata.fadeOut = 1000;
         regiondata.functions = new List<Doc>(); 
         return regiondata;
     };
 
-    
+    export const convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time", tickSpacing:number, tickIncrement:number) => {
+        let time = dir === "pixel" ? (pos * tickSpacing) / tickIncrement : (pos / tickSpacing) * tickIncrement; 
+        switch (unit) {
+            case "mili":
+                return time; 
+            case "sec":
+                return dir === "pixel" ? time / 1000 : time * 1000; 
+            case "min":
+                return dir === "pixel" ? time / 60000 : time * 60000; 
+            case "hr":
+                return dir === "pixel" ? time / 3600000 : time * 3600000; 
+            default: 
+                return time; 
+        }
+    };
 }
 
 export const RegionDataSchema = createSchema({
@@ -109,6 +123,9 @@ interface IProps {
     node: Doc;
     RegionData: Doc;
     collection: Doc;
+    tickSpacing: number; 
+    tickIncrement: number; 
+    time: number; 
     changeCurrentBarX: (x: number) => void;
     transform: Transform;
 }
@@ -118,6 +135,8 @@ export class Keyframe extends React.Component<IProps> {
 
     @observable private _bar = React.createRef<HTMLDivElement>();
     @observable private _gain = 20; //default
+    @observable private _mouseToggled = false; 
+    @observable private _doubleClickEnabled = false; 
 
     @computed
     private get regiondata() {
@@ -155,6 +174,7 @@ export class Keyframe extends React.Component<IProps> {
         });
         return last;
     }
+
     @computed
     private get keyframes(){
         return DocListCast(this.regiondata.keyframes); 
@@ -171,6 +191,26 @@ export class Keyframe extends React.Component<IProps> {
         }
     }
 
+    @computed 
+    private get pixelPosition(){
+        return KeyframeFunc.convertPixelTime(this.regiondata.position, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
+    }
+
+    @computed 
+    private get pixelDuration(){
+        return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
+    }
+
+    @computed
+    private get pixelFadeIn() {
+        return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
+    }
+
+    @computed
+    private get pixelFadeOut(){
+        return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
+    }
+
     async componentWillMount() {
         if (!this.regiondata.keyframes) {
             this.regiondata.keyframes = new List<Doc>();
@@ -183,20 +223,6 @@ export class Keyframe extends React.Component<IProps> {
         (fadeOut.key! as Doc).opacity = 1;
         (start.key! as Doc).opacity = 0.1;
         (finish.key! as Doc).opacity = 0.1;
-
-        observe(this.regiondata, change => {
-            if (change.type === "update") {
-                fadeIn.time = this.regiondata.position + this.regiondata.fadeIn;
-                fadeOut.time = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut;
-                start.time = this.regiondata.position;
-                finish.time = this.regiondata.position + this.regiondata.duration;
-                this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(fadeIn)] = fadeIn;
-                this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(fadeOut)] = fadeOut;
-                this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(start)] = start;
-                this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(finish)] = finish;
-                this.forceUpdate();
-            }
-        });
     }
 
     @action
@@ -236,8 +262,7 @@ export class Keyframe extends React.Component<IProps> {
         return TK;
     }
 
-    @observable private _mouseToggled = false; 
-    @observable private _doubleClickEnabled = false; 
+    
     @action
     onBarPointerDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -247,14 +272,14 @@ export class Keyframe extends React.Component<IProps> {
             this.createKeyframe(clientX); 
             this._doubleClickEnabled = false; 
         } else {
-            setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled)this.props.changeCurrentBarX(this.regiondata.position + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale); 
+            setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled)this.props.changeCurrentBarX(this.pixelPosition + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale); 
                 this._mouseToggled = false;            
                 this._doubleClickEnabled = false; }, 200); 
             this._doubleClickEnabled = true; 
             document.addEventListener("pointermove", this.onBarPointerMove);
             document.addEventListener("pointerup", (e: PointerEvent) => {
                 document.removeEventListener("pointermove", this.onBarPointerMove);
-        });
+            });
         }
     }
 
@@ -269,23 +294,20 @@ export class Keyframe extends React.Component<IProps> {
         let left = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions)!;
         let right = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions!);
         let prevX = this.regiondata.position;
-        let futureX = this.regiondata.position + e.movementX;
+        let futureX = this.regiondata.position + KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         if (futureX <= 0) {
             this.regiondata.position = 0;
         } else if ((left && left.position + left.duration >= futureX)) {
             this.regiondata.position = left.position + left.duration;
-        } else if ((right && right.position <= futureX + this.regiondata.duration)) {
-            this.regiondata.position = right.position - this.regiondata.duration;
+        } else if ((right && right.position <= futureX + this.pixelDuration)) {
+            this.regiondata.position = right.position - this.pixelDuration;
         } else {
             this.regiondata.position = futureX;
-        }
-        for (let i = 0; i < this.regiondata.keyframes!.length; i++) {
-            if ((this.regiondata.keyframes![i] as Doc).type !== KeyframeFunc.KeyframeType.fade) {
-                let movement = this.regiondata.position - prevX;
-                (this.regiondata.keyframes![i] as Doc).time = NumCast((this.regiondata.keyframes![i] as Doc).time) + movement;
-            }
-        }
-        this.forceUpdate();
+        }            
+        let movement = this.regiondata.position - prevX; 
+        this.keyframes.forEach(kf => {
+            kf.time = NumCast(kf.time) + movement; 
+        });
     }
 
     @action
@@ -313,11 +335,11 @@ export class Keyframe extends React.Component<IProps> {
         e.preventDefault();
         e.stopPropagation();
         let bar = this._bar.current!;
-        let offset = Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale);
+        let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         let leftRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions);
         let firstkf: (Doc | undefined) = this.firstKeyframe;
         if (firstkf && this.regiondata.position + this.regiondata.fadeIn + offset >= NumCast(firstkf!.time)) {
-            let dif = NumCast(firstkf!.time) - (this.regiondata.position + this.regiondata.fadeIn);
+            let dif = NumCast(firstkf!.time) - (this.pixelPosition + this.pixelFadeIn);
             this.regiondata.position = NumCast(firstkf!.time) - this.regiondata.fadeIn;
             this.regiondata.duration -= dif;
         } else if (this.regiondata.duration - offset < this.regiondata.fadeIn + this.regiondata.fadeOut) { // no keyframes, just fades
@@ -331,6 +353,7 @@ export class Keyframe extends React.Component<IProps> {
             this.regiondata.duration -= offset;
             this.regiondata.position += offset;
         }
+        
     }
 
 
@@ -339,7 +362,7 @@ export class Keyframe extends React.Component<IProps> {
         e.preventDefault();
         e.stopPropagation();
         let bar = this._bar.current!;
-        let offset = Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale);
+        let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions);
         if (this.lastKeyframe! && this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= NumCast((this.lastKeyframe! as Doc).time)) {
             let dif = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - NumCast((this.lastKeyframe! as Doc).time);
@@ -352,27 +375,18 @@ export class Keyframe extends React.Component<IProps> {
         } else {
             this.regiondata.duration += offset;
         }
-    }
-
-    createDivider = (type?: KeyframeFunc.Direction): JSX.Element => {
-        if (type === "left") {
-            return <div className="divider" style={{ right: "0px" }}></div>;
-        } else if (type === "right") {
-            return <div className="divider" style={{ left: "0px" }}> </div>;
-        }
-        return <div className="divider"></div>;
+       
     }
 
     @action
     createKeyframe = async (clientX:number) => {
         this._mouseToggled = true; 
         let bar = this._bar.current!;
-        let offset = Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale);
+        let offset = KeyframeFunc.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
-            let position = NumCast(this.regiondata.position);
+            let position = this.regiondata.position;
             await this.makeKeyData(Math.round(position + offset));
-            console.log(this.regiondata.keyframes!.length);
-            this.props.changeCurrentBarX(NumCast(Math.round(position + offset))); //first move the keyframe to the correct location and make a copy so the correct file gets coppied
+            this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied
         }
     }
 
@@ -381,7 +395,7 @@ export class Keyframe extends React.Component<IProps> {
     moveKeyframe = async (e: React.MouseEvent, kf: Doc) => {
         e.preventDefault();
         e.stopPropagation();
-        this.props.changeCurrentBarX(NumCast(kf.time!));
+        this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(NumCast(kf.time!), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement));
     }
 
 
@@ -390,33 +404,38 @@ export class Keyframe extends React.Component<IProps> {
         e.preventDefault();
         e.stopPropagation();
         this.props.node.backgroundColor = "#000000";
-
     }
+
+    @action 
+    makeKeyframeMenu = (kf :Doc, e:MouseEvent) => {
+        let items = [
+            TimelineMenu.Instance.addItem("button", "Show Data", () => {
+            runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); 
+            CollectionDockingView.Instance.AddRightSplit(kvp, (kf.key as Doc).data as Doc); });
+            }), 
+            TimelineMenu.Instance.addItem("button", "Delete", () => {}), 
+            TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);})  
+        ]; 
+        TimelineMenu.Instance.addMenu("Keyframe", items); 
+        TimelineMenu.Instance.openMenu(e.clientX, e.clientY); 
+}
     @action
     private createKeyframeJSX = (kf: Doc, type = KeyframeFunc.KeyframeType.default) => {
         if (type === KeyframeFunc.KeyframeType.default) {
             return (
-                <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}>
-                    {this.createDivider()}
+                <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                    <div className="divider"></div>
                     <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf as Doc); }} onContextMenu={(e: React.MouseEvent) => {
                         e.preventDefault();
                         e.stopPropagation();
-                        let items = [
-                            TimelineMenu.Instance.addItem("button", "Show Data", () => {
-                            runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); 
-                            CollectionDockingView.Instance.AddRightSplit(kvp, (kf.key as Doc).data as Doc); });
-                           }), 
-                            TimelineMenu.Instance.addItem("button", "Delete", () => {}), 
-                            TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);})  
-                        ]; 
-                        TimelineMenu.Instance.addMenu("Keyframe", items); 
-                        TimelineMenu.Instance.openMenu(e.clientX, e.clientY); 
+                        this.makeKeyframeMenu(kf, e.nativeEvent); 
                     }}></div>
-                </div>);
+                </div>
+            );
         }
         return (
-            <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}>
-                {this.createDivider()}
+            <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                <div className="divider"></div>
             </div>
         );
     }
@@ -460,9 +479,6 @@ export class Keyframe extends React.Component<IProps> {
         
     }
 
-
-
-
     @action
     onReactionListen = (e: PointerEvent) => {
         e.preventDefault();
@@ -514,7 +530,6 @@ export class Keyframe extends React.Component<IProps> {
                 (Cast(this.regiondata.functions![index], Doc) as Doc).pathX = xPlots;
                 (Cast(this.regiondata.functions![index], Doc) as Doc).pathY = yPlots;
             }
-          
             this._reac = undefined; 
             this._interpolationKeyframe = undefined; 
             this._plotList = undefined; 
@@ -525,19 +540,21 @@ export class Keyframe extends React.Component<IProps> {
     render() {
         return (
             <div>
-                <div className="bar" ref={this._bar} style={{ transform: `translate(${this.regiondata.position}px)`, width: `${this.regiondata.duration}px`, background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.regiondata.fadeIn / this.regiondata.duration * 100}%, rgba(77, 153, 0, 1) ${(this.regiondata.duration - this.regiondata.fadeOut) / this.regiondata.duration * 100}%, rgba(77, 153, 0, 0) 100% )` }}
+                <div className="bar" ref={this._bar} style={{ transform: `translate(${this.pixelPosition}px)`, 
+                width: `${this.pixelDuration}px`, 
+                background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.pixelFadeIn / this.pixelDuration}%, rgba(77, 153, 0, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(77, 153, 0, 0) 100% )` }}
                     onPointerDown={this.onBarPointerDown}>
                     <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
                     <div className="rightResize" onPointerDown={this.onResizeRight}></div>
-                    {this.regiondata.keyframes!.map(kf => {
-                        return this.createKeyframeJSX(kf as Doc, (kf! as Doc).type as KeyframeFunc.KeyframeType);
-                    })}
+                    {this.keyframes.map(kf => { this.createKeyframeJSX(kf, kf.type as KeyframeFunc.KeyframeType); })}
                     {this.keyframes.map( kf => {
                        if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
                             let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; 
                             let bodyRef = React.createRef<HTMLDivElement>(); 
+                            let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
+                            let leftPos = KeyframeFunc.convertPixelTime(NumCast(left!.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
                             return (
-                                <div ref={bodyRef}className="body-container" style={{left: `${NumCast(kf.time) - this.regiondata.position}px`, width:`${NumCast(left!.time) - NumCast(kf.time)}px`}}
+                                <div ref={bodyRef}className="body-container" style={{left: `${kfPos - this.pixelPosition}px`, width:`${leftPos - kfPos}px`}}
                                 onPointerOver={(e) => { this.onContainerOver(e, bodyRef); }}
                                 onPointerOut={(e) => { this.onContainerOut(e, bodyRef); }}
                                 onContextMenu={(e) => {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index d0f83676b..036c3ad9b 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -110,7 +110,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                     this._ticks.push(i);
                     i += 1000;
                 }
-                this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); 
+                this._totalLength = this._tickSpacing * (this._time/ this._tickIncrement); 
             }, {fireImmediately:true}); 
             this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); 
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; 
@@ -322,22 +322,6 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
-    convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time") => {
-        let time = dir === "pixel" ?  pos / this._tickSpacing * this._tickIncrement : pos * this._tickSpacing / this._tickIncrement; 
-        switch (unit) {
-            case "mili":
-                return time; 
-            case "sec":
-                return dir === "pixel" ? time / 1000 : time * 1000; 
-            case "min":
-                return dir === "pixel" ? time / 60000 : time * 60000; 
-            case "hr":
-                return dir === "pixel" ? time / 3600000 : time * 3600000; 
-            default: 
-                return time; 
-        }
-    }
-
     timelineContextMenu = (e:MouseEvent): void => {
         let subitems: ContextMenuProps[] = [];
         let timelineContainer = this._timelineWrapper.current!;
@@ -380,20 +364,21 @@ export class Timeline extends React.Component<FieldViewProps> {
                 if (this._tickSpacing >= 100) {
                     this._tickIncrement /= 2; 
                     this._tickSpacing = 50; 
-                    this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); //CONSIDER THIS MUST CHANGE
                 } else {
                     this._tickSpacing += 10; 
                 }
             } 
         } else {
-            if (this._tickSpacing <= 50) {
-                this._tickSpacing = 100; 
-                this._tickIncrement *= 2; 
-                this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); //CONSIDER THIS MUST CHANGE
-            } else {
-                this._tickSpacing -= 10; 
+            if (this._totalLength >= this._infoContainer.current!.getBoundingClientRect().width){
+                if (this._tickSpacing <= 50) {
+                    this._tickSpacing = 100; 
+                    this._tickIncrement *= 2; 
+                } else {
+                    this._tickSpacing -= 10; 
+                }
             }
         }
+        this._totalLength = this._tickSpacing * (this._time/ this._tickIncrement); 
     }
 
     private timelineToolBox = (scale:number) => {
@@ -424,7 +409,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                                 <div key="timeline_scrubberhead" className="scrubberhead"></div>
                             </div>
                             <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}>
-                                {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} collection = {this.props.Document}/>)}
+                                {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document}/>)}
                             </div>
                         </div>
                         <div key="timeline_title"className="title-container" ref={this._titleContainer}>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index d91954022..5a43f5b2a 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -10,12 +10,17 @@ import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
 import { FlyoutProps } from "./Timeline";
 import { Transform } from "../../util/Transform";
 import { RichTextField } from "../../../new_fields/RichTextField";
+import { createObjectBindingPattern } from "typescript";
+import { DateField } from "../../../new_fields/DateField";
 
 interface IProps {
     node: Doc;
     currentBarX: number;
     transform: Transform;
     collection: Doc; 
+    time: number; 
+    tickIncrement: number; 
+    tickSpacing: number; 
     changeCurrentBarX: (x: number) => void;
 }
 
@@ -44,7 +49,7 @@ export class Track extends React.Component<IProps> {
     componentDidMount() {
         runInAction(() => {
             this._currentBarXReaction = this.currentBarXReaction();
-            if (this.regions.length === 0) this.createRegion(this.props.currentBarX);
+            if (this.regions.length === 0) this.createRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
             this.props.node.hidden = false;
         });
     }
@@ -62,17 +67,33 @@ export class Track extends React.Component<IProps> {
         let kf = keyframes[kfIndex] as Doc; 
         if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
             kf.key = Doc.MakeCopy(this.props.node, true);
-            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.props.currentBarX, kf); // lef keyframe, if it exists
-            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, this.props.currentBarX, kf); //right keyframe, if it exists
+            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); // lef keyframe, if it exists
+            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); //right keyframe, if it exists
+            // while (leftkf !== undefined) {
+            //     if (leftkf!.type === KeyframeFunc.KeyframeType.fade) {
+            //         let edge:(Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), leftkf!);
+            //         edge!.key = Doc.MakeCopy(kf.key as Doc, true);
+            //         leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
+            //         (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
+            //         (Cast(leftkf!.key, Doc)! as Doc).opacity = 1;
+            //     } else if (leftkf!.key ) {
+            //         leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
+            //     }
+
+            // }
+            
+            
+            
+            
             if (leftkf!.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
-                let edge:(Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.props.currentBarX, leftkf!);
+                let edge:(Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), leftkf!);
                 edge!.key = Doc.MakeCopy(kf.key as Doc, true);
                 leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
                 (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
                 (Cast(leftkf!.key, Doc)! as Doc).opacity = 1;
             }
             if (rightkf!.type === KeyframeFunc.KeyframeType.fade) {
-                let edge:(Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!,this.props.currentBarX, rightkf!);
+                let edge:(Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!,KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), rightkf!);
                 edge!.key = Doc.MakeCopy(kf.key as Doc, true);
                 rightkf!.key = Doc.MakeCopy(kf.key as Doc, true);
                 (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
@@ -88,10 +109,10 @@ export class Track extends React.Component<IProps> {
     @action 
     currentBarXReaction = () => {
         return reaction(() => this.props.currentBarX, async () => {
-            let regiondata: (Doc | undefined) = await this.findRegion(this.props.currentBarX);
+            let regiondata: (Doc | undefined) = await this.findRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
             if (regiondata) {
                 this.props.node.hidden = false;
-                await this.timeChange(this.props.currentBarX);
+                await this.timeChange(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
             } else {
                   this.props.node.hidden = true;
                   this.props.node.opacity = 0; 
@@ -107,8 +128,8 @@ export class Track extends React.Component<IProps> {
         }
         let regiondata = await this.findRegion(Math.round(time)); //finds a region that the scrubber is on
         if (regiondata) {
-            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata, this.props.currentBarX); // lef keyframe, if it exists
-            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.props.currentBarX); //right keyframe, if it exists            
+            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement)); // lef keyframe, if it exists
+            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement)); //right keyframe, if it exists            
             let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
             if (currentkf) {
                 await this.applyKeys(currentkf);
@@ -139,6 +160,8 @@ export class Track extends React.Component<IProps> {
                         this.props.node[key] = new RichTextField(nodeData); 
                     }
                 } else if (key === "creationDate") {
+                    
+                    this.props.node[key] = new DateField(); 
                 }  else {
                     this.props.node[key] = kfNode[key];
                 }
@@ -162,7 +185,7 @@ export class Track extends React.Component<IProps> {
         let currentkf: (Doc | undefined) = undefined;
         let keyframes = await DocListCastAsync(region.keyframes!); 
         keyframes!.forEach((kf) => {
-            if (NumCast(kf.time) === Math.round(this.props.currentBarX)) currentkf = kf;
+            if (NumCast(kf.time) === Math.round(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement))) currentkf = kf;
         });
         return currentkf;
     }
@@ -173,7 +196,7 @@ export class Track extends React.Component<IProps> {
         let leftNode = left.key as Doc;
         let rightNode = right.key as Doc;
         const dif_time = NumCast(right.time) - NumCast(left.time);
-        const timeratio = (this.props.currentBarX - NumCast(left.time)) / dif_time; //linear 
+        const timeratio = (KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement) - NumCast(left.time)) / dif_time; //linear 
         let keyframes = (await DocListCastAsync(regiondata.keyframes!))!; 
         let indexLeft = keyframes.indexOf(left); 
         let interY:List<number> = (await ((regiondata.functions as List<Doc>)[indexLeft] as Doc).interpolationY as List<number>)!;  
@@ -251,7 +274,7 @@ export class Track extends React.Component<IProps> {
     onInnerDoubleClick = (e: React.MouseEvent) => {
         let inner = this._inner.current!;
         let offsetX = Math.round((e.clientX - inner.getBoundingClientRect().left) * this.props.transform.Scale);
-        this.createRegion(offsetX);
+        this.createRegion(KeyframeFunc.convertPixelTime(offsetX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
     }
 
     createRegion = (position: number) => {
@@ -275,7 +298,7 @@ export class Track extends React.Component<IProps> {
                 <div className="track">
                     <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick}>
                         {DocListCast(this.regions).map((region) => {
-                            return <Keyframe node={this.props.node} RegionData={region} changeCurrentBarX={this.props.changeCurrentBarX} transform={this.props.transform} collection={this.props.collection}/>;
+                            return <Keyframe {...this.props} RegionData={region}/>;
                         })}
                     </div>
                 </div>
-- 
cgit v1.2.3-70-g09d2


From 1b7e8873ead3cc15349bd4c9e669f3b1edcbbc2b Mon Sep 17 00:00:00 2001
From: Andrew Kim <andrewdkim@users.noreply.github.com>
Date: Mon, 19 Aug 2019 00:25:14 -0400
Subject: updates

---
 src/client/views/MainView.tsx                      |  6 +--
 src/client/views/animationtimeline/Keyframe.tsx    | 59 ++++++++++++----------
 src/client/views/animationtimeline/Timeline.tsx    | 51 +++++++++++--------
 .../views/animationtimeline/TimelineMenu.tsx       | 20 ++++----
 src/client/views/animationtimeline/Track.tsx       | 40 ++++-----------
 5 files changed, 87 insertions(+), 89 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d5482bc12..126760234 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -206,9 +206,9 @@ export class MainView extends React.Component {
         if (targets && targets.length && targets[0].className.toString().indexOf("contextMenu") === -1) {
             ContextMenu.Instance.closeMenu();
         }
-        // if (targets && targets.length && targets[0].className.toString().indexOf("timeline-menu-container") === -1) {
-        //     TimelineMenu.Instance.closeMenu();
-        // }   
+        if (targets && targets.length && targets[0].className.toString().indexOf("timeline-menu-desc") === -1 || targets[0].className.toString().indexOf("timeline-menu-item") === -1 || targets[0].className.toString().indexOf("timeline-menu-item") === -1 || targets[0].className.toString().indexOf("timeline-menu-input") === -1){
+            TimelineMenu.Instance.closeMenu(); 
+        } 
     });
 
     globalPointerUp = () => this.isPointerDown = false;
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index b02d89bf0..2f0a968b9 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -28,7 +28,7 @@ export namespace KeyframeFunc {
         let leftMost: (RegionData | undefined) = undefined;
         let rightMost: (RegionData | undefined) = undefined;
         DocListCast(regions).forEach(region => {
-            let neighbor = RegionData(region as Doc);
+            let neighbor = RegionData(region);
             if (currentRegion.position! > neighbor.position) {
                 if (!leftMost || neighbor.position > leftMost.position) {
                     leftMost = neighbor;
@@ -230,7 +230,6 @@ export class Keyframe extends React.Component<IProps> {
         let doclist = (await DocListCastAsync(this.regiondata.keyframes))!;
         let existingkf: (Doc | undefined) = undefined;
         doclist.forEach(TK => {
-            TK = TK as Doc;
             if (TK.time === kfpos) existingkf = TK;
         });
         if (existingkf) return existingkf;
@@ -299,8 +298,8 @@ export class Keyframe extends React.Component<IProps> {
             this.regiondata.position = 0;
         } else if ((left && left.position + left.duration >= futureX)) {
             this.regiondata.position = left.position + left.duration;
-        } else if ((right && right.position <= futureX + this.pixelDuration)) {
-            this.regiondata.position = right.position - this.pixelDuration;
+        } else if ((right && right.position <= futureX + this.regiondata.duration)) {
+            this.regiondata.position = right.position - this.regiondata.duration;
         } else {
             this.regiondata.position = futureX;
         }            
@@ -353,7 +352,8 @@ export class Keyframe extends React.Component<IProps> {
             this.regiondata.duration -= offset;
             this.regiondata.position += offset;
         }
-        
+        this.keyframes[0].time = this.regiondata.position; 
+        this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn; 
     }
 
 
@@ -375,6 +375,8 @@ export class Keyframe extends React.Component<IProps> {
         } else {
             this.regiondata.duration += offset;
         }
+        this.keyframes[this.keyframes.length - 2].time = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut; 
+        this.keyframes[this.keyframes.length - 1].time = this.regiondata.position + this.regiondata.duration; 
        
     }
 
@@ -408,24 +410,36 @@ export class Keyframe extends React.Component<IProps> {
 
     @action 
     makeKeyframeMenu = (kf :Doc, e:MouseEvent) => {
-        let items = [
-            TimelineMenu.Instance.addItem("button", "Show Data", () => {
-            runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); 
+   
+        TimelineMenu.Instance.addItem("button", "Show Data", () => {
+        runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); 
             CollectionDockingView.Instance.AddRightSplit(kvp, (kf.key as Doc).data as Doc); });
-            }), 
-            TimelineMenu.Instance.addItem("button", "Delete", () => {}), 
-            TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);})  
-        ]; 
-        TimelineMenu.Instance.addMenu("Keyframe", items); 
+        }), 
+        TimelineMenu.Instance.addItem("button", "Delete", () => {}), 
+        TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);});  
+        
+        TimelineMenu.Instance.addMenu("Keyframe"); 
         TimelineMenu.Instance.openMenu(e.clientX, e.clientY); 
-}
+    }
+
+    @action 
+    makeRegionMenu = (kf: Doc, e: MouseEvent) => {
+        TimelineMenu.Instance.addItem("button", "Add Ease", () => {this.onContainerDown(kf, "interpolate");}),
+        TimelineMenu.Instance.addItem("button", "Add Path", () => {this.onContainerDown(kf, "path");}), 
+        TimelineMenu.Instance.addItem("input", "fadeIn", (val) => {this.regiondata.fadeIn = parseInt(val, 10);}), 
+        TimelineMenu.Instance.addItem("input", "fadeOut", (val) => {this.regiondata.fadeOut = parseInt(val, 10);}),
+        TimelineMenu.Instance.addItem("input", "position", (val) => {this.regiondata.position = parseInt(val, 10);}),
+        TimelineMenu.Instance.addItem("input", "duration", (val) => {this.regiondata.duration = parseInt(val, 10);}),
+        TimelineMenu.Instance.addMenu("Region"); 
+        TimelineMenu.Instance.openMenu(e.clientX, e.clientY); 
+    }
     @action
     private createKeyframeJSX = (kf: Doc, type = KeyframeFunc.KeyframeType.default) => {
         if (type === KeyframeFunc.KeyframeType.default) {
             return (
                 <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
                     <div className="divider"></div>
-                    <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf as Doc); }} onContextMenu={(e: React.MouseEvent) => {
+                    <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
                         e.preventDefault();
                         e.stopPropagation();
                         this.makeKeyframeMenu(kf, e.nativeEvent); 
@@ -546,7 +560,9 @@ export class Keyframe extends React.Component<IProps> {
                     onPointerDown={this.onBarPointerDown}>
                     <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
                     <div className="rightResize" onPointerDown={this.onResizeRight}></div>
-                    {this.keyframes.map(kf => { this.createKeyframeJSX(kf, kf.type as KeyframeFunc.KeyframeType); })}
+                    {this.keyframes.map(kf => {
+                        return this.createKeyframeJSX(kf, kf.type as KeyframeFunc.KeyframeType); 
+                    })}
                     {this.keyframes.map( kf => {
                        if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
                             let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; 
@@ -561,16 +577,7 @@ export class Keyframe extends React.Component<IProps> {
                                     e.preventDefault(); 
                                     e.stopPropagation(); 
                                     this._mouseToggled = true; 
-                                    let items = [
-                                        TimelineMenu.Instance.addItem("button", "Add Ease", () => {this.onContainerDown(kf, "interpolate");}),
-                                        TimelineMenu.Instance.addItem("button", "Add Path", () => {this.onContainerDown(kf, "path");}), 
-                                        TimelineMenu.Instance.addItem("input", "fadeIn", (val) => {this.regiondata.fadeIn = parseInt(val, 10);}), 
-                                        TimelineMenu.Instance.addItem("input", "fadeOut", (val) => {this.regiondata.fadeOut = parseInt(val, 10);}),
-                                        TimelineMenu.Instance.addItem("input", "position", (val) => {this.regiondata.position = parseInt(val, 10);}),
-                                        TimelineMenu.Instance.addItem("input", "duration", (val) => {this.regiondata.duration = parseInt(val, 10);}),
-                                    ]; 
-                                    TimelineMenu.Instance.addMenu("Region", items); 
-                                    TimelineMenu.Instance.openMenu(e.clientX, e.clientY); 
+                                    this.makeRegionMenu(kf, e.nativeEvent); 
                                 }}>
                                 </div>
                             ); 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 036c3ad9b..4eb5958b5 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -1,7 +1,6 @@
 import * as React from "react";
 import "./Timeline.scss";
-import { CollectionSubView } from "../collections/CollectionSubView";
-import { Document, listSpec } from "../../../new_fields/Schema";
+import { listSpec } from "../../../new_fields/Schema";
 import { observer } from "mobx-react";
 import { Track } from "./Track";
 import { observable, reaction, action, IReactionDisposer, computed, runInAction, observe } from "mobx";
@@ -13,8 +12,8 @@ import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDow
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
-import { playcustomapp } from "googleapis/build/src/apis/playcustomapp";
-import { FieldView, FieldViewProps } from "../nodes/FieldView";
+import { FieldViewProps } from "../nodes/FieldView";
+import { KeyframeFunc } from "./Keyframe";
 
 
 
@@ -62,6 +61,8 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _timelineVisible = false; 
     @observable private _mouseToggled = false; 
     @observable private _doubleClickEnabled = false; 
+    @observable private _mutationDisposer:MutationObserver[] = []; 
+    @observable private _reactionDisposer:IReactionDisposer[] = []; 
 
 
     @computed
@@ -89,7 +90,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             console.log(this.props.Document.duration);
             if (this.props.Document.duration) {
                 this._time = Math.round(NumCast(this.props.Document.duration)) * 1000;
-                reaction(() => {
+                this._reactionDisposer.push(reaction(() => {
                     return NumCast(this.props.Document.curPage);
                 }, curPage => {
                     if (!this._isPlaying) {
@@ -97,12 +98,11 @@ export class Timeline extends React.Component<FieldViewProps> {
                         this.props.Document.curPage = this._currentBarX; 
                         this.play(); 
                     }
-                   
-                });
+                }));
             }
         }
         runInAction(() => {
-            reaction(() => {
+            this._reactionDisposer.push(reaction(() => {
                 return this._time;  
             }, () => {
                 this._ticks = [];
@@ -111,7 +111,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                     i += 1000;
                 }
                 this._totalLength = this._tickSpacing * (this._time/ this._tickIncrement); 
-            }, {fireImmediately:true}); 
+            }, {fireImmediately:true})); 
             this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); 
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; 
             this._visibleStart = this._infoContainer.current!.scrollLeft;   
@@ -321,7 +321,6 @@ export class Timeline extends React.Component<FieldViewProps> {
         return `${min}:${sec}`;
     }
 
-
     timelineContextMenu = (e:MouseEvent): void => {
         let subitems: ContextMenuProps[] = [];
         let timelineContainer = this._timelineWrapper.current!;
@@ -354,31 +353,41 @@ export class Timeline extends React.Component<FieldViewProps> {
     onWheelZoom = (e: React.WheelEvent) => {
         e.preventDefault(); 
         e.stopPropagation(); 
+        let offset = e.clientX - this._infoContainer.current!.getBoundingClientRect().left; 
+        let prevTime = KeyframeFunc.convertPixelTime(this._visibleStart + offset, "mili", "time", this._tickSpacing, this._tickIncrement); 
         e.deltaY < 0 ? this.zoom(true) : this.zoom(false); 
+        let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
+        this._infoContainer.current!.scrollLeft = currPixel - offset; 
+        this._visibleStart = currPixel - offset; 
     }
 
     @action
     zoom = (dir: boolean) => {
+        let spacingChange = this._tickSpacing; 
+        let incrementChange = this._tickIncrement; 
         if (dir){
             if (!(this._tickSpacing === 100 && this._tickIncrement === 1000)){
                 if (this._tickSpacing >= 100) {
-                    this._tickIncrement /= 2; 
-                    this._tickSpacing = 50; 
+                    incrementChange /= 2; 
+                    spacingChange = 50; 
                 } else {
-                    this._tickSpacing += 10; 
+                    spacingChange += 5; 
                 }
             } 
         } else {
-            if (this._totalLength >= this._infoContainer.current!.getBoundingClientRect().width){
-                if (this._tickSpacing <= 50) {
-                    this._tickSpacing = 100; 
-                    this._tickIncrement *= 2; 
-                } else {
-                    this._tickSpacing -= 10; 
-                }
+            if (this._tickSpacing <= 50) {
+                spacingChange = 100; 
+                incrementChange *= 2; 
+            } else {
+                spacingChange -= 5; 
             }
         }
-        this._totalLength = this._tickSpacing * (this._time/ this._tickIncrement); 
+        let finalLength = spacingChange * (this._time / incrementChange);  
+        if (finalLength >= this._infoContainer.current!.getBoundingClientRect().width){
+            this._totalLength = finalLength; 
+            this._tickSpacing = spacingChange; 
+            this._tickIncrement = incrementChange; 
+        }
     }
 
     private timelineToolBox = (scale:number) => {
diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx
index 3e63eec61..572b35b90 100644
--- a/src/client/views/animationtimeline/TimelineMenu.tsx
+++ b/src/client/views/animationtimeline/TimelineMenu.tsx
@@ -31,31 +31,31 @@ export class TimelineMenu extends React.Component {
     closeMenu = () => {
         this._opacity = 0; 
         this._currentMenu = []; 
+        this._x = -1000000; 
+        this._y = -1000000; 
     }
 
+    @action
     addItem = (type: "input" | "button", title: string, event: (e:any) => void) => {
         if (type === "input"){
-            let ref = React.createRef<HTMLInputElement>(); 
-            return <div className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {ref} placeholder={title} onChange={(e) => {
+            let inputRef = React.createRef<HTMLInputElement>(); 
+            this._currentMenu.push( <div className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {inputRef} placeholder={title} onChange={(e) => {
                 let text = e.target.value;
                 document.addEventListener("keypress", (e:KeyboardEvent) => {
                     if (e.keyCode === 13) {
                         event(text); 
                     }
                 });
-            }}/></div>; 
+            }}/></div>); 
         } else if (type === "button") {
-            let ref = React.createRef<HTMLDivElement>(); 
-            return <div className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={event}>{title}</p></div>; 
+            let buttonRef = React.createRef<HTMLDivElement>(); 
+            this._currentMenu.push( <div className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={event}>{title}</p></div>); 
         }
-        return <div></div>; 
     }
 
     @action 
-    addMenu = (title:string, items: JSX.Element[]) => {
-        items.unshift(<div className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>); 
-        this._currentMenu = items;
-    
+    addMenu = (title:string) => {
+        this._currentMenu.unshift(<div className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>);     
     }
 
     render() {
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 5a43f5b2a..13fe55e80 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -1,16 +1,14 @@
 import * as React from "react";
 import { observer } from "mobx-react";
-import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS, IObservableObject, runInAction, autorun } from "mobx";
+import { observable, reaction, action, IReactionDisposer, computed, runInAction, autorun } from "mobx";
 import "./Track.scss";
 import { Doc, DocListCastAsync, DocListCast, Field } from "../../../new_fields/Doc";
 import { listSpec } from "../../../new_fields/Schema";
 import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
-import { FlyoutProps } from "./Timeline";
 import { Transform } from "../../util/Transform";
 import { RichTextField } from "../../../new_fields/RichTextField";
-import { createObjectBindingPattern } from "typescript";
 import { DateField } from "../../../new_fields/DateField";
 
 interface IProps {
@@ -68,23 +66,7 @@ export class Track extends React.Component<IProps> {
         if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
             kf.key = Doc.MakeCopy(this.props.node, true);
             let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); // lef keyframe, if it exists
-            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); //right keyframe, if it exists
-            // while (leftkf !== undefined) {
-            //     if (leftkf!.type === KeyframeFunc.KeyframeType.fade) {
-            //         let edge:(Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), leftkf!);
-            //         edge!.key = Doc.MakeCopy(kf.key as Doc, true);
-            //         leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
-            //         (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
-            //         (Cast(leftkf!.key, Doc)! as Doc).opacity = 1;
-            //     } else if (leftkf!.key ) {
-            //         leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
-            //     }
-
-            // }
-            
-            
-            
-            
+            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); //right keyframe, if it exists 
             if (leftkf!.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
                 let edge:(Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), leftkf!);
                 edge!.key = Doc.MakeCopy(kf.key as Doc, true);
@@ -160,7 +142,6 @@ export class Track extends React.Component<IProps> {
                         this.props.node[key] = new RichTextField(nodeData); 
                     }
                 } else if (key === "creationDate") {
-                    
                     this.props.node[key] = new DateField(); 
                 }  else {
                     this.props.node[key] = kfNode[key];
@@ -175,9 +156,9 @@ export class Track extends React.Component<IProps> {
     @action
     private filterKeys = (keys: string[]): string[] => {
         return keys.reduce((acc: string[], key: string) => {
-            if (key !== "regions" && key !== "cursors" && key !== "hidden" && key !== "nativeHeight" && key !== "nativeWidth" && key !== "schemaColumns") acc.push(key);
+            if (key !== "regions" && key !== "cursors" && key !== "hidden" && key !== "nativeHeight" && key !== "nativeWidth" && key !== "schemaColumns" && key !==  "creationDate") acc.push(key);
             return acc;
-        }, []) as string[];
+        }, []);
     }
 
     @action
@@ -280,15 +261,16 @@ export class Track extends React.Component<IProps> {
     createRegion = (position: number) => {
         let regiondata = KeyframeFunc.defaultKeyframe();
         regiondata.position = position;
-        let leftRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, regiondata, this.regions);
         let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, regiondata, this.regions);
-        if ((rightRegion && leftRegion && rightRegion.position - (leftRegion.position + leftRegion.duration) < NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut)) || (rightRegion && rightRegion.position - regiondata.position < NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut))) {
-            return;
-        } else if (rightRegion && rightRegion.position - regiondata.position >= NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut)) {
+    
+        if (rightRegion && rightRegion.position - regiondata.position <= 4000) {
             regiondata.duration = rightRegion.position - regiondata.position;
+        } 
+        if(this.regions.length === 0 || !rightRegion || (rightRegion && rightRegion.position - regiondata.position >= NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut))){
+            this.regions.push(regiondata);
+            return regiondata;
         }
-        this.regions.push(regiondata);
-        return regiondata;
+       
     }
 
 
-- 
cgit v1.2.3-70-g09d2


From 96551aa8ef23485f48f6090192f18451ff66b557 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 15 Sep 2019 17:01:13 -0400
Subject: changes

---
 src/client/views/animationtimeline/Keyframe.tsx    |  48 +++++-----
 src/client/views/animationtimeline/Timeline.tsx    |  10 +--
 src/client/views/animationtimeline/Track.tsx       | 100 ++++++++++++---------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   1 +
 4 files changed, 88 insertions(+), 71 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 2f0a968b9..253515dfd 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -410,14 +410,17 @@ export class Keyframe extends React.Component<IProps> {
 
     @action 
     makeKeyframeMenu = (kf :Doc, e:MouseEvent) => {
-   
         TimelineMenu.Instance.addItem("button", "Show Data", () => {
         runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); 
             CollectionDockingView.Instance.AddRightSplit(kvp, (kf.key as Doc).data as Doc); });
         }), 
-        TimelineMenu.Instance.addItem("button", "Delete", () => {}), 
+        TimelineMenu.Instance.addItem("button", "Delete", () => {
+            runInAction(() => {
+                console.log(this.keyframes.indexOf(kf));
+                this.keyframes.splice(this.keyframes.indexOf(kf), 1);
+            });         
+        }), 
         TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);});  
-        
         TimelineMenu.Instance.addMenu("Keyframe"); 
         TimelineMenu.Instance.openMenu(e.clientX, e.clientY); 
     }
@@ -425,7 +428,8 @@ export class Keyframe extends React.Component<IProps> {
     @action 
     makeRegionMenu = (kf: Doc, e: MouseEvent) => {
         TimelineMenu.Instance.addItem("button", "Add Ease", () => {this.onContainerDown(kf, "interpolate");}),
-        TimelineMenu.Instance.addItem("button", "Add Path", () => {this.onContainerDown(kf, "path");}), 
+        TimelineMenu.Instance.addItem("button", "Add Path", () => {this.onContainerDown(kf, "path");}),         
+        TimelineMenu.Instance.addItem("button", "Remove Region", ()=>{this.regions.splice(this.regions.indexOf(this.regiondata), 1);}),
         TimelineMenu.Instance.addItem("input", "fadeIn", (val) => {this.regiondata.fadeIn = parseInt(val, 10);}), 
         TimelineMenu.Instance.addItem("input", "fadeOut", (val) => {this.regiondata.fadeOut = parseInt(val, 10);}),
         TimelineMenu.Instance.addItem("input", "position", (val) => {this.regiondata.position = parseInt(val, 10);}),
@@ -435,23 +439,7 @@ export class Keyframe extends React.Component<IProps> {
     }
     @action
     private createKeyframeJSX = (kf: Doc, type = KeyframeFunc.KeyframeType.default) => {
-        if (type === KeyframeFunc.KeyframeType.default) {
-            return (
-                <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
-                    <div className="divider"></div>
-                    <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
-                        e.preventDefault();
-                        e.stopPropagation();
-                        this.makeKeyframeMenu(kf, e.nativeEvent); 
-                    }}></div>
-                </div>
-            );
-        }
-        return (
-            <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
-                <div className="divider"></div>
-            </div>
-        );
+        
     }
 
     onContainerOver = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
@@ -561,7 +549,23 @@ export class Keyframe extends React.Component<IProps> {
                     <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
                     <div className="rightResize" onPointerDown={this.onResizeRight}></div>
                     {this.keyframes.map(kf => {
-                        return this.createKeyframeJSX(kf, kf.type as KeyframeFunc.KeyframeType); 
+                        if (kf.type as KeyframeFunc.KeyframeType === KeyframeFunc.KeyframeType.default) {
+                            return (
+                                <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                                    <div className="divider"></div>
+                                    <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
+                                        e.preventDefault();
+                                        e.stopPropagation();
+                                        this.makeKeyframeMenu(kf, e.nativeEvent); 
+                                    }}></div>
+                                </div>
+                            );
+                        }
+                        return (
+                            <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                                <div className="divider"></div>
+                            </div>
+                        );
                     })}
                     {this.keyframes.map( kf => {
                        if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 4eb5958b5..187c9396d 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -3,7 +3,7 @@ import "./Timeline.scss";
 import { listSpec } from "../../../new_fields/Schema";
 import { observer } from "mobx-react";
 import { Track } from "./Track";
-import { observable, reaction, action, IReactionDisposer, computed, runInAction, observe } from "mobx";
+import { observable, reaction, action, IReactionDisposer, computed, runInAction, observe, toJS } from "mobx";
 import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
@@ -61,14 +61,12 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _timelineVisible = false; 
     @observable private _mouseToggled = false; 
     @observable private _doubleClickEnabled = false; 
-    @observable private _mutationDisposer:MutationObserver[] = []; 
     @observable private _reactionDisposer:IReactionDisposer[] = []; 
 
 
     @computed
     private get children(): List<Doc> {
         let extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type));
-       
         if (extendedDocument) {
             if (this.props.Document.data_ext) {
                 return Cast((Cast(this.props.Document.data_ext, Doc) as Doc).annotations, listSpec(Doc)) as List<Doc>;
@@ -86,7 +84,7 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     componentDidMount() {
         if (StrCast(this.props.Document.type) === "video") {
-            console.log("ran");
+            console.log("video");
             console.log(this.props.Document.duration);
             if (this.props.Document.duration) {
                 this._time = Math.round(NumCast(this.props.Document.duration)) * 1000;
@@ -358,7 +356,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         e.deltaY < 0 ? this.zoom(true) : this.zoom(false); 
         let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
         this._infoContainer.current!.scrollLeft = currPixel - offset; 
-        this._visibleStart = currPixel - offset; 
+        this._visibleStart = currPixel - offset;    
     }
 
     @action
@@ -418,7 +416,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                                 <div key="timeline_scrubberhead" className="scrubberhead"></div>
                             </div>
                             <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}>
-                                {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document}/>)}
+                                {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document} timelineVisible = {this._timelineVisible}/>)}
                             </div>
                         </div>
                         <div key="timeline_title"className="title-container" ref={this._titleContainer}>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 8f0e2d1cc..e99da6648 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -8,9 +8,8 @@ import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_field
 import { List } from "../../../new_fields/List";
 import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
 import { Transform } from "../../util/Transform";
-import { RichTextField } from "../../../new_fields/RichTextField";
-import { DateField } from "../../../new_fields/DateField";
 import { Copy } from "../../../new_fields/FieldSymbols";
+import { ObjectField } from "../../../new_fields/ObjectField";
 
 interface IProps {
     node: Doc;
@@ -20,19 +19,20 @@ interface IProps {
     time: number;
     tickIncrement: number;
     tickSpacing: number;
+    timelineVisible: boolean; 
     changeCurrentBarX: (x: number) => void;
 }
 
 @observer
 export class Track extends React.Component<IProps> {
     @observable private _inner = React.createRef<HTMLDivElement>();
-    @observable private _reactionDisposers: IReactionDisposer[] = [];
     @observable private _currentBarXReaction: any;
+    @observable private _timelineVisibleReaction: any;
     @observable private _isOnKeyframe: boolean = false;
     @observable private _onKeyframe: (Doc | undefined) = undefined;
     @observable private _onRegionData: (Doc | undefined) = undefined;
-    @observable private _leftCurrKeyframe: (Doc | undefined) = undefined;
-
+    @observable private _storedState: (Doc | undefined) = undefined;
+    
     @computed
     private get regions() {
         return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;
@@ -40,22 +40,31 @@ export class Track extends React.Component<IProps> {
 
     componentWillMount() {
         if (!this.props.node.regions) {
-            this.props.node.regions = new List<Doc>();
+            this.props.node.regions = new List<Doc>();            
         }
-        this.props.node.opacity = 1;
+      
+        
     }
 
     componentDidMount() {
-        runInAction(() => {
+        runInAction(async () => {
+            this._timelineVisibleReaction = this.timelineVisibleReaction(); 
             this._currentBarXReaction = this.currentBarXReaction();
             if (this.regions.length === 0) this.createRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
-            this.props.node.hidden = false;
+            this.props.node.hidden = false;                   
+            this.props.node.opacity = 1; 
+            let state = new Doc();  
+            state.key = Doc.MakeCopy(await this.props.node, true);
+            console.log(this.props.node.x); 
+            this._storedState = state;             
         });
+
     }
 
     componentWillUnmount() {
         runInAction(() => {
             if (this._currentBarXReaction) this._currentBarXReaction();
+            if (this._timelineVisibleReaction) this._timelineVisibleReaction(); 
         });
     }
 
@@ -89,6 +98,15 @@ export class Track extends React.Component<IProps> {
         this._isOnKeyframe = false;
     }
 
+    @action 
+    revertState = () => {
+        let copyDoc = Doc.MakeCopy(this.props.node, true); 
+        this.applyKeys(this._storedState!); 
+        let newState = new Doc(); 
+        newState.key = copyDoc; 
+        this._storedState = newState; 
+    }
+
     @action
     currentBarXReaction = () => {
         return reaction(() => this.props.currentBarX, async () => {
@@ -100,9 +118,16 @@ export class Track extends React.Component<IProps> {
                 this.props.node.hidden = true;
                 this.props.node.opacity = 0;
             }
-        }, { fireImmediately: true });
+        });
+    }
+    @action 
+    timelineVisibleReaction = () => {
+        return reaction(() => {
+            return this.props.timelineVisible; 
+        }, isVisible => {
+            this.revertState(); 
+        }); 
     }
-
 
     @action
     timeChange = async (time: number) => {
@@ -116,7 +141,6 @@ export class Track extends React.Component<IProps> {
             let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
             if (currentkf) {
                 await this.applyKeys(currentkf);
-                this._leftCurrKeyframe = currentkf;
                 this._isOnKeyframe = true;
                 this._onKeyframe = currentkf;
                 this._onRegionData = regiondata;
@@ -129,39 +153,38 @@ export class Track extends React.Component<IProps> {
     @action
     private applyKeys = async (kf: Doc) => {
         let kfNode = await Cast(kf.key, Doc) as Doc;
-        let docFromApply = kfNode;
-        console.log(Doc.allKeys(docFromApply));
+        let docFromApply = kfNode;        
         if (this.filterKeys(Doc.allKeys(this.props.node)).length > this.filterKeys(Doc.allKeys(kfNode)).length) docFromApply = this.props.node;
         this.filterKeys(Doc.allKeys(docFromApply)).forEach(key => {
-            console.log(key);
             if (!kfNode[key]) {
                 this.props.node[key] = undefined;
             } else {
-                if (key === "data") {
-                    if (this.props.node.type === "text") {
-                        let nodeData = (kfNode[key] as RichTextField).Data;
-                        this.props.node[key] = new RichTextField(nodeData);
-                    }
-                } else if (key === "creationDate") {
-                    this.props.node[key] = new DateField();
+                let stored = kfNode[key];
+                if(stored instanceof ObjectField){                    
+                    this.props.node[key] = stored[Copy](); 
                 } else {
-                    let stored = kfNode[key];
-                    if (stored instanceof DateField) {
-                        stored = stored[Copy]();
-                    }
-                    this.props.node[key] = stored;
+                    this.props.node[key] = stored; 
                 }
-
             }
-
         });
     }
 
+    private filterList = [
+        "regions", 
+        "cursors", 
+        "hidden", 
+        "nativeHeight", 
+        "nativeWidth", 
+        "schemaColumns", 
+        "baseLayout", 
+        "backgroundLayout", 
+        "layout", 
+    ]; 
 
     @action
     private filterKeys = (keys: string[]): string[] => {
         return keys.reduce((acc: string[], key: string) => {
-            if (key !== "regions" && key !== "cursors" && key !== "hidden" && key !== "nativeHeight" && key !== "nativeWidth" && key !== "schemaColumns" && key !== "creationDate") acc.push(key);
+            if (!this.filterList.includes(key)) acc.push(key); 
             return acc;
         }, []);
     }
@@ -226,18 +249,11 @@ export class Track extends React.Component<IProps> {
                     this.props.node[key] = NumCast(leftNode[key]) + adjusted;
                 }
             } else {
-                if (key === "data") {
-                    if (this.props.node.type === "text") {
-                        let nodeData = StrCast((leftNode[key] as RichTextField).Data);
-                        let currentNodeData = StrCast((this.props.node[key] as RichTextField).Data);
-                        if (nodeData !== currentNodeData) {
-                            this.props.node[key] = new RichTextField(nodeData);
-                        }
-                    }
-                } else if (key === "creationDate") {
-
+                let stored = leftNode[key];
+                if(stored instanceof ObjectField){                    
+                    this.props.node[key] = stored[Copy](); 
                 } else {
-                    this.props.node[key] = leftNode[key];
+                    this.props.node[key] = stored; 
                 }
             }
         });
@@ -277,8 +293,6 @@ export class Track extends React.Component<IProps> {
         }
 
     }
-
-
     render() {
         return (
             <div className="track-container">
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d9fc388cd..67d700f1a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -912,6 +912,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         if (this.childDocs.some(d => BoolCast(d.isTemplate))) {
             layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" });
         }
+        this._timelineRef.current!.timelineContextMenu(e.nativeEvent); 
         layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
         layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
         layoutItems.push({
-- 
cgit v1.2.3-70-g09d2


From 53c4f6ddad5534101d7a7482332cddb02ba99c21 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 17 Sep 2019 18:01:36 -0400
Subject: zoom, contextmenu fix

---
 src/client/views/MainView.tsx                       | 3 +--
 src/client/views/animationtimeline/Timeline.tsx     | 7 +++++--
 src/client/views/animationtimeline/TimelineMenu.tsx | 6 +++++-
 src/client/views/animationtimeline/Track.tsx        | 6 +-----
 src/new_fields/Doc.ts                               | 2 +-
 5 files changed, 13 insertions(+), 11 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6331763f1..139ac11db 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -206,8 +206,7 @@ export class MainView extends React.Component {
         if (targets && targets.length && targets[0].className.toString().indexOf("contextMenu") === -1) {
             ContextMenu.Instance.closeMenu();
         }
-        console.log(targets.toString()); 
-        if (targets && targets.length && targets[0].className.toString().indexOf("timeline-menu-desc") === -1 || targets[0].className.toString().indexOf("timeline-menu-item") === -1 || targets[0].className.toString().indexOf("timeline-menu-item") === -1 || targets[0].className.toString().indexOf("timeline-menu-input") === -1){
+        if (targets && (targets.length && targets[0].className.toString() !== "timeline-menu-desc" && targets[0].className.toString() !== "timeline-menu-item" && targets[0].className.toString() !=="timeline-menu-input")){
             TimelineMenu.Instance.closeMenu(); 
         } 
     });
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 187c9396d..c50ffa51b 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -352,11 +352,14 @@ export class Timeline extends React.Component<FieldViewProps> {
         e.preventDefault(); 
         e.stopPropagation(); 
         let offset = e.clientX - this._infoContainer.current!.getBoundingClientRect().left; 
-        let prevTime = KeyframeFunc.convertPixelTime(this._visibleStart + offset, "mili", "time", this._tickSpacing, this._tickIncrement); 
+        let prevTime = KeyframeFunc.convertPixelTime(this._visibleStart + offset, "mili", "time", this._tickSpacing, this._tickIncrement);
+        let prevCurrent = KeyframeFunc.convertPixelTime(this._currentBarX,"mili", "time", this._tickSpacing, this._tickIncrement);  
         e.deltaY < 0 ? this.zoom(true) : this.zoom(false); 
         let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
+        let currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
         this._infoContainer.current!.scrollLeft = currPixel - offset; 
-        this._visibleStart = currPixel - offset;    
+        this._visibleStart = currPixel - offset;  
+        this.changeCurrentBarX(currCurrent);  
     }
 
     @action
diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx
index 572b35b90..1fd97c6c1 100644
--- a/src/client/views/animationtimeline/TimelineMenu.tsx
+++ b/src/client/views/animationtimeline/TimelineMenu.tsx
@@ -44,12 +44,16 @@ export class TimelineMenu extends React.Component {
                 document.addEventListener("keypress", (e:KeyboardEvent) => {
                     if (e.keyCode === 13) {
                         event(text); 
+                        this.closeMenu(); 
                     }
                 });
             }}/></div>); 
         } else if (type === "button") {
             let buttonRef = React.createRef<HTMLDivElement>(); 
-            this._currentMenu.push( <div className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={event}>{title}</p></div>); 
+            this._currentMenu.push( <div className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={(e) => {
+                event(e); 
+                this.closeMenu(); 
+            }}>{title}</p></div>); 
         }
     }
 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index e99da6648..89533c4df 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -53,10 +53,6 @@ export class Track extends React.Component<IProps> {
             if (this.regions.length === 0) this.createRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
             this.props.node.hidden = false;                   
             this.props.node.opacity = 1; 
-            let state = new Doc();  
-            state.key = Doc.MakeCopy(await this.props.node, true);
-            console.log(this.props.node.x); 
-            this._storedState = state;             
         });
 
     }
@@ -101,7 +97,7 @@ export class Track extends React.Component<IProps> {
     @action 
     revertState = () => {
         let copyDoc = Doc.MakeCopy(this.props.node, true); 
-        this.applyKeys(this._storedState!); 
+        if (this._storedState) this.applyKeys(this._storedState);
         let newState = new Doc(); 
         newState.key = copyDoc; 
         this._storedState = newState; 
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index e3b5f78a7..01a064b69 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -334,7 +334,7 @@ export namespace Doc {
     }
 
     export function IndexOf(toFind: Doc, list: Doc[]) {
-        return list.findIndex(doc => doc === toFind || Doc.AreProtosEqual(doc, toFind))
+        return list.findIndex(doc => doc === toFind || Doc.AreProtosEqual(doc, toFind));
     }
     export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean, reversed?: boolean) {
         if (target[key] === undefined) {
-- 
cgit v1.2.3-70-g09d2


From bf8907cfc3e005f2ce6756820d9b3f9de35f1807 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 24 Sep 2019 16:50:23 -0400
Subject: brushing

---
 src/client/views/animationtimeline/Keyframe.tsx | 3 ++-
 src/client/views/animationtimeline/Timeline.tsx | 2 +-
 src/client/views/animationtimeline/Track.tsx    | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 7197f4b49..9728c2462 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -532,6 +532,7 @@ export class Keyframe extends React.Component<IProps> {
         e.stopPropagation();
         let div = ref.current!;
         div.style.opacity = "1";
+        Doc.BrushDoc(this.props.node); 
     }
 
     onContainerOut = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
@@ -539,6 +540,7 @@ export class Keyframe extends React.Component<IProps> {
         e.stopPropagation();
         let div = ref.current!;
         div.style.opacity = "0";
+        Doc.UnBrushDoc(this.props.node); 
     }
 
 
@@ -623,7 +625,6 @@ export class Keyframe extends React.Component<IProps> {
         }
     }
     render() {
-        console.log("RERENDERING"); 
         return (
             <div>
                 <div className="bar" ref={this._bar} style={{ transform: `translate(${this.pixelPosition}px)`, 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index c50ffa51b..875a0b8f3 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -423,7 +423,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                             </div>
                         </div>
                         <div key="timeline_title"className="title-container" ref={this._titleContainer}>
-                            {DocListCast(this.children).map(doc => <div className="datapane"><p>{doc.title}</p></div>)}
+                            {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => {Doc.BrushDoc(doc);}} onPointerOut={() => {Doc.UnBrushDoc(doc);}}><p>{doc.title}</p></div>)}
                         </div>
                         <div key="timeline_resize" onPointerDown={this.onResizeDown}>
                             <FontAwesomeIcon className="resize" icon={faGripLines} />
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index c68d9bb3a..274b215d9 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -294,7 +294,7 @@ export class Track extends React.Component<IProps> {
         return (
             <div className="track-container">
                 <div className="track">
-                    <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick}>
+                    <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick} onPointerOver = {() => {Doc.BrushDoc(this.props.node);}}onPointerOut={() => {Doc.UnBrushDoc(this.props.node);}}>
                         {DocListCast(this.regions).map((region) => {
                             return <Keyframe {...this.props} RegionData={region} />;
                         })}
-- 
cgit v1.2.3-70-g09d2


From 8c018a7a686a752ef1b86b852ec2d298792aa354 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sat, 28 Sep 2019 17:00:47 -0400
Subject: toggle

---
 src/client/views/animationtimeline/Keyframe.tsx    | 100 ++++-------------
 src/client/views/animationtimeline/Timeline.scss   |  20 ++++
 src/client/views/animationtimeline/Timeline.tsx    | 121 ++++++---------------
 .../views/animationtimeline/TimelineMenu.tsx       |  11 +-
 .../views/animationtimeline/TimelineOverview.tsx   |   2 +
 src/client/views/animationtimeline/Track.tsx       |  40 +++----
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   3 +-
 7 files changed, 102 insertions(+), 195 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 9728c2462..66ad6a76d 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -8,7 +8,6 @@ import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
 import { Cast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new_fields/Schema";
-import { FlyoutProps } from "./Timeline";
 import { Transform } from "../../util/Transform";
 import { InkField, StrokeData } from "../../../new_fields/InkField";
 import { TimelineMenu } from "./TimelineMenu";
@@ -138,48 +137,13 @@ export class Keyframe extends React.Component<IProps> {
     @observable private _mouseToggled = false; 
     @observable private _doubleClickEnabled = false; 
 
-    @computed
-    private get regiondata() {
-        let index = this.regions.indexOf(this.props.RegionData);
-        return RegionData(this.regions[index] as Doc);
-    }
-
-    @computed
-    private get regions() {
-        return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;
-    }
-
-    @computed
-    private get firstKeyframe() {
-        let first: (Doc | undefined) = undefined;
-        DocListCast(this.regiondata.keyframes!).forEach(kf => {
-            if (kf.type !== KeyframeFunc.KeyframeType.fade) {
-                if (!first || first && NumCast(kf.time) < NumCast(first.time)) {
-                    first = kf;
-                }
-            }
-        });
-        return first;
-    }
-
-    @computed
-    private get lastKeyframe() {
-        let last: (Doc | undefined) = undefined;
-        DocListCast(this.regiondata.keyframes!).forEach(kf => {
-            if (kf.type !== KeyframeFunc.KeyframeType.fade) {
-                if (!last || last && NumCast(kf.time) > NumCast(last.time)) {
-                    last = kf;
-                }
-            }
-        });
-        return last;
-    }
-
-    @computed
-    private get keyframes(){
-        return DocListCast(this.regiondata.keyframes); 
-    }
-
+    @computed private get regiondata() { return RegionData(this.regions[this.regions.indexOf(this.props.RegionData)] as Doc);}
+    @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;}
+    @computed private get keyframes(){ return DocListCast(this.regiondata.keyframes); }
+    @computed private get pixelPosition(){ return KeyframeFunc.convertPixelTime(this.regiondata.position, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);}    
+    @computed private get pixelDuration(){ return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
+    @computed private get pixelFadeIn() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
+    @computed private get pixelFadeOut(){ return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed
     private get inks() {
         if (this.props.collection.data_ext) {
@@ -191,38 +155,18 @@ export class Keyframe extends React.Component<IProps> {
         }
     }
 
-    @computed 
-    private get pixelPosition(){
-        return KeyframeFunc.convertPixelTime(this.regiondata.position, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
-    }
-
-    @computed 
-    private get pixelDuration(){
-        return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
-    }
-
-    @computed
-    private get pixelFadeIn() {
-        return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
-    }
-
-    @computed
-    private get pixelFadeOut(){
-        return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
-    }
-
-    async componentWillMount() {
-        if (!this.regiondata.keyframes) {
-            this.regiondata.keyframes = new List<Doc>();
-        }
-        let fadeIn = await this.makeKeyData(this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade)!;
-        let fadeOut = await this.makeKeyData(this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade)!;
-        let start = await this.makeKeyData(this.regiondata.position, KeyframeFunc.KeyframeType.fade)!;
-        let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!;
-        (fadeIn.key! as Doc).opacity = 1;
-        (fadeOut.key! as Doc).opacity = 1;
-        (start.key! as Doc).opacity = 0.1;
-        (finish.key! as Doc).opacity = 0.1;
+    componentWillMount() {
+        runInAction(async () => {
+            if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();
+            let fadeIn = await this.makeKeyData(this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade)!;
+            let fadeOut = await this.makeKeyData(this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade)!;
+            let start = await this.makeKeyData(this.regiondata.position, KeyframeFunc.KeyframeType.fade)!;
+            let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!;
+            (fadeIn.key! as Doc).opacity = 1;
+            (fadeOut.key! as Doc).opacity = 1;
+            (start.key! as Doc).opacity = 0.1;
+            (finish.key! as Doc).opacity = 0.1;
+        }); 
     }
 
     @action
@@ -336,7 +280,7 @@ export class Keyframe extends React.Component<IProps> {
         let bar = this._bar.current!;
         let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         let leftRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions);
-        let firstkf: (Doc | undefined) = this.firstKeyframe;
+        let firstkf: (Doc | undefined) = this.keyframes[0];
         if (firstkf && this.regiondata.position + this.regiondata.fadeIn + offset >= NumCast(firstkf!.time)) {
             let dif = NumCast(firstkf!.time) - (this.pixelPosition + this.pixelFadeIn);
             this.regiondata.position = NumCast(firstkf!.time) - this.regiondata.fadeIn;
@@ -364,8 +308,8 @@ export class Keyframe extends React.Component<IProps> {
         let bar = this._bar.current!;
         let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions);
-        if (this.lastKeyframe! && this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= NumCast((this.lastKeyframe! as Doc).time)) {
-            let dif = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - NumCast((this.lastKeyframe! as Doc).time);
+        if (this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= NumCast((this.keyframes[this.keyframes.length - 1]).time)) {
+            let dif = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - NumCast((this.keyframes[this.keyframes.length - 1]).time);
             this.regiondata.duration -= dif;
         } else if (this.regiondata.duration + offset < this.regiondata.fadeIn + this.regiondata.fadeOut) { // nokeyframes, just fades
             this.regiondata.duration = this.regiondata.fadeIn + this.regiondata.fadeOut;
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 1457d5a84..990bc681c 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -119,4 +119,24 @@
         width: 100%; 
         background-color: grey; 
     }
+}
+
+.round-toggle {
+    position: absolute;
+    height: 40px;
+    width: 80px;
+    background-color: white;
+    border: 2px solid purple;
+    border-radius: 20px;
+    input{
+        opacity: 0; 
+        height: 0; 
+        width: 0; 
+    }
+    .slider{
+        height: 40px; 
+        width: 40px; 
+        background-color: black; 
+        border-radius: 20px; 
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 875a0b8f3..8f96315a0 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -15,17 +15,6 @@ import { TimelineOverview } from "./TimelineOverview";
 import { FieldViewProps } from "../nodes/FieldView";
 import { KeyframeFunc } from "./Keyframe";
 
-
-
-export interface FlyoutProps {
-    x?: number;
-    y?: number;
-    display?: string;
-    regiondata?: Doc;
-    regions?: List<Doc>;
-}
-
-
 @observer
 export class Timeline extends React.Component<FieldViewProps> {
 
@@ -35,26 +24,21 @@ export class Timeline extends React.Component<FieldViewProps> {
     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 _timelineWrapper = React.createRef<HTMLDivElement>();
     @observable private _infoContainer = React.createRef<HTMLDivElement>();
 
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
     @observable private _isPlaying: boolean = false; //scrubber playing
-    @observable private _isFrozen: boolean = true; //timeline freeze
     @observable private _totalLength: number = 0;
     @observable private _visibleLength: number = 0; 
     @observable private _visibleStart: number = 0; 
-    @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT;
+    @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT; 
+    @observable private _tickSpacing = this.DEFAULT_TICK_SPACING;
+    @observable private _tickIncrement = this.DEFAULT_TICK_INCREMENT;
     @observable private _time = 100000; //DEFAULT
     @observable private _ticks: number[] = [];
     @observable private _playButton = faPlayCircle; 
@@ -273,39 +257,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
-    @action
-    onTimelineDown = (e: React.PointerEvent) => {
-        e.preventDefault();
-        if (e.nativeEvent.which === 1 && !this._isFrozen) {
-            document.addEventListener("pointermove", this.onTimelineMove);
-            document.addEventListener("pointerup", () => { document.removeEventListener("pointermove", this.onTimelineMove); });
-        }
-    }
 
-    @action
-    onTimelineMove = (e: PointerEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        let timelineContainer = this._timelineWrapper.current!;
-        let left = parseFloat(timelineContainer.style.left!);
-        let top = parseFloat(timelineContainer.style.top!);
-        timelineContainer.style.left = `${left + e.movementX}px`;
-        timelineContainer.style.top = `${top + e.movementY}px`;
-    }
-
-    @action
-    minimize = (e: React.MouseEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        let timelineContainer = this._timelineContainer.current!;
-        if (this._isMinimized) {
-            this._isMinimized = false;
-            timelineContainer.style.visibility = "visible";
-        } else {
-            this._isMinimized = true;
-            timelineContainer.style.visibility = "hidden";
-        }
-    }
 
     @action
     toReadTime = (time: number): string => {
@@ -321,21 +273,6 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     timelineContextMenu = (e:MouseEvent): void => {
         let subitems: ContextMenuProps[] = [];
-        let timelineContainer = this._timelineWrapper.current!;
-        subitems.push({
-            description: "Pin to Top", event: action(() => {
-                if (!this._isFrozen) {
-                    timelineContainer.style.left = "0px";
-                    timelineContainer.style.top = "0px";
-                    timelineContainer.style.transition = "none";
-                }
-            }), icon: faArrowUp
-        });
-        subitems.push({
-            description: this._isFrozen ? "Unfreeze Timeline" : "Freeze Timeline", event: action(() => {
-                this._isFrozen = !this._isFrozen; 
-            }), icon: "thumbtack"
-        });
         subitems.push({
             description: this._timelineVisible ? "Hide Timeline" : "Show Timeline", event: action(() => {
                 this._timelineVisible = !this._timelineVisible; 
@@ -358,7 +295,8 @@ export class Timeline extends React.Component<FieldViewProps> {
         let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
         let currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
         this._infoContainer.current!.scrollLeft = currPixel - offset; 
-        this._visibleStart = currPixel - offset;  
+        this._visibleStart = currPixel - offset > 0 ? currPixel - offset : 0;
+        this._visibleStart += this._visibleLength + this._visibleStart > this._totalLength ? this._totalLength - (this._visibleStart + this._visibleLength) :0;        
         this.changeCurrentBarX(currCurrent);  
     }
 
@@ -402,35 +340,42 @@ export class Timeline extends React.Component<FieldViewProps> {
         </div>
         );
     }
+
     render() {
         return (
-            <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}>
-                <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}} ref={this._timelineWrapper}>
-                    <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button>
-                    <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown}>
-                        {this.timelineToolBox(0.5)}
-                        <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
-                            <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} onClick={this.onScrubberClick}>
-                                {this._ticks.map(element => {
-                                    if(element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement)* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>;
-                                })}
+            <div>
+                <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}>
+                    <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}}>
+                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }}>
+                            {this.timelineToolBox(0.5)}
+                            <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
+                                <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} onClick={this.onScrubberClick}>
+                                    {this._ticks.map(element => {
+                                        if(element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement)* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>;
+                                    })}
+                                </div>
+                                <div key="timeline_scrubber" className="scrubber" onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
+                                    <div key="timeline_scrubberhead" className="scrubberhead"></div>
+                                </div>
+                                <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}>
+                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document} timelineVisible = {this._timelineVisible}/>)}
+                                </div>
                             </div>
-                            <div key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
-                                <div key="timeline_scrubberhead" className="scrubberhead"></div>
+                            <div key="timeline_title"className="title-container" ref={this._titleContainer}>
+                                {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => {Doc.BrushDoc(doc);}} onPointerOut={() => {Doc.UnBrushDoc(doc);}}><p>{doc.title}</p></div>)}
                             </div>
-                            <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}>
-                                {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document} timelineVisible = {this._timelineVisible}/>)}
+                            <div key="timeline_resize" onPointerDown={this.onResizeDown}>
+                                <FontAwesomeIcon className="resize" icon={faGripLines} />
                             </div>
                         </div>
-                        <div key="timeline_title"className="title-container" ref={this._titleContainer}>
-                            {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => {Doc.BrushDoc(doc);}} onPointerOut={() => {Doc.UnBrushDoc(doc);}}><p>{doc.title}</p></div>)}
-                        </div>
-                        <div key="timeline_resize" onPointerDown={this.onResizeDown}>
-                            <FontAwesomeIcon className="resize" icon={faGripLines} />
-                        </div>
                     </div>
+                    {BoolCast(this.props.Document.isAnimating) ? <div></div>: this.timelineToolBox(1) }
                 </div>
-                {BoolCast(this.props.Document.isAnimating) ? <div></div>: this.timelineToolBox(1) }
+                <label key="round-toggle" className="round-toggle">
+                    <input type="checkbox"/>
+                    <span className="round-toggle-slider"> </span>                    
+                </label>
+
             </div>
         );
     }
diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx
index f3b985297..59c25596e 100644
--- a/src/client/views/animationtimeline/TimelineMenu.tsx
+++ b/src/client/views/animationtimeline/TimelineMenu.tsx
@@ -4,6 +4,7 @@ import {observer} from "mobx-react";
 import "./TimelineMenu.scss"; 
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { faChartLine, faRoad, faClipboard, faPen, faTrash, faTable } from "@fortawesome/free-solid-svg-icons";
+import { Utils } from "../../../Utils";
 
 
 @observer
@@ -40,7 +41,7 @@ export class TimelineMenu extends React.Component {
         if (type === "input"){
             let inputRef = React.createRef<HTMLInputElement>(); 
             let text = ""; 
-            this._currentMenu.push(<div className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {inputRef} placeholder={title} onChange={(e) => {
+            this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {inputRef} placeholder={title} onChange={(e) => {
                 e.stopPropagation();
                 text = e.target.value;
             }} onKeyDown={(e) => {
@@ -52,23 +53,23 @@ export class TimelineMenu extends React.Component {
             }}/></div>); 
         } else if (type === "button") {
             let buttonRef = React.createRef<HTMLDivElement>(); 
-            this._currentMenu.push( <div className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={(e) => {
+            this._currentMenu.push( <div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={(e) => {
                 e.preventDefault(); 
                 e.stopPropagation(); 
                 event(e); 
                 this.closeMenu(); 
             }}>{title}</p></div>); 
-        }
+        }  
     }
 
     @action 
     addMenu = (title:string) => {
-        this._currentMenu.unshift(<div className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>);     
+        this._currentMenu.unshift(<div key={Utils.GenerateGuid()} className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>);     
     }
 
     render() {
         return (
-            <div className="timeline-menu-container" style={{opacity: this._opacity, left: this._x, top: this._y}} >
+            <div key={Utils.GenerateGuid()} className="timeline-menu-container" style={{opacity: this._opacity, left: this._x, top: this._y}} >
                 {this._currentMenu}
             </div>
         );
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 38b823cbc..a8f7faba8 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -78,6 +78,8 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     }
 
     render(){
+        console.log("rendered"); 
+        console.log(this.props.visibleStart); 
         return(
             <div key="timeline-overview-container" className="timeline-overview-container" style={{height: `${this.DEFAULT_HEIGHT * this.props.scale * 0.8}px` ,width:`${this.DEFAULT_WIDTH * this.props.scale}`}}>
                 <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{marginLeft:`${(this.props.visibleStart / this.props.totalLength)* this.DEFAULT_WIDTH * this.props.scale}px`, width:`${(this.props.visibleLength / this.props.totalLength) * this.DEFAULT_WIDTH * this.props.scale}px`}} onPointerDown={this.onPointerDown}></div>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 274b215d9..3ec410216 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -32,18 +32,24 @@ export class Track extends React.Component<IProps> {
     @observable private _onKeyframe: (Doc | undefined) = undefined;
     @observable private _onRegionData: (Doc | undefined) = undefined;
     @observable private _storedState: (Doc | undefined) = undefined;
-    
-    @computed
-    private get regions() {
-        return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;
-    }
+    @observable private filterList = [
+        "regions", 
+        "cursors", 
+        "hidden", 
+        "nativeHeight", 
+        "nativeWidth", 
+        "schemaColumns", 
+        "baseLayout", 
+        "backgroundLayout", 
+        "layout", 
+    ]; 
+        
+    @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;}
 
     componentWillMount() {
-        if (!this.props.node.regions) {
-            this.props.node.regions = new List<Doc>();            
-        }
-      
-        
+        runInAction(() => {
+            if (!this.props.node.regions) this.props.node.regions = new List<Doc>();            
+        });
     }
 
     componentDidMount() {
@@ -54,11 +60,11 @@ export class Track extends React.Component<IProps> {
             this.props.node.hidden = false;                   
             this.props.node.opacity = 1; 
         });
-
     }
 
     componentWillUnmount() {
         runInAction(() => {
+            //disposing reactions 
             if (this._currentBarXReaction) this._currentBarXReaction();
             if (this._timelineVisibleReaction) this._timelineVisibleReaction(); 
         });
@@ -166,17 +172,7 @@ export class Track extends React.Component<IProps> {
         });
     }
 
-    private filterList = [
-        "regions", 
-        "cursors", 
-        "hidden", 
-        "nativeHeight", 
-        "nativeWidth", 
-        "schemaColumns", 
-        "baseLayout", 
-        "backgroundLayout", 
-        "layout", 
-    ]; 
+ 
 
     @action
     private filterKeys = (keys: string[]): string[] => {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index af2651dc8..bbfc5eb51 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -115,8 +115,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                                         StrCast(this.layoutDoc.boxShadow, ""),
                     borderRadius: this.borderRounding(),
                     transform: this.transform,
-                    //CHANGE
-                    transition: this.Document.isAnimating !== undefined ? ".5s ease-in" : this.props.transition ? this.props.transition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.transition),
+                    // transition: this.Document.isAnimating !== undefined ? ".5s ease-in" : this.props.transition ? this.props.transition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.transition),
                     width: this.width,
                     height: this.height,
                     zIndex: this.Document.zIndex || 0,
-- 
cgit v1.2.3-70-g09d2


From d2207f2fe6369edea33bec74812a8112b138aaee Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 1 Oct 2019 16:24:18 -0400
Subject: toggle button

---
 src/client/views/animationtimeline/Timeline.scss   | 44 +++++++++++++++------
 src/client/views/animationtimeline/Timeline.tsx    | 45 ++++++++++++++++------
 .../views/animationtimeline/TimelineOverview.tsx   |  2 -
 3 files changed, 65 insertions(+), 26 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 990bc681c..09fc593fc 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -1,11 +1,6 @@
 @import "./../globalCssVariables.scss"; 
 
-.minimize{
-    position:relative; 
-    z-index: 1000; 
-    height: 30px; 
-    width: 100px; 
-}
+
 
 .timeline-toolbox{
     position:absolute; 
@@ -17,6 +12,8 @@
         margin-left:10px; 
     }
 }
+
+
 .timeline-container{
     width:100%;
     height:300px; 
@@ -37,12 +34,10 @@
             background-color: transparent; 
             height: 30px;
             width:100%; 
-            
             .tick{
                 height:100%; 
                 width: 1px; 
                 background-color:black; 
-
             }   
         }
         .scrubber{
@@ -128,15 +123,40 @@
     background-color: white;
     border: 2px solid purple;
     border-radius: 20px;
+    animation-fill-mode: forwards; 
+    animation-duration: 500ms;
     input{
+        position:absolute; 
         opacity: 0; 
         height: 0; 
         width: 0; 
     }
-    .slider{
-        height: 40px; 
-        width: 40px; 
-        background-color: black; 
+    .round-toggle-slider{
+        position:absolute; 
+        height: 35px; 
+        width: 35px; 
+        top: 0.5px;
+        background-color: white;
+        border:1px solid grey;
         border-radius: 20px; 
+        transition: transform 500ms ease-in-out; 
+
+    } 
+ 
+}
+@keyframes turnon{
+    from{
+        background-color: white;
+    }
+    to{
+        background-color: purple; 
+    }
+}   
+@keyframes turnoff{
+    from{
+        background-color: purple; 
+    }
+    to{
+        background-color: white; 
     }
 }
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 8f96315a0..8127e4de2 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -29,6 +29,8 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _titleContainer = React.createRef<HTMLDivElement>();
     @observable private _timelineContainer = React.createRef<HTMLDivElement>();
     @observable private _infoContainer = React.createRef<HTMLDivElement>();
+    @observable private _roundToggleRef = React.createRef<HTMLDivElement>();  
+    @observable private _roundToggleContainerRef = React.createRef<HTMLDivElement>(); 
 
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
@@ -331,23 +333,45 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     private timelineToolBox = (scale:number) => {
         let size = 50 * scale; //50 is default
-        return (
+        return (   
+      
         <div key="timeline_toolbox" className="timeline-toolbox" style={{height:`${size}px`}}>
-                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{height:`${size}px`, width: `${size}px`}} /> </div>
-                <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
-                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
-                <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> 
+            <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{height:`${size}px`, width: `${size}px`}} /> </div>
+            <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
+            <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
+            <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/>            
+            <div ref={this._roundToggleContainerRef}key="round-toggle" className="round-toggle">
+                <div ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown = {this.toggleChecked}> </div>                    
+            </div>
         </div>
         );
     }
 
+    @action
+    private toggleChecked = (e:React.PointerEvent) => {
+        e.preventDefault(); 
+        e.stopPropagation(); 
+        let roundToggle = this._roundToggleRef.current!; 
+        let roundToggleContainer = this._roundToggleContainerRef.current!; 
+        if (BoolCast(this.props.Document.isAnimating)){
+            roundToggle.style.transform = "translate(0px, 0px)";
+            roundToggle.style.animationName = "turnoff"; 
+            roundToggleContainer.style.animationName = "turnoff"; 
+ 
+            this.props.Document.isAnimating = false;
+        } else {
+            roundToggle.style.transform = "translate(45px, 0px)"; 
+            roundToggle.style.animationName = "turnon"; 
+            roundToggleContainer.style.animationName = "turnon"; 
+            this.props.Document.isAnimating = true; 
+        }
+    }
     render() {
         return (
             <div>
                 <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}>
                     <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}}>
                         <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }}>
-                            {this.timelineToolBox(0.5)}
                             <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
                                 <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} onClick={this.onScrubberClick}>
                                     {this._ticks.map(element => {
@@ -365,16 +389,13 @@ export class Timeline extends React.Component<FieldViewProps> {
                                 {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => {Doc.BrushDoc(doc);}} onPointerOut={() => {Doc.UnBrushDoc(doc);}}><p>{doc.title}</p></div>)}
                             </div>
                             <div key="timeline_resize" onPointerDown={this.onResizeDown}>
-                                <FontAwesomeIcon className="resize" icon={faGripLines} />
+                                <FontAwesomeIcon className="resize" icon={faGripLines}/>
                             </div>
                         </div>
                     </div>
-                    {BoolCast(this.props.Document.isAnimating) ? <div></div>: this.timelineToolBox(1) }
+                    { this.timelineToolBox(1) }
                 </div>
-                <label key="round-toggle" className="round-toggle">
-                    <input type="checkbox"/>
-                    <span className="round-toggle-slider"> </span>                    
-                </label>
+      
 
             </div>
         );
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index a8f7faba8..38b823cbc 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -78,8 +78,6 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     }
 
     render(){
-        console.log("rendered"); 
-        console.log(this.props.visibleStart); 
         return(
             <div key="timeline-overview-container" className="timeline-overview-container" style={{height: `${this.DEFAULT_HEIGHT * this.props.scale * 0.8}px` ,width:`${this.DEFAULT_WIDTH * this.props.scale}`}}>
                 <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{marginLeft:`${(this.props.visibleStart / this.props.totalLength)* this.DEFAULT_WIDTH * this.props.scale}px`, width:`${(this.props.visibleLength / this.props.totalLength) * this.DEFAULT_WIDTH * this.props.scale}px`}} onPointerDown={this.onPointerDown}></div>
-- 
cgit v1.2.3-70-g09d2


From 7ccce9564e11ede82bec01b9eea3889da4dc1bc2 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 1 Oct 2019 17:10:17 -0400
Subject: changes with toggling

---
 src/client/views/animationtimeline/Timeline.scss | 11 +++++------
 src/client/views/animationtimeline/Timeline.tsx  |  8 +++++---
 2 files changed, 10 insertions(+), 9 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 09fc593fc..71fac876d 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -22,7 +22,7 @@
     box-shadow: 0px 10px 20px; 
 
     .info-container{ 
-        margin-top: 50px; 
+        margin-top: 80px; 
         right:20px; 
         position:absolute; 
         height: calc(100% - 100px); 
@@ -72,7 +72,7 @@
         
     }
     .title-container{
-        margin-top: 80px; 
+        margin-top: 110px; 
         margin-left: 20px; 
         height: calc(100% - 100px - 30px); 
         width: 100px; 
@@ -117,7 +117,6 @@
 }
 
 .round-toggle {
-    position: absolute;
     height: 40px;
     width: 80px;
     background-color: white;
@@ -125,6 +124,7 @@
     border-radius: 20px;
     animation-fill-mode: forwards; 
     animation-duration: 500ms;
+    top: 20px; 
     input{
         position:absolute; 
         opacity: 0; 
@@ -132,15 +132,14 @@
         width: 0; 
     }
     .round-toggle-slider{
-        position:absolute; 
         height: 35px; 
         width: 35px; 
-        top: 0.5px;
         background-color: white;
         border:1px solid grey;
         border-radius: 20px; 
         transition: transform 500ms ease-in-out; 
-
+        margin-left: 0px; 
+        margin-top: 0.5px; 
     } 
  
 }
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 8127e4de2..bc48f422a 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -18,7 +18,7 @@ import { KeyframeFunc } from "./Keyframe";
 @observer
 export class Timeline extends React.Component<FieldViewProps> {
 
-    private readonly DEFAULT_CONTAINER_HEIGHT: number = 300;
+    private readonly DEFAULT_CONTAINER_HEIGHT: number = 330;
     private readonly DEFAULT_TICK_SPACING: number = 50;
     private readonly MIN_CONTAINER_HEIGHT: number = 205;
     private readonly MAX_CONTAINER_HEIGHT: number = 800;
@@ -353,16 +353,18 @@ export class Timeline extends React.Component<FieldViewProps> {
         e.stopPropagation(); 
         let roundToggle = this._roundToggleRef.current!; 
         let roundToggleContainer = this._roundToggleContainerRef.current!; 
+        let timelineContainer = this._timelineContainer.current!; 
         if (BoolCast(this.props.Document.isAnimating)){
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff"; 
             roundToggleContainer.style.animationName = "turnoff"; 
- 
+            timelineContainer.style.transform = `translate(0px, ${this._containerHeight}px)`; 
             this.props.Document.isAnimating = false;
         } else {
             roundToggle.style.transform = "translate(45px, 0px)"; 
             roundToggle.style.animationName = "turnon"; 
             roundToggleContainer.style.animationName = "turnon"; 
+            timelineContainer.style.transform = `translate(0px, ${-this._containerHeight}px)`; 
             this.props.Document.isAnimating = true; 
         }
     }
@@ -371,7 +373,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             <div>
                 <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}>
                     <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}}>
-                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }}>
+                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top:`${-this._containerHeight}`}}>
                             <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
                                 <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} onClick={this.onScrubberClick}>
                                     {this._ticks.map(element => {
-- 
cgit v1.2.3-70-g09d2


From 3143c2775cdf7bdafa44f047ea9b6ebbd090b28e Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sat, 5 Oct 2019 17:26:10 -0400
Subject: animation

---
 src/client/views/animationtimeline/Timeline.scss |   1 +
 src/client/views/animationtimeline/Timeline.tsx  | 251 ++++++++++++-----------
 2 files changed, 131 insertions(+), 121 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 71fac876d..fbdb2a200 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -20,6 +20,7 @@
     position:absolute;
     background-color: $light-color-secondary;
     box-shadow: 0px 10px 20px; 
+    transition: transform 500ms ease; 
 
     .info-container{ 
         margin-top: 80px; 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index bc48f422a..8a41a5943 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -29,25 +29,25 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _titleContainer = React.createRef<HTMLDivElement>();
     @observable private _timelineContainer = React.createRef<HTMLDivElement>();
     @observable private _infoContainer = React.createRef<HTMLDivElement>();
-    @observable private _roundToggleRef = React.createRef<HTMLDivElement>();  
-    @observable private _roundToggleContainerRef = React.createRef<HTMLDivElement>(); 
+    @observable private _roundToggleRef = React.createRef<HTMLDivElement>();
+    @observable private _roundToggleContainerRef = React.createRef<HTMLDivElement>();
 
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
     @observable private _isPlaying: boolean = false; //scrubber playing
     @observable private _totalLength: number = 0;
-    @observable private _visibleLength: number = 0; 
-    @observable private _visibleStart: number = 0; 
-    @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT; 
+    @observable private _visibleLength: number = 0;
+    @observable private _visibleStart: number = 0;
+    @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT;
     @observable private _tickSpacing = this.DEFAULT_TICK_SPACING;
     @observable private _tickIncrement = this.DEFAULT_TICK_INCREMENT;
     @observable private _time = 100000; //DEFAULT
     @observable private _ticks: number[] = [];
-    @observable private _playButton = faPlayCircle; 
-    @observable private _timelineVisible = false; 
-    @observable private _mouseToggled = false; 
-    @observable private _doubleClickEnabled = false; 
-    @observable private _reactionDisposer:IReactionDisposer[] = []; 
+    @observable private _playButton = faPlayCircle;
+    @observable private _timelineVisible = false;
+    @observable private _mouseToggled = false;
+    @observable private _doubleClickEnabled = false;
+    @observable private _reactionDisposer: IReactionDisposer[] = [];
 
 
     @computed
@@ -65,7 +65,7 @@ export class Timeline extends React.Component<FieldViewProps> {
 
 
     componentWillMount() {
-        this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false; 
+        this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false;
     }
 
     componentDidMount() {
@@ -78,29 +78,29 @@ export class Timeline extends React.Component<FieldViewProps> {
                     return NumCast(this.props.Document.curPage);
                 }, curPage => {
                     if (!this._isPlaying) {
-                        this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing); 
-                        this.props.Document.curPage = this._currentBarX; 
-                        this.play(); 
+                        this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
+                        this.props.Document.curPage = this._currentBarX;
+                        this.play();
                     }
                 }));
             }
         }
         runInAction(() => {
             this._reactionDisposer.push(reaction(() => {
-                return this._time;  
+                return this._time;
             }, () => {
                 this._ticks = [];
                 for (let i = 0; i < this._time;) {
                     this._ticks.push(i);
                     i += 1000;
                 }
-                this._totalLength = this._tickSpacing * (this._time/ this._tickIncrement); 
-            }, {fireImmediately:true})); 
-            this._totalLength = this._tickSpacing * (this._ticks.length/ this._tickIncrement); 
-            this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; 
-            this._visibleStart = this._infoContainer.current!.scrollLeft;   
+                this._totalLength = this._tickSpacing * (this._time / this._tickIncrement);
+            }, { fireImmediately: true }));
+            this._totalLength = this._tickSpacing * (this._ticks.length / this._tickIncrement);
+            this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width;
+            this._visibleStart = this._infoContainer.current!.scrollLeft;
         });
-       
+
 
     }
 
@@ -112,30 +112,30 @@ export class Timeline extends React.Component<FieldViewProps> {
     //for playing
     @action
     onPlay = (e: React.MouseEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
-        this.play(); 
+        e.preventDefault();
+        e.stopPropagation();
+        this.play();
     }
 
     @action
     play = () => {
         if (this._isPlaying) {
             this._isPlaying = false;
-            this._playButton = faPlayCircle; 
+            this._playButton = faPlayCircle;
         } else {
             this._isPlaying = true;
-            this._playButton = faPauseCircle; 
+            this._playButton = faPauseCircle;
             const playTimeline = () => {
-                if (this._isPlaying){
+                if (this._isPlaying) {
                     if (this._currentBarX >= this._totalLength) {
-                        this.changeCurrentBarX(0); 
+                        this.changeCurrentBarX(0);
                     } else {
                         this.changeCurrentBarX(this._currentBarX + this._windSpeed);
-                    }                        
-                    setTimeout(playTimeline, 15);  
+                    }
+                    setTimeout(playTimeline, 15);
                 }
-            }; 
-            playTimeline(); 
+            };
+            playTimeline();
         }
     }
 
@@ -143,8 +143,8 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     @action
     windForward = (e: React.MouseEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
+        e.preventDefault();
+        e.stopPropagation();
         if (this._windSpeed < 64) { //max speed is 32
             this._windSpeed = this._windSpeed * 2;
         }
@@ -152,8 +152,8 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     @action
     windBackward = (e: React.MouseEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
+        e.preventDefault();
+        e.stopPropagation();
         if (this._windSpeed > 1 / 16) { // min speed is 1/8
             this._windSpeed = this._windSpeed / 2;
         }
@@ -177,7 +177,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         let scrubberbox = this._scrubberbox.current!;
         let left = scrubberbox.getBoundingClientRect().left;
         let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
-        this.changeCurrentBarX(offsetX); 
+        this.changeCurrentBarX(offsetX);
     }
 
     @action
@@ -186,7 +186,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         e.stopPropagation();
         let scrubberbox = this._scrubberbox.current!;
         let offsetX = (e.clientX - scrubberbox.getBoundingClientRect().left) * this.props.ScreenToLocalTransform().Scale;
-        this.changeCurrentBarX(offsetX); 
+        this.changeCurrentBarX(offsetX);
     }
 
 
@@ -195,19 +195,21 @@ export class Timeline extends React.Component<FieldViewProps> {
     onPanDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let clientX = e.clientX; 
-        if (this._doubleClickEnabled){
-            this._doubleClickEnabled = false; 
+        let clientX = e.clientX;
+        if (this._doubleClickEnabled) {
+            this._doubleClickEnabled = false;
         } else {
-            setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled) this.changeCurrentBarX(this._trackbox.current!.scrollLeft + clientX -  this._trackbox.current!.getBoundingClientRect().left); 
+            setTimeout(() => {
+                if (!this._mouseToggled && this._doubleClickEnabled) this.changeCurrentBarX(this._trackbox.current!.scrollLeft + clientX - this._trackbox.current!.getBoundingClientRect().left);
                 this._mouseToggled = false;
-                this._doubleClickEnabled = false;}, 200); 
-            this._doubleClickEnabled = true; 
+                this._doubleClickEnabled = false;
+            }, 200);
+            this._doubleClickEnabled = true;
             document.addEventListener("pointermove", this.onPanMove);
             document.addEventListener("pointerup", () => {
                 document.removeEventListener("pointermove", this.onPanMove);
                 if (!this._doubleClickEnabled) {
-                    this._mouseToggled = false; 
+                    this._mouseToggled = false;
                 }
             });
 
@@ -219,7 +221,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         e.preventDefault();
         e.stopPropagation();
         if (e.movementX !== 0 || e.movementY !== 0) {
-            this._mouseToggled = true; 
+            this._mouseToggled = true;
         }
         let trackbox = this._trackbox.current!;
         let titleContainer = this._titleContainer.current!;
@@ -227,10 +229,10 @@ export class Timeline extends React.Component<FieldViewProps> {
         trackbox.scrollTop = trackbox.scrollTop - e.movementY;
         titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;
     }
-    @action 
-    movePanX = (pixel:number) => {
+    @action
+    movePanX = (pixel: number) => {
         let infoContainer = this._infoContainer.current!;
-        infoContainer.scrollLeft = pixel; 
+        infoContainer.scrollLeft = pixel;
         this._visibleStart = infoContainer.scrollLeft;
     }
 
@@ -273,131 +275,138 @@ export class Timeline extends React.Component<FieldViewProps> {
         return `${min}:${sec}`;
     }
 
-    timelineContextMenu = (e:MouseEvent): void => {
+    timelineContextMenu = (e: MouseEvent): void => {
         let subitems: ContextMenuProps[] = [];
         subitems.push({
             description: this._timelineVisible ? "Hide Timeline" : "Show Timeline", event: action(() => {
-                this._timelineVisible = !this._timelineVisible; 
+                this._timelineVisible = !this._timelineVisible;
             }), icon: this._timelineVisible ? faEyeSlash : "eye"
-        }); 
-        subitems.push({ description: BoolCast(this.props.Document.isAnimating) ? "Enter Play Mode" : "Enter Authoring Mode", event: () => {
-            BoolCast(this.props.Document.isAnimating) ? this.props.Document.isAnimating = false : this.props.Document.isAnimating = true;}
-            , icon:BoolCast(this.props.Document.isAnimating) ? "play" : "edit"}); 
+        });
+        subitems.push({
+            description: BoolCast(this.props.Document.isAnimating) ? "Enter Play Mode" : "Enter Authoring Mode", event: () => {
+                BoolCast(this.props.Document.isAnimating) ? this.props.Document.isAnimating = false : this.props.Document.isAnimating = true;
+            }
+            , icon: BoolCast(this.props.Document.isAnimating) ? "play" : "edit"
+        });
         ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems, icon: faClock });
     }
 
     @action
     onWheelZoom = (e: React.WheelEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
-        let offset = e.clientX - this._infoContainer.current!.getBoundingClientRect().left; 
+        e.preventDefault();
+        e.stopPropagation();
+        let offset = e.clientX - this._infoContainer.current!.getBoundingClientRect().left;
         let prevTime = KeyframeFunc.convertPixelTime(this._visibleStart + offset, "mili", "time", this._tickSpacing, this._tickIncrement);
-        let prevCurrent = KeyframeFunc.convertPixelTime(this._currentBarX,"mili", "time", this._tickSpacing, this._tickIncrement);  
-        e.deltaY < 0 ? this.zoom(true) : this.zoom(false); 
-        let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
-        let currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
-        this._infoContainer.current!.scrollLeft = currPixel - offset; 
+        let prevCurrent = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
+        e.deltaY < 0 ? this.zoom(true) : this.zoom(false);
+        let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement);
+        let currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, "mili", "pixel", this._tickSpacing, this._tickIncrement);
+        this._infoContainer.current!.scrollLeft = currPixel - offset;
         this._visibleStart = currPixel - offset > 0 ? currPixel - offset : 0;
-        this._visibleStart += this._visibleLength + this._visibleStart > this._totalLength ? this._totalLength - (this._visibleStart + this._visibleLength) :0;        
-        this.changeCurrentBarX(currCurrent);  
+        this._visibleStart += this._visibleLength + this._visibleStart > this._totalLength ? this._totalLength - (this._visibleStart + this._visibleLength) : 0;
+        this.changeCurrentBarX(currCurrent);
     }
 
     @action
     zoom = (dir: boolean) => {
-        let spacingChange = this._tickSpacing; 
-        let incrementChange = this._tickIncrement; 
-        if (dir){
-            if (!(this._tickSpacing === 100 && this._tickIncrement === 1000)){
+        let spacingChange = this._tickSpacing;
+        let incrementChange = this._tickIncrement;
+        if (dir) {
+            if (!(this._tickSpacing === 100 && this._tickIncrement === 1000)) {
                 if (this._tickSpacing >= 100) {
-                    incrementChange /= 2; 
-                    spacingChange = 50; 
+                    incrementChange /= 2;
+                    spacingChange = 50;
                 } else {
-                    spacingChange += 5; 
+                    spacingChange += 5;
                 }
-            } 
+            }
         } else {
             if (this._tickSpacing <= 50) {
-                spacingChange = 100; 
-                incrementChange *= 2; 
+                spacingChange = 100;
+                incrementChange *= 2;
             } else {
-                spacingChange -= 5; 
+                spacingChange -= 5;
             }
         }
-        let finalLength = spacingChange * (this._time / incrementChange);  
-        if (finalLength >= this._infoContainer.current!.getBoundingClientRect().width){
-            this._totalLength = finalLength; 
-            this._tickSpacing = spacingChange; 
-            this._tickIncrement = incrementChange; 
+        let finalLength = spacingChange * (this._time / incrementChange);
+        if (finalLength >= this._infoContainer.current!.getBoundingClientRect().width) {
+            this._totalLength = finalLength;
+            this._tickSpacing = spacingChange;
+            this._tickIncrement = incrementChange;
         }
     }
 
-    private timelineToolBox = (scale:number) => {
+    private timelineToolBox = (scale: number) => {
         let size = 50 * scale; //50 is default
-        return (   
-      
-        <div key="timeline_toolbox" className="timeline-toolbox" style={{height:`${size}px`}}>
-            <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{height:`${size}px`, width: `${size}px`}} /> </div>
-            <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
-            <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{height:`${size}px`, width: `${size}px`}}  /> </div>
-            <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/>            
-            <div ref={this._roundToggleContainerRef}key="round-toggle" className="round-toggle">
-                <div ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown = {this.toggleChecked}> </div>                    
+        return (
+
+            <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
+                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
+                <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
+                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
+                <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                <div ref={this._roundToggleContainerRef} key="round-toggle" className="round-toggle">
+                    <div ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
+                </div>
             </div>
-        </div>
         );
     }
 
     @action
-    private toggleChecked = (e:React.PointerEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
-        let roundToggle = this._roundToggleRef.current!; 
-        let roundToggleContainer = this._roundToggleContainerRef.current!; 
-        let timelineContainer = this._timelineContainer.current!; 
-        if (BoolCast(this.props.Document.isAnimating)){
+    private toggleChecked = (e: React.PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        let roundToggle = this._roundToggleRef.current!;
+        let roundToggleContainer = this._roundToggleContainerRef.current!;
+        let timelineContainer = this._timelineContainer.current!;
+        if (BoolCast(this.props.Document.isAnimating)) {
+
             roundToggle.style.transform = "translate(0px, 0px)";
-            roundToggle.style.animationName = "turnoff"; 
-            roundToggleContainer.style.animationName = "turnoff"; 
-            timelineContainer.style.transform = `translate(0px, ${this._containerHeight}px)`; 
-            this.props.Document.isAnimating = false;
+            roundToggle.style.animationName = "turnoff";
+            roundToggleContainer.style.animationName = "turnoff";
+            timelineContainer.style.transform = `translate(0px, ${0}px)`;
+            setTimeout(() => {
+                this.props.Document.isAnimating = false;
+            }, 500);
         } else {
-            roundToggle.style.transform = "translate(45px, 0px)"; 
-            roundToggle.style.animationName = "turnon"; 
-            roundToggleContainer.style.animationName = "turnon"; 
-            timelineContainer.style.transform = `translate(0px, ${-this._containerHeight}px)`; 
-            this.props.Document.isAnimating = true; 
+            roundToggle.style.transform = "translate(45px, 0px)";
+            roundToggle.style.animationName = "turnon";
+            roundToggleContainer.style.animationName = "turnon";
+            timelineContainer.style.transform = `translate(0px, ${this._containerHeight}px)`;
+            this.props.Document.isAnimating = true;
+
         }
     }
     render() {
         return (
             <div>
-                <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}>
-                    <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}}>
-                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top:`${-this._containerHeight}`}}>
-                            <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
-                                <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} onClick={this.onScrubberClick}>
+                <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
+                    <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
+                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `-${this._containerHeight}px` }}>
+                            <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
+                                <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{ width: `${this._totalLength}px` }} onClick={this.onScrubberClick}>
                                     {this._ticks.map(element => {
-                                        if(element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement)* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>;
+                                        if (element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement) * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>;
                                     })}
                                 </div>
                                 <div key="timeline_scrubber" className="scrubber" onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
                                     <div key="timeline_scrubberhead" className="scrubberhead"></div>
                                 </div>
-                                <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}>
-                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document} timelineVisible = {this._timelineVisible}/>)}
+                                <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
+                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} />)}
                                 </div>
                             </div>
-                            <div key="timeline_title"className="title-container" ref={this._titleContainer}>
-                                {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => {Doc.BrushDoc(doc);}} onPointerOut={() => {Doc.UnBrushDoc(doc);}}><p>{doc.title}</p></div>)}
+                            <div key="timeline_title" className="title-container" ref={this._titleContainer}>
+                                {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)}
                             </div>
                             <div key="timeline_resize" onPointerDown={this.onResizeDown}>
-                                <FontAwesomeIcon className="resize" icon={faGripLines}/>
+                                <FontAwesomeIcon className="resize" icon={faGripLines} />
                             </div>
                         </div>
                     </div>
-                    { this.timelineToolBox(1) }
+                    {this.timelineToolBox(1)}
                 </div>
-      
+
 
             </div>
         );
-- 
cgit v1.2.3-70-g09d2


From 98cc5ba95454be7d36343917c6e2c28047f109b9 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 6 Oct 2019 16:59:33 -0400
Subject: refactoring and resize right fix

---
 src/client/views/animationtimeline/Keyframe.tsx  | 121 +++++++++++++----------
 src/client/views/animationtimeline/Timeline.scss |  12 +--
 src/client/views/animationtimeline/Timeline.tsx  | 104 +++++--------------
 3 files changed, 98 insertions(+), 139 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 66ad6a76d..587625efa 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -288,7 +288,7 @@ export class Keyframe extends React.Component<IProps> {
         } else if (this.regiondata.duration - offset < this.regiondata.fadeIn + this.regiondata.fadeOut) { // no keyframes, just fades
             this.regiondata.position -= (this.regiondata.fadeIn + this.regiondata.fadeOut - this.regiondata.duration);
             this.regiondata.duration = this.regiondata.fadeIn + this.regiondata.fadeOut;
-        } else if (leftRegion && this.regiondata.position + offset <= leftRegion.position + leftRegion.duration) {
+        } else if (leftRegion && this.regiondata.position + offset <= leftRegion.position + leftRegion.duration) {  
             let dif = this.regiondata.position - (leftRegion.position + leftRegion.duration);
             this.regiondata.position = leftRegion.position + leftRegion.duration;
             this.regiondata.duration += dif;
@@ -296,8 +296,8 @@ export class Keyframe extends React.Component<IProps> {
             this.regiondata.duration -= offset;
             this.regiondata.position += offset;
         }
-        this.keyframes[0].time = this.regiondata.position; 
-        this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn; 
+        // this.keyframes[0].time = this.regiondata.position; 
+        // this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn; 
     }
 
 
@@ -308,14 +308,11 @@ export class Keyframe extends React.Component<IProps> {
         let bar = this._bar.current!;
         let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions);
-        if (this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= NumCast((this.keyframes[this.keyframes.length - 1]).time)) {
-            let dif = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - NumCast((this.keyframes[this.keyframes.length - 1]).time);
-            this.regiondata.duration -= dif;
-        } else if (this.regiondata.duration + offset < this.regiondata.fadeIn + this.regiondata.fadeOut) { // nokeyframes, just fades
-            this.regiondata.duration = this.regiondata.fadeIn + this.regiondata.fadeOut;
-        } else if (rightRegion && this.regiondata.position + this.regiondata.duration + offset >= rightRegion.position) {
-            let dif = rightRegion.position - (this.regiondata.position + this.regiondata.duration);
-            this.regiondata.duration += dif;
+        console.log(offset); 
+        console.log(this.keyframes[this.keyframes.length - 3].time); 
+        console.log(this.regiondata.position + this.regiondata.duration - offset); 
+        if (this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - offset <= NumCast(this.keyframes[this.keyframes.length - 3].time)) {
+            console.log("HI"); 
         } else {
             this.regiondata.duration += offset;
         }
@@ -458,6 +455,7 @@ export class Keyframe extends React.Component<IProps> {
         TimelineMenu.Instance.openMenu(e.clientX, e.clientY); 
     }
 
+    @action
     checkInput = (val: any) => {
         return typeof(val === "number"); 
     }
@@ -471,6 +469,7 @@ export class Keyframe extends React.Component<IProps> {
         });
     }
 
+    @action
     onContainerOver = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
         e.preventDefault();
         e.stopPropagation();
@@ -479,6 +478,7 @@ export class Keyframe extends React.Component<IProps> {
         Doc.BrushDoc(this.props.node); 
     }
 
+    @action
     onContainerOut = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
         e.preventDefault();
         e.stopPropagation();
@@ -568,6 +568,60 @@ export class Keyframe extends React.Component<IProps> {
             document.removeEventListener("pointerup", this.onReactionListen); 
         }
     }
+
+    @action
+    drawKeyframes = () => {
+        let keyframeDivs:JSX.Element[] = []; 
+        this.keyframes.forEach( kf => {
+            if (kf.type as KeyframeFunc.KeyframeType === KeyframeFunc.KeyframeType.default) {
+                keyframeDivs.push(
+                    <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                        <div className="divider"></div>
+                        <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
+                            e.preventDefault();
+                            e.stopPropagation();
+                            this.makeKeyframeMenu(kf, e.nativeEvent); 
+                        }}></div>
+                    </div>
+                );
+            }
+            else {
+                keyframeDivs.push(
+                    <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                        <div className="divider"></div>
+                    </div>
+                );
+            }
+        });
+        return keyframeDivs; 
+    }
+
+    @action 
+    drawKeyframeDividers = () => {
+        let keyframeDividers:JSX.Element[] = []; 
+        this.keyframes.forEach(kf => {
+            if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
+                let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; 
+                let bodyRef = React.createRef<HTMLDivElement>(); 
+                let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
+                let leftPos = KeyframeFunc.convertPixelTime(NumCast(left!.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
+                return (
+                    <div ref={bodyRef}className="body-container" style={{left: `${kfPos - this.pixelPosition}px`, width:`${leftPos - kfPos}px`}}
+                    onPointerOver={(e) => { this.onContainerOver(e, bodyRef); }}
+                    onPointerOut={(e) => { this.onContainerOut(e, bodyRef); }}
+                    onContextMenu={(e) => {
+                        e.preventDefault(); 
+                        e.stopPropagation(); 
+                        this._mouseToggled = true; 
+                        this.makeRegionMenu(kf, e.nativeEvent); 
+                    }}>
+                    </div>
+                ); 
+            }  
+        }); 
+        return keyframeDividers; 
+    }
+
     render() {
         return (
             <div>
@@ -577,49 +631,8 @@ export class Keyframe extends React.Component<IProps> {
                     onPointerDown={this.onBarPointerDown}>
                     <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
                     <div className="rightResize" onPointerDown={this.onResizeRight}></div>
-                    {this.keyframes.map(kf => {
-                        if (kf.type as KeyframeFunc.KeyframeType === KeyframeFunc.KeyframeType.default) {
-                            return (
-                                <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
-                                    <div className="divider"></div>
-                                    <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
-                                        e.preventDefault();
-                                        e.stopPropagation();
-                                        this.makeKeyframeMenu(kf, e.nativeEvent); 
-                                    }}></div>
-                                </div>
-                            );
-                        }
-                        else {
-                            return (
-                                <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
-                                    <div className="divider"></div>
-                                </div>
-                            );
-                        }
-                      
-                    })}
-                    {this.keyframes.map( kf => {
-                       if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
-                            let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; 
-                            let bodyRef = React.createRef<HTMLDivElement>(); 
-                            let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
-                            let leftPos = KeyframeFunc.convertPixelTime(NumCast(left!.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
-                            return (
-                                <div ref={bodyRef}className="body-container" style={{left: `${kfPos - this.pixelPosition}px`, width:`${leftPos - kfPos}px`}}
-                                onPointerOver={(e) => { this.onContainerOver(e, bodyRef); }}
-                                onPointerOut={(e) => { this.onContainerOut(e, bodyRef); }}
-                                onContextMenu={(e) => {
-                                    e.preventDefault(); 
-                                    e.stopPropagation(); 
-                                    this._mouseToggled = true; 
-                                    this.makeRegionMenu(kf, e.nativeEvent); 
-                                }}>
-                                </div>
-                            ); 
-                       }  
-                    })}
-
+                    {this.drawKeyframes()}
+                    {this.drawKeyframeDividers()}
                 </div>
             </div>
         );
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index fbdb2a200..cf6b4b3d5 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -13,7 +13,11 @@
     }
 }
 
-
+.tick{
+    height:100%; 
+    width: 1px; 
+    background-color:black; 
+}   
 .timeline-container{
     width:100%;
     height:300px; 
@@ -35,11 +39,7 @@
             background-color: transparent; 
             height: 30px;
             width:100%; 
-            .tick{
-                height:100%; 
-                width: 1px; 
-                background-color:black; 
-            }   
+          
         }
         .scrubber{
             top:30px; 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 8a41a5943..9ac5d98d2 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -8,12 +8,13 @@ import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
+import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes } from "@fortawesome/free-solid-svg-icons";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
 import { FieldViewProps } from "../nodes/FieldView";
 import { KeyframeFunc } from "./Keyframe";
+import { Utils } from "../../../Utils";
 
 @observer
 export class Timeline extends React.Component<FieldViewProps> {
@@ -24,7 +25,6 @@ export class Timeline extends React.Component<FieldViewProps> {
     private readonly MAX_CONTAINER_HEIGHT: number = 800;
     private readonly DEFAULT_TICK_INCREMENT: number = 1000;
 
-    @observable private _scrubberbox = React.createRef<HTMLDivElement>();
     @observable private _trackbox = React.createRef<HTMLDivElement>();
     @observable private _titleContainer = React.createRef<HTMLDivElement>();
     @observable private _timelineContainer = React.createRef<HTMLDivElement>();
@@ -42,13 +42,10 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _tickSpacing = this.DEFAULT_TICK_SPACING;
     @observable private _tickIncrement = this.DEFAULT_TICK_INCREMENT;
     @observable private _time = 100000; //DEFAULT
-    @observable private _ticks: number[] = [];
     @observable private _playButton = faPlayCircle;
     @observable private _timelineVisible = false;
     @observable private _mouseToggled = false;
-    @observable private _doubleClickEnabled = false;
-    @observable private _reactionDisposer: IReactionDisposer[] = [];
-
+    @observable private _doubleClickEnabled = false; 
 
     @computed
     private get children(): List<Doc> {
@@ -63,47 +60,28 @@ export class Timeline extends React.Component<FieldViewProps> {
         return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
     }
 
-
-    componentWillMount() {
-        this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false;
-    }
-
     componentDidMount() {
-        if (StrCast(this.props.Document.type) === "video") {
-            console.log("video");
-            console.log(this.props.Document.duration);
-            if (this.props.Document.duration) {
-                this._time = Math.round(NumCast(this.props.Document.duration)) * 1000;
-                this._reactionDisposer.push(reaction(() => {
-                    return NumCast(this.props.Document.curPage);
-                }, curPage => {
-                    if (!this._isPlaying) {
-                        this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing);
-                        this.props.Document.curPage = this._currentBarX;
-                        this.play();
-                    }
-                }));
-            }
-        }
         runInAction(() => {
-            this._reactionDisposer.push(reaction(() => {
-                return this._time;
-            }, () => {
-                this._ticks = [];
-                for (let i = 0; i < this._time;) {
-                    this._ticks.push(i);
-                    i += 1000;
-                }
-                this._totalLength = this._tickSpacing * (this._time / this._tickIncrement);
-            }, { fireImmediately: true }));
-            this._totalLength = this._tickSpacing * (this._ticks.length / this._tickIncrement);
+            this._totalLength = this._tickSpacing * (this._time / this._tickIncrement);
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width;
             this._visibleStart = this._infoContainer.current!.scrollLeft;
         });
+    }
 
-
+    /**
+     * React Functional Component
+     * Purpose: For drawing Tick marks across the timeline in authoring mode
+     */
+    @action
+    drawTicks = () => {
+        let ticks = []; 
+        for (let i = 0; i < this._time / this._tickIncrement; i++){
+            ticks.push(<div key={Utils.GenerateGuid()} className="tick" style={{ transform: `translate(${i* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(i * this._tickIncrement)}</p></div>); 
+        }
+        return ticks; 
     }
 
+
     @action
     changeCurrentBarX = (pixel: number) => {
         pixel <= 0 ? this._currentBarX = 0 : pixel >= this._totalLength ? this._currentBarX = this._totalLength : this._currentBarX = pixel;
@@ -174,23 +152,12 @@ export class Timeline extends React.Component<FieldViewProps> {
     onScrubberMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let scrubberbox = this._scrubberbox.current!;
+        let scrubberbox = this._infoContainer.current!;
         let left = scrubberbox.getBoundingClientRect().left;
         let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
         this.changeCurrentBarX(offsetX);
     }
 
-    @action
-    onScrubberClick = (e: React.MouseEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        let scrubberbox = this._scrubberbox.current!;
-        let offsetX = (e.clientX - scrubberbox.getBoundingClientRect().left) * this.props.ScreenToLocalTransform().Scale;
-        this.changeCurrentBarX(offsetX);
-    }
-
-
-
     @action
     onPanDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -236,7 +203,6 @@ export class Timeline extends React.Component<FieldViewProps> {
         this._visibleStart = infoContainer.scrollLeft;
     }
 
-
     @action
     onResizeDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -261,8 +227,6 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
-
-
     @action
     toReadTime = (time: number): string => {
         const inSeconds = time / 1000;
@@ -276,21 +240,12 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
     timelineContextMenu = (e: MouseEvent): void => {
-        let subitems: ContextMenuProps[] = [];
-        subitems.push({
-            description: this._timelineVisible ? "Hide Timeline" : "Show Timeline", event: action(() => {
-                this._timelineVisible = !this._timelineVisible;
-            }), icon: this._timelineVisible ? faEyeSlash : "eye"
-        });
-        subitems.push({
-            description: BoolCast(this.props.Document.isAnimating) ? "Enter Play Mode" : "Enter Authoring Mode", event: () => {
-                BoolCast(this.props.Document.isAnimating) ? this.props.Document.isAnimating = false : this.props.Document.isAnimating = true;
-            }
-            , icon: BoolCast(this.props.Document.isAnimating) ? "play" : "edit"
-        });
-        ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems, icon: faClock });
+        ContextMenu.Instance.addItem({description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
+            this._timelineVisible = !this._timelineVisible; 
+        }), icon: faTimes}); 
     }
 
+
     @action
     onWheelZoom = (e: React.WheelEvent) => {
         e.preventDefault();
@@ -339,14 +294,13 @@ export class Timeline extends React.Component<FieldViewProps> {
     private timelineToolBox = (scale: number) => {
         let size = 50 * scale; //50 is default
         return (
-
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
                 <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
                 <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
                 <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
                 <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
-                <div ref={this._roundToggleContainerRef} key="round-toggle" className="round-toggle">
-                    <div ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
+                <div key="round-toggle" ref={this._roundToggleContainerRef} className="round-toggle">
+                    <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
                 </div>
             </div>
         );
@@ -360,7 +314,6 @@ export class Timeline extends React.Component<FieldViewProps> {
         let roundToggleContainer = this._roundToggleContainerRef.current!;
         let timelineContainer = this._timelineContainer.current!;
         if (BoolCast(this.props.Document.isAnimating)) {
-
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff";
             roundToggleContainer.style.animationName = "turnoff";
@@ -374,7 +327,6 @@ export class Timeline extends React.Component<FieldViewProps> {
             roundToggleContainer.style.animationName = "turnon";
             timelineContainer.style.transform = `translate(0px, ${this._containerHeight}px)`;
             this.props.Document.isAnimating = true;
-
         }
     }
     render() {
@@ -384,11 +336,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                     <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
                         <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `-${this._containerHeight}px` }}>
                             <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
-                                <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{ width: `${this._totalLength}px` }} onClick={this.onScrubberClick}>
-                                    {this._ticks.map(element => {
-                                        if (element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement) * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>;
-                                    })}
-                                </div>
+                                {this.drawTicks()}
                                 <div key="timeline_scrubber" className="scrubber" onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
                                     <div key="timeline_scrubberhead" className="scrubberhead"></div>
                                 </div>
@@ -406,8 +354,6 @@ export class Timeline extends React.Component<FieldViewProps> {
                     </div>
                     {this.timelineToolBox(1)}
                 </div>
-
-
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 9e914734438a52c5f9bb9a43421418c8ed5f903a Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sat, 19 Oct 2019 16:59:01 -0400
Subject: lots of bug fixes

---
 src/client/views/animationtimeline/Keyframe.tsx | 25 +++++++++++++++----------
 src/client/views/animationtimeline/Timeline.tsx | 16 +++++++++-------
 src/client/views/animationtimeline/Track.tsx    |  1 +
 src/new_fields/util.ts                          |  2 +-
 4 files changed, 26 insertions(+), 18 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 810f9a057..c872b8740 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -13,7 +13,6 @@ import { InkField, StrokeData } from "../../../new_fields/InkField";
 import { TimelineMenu } from "./TimelineMenu";
 import { Docs } from "../../documents/Documents";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { thisTypeAnnotation } from "babel-types";
 
 export namespace KeyframeFunc {
     export enum KeyframeType {
@@ -167,6 +166,7 @@ export class Keyframe extends React.Component<IProps> {
             (fadeOut.key! as Doc).opacity = 1;
             (start.key! as Doc).opacity = 0.1;
             (finish.key! as Doc).opacity = 0.1;
+            this.forceUpdate(); 
         }); 
     }
 
@@ -315,6 +315,7 @@ export class Keyframe extends React.Component<IProps> {
         this.keyframes[this.keyframes.length - 1].time = this.regiondata.position + this.regiondata.duration; 
     }
 
+
     @action
     createKeyframe = async (clientX:number) => {
         this._mouseToggled = true; 
@@ -327,7 +328,7 @@ export class Keyframe extends React.Component<IProps> {
         }
     }
 
-
+    
     @action
     moveKeyframe = async (e: React.MouseEvent, kf: Doc) => {
         e.preventDefault();
@@ -346,12 +347,13 @@ export class Keyframe extends React.Component<IProps> {
     @action 
     makeKeyframeMenu = (kf :Doc, e:MouseEvent) => {
         TimelineMenu.Instance.addItem("button", "Show Data", () => {
-        runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); 
-            CollectionDockingView.AddRightSplit(kvp, (kf.key as Doc).data as Doc); });
-        }), 
+            runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); 
+                CollectionDockingView.AddRightSplit(kvp, (kf.key as Doc).data as Doc); });
+            }), 
         TimelineMenu.Instance.addItem("button", "Delete", () => {
             runInAction(() => {
                 (this.regiondata.keyframes as List<Doc>).splice(this.keyframes.indexOf(kf), 1);
+                this.forceUpdate(); 
             });         
         }), 
         TimelineMenu.Instance.addItem("input", "Move", (val) => {
@@ -381,7 +383,10 @@ export class Keyframe extends React.Component<IProps> {
         TimelineMenu.Instance.addItem("button", "Add Path", () => {
             this.onContainerDown(kf, "path");
         }),         
-        TimelineMenu.Instance.addItem("button", "Remove Region", ()=>{this.regions.splice(this.regions.indexOf(this.regiondata), 1);}),
+        TimelineMenu.Instance.addItem("button", "Remove Region", ()=>{
+            runInAction(() => {
+            this.regions.splice(this.regions.indexOf(this.regiondata), 1);}
+        );}),
         TimelineMenu.Instance.addItem("input", `fadeIn: ${this.regiondata.fadeIn}ms`, (val) => {
             runInAction(() => {
                 if (this.checkInput(val)){
@@ -554,9 +559,9 @@ export class Keyframe extends React.Component<IProps> {
     }
 
     @action
-    drawKeyframes = () => {
+    drawKeyframes =  () => {
         let keyframeDivs:JSX.Element[] = []; 
-        this.keyframes.forEach( kf => {
+        DocListCast(this.regiondata.keyframes).forEach( kf => {
             if (kf.type as KeyframeFunc.KeyframeType === KeyframeFunc.KeyframeType.default) {
                 keyframeDivs.push(
                     <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
@@ -581,9 +586,9 @@ export class Keyframe extends React.Component<IProps> {
     }
 
     @action 
-    drawKeyframeDividers = () => {
+    drawKeyframeDividers = () =>  {
         let keyframeDividers:JSX.Element[] = []; 
-        this.keyframes.forEach(kf => {
+        DocListCast(this.regiondata.keyframes).forEach(kf => {
             if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
                 let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; 
                 let bodyRef = React.createRef<HTMLDivElement>(); 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 9ac5d98d2..666048a54 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -155,7 +155,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         let scrubberbox = this._infoContainer.current!;
         let left = scrubberbox.getBoundingClientRect().left;
         let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
-        this.changeCurrentBarX(offsetX);
+        this.changeCurrentBarX(offsetX + this._visibleStart);
     }
 
     @action
@@ -201,6 +201,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         let infoContainer = this._infoContainer.current!;
         infoContainer.scrollLeft = pixel;
         this._visibleStart = infoContainer.scrollLeft;
+        console.log(infoContainer.scrollLeft); 
+        console.log(this._totalLength); 
+        console.log(this._visibleLength); 
     }
 
     @action
@@ -317,15 +320,14 @@ export class Timeline extends React.Component<FieldViewProps> {
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff";
             roundToggleContainer.style.animationName = "turnoff";
-            timelineContainer.style.transform = `translate(0px, ${0}px)`;
-            setTimeout(() => {
-                this.props.Document.isAnimating = false;
-            }, 500);
+            timelineContainer.style.top = `${-this._containerHeight}px`;
+            this.props.Document.isAnimating = false;
+        
         } else {
             roundToggle.style.transform = "translate(45px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
-            timelineContainer.style.transform = `translate(0px, ${this._containerHeight}px)`;
+            timelineContainer.style.top = "0px"; 
             this.props.Document.isAnimating = true;
         }
     }
@@ -334,7 +336,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             <div>
                 <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
                     <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
-                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `-${this._containerHeight}px` }}>
+                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
                             <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
                                 {this.drawTicks()}
                                 <div key="timeline_scrubber" className="scrubber" onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 3ec410216..7a8f42ea7 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -270,6 +270,7 @@ export class Track extends React.Component<IProps> {
         let inner = this._inner.current!;
         let offsetX = Math.round((e.clientX - inner.getBoundingClientRect().left) * this.props.transform.Scale);
         this.createRegion(KeyframeFunc.convertPixelTime(offsetX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
+        this.forceUpdate(); 
     }
 
     createRegion = (position: number) => {
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 04194509c..a92b1858d 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -69,7 +69,7 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number
         } else {
             target.__fields[prop] = value;
         }
-        if (typeof value === "object" && !(value instanceof ObjectField)) debugger;
+        // if (typeof value === "object" && !(value instanceof ObjectField)) debugger;
         if (writeToServer) {
             if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } });
             else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } });
-- 
cgit v1.2.3-70-g09d2


From 8e45ed5a6705becf6708c3d9e9740ce8febe65d9 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 20 Oct 2019 17:16:52 -0400
Subject: changed ui input, and more bug fixes

---
 src/client/views/animationtimeline/Timeline.scss | 68 ++++++++++++++----------
 src/client/views/animationtimeline/Timeline.tsx  | 51 +++++++++++++++---
 2 files changed, 85 insertions(+), 34 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index cf6b4b3d5..f6a48d876 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -7,10 +7,48 @@
     display:flex;
     align-items: flex-start; 
     flex-direction: row;  
+    justify-content: space-evenly; 
+    align-items: baseline; 
     top: 10px;
     div{
         margin-left:10px; 
     }
+    .animation-text{
+        font-size: 20px; 
+        height: auto; 
+        width: auto; 
+    }
+    .round-toggle {
+        height: 40px;
+        width: 80px;
+        background-color: white;
+        border: 2px solid purple;
+        border-radius: 20px;
+        animation-fill-mode: forwards; 
+        animation-duration: 500ms;
+        top: 30px; 
+        input{
+            position:absolute; 
+            opacity: 0; 
+            height: 0; 
+            width: 0; 
+        }
+        .round-toggle-slider{
+            height: 35px; 
+            width: 35px; 
+            background-color: white;
+            border:1px solid grey;
+            border-radius: 20px; 
+            transition: transform 500ms ease-in-out; 
+            margin-left: 0px; 
+            margin-top: 0.5px; 
+        } 
+    }
+    .time-input{
+        height: 40px; 
+        width: 100px; 
+        
+    }
 }
 
 .tick{
@@ -112,38 +150,12 @@
         float: left 0px; 
         top: 25%; 
         height: 75%; 
-        width: 100%; 
+        width: 100%;     
         background-color: grey; 
     }
 }
 
-.round-toggle {
-    height: 40px;
-    width: 80px;
-    background-color: white;
-    border: 2px solid purple;
-    border-radius: 20px;
-    animation-fill-mode: forwards; 
-    animation-duration: 500ms;
-    top: 20px; 
-    input{
-        position:absolute; 
-        opacity: 0; 
-        height: 0; 
-        width: 0; 
-    }
-    .round-toggle-slider{
-        height: 35px; 
-        width: 35px; 
-        background-color: white;
-        border:1px solid grey;
-        border-radius: 20px; 
-        transition: transform 500ms ease-in-out; 
-        margin-left: 0px; 
-        margin-top: 0.5px; 
-    } 
- 
-}
+
 @keyframes turnon{
     from{
         background-color: white;
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 666048a54..30fa70b12 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -31,6 +31,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _infoContainer = React.createRef<HTMLDivElement>();
     @observable private _roundToggleRef = React.createRef<HTMLDivElement>();
     @observable private _roundToggleContainerRef = React.createRef<HTMLDivElement>();
+    @observable private _timeInputRef = React.createRef<HTMLInputElement>(); 
 
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
@@ -62,12 +63,27 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     componentDidMount() {
         runInAction(() => {
+            if (!this.props.Document.AnimationLength){
+                this.props.Document.AnimationLength = this._time; 
+            } else {
+                this._time = NumCast(this.props.Document.AnimationLength); 
+                console.log(this._time); 
+            }
             this._totalLength = this._tickSpacing * (this._time / this._tickIncrement);
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width;
             this._visibleStart = this._infoContainer.current!.scrollLeft;
+            this.props.Document.isAnimating = !this.props.Document.isAnimating; 
+            this.toggleHandle(); 
         });
     }
 
+    componentWillUnmount(){
+        runInAction(() => {
+            console.log(this._time); 
+            this.props.Document.AnimationLength = this._time; 
+        }); 
+    }
+
     /**
      * React Functional Component
      * Purpose: For drawing Tick marks across the timeline in authoring mode
@@ -194,16 +210,20 @@ export class Timeline extends React.Component<FieldViewProps> {
         let titleContainer = this._titleContainer.current!;
         this.movePanX(this._visibleStart - e.movementX);
         trackbox.scrollTop = trackbox.scrollTop - e.movementY;
-        titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;
+        titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;    
+        if (this._visibleStart + this._visibleLength + 20>= this._totalLength){
+            this._visibleStart -= e.movementX; 
+            this._totalLength -= e.movementX;
+            this._time -= KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this._tickSpacing, this._tickIncrement); 
+            this.props.Document.AnimationLength = this._time; 
+        }
+        
     }
     @action
     movePanX = (pixel: number) => {
         let infoContainer = this._infoContainer.current!;
         infoContainer.scrollLeft = pixel;
         this._visibleStart = infoContainer.scrollLeft;
-        console.log(infoContainer.scrollLeft); 
-        console.log(this._totalLength); 
-        console.log(this._visibleLength); 
     }
 
     @action
@@ -300,19 +320,39 @@ export class Timeline extends React.Component<FieldViewProps> {
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
                 <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
                 <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
-                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
+                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>                
+                <div key="overview-text" className="animation-text"><p>Timeline Overview</p></div>
                 <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                <div key="animation-text" className="animation-text"><p>Mode: {this.props.Document.isAnimating ? "Authoring" : "Play"}</p></div>
                 <div key="round-toggle" ref={this._roundToggleContainerRef} className="round-toggle">
                     <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
                 </div>
+                <div key="time-text" className="animation-text"><p>Length: </p></div>
+                <input placeholder={String(this._time) + "ms"} ref = {this._timeInputRef} onKeyDown={this.onTimeInput}/>
+
             </div>
         );
     }
+    
+    @action 
+    private onTimeInput = (e: React.KeyboardEvent) => {
+        if (e.keyCode === 13){
+            let timeInput = this._timeInputRef.current!; 
+            this._time = parseInt(timeInput.value, 10);
+            this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
+            this.props.Document.AnimationLength = this._time; 
+            
+        }
+    }
 
     @action
     private toggleChecked = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
+        this.toggleHandle(); 
+    }
+
+    private toggleHandle = () => {
         let roundToggle = this._roundToggleRef.current!;
         let roundToggleContainer = this._roundToggleContainerRef.current!;
         let timelineContainer = this._timelineContainer.current!;
@@ -322,7 +362,6 @@ export class Timeline extends React.Component<FieldViewProps> {
             roundToggleContainer.style.animationName = "turnoff";
             timelineContainer.style.top = `${-this._containerHeight}px`;
             this.props.Document.isAnimating = false;
-        
         } else {
             roundToggle.style.transform = "translate(45px, 0px)";
             roundToggle.style.animationName = "turnon";
-- 
cgit v1.2.3-70-g09d2


From 21621ac406b7703811ac40b429c51dac752dd142 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sat, 26 Oct 2019 16:47:42 -0400
Subject: ui changes, bug fix, icon fix

---
 src/client/views/animationtimeline/Keyframe.tsx  |  1 +
 src/client/views/animationtimeline/Timeline.scss | 21 +++++++--------------
 src/client/views/animationtimeline/Timeline.tsx  | 10 ++++++----
 3 files changed, 14 insertions(+), 18 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index c872b8740..6a5163cde 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -125,6 +125,7 @@ interface IProps {
     tickSpacing: number; 
     tickIncrement: number; 
     time: number; 
+    
     changeCurrentBarX: (x: number) => void;
     transform: Transform;
 }
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index f6a48d876..8317a3606 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -156,19 +156,12 @@
 }
 
 
-@keyframes turnon{
-    from{
-        background-color: white;
-    }
-    to{
-        background-color: purple; 
-    }
-}   
-@keyframes turnoff{
-    from{
-        background-color: purple; 
-    }
-    to{
-        background-color: white; 
+.timeline-checker{
+    height: auto; 
+    width: auto; 
+    position: absolute;     
+    .check{
+        width: 100px; 
+        height: 100px; 
     }
 }
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 30fa70b12..0b6b06aaa 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -8,7 +8,7 @@ import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes } from "@fortawesome/free-solid-svg-icons";
+import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes, faEye, faCheck, faCross} from "@fortawesome/free-solid-svg-icons";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
@@ -265,7 +265,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     timelineContextMenu = (e: MouseEvent): void => {
         ContextMenu.Instance.addItem({description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
             this._timelineVisible = !this._timelineVisible; 
-        }), icon: faTimes}); 
+        }), icon: this._timelineVisible ? faEyeSlash : faEye }); 
     }
 
 
@@ -329,7 +329,6 @@ export class Timeline extends React.Component<FieldViewProps> {
                 </div>
                 <div key="time-text" className="animation-text"><p>Length: </p></div>
                 <input placeholder={String(this._time) + "ms"} ref = {this._timeInputRef} onKeyDown={this.onTimeInput}/>
-
             </div>
         );
     }
@@ -341,7 +340,6 @@ export class Timeline extends React.Component<FieldViewProps> {
             this._time = parseInt(timeInput.value, 10);
             this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
             this.props.Document.AnimationLength = this._time; 
-            
         }
     }
 
@@ -392,6 +390,10 @@ export class Timeline extends React.Component<FieldViewProps> {
                                 <FontAwesomeIcon className="resize" icon={faGripLines} />
                             </div>
                         </div>
+                        <div key="timeline-checker"> 
+                            <FontAwesomeIcon className="check" icon={faCheck} />
+                            <FontAwesomeIcon className="check" icon={faCross} />
+                        </div>
                     </div>
                     {this.timelineToolBox(1)}
                 </div>
-- 
cgit v1.2.3-70-g09d2


From 2b7b564aa051db78c89d14ff48cf38ace2f42b37 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 27 Oct 2019 16:42:34 -0400
Subject: confirm box, regiondata bugfix

---
 src/client/views/animationtimeline/Keyframe.tsx  | 24 ++++++++++------
 src/client/views/animationtimeline/Timeline.scss | 16 +++++++++--
 src/client/views/animationtimeline/Timeline.tsx  | 36 ++++++++++++++++++++----
 src/client/views/animationtimeline/Track.tsx     |  3 ++
 4 files changed, 62 insertions(+), 17 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 6a5163cde..35d7afc7a 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -125,9 +125,10 @@ interface IProps {
     tickSpacing: number; 
     tickIncrement: number; 
     time: number; 
-    
+    check: string; 
     changeCurrentBarX: (x: number) => void;
     transform: Transform;
+    checkCallBack: (visible: boolean) => void; 
 }
 
 @observer
@@ -137,6 +138,7 @@ export class Keyframe extends React.Component<IProps> {
     @observable private _gain = 20; //default
     @observable private _mouseToggled = false; 
     @observable private _doubleClickEnabled = false; 
+    @observable private _index:number = 0; 
 
     @computed private get regiondata() { return RegionData(this.regions[this.regions.indexOf(this.props.RegionData)] as Doc);}
     @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;}
@@ -386,7 +388,7 @@ export class Keyframe extends React.Component<IProps> {
         }),         
         TimelineMenu.Instance.addItem("button", "Remove Region", ()=>{
             runInAction(() => {
-            this.regions.splice(this.regions.indexOf(this.regiondata), 1);}
+            this.regions.splice(this.regions.indexOf(this.props.RegionData), 1);}
         );}),
         TimelineMenu.Instance.addItem("input", `fadeIn: ${this.regiondata.fadeIn}ms`, (val) => {
             runInAction(() => {
@@ -492,10 +494,12 @@ export class Keyframe extends React.Component<IProps> {
     private _plotList: ([string, StrokeData] | undefined) = undefined;
     private _interpolationKeyframe: (Doc | undefined) = undefined; 
     private _type: string = ""; 
+    
 
     @action
     onContainerDown = (kf: Doc, type: string) => {
-        let listenerCreated = false;                 
+        let listenerCreated = false;              
+        this.props.checkCallBack(true);    
         this._type = type; 
         this.props.collection.backgroundColor = "rgb(0,0,0)";
         this._reac = reaction(() => {
@@ -504,16 +508,20 @@ export class Keyframe extends React.Component<IProps> {
             if (!listenerCreated) {
                 this._plotList = Array.from(data!)[data!.size - 1]!;
                 this._interpolationKeyframe = kf; 
-                document.addEventListener("pointerup", this.onReactionListen); 
                 listenerCreated = true; 
+                const reac = reaction(() => {
+                    return this.props.check; 
+                },  () => {
+                    if(this.props.check === "yes")  this.onReactionListen(); 
+                    reac(); 
+                    this.props.checkCallBack(false); 
+                }); 
             }
         });
     }
 
     @action
-    onReactionListen = (e: PointerEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
+    onReactionListen = () => {
         if (this._reac && this._plotList && this._interpolationKeyframe) {
             this.props.collection.backgroundColor = "#FFF";
             this._reac();
@@ -554,8 +562,6 @@ export class Keyframe extends React.Component<IProps> {
             this._reac = undefined; 
             this._interpolationKeyframe = undefined; 
             this._plotList = undefined; 
-            this._type = ""; 
-            document.removeEventListener("pointerup", this.onReactionListen); 
         }
     }
 
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 8317a3606..0f98ed7c4 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -159,9 +159,19 @@
 .timeline-checker{
     height: auto; 
     width: auto; 
-    position: absolute;     
+    overflow: hidden; 
+    position: absolute; 
+    display: flex; 
+    padding: 10px 10px; 
+    div{
+        height: auto; 
+        width: auto;
+        overflow: hidden; 
+        margin: 0px 10px; 
+        cursor: pointer
+    }
     .check{
-        width: 100px; 
-        height: 100px; 
+        width: 50px; 
+        height: 50px; 
     }
 }
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 0b6b06aaa..6028656dc 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -8,7 +8,7 @@ import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes, faEye, faCheck, faCross} from "@fortawesome/free-solid-svg-icons";
+import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes, faEye, faCheck, faCross, faCheckCircle, faTimesCircle} from "@fortawesome/free-solid-svg-icons";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
@@ -368,6 +368,28 @@ export class Timeline extends React.Component<FieldViewProps> {
             this.props.Document.isAnimating = true;
         }
     }
+
+
+    @observable private _check:string = ""; 
+    @observable private _checkVisible:boolean = false; 
+    @action
+    private onCheckClicked = (type: string) => {
+        if (type === "yes"){
+            this._check = "yes";  
+        } else if (type === "no"){
+            this._check = "no";
+        }
+    }
+
+
+    @action 
+    private checkCallBack = (visible:boolean) => {
+        this._checkVisible = visible; 
+        if (!visible){ //when user confirms
+            this._check = "";
+        }
+
+    }
     render() {
         return (
             <div>
@@ -380,7 +402,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                                     <div key="timeline_scrubberhead" className="scrubberhead"></div>
                                 </div>
                                 <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
-                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} />)}
+                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} checkCallBack={this.checkCallBack}/>)}
                                 </div>
                             </div>
                             <div key="timeline_title" className="title-container" ref={this._titleContainer}>
@@ -390,9 +412,13 @@ export class Timeline extends React.Component<FieldViewProps> {
                                 <FontAwesomeIcon className="resize" icon={faGripLines} />
                             </div>
                         </div>
-                        <div key="timeline-checker"> 
-                            <FontAwesomeIcon className="check" icon={faCheck} />
-                            <FontAwesomeIcon className="check" icon={faCross} />
+                        <div key="timeline-checker" className="timeline-checker" style={{top: `${this._containerHeight}px`, visibility: this._checkVisible ? "visible" : "hidden"}}> 
+                            <div onClick = {() => {this.onCheckClicked("yes");}}>
+                                <FontAwesomeIcon style={{color: "#42b883"}} className="check" icon={faCheckCircle} /> 
+                            </div>
+                            <div onClick = {() => {this.onCheckClicked("no");}}>
+                                <FontAwesomeIcon style={{color: "#ff7e67"}} className="check" icon={faTimesCircle} />
+                            </div>
                         </div>
                     </div>
                     {this.timelineToolBox(1)}
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 7a8f42ea7..14e309f68 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -20,7 +20,10 @@ interface IProps {
     tickIncrement: number;
     tickSpacing: number;
     timelineVisible: boolean; 
+    check: string; 
     changeCurrentBarX: (x: number) => void;
+    checkCallBack: (visible: boolean) => void; 
+
 }
 
 @observer
-- 
cgit v1.2.3-70-g09d2


From 7977625e5b408d6e47432caaf7382aa315fc9832 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 3 Nov 2019 16:48:56 -0500
Subject: changes to timeline overview

---
 src/client/views/animationtimeline/Keyframe.tsx    |  1 -
 src/client/views/animationtimeline/Timeline.scss   | 35 +++++++----
 src/client/views/animationtimeline/Timeline.tsx    | 10 +--
 .../views/animationtimeline/TimelineOverview.scss  | 73 ++++++++++++++++++----
 .../views/animationtimeline/TimelineOverview.tsx   | 30 ++++++---
 5 files changed, 109 insertions(+), 40 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 35d7afc7a..55a2b2075 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -138,7 +138,6 @@ export class Keyframe extends React.Component<IProps> {
     @observable private _gain = 20; //default
     @observable private _mouseToggled = false; 
     @observable private _doubleClickEnabled = false; 
-    @observable private _index:number = 0; 
 
     @computed private get regiondata() { return RegionData(this.regions[this.regions.indexOf(this.props.RegionData)] as Doc);}
     @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;}
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 0f98ed7c4..6270eed41 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -4,25 +4,33 @@
 
 .timeline-toolbox{
     position:absolute; 
+    margin: 0px; 
+    padding: 0px; 
     display:flex;
     align-items: flex-start; 
-    flex-direction: row;  
-    justify-content: space-evenly; 
-    align-items: baseline; 
-    top: 10px;
+    flex-direction: row;
+    justify-content: space-evenly;
+    align-items: center;
+    top: 15px;
     div{
+        padding: 0px; 
         margin-left:10px; 
     }
     .animation-text{
         font-size: 20px; 
         height: auto; 
         width: auto; 
+        white-space: nowrap;
+        font-size: 16px;
+        color: grey;
+        letter-spacing: 2px;
+        text-transform: uppercase;
     }
     .round-toggle {
         height: 40px;
         width: 80px;
         background-color: white;
-        border: 2px solid purple;
+        border: 2px solid grey;
         border-radius: 20px;
         animation-fill-mode: forwards; 
         animation-duration: 500ms;
@@ -44,13 +52,18 @@
             margin-top: 0.5px; 
         } 
     }
-    .time-input{
-        height: 40px; 
-        width: 100px; 
-        
-    }
+    
+}
+.time-input{
+    height: 40px; 
+    width: 100px; 
+    white-space: nowrap;
+    font-size: 16px;
+    color: grey;
+    letter-spacing: 2px;
+    text-transform: uppercase;
+    
 }
-
 .tick{
     height:100%; 
     width: 1px; 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 6028656dc..94cd0629d 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -321,14 +321,14 @@ export class Timeline extends React.Component<FieldViewProps> {
                 <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
                 <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
                 <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>                
-                <div key="overview-text" className="animation-text"><p>Timeline Overview</p></div>
-                <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
-                <div key="animation-text" className="animation-text"><p>Mode: {this.props.Document.isAnimating ? "Authoring" : "Play"}</p></div>
+                <div key="overview-text" className="animation-text">Timeline Overview</div>
+                <TimelineOverview isAuthoring = {BoolCast(this.props.Document.isAnimating)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                <div key="animation-text" className="animation-text">Mode: {this.props.Document.isAnimating ? "Authoring" : "Play"}</div>
                 <div key="round-toggle" ref={this._roundToggleContainerRef} className="round-toggle">
                     <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
                 </div>
-                <div key="time-text" className="animation-text"><p>Length: </p></div>
-                <input placeholder={String(this._time) + "ms"} ref = {this._timeInputRef} onKeyDown={this.onTimeInput}/>
+                <div key="time-text" className="animation-text" style ={{visibility: this.props.Document.isAnimating ? "visible" : "hidden"}}>Length: </div>
+                <input className="time-input" style={{visibility: this.props.Document.isAnimating ? "visible" : "hidden"}} placeholder={String(this._time) + "ms"} ref = {this._timeInputRef} onKeyDown={this.onTimeInput}/>
             </div>
         );
     }
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index 9e69c2adf..c7f9bd059 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -1,38 +1,85 @@
 @import "./../globalCssVariables.scss"; 
 
-.timeline-overview-container{
+
+.timeline-overview-container{ 
+    padding: 0px; 
+    margin: 0px; 
     width: 300px; 
     height: 40px;
-    margin-top: 10px; 
-    margin-left: 20px;  
     background: white; 
+    position: relative; 
     border: 2px solid black; 
-    padding: 0px; 
-    display:inline-block; 
+    
     .timeline-overview-visible{
+        position: absolute; 
         height: 100%; 
         background: green; 
+        display: inline-block;
         margin: 0px; 
+        padding: 0px; 
     }
-    .timeline-overview-scrubber-container{
+    .timeline-overview-scrubber-container{   
+        margin: 0px; 
+        padding: 0px; 
+        position: absolute; 
         height: 100%;
-        margin-top: -40px;  
-        margin-left: 0px; 
         width: 2px; 
+        top: 0px; 
+        left: 0px; 
         z-index: 1001;
         background-color:black; 
         display: inline-block; 
-        .timeline-overview-scrubber-head{
+
+        .timeline-overview-scrubber-head{   
+            padding: 0px; 
+            margin: 0px; 
             position:absolute; 
             height: 30px; 
             width: 30px;
             background-color:transparent; 
             border-radius: 50%; 
             border: 5px solid black; 
-            margin-left: -15px; 
-            top: -15px; 
-
+            left: -15px;
+            top: -30px; 
         }
-        
     }
+}
+
+
+
+.timeline-play-bar{
+    position: relative; 
+    padding: 0px; 
+    margin: 0px; 
+    width: 300px; 
+    height: 4px; 
+    background-color: grey;
+    border-radius: 20px;
+    cursor: pointer; 
+    
+    .timeline-play-head{
+        position: absolute; 
+        padding: 0px; 
+        margin: 0px; 
+        width: 20px; 
+        height: 20px; 
+        border-radius: 50%; 
+        background-color: white; 
+        border: 3px grey solid; 
+        left: 0px; 
+        top: -10px; 
+        cursor: pointer; 
+    }
+}  
+.timeline-play-tail{
+    position: absolute; 
+    padding: 0px; 
+    margin: 0px; 
+    height: 4px; 
+    width: 0px;   
+    z-index: 1000; 
+    background-color: green;
+    border-radius: 20px;
+    margin-top: -4px; 
+    cursor: pointer; 
 }
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 38b823cbc..4741969dc 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -6,11 +6,11 @@ import "./TimelineOverview.scss";
 
 
 interface TimelineOverviewProps{
-    scale: number; 
     totalLength: number; 
     visibleLength:number; 
     visibleStart:number;
-    currentBarX:number; 
+    currentBarX:number;
+    isAuthoring: boolean;  
     changeCurrentBarX: (pixel:number) => void; 
     movePanX: (pixel:number) => any;
 }
@@ -37,8 +37,8 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     onPanX = (e: PointerEvent) => {
         e.stopPropagation(); 
         e.preventDefault(); 
-        let movX = (this.props.visibleStart / this.props.totalLength)* (this.DEFAULT_WIDTH * this.props.scale) + e.movementX; 
-        this.props.movePanX((movX / (this.DEFAULT_WIDTH * this.props.scale)) * this.props.totalLength); 
+        let movX = (this.props.visibleStart / this.props.totalLength)* (this.DEFAULT_WIDTH) + e.movementX; 
+        this.props.movePanX((movX / (this.DEFAULT_WIDTH )) * this.props.totalLength); 
     }
 
     @action
@@ -66,7 +66,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         let scrubberRef = this._scrubberRef.current!; 
         let left = scrubberRef.getBoundingClientRect().left; 
         let offsetX = Math.round(e.clientX - left); 
-        this.props.changeCurrentBarX(((offsetX / (this.DEFAULT_WIDTH * this.props.scale)) * this.props.totalLength) + this.props.currentBarX); 
+        this.props.changeCurrentBarX((offsetX / (this.DEFAULT_WIDTH) * this.props.totalLength) + this.props.currentBarX); 
     }
 
     @action
@@ -78,12 +78,22 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     }
 
     render(){
+        let timeline = this.props.isAuthoring ? [
+            <div key="timeline-overview-container" className="timeline-overview-container">
+                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{left:`${(Math.round(this.props.visibleStart) / Math.round(this.props.totalLength)) * 296}px`, width:`${(Math.round(this.props.visibleLength) / Math.round(this.props.totalLength)) * 296}px`}} onPointerDown={this.onPointerDown}></div>,
+                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{left:`${(this.props.currentBarX / this.props.totalLength) * 294}px`}} onPointerDown={this.onScrubberDown}>
+                    <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
+                </div>            
+            </div>
+        ] : [
+            <div className="timeline-play-bar">
+                <div ref={this._scrubberRef} className="timeline-play-head" style={{left:`${(this.props.currentBarX / this.props.totalLength) * 294}px`}} onPointerDown={this.onScrubberDown}></div>
+            </div>,
+            <div className="timeline-play-tail" style={{width: `${(this.props.currentBarX / this.props.totalLength) * 294}px`}}></div>
+        ]; 
         return(
-            <div key="timeline-overview-container" className="timeline-overview-container" style={{height: `${this.DEFAULT_HEIGHT * this.props.scale * 0.8}px` ,width:`${this.DEFAULT_WIDTH * this.props.scale}`}}>
-                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{marginLeft:`${(this.props.visibleStart / this.props.totalLength)* this.DEFAULT_WIDTH * this.props.scale}px`, width:`${(this.props.visibleLength / this.props.totalLength) * this.DEFAULT_WIDTH * this.props.scale}px`}} onPointerDown={this.onPointerDown}></div>
-                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{marginLeft:`${(this.props.currentBarX / this.props.totalLength) * this.DEFAULT_WIDTH * this.props.scale}px`, marginTop: `${-this.DEFAULT_HEIGHT * this.props.scale * 0.8}px`}} onPointerDown={this.onScrubberDown}>
-                    <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head" style={{}}></div>
-                </div>
+            <div>
+                {timeline}
             </div>
         ); 
     }
-- 
cgit v1.2.3-70-g09d2


From 4d4db3aecf54a501a981c239feacdfddfe71152c Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 12 Nov 2019 17:20:21 -0500
Subject: bug fix with ui changes

---
 src/client/views/animationtimeline/Keyframe.tsx  | 13 ++++++++-----
 src/client/views/animationtimeline/Timeline.scss |  5 +++--
 src/client/views/animationtimeline/Timeline.tsx  | 10 ++++++----
 3 files changed, 17 insertions(+), 11 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 55a2b2075..424f4ed8d 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -572,11 +572,11 @@ export class Keyframe extends React.Component<IProps> {
                 keyframeDivs.push(
                     <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
                         <div className="divider"></div>
-                        <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
+                        <div className="keyframeCircle" onPointerDown={(e) => { e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
                             e.preventDefault();
                             e.stopPropagation();
                             this.makeKeyframeMenu(kf, e.nativeEvent); 
-                        }}></div>
+                        }} onDoubleClick={(e) => {e.preventDefault(); e.stopPropagation(); }}></div>
                     </div>
                 );
             }
@@ -595,7 +595,8 @@ export class Keyframe extends React.Component<IProps> {
     drawKeyframeDividers = () =>  {
         let keyframeDividers:JSX.Element[] = []; 
         DocListCast(this.regiondata.keyframes).forEach(kf => {
-            if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) {
+            let index = this.keyframes.indexOf(kf); 
+            if(index !== this.keyframes.length - 1 ) {
                 let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; 
                 let bodyRef = React.createRef<HTMLDivElement>(); 
                 let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); 
@@ -606,8 +607,10 @@ export class Keyframe extends React.Component<IProps> {
                     onPointerOut={(e) => { e.preventDefault(); e.stopPropagation(); this.onContainerOut(e, bodyRef); }}
                     onContextMenu={(e) => {
                         e.preventDefault(); 
-                        e.stopPropagation(); 
-                        this._mouseToggled = true; 
+                        e.stopPropagation();
+                        if (index !== 0 || index !== this.keyframes.length - 2){
+                            this._mouseToggled = true; 
+                        }
                         this.makeRegionMenu(kf, e.nativeEvent); 
                     }}>
                     </div>
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 6270eed41..88d602d76 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -11,7 +11,7 @@
     flex-direction: row;
     justify-content: space-evenly;
     align-items: center;
-    top: 15px;
+    top: 20px;
     div{
         padding: 0px; 
         margin-left:10px; 
@@ -56,12 +56,13 @@
 }
 .time-input{
     height: 40px; 
-    width: 100px; 
+    width: 120px; 
     white-space: nowrap;
     font-size: 16px;
     color: grey;
     letter-spacing: 2px;
     text-transform: uppercase;
+    padding-left: 5px; 
     
 }
 .tick{
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 94cd0629d..73e6c600f 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -315,12 +315,12 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
     private timelineToolBox = (scale: number) => {
-        let size = 50 * scale; //50 is default
+        let size = 40 * scale; //50 is default
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
-                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
-                <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
-                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>                
+                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px`, color:"grey"}} /> </div>
+                <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px`, color:"grey"}} /> </div>
+                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px`, color: "grey"}} /> </div>                
                 <div key="overview-text" className="animation-text">Timeline Overview</div>
                 <TimelineOverview isAuthoring = {BoolCast(this.props.Document.isAnimating)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
                 <div key="animation-text" className="animation-text">Mode: {this.props.Document.isAnimating ? "Authoring" : "Play"}</div>
@@ -358,12 +358,14 @@ export class Timeline extends React.Component<FieldViewProps> {
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff";
             roundToggleContainer.style.animationName = "turnoff";
+            roundToggleContainer.style.backgroundColor = "white"; 
             timelineContainer.style.top = `${-this._containerHeight}px`;
             this.props.Document.isAnimating = false;
         } else {
             roundToggle.style.transform = "translate(45px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
+            roundToggleContainer.style.backgroundColor = "green"; 
             timelineContainer.style.top = "0px"; 
             this.props.Document.isAnimating = true;
         }
-- 
cgit v1.2.3-70-g09d2


From 13de65ec4ca3fbeef4a687d079e7b480bd691764 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 12 Nov 2019 18:15:32 -0500
Subject: isanimating fix

---
 src/client/views/animationtimeline/Timeline.tsx | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 73e6c600f..43019903e 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -72,7 +72,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             this._totalLength = this._tickSpacing * (this._time / this._tickIncrement);
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width;
             this._visibleStart = this._infoContainer.current!.scrollLeft;
-            this.props.Document.isAnimating = !this.props.Document.isAnimating; 
+            this.props.Document.isATOn = !this.props.Document.isATOn; 
             this.toggleHandle(); 
         });
     }
@@ -322,13 +322,13 @@ export class Timeline extends React.Component<FieldViewProps> {
                 <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px`, color:"grey"}} /> </div>
                 <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px`, color: "grey"}} /> </div>                
                 <div key="overview-text" className="animation-text">Timeline Overview</div>
-                <TimelineOverview isAuthoring = {BoolCast(this.props.Document.isAnimating)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
-                <div key="animation-text" className="animation-text">Mode: {this.props.Document.isAnimating ? "Authoring" : "Play"}</div>
+                <TimelineOverview isAuthoring = {BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                <div key="animation-text" className="animation-text">Mode: {this.props.Document.isATOn ? "Authoring" : "Play"}</div>
                 <div key="round-toggle" ref={this._roundToggleContainerRef} className="round-toggle">
                     <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
                 </div>
-                <div key="time-text" className="animation-text" style ={{visibility: this.props.Document.isAnimating ? "visible" : "hidden"}}>Length: </div>
-                <input className="time-input" style={{visibility: this.props.Document.isAnimating ? "visible" : "hidden"}} placeholder={String(this._time) + "ms"} ref = {this._timeInputRef} onKeyDown={this.onTimeInput}/>
+                <div key="time-text" className="animation-text" style ={{visibility: this.props.Document.isATOn ? "visible" : "hidden"}}>Length: </div>
+                <input className="time-input" style={{visibility: this.props.Document.isATOn ? "visible" : "hidden"}} placeholder={String(this._time) + "ms"} ref = {this._timeInputRef} onKeyDown={this.onTimeInput}/>
             </div>
         );
     }
@@ -354,20 +354,20 @@ export class Timeline extends React.Component<FieldViewProps> {
         let roundToggle = this._roundToggleRef.current!;
         let roundToggleContainer = this._roundToggleContainerRef.current!;
         let timelineContainer = this._timelineContainer.current!;
-        if (BoolCast(this.props.Document.isAnimating)) {
+        if (BoolCast(this.props.Document.isATOn)) {
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff";
             roundToggleContainer.style.animationName = "turnoff";
             roundToggleContainer.style.backgroundColor = "white"; 
             timelineContainer.style.top = `${-this._containerHeight}px`;
-            this.props.Document.isAnimating = false;
+            this.props.Document.isATOn = false;
         } else {
             roundToggle.style.transform = "translate(45px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
             roundToggleContainer.style.backgroundColor = "green"; 
             timelineContainer.style.top = "0px"; 
-            this.props.Document.isAnimating = true;
+            this.props.Document.isATOn = true;
         }
     }
 
@@ -396,7 +396,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         return (
             <div>
                 <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
-                    <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
+                    <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
                         <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
                             <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
                                 {this.drawTicks()}
-- 
cgit v1.2.3-70-g09d2


From 5becac4b0442da73a6fe3b48e3a248f6cf2df61d Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sat, 23 Nov 2019 15:40:07 -0500
Subject: responsive ui

---
 src/client/views/animationtimeline/Timeline.scss | 276 ++++++++++++-----------
 src/client/views/animationtimeline/Timeline.tsx  | 129 ++++++-----
 src/client/views/animationtimeline/Track.scss    |   1 -
 src/client/views/animationtimeline/Track.tsx     |  88 ++++----
 src/client/views/linking/LinkFollowBox.tsx       |   2 +-
 5 files changed, 260 insertions(+), 236 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 88d602d76..493b084a8 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -1,191 +1,209 @@
-@import "./../globalCssVariables.scss"; 
+@import "./../globalCssVariables.scss";
 
 
 
-.timeline-toolbox{
-    position:absolute; 
-    margin: 0px; 
-    padding: 0px; 
-    display:flex;
-    align-items: flex-start; 
+.timeline-toolbox {
+    position: absolute;
+    margin: 0px;
+    padding: 0px;
+    display: flex;
+    align-items: flex-start;
     flex-direction: row;
     justify-content: space-evenly;
     align-items: center;
     top: 20px;
-    div{
-        padding: 0px; 
-        margin-left:10px; 
+
+    div {
+        padding: 0px;
+        margin-left: 10px;
     }
-    .animation-text{
-        font-size: 20px; 
-        height: auto; 
-        width: auto; 
+
+    .animation-text {
+        font-size: 20px;
+        height: auto;
+        width: auto;
         white-space: nowrap;
         font-size: 16px;
         color: grey;
         letter-spacing: 2px;
         text-transform: uppercase;
     }
+
     .round-toggle {
         height: 40px;
         width: 80px;
         background-color: white;
         border: 2px solid grey;
         border-radius: 20px;
-        animation-fill-mode: forwards; 
+        animation-fill-mode: forwards;
         animation-duration: 500ms;
-        top: 30px; 
-        input{
-            position:absolute; 
-            opacity: 0; 
-            height: 0; 
-            width: 0; 
+        top: 30px;
+
+        input {
+            position: absolute;
+            opacity: 0;
+            height: 0;
+            width: 0;
         }
-        .round-toggle-slider{
-            height: 35px; 
-            width: 35px; 
+
+        .round-toggle-slider {
+            height: 35px;
+            width: 35px;
             background-color: white;
-            border:1px solid grey;
-            border-radius: 20px; 
-            transition: transform 500ms ease-in-out; 
-            margin-left: 0px; 
-            margin-top: 0.5px; 
-        } 
+            border: 1px solid grey;
+            border-radius: 20px;
+            transition: transform 500ms ease-in-out;
+            margin-left: 0px;
+            margin-top: 0.5px;
+        }
     }
-    
+
 }
-.time-input{
-    height: 40px; 
-    width: 120px; 
+
+.time-input {
+    height: 40px;
+    width: 120px;
     white-space: nowrap;
     font-size: 16px;
     color: grey;
     letter-spacing: 2px;
     text-transform: uppercase;
-    padding-left: 5px; 
-    
+    padding-left: 5px;
+
 }
-.tick{
-    height:100%; 
-    width: 1px; 
-    background-color:black; 
-}   
-.timeline-container{
-    width:100%;
-    height:300px; 
-    position:absolute;
+
+.tick {
+    height: 100%;
+    width: 1px;
+    background-color: black;
+}
+
+.timeline-container {
+    width: 100%;
+    height: 300px;
+    position: absolute;
     background-color: $light-color-secondary;
-    box-shadow: 0px 10px 20px; 
-    transition: transform 500ms ease; 
-
-    .info-container{ 
-        margin-top: 80px; 
-        right:20px; 
-        position:absolute; 
-        height: calc(100% - 100px); 
-        width: calc(100% - 140px); 
+    box-shadow: 0px 10px 20px;
+    transition: transform 500ms ease;
+
+    .info-container {
+        margin-top: 80px;
+        right: 20px;
+        position: absolute;
+        height: calc(100% - 100px);
+        width: calc(100% - 140px);
         overflow: hidden;
 
-        .scrubberbox{
-            position:absolute; 
-            background-color: transparent; 
+        .scrubberbox {
+            position: absolute;
+            background-color: transparent;
             height: 30px;
-            width:100%; 
-          
+            width: 100%;
+
         }
-        .scrubber{
-            top:30px; 
-            height: 100%; 
-            width: 2px; 
-            position:absolute;
+
+        .scrubber {
+            top: 30px;
+            height: 100%;
+            width: 2px;
+            position: absolute;
             z-index: 1001;
-            background-color:black; 
-            .scrubberhead{
-                top: -30px; 
-                height: 30px; 
+            background-color: black;
+
+            .scrubberhead {
+                top: -30px;
+                height: 30px;
                 width: 30px;
-                background-color:transparent; 
-                border-radius: 50%; 
-                border: 5px solid black; 
+                background-color: transparent;
+                border-radius: 50%;
+                border: 5px solid black;
                 left: -15px;
-                position:absolute;                 
+                position: absolute;
             }
         }
 
-        .trackbox{
-            top: 30px; 
-            height:calc(100% - 30px);
-            width:100%;
-            border:1px;
-            overflow:hidden;
-            background-color:white;
-            position:absolute;
-            box-shadow: -10px 0px 10px 10px grey; 
+        .trackbox {
+            top: 30px;
+            height: calc(100% - 30px);
+            width: 100%;
+            border: 1px;
+            overflow: hidden;
+            background-color: white;
+            position: absolute;
+            box-shadow: -10px 0px 10px 10px grey;
         }
-        
+
     }
-    .title-container{
-        margin-top: 110px; 
-        margin-left: 20px; 
-        height: calc(100% - 100px - 30px); 
-        width: 100px; 
-        background-color:white;
-        overflow: hidden;  
-        .datapane{
-            top:0px; 
-            width: 100px; 
-            height: 75px; 
+
+    .title-container {
+        margin-top: 110px;
+        margin-left: 20px;
+        height: calc(100% - 100px - 30px);
+        width: 100px;
+        background-color: white;
+        overflow: hidden;
+
+        .datapane {
+            top: 0px;
+            width: 100px;
+            height: 30%;
             border: 1px solid $dark-color;
-            background-color: $intermediate-color; 
-            color: white; 
-            position:relative; 
-            float:left; 
-            border-style:solid; 
+            background-color: $intermediate-color;
+            color: white;
+            position: relative;
+            float: left;
+            border-style: solid;
+            overflow-y: scroll;
+            overflow-x: hidden; 
         }
     }
-    .resize{
-        bottom: 5px; 
-        position:absolute; 
-        height: 30px; 
-        width: 50px; 
+
+    .resize {
+        bottom: 5px;
+        position: absolute;
+        height: 30px;
+        width: 50px;
         left: calc(50% - 25px);
     }
 }
 
 
 
-.overview{
-    position: absolute; 
-    height: 50px; 
-    width: 200px; 
-    background-color: black; 
-    .container{        
-        position: absolute; 
-        float: left 0px; 
-        top: 25%; 
-        height: 75%; 
-        width: 100%;     
-        background-color: grey; 
+.overview {
+    position: absolute;
+    height: 50px;
+    width: 200px;
+    background-color: black;
+
+    .container {
+        position: absolute;
+        float: left 0px;
+        top: 25%;
+        height: 75%;
+        width: 100%;
+        background-color: grey;
     }
 }
 
 
-.timeline-checker{
-    height: auto; 
-    width: auto; 
-    overflow: hidden; 
-    position: absolute; 
-    display: flex; 
-    padding: 10px 10px; 
-    div{
-        height: auto; 
+.timeline-checker {
+    height: auto;
+    width: auto;
+    overflow: hidden;
+    position: absolute;
+    display: flex;
+    padding: 10px 10px;
+
+    div {
+        height: auto;
         width: auto;
-        overflow: hidden; 
-        margin: 0px 10px; 
+        overflow: hidden;
+        margin: 0px 10px;
         cursor: pointer
     }
-    .check{
-        width: 50px; 
-        height: 50px; 
+
+    .check {
+        width: 50px;
+        height: 50px;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 43019903e..f8aa88755 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -8,7 +8,7 @@ import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes, faEye, faCheck, faCross, faCheckCircle, faTimesCircle} from "@fortawesome/free-solid-svg-icons";
+import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes, faEye, faCheck, faCross, faCheckCircle, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
@@ -19,9 +19,9 @@ import { Utils } from "../../../Utils";
 @observer
 export class Timeline extends React.Component<FieldViewProps> {
 
-    private readonly DEFAULT_CONTAINER_HEIGHT: number = 330;
+    private DEFAULT_CONTAINER_HEIGHT: number = 330;
     private readonly DEFAULT_TICK_SPACING: number = 50;
-    private readonly MIN_CONTAINER_HEIGHT: number = 205;
+    private MIN_CONTAINER_HEIGHT: number = 205;
     private readonly MAX_CONTAINER_HEIGHT: number = 800;
     private readonly DEFAULT_TICK_INCREMENT: number = 1000;
 
@@ -31,7 +31,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _infoContainer = React.createRef<HTMLDivElement>();
     @observable private _roundToggleRef = React.createRef<HTMLDivElement>();
     @observable private _roundToggleContainerRef = React.createRef<HTMLDivElement>();
-    @observable private _timeInputRef = React.createRef<HTMLInputElement>(); 
+    @observable private _timeInputRef = React.createRef<HTMLInputElement>();
 
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
@@ -46,8 +46,8 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _playButton = faPlayCircle;
     @observable private _timelineVisible = false;
     @observable private _mouseToggled = false;
-    @observable private _doubleClickEnabled = false; 
-
+    @observable private _doubleClickEnabled = false;
+    private _titleHeight = 0;
     @computed
     private get children(): List<Doc> {
         let extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type));
@@ -60,28 +60,33 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
         return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
     }
+    componentWillMount() {
+        this._titleHeight = window.innerHeight / 14; //arbitrary number, but for responsiveness              
+        this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; 
+        this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; 
+    }
 
     componentDidMount() {
         runInAction(() => {
-            if (!this.props.Document.AnimationLength){
-                this.props.Document.AnimationLength = this._time; 
+            if (!this.props.Document.AnimationLength) {
+                this.props.Document.AnimationLength = this._time;
             } else {
-                this._time = NumCast(this.props.Document.AnimationLength); 
-                console.log(this._time); 
+                this._time = NumCast(this.props.Document.AnimationLength);
+                console.log(this._time);
             }
             this._totalLength = this._tickSpacing * (this._time / this._tickIncrement);
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width;
             this._visibleStart = this._infoContainer.current!.scrollLeft;
-            this.props.Document.isATOn = !this.props.Document.isATOn; 
-            this.toggleHandle(); 
+            this.props.Document.isATOn = !this.props.Document.isATOn;
+            this.toggleHandle();
         });
     }
 
-    componentWillUnmount(){
+    componentWillUnmount() {
         runInAction(() => {
-            console.log(this._time); 
-            this.props.Document.AnimationLength = this._time; 
-        }); 
+            console.log(this._time);
+            this.props.Document.AnimationLength = this._time;
+        });
     }
 
     /**
@@ -90,11 +95,11 @@ export class Timeline extends React.Component<FieldViewProps> {
      */
     @action
     drawTicks = () => {
-        let ticks = []; 
-        for (let i = 0; i < this._time / this._tickIncrement; i++){
-            ticks.push(<div key={Utils.GenerateGuid()} className="tick" style={{ transform: `translate(${i* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(i * this._tickIncrement)}</p></div>); 
+        let ticks = [];
+        for (let i = 0; i < this._time / this._tickIncrement; i++) {
+            ticks.push(<div key={Utils.GenerateGuid()} className="tick" style={{ transform: `translate(${i * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(i * this._tickIncrement)}</p></div>);
         }
-        return ticks; 
+        return ticks;
     }
 
 
@@ -210,14 +215,14 @@ export class Timeline extends React.Component<FieldViewProps> {
         let titleContainer = this._titleContainer.current!;
         this.movePanX(this._visibleStart - e.movementX);
         trackbox.scrollTop = trackbox.scrollTop - e.movementY;
-        titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;    
-        if (this._visibleStart + this._visibleLength + 20>= this._totalLength){
-            this._visibleStart -= e.movementX; 
+        titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;
+        if (this._visibleStart + this._visibleLength + 20 >= this._totalLength) {
+            this._visibleStart -= e.movementX;
             this._totalLength -= e.movementX;
-            this._time -= KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this._tickSpacing, this._tickIncrement); 
-            this.props.Document.AnimationLength = this._time; 
+            this._time -= KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this._tickSpacing, this._tickIncrement);
+            this.props.Document.AnimationLength = this._time;
         }
-        
+
     }
     @action
     movePanX = (pixel: number) => {
@@ -263,9 +268,11 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
     timelineContextMenu = (e: MouseEvent): void => {
-        ContextMenu.Instance.addItem({description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
-            this._timelineVisible = !this._timelineVisible; 
-        }), icon: this._timelineVisible ? faEyeSlash : faEye }); 
+        ContextMenu.Instance.addItem({
+            description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
+                this._timelineVisible = !this._timelineVisible;
+            }), icon: this._timelineVisible ? faEyeSlash : faEye
+        });
     }
 
 
@@ -318,28 +325,28 @@ export class Timeline extends React.Component<FieldViewProps> {
         let size = 40 * scale; //50 is default
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
-                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px`, color:"grey"}} /> </div>
-                <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px`, color:"grey"}} /> </div>
-                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px`, color: "grey"}} /> </div>                
+                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px`, color: "grey" }} /> </div>
+                <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px`, color: "grey" }} /> </div>
+                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px`, color: "grey" }} /> </div>
                 <div key="overview-text" className="animation-text">Timeline Overview</div>
-                <TimelineOverview isAuthoring = {BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                <TimelineOverview isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
                 <div key="animation-text" className="animation-text">Mode: {this.props.Document.isATOn ? "Authoring" : "Play"}</div>
                 <div key="round-toggle" ref={this._roundToggleContainerRef} className="round-toggle">
                     <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
                 </div>
-                <div key="time-text" className="animation-text" style ={{visibility: this.props.Document.isATOn ? "visible" : "hidden"}}>Length: </div>
-                <input className="time-input" style={{visibility: this.props.Document.isATOn ? "visible" : "hidden"}} placeholder={String(this._time) + "ms"} ref = {this._timeInputRef} onKeyDown={this.onTimeInput}/>
+                <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }}>Length: </div>
+                <input className="time-input" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }} placeholder={String(this._time) + "ms"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
             </div>
         );
     }
-    
-    @action 
+
+    @action
     private onTimeInput = (e: React.KeyboardEvent) => {
-        if (e.keyCode === 13){
-            let timeInput = this._timeInputRef.current!; 
+        if (e.keyCode === 13) {
+            let timeInput = this._timeInputRef.current!;
             this._time = parseInt(timeInput.value, 10);
-            this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
-            this.props.Document.AnimationLength = this._time; 
+            this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement);
+            this.props.Document.AnimationLength = this._time;
         }
     }
 
@@ -347,7 +354,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     private toggleChecked = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        this.toggleHandle(); 
+        this.toggleHandle();
     }
 
     private toggleHandle = () => {
@@ -358,36 +365,36 @@ export class Timeline extends React.Component<FieldViewProps> {
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff";
             roundToggleContainer.style.animationName = "turnoff";
-            roundToggleContainer.style.backgroundColor = "white"; 
+            roundToggleContainer.style.backgroundColor = "white";
             timelineContainer.style.top = `${-this._containerHeight}px`;
             this.props.Document.isATOn = false;
         } else {
             roundToggle.style.transform = "translate(45px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
-            roundToggleContainer.style.backgroundColor = "green"; 
-            timelineContainer.style.top = "0px"; 
+            roundToggleContainer.style.backgroundColor = "green";
+            timelineContainer.style.top = "0px";
             this.props.Document.isATOn = true;
         }
     }
 
 
-    @observable private _check:string = ""; 
-    @observable private _checkVisible:boolean = false; 
+    @observable private _check: string = "";
+    @observable private _checkVisible: boolean = false;
     @action
     private onCheckClicked = (type: string) => {
-        if (type === "yes"){
-            this._check = "yes";  
-        } else if (type === "no"){
+        if (type === "yes") {
+            this._check = "yes";
+        } else if (type === "no") {
             this._check = "no";
         }
     }
 
 
-    @action 
-    private checkCallBack = (visible:boolean) => {
-        this._checkVisible = visible; 
-        if (!visible){ //when user confirms
+    @action
+    private checkCallBack = (visible: boolean) => {
+        this._checkVisible = visible;
+        if (!visible) { //when user confirms
             this._check = "";
         }
 
@@ -404,22 +411,22 @@ export class Timeline extends React.Component<FieldViewProps> {
                                     <div key="timeline_scrubberhead" className="scrubberhead"></div>
                                 </div>
                                 <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
-                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} checkCallBack={this.checkCallBack}/>)}
+                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} checkCallBack={this.checkCallBack} />)}
                                 </div>
                             </div>
                             <div key="timeline_title" className="title-container" ref={this._titleContainer}>
-                                {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)}
+                                {DocListCast(this.children).map(doc => <div style={{ height: `${(this._titleHeight)}px` }} className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)}
                             </div>
                             <div key="timeline_resize" onPointerDown={this.onResizeDown}>
                                 <FontAwesomeIcon className="resize" icon={faGripLines} />
                             </div>
                         </div>
-                        <div key="timeline-checker" className="timeline-checker" style={{top: `${this._containerHeight}px`, visibility: this._checkVisible ? "visible" : "hidden"}}> 
-                            <div onClick = {() => {this.onCheckClicked("yes");}}>
-                                <FontAwesomeIcon style={{color: "#42b883"}} className="check" icon={faCheckCircle} /> 
+                        <div key="timeline-checker" className="timeline-checker" style={{ top: `${this._containerHeight}px`, visibility: this._checkVisible ? "visible" : "hidden" }}>
+                            <div onClick={() => { this.onCheckClicked("yes"); }}>
+                                <FontAwesomeIcon style={{ color: "#42b883" }} className="check" icon={faCheckCircle} />
                             </div>
-                            <div onClick = {() => {this.onCheckClicked("no");}}>
-                                <FontAwesomeIcon style={{color: "#ff7e67"}} className="check" icon={faTimesCircle} />
+                            <div onClick={() => { this.onCheckClicked("no"); }}>
+                                <FontAwesomeIcon style={{ color: "#ff7e67" }} className="check" icon={faTimesCircle} />
                             </div>
                         </div>
                     </div>
diff --git a/src/client/views/animationtimeline/Track.scss b/src/client/views/animationtimeline/Track.scss
index c8d56edf6..61a8e0b88 100644
--- a/src/client/views/animationtimeline/Track.scss
+++ b/src/client/views/animationtimeline/Track.scss
@@ -5,7 +5,6 @@
     .track {
         .inner {  
             top:0px; 
-            height: 75px;
             width: calc(100%); 
             background-color: $light-color;     
             border: 1px solid $dark-color;        
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index e66b42690..bee9933b0 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -19,10 +19,10 @@ interface IProps {
     time: number;
     tickIncrement: number;
     tickSpacing: number;
-    timelineVisible: boolean; 
-    check: string; 
+    timelineVisible: boolean;
+    check: string;
     changeCurrentBarX: (x: number) => void;
-    checkCallBack: (visible: boolean) => void; 
+    checkCallBack: (visible: boolean) => void;
 
 }
 
@@ -36,35 +36,35 @@ export class Track extends React.Component<IProps> {
     @observable private _onRegionData: (Doc | undefined) = undefined;
     @observable private _storedState: (Doc | undefined) = undefined;
     @observable private filterList = [
-        "regions", 
-        "cursors", 
-        "hidden", 
-        "nativeHeight", 
-        "nativeWidth", 
-        "schemaColumns", 
-        "baseLayout", 
-        "backgroundLayout", 
-        "layout", 
-    ]; 
-        
-    @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;}
+        "regions",
+        "cursors",
+        "hidden",
+        "nativeHeight",
+        "nativeWidth",
+        "schemaColumns",
+        "baseLayout",
+        "backgroundLayout",
+        "layout",
+    ];
+    private _trackHeight = 0;
+
+    @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; }
 
     componentWillMount() {
         runInAction(() => {
-            if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); 
-            console.log("hi");          
-            console.log("HELLO");  
-            console.log("hi");
+            if (!this.props.node.regions) this.props.node.regions = new List<Doc>();
+            this._trackHeight = window.innerHeight / 14; //for responsiveness
+
         });
     }
 
     componentDidMount() {
         runInAction(async () => {
-            this._timelineVisibleReaction = this.timelineVisibleReaction(); 
+            this._timelineVisibleReaction = this.timelineVisibleReaction();
             this._currentBarXReaction = this.currentBarXReaction();
             if (this.regions.length === 0) this.createRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
-            this.props.node.hidden = false;                   
-            this.props.node.opacity = 1; 
+            this.props.node.hidden = false;
+            this.props.node.opacity = 1;
         });
     }
 
@@ -72,7 +72,7 @@ export class Track extends React.Component<IProps> {
         runInAction(() => {
             //disposing reactions 
             if (this._currentBarXReaction) this._currentBarXReaction();
-            if (this._timelineVisibleReaction) this._timelineVisibleReaction(); 
+            if (this._timelineVisibleReaction) this._timelineVisibleReaction();
         });
     }
 
@@ -81,7 +81,7 @@ export class Track extends React.Component<IProps> {
         let keyframes: List<Doc> = (Cast(regiondata.keyframes, listSpec(Doc)) as List<Doc>);
         let kfIndex: number = keyframes.indexOf(ref);
         let kf = keyframes[kfIndex] as Doc;
-        if (!kf) return; 
+        if (!kf) return;
         if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
             kf.key = Doc.MakeCopy(this.props.node, true);
             let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); // lef keyframe, if it exists
@@ -107,13 +107,13 @@ export class Track extends React.Component<IProps> {
         this._isOnKeyframe = false;
     }
 
-    @action 
+    @action
     revertState = () => {
-        let copyDoc = Doc.MakeCopy(this.props.node, true); 
+        let copyDoc = Doc.MakeCopy(this.props.node, true);
         if (this._storedState) this.applyKeys(this._storedState);
-        let newState = new Doc(); 
-        newState.key = copyDoc; 
-        this._storedState = newState; 
+        let newState = new Doc();
+        newState.key = copyDoc;
+        this._storedState = newState;
     }
 
     @action
@@ -129,13 +129,13 @@ export class Track extends React.Component<IProps> {
             }
         });
     }
-    @action 
+    @action
     timelineVisibleReaction = () => {
         return reaction(() => {
-            return this.props.timelineVisible; 
+            return this.props.timelineVisible;
         }, isVisible => {
-            this.revertState(); 
-        }); 
+            this.revertState();
+        });
     }
 
     @action
@@ -162,28 +162,28 @@ export class Track extends React.Component<IProps> {
     @action
     private applyKeys = async (kf: Doc) => {
         let kfNode = await Cast(kf.key, Doc) as Doc;
-        let docFromApply = kfNode;        
+        let docFromApply = kfNode;
         if (this.filterKeys(Doc.allKeys(this.props.node)).length > this.filterKeys(Doc.allKeys(kfNode)).length) docFromApply = this.props.node;
         this.filterKeys(Doc.allKeys(docFromApply)).forEach(key => {
             if (!kfNode[key]) {
                 this.props.node[key] = undefined;
             } else {
                 let stored = kfNode[key];
-                if(stored instanceof ObjectField){                    
-                    this.props.node[key] = stored[Copy](); 
+                if (stored instanceof ObjectField) {
+                    this.props.node[key] = stored[Copy]();
                 } else {
-                    this.props.node[key] = stored; 
+                    this.props.node[key] = stored;
                 }
             }
         });
     }
 
- 
+
 
     @action
     private filterKeys = (keys: string[]): string[] => {
         return keys.reduce((acc: string[], key: string) => {
-            if (!this.filterList.includes(key)) acc.push(key); 
+            if (!this.filterList.includes(key)) acc.push(key);
             return acc;
         }, []);
     }
@@ -249,10 +249,10 @@ export class Track extends React.Component<IProps> {
                 }
             } else {
                 let stored = leftNode[key];
-                if(stored instanceof ObjectField){                    
-                    this.props.node[key] = stored[Copy](); 
+                if (stored instanceof ObjectField) {
+                    this.props.node[key] = stored[Copy]();
                 } else {
-                    this.props.node[key] = stored; 
+                    this.props.node[key] = stored;
                 }
             }
         });
@@ -276,7 +276,7 @@ export class Track extends React.Component<IProps> {
         let inner = this._inner.current!;
         let offsetX = Math.round((e.clientX - inner.getBoundingClientRect().left) * this.props.transform.Scale);
         this.createRegion(KeyframeFunc.convertPixelTime(offsetX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
-        this.forceUpdate(); 
+        this.forceUpdate();
     }
 
     createRegion = (position: number) => {
@@ -297,7 +297,7 @@ export class Track extends React.Component<IProps> {
         return (
             <div className="track-container">
                 <div className="track">
-                    <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick} onPointerOver = {() => {Doc.BrushDoc(this.props.node);}}onPointerOut={() => {Doc.UnBrushDoc(this.props.node);}}>
+                    <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick} onPointerOver={() => { Doc.BrushDoc(this.props.node); }} onPointerOut={() => { Doc.UnBrushDoc(this.props.node); }} style={{ height: `${this._trackHeight}px` }}>
                         {DocListCast(this.regions).map((region) => {
                             return <Keyframe {...this.props} RegionData={region} />;
                         })}
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index efe2c7f2a..f3193896f 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -21,7 +21,7 @@ import { docs_v1 } from "googleapis";
 import { Utils } from "../../../Utils";
 import { Link } from "@react-pdf/renderer";
 
-enum FollowModes {
+export enum FollowModes {
     OPENTAB = "Open in Tab",
     OPENRIGHT = "Open in Right Split",
     OPENFULL = "Open Full Screen",
-- 
cgit v1.2.3-70-g09d2


From 8af45ed7f376981ce8f8b1c6d1b2fd3b1546a00e Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sat, 23 Nov 2019 16:08:44 -0500
Subject: responsive update

---
 src/client/views/animationtimeline/Timeline.tsx | 4 +++-
 src/client/views/animationtimeline/Track.tsx    | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index f8aa88755..64822542d 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -21,6 +21,7 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     private DEFAULT_CONTAINER_HEIGHT: number = 330;
     private readonly DEFAULT_TICK_SPACING: number = 50;
+    private readonly MAX_TITLE_HEIGHT = 75; 
     private MIN_CONTAINER_HEIGHT: number = 205;
     private readonly MAX_CONTAINER_HEIGHT: number = 800;
     private readonly DEFAULT_TICK_INCREMENT: number = 1000;
@@ -61,7 +62,8 @@ export class Timeline extends React.Component<FieldViewProps> {
         return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
     }
     componentWillMount() {
-        this._titleHeight = window.innerHeight / 14; //arbitrary number, but for responsiveness              
+        let relativeHeight = window.innerHeight / 14; 
+        this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; 
         this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; 
         this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; 
     }
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index bee9933b0..a3aa62a31 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -46,6 +46,7 @@ export class Track extends React.Component<IProps> {
         "backgroundLayout",
         "layout",
     ];
+    private readonly MAX_TITLE_HEIGHT = 75; 
     private _trackHeight = 0;
 
     @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; }
@@ -53,7 +54,8 @@ export class Track extends React.Component<IProps> {
     componentWillMount() {
         runInAction(() => {
             if (!this.props.node.regions) this.props.node.regions = new List<Doc>();
-            this._trackHeight = window.innerHeight / 14; //for responsiveness
+            let relativeHeight = window.innerHeight / 14; 
+            this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness
 
         });
     }
-- 
cgit v1.2.3-70-g09d2


From 5bf4dfa43e07a21bc5cb96b3b98f1a6ddb75b903 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sat, 23 Nov 2019 16:31:15 -0500
Subject: another change

---
 src/client/views/animationtimeline/Timeline.tsx                        | 3 +--
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx    | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 64822542d..2b960cc88 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -8,8 +8,7 @@ import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlayCircle, faBackward, faForward, faGripLines, faArrowUp, faArrowDown, faClock, faPauseCircle, faEyeSlash, faTimes, faEye, faCheck, faCross, faCheckCircle, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
-import { ContextMenuProps } from "../ContextMenuItem";
+import { faPlayCircle, faBackward, faForward, faGripLines,faPauseCircle, faEyeSlash,faEye,faCheckCircle, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
 import { FieldViewProps } from "../nodes/FieldView";
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9fbfffc82..e2b4716ce 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -637,7 +637,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     }
 
     private viewDefToJSX(viewDef: any): Opt<ViewDefResult> {
-        if (viewDef.type === "text") {
+        if (viewDef.type === "text") { 
             const text = Cast(viewDef.text, "string"); // don't use NumCast, StrCast, etc since we want to test for undefined below
             const x = Cast(viewDef.x, "number");
             const y = Cast(viewDef.y, "number");
-- 
cgit v1.2.3-70-g09d2


From a24f9da758415c60dbcb56b1cb488bec02d5b1a0 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Tue, 10 Dec 2019 17:55:13 -0500
Subject: some changes

---
 src/client/views/animationtimeline/Keyframe.tsx |  5 ++-
 src/client/views/animationtimeline/Timeline.tsx | 45 ++++++++++++++++++++-----
 src/client/views/animationtimeline/Track.tsx    | 25 ++++++++++++--
 src/client/views/nodes/DocumentView.tsx         |  4 +--
 4 files changed, 64 insertions(+), 15 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index e8b75eef4..c3e018112 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -88,6 +88,7 @@ export namespace KeyframeFunc {
         regiondata.fadeIn = 1000;
         regiondata.fadeOut = 1000;
         regiondata.functions = new List<Doc>();
+        regiondata.hasData = false; 
         return regiondata;
     };
 
@@ -114,7 +115,8 @@ export const RegionDataSchema = createSchema({
     keyframes: listSpec(Doc),
     fadeIn: defaultSpec("number", 0),
     fadeOut: defaultSpec("number", 0),
-    functions: listSpec(Doc)
+    functions: listSpec(Doc), 
+    hasData: defaultSpec("boolean", false)
 });
 export type RegionData = makeInterface<[typeof RegionDataSchema]>;
 export const RegionData = makeInterface(RegionDataSchema);
@@ -340,6 +342,7 @@ export class Keyframe extends React.Component<IProps> {
         if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
             let position = this.regiondata.position;
             await this.makeKeyData(Math.round(position + offset));
+            this.regiondata.hasData = true; 
             this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied
         }
     }
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 2b960cc88..c13a039a5 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -3,7 +3,7 @@ import "./Timeline.scss";
 import { listSpec } from "../../../new_fields/Schema";
 import { observer } from "mobx-react";
 import { Track } from "./Track";
-import { observable, reaction, action, IReactionDisposer, computed, runInAction, observe, toJS } from "mobx";
+import { observable, action, computed, runInAction } from "mobx";
 import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
@@ -17,14 +17,18 @@ import { Utils } from "../../../Utils";
 
 @observer
 export class Timeline extends React.Component<FieldViewProps> {
-
-    private DEFAULT_CONTAINER_HEIGHT: number = 330;
+    
+    //readonly constants
     private readonly DEFAULT_TICK_SPACING: number = 50;
     private readonly MAX_TITLE_HEIGHT = 75; 
-    private MIN_CONTAINER_HEIGHT: number = 205;
     private readonly MAX_CONTAINER_HEIGHT: number = 800;
     private readonly DEFAULT_TICK_INCREMENT: number = 1000;
 
+    //height variables
+    private DEFAULT_CONTAINER_HEIGHT: number = 330;
+    private MIN_CONTAINER_HEIGHT: number = 205;
+    
+    //react refs
     @observable private _trackbox = React.createRef<HTMLDivElement>();
     @observable private _titleContainer = React.createRef<HTMLDivElement>();
     @observable private _timelineContainer = React.createRef<HTMLDivElement>();
@@ -33,6 +37,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _roundToggleContainerRef = React.createRef<HTMLDivElement>();
     @observable private _timeInputRef = React.createRef<HTMLInputElement>();
 
+    //boolean vars and instance vars 
     @observable private _currentBarX: number = 0;
     @observable private _windSpeed: number = 1;
     @observable private _isPlaying: boolean = false; //scrubber playing
@@ -47,7 +52,11 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _timelineVisible = false;
     @observable private _mouseToggled = false;
     @observable private _doubleClickEnabled = false;
-    private _titleHeight = 0;
+    @observable private _titleHeight = 0;
+
+    /**
+     * collection get method. Basically defines what defines collection's children. These will be tracked in the timeline. Do not edit. 
+     */
     @computed
     private get children(): List<Doc> {
         let extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type));
@@ -60,6 +69,10 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
         return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
     }
+
+    /**
+     * 
+     */
     componentWillMount() {
         let relativeHeight = window.innerHeight / 14; 
         this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; 
@@ -140,16 +153,21 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
-
+    /**
+     * fast forward the timeline scrubbing
+     */
     @action
     windForward = (e: React.MouseEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        if (this._windSpeed < 64) { //max speed is 32
+        if (this._windSpeed < 64) { //max speed is 32 
             this._windSpeed = this._windSpeed * 2;
         }
     }
 
+    /**
+     * rewind the timeline scrubbing 
+     */
     @action
     windBackward = (e: React.MouseEvent) => {
         e.preventDefault();
@@ -159,7 +177,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
-    //for scrubber action 
+    
     @action
     onScrubberDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -392,6 +410,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
+
     @action
     private checkCallBack = (visible: boolean) => {
         this._checkVisible = visible;
@@ -400,10 +419,18 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
 
     }
+
+
+
+
+
+
+
+
     render() {
         return (
             <div>
-                <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
+                <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}> 
                     <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
                         <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
                             <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 22b83f055..d0bcdd655 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -65,9 +65,8 @@ export class Track extends React.Component<IProps> {
     componentWillMount() {
         runInAction(() => {
             if (!this.props.node.regions) this.props.node.regions = new List<Doc>();
-            let relativeHeight = window.innerHeight / 14; 
+            let relativeHeight = window.innerHeight / 14;
             this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness
-
         });
     }
 
@@ -145,12 +144,32 @@ export class Track extends React.Component<IProps> {
     @action
     timelineVisibleReaction = () => {
         return reaction(() => {
-            return this.props.timelineVisible;
+            return this.props.timelineVisible; 
         }, isVisible => {
             this.revertState();
+            if (isVisible){
+                DocListCast(this.regions).forEach(region => {
+                    if (!BoolCast((Cast(region, Doc) as Doc).hasData)){
+                        for (let i = 0; i < 4; i++){
+                            DocListCast(((Cast(region, Doc) as Doc).keyframes as List<Doc>))[i].key = Doc.MakeCopy(this.props.node, true); 
+                            if (i === 0 || i === 3){
+                                DocListCast(((Cast(region, Doc) as Doc).keyframes as List<Doc>))[i].key.opacity = 0.1;
+                            }
+                        }
+                        console.log("saving keyframes"); 
+                    }
+                }); 
+            }
         });
     }
 
+    @action 
+    /**
+     * Simple loop through all the regions to update the keyframes. Only applies to timelineVisibleReaction
+     */
+    updateAllRegions = () => {
+        
+    }
     @action
     timeChange = async (time: number) => {
         if (this._isOnKeyframe && this._onKeyframe && this._onRegionData) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 467fd4b32..6c3dd2051 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -669,10 +669,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         return <div className={`documentView-node${this.topMost ? "-topmost" : ""}`} ref={this._mainCont}
             onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
             onPointerEnter={e => {
-                console.log("Brush" + this.props.Document.title);
+                //console.log("Brush" + this.props.Document.title);
                 Doc.BrushDoc(this.props.Document);
             }} onPointerLeave={e => {
-                console.log("UnBrush" + this.props.Document.title);
+                //console.log("UnBrush" + this.props.Document.title);
                 Doc.UnBrushDoc(this.props.Document);
 
             }}
-- 
cgit v1.2.3-70-g09d2


From aa5b205e3d5239457fd224da37fe32421a4f3b3c Mon Sep 17 00:00:00 2001
From: Andrew Kim <andrewdkim@users.noreply.github.com>
Date: Thu, 9 Jan 2020 21:45:00 +0900
Subject: documentation

---
 src/client/views/animationtimeline/Keyframe.tsx |  65 ++++++++++++
 src/client/views/animationtimeline/Timeline.tsx | 127 ++++++++++++++++++------
 src/client/views/animationtimeline/Track.tsx    |  62 ++++++++++--
 3 files changed, 218 insertions(+), 36 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index c3e018112..c3c1f5f8c 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -15,6 +15,11 @@ import { Docs } from "../../documents/Documents";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 
+
+
+/**
+ * Useful static functions that you can use. Mostly for logic, but you can also add UI logic here also 
+ */
 export namespace KeyframeFunc {
     export enum KeyframeType {
         fade = "fade",
@@ -134,6 +139,30 @@ interface IProps {
     checkCallBack: (visible: boolean) => void;
 }
 
+
+/**
+ * 
+ * This class handles the green region stuff
+ * Key facts:
+ * 
+ * Structure looks like this
+ * 
+ * region as a whole
+ *  <------------------------------REGION------------------------------->
+ * 
+ * region broken down 
+ * 
+ *  <|---------|############ MAIN CONTENT #################|-----------|>      .....followed by void.........
+ *  (start)                                             (Fade 2)
+ *            (fade 1)                                              (finish)
+ * 
+ * 
+ * As you can see, this is different from After Effect and Premiere Pro, but this is how TAG worked. 
+ * If you want to checkout TAG, it's in the lockers, and the password is the usual lab door password. It's the blue laptop.  
+ * If you want to know the exact location of the computer, message me. 
+ * 
+ * @author Andrew Kim 
+ */
 @observer
 export class Keyframe extends React.Component<IProps> {
 
@@ -363,6 +392,10 @@ export class Keyframe extends React.Component<IProps> {
         this.props.node.backgroundColor = "#000000";
     }
 
+
+    /**
+     * custom keyframe context menu items (when clicking on the keyframe circle)
+     */
     @action
     makeKeyframeMenu = (kf: Doc, e: MouseEvent) => {
         TimelineMenu.Instance.addItem("button", "Show Data", () => {
@@ -396,6 +429,9 @@ export class Keyframe extends React.Component<IProps> {
         TimelineMenu.Instance.openMenu(e.clientX, e.clientY);
     }
 
+    /**
+     * context menu for region (anywhere on the green region). 
+     */
     @action
     makeRegionMenu = (kf: Doc, e: MouseEvent) => {
         TimelineMenu.Instance.addItem("button", "Add Ease", () => {
@@ -481,6 +517,10 @@ export class Keyframe extends React.Component<IProps> {
         TimelineMenu.Instance.openMenu(e.clientX, e.clientY);
     }
 
+
+    /**
+     * checking if input is correct (might have to use external module)
+     */
     @action
     checkInput = (val: any) => {
         return typeof (val === "number");
@@ -495,6 +535,9 @@ export class Keyframe extends React.Component<IProps> {
         });
     }
 
+    /**
+     * hovering effect when hovered (hidden div darkens)
+     */
     @action
     onContainerOver = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
         e.preventDefault();
@@ -504,6 +547,9 @@ export class Keyframe extends React.Component<IProps> {
         Doc.BrushDoc(this.props.node);
     }
 
+    /**
+     * hovering effect when hovered out (hidden div becomes invisible)
+     */
     @action
     onContainerOut = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
         e.preventDefault();
@@ -520,6 +566,9 @@ export class Keyframe extends React.Component<IProps> {
     private _type: string = "";
 
 
+    /**
+     * Need to fix this. skip
+     */
     @action
     onContainerDown = (kf: Doc, type: string) => {
         let listenerCreated = false;
@@ -544,6 +593,9 @@ export class Keyframe extends React.Component<IProps> {
         });
     }
 
+    /**
+     * for custom draw interpolation. Need to be refactored
+     */
     @action
     onReactionListen = () => {
         if (this._reac && this._plotList && this._interpolationKeyframe) {
@@ -589,6 +641,13 @@ export class Keyframe extends React.Component<IProps> {
         }
     }
 
+    ///////////////////////UI STUFF /////////////////////////
+
+
+    /**
+     * drawing keyframe. Handles both keyframe with a circle (one that you create by double clicking) and one without circle (fades)
+     * this probably needs biggest change, since everyone expected all keyframes to have a circle (and draggable)
+     */
     @action
     drawKeyframes = () => {
         let keyframeDivs: JSX.Element[] = [];
@@ -616,6 +675,9 @@ export class Keyframe extends React.Component<IProps> {
         return keyframeDivs;
     }
 
+    /**
+     * drawing the hidden divs that partition different intervals within a region. 
+     */
     @action
     drawKeyframeDividers = () => {
         let keyframeDividers: JSX.Element[] = [];
@@ -645,6 +707,9 @@ export class Keyframe extends React.Component<IProps> {
         return keyframeDividers;
     }
 
+    /**
+     * rendering that green region
+     */
     render() {
         return (
             <div>
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index c13a039a5..9cf600b5f 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -15,9 +15,32 @@ import { FieldViewProps } from "../nodes/FieldView";
 import { KeyframeFunc } from "./Keyframe";
 import { Utils } from "../../../Utils";
 
+
+/**
+ * Timeline class controls most of timeline functions besides individual keyframe and track mechanism. Main functions are 
+ * zooming, panning, currentBarX (scrubber movement). Most of the UI stuff is also handled here. You shouldn't really make 
+ * any logical changes here. Most work is needed on UI. 
+ * 
+ * The hierarchy works this way: 
+ * 
+ *              Timeline.tsx --> Track.tsx --> Keyframe.tsx 
+                      |                              |
+                      |                   TimelineMenu.tsx (timeline's custom contextmenu)
+                      |
+                      |
+                TimelineOverview.tsx (youtube like dragging thing is play mode, complex dragging thing in editing mode)
+
+
+    Most style changes are in SCSS file. 
+    If you have any questions, email me or text me. 
+    @author Andrew Kim 
+ */
+
+
 @observer
 export class Timeline extends React.Component<FieldViewProps> {
-    
+
+
     //readonly constants
     private readonly DEFAULT_TICK_SPACING: number = 50;
     private readonly MAX_TITLE_HEIGHT = 75; 
@@ -70,38 +93,35 @@ export class Timeline extends React.Component<FieldViewProps> {
         return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>;
     }
 
-    /**
-     * 
-     */
+    /////////lifecycle functions////////////
     componentWillMount() {
-        let relativeHeight = window.innerHeight / 14; 
-        this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; 
-        this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; 
-        this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; 
+        let relativeHeight = window.innerHeight / 14; //sets height to arbitrary size, relative to innerHeight
+        this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //check if relHeight is less than Maxheight. Else, just set relheight to max
+        this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; //offset
+        this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; //twice the titleheight + offset
     }
 
     componentDidMount() {
         runInAction(() => {
-            if (!this.props.Document.AnimationLength) {
-                this.props.Document.AnimationLength = this._time;
+            if (!this.props.Document.AnimationLength) { //if animation length did not exist
+                this.props.Document.AnimationLength = this._time; //set it to default time
             } else {
-                this._time = NumCast(this.props.Document.AnimationLength);
-                console.log(this._time);
+                this._time = NumCast(this.props.Document.AnimationLength); //else, set time to animationlength stored from before
             }
-            this._totalLength = this._tickSpacing * (this._time / this._tickIncrement);
-            this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width;
-            this._visibleStart = this._infoContainer.current!.scrollLeft;
-            this.props.Document.isATOn = !this.props.Document.isATOn;
+            this._totalLength = this._tickSpacing * (this._time / this._tickIncrement); //the entire length of the timeline div (actual div part itself)
+            this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; //the visible length of the timeline (the length that you current see)
+            this._visibleStart = this._infoContainer.current!.scrollLeft; //where the div starts
+            this.props.Document.isATOn = !this.props.Document.isATOn; //turns the boolean on, saying AT (animation timeline) is on
             this.toggleHandle();
         });
     }
 
     componentWillUnmount() {
         runInAction(() => {
-            console.log(this._time);
-            this.props.Document.AnimationLength = this._time;
+            this.props.Document.AnimationLength = this._time; //save animation length
         });
     }
+    /////////////////////////////////////////////////
 
     /**
      * React Functional Component
@@ -116,7 +136,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         return ticks;
     }
 
-
+    /**
+     * changes the scrubber to actual pixel position
+     */
     @action
     changeCurrentBarX = (pixel: number) => {
         pixel <= 0 ? this._currentBarX = 0 : pixel >= this._totalLength ? this._currentBarX = this._totalLength : this._currentBarX = pixel;
@@ -130,6 +152,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         this.play();
     }
 
+    /**
+     * when playbutton is clicked
+     */
     @action
     play = () => {
         if (this._isPlaying) {
@@ -177,7 +202,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
-    
+    /**
+     * scrubber down 
+     */
     @action
     onScrubberDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -188,16 +215,22 @@ export class Timeline extends React.Component<FieldViewProps> {
         });
     }
 
+    /**
+     * when there is any scrubber movement
+     */
     @action
     onScrubberMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
         let scrubberbox = this._infoContainer.current!;
         let left = scrubberbox.getBoundingClientRect().left;
-        let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
-        this.changeCurrentBarX(offsetX + this._visibleStart);
+        let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale; 
+        this.changeCurrentBarX(offsetX + this._visibleStart); //changes scrubber to clicked scrubber position
     }
 
+    /**
+     * when panning the timeline (in editing mode)
+     */
     @action
     onPanDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -223,6 +256,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
+    /**
+     * when moving the timeline (in editing mode)
+     */
     @action
     onPanMove = (e: PointerEvent) => {
         e.preventDefault();
@@ -243,6 +279,8 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
 
     }
+
+
     @action
     movePanX = (pixel: number) => {
         let infoContainer = this._infoContainer.current!;
@@ -250,6 +288,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         this._visibleStart = infoContainer.scrollLeft;
     }
 
+    /**
+     * resizing timeline (in editing mode) (the hamburger drag icon)
+     */
     @action
     onResizeDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -274,6 +315,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
+    /**
+     * for displaying time to standard min:sec
+     */
     @action
     toReadTime = (time: number): string => {
         const inSeconds = time / 1000;
@@ -286,6 +330,11 @@ export class Timeline extends React.Component<FieldViewProps> {
         return `${min}:${sec}`;
     }
 
+
+    /**
+     * context menu function. 
+     * opens the timeline or closes the timeline. 
+     */
     timelineContextMenu = (e: MouseEvent): void => {
         ContextMenu.Instance.addItem({
             description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
@@ -295,6 +344,10 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
+    /**
+     * timeline zoom function 
+     * use mouse middle button to zoom in/out the timeline
+     */
     @action
     onWheelZoom = (e: React.WheelEvent) => {
         e.preventDefault();
@@ -311,6 +364,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         this.changeCurrentBarX(currCurrent);
     }
 
+    /**
+     * zooming mechanism (increment and spacing changes)
+     */
     @action
     zoom = (dir: boolean) => {
         let spacingChange = this._tickSpacing;
@@ -340,6 +396,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
+    /**
+     * tool box includes the toggle buttons at the top of the timeline (both editing mode and play mode)
+     */
     private timelineToolBox = (scale: number) => {
         let size = 40 * scale; //50 is default
         return (
@@ -359,6 +418,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         );
     }
 
+    /**
+     * manual time input (kinda broken right now)
+     */
     @action
     private onTimeInput = (e: React.KeyboardEvent) => {
         if (e.keyCode === 13) {
@@ -369,6 +431,10 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
+
+    /**
+     * when the user decides to click the toggle button (either user wants to enter editing mode or play mode)
+     */
     @action
     private toggleChecked = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -376,6 +442,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         this.toggleHandle();
     }
 
+    /**
+     * turns on the toggle button (the purple slide button that changes from editing mode and play mode
+     */
     private toggleHandle = () => {
         let roundToggle = this._roundToggleRef.current!;
         let roundToggleContainer = this._roundToggleContainerRef.current!;
@@ -410,7 +479,9 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
-
+    /**
+     * check mark thing that needs to be fixed. Do not edit this, because it most likely change.
+     */
     @action
     private checkCallBack = (visible: boolean) => {
         this._checkVisible = visible;
@@ -421,12 +492,10 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
-
-
-
-
-
-
+    /**
+     * if you have any question here, just shoot me an email or text. 
+     * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
+     */
     render() {
         return (
             <div>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index d0bcdd655..d9b8026c5 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -62,9 +62,11 @@ export class Track extends React.Component<IProps> {
 
     @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; }
 
+    ////////// life cycle functions///////////////
     componentWillMount() {
         runInAction(() => {
-            if (!this.props.node.regions) this.props.node.regions = new List<Doc>();
+            if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); //if there is no region, then create new doc to store stuff
+            //these two lines are exactly same from timeline.tsx 
             let relativeHeight = window.innerHeight / 14;
             this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness
         });
@@ -80,6 +82,9 @@ export class Track extends React.Component<IProps> {
         });
     }
 
+    /**
+     * mainly for disposing reactions
+     */
     componentWillUnmount() {
         runInAction(() => {
             //disposing reactions 
@@ -87,7 +92,11 @@ export class Track extends React.Component<IProps> {
             if (this._timelineVisibleReaction) this._timelineVisibleReaction();
         });
     }
+    ////////////////////////////////
 
+    /**
+     * keyframe save logic. Needs to be changed so it's more efficient
+     */
     @action
     saveKeyframe = async (ref: Doc, regiondata: Doc) => {
         let keyframes: List<Doc> = (Cast(regiondata.keyframes, listSpec(Doc)) as List<Doc>);
@@ -119,6 +128,9 @@ export class Track extends React.Component<IProps> {
         this._isOnKeyframe = false;
     }
 
+    /**
+     * reverting back to previous state before editing on AT
+     */
     @action
     revertState = () => {
         let copyDoc = Doc.MakeCopy(this.props.node, true);
@@ -128,6 +140,10 @@ export class Track extends React.Component<IProps> {
         this._storedState = newState;
     }
 
+    /**
+     * Reaction when scrubber bar changes
+     * made into function so it's easier to dispose later
+    */
     @action
     currentBarXReaction = () => {
         return reaction(() => this.props.currentBarX, async () => {
@@ -141,6 +157,10 @@ export class Track extends React.Component<IProps> {
             }
         });
     }
+
+    /**
+     * when timeline is visible, reaction is ran so states are reverted
+     */
     @action
     timelineVisibleReaction = () => {
         return reaction(() => {
@@ -163,13 +183,9 @@ export class Track extends React.Component<IProps> {
         });
     }
 
-    @action 
-    /**
-     * Simple loop through all the regions to update the keyframes. Only applies to timelineVisibleReaction
+    /**w
+     * when scrubber position changes. Need to edit the logic
      */
-    updateAllRegions = () => {
-        
-    }
     @action
     timeChange = async (time: number) => {
         if (this._isOnKeyframe && this._onKeyframe && this._onRegionData) {
@@ -191,6 +207,10 @@ export class Track extends React.Component<IProps> {
         }
     }
 
+    /**
+     * applying changes (when saving the keyframe) 
+     * need to change the logic here
+     */
     @action
     private applyKeys = async (kf: Doc) => {
         let kfNode = await Cast(kf.key, Doc) as Doc;
@@ -212,6 +232,9 @@ export class Track extends React.Component<IProps> {
 
 
 
+    /**
+     * changing the filter here 
+     */
     @action
     private filterKeys = (keys: string[]): string[] => {
         return keys.reduce((acc: string[], key: string) => {
@@ -220,6 +243,10 @@ export class Track extends React.Component<IProps> {
         }, []);
     }
 
+
+    /**
+     *  calculating current keyframe, if the scrubber is right on the keyframe
+     */
     @action
     calcCurrent = async (region: Doc) => {
         let currentkf: (Doc | undefined) = undefined;
@@ -231,6 +258,10 @@ export class Track extends React.Component<IProps> {
     }
 
 
+    /**
+     * interpolation. definetely needs to be changed. (currently involves custom linear splicing interpolations). 
+     * Too complex right now. Also need to apply quadratic spline later on (for smoothness, instead applying "gains")
+     */
     @action
     interpolate = async (left: Doc, right: Doc, regiondata: Doc) => {
         let leftNode = left.key as Doc;
@@ -290,6 +321,10 @@ export class Track extends React.Component<IProps> {
         });
     }
 
+    /**
+     * finds region that corresponds to specific time (is there a region at this time?)
+     * linear O(n) (maybe possible to optimize this with other Data structures?)
+     */
     @action
     findRegion = async (time: number) => {
         let foundRegion: (Doc | undefined) = undefined;
@@ -303,6 +338,10 @@ export class Track extends React.Component<IProps> {
         return foundRegion;
     }
 
+
+    /**
+     * double click on track. Signalling keyframe creation. Problem with phantom regions
+     */
     @action
     onInnerDoubleClick = (e: React.MouseEvent) => {
         let inner = this._inner.current!;
@@ -311,6 +350,10 @@ export class Track extends React.Component<IProps> {
         this.forceUpdate();
     }
 
+
+    /**
+     * creates a region (KEYFRAME.TSX stuff). 
+     */
     createRegion = (position: number) => {
         let regiondata = KeyframeFunc.defaultKeyframe();
         regiondata.position = position;
@@ -325,6 +368,11 @@ export class Track extends React.Component<IProps> {
         }
 
     }
+
+
+    /**
+     * UI sstuff here. Not really much to change
+     */
     render() {
         return (
             <div className="track-container">
-- 
cgit v1.2.3-70-g09d2


From b25276d9442f5ae9196a72b4af05849b9e69ef2f Mon Sep 17 00:00:00 2001
From: Andrew Kim <andrewdkim@users.noreply.github.com>
Date: Sat, 11 Jan 2020 15:42:58 +0900
Subject: phantom region fix, scrubber double click, fade kf

---
 src/client/views/animationtimeline/Keyframe.tsx  | 104 +++++++----------------
 src/client/views/animationtimeline/Timeline.scss |   2 +
 src/client/views/animationtimeline/Timeline.tsx  |   4 +-
 src/client/views/animationtimeline/Track.tsx     |  26 +++---
 4 files changed, 51 insertions(+), 85 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index c3c1f5f8c..62528483b 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -22,6 +22,7 @@ import { undoBatch, UndoManager } from "../../util/UndoManager";
  */
 export namespace KeyframeFunc {
     export enum KeyframeType {
+        end = "end",
         fade = "fade",
         default = "default",
     }
@@ -194,8 +195,8 @@ export class Keyframe extends React.Component<IProps> {
             if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();
             let fadeIn = await this.makeKeyData(this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade)!;
             let fadeOut = await this.makeKeyData(this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade)!;
-            let start = await this.makeKeyData(this.regiondata.position, KeyframeFunc.KeyframeType.fade)!;
-            let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!;
+            let start = await this.makeKeyData(this.regiondata.position, KeyframeFunc.KeyframeType.end)!;
+            let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.end)!;
             (fadeIn.key! as Doc).opacity = 1;
             (fadeOut.key! as Doc).opacity = 1;
             (start.key! as Doc).opacity = 0.1;
@@ -206,7 +207,6 @@ export class Keyframe extends React.Component<IProps> {
 
     @action
     makeKeyData = async (kfpos: number, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time 
-        const batch = UndoManager.StartBatch("makeKeyData");
         let doclist = (await DocListCastAsync(this.regiondata.keyframes))!;
         let existingkf: (Doc | undefined) = undefined;
         doclist.forEach(TK => {
@@ -218,19 +218,11 @@ export class Keyframe extends React.Component<IProps> {
         TK.key = Doc.MakeCopy(this.props.node, true);
         TK.type = type;
         this.regiondata.keyframes!.push(TK);
-
-        // myObservable++;
-        // UndoManager.AddEvent({
-        //     undo: action(() => myObservable--),
-        //     redo: action(() => myObservable++)
-        // });
-
         let interpolationFunctions = new Doc();
         interpolationFunctions.interpolationX = new List<number>([0, 1]);
         interpolationFunctions.interpolationY = new List<number>([0, 100]);
         interpolationFunctions.pathX = new List<number>();
         interpolationFunctions.pathY = new List<number>();
-
         this.regiondata.functions!.push(interpolationFunctions);
         let found: boolean = false;
         this.regiondata.keyframes!.forEach(compkf => {
@@ -244,7 +236,6 @@ export class Keyframe extends React.Component<IProps> {
                 return;
             }
         });
-        batch.end();
         return TK;
     }
 
@@ -384,15 +375,6 @@ export class Keyframe extends React.Component<IProps> {
         this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(NumCast(kf.time!), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement));
     }
 
-
-    @action
-    onKeyframeOver = (e: React.PointerEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        this.props.node.backgroundColor = "#000000";
-    }
-
-
     /**
      * custom keyframe context menu items (when clicking on the keyframe circle)
      */
@@ -412,7 +394,6 @@ export class Keyframe extends React.Component<IProps> {
             }),
             TimelineMenu.Instance.addItem("input", "Move", (val) => {
                 runInAction(() => {
-                    if (this.checkInput(val)) {
                         let cannotMove: boolean = false;
                         let kfIndex: number = this.keyframes.indexOf(kf);
                         if (val < 0 || (val < NumCast(this.keyframes[kfIndex - 1].time) || val > NumCast(this.keyframes[kfIndex + 1].time))) {
@@ -422,7 +403,6 @@ export class Keyframe extends React.Component<IProps> {
                             this.keyframes[kfIndex].time = parseInt(val, 10);
                             this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn;
                         }
-                    }
                 });
             });
         TimelineMenu.Instance.addMenu("Keyframe");
@@ -448,7 +428,6 @@ export class Keyframe extends React.Component<IProps> {
             }),
             TimelineMenu.Instance.addItem("input", `fadeIn: ${this.regiondata.fadeIn}ms`, (val) => {
                 runInAction(() => {
-                    if (this.checkInput(val)) {
                         let cannotMove: boolean = false;
                         if (val < 0 || val > NumCast(this.keyframes[2].time) - this.regiondata.position) {
                             cannotMove = true;
@@ -457,59 +436,52 @@ export class Keyframe extends React.Component<IProps> {
                             this.regiondata.fadeIn = parseInt(val, 10);
                             this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn;
                         }
-                    }
                 });
             }),
             TimelineMenu.Instance.addItem("input", `fadeOut: ${this.regiondata.fadeOut}ms`, (val) => {
                 runInAction(() => {
-                    if (this.checkInput(val)) {
-                        let cannotMove: boolean = false;
-                        if (val < 0 || val > this.regiondata.position + this.regiondata.duration - NumCast(this.keyframes[this.keyframes.length - 3].time)) {
-                            cannotMove = true;
-                        }
-                        if (!cannotMove) {
-                            this.regiondata.fadeOut = parseInt(val, 10);
-                            this.keyframes[this.keyframes.length - 2].time = this.regiondata.position + this.regiondata.duration - val;
-                        }
+                    let cannotMove: boolean = false;
+                    if (val < 0 || val > this.regiondata.position + this.regiondata.duration - NumCast(this.keyframes[this.keyframes.length - 3].time)) {
+                        cannotMove = true;
+                    }
+                    if (!cannotMove) {
+                        this.regiondata.fadeOut = parseInt(val, 10);
+                        this.keyframes[this.keyframes.length - 2].time = this.regiondata.position + this.regiondata.duration - val;
                     }
                 });
             }),
             TimelineMenu.Instance.addItem("input", `position: ${this.regiondata.position}ms`, (val) => {
                 runInAction(() => {
-                    if (this.checkInput(val)) {
-                        let prevPosition = this.regiondata.position;
-                        let cannotMove: boolean = false;
-                        DocListCast(this.regions).forEach(region => {
-                            if (NumCast(region.position) !== this.regiondata.position) {
-                                if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration) || (this.regiondata.duration + val > NumCast(region.position) && this.regiondata.duration + val < NumCast(region.position) + NumCast(region.duration)))) {
-                                    cannotMove = true;
-                                }
+                    let prevPosition = this.regiondata.position;
+                    let cannotMove: boolean = false;
+                    DocListCast(this.regions).forEach(region => {
+                        if (NumCast(region.position) !== this.regiondata.position) {
+                            if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration) || (this.regiondata.duration + val > NumCast(region.position) && this.regiondata.duration + val < NumCast(region.position) + NumCast(region.duration)))) {
+                                cannotMove = true;
                             }
-                        });
-                        if (!cannotMove) {
-                            this.regiondata.position = parseInt(val, 10);
-                            this.updateKeyframes(this.regiondata.position - prevPosition);
                         }
+                    });
+                    if (!cannotMove) {
+                        this.regiondata.position = parseInt(val, 10);
+                        this.updateKeyframes(this.regiondata.position - prevPosition);
                     }
                 });
             }),
             TimelineMenu.Instance.addItem("input", `duration: ${this.regiondata.duration}ms`, (val) => {
                 runInAction(() => {
-                    if (this.checkInput(val)) {
-                        let cannotMove: boolean = false;
-                        DocListCast(this.regions).forEach(region => {
-                            if (NumCast(region.position) !== this.regiondata.position) {
-                                val += this.regiondata.position;
-                                if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration))) {
-                                    cannotMove = true;
-                                }
+                    let cannotMove: boolean = false;
+                    DocListCast(this.regions).forEach(region => {
+                        if (NumCast(region.position) !== this.regiondata.position) {
+                            val += this.regiondata.position;
+                            if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration))) {
+                                cannotMove = true;
                             }
-                        });
-                        if (!cannotMove) {
-                            this.regiondata.duration = parseInt(val, 10);
-                            this.keyframes[this.keyframes.length - 1].time = this.regiondata.position + this.regiondata.duration;
-                            this.keyframes[this.keyframes.length - 2].time = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut;
                         }
+                    });
+                    if (!cannotMove) {
+                        this.regiondata.duration = parseInt(val, 10);
+                        this.keyframes[this.keyframes.length - 1].time = this.regiondata.position + this.regiondata.duration;
+                        this.keyframes[this.keyframes.length - 2].time = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut;
                     }
                 });
             }),
@@ -517,15 +489,6 @@ export class Keyframe extends React.Component<IProps> {
         TimelineMenu.Instance.openMenu(e.clientX, e.clientY);
     }
 
-
-    /**
-     * checking if input is correct (might have to use external module)
-     */
-    @action
-    checkInput = (val: any) => {
-        return typeof (val === "number");
-    }
-
     @action
     updateKeyframes = (incr: number, filter: number[] = []) => {
         this.keyframes.forEach(kf => {
@@ -652,7 +615,7 @@ export class Keyframe extends React.Component<IProps> {
     drawKeyframes = () => {
         let keyframeDivs: JSX.Element[] = [];
         DocListCast(this.regiondata.keyframes).forEach(kf => {
-            if (kf.type as KeyframeFunc.KeyframeType === KeyframeFunc.KeyframeType.default) {
+            if (kf.type as KeyframeFunc.KeyframeType !== KeyframeFunc.KeyframeType.end) {
                 keyframeDivs.push(
                     <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
                         <div className="divider"></div>
@@ -663,8 +626,7 @@ export class Keyframe extends React.Component<IProps> {
                         }} onDoubleClick={(e) => { e.preventDefault(); e.stopPropagation(); }}></div>
                     </div>
                 );
-            }
-            else {
+            } else {
                 keyframeDivs.push(
                     <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
                         <div className="divider"></div>
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 493b084a8..76c8475d1 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -109,6 +109,7 @@
             position: absolute;
             z-index: 1001;
             background-color: black;
+            pointer-events: none;
 
             .scrubberhead {
                 top: -30px;
@@ -119,6 +120,7 @@
                 border: 5px solid black;
                 left: -15px;
                 position: absolute;
+                pointer-events: all;
             }
         }
 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 9cf600b5f..df25f709a 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -504,8 +504,8 @@ export class Timeline extends React.Component<FieldViewProps> {
                         <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
                             <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
                                 {this.drawTicks()}
-                                <div key="timeline_scrubber" className="scrubber" onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
-                                    <div key="timeline_scrubberhead" className="scrubberhead"></div>
+                                <div key="timeline_scrubber" className="scrubber" style={{ transform: `translate(${this._currentBarX}px)` }}>
+                                    <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div>
                                 </div>
                                 <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
                                     {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} checkCallBack={this.checkCallBack} />)}
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index d9b8026c5..2ea3d168f 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -96,6 +96,7 @@ export class Track extends React.Component<IProps> {
 
     /**
      * keyframe save logic. Needs to be changed so it's more efficient
+     * 
      */
     @action
     saveKeyframe = async (ref: Doc, regiondata: Doc) => {
@@ -354,19 +355,20 @@ export class Track extends React.Component<IProps> {
     /**
      * creates a region (KEYFRAME.TSX stuff). 
      */
-    createRegion = (position: number) => {
-        let regiondata = KeyframeFunc.defaultKeyframe();
-        regiondata.position = position;
-        let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, regiondata, this.regions);
-
-        if (rightRegion && rightRegion.position - regiondata.position <= 4000) {
-            regiondata.duration = rightRegion.position - regiondata.position;
-        }
-        if (this.regions.length === 0 || !rightRegion || (rightRegion && rightRegion.position - regiondata.position >= NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut))) {
-            this.regions.push(regiondata);
-            return regiondata;
+    createRegion = async (time: number) => {
+        if (await this.findRegion(time) === undefined){  //check if there is a region where double clicking (prevents phantom regions)
+            let regiondata = KeyframeFunc.defaultKeyframe(); //create keyframe data
+            regiondata.position = time; //set position
+            let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, regiondata, this.regions);
+    
+            if (rightRegion && rightRegion.position - regiondata.position <= 4000) { //edge case when there is less than default 4000 duration space between this and right region
+                regiondata.duration = rightRegion.position - regiondata.position;
+            }
+            if (this.regions.length === 0 || !rightRegion || (rightRegion && rightRegion.position - regiondata.position >= NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut))) {
+                this.regions.push(regiondata);
+                return regiondata;
+            }
         }
-
     }
 
 
-- 
cgit v1.2.3-70-g09d2


From 04defabf37c5d3d9165c0ce07fefa43050e70584 Mon Sep 17 00:00:00 2001
From: Andrew Kim <andrewdkim@users.noreply.github.com>
Date: Wed, 15 Jan 2020 01:38:06 +0900
Subject: autokeyframe still doesn't work

---
 src/client/views/animationtimeline/Keyframe.tsx | 103 +-----------------------
 src/client/views/animationtimeline/Timeline.tsx |   2 +-
 src/client/views/animationtimeline/Track.tsx    |  50 ++++++------
 3 files changed, 28 insertions(+), 127 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 5e4676f56..2f2639c76 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -9,7 +9,6 @@ import { Cast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new_fields/Schema";
 import { Transform } from "../../util/Transform";
-import { InkField, StrokeData } from "../../../new_fields/InkField";
 import { TimelineMenu } from "./TimelineMenu";
 import { Docs } from "../../documents/Documents";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
@@ -172,7 +171,6 @@ interface IProps {
     check: string;
     changeCurrentBarX: (x: number) => void;
     transform: Transform;
-    checkCallBack: (visible: boolean) => void;
 }
 
 
@@ -214,17 +212,7 @@ export class Keyframe extends React.Component<IProps> {
     @computed private get pixelDuration() { return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed private get pixelFadeIn() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed private get pixelFadeOut() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
-    @computed
-    private get inks() {
-        if (this.props.collection.data_ext) {
-            let data_ext = Cast(this.props.collection.data_ext, Doc) as Doc;
-            let ink = Cast(data_ext.ink, InkField) as InkField;
-            if (ink) {
-                return ink.inkData;
-            }
-        }
-    }
-
+   
     componentWillMount() {
         runInAction(async () => {
             if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();
@@ -418,12 +406,6 @@ export class Keyframe extends React.Component<IProps> {
      */
     @action
     makeRegionMenu = (kf: Doc, e: MouseEvent) => {
-        TimelineMenu.Instance.addItem("button", "Add Ease", () => {
-            this.onContainerDown(kf, "interpolate");
-        }),
-            TimelineMenu.Instance.addItem("button", "Add Path", () => {
-                this.onContainerDown(kf, "path");
-            }),
             TimelineMenu.Instance.addItem("button", "Remove Region", () => {
                 runInAction(() => {
                     this.regions.splice(this.regions.indexOf(this.props.RegionData), 1);
@@ -525,88 +507,7 @@ export class Keyframe extends React.Component<IProps> {
         div.style.opacity = "0";
         Doc.UnBrushDoc(this.props.node);
     }
-
-
-    private _reac: (undefined | IReactionDisposer) = undefined;
-    private _plotList: ([string, StrokeData] | undefined) = undefined;
-    private _interpolationKeyframe: (Doc | undefined) = undefined;
-    private _type: string = "";
-
-
-    /**
-     * Need to fix this. skip
-     */
-    @action
-    onContainerDown = (kf: Doc, type: string) => {
-        let listenerCreated = false;
-        this.props.checkCallBack(true);
-        this._type = type;
-        this.props.collection.backgroundColor = "rgb(0,0,0)";
-        this._reac = reaction(() => {
-            return this.inks;
-        }, data => {
-            if (!listenerCreated) {
-                this._plotList = Array.from(data!)[data!.size - 1]!;
-                this._interpolationKeyframe = kf;
-                listenerCreated = true;
-                const reac = reaction(() => {
-                    return this.props.check;
-                }, () => {
-                    if (this.props.check === "yes") this.onReactionListen();
-                    reac();
-                    this.props.checkCallBack(false);
-                });
-            }
-        });
-    }
-
-    /**
-     * for custom draw interpolation. Need to be refactored
-     */
-    @action
-    onReactionListen = () => {
-        if (this._reac && this._plotList && this._interpolationKeyframe) {
-            this.props.collection.backgroundColor = "#FFF";
-            this._reac();
-            let xPlots = new List<number>();
-            let yPlots = new List<number>();
-            let maxY = 0;
-            let minY = Infinity;
-            let pathData = this._plotList![1].pathData;
-            for (let i = 0; i < pathData.length - 1;) {
-                let val = pathData[i];
-                if (val.y > maxY) {
-                    maxY = val.y;
-                }
-                if (val.y < minY) {
-                    minY = val.y;
-                }
-                xPlots.push(val.x);
-                yPlots.push(val.y);
-                let increment = Math.floor(pathData.length / this._gain);
-                if (pathData.length > this._gain) {
-                    if (i + increment < pathData.length) {
-                        i = i + increment;
-                    } else {
-                        i = pathData.length - 1;
-                    }
-                } else {
-                    i++;
-                }
-            }
-            let index = this.keyframes.indexOf(this._interpolationKeyframe!);
-            if (this._type === "interpolate") {
-                (Cast(this.regiondata.functions![index], Doc) as Doc).interpolationX = xPlots;
-                (Cast(this.regiondata.functions![index], Doc) as Doc).interpolationY = yPlots;
-            } else if (this._type === "path") {
-                (Cast(this.regiondata.functions![index], Doc) as Doc).pathX = xPlots;
-                (Cast(this.regiondata.functions![index], Doc) as Doc).pathY = yPlots;
-            }
-            this._reac = undefined;
-            this._interpolationKeyframe = undefined;
-            this._plotList = undefined;
-        }
-    }
+  
 
     ///////////////////////UI STUFF /////////////////////////
 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index df25f709a..fedffe8c1 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -508,7 +508,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                                     <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div>
                                 </div>
                                 <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
-                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} checkCallBack={this.checkCallBack} />)}
+                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} />)}
                                 </div>
                             </div>
                             <div key="timeline_title" className="title-container" ref={this._titleContainer}>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index c27a24ecf..fc8d0852f 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -1,6 +1,6 @@
 import * as React from "react";
 import { observer } from "mobx-react";
-import { observable, reaction, action, IReactionDisposer, computed, runInAction, autorun , toJS} from "mobx";
+import { observable, reaction, action, IReactionDisposer, computed, runInAction, autorun , toJS, isObservableArray, IObservableArray} from "mobx";
 import "./Track.scss";
 import { Doc, DocListCastAsync, DocListCast, Field } from "../../../new_fields/Doc";
 import { listSpec } from "../../../new_fields/Schema";
@@ -22,8 +22,6 @@ interface IProps {
     timelineVisible: boolean;
     check: string;
     changeCurrentBarX: (x: number) => void;
-    checkCallBack: (visible: boolean) => void;
-
 }
 
 @observer
@@ -58,18 +56,6 @@ export class Track extends React.Component<IProps> {
         "zIndex"
     ];
 
-    private whiteList = [
-        "data", 
-        "height", 
-        "opacity", 
-        "width", 
-        "x", 
-        "y"
-    ]
-
-    @observable private whitelist = [
-
-    ]; 
     private readonly MAX_TITLE_HEIGHT = 75; 
     private _trackHeight = 0;
 
@@ -143,24 +129,38 @@ export class Track extends React.Component<IProps> {
         this._isOnKeyframe = false;
     }
 
+
+    private whitelist = [
+        "x", 
+        "y", 
+        "width", 
+        "height", 
+        "data"
+    ]
     /**
      * autocreates keyframe
      */
     @action 
-    autoCreateKeyframe = async () => {
-        return reaction(() => [this.props.node.data, this.props.node.height, this.props.node.width, this.props.node.x, this.props.node.y, this.props.node.opacity], async changed => {            
-            console.log("RAN!"); 
+    autoCreateKeyframe = async () => {        
+        return reaction(async () => {
+            return this.whitelist.map(key => this.props.node[key]);
+        }, (changed, reaction) => {            
             //convert scrubber pos(pixel) to time
             let time = KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement); 
             //check for region 
-            let region:(Doc | undefined) = await this.findRegion(time); 
-            if (region !== undefined){ //if region at scrub time exist
-                if (DocListCast(region!.keyframes).find(kf => {return kf.time === time}) === undefined ){
-                   console.log("change has occured");
-                } 
-            }
+            //let region:(Doc | undefined) = await this.findRegion(time); 
+            console.log(this.props.node.x);
+            console.log(this.props.node.y); 
+            console.log(changed);  
             
+            // if (region !== undefined){ //if region at scrub time exist
+            //     if (DocListCast(region!.keyframes).find(kf => {return kf.time === time}) === undefined ){
+            //        console.log("change has occured");
+            //     } 
+            // }
+            //reaction.dispose(); 
         });
+        
     }
 
     /**
@@ -185,7 +185,7 @@ export class Track extends React.Component<IProps> {
             let regiondata: (Doc | undefined) = await this.findRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
             if (regiondata) {
                 this.props.node.hidden = false;
-                await this.timeChange(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
+                //await this.timeChange(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
             } else {
                 this.props.node.hidden = true;
                 this.props.node.opacity = 0;
-- 
cgit v1.2.3-70-g09d2


From b481a3a3d95a7481c785373b9a088c442488dfde Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 14 Jan 2020 17:27:26 -0500
Subject: initial stylistic changes

---
 src/client/views/animationtimeline/Timeline.scss   |  30 +++--
 src/client/views/animationtimeline/Timeline.tsx    |  18 +--
 .../views/animationtimeline/TimelineOverview.scss  | 138 +++++++++++----------
 3 files changed, 97 insertions(+), 89 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 76c8475d1..83988e324 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -1,6 +1,6 @@
 @import "./../globalCssVariables.scss";
 
-
+$timelineColor: #9acedf;
 
 .timeline-toolbox {
     position: absolute;
@@ -13,6 +13,10 @@
     align-items: center;
     top: 20px;
 
+    .timeline-icon {
+        color: $timelineColor;
+    }
+
     div {
         padding: 0px;
         margin-left: 10px;
@@ -24,7 +28,7 @@
         width: auto;
         white-space: nowrap;
         font-size: 16px;
-        color: grey;
+        color: black;
         letter-spacing: 2px;
         text-transform: uppercase;
     }
@@ -33,7 +37,7 @@
         height: 40px;
         width: 80px;
         background-color: white;
-        border: 2px solid grey;
+        border: 2px solid black;
         border-radius: 20px;
         animation-fill-mode: forwards;
         animation-duration: 500ms;
@@ -50,7 +54,7 @@
             height: 35px;
             width: 35px;
             background-color: white;
-            border: 1px solid grey;
+            border: 1px solid black;
             border-radius: 20px;
             transition: transform 500ms ease-in-out;
             margin-left: 0px;
@@ -65,7 +69,7 @@
     width: 120px;
     white-space: nowrap;
     font-size: 16px;
-    color: grey;
+    color: black;
     letter-spacing: 2px;
     text-transform: uppercase;
     padding-left: 5px;
@@ -112,13 +116,13 @@
             pointer-events: none;
 
             .scrubberhead {
-                top: -30px;
-                height: 30px;
-                width: 30px;
-                background-color: transparent;
+                top: -20px;
+                height: 20px;
+                width: 20px;
+                background-color: white;
                 border-radius: 50%;
-                border: 5px solid black;
-                left: -15px;
+                border: 3px solid black;
+                left: -9px;
                 position: absolute;
                 pointer-events: all;
             }
@@ -132,7 +136,7 @@
             overflow: hidden;
             background-color: white;
             position: absolute;
-            box-shadow: -10px 0px 10px 10px grey;
+            // box-shadow: -10px 0px 10px 10px red;
         }
 
     }
@@ -156,7 +160,7 @@
             float: left;
             border-style: solid;
             overflow-y: scroll;
-            overflow-x: hidden; 
+            overflow-x: hidden;
         }
     }
 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index fedffe8c1..589470111 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -8,7 +8,7 @@ import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlayCircle, faBackward, faForward, faGripLines,faPauseCircle, faEyeSlash,faEye,faCheckCircle, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
+import { faPlayCircle, faBackward, faForward, faGripLines, faPauseCircle, faEyeSlash, faEye, faCheckCircle, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
 import { ContextMenu } from "../ContextMenu";
 import { TimelineOverview } from "./TimelineOverview";
 import { FieldViewProps } from "../nodes/FieldView";
@@ -43,14 +43,14 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     //readonly constants
     private readonly DEFAULT_TICK_SPACING: number = 50;
-    private readonly MAX_TITLE_HEIGHT = 75; 
+    private readonly MAX_TITLE_HEIGHT = 75;
     private readonly MAX_CONTAINER_HEIGHT: number = 800;
     private readonly DEFAULT_TICK_INCREMENT: number = 1000;
 
     //height variables
     private DEFAULT_CONTAINER_HEIGHT: number = 330;
     private MIN_CONTAINER_HEIGHT: number = 205;
-    
+
     //react refs
     @observable private _trackbox = React.createRef<HTMLDivElement>();
     @observable private _titleContainer = React.createRef<HTMLDivElement>();
@@ -224,7 +224,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         e.stopPropagation();
         let scrubberbox = this._infoContainer.current!;
         let left = scrubberbox.getBoundingClientRect().left;
-        let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale; 
+        let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
         this.changeCurrentBarX(offsetX + this._visibleStart); //changes scrubber to clicked scrubber position
     }
 
@@ -403,9 +403,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         let size = 40 * scale; //50 is default
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
-                <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px`, color: "grey" }} /> </div>
-                <div key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px`, color: "grey" }} /> </div>
-                <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px`, color: "grey" }} /> </div>
+                <div className="timeline-icon" key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
+                <div className="timeline-icon" key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
+                <div className="timeline-icon" key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
                 <div key="overview-text" className="animation-text">Timeline Overview</div>
                 <TimelineOverview isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
                 <div key="animation-text" className="animation-text">Mode: {this.props.Document.isATOn ? "Authoring" : "Play"}</div>
@@ -460,7 +460,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             roundToggle.style.transform = "translate(45px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
-            roundToggleContainer.style.backgroundColor = "green";
+            roundToggleContainer.style.backgroundColor = "#9acedf";
             timelineContainer.style.top = "0px";
             this.props.Document.isATOn = true;
         }
@@ -499,7 +499,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     render() {
         return (
             <div>
-                <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}> 
+                <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
                     <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
                         <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
                             <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index c7f9bd059..c643b978b 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -1,85 +1,89 @@
-@import "./../globalCssVariables.scss"; 
+@import "./../globalCssVariables.scss";
 
+$timelineColor: #9acedf;
 
-.timeline-overview-container{ 
-    padding: 0px; 
-    margin: 0px; 
-    width: 300px; 
+.timeline-overview-container {
+    padding: 0px;
+    margin: 0px;
+    width: 300px;
     height: 40px;
-    background: white; 
-    position: relative; 
-    border: 2px solid black; 
-    
-    .timeline-overview-visible{
-        position: absolute; 
-        height: 100%; 
-        background: green; 
+    background: white;
+    position: relative;
+    border: 2px solid black;
+
+    .timeline-overview-visible {
+        position: absolute;
+        height: 98%;
+        background: $timelineColor;
         display: inline-block;
-        margin: 0px; 
-        padding: 0px; 
+        margin: 0px;
+        padding: 0px;
     }
-    .timeline-overview-scrubber-container{   
-        margin: 0px; 
-        padding: 0px; 
-        position: absolute; 
+
+    .timeline-overview-scrubber-container {
+        margin: 0px;
+        padding: 0px;
+        position: absolute;
         height: 100%;
-        width: 2px; 
-        top: 0px; 
-        left: 0px; 
+        width: 2px;
+        top: 0px;
+        left: 0px;
         z-index: 1001;
-        background-color:black; 
-        display: inline-block; 
+        background-color: black;
+        display: inline-block;
 
-        .timeline-overview-scrubber-head{   
-            padding: 0px; 
-            margin: 0px; 
-            position:absolute; 
-            height: 30px; 
-            width: 30px;
-            background-color:transparent; 
-            border-radius: 50%; 
-            border: 5px solid black; 
-            left: -15px;
-            top: -30px; 
+        .timeline-overview-scrubber-head {
+            padding: 0px;
+            margin: 0px;
+            position: absolute;
+            height: 10px;
+            width: 10px;
+            // background-color: black;
+            border-radius: 50%;
+            // border: 3px solid black;
+            left: -4px;
+            // top: -30px;
+            top: -10px;
         }
     }
 }
 
 
 
-.timeline-play-bar{
-    position: relative; 
-    padding: 0px; 
-    margin: 0px; 
-    width: 300px; 
-    height: 4px; 
-    background-color: grey;
+.timeline-play-bar {
+    position: relative;
+    padding: 0px;
+    margin: 0px;
+    width: 300px;
+    height: 4px;
+    background-color: $timelineColor;
     border-radius: 20px;
-    cursor: pointer; 
-    
-    .timeline-play-head{
-        position: absolute; 
-        padding: 0px; 
-        margin: 0px; 
-        width: 20px; 
-        height: 20px; 
-        border-radius: 50%; 
-        background-color: white; 
-        border: 3px grey solid; 
-        left: 0px; 
-        top: -10px; 
-        cursor: pointer; 
+    cursor: pointer;
+
+    .timeline-play-head {
+        position: absolute;
+        padding: 0px;
+        margin: 0px;
+        width: 20px;
+        height: 20px;
+        border-radius: 50%;
+        background-color: white;
+        border: 3px $timelineColor;
+        left: 0px;
+        top: -10px;
+        cursor: pointer;
     }
-}  
-.timeline-play-tail{
-    position: absolute; 
-    padding: 0px; 
-    margin: 0px; 
-    height: 4px; 
-    width: 0px;   
-    z-index: 1000; 
-    background-color: green;
+}
+
+.timeline-play-tail {
+    position: absolute;
+    padding: 0px;
+    margin: 0px;
+    height: 4px;
+    width: 0px;
+    z-index: 1000;
+    background-color: $timelineColor;
     border-radius: 20px;
-    margin-top: -4px; 
-    cursor: pointer; 
+    margin-top: -4px;
+    cursor: pointer;
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 95e321930a5e6f5a6fd86047542615dff49813f2 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 14 Jan 2020 19:35:47 -0500
Subject: color fixes

---
 src/client/views/animationtimeline/Timeline.scss         | 9 ++++++++-
 src/client/views/animationtimeline/Timeline.tsx          | 4 ++--
 src/client/views/animationtimeline/TimelineOverview.scss | 6 +++---
 3 files changed, 13 insertions(+), 6 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 83988e324..060627c17 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -54,7 +54,7 @@ $timelineColor: #9acedf;
             height: 35px;
             width: 35px;
             background-color: white;
-            border: 1px solid black;
+            border: 3px solid black;
             border-radius: 20px;
             transition: transform 500ms ease-in-out;
             margin-left: 0px;
@@ -80,6 +80,13 @@ $timelineColor: #9acedf;
     height: 100%;
     width: 1px;
     background-color: black;
+    color: black;
+}
+
+.number-label {
+    color: black;
+    padding-left: 5px;
+
 }
 
 .timeline-container {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 589470111..2332b4d5f 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -131,7 +131,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     drawTicks = () => {
         let ticks = [];
         for (let i = 0; i < this._time / this._tickIncrement; i++) {
-            ticks.push(<div key={Utils.GenerateGuid()} className="tick" style={{ transform: `translate(${i * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(i * this._tickIncrement)}</p></div>);
+            ticks.push(<div key={Utils.GenerateGuid()} className="tick" style={{ transform: `translate(${i * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p className="number-label">{this.toReadTime(i * this._tickIncrement)}</p></div>);
         }
         return ticks;
     }
@@ -457,7 +457,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             timelineContainer.style.top = `${-this._containerHeight}px`;
             this.props.Document.isATOn = false;
         } else {
-            roundToggle.style.transform = "translate(45px, 0px)";
+            roundToggle.style.transform = "translate(40px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
             roundToggleContainer.style.backgroundColor = "#9acedf";
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index c643b978b..3517d3f39 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -38,7 +38,7 @@ $timelineColor: #9acedf;
             position: absolute;
             height: 10px;
             width: 10px;
-            // background-color: black;
+            background-color: black;
             border-radius: 50%;
             // border: 3px solid black;
             left: -4px;
@@ -68,9 +68,9 @@ $timelineColor: #9acedf;
         height: 20px;
         border-radius: 50%;
         background-color: white;
-        border: 3px $timelineColor;
+        border: 3px solid $timelineColor;
         left: 0px;
-        top: -10px;
+        top: -8px;
         cursor: pointer;
     }
 }
-- 
cgit v1.2.3-70-g09d2


From da6ce86f604ad5a6e7857f073ebba0095fc5d467 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 14 Jan 2020 20:02:57 -0500
Subject: more minor changes

---
 src/client/views/animationtimeline/Timeline.scss | 20 ++++++++++++--------
 src/client/views/animationtimeline/Timeline.tsx  |  7 ++++---
 2 files changed, 16 insertions(+), 11 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 060627c17..02c1bdb16 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -1,6 +1,7 @@
 @import "./../globalCssVariables.scss";
 
 $timelineColor: #9acedf;
+$timelineDark: #77a1aa;
 
 .timeline-toolbox {
     position: absolute;
@@ -78,15 +79,15 @@ $timelineColor: #9acedf;
 
 .tick {
     height: 100%;
-    width: 1px;
+    width: 2px;
     background-color: black;
     color: black;
 }
 
 .number-label {
     color: black;
-    padding-left: 5px;
-
+    transform: rotate(-90deg) translate(-15px, 8px);
+    font-size: .85em;
 }
 
 .timeline-container {
@@ -94,7 +95,7 @@ $timelineColor: #9acedf;
     height: 300px;
     position: absolute;
     background-color: $light-color-secondary;
-    box-shadow: 0px 10px 20px;
+    border-bottom: 2px solid $timelineDark;
     transition: transform 500ms ease;
 
     .info-container {
@@ -139,7 +140,7 @@ $timelineColor: #9acedf;
             top: 30px;
             height: calc(100% - 30px);
             width: 100%;
-            border: 1px;
+            border: 2px solid black;
             overflow: hidden;
             background-color: white;
             position: absolute;
@@ -155,6 +156,9 @@ $timelineColor: #9acedf;
         width: 100px;
         background-color: white;
         overflow: hidden;
+        border-left: 2px solid black;
+        border-top: 2px solid black;
+        border-bottom: 2px solid black;
 
         .datapane {
             top: 0px;
@@ -172,10 +176,10 @@ $timelineColor: #9acedf;
     }
 
     .resize {
-        bottom: 5px;
+        bottom: 0px;
         position: absolute;
-        height: 30px;
-        width: 50px;
+        height: 20px;
+        width: 40px;
         left: calc(50% - 25px);
     }
 }
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 2332b4d5f..37d93f6c1 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -401,11 +401,12 @@ export class Timeline extends React.Component<FieldViewProps> {
      */
     private timelineToolBox = (scale: number) => {
         let size = 40 * scale; //50 is default
+        let iconSize = 25;
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
-                <div className="timeline-icon" key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
-                <div className="timeline-icon" key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
-                <div className="timeline-icon" key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${size}px`, width: `${size}px` }} /> </div>
+                <div className="timeline-icon" key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
+                <div className="timeline-icon" key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
+                <div className="timeline-icon" key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
                 <div key="overview-text" className="animation-text">Timeline Overview</div>
                 <TimelineOverview isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
                 <div key="animation-text" className="animation-text">Mode: {this.props.Document.isATOn ? "Authoring" : "Play"}</div>
-- 
cgit v1.2.3-70-g09d2


From 68a8c2bdbeafc7bc799884a6c1dcea86dbfd9f27 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Fri, 24 Jan 2020 15:04:59 -0500
Subject: change branch

---
 src/client/views/animationtimeline/Timeline.scss   |  92 ++++++++---
 src/client/views/animationtimeline/Timeline.tsx    |  88 ++++++++--
 .../views/animationtimeline/TimelineOverview.scss  |  29 ++--
 .../views/animationtimeline/TimelineOverview.tsx   | 180 ++++++++++++++-------
 4 files changed, 284 insertions(+), 105 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 02c1bdb16..a8dd9b9e7 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -10,39 +10,79 @@ $timelineDark: #77a1aa;
     display: flex;
     align-items: flex-start;
     flex-direction: row;
-    justify-content: space-evenly;
+    // justify-content: space-evenly;
     align-items: center;
-    top: 20px;
+    top: 3px;
+    width: 100%;
 
-    .timeline-icon {
-        color: $timelineColor;
+    .overview-tool {
+        display: flex;
+        justify-content: center;
     }
 
-    div {
-        padding: 0px;
+    .playbackControls {
+        display: flex;
+        margin-left: 30px;
+        max-width: 84px;
+        width: 84px;
+
+        .timeline-icon {
+            color: $timelineColor;
+            margin-left: 3px;
+        }
+
+    }
+
+    .grid-box {
+        display: grid;
+        grid-template-columns: [first] 50% [line2] 25% [line3] 25%;
+        width: calc(100% - 150px);
+        // width: 100%;
         margin-left: 10px;
+
+        .time-box {
+            margin-left: 5px;
+            display: flex;
+        }
+
+        .mode-box {
+            display: flex;
+            margin-left: 5px;
+        }
+
+        .overview-box {
+            width: 100%;
+            display: flex;
+        }
+
+        div {
+            padding: 0px;
+            // margin-left: 10px;
+        }
     }
 
     .animation-text {
-        font-size: 20px;
+        // font-size: 16px;
         height: auto;
         width: auto;
         white-space: nowrap;
-        font-size: 16px;
+        font-size: 14px;
         color: black;
         letter-spacing: 2px;
         text-transform: uppercase;
     }
 
     .round-toggle {
-        height: 40px;
-        width: 80px;
+        height: 20px;
+        width: 40px;
+        min-width: 40px;
         background-color: white;
-        border: 2px solid black;
+        border: 2px solid $timelineDark;
         border-radius: 20px;
         animation-fill-mode: forwards;
         animation-duration: 500ms;
         top: 30px;
+        margin-left: 5px;
 
         input {
             position: absolute;
@@ -52,29 +92,30 @@ $timelineDark: #77a1aa;
         }
 
         .round-toggle-slider {
-            height: 35px;
-            width: 35px;
+            height: 17px;
+            width: 17px;
             background-color: white;
-            border: 3px solid black;
-            border-radius: 20px;
+            border: 2px solid $timelineDark;
+            border-radius: 50%;
             transition: transform 500ms ease-in-out;
             margin-left: 0px;
-            margin-top: 0.5px;
+            // margin-top: 0.5px;
         }
     }
 
 }
 
 .time-input {
-    height: 40px;
-    width: 120px;
+    height: 20px;
+    // width: 120px;
+    width: 100%;
     white-space: nowrap;
-    font-size: 16px;
+    font-size: 12px;
     color: black;
     letter-spacing: 2px;
     text-transform: uppercase;
     padding-left: 5px;
-
+    margin-left: 5px;
 }
 
 .tick {
@@ -99,7 +140,7 @@ $timelineDark: #77a1aa;
     transition: transform 500ms ease;
 
     .info-container {
-        margin-top: 80px;
+        margin-top: 50px;
         right: 20px;
         position: absolute;
         height: calc(100% - 100px);
@@ -138,9 +179,12 @@ $timelineDark: #77a1aa;
 
         .trackbox {
             top: 30px;
+            // TODO: where is this 30px coming from?
             height: calc(100% - 30px);
+            // height: 100%;
             width: 100%;
-            border: 2px solid black;
+            border-top: 2px solid black;
+            border-bottom: 2px solid black;
             overflow: hidden;
             background-color: white;
             position: absolute;
@@ -150,7 +194,7 @@ $timelineDark: #77a1aa;
     }
 
     .title-container {
-        margin-top: 110px;
+        margin-top: 80px;
         margin-left: 20px;
         height: calc(100% - 100px - 30px);
         width: 100px;
@@ -159,6 +203,7 @@ $timelineDark: #77a1aa;
         border-left: 2px solid black;
         border-top: 2px solid black;
         border-bottom: 2px solid black;
+        border-right: 2px solid $timelineDark;
 
         .datapane {
             top: 0px;
@@ -181,6 +226,7 @@ $timelineDark: #77a1aa;
         height: 20px;
         width: 40px;
         left: calc(50% - 25px);
+        color: $timelineDark;
     }
 }
 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 37d93f6c1..e6201d431 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -3,7 +3,7 @@ import "./Timeline.scss";
 import { listSpec } from "../../../new_fields/Schema";
 import { observer } from "mobx-react";
 import { Track } from "./Track";
-import { observable, action, computed, runInAction } from "mobx";
+import { observable, action, computed, runInAction, IReactionDisposer, reaction } from "mobx";
 import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
@@ -77,6 +77,11 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _doubleClickEnabled = false;
     @observable private _titleHeight = 0;
 
+    // so a reaction can be made
+    @observable public _isAuthoring = this.props.Document.isATOn;
+    @observable private _resizeReaction?: IReactionDisposer;
+    @observable private _panelWidth = 0;
+
     /**
      * collection get method. Basically defines what defines collection's children. These will be tracked in the timeline. Do not edit. 
      */
@@ -114,6 +119,19 @@ export class Timeline extends React.Component<FieldViewProps> {
             this.props.Document.isATOn = !this.props.Document.isATOn; //turns the boolean on, saying AT (animation timeline) is on
             this.toggleHandle();
         });
+
+        this._resizeReaction = reaction(
+            () => this.props.PanelWidth,
+            () => {
+                // if (!this.props.parent._isAuthoring) {
+                // runInAction(() => {
+                console.log("resizing");
+                // this.setOverviewWidth();
+                // });
+                // }
+            },
+        );
+
     }
 
     componentWillUnmount() {
@@ -402,19 +420,58 @@ export class Timeline extends React.Component<FieldViewProps> {
     private timelineToolBox = (scale: number) => {
         let size = 40 * scale; //50 is default
         let iconSize = 25;
+
+        //decides if information should be omitted because the timeline is very small
+        // if its less than 950 pixels then it's going to be overlapping
+        let shouldCompress = false;
+        let width: number = this.props.PanelWidth();
+        if (width < 850) {
+            shouldCompress = true;
+        }
+
+        let modeString, overviewString, lengthString;
+        let modeType = this.props.Document.isATOn ? "Author" : "Play";
+
+        if (!shouldCompress) {
+            modeString = "Mode: " + modeType;
+            overviewString = "Overview:";
+            lengthString = "Length: ";
+        }
+        else {
+            modeString = modeType;
+            overviewString = "";
+            lengthString = "";
+        }
+
+
+        // let modeType: string = this.props.Document.isATOn ? "Author" : "Play";
+        // let modeString: string = "Mode: " + modeType;
+        // let overviewString: string = "Overview:";
+        // let lengthString: string = "Length: ";
+
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
-                <div className="timeline-icon" key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
-                <div className="timeline-icon" key=" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
-                <div className="timeline-icon" key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
-                <div key="overview-text" className="animation-text">Timeline Overview</div>
-                <TimelineOverview isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
-                <div key="animation-text" className="animation-text">Mode: {this.props.Document.isATOn ? "Authoring" : "Play"}</div>
-                <div key="round-toggle" ref={this._roundToggleContainerRef} className="round-toggle">
-                    <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
+                <div className="playbackControls">
+                    <div className="timeline-icon" key="timeline_windBack" onClick={this.windBackward} title="Slow Down Animation"> <FontAwesomeIcon icon={faBackward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
+                    <div className="timeline-icon" key=" timeline_play" onClick={this.onPlay} title="Play/Pause"> <FontAwesomeIcon icon={this._playButton} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
+                    <div className="timeline-icon" key="timeline_windForward" onClick={this.windForward} title="Speed Up Animation"> <FontAwesomeIcon icon={faForward} style={{ height: `${iconSize}px`, width: `${iconSize}px` }} /> </div>
+                </div>
+                <div className="grid-box overview-tool">
+                    <div className="overview-box">
+                        <div key="overview-text" className="animation-text">{overviewString}</div>
+                        <TimelineOverview parent={this} isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                    </div>
+                    <div className="mode-box overview-tool">
+                        <div key="animation-text" className="animation-text">{modeString}</div>
+                        <div key="round-toggle" ref={this._roundToggleContainerRef} className="round-toggle">
+                            <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
+                        </div>
+                    </div>
+                    <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
+                        <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }}>{lengthString}</div>
+                        <input className="time-input" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
+                    </div>
                 </div>
-                <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }}>Length: </div>
-                <input className="time-input" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }} placeholder={String(this._time) + "ms"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
             </div>
         );
     }
@@ -457,13 +514,15 @@ export class Timeline extends React.Component<FieldViewProps> {
             roundToggleContainer.style.backgroundColor = "white";
             timelineContainer.style.top = `${-this._containerHeight}px`;
             this.props.Document.isATOn = false;
+            this._isAuthoring = false;
         } else {
-            roundToggle.style.transform = "translate(40px, 0px)";
+            roundToggle.style.transform = "translate(20px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
             roundToggleContainer.style.backgroundColor = "#9acedf";
             timelineContainer.style.top = "0px";
             this.props.Document.isATOn = true;
+            this._isAuthoring = true;
         }
     }
 
@@ -498,6 +557,11 @@ export class Timeline extends React.Component<FieldViewProps> {
      * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
      */
     render() {
+        console.log(this.props.PanelWidth());
+        runInAction(() => {
+            this._panelWidth = this.props.PanelWidth();
+            console.log("changing!!")
+        });
         return (
             <div>
                 <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index 3517d3f39..a0b9d462b 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -1,23 +1,34 @@
 @import "./../globalCssVariables.scss";
 
 $timelineColor: #9acedf;
+$timelineDark: #77a1aa;
+
+.timelineOverview-bounding {
+    width: 100%;
+    margin-right: 10px;
+}
 
 .timeline-overview-container {
-    padding: 0px;
-    margin: 0px;
-    width: 300px;
-    height: 40px;
+    // padding: 0px;
+    margin-right: 5px;
+    // margin: 0px;
+    margin-left: 5px;
+    // width: 300px;
+    width: 100%;
+    height: 25px;
     background: white;
     position: relative;
-    border: 2px solid black;
+    border: 2px solid $timelineDark;
+    // width: 100%;
 
     .timeline-overview-visible {
         position: absolute;
-        height: 98%;
+        height: 21px;
         background: $timelineColor;
         display: inline-block;
         margin: 0px;
         padding: 0px;
+        // top: 1px;
     }
 
     .timeline-overview-scrubber-container {
@@ -38,9 +49,9 @@ $timelineColor: #9acedf;
             position: absolute;
             height: 10px;
             width: 10px;
-            background-color: black;
+            background-color: white;
             border-radius: 50%;
-            // border: 3px solid black;
+            border: 2px solid black;
             left: -4px;
             // top: -30px;
             top: -10px;
@@ -54,7 +65,7 @@ $timelineColor: #9acedf;
     position: relative;
     padding: 0px;
     margin: 0px;
-    width: 300px;
+    width: 100%;
     height: 4px;
     background-color: $timelineColor;
     border-radius: 20px;
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 4741969dc..4907a1ae1 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -1,101 +1,159 @@
-import * as React from "react"; 
-import {observable, action} from "mobx"; 
-import {observer} from "mobx-react";
-import "./TimelineOverview.scss"; 
+import * as React from "react";
+import { observable, action, computed, runInAction, reaction, IReactionDisposer } from "mobx";
+import { observer } from "mobx-react";
+import "./TimelineOverview.scss";
+import * as $ from 'jquery';
+import { Timeline } from "./Timeline";
 
 
-
-interface TimelineOverviewProps{
-    totalLength: number; 
-    visibleLength:number; 
-    visibleStart:number;
-    currentBarX:number;
-    isAuthoring: boolean;  
-    changeCurrentBarX: (pixel:number) => void; 
-    movePanX: (pixel:number) => any;
+interface TimelineOverviewProps {
+    totalLength: number;
+    visibleLength: number;
+    visibleStart: number;
+    currentBarX: number;
+    isAuthoring: boolean;
+    parent: Timeline;
+    changeCurrentBarX: (pixel: number) => void;
+    movePanX: (pixel: number) => any;
 }
 
 
 @observer
 export class TimelineOverview extends React.Component<TimelineOverviewProps>{
-    @observable private _visibleRef = React.createRef<HTMLDivElement>(); 
-    @observable private _scrubberRef = React.createRef<HTMLDivElement>(); 
-    private readonly DEFAULT_HEIGHT = 50; 
-    private readonly DEFAULT_WIDTH = 300; 
+    @observable private _visibleRef = React.createRef<HTMLDivElement>();
+    @observable private _scrubberRef = React.createRef<HTMLDivElement>();
+    @observable private overviewBarWidth: number = 0;
+    @observable private _authoringReaction?: IReactionDisposer;
+    @observable private _resizeReaction?: IReactionDisposer;
+    private readonly DEFAULT_HEIGHT = 50;
+    private readonly DEFAULT_WIDTH = 300;
+
+    componentDidMount = () => {
+        this.setOverviewWidth();
+
+        this._authoringReaction = reaction(
+            () => this.props.parent._isAuthoring,
+            () => {
+                if (!this.props.parent._isAuthoring) {
+                    runInAction(() => {
+                        this.setOverviewWidth();
+                    });
+                }
+            },
+        );
+        // this._resizeReaction = reaction(
+        //     () => this.props.parent.props.PanelWidth,
+        //     () => {
+        //         // if (!this.props.parent._isAuthoring) {
+        //         // runInAction(() => {
+        //         console.log("resizing");
+        //         this.setOverviewWidth();
+        //         // });
+        //         // }
+        //     },
+        // );
+    }
+
+    componentWillUnmount = () => {
+        this._authoringReaction && this._authoringReaction();
+        this._resizeReaction && this._resizeReaction();
+    }
 
     @action
-    onPointerDown = (e:React.PointerEvent) => {
-        e.stopPropagation(); 
-        e.preventDefault(); 
-        document.removeEventListener("pointermove", this.onPanX); 
-        document.removeEventListener("pointerup", this.onPointerUp); 
-        document.addEventListener("pointermove", this.onPanX); 
-        document.addEventListener("pointerup", this.onPointerUp); 
+    setOverviewWidth() {
+        let width = $("#timelineOverview").width();
+        if (width) this.overviewBarWidth = width;
+        else this.overviewBarWidth = 0;
+    }
+
+    @action
+    onPointerDown = (e: React.PointerEvent) => {
+        e.stopPropagation();
+        e.preventDefault();
+        document.removeEventListener("pointermove", this.onPanX);
+        document.removeEventListener("pointerup", this.onPointerUp);
+        document.addEventListener("pointermove", this.onPanX);
+        document.addEventListener("pointerup", this.onPointerUp);
     }
 
     @action
     onPanX = (e: PointerEvent) => {
-        e.stopPropagation(); 
-        e.preventDefault(); 
-        let movX = (this.props.visibleStart / this.props.totalLength)* (this.DEFAULT_WIDTH) + e.movementX; 
-        this.props.movePanX((movX / (this.DEFAULT_WIDTH )) * this.props.totalLength); 
+        e.stopPropagation();
+        e.preventDefault();
+        let movX = (this.props.visibleStart / this.props.totalLength) * (this.DEFAULT_WIDTH) + e.movementX;
+        // let movX = (this.props.visibleStart / this.props.totalLength) * (this.overviewWidth) + e.movementX;
+        this.props.movePanX((movX / (this.DEFAULT_WIDTH)) * this.props.totalLength);
+        // this.props.movePanX((movX / (this.overviewWidth) * this.props.totalLength);
+
+        // console.log(this.props.totalLength);
     }
 
     @action
     onPointerUp = (e: PointerEvent) => {
-        e.stopPropagation(); 
-        e.preventDefault(); 
-        document.removeEventListener("pointermove", this.onPanX); 
-        document.removeEventListener("pointerup", this.onPointerUp); 
+        e.stopPropagation();
+        e.preventDefault();
+        document.removeEventListener("pointermove", this.onPanX);
+        document.removeEventListener("pointerup", this.onPointerUp);
     }
 
     @action
-    onScrubberDown = ( e:React.PointerEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
-        document.removeEventListener("pointermove", this.onScrubberMove); 
-        document.removeEventListener("pointerup", this.onScrubberUp); 
-        document.addEventListener("pointermove", this.onScrubberMove); 
+    onScrubberDown = (e: React.PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        document.removeEventListener("pointermove", this.onScrubberMove);
+        document.removeEventListener("pointerup", this.onScrubberUp);
+        document.addEventListener("pointermove", this.onScrubberMove);
         document.addEventListener("pointerup", this.onScrubberUp);
     }
 
     @action
     onScrubberMove = (e: PointerEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
-        let scrubberRef = this._scrubberRef.current!; 
-        let left = scrubberRef.getBoundingClientRect().left; 
-        let offsetX = Math.round(e.clientX - left); 
-        this.props.changeCurrentBarX((offsetX / (this.DEFAULT_WIDTH) * this.props.totalLength) + this.props.currentBarX); 
+        e.preventDefault();
+        e.stopPropagation();
+        let scrubberRef = this._scrubberRef.current!;
+        let left = scrubberRef.getBoundingClientRect().left;
+        let offsetX = Math.round(e.clientX - left);
+        this.props.changeCurrentBarX((offsetX / (this.DEFAULT_WIDTH) * this.props.totalLength) + this.props.currentBarX);
     }
 
     @action
-    onScrubberUp = (e:PointerEvent) => {
-        e.preventDefault(); 
-        e.stopPropagation(); 
-        document.removeEventListener("pointermove", this.onScrubberMove); 
+    onScrubberUp = (e: PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+        document.removeEventListener("pointermove", this.onScrubberMove);
         document.removeEventListener("pointerup", this.onScrubberUp);
     }
 
-    render(){
+    render() {
+        // calculates where everything should fall based on its size
+        let percentVisible = this.props.visibleLength / this.props.totalLength;
+        let visibleBarWidth = percentVisible * this.overviewBarWidth;
+
+        let percentScrubberStart = this.props.currentBarX / this.props.totalLength;
+        let scrubberStart = percentScrubberStart * this.overviewBarWidth;
+
+        let percentBarStart = this.props.visibleStart / this.props.totalLength;
+        let barStart = percentBarStart * this.overviewBarWidth;
+
         let timeline = this.props.isAuthoring ? [
-            <div key="timeline-overview-container" className="timeline-overview-container">
-                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{left:`${(Math.round(this.props.visibleStart) / Math.round(this.props.totalLength)) * 296}px`, width:`${(Math.round(this.props.visibleLength) / Math.round(this.props.totalLength)) * 296}px`}} onPointerDown={this.onPointerDown}></div>,
-                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{left:`${(this.props.currentBarX / this.props.totalLength) * 294}px`}} onPointerDown={this.onScrubberDown}>
+
+            <div key="timeline-overview-container" className="timeline-overview-container" id="timelineOverview">
+                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>,
+                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}>
                     <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
-                </div>            
+                </div>
             </div>
         ] : [
-            <div className="timeline-play-bar">
-                <div ref={this._scrubberRef} className="timeline-play-head" style={{left:`${(this.props.currentBarX / this.props.totalLength) * 294}px`}} onPointerDown={this.onScrubberDown}></div>
-            </div>,
-            <div className="timeline-play-tail" style={{width: `${(this.props.currentBarX / this.props.totalLength) * 294}px`}}></div>
-        ]; 
-        return(
-            <div>
+                <div className="timeline-play-bar">
+                    <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${(this.props.currentBarX / this.props.totalLength) * 294}px` }} onPointerDown={this.onScrubberDown}></div>
+                </div>,
+                <div className="timeline-play-tail" style={{ width: `${(this.props.currentBarX / this.props.totalLength) * 294}px` }}></div>
+            ];
+        return (
+            <div className="timelineOverview-bounding">
                 {timeline}
             </div>
-        ); 
+        );
     }
 
 }
-- 
cgit v1.2.3-70-g09d2


From 2320240229cd8e89e8f5abe917053caad7bf38c2 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sat, 1 Feb 2020 13:50:32 -0500
Subject: overveiw resize

---
 src/client/views/animationtimeline/Timeline.tsx        | 18 ++++++++++++++++--
 .../views/animationtimeline/TimelineOverview.tsx       |  4 ++++
 2 files changed, 20 insertions(+), 2 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index e6201d431..8b943f209 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -449,6 +449,9 @@ export class Timeline extends React.Component<FieldViewProps> {
         // let overviewString: string = "Overview:";
         // let lengthString: string = "Length: ";
 
+        console.log("visible: " + this._visibleLength)
+        console.log("total: " + this._totalLength)
+
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
                 <div className="playbackControls">
@@ -459,7 +462,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                 <div className="grid-box overview-tool">
                     <div className="overview-box">
                         <div key="overview-text" className="animation-text">{overviewString}</div>
-                        <TimelineOverview parent={this} isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                        <TimelineOverview panelWidth={this._panelWidth} parent={this} isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
                     </div>
                     <div className="mode-box overview-tool">
                         <div key="animation-text" className="animation-text">{modeString}</div>
@@ -551,17 +554,28 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     }
 
+    @action.bound
+    changeLenths() {
+        if (this._infoContainer.current) {
+            this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; //the visible length of the timeline (the length that you current see)
+            this._visibleStart = this._infoContainer.current!.scrollLeft; //where the div starts
+        }
+    }
+
 
     /**
      * if you have any question here, just shoot me an email or text. 
      * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
      */
     render() {
-        console.log(this.props.PanelWidth());
+        // console.log(this.props.PanelWidth());
         runInAction(() => {
             this._panelWidth = this.props.PanelWidth();
+            this.changeLenths();
             console.log("changing!!")
         });
+
+        // change visible and total width
         return (
             <div>
                 <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 4907a1ae1..caa97bb70 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -15,6 +15,7 @@ interface TimelineOverviewProps {
     parent: Timeline;
     changeCurrentBarX: (pixel: number) => void;
     movePanX: (pixel: number) => any;
+    panelWidth: number;
 }
 
 
@@ -125,8 +126,11 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     }
 
     render() {
+
+        console.log("helo")
         // calculates where everything should fall based on its size
         let percentVisible = this.props.visibleLength / this.props.totalLength;
+        console.log(this.props.visibleLength)
         let visibleBarWidth = percentVisible * this.overviewBarWidth;
 
         let percentScrubberStart = this.props.currentBarX / this.props.totalLength;
-- 
cgit v1.2.3-70-g09d2


From 78810a40e22510eefe747c099e73fa3f2c4860a9 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sat, 1 Feb 2020 15:03:15 -0500
Subject: ui changes cl.ose to done

---
 src/client/views/animationtimeline/Keyframe.scss   | 138 ++++++++++-----------
 src/client/views/animationtimeline/Keyframe.tsx    |  79 ++++++------
 src/client/views/animationtimeline/Timeline.scss   |  24 ++--
 src/client/views/animationtimeline/Timeline.tsx    |  24 +---
 .../views/animationtimeline/TimelineOverview.tsx   |  51 ++++----
 src/client/views/animationtimeline/Track.tsx       |   2 +-
 6 files changed, 153 insertions(+), 165 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.scss b/src/client/views/animationtimeline/Keyframe.scss
index b1e8b0b65..8ff1c53f5 100644
--- a/src/client/views/animationtimeline/Keyframe.scss
+++ b/src/client/views/animationtimeline/Keyframe.scss
@@ -1,94 +1,94 @@
-@import "./../globalCssVariables.scss"; 
+@import "./../globalCssVariables.scss";
+
+
+$timelineColor: #9acedf;
+$timelineDark: #77a1aa;
 
 .bar {
     height: 100%;
     width: 5px;
     position: absolute;
-    
+
     // pointer-events: none; 
     .menubox {
-        width: 200px; 
-        height:200px;
+        width: 200px;
+        height: 200px;
         top: 50%;
-        position: relative; 
-        background-color: $light-color; 
-        .menutable{
-            tr:nth-child(odd){
-                background-color:$light-color-secondary;
+        position: relative;
+        background-color: $light-color;
+
+        .menutable {
+            tr:nth-child(odd) {
+                background-color: $light-color-secondary;
             }
         }
     }
 
-    .leftResize{
-        left:-12.5px; 
-        height:25px; 
-        width:25px; 
-        border-radius: 50%; 
-        background-color: white;
-        border:3px solid black;
-        top: calc(50% - 12.5px); 
-        z-index: 1000; 
-        position:absolute; 
+    .leftResize {
+        left: -10px;
+        border: 3px solid black;
+    }
+
+    .rightResize {
+        right: -10px;
+        border: 3px solid black;
     }
-    .rightResize{
-        right:-12.5px; 
-        height:25px; 
-        width:25px; 
-        border-radius: 50%; 
-        top:calc(50% - 12.5px); 
-        background-color:white; 
-        border:3px solid black;
-        z-index: 1000; 
-        position:absolute; 
+
+    .keyframe-indicator {
+        height: 20px;
+        width: 20px;
+        top: calc(50% - 10px);
+        background-color: white;
+        -ms-transform: rotate(45deg);
+        -webkit-transform: rotate(45deg);
+        transform: rotate(45deg);
+        z-index: 1000;
+        position: absolute;
     }
-    .fadeLeft{
-        left:0px; 
-        height:100%; 
-        position:absolute; 
-        pointer-events: none; 
-        background: linear-gradient(to left, #4d9900 10%,  $light-color);
+
+    .keyframeCircle {
+        left: -10px;
+        border: 3px solid $timelineDark;
     }
 
-    .fadeRight{
-        right:0px; 
-        height:100%; 
-        position:absolute; 
-        pointer-events: none; 
-        background: linear-gradient(to right, #4d9900 10%,  $light-color);
+    .fadeLeft {
+        left: 0px;
+        height: 100%;
+        position: absolute;
+        pointer-events: none;
+        background: linear-gradient(to left, $timelineColor 10%, $light-color);
     }
-    .divider{
-        height:100%; 
-        width: 1px; 
-        position: absolute; 
-        background-color:black; 
-        cursor: col-resize; 
-        pointer-events:none; 
+
+    .fadeRight {
+        right: 0px;
+        height: 100%;
+        position: absolute;
+        pointer-events: none;
+        background: linear-gradient(to right, $timelineColor 10%, $light-color);
     }
-    .keyframe{
-        height:100%; 
-        position:absolute;
+
+    .divider {
+        height: 100%;
+        width: 1px;
+        position: absolute;
+        background-color: black;
+        cursor: col-resize;
+        pointer-events: none;
     }
-    .keyframeCircle{        
-        left:-15px;         
-        height:30px; 
-        width:30px; 
-        border-radius: 50%; 
-        top:calc(50% - 15px); 
-        background-color:white; 
-        border:3px solid green;
-        z-index: 1000; 
-        position:absolute; 
+
+    .keyframe {
+        height: 100%;
+        position: absolute;
     }
 
-    .fadeIn-container, .fadeOut-container, .body-container{
-        position:absolute; 
-        height:100%; 
+    .fadeIn-container,
+    .fadeOut-container,
+    .body-container {
+        position: absolute;
+        height: 100%;
         background-color: rgba(0, 0, 0, 0.5);
-        opacity: 0; 
+        opacity: 0;
     }
- 
-
-}
-    
 
 
+}
\ No newline at end of file
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 2f2639c76..9c486a6d6 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -93,11 +93,11 @@ export namespace KeyframeFunc {
         regiondata.fadeIn = 1000;
         regiondata.fadeOut = 1000;
         regiondata.functions = new List<Doc>();
-        regiondata.hasData = false; 
+        regiondata.hasData = false;
         return regiondata;
     };
 
-    export const makeKeyData = async (regiondata:RegionData, time: number, badNode:Doc, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time 
+    export const makeKeyData = async (regiondata: RegionData, time: number, badNode: Doc, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time 
         runInAction(async () => {
             let doclist = (await DocListCastAsync(regiondata.keyframes))!;
             let existingkf: (Doc | undefined) = undefined;
@@ -155,7 +155,7 @@ export const RegionDataSchema = createSchema({
     keyframes: listSpec(Doc),
     fadeIn: defaultSpec("number", 0),
     fadeOut: defaultSpec("number", 0),
-    functions: listSpec(Doc), 
+    functions: listSpec(Doc),
     hasData: defaultSpec("boolean", false)
 });
 export type RegionData = makeInterface<[typeof RegionDataSchema]>;
@@ -212,7 +212,7 @@ export class Keyframe extends React.Component<IProps> {
     @computed private get pixelDuration() { return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed private get pixelFadeIn() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed private get pixelFadeOut() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
-   
+
     componentWillMount() {
         runInAction(async () => {
             if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();
@@ -228,7 +228,7 @@ export class Keyframe extends React.Component<IProps> {
         });
     }
 
-    
+
 
 
     @action
@@ -313,10 +313,10 @@ export class Keyframe extends React.Component<IProps> {
         } else if (NumCast(this.keyframes[1].time) + offset >= NumCast(this.keyframes[2].time)) {
             this.regiondata.position = NumCast(this.keyframes[2].time) - this.regiondata.fadeIn;
             this.regiondata.duration = NumCast(this.keyframes[this.keyframes.length - 1].time) - NumCast(this.keyframes[2].time) + this.regiondata.fadeIn;
-        } else if (NumCast(this.keyframes[0].time) + offset <= 0){
-            this.regiondata.position = 0; 
-            this.regiondata.duration = NumCast(this.keyframes[this.keyframes.length - 1].time); 
-        }else {
+        } else if (NumCast(this.keyframes[0].time) + offset <= 0) {
+            this.regiondata.position = 0;
+            this.regiondata.duration = NumCast(this.keyframes[this.keyframes.length - 1].time);
+        } else {
             this.regiondata.duration -= offset;
             this.regiondata.position += offset;
         }
@@ -353,9 +353,9 @@ export class Keyframe extends React.Component<IProps> {
         if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
             let position = this.regiondata.position;
             await KeyframeFunc.makeKeyData(this.regiondata, Math.round(position + offset), this.props.node);
-            this.regiondata.hasData = true; 
+            this.regiondata.hasData = true;
             this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied
-        
+
         }
     }
 
@@ -386,15 +386,15 @@ export class Keyframe extends React.Component<IProps> {
             }),
             TimelineMenu.Instance.addItem("input", "Move", (val) => {
                 runInAction(() => {
-                        let cannotMove: boolean = false;
-                        let kfIndex: number = this.keyframes.indexOf(kf);
-                        if (val < 0 || (val < NumCast(this.keyframes[kfIndex - 1].time) || val > NumCast(this.keyframes[kfIndex + 1].time))) {
-                            cannotMove = true;
-                        }
-                        if (!cannotMove) {
-                            this.keyframes[kfIndex].time = parseInt(val, 10);
-                            this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn;
-                        }
+                    let cannotMove: boolean = false;
+                    let kfIndex: number = this.keyframes.indexOf(kf);
+                    if (val < 0 || (val < NumCast(this.keyframes[kfIndex - 1].time) || val > NumCast(this.keyframes[kfIndex + 1].time))) {
+                        cannotMove = true;
+                    }
+                    if (!cannotMove) {
+                        this.keyframes[kfIndex].time = parseInt(val, 10);
+                        this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn;
+                    }
                 });
             });
         TimelineMenu.Instance.addMenu("Keyframe");
@@ -406,22 +406,22 @@ export class Keyframe extends React.Component<IProps> {
      */
     @action
     makeRegionMenu = (kf: Doc, e: MouseEvent) => {
-            TimelineMenu.Instance.addItem("button", "Remove Region", () => {
-                runInAction(() => {
-                    this.regions.splice(this.regions.indexOf(this.props.RegionData), 1);
-                }
-                );
-            }),
+        TimelineMenu.Instance.addItem("button", "Remove Region", () => {
+            runInAction(() => {
+                this.regions.splice(this.regions.indexOf(this.props.RegionData), 1);
+            }
+            );
+        }),
             TimelineMenu.Instance.addItem("input", `fadeIn: ${this.regiondata.fadeIn}ms`, (val) => {
                 runInAction(() => {
-                        let cannotMove: boolean = false;
-                        if (val < 0 || val > NumCast(this.keyframes[2].time) - this.regiondata.position) {
-                            cannotMove = true;
-                        }
-                        if (!cannotMove) {
-                            this.regiondata.fadeIn = parseInt(val, 10);
-                            this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn;
-                        }
+                    let cannotMove: boolean = false;
+                    if (val < 0 || val > NumCast(this.keyframes[2].time) - this.regiondata.position) {
+                        cannotMove = true;
+                    }
+                    if (!cannotMove) {
+                        this.regiondata.fadeIn = parseInt(val, 10);
+                        this.keyframes[1].time = this.regiondata.position + this.regiondata.fadeIn;
+                    }
                 });
             }),
             TimelineMenu.Instance.addItem("input", `fadeOut: ${this.regiondata.fadeOut}ms`, (val) => {
@@ -507,7 +507,7 @@ export class Keyframe extends React.Component<IProps> {
         div.style.opacity = "0";
         Doc.UnBrushDoc(this.props.node);
     }
-  
+
 
     ///////////////////////UI STUFF /////////////////////////
 
@@ -524,7 +524,7 @@ export class Keyframe extends React.Component<IProps> {
                 keyframeDivs.push(
                     <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
                         <div className="divider"></div>
-                        <div className="keyframeCircle" onPointerDown={(e) => { e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
+                        <div className="keyframeCircle keyframe-indicator" onPointerDown={(e) => { e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
                             e.preventDefault();
                             e.stopPropagation();
                             this.makeKeyframeMenu(kf, e.nativeEvent);
@@ -577,18 +577,19 @@ export class Keyframe extends React.Component<IProps> {
     /**
      * rendering that green region
      */
+    //154, 206, 223
     render() {
         return (
             <div>
                 <div className="bar" ref={this._bar} style={{
                     transform: `translate(${this.pixelPosition}px)`,
                     width: `${this.pixelDuration}px`,
-                    background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.pixelFadeIn / this.pixelDuration * 100}%, rgba(77, 153, 0, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(77, 153, 0, 0) 100% )`
+                    background: `linear-gradient(90deg, rgba(154, 206, 223, 0) 0%, rgba(154, 206, 223, 1) ${this.pixelFadeIn / this.pixelDuration * 100}%, rgba(154, 206, 223, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(154, 206, 223, 0) 100% )`
                 }}
                     onPointerDown={this.onBarPointerDown
                     }>
-                    <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
-                    <div className="rightResize" onPointerDown={this.onResizeRight}></div>
+                    <div className="leftResize keyframe-indicator" onPointerDown={this.onResizeLeft} ></div>
+                    <div className="rightResize keyframe-indicator" onPointerDown={this.onResizeRight}></div>
                     {this.drawKeyframes()}
                     {this.drawKeyframeDividers()}
                 </div>
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index a8dd9b9e7..40479559d 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -206,18 +206,18 @@ $timelineDark: #77a1aa;
         border-right: 2px solid $timelineDark;
 
         .datapane {
-            top: 0px;
-            width: 100px;
-            height: 30%;
-            border: 1px solid $dark-color;
-            background-color: $intermediate-color;
-            color: white;
-            position: relative;
-            float: left;
-            border-style: solid;
-            overflow-y: scroll;
-            overflow-x: hidden;
-        }
+    top: 0px;
+    width: 100px;
+    height: 30%;
+    border: 1px solid $dark-color;
+    background-color: $intermediate-color;
+    color: white;
+    position: relative;
+    float: left;
+    border-style: solid;
+    overflow-y: scroll;
+    overflow-x: hidden;
+}
     }
 
     .resize {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 8b943f209..5ff721ebb 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -120,18 +120,6 @@ export class Timeline extends React.Component<FieldViewProps> {
             this.toggleHandle();
         });
 
-        this._resizeReaction = reaction(
-            () => this.props.PanelWidth,
-            () => {
-                // if (!this.props.parent._isAuthoring) {
-                // runInAction(() => {
-                console.log("resizing");
-                // this.setOverviewWidth();
-                // });
-                // }
-            },
-        );
-
     }
 
     componentWillUnmount() {
@@ -443,15 +431,6 @@ export class Timeline extends React.Component<FieldViewProps> {
             lengthString = "";
         }
 
-
-        // let modeType: string = this.props.Document.isATOn ? "Author" : "Play";
-        // let modeString: string = "Mode: " + modeType;
-        // let overviewString: string = "Overview:";
-        // let lengthString: string = "Length: ";
-
-        console.log("visible: " + this._visibleLength)
-        console.log("total: " + this._totalLength)
-
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
                 <div className="playbackControls">
@@ -462,7 +441,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                 <div className="grid-box overview-tool">
                     <div className="overview-box">
                         <div key="overview-text" className="animation-text">{overviewString}</div>
-                        <TimelineOverview panelWidth={this._panelWidth} parent={this} isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
+                        <TimelineOverview tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} time={this._time} parent={this} isAuthoring={BoolCast(this.props.Document.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX} />
                     </div>
                     <div className="mode-box overview-tool">
                         <div key="animation-text" className="animation-text">{modeString}</div>
@@ -572,7 +551,6 @@ export class Timeline extends React.Component<FieldViewProps> {
         runInAction(() => {
             this._panelWidth = this.props.PanelWidth();
             this.changeLenths();
-            console.log("changing!!")
         });
 
         // change visible and total width
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index caa97bb70..9a881264f 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -4,6 +4,7 @@ import { observer } from "mobx-react";
 import "./TimelineOverview.scss";
 import * as $ from 'jquery';
 import { Timeline } from "./Timeline";
+import { Keyframe, KeyframeFunc } from "./Keyframe";
 
 
 interface TimelineOverviewProps {
@@ -15,7 +16,9 @@ interface TimelineOverviewProps {
     parent: Timeline;
     changeCurrentBarX: (pixel: number) => void;
     movePanX: (pixel: number) => any;
-    panelWidth: number;
+    time: number;
+    tickSpacing: number;
+    tickIncrement: number;
 }
 
 
@@ -25,7 +28,9 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     @observable private _scrubberRef = React.createRef<HTMLDivElement>();
     @observable private overviewBarWidth: number = 0;
     @observable private _authoringReaction?: IReactionDisposer;
-    @observable private _resizeReaction?: IReactionDisposer;
+    @observable private visibleTime: number = 0;
+    @observable private currentX: number = 0;
+    @observable private visibleStart: number = 0;
     private readonly DEFAULT_HEIGHT = 50;
     private readonly DEFAULT_WIDTH = 300;
 
@@ -42,22 +47,10 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
                 }
             },
         );
-        // this._resizeReaction = reaction(
-        //     () => this.props.parent.props.PanelWidth,
-        //     () => {
-        //         // if (!this.props.parent._isAuthoring) {
-        //         // runInAction(() => {
-        //         console.log("resizing");
-        //         this.setOverviewWidth();
-        //         // });
-        //         // }
-        //     },
-        // );
     }
 
     componentWillUnmount = () => {
         this._authoringReaction && this._authoringReaction();
-        this._resizeReaction && this._resizeReaction();
     }
 
     @action
@@ -85,8 +78,6 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         // let movX = (this.props.visibleStart / this.props.totalLength) * (this.overviewWidth) + e.movementX;
         this.props.movePanX((movX / (this.DEFAULT_WIDTH)) * this.props.totalLength);
         // this.props.movePanX((movX / (this.overviewWidth) * this.props.totalLength);
-
-        // console.log(this.props.totalLength);
     }
 
     @action
@@ -125,18 +116,36 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         document.removeEventListener("pointerup", this.onScrubberUp);
     }
 
+    @action
+    getTimes() {
+        let vis = KeyframeFunc.convertPixelTime(this.props.visibleLength, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        let x = KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        let start = KeyframeFunc.convertPixelTime(this.props.visibleStart, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        this.visibleTime = vis;
+        this.currentX = x;
+        this.visibleStart = start;
+    }
+
     render() {
 
-        console.log("helo")
+        this.getTimes();
         // calculates where everything should fall based on its size
-        let percentVisible = this.props.visibleLength / this.props.totalLength;
-        console.log(this.props.visibleLength)
+        // let percentVisible = this.props.visibleLength / this.props.totalLength;
+        // let visibleBarWidth = percentVisible * this.overviewBarWidth;
+
+        // let percentScrubberStart = this.props.currentBarX / this.props.totalLength;
+        // let scrubberStart = percentScrubberStart * this.overviewBarWidth;
+
+        // let percentBarStart = this.props.visibleStart / this.props.totalLength;
+        // let barStart = percentBarStart * this.overviewBarWidth;
+
+        let percentVisible = this.visibleTime / this.props.time;
         let visibleBarWidth = percentVisible * this.overviewBarWidth;
 
-        let percentScrubberStart = this.props.currentBarX / this.props.totalLength;
+        let percentScrubberStart = this.currentX / this.props.time;
         let scrubberStart = percentScrubberStart * this.overviewBarWidth;
 
-        let percentBarStart = this.props.visibleStart / this.props.totalLength;
+        let percentBarStart = this.visibleStart / this.props.time;
         let barStart = percentBarStart * this.overviewBarWidth;
 
         let timeline = this.props.isAuthoring ? [
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 1ca8022a1..3ea34a2f3 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -66,7 +66,7 @@ export class Track extends React.Component<IProps> {
         runInAction(() => {
             if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); //if there is no region, then create new doc to store stuff
             //these two lines are exactly same from timeline.tsx 
-            let relativeHeight = window.innerHeight / 14;
+            let relativeHeight = window.innerHeight / 20;
             this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness
         });
     }
-- 
cgit v1.2.3-70-g09d2


From c12573ba5e45271493acf01ee7d63ce9387ac606 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sat, 1 Feb 2020 16:23:51 -0500
Subject: lots of changes

---
 src/client/views/animationtimeline/Keyframe.tsx    |  95 ++++++++--------
 src/client/views/animationtimeline/Timeline.tsx    |   4 -
 .../views/animationtimeline/TimelineOverview.tsx   |   2 -
 src/client/views/animationtimeline/Track.tsx       | 120 +++++++--------------
 4 files changed, 79 insertions(+), 142 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 9f4d80d2b..4f6ba728d 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -20,15 +20,18 @@ import { undoBatch, UndoManager } from "../../util/UndoManager";
  * Useful static functions that you can use. Mostly for logic, but you can also add UI logic here also 
  */
 export namespace KeyframeFunc {
+
     export enum KeyframeType {
         end = "end",
         fade = "fade",
         default = "default",
     }
+
     export enum Direction {
         left = "left",
         right = "right"
     }
+
     export const findAdjacentRegion = (dir: KeyframeFunc.Direction, currentRegion: Doc, regions: List<Doc>): (RegionData | undefined) => {
         let leftMost: (RegionData | undefined) = undefined;
         let rightMost: (RegionData | undefined) = undefined;
@@ -97,41 +100,6 @@ export namespace KeyframeFunc {
         return regiondata;
     };
 
-    export const makeKeyData = async (regiondata:RegionData, time: number, badNode:Doc, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time 
-        runInAction(async () => {
-            console.log("ran"); 
-            let doclist = (await DocListCastAsync(regiondata.keyframes))!;
-            let existingkf: (Doc | undefined) = undefined;
-            doclist.forEach(TK => {
-                if (TK.time === time) existingkf = TK;
-            });
-            if (existingkf) return existingkf;
-            let TK: Doc = new Doc();
-            TK.time = time;
-            TK.key = Doc.MakeCopy(badNode, true);
-            TK.type = type;
-            regiondata.keyframes!.push(TK);
-            let interpolationFunctions = new Doc();
-            interpolationFunctions.interpolationX = new List<number>([0, 1]);
-            interpolationFunctions.interpolationY = new List<number>([0, 100]);
-            interpolationFunctions.pathX = new List<number>();
-            interpolationFunctions.pathY = new List<number>();
-            regiondata.functions!.push(interpolationFunctions);
-            let found: boolean = false;
-            regiondata.keyframes!.forEach(compkf => {
-                compkf = compkf as Doc;
-                if (time < NumCast(compkf.time) && !found) {
-                    runInAction(() => {
-                        regiondata.keyframes!.splice(doclist.indexOf(compkf as Doc), 0, TK);
-                        regiondata.keyframes!.pop();
-                        found = true;
-                    });
-                    return;
-                }
-            });
-            return TK;
-        });
-    };
 
     export const convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time", tickSpacing: number, tickIncrement: number) => {
         let time = dir === "pixel" ? (pos * tickSpacing) / tickIncrement : (pos / tickSpacing) * tickIncrement;
@@ -202,7 +170,6 @@ interface IProps {
 export class Keyframe extends React.Component<IProps> {
 
     @observable private _bar = React.createRef<HTMLDivElement>();
-    @observable private _gain = 20; //default
     @observable private _mouseToggled = false;
     @observable private _doubleClickEnabled = false;
 
@@ -215,18 +182,15 @@ export class Keyframe extends React.Component<IProps> {
     @computed private get pixelFadeOut() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
    
     componentWillMount() {
-        runInAction(async () => {
-            if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();
-            let fadeIn = (await KeyframeFunc.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, this.props.node, KeyframeFunc.KeyframeType.fade))! as any as Doc;
-            let fadeOut = (await KeyframeFunc.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, this.props.node, KeyframeFunc.KeyframeType.fade))! as any as Doc;
-            let start = (await KeyframeFunc.makeKeyData(this.regiondata, this.regiondata.position, this.props.node, KeyframeFunc.KeyframeType.end))! as any as Doc;
-            let finish = (await KeyframeFunc.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration, this.props.node, KeyframeFunc.KeyframeType.end))! as any as Doc;
-            (fadeIn.key! as Doc).opacity = 1;
-            (fadeOut.key! as Doc).opacity = 1;
-            (start.key! as Doc).opacity = 0.1;
-            (finish.key! as Doc).opacity = 0.1;
-            this.forceUpdate();
-        });
+        if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();        
+        let start = this.makeKeyData(this.regiondata, this.regiondata.position,  KeyframeFunc.KeyframeType.end);
+        let fadeIn = this.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade);
+        let fadeOut = this.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade);
+        let finish = this.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration,KeyframeFunc.KeyframeType.end);
+        (fadeIn.key as Doc).opacity = 1;
+        (fadeOut.key as Doc).opacity = 1;
+        (start.key as Doc).opacity = 0.1;
+        (finish.key as Doc).opacity = 0.1;
     }
 
     
@@ -253,7 +217,32 @@ export class Keyframe extends React.Component<IProps> {
             });
         }
     }
-
+    private makeKeyData = (regiondata:RegionData, time: number, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time 
+        let doclist =  DocListCast(regiondata.keyframes)!;
+        let existingkf: (Doc | undefined) = undefined;
+        doclist.forEach(TK => {
+            if (TK.time === time) existingkf = TK;
+        });
+        if (existingkf) return existingkf;
+        //else creates a new doc. 
+        let TK: Doc = new Doc();
+        TK.time = time;
+        TK.key = Doc.MakeCopy(this.props.node, true);
+        TK.type = type;
+        //assuming there are already keyframes (for keeping keyframes in order, sorted by time)
+        console.log("making..."); 
+        if (doclist.length === 0) regiondata.keyframes!.push(TK); 
+        doclist.forEach(kf => {
+            let index = doclist.indexOf(kf); 
+            let kfTime = NumCast(kf.time);
+                console.log(kfTime); 
+            if ((kfTime < time && index === doclist.length - 1) || (kfTime < time && time < NumCast(doclist[index + 1].time))){
+               regiondata.keyframes!.splice(index + 1, 0, TK);
+                return; 
+            }
+        });
+        return TK; 
+    }
 
     @action
     onBarPointerMove = (e: PointerEvent) => {
@@ -353,7 +342,7 @@ export class Keyframe extends React.Component<IProps> {
         let offset = KeyframeFunc.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
             let position = this.regiondata.position;
-            await KeyframeFunc.makeKeyData(this.regiondata, Math.round(position + offset), this.props.node);
+            this.makeKeyData(this.regiondata, Math.round(position + offset));
             this.regiondata.hasData = true; 
             this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied
         
@@ -552,12 +541,12 @@ export class Keyframe extends React.Component<IProps> {
         DocListCast(this.regiondata.keyframes).forEach(kf => {
             let index = this.keyframes.indexOf(kf);
             if (index !== this.keyframes.length - 1) {
-                let left = this.keyframes[this.keyframes.indexOf(kf) + 1];
+                let right = this.keyframes[index + 1];
                 let bodyRef = React.createRef<HTMLDivElement>();
                 let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
-                let leftPos = KeyframeFunc.convertPixelTime(NumCast(left!.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
+                let rightPos = KeyframeFunc.convertPixelTime(NumCast(right.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
                 keyframeDividers.push(
-                    <div ref={bodyRef} className="body-container" style={{ left: `${kfPos - this.pixelPosition}px`, width: `${leftPos - kfPos}px` }}
+                    <div ref={bodyRef} className="body-container" style={{ left: `${kfPos - this.pixelPosition}px`, width: `${rightPos - kfPos}px` }}
                         onPointerOver={(e) => { e.preventDefault(); e.stopPropagation(); this.onContainerOver(e, bodyRef); }}
                         onPointerOut={(e) => { e.preventDefault(); e.stopPropagation(); this.onContainerOut(e, bodyRef); }}
                         onContextMenu={(e) => {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 8b943f209..604827213 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -449,9 +449,6 @@ export class Timeline extends React.Component<FieldViewProps> {
         // let overviewString: string = "Overview:";
         // let lengthString: string = "Length: ";
 
-        console.log("visible: " + this._visibleLength)
-        console.log("total: " + this._totalLength)
-
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
                 <div className="playbackControls">
@@ -572,7 +569,6 @@ export class Timeline extends React.Component<FieldViewProps> {
         runInAction(() => {
             this._panelWidth = this.props.PanelWidth();
             this.changeLenths();
-            console.log("changing!!")
         });
 
         // change visible and total width
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index caa97bb70..553ba890d 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -127,10 +127,8 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
     render() {
 
-        console.log("helo")
         // calculates where everything should fall based on its size
         let percentVisible = this.props.visibleLength / this.props.totalLength;
-        console.log(this.props.visibleLength)
         let visibleBarWidth = percentVisible * this.overviewBarWidth;
 
         let percentScrubberStart = this.props.currentBarX / this.props.totalLength;
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index e5e7a364c..17466bd1a 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -10,6 +10,7 @@ import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
 import { Transform } from "../../util/Transform";
 import { Copy } from "../../../new_fields/FieldSymbols";
 import { ObjectField } from "../../../new_fields/ObjectField";
+import { fromCallback } from "bluebird";
 
 interface IProps {
     node: Doc;
@@ -40,10 +41,12 @@ export class Track extends React.Component<IProps> {
         "y",
         "width",
         "height",
-        "data"
+        "data", 
+        "opacity"
     ];
+
     @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; }
-    // @computed private get time() {}
+    @computed private get time() {return NumCast(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));}
 
     ////////// life cycle functions///////////////
     componentWillMount() {
@@ -59,7 +62,7 @@ export class Track extends React.Component<IProps> {
         runInAction(async () => {
             this._timelineVisibleReaction = this.timelineVisibleReaction();
             this._currentBarXReaction = this.currentBarXReaction();
-            if (this.regions.length === 0) this.createRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
+            if (this.regions.length === 0) this.createRegion(this.time);
             this.props.node.hidden = false;
             this.props.node.opacity = 1;
            // this.autoCreateKeyframe(); 
@@ -90,17 +93,17 @@ export class Track extends React.Component<IProps> {
         if (!kf) return;
         if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
             kf.key = Doc.MakeCopy(this.props.node, true);
-            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); // lef keyframe, if it exists
-            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), kf); //right keyframe, if it exists 
+            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.time, kf); // lef keyframe, if it exists
+            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, this.time, kf); //right keyframe, if it exists 
             if (leftkf!.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
-                let edge: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), leftkf!);
+                let edge: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata!, this.time, leftkf!);
                 edge!.key = Doc.MakeCopy(kf.key as Doc, true);
                 leftkf!.key = Doc.MakeCopy(kf.key as Doc, true);
                 (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
                 (Cast(leftkf!.key, Doc)! as Doc).opacity = 1;
             }
             if (rightkf!.type === KeyframeFunc.KeyframeType.fade) {
-                let edge: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement), rightkf!);
+                let edge: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata!, this.time, rightkf!);
                 edge!.key = Doc.MakeCopy(kf.key as Doc, true);
                 rightkf!.key = Doc.MakeCopy(kf.key as Doc, true);
                 (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
@@ -124,14 +127,12 @@ export class Track extends React.Component<IProps> {
             return this.whitelist.map(key => node[key]);
         }, (changed, reaction) => {
             console.log(changed); 
-            //convert scrubber pos(pixel) to time
-            let time = KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
             //check for region 
-            this.findRegion(time).then((region) => {
+            this.findRegion(this.time).then((region) => {
                 if (region !== undefined){ //if region at scrub time exist
                     let r = region as any as RegionData; //for some region is returning undefined... which is not the case
-                    if (DocListCast(r.keyframes).find(kf => kf.time === time) === undefined ){ //basically when there is no additional keyframe at that timespot 
-                        KeyframeFunc.makeKeyData(r, time, this.props.node, KeyframeFunc.KeyframeType.default); 
+                    if (DocListCast(r.keyframes).find(kf => kf.time === this.time) === undefined ){ //basically when there is no additional keyframe at that timespot 
+                        KeyframeFunc.makeKeyData(r, this.time, this.props.node, KeyframeFunc.KeyframeType.default); 
                     } 
                 }
                 // reaction.dispose(); 
@@ -158,10 +159,10 @@ export class Track extends React.Component<IProps> {
     @action
     currentBarXReaction = () => {
         return reaction(() => this.props.currentBarX, async () => {
-            let regiondata: (Doc | undefined) = await this.findRegion(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
+            let regiondata: (Doc | undefined) = await this.findRegion(this.time);
             if (regiondata) {
                 this.props.node.hidden = false;
-                await this.timeChange(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
+                await this.timeChange();
             } else {
                 this.props.node.hidden = true;
                 this.props.node.opacity = 0;
@@ -198,14 +199,14 @@ export class Track extends React.Component<IProps> {
      * when scrubber position changes. Need to edit the logic
      */
     @action
-    timeChange = async (time: number) => {
+    timeChange = async () => {
         if (this._isOnKeyframe && this._onKeyframe && this._onRegionData) {
             await this.saveKeyframe(this._onKeyframe, this._onRegionData);
         }
-        let regiondata = await this.findRegion(Math.round(time)); //finds a region that the scrubber is on
+        let regiondata = await this.findRegion(Math.round(this.time)); //finds a region that the scrubber is on
         if (regiondata) {
-            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement)); // lef keyframe, if it exists
-            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement)); //right keyframe, if it exists            
+            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata, this.time); // lef keyframe, if it exists
+            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.time); //right keyframe, if it exists        
             let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
             if (currentkf) {
                 await this.applyKeys(currentkf);
@@ -213,7 +214,7 @@ export class Track extends React.Component<IProps> {
                 this._onKeyframe = currentkf;
                 this._onRegionData = regiondata;
             } else if (leftkf && rightkf) {
-                await this.interpolate(leftkf, rightkf, regiondata);
+                await this.interpolate(leftkf, rightkf);
             }
         }
     }
@@ -225,17 +226,12 @@ export class Track extends React.Component<IProps> {
     @action
     private applyKeys = async (kf: Doc) => {
         let kfNode = await Cast(kf.key, Doc) as Doc;
-        let docFromApply = kfNode;
         this.whitelist.forEach(key => {
             if (!kfNode[key]) {
                 this.props.node[key] = undefined;
             } else {
                 let stored = kfNode[key];
-                if (stored instanceof ObjectField) {
-                    this.props.node[key] = stored[Copy]();
-                } else {
-                    this.props.node[key] = stored;
-                }
+                this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored; 
             }
         });
     }
@@ -245,77 +241,35 @@ export class Track extends React.Component<IProps> {
      *  calculating current keyframe, if the scrubber is right on the keyframe
      */
     @action
-    calcCurrent = async (region: Doc) => {
+    calcCurrent = (region: Doc) => {
         let currentkf: (Doc | undefined) = undefined;
-        let keyframes = await DocListCastAsync(region.keyframes!);
-        keyframes!.forEach((kf) => {
-            if (NumCast(kf.time) === Math.round(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement))) currentkf = kf;
+        let keyframes = DocListCast(region.keyframes!);
+        keyframes.forEach((kf) => {
+            if (NumCast(kf.time) === Math.round(this.time)) currentkf = kf;
         });
         return currentkf;
     }
 
 
     /**
-     * interpolation. definetely needs to be changed. (currently involves custom linear splicing interpolations). 
-     * Too complex right now. Also need to apply quadratic spline later on (for smoothness, instead applying "gains")
+     * basic linear interpolation function 
      */
     @action
-    interpolate = async (left: Doc, right: Doc, regiondata: Doc) => {
-        let leftNode = left.key as Doc;
-        let rightNode = right.key as Doc;
-        // const dif_time = NumCast(right.time) - NumCast(left.time);
-        // const timeratio = (KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement) - NumCast(left.time)) / dif_time; //linear 
-        // let keyframes = (await DocListCastAsync(regiondata.keyframes!))!;
-        // let indexLeft = keyframes.indexOf(left);
-        // let interY: List<number> = (await ((regiondata.functions as List<Doc>)[indexLeft] as Doc).interpolationY as List<number>)!;
-        // let realIndex = (interY.length - 1) * timeratio;
-        // let xIndex = Math.floor(realIndex);
-        // let yValue = interY[xIndex];
-        // let secondYOffset: number = yValue;
-        // let minY = interY[0];  // for now
-        // let maxY = interY[interY.length - 1]; //for now 
-        // if (interY.length !== 1) {
-        //     secondYOffset = interY[xIndex] + ((realIndex - xIndex) / 1) * (interY[xIndex + 1] - interY[xIndex]) - minY;
-        // }
-        // let finalRatio = secondYOffset / (maxY - minY);
-        // let pathX: List<number> = await ((regiondata.functions as List<Doc>)[indexLeft] as Doc).pathX as List<number>;
-        // let pathY: List<number> = await ((regiondata.functions as List<Doc>)[indexLeft] as Doc).pathY as List<number>;
-        // let proposedX = 0;
-        // let proposedY = 0;
-        // if (pathX.length !== 0) {
-        //     let realPathCorrespondingIndex = finalRatio * (pathX.length - 1);
-        //     let pathCorrespondingIndex = Math.floor(realPathCorrespondingIndex);
-        //     if (pathCorrespondingIndex >= pathX.length - 1) {
-        //         proposedX = pathX[pathX.length - 1];
-        //         proposedY = pathY[pathY.length - 1];
-        //     } else if (pathCorrespondingIndex < 0) {
-        //         proposedX = pathX[0];
-        //         proposedY = pathY[0];
-        //     } else {
-        //         proposedX = pathX[pathCorrespondingIndex] + ((realPathCorrespondingIndex - pathCorrespondingIndex) / 1) * (pathX[pathCorrespondingIndex + 1] - pathX[pathCorrespondingIndex]);
-        //         proposedY = pathY[pathCorrespondingIndex] + ((realPathCorrespondingIndex - pathCorrespondingIndex) / 1) * (pathY[pathCorrespondingIndex + 1] - pathY[pathCorrespondingIndex]);
-        //     }
-
-        // }
+    interpolate = async (left: Doc, right: Doc) => {
+        let leftNode = await(left.key) as Doc;
+        let rightNode = await(right.key) as Doc;
         this.whitelist.forEach(key => {
+            console.log(key); 
+            console.log(leftNode[key]); 
+            console.log(rightNode[key]); 
             if (leftNode[key] && rightNode[key] && typeof (leftNode[key]) === "number" && typeof (rightNode[key]) === "number") { //if it is number, interpolate
-                // if ((key === "x" || key === "y") && pathX.length !== 0) {
-                //     if (key === "x") this.props.node[key] = proposedX;
-                //     if (key === "y") this.props.node[key] = proposedY;
-                // } else {
-                //     const diff = NumCast(rightNode[key]) - NumCast(leftNode[key]);
-                //     const adjusted = diff * finalRatio;
-                //     this.props.node[key] = NumCast(leftNode[key]) + adjusted;
-                // }
                 let dif = NumCast(rightNode[key]) - NumCast(leftNode[key]); 
-                
-            } else {
+                let deltaLeft = this.time - NumCast(left.time);
+                let ratio = deltaLeft / (NumCast(right.time) - NumCast(left.time)); 
+                this.props.node[key] = NumCast(leftNode[key]) + (dif * ratio); 
+            } else { // case data 
                 let stored = leftNode[key];
-                if (stored instanceof ObjectField) {
-                    this.props.node[key] = stored[Copy]();
-                } else {
-                    this.props.node[key] = stored;
-                }
+                this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored; 
             }
         });
     }
-- 
cgit v1.2.3-70-g09d2


From 0688541300ad0fa5cda7543d5bdc2e2c56246fbc Mon Sep 17 00:00:00 2001
From: Andrew Kim <andrewdkim@users.noreply.github.com>
Date: Sun, 2 Feb 2020 10:40:45 -0500
Subject: cleanup (unstable)

---
 src/client/views/animationtimeline/Keyframe.tsx |  1 -
 src/client/views/animationtimeline/Timeline.tsx | 48 +------------------------
 src/client/views/animationtimeline/Track.tsx    |  5 ---
 3 files changed, 1 insertion(+), 53 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index d53000460..482d066ba 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -137,7 +137,6 @@ interface IProps {
     tickSpacing: number;
     tickIncrement: number;
     time: number;
-    check: string;
     changeCurrentBarX: (x: number) => void;
     transform: Transform;
     makeKeyData: (region:RegionData, pos: number, kftype:KeyframeFunc.KeyframeType) => Doc; 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 604827213..da9c361da 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -79,7 +79,6 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     // so a reaction can be made
     @observable public _isAuthoring = this.props.Document.isATOn;
-    @observable private _resizeReaction?: IReactionDisposer;
     @observable private _panelWidth = 0;
 
     /**
@@ -119,19 +118,6 @@ export class Timeline extends React.Component<FieldViewProps> {
             this.props.Document.isATOn = !this.props.Document.isATOn; //turns the boolean on, saying AT (animation timeline) is on
             this.toggleHandle();
         });
-
-        this._resizeReaction = reaction(
-            () => this.props.PanelWidth,
-            () => {
-                // if (!this.props.parent._isAuthoring) {
-                // runInAction(() => {
-                console.log("resizing");
-                // this.setOverviewWidth();
-                // });
-                // }
-            },
-        );
-
     }
 
     componentWillUnmount() {
@@ -527,30 +513,6 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
-    @observable private _check: string = "";
-    @observable private _checkVisible: boolean = false;
-    @action
-    private onCheckClicked = (type: string) => {
-        if (type === "yes") {
-            this._check = "yes";
-        } else if (type === "no") {
-            this._check = "no";
-        }
-    }
-
-
-    /**
-     * check mark thing that needs to be fixed. Do not edit this, because it most likely change.
-     */
-    @action
-    private checkCallBack = (visible: boolean) => {
-        this._checkVisible = visible;
-        if (!visible) { //when user confirms
-            this._check = "";
-        }
-
-    }
-
     @action.bound
     changeLenths() {
         if (this._infoContainer.current) {
@@ -583,7 +545,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                                     <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div>
                                 </div>
                                 <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
-                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} />)}
+                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible}/>)}
                                 </div>
                             </div>
                             <div key="timeline_title" className="title-container" ref={this._titleContainer}>
@@ -593,14 +555,6 @@ export class Timeline extends React.Component<FieldViewProps> {
                                 <FontAwesomeIcon className="resize" icon={faGripLines} />
                             </div>
                         </div>
-                        <div key="timeline-checker" className="timeline-checker" style={{ top: `${this._containerHeight}px`, visibility: this._checkVisible ? "visible" : "hidden" }}>
-                            <div onClick={() => { this.onCheckClicked("yes"); }}>
-                                <FontAwesomeIcon style={{ color: "#42b883" }} className="check" icon={faCheckCircle} />
-                            </div>
-                            <div onClick={() => { this.onCheckClicked("no"); }}>
-                                <FontAwesomeIcon style={{ color: "#ff7e67" }} className="check" icon={faTimesCircle} />
-                            </div>
-                        </div>
                     </div>
                     {this.timelineToolBox(1)}
                 </div>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 40350bc7a..d260792e1 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -21,7 +21,6 @@ interface IProps {
     tickIncrement: number;
     tickSpacing: number;
     timelineVisible: boolean;
-    check: string;
     changeCurrentBarX: (x: number) => void;
 }
 
@@ -30,10 +29,6 @@ export class Track extends React.Component<IProps> {
     @observable private _inner = React.createRef<HTMLDivElement>();
     @observable private _currentBarXReaction: any;
     @observable private _timelineVisibleReaction: any;
-    @observable private _isOnKeyframe: boolean = false;
-    @observable private _onKeyframe: (Doc | undefined) = undefined;
-    @observable private _onRegionData: (Doc | undefined) = undefined;
-    @observable private _storedState: (Doc | undefined) = undefined;
     private readonly MAX_TITLE_HEIGHT = 75;
     private _trackHeight = 0;
     private whitelist = [
-- 
cgit v1.2.3-70-g09d2


From 4fd68c0ec41f2871ae24a87d8e5316d093bdb505 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sun, 2 Feb 2020 15:10:34 -0500
Subject: changes

---
 src/client/views/animationtimeline/Keyframe.scss | 15 +++++++++++
 src/client/views/animationtimeline/Keyframe.tsx  |  8 +++++-
 src/client/views/animationtimeline/Timeline.scss | 32 +++++++++++++++---------
 src/client/views/animationtimeline/Timeline.tsx  |  2 +-
 src/client/views/animationtimeline/Track.scss    | 17 +++++++------
 5 files changed, 52 insertions(+), 22 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.scss b/src/client/views/animationtimeline/Keyframe.scss
index 8ff1c53f5..f0685943b 100644
--- a/src/client/views/animationtimeline/Keyframe.scss
+++ b/src/client/views/animationtimeline/Keyframe.scss
@@ -46,6 +46,21 @@ $timelineDark: #77a1aa;
         position: absolute;
     }
 
+    .keyframe:hover~.keyframe-information {
+        display: flex;
+    }
+
+    .keyframe-information {
+        display: none;
+        position: relative;
+        // z-index: 100000;
+        // background: $timelineDark;
+        width: 100px;
+        // left: -50px;
+        height: 100px;
+        // top: 40px;
+    }
+
     .keyframeCircle {
         left: -10px;
         border: 3px solid $timelineDark;
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 9c486a6d6..2348da813 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -522,14 +522,18 @@ export class Keyframe extends React.Component<IProps> {
         DocListCast(this.regiondata.keyframes).forEach(kf => {
             if (kf.type as KeyframeFunc.KeyframeType !== KeyframeFunc.KeyframeType.end) {
                 keyframeDivs.push(
-                    <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                    <><div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
                         <div className="divider"></div>
                         <div className="keyframeCircle keyframe-indicator" onPointerDown={(e) => { e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
                             e.preventDefault();
                             e.stopPropagation();
                             this.makeKeyframeMenu(kf, e.nativeEvent);
                         }} onDoubleClick={(e) => { e.preventDefault(); e.stopPropagation(); }}></div>
+
                     </div>
+                        <div className="keyframe-information"></div>
+                    </>
+
                 );
             } else {
                 keyframeDivs.push(
@@ -589,7 +593,9 @@ export class Keyframe extends React.Component<IProps> {
                     onPointerDown={this.onBarPointerDown
                     }>
                     <div className="leftResize keyframe-indicator" onPointerDown={this.onResizeLeft} ></div>
+                    {/* <div className="keyframe-information"></div> */}
                     <div className="rightResize keyframe-indicator" onPointerDown={this.onResizeRight}></div>
+                    {/* <div className="keyframe-information"></div> */}
                     {this.drawKeyframes()}
                     {this.drawKeyframeDividers()}
                 </div>
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index 40479559d..dbdade03f 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -206,18 +206,26 @@ $timelineDark: #77a1aa;
         border-right: 2px solid $timelineDark;
 
         .datapane {
-    top: 0px;
-    width: 100px;
-    height: 30%;
-    border: 1px solid $dark-color;
-    background-color: $intermediate-color;
-    color: white;
-    position: relative;
-    float: left;
-    border-style: solid;
-    overflow-y: scroll;
-    overflow-x: hidden;
-}
+            top: 0px;
+            width: 100px;
+            height: 30%;
+            border: 1px solid $dark-color;
+            font-size: 12px;
+            line-height: 11px;
+            background-color: $timelineDark;
+            color: white;
+            position: relative;
+            float: left;
+            padding: 3px;
+            border-style: solid;
+            overflow-y: scroll;
+            overflow-x: hidden;
+
+            p {
+                hyphens: auto;
+            }
+
+        }
     }
 
     .resize {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 5ff721ebb..f0ca1c0ab 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -100,7 +100,7 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     /////////lifecycle functions////////////
     componentWillMount() {
-        let relativeHeight = window.innerHeight / 14; //sets height to arbitrary size, relative to innerHeight
+        let relativeHeight = window.innerHeight / 20; //sets height to arbitrary size, relative to innerHeight
         this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //check if relHeight is less than Maxheight. Else, just set relheight to max
         this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; //offset
         this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; //twice the titleheight + offset
diff --git a/src/client/views/animationtimeline/Track.scss b/src/client/views/animationtimeline/Track.scss
index 61a8e0b88..aec587a79 100644
--- a/src/client/views/animationtimeline/Track.scss
+++ b/src/client/views/animationtimeline/Track.scss
@@ -1,14 +1,15 @@
-@import "./../globalCssVariables.scss"; 
+@import "./../globalCssVariables.scss";
 
-.track-container{
+.track-container {
 
     .track {
-        .inner {  
-            top:0px; 
-            width: calc(100%); 
-            background-color: $light-color;     
-            border: 1px solid $dark-color;        
-            position:relative; 
+        .inner {
+            top: 0px;
+            width: calc(100%);
+            background-color: $light-color;
+            border: 1px solid $dark-color;
+            position: relative;
+            z-index: 100;
         }
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 9e4d644c5977c781b4822ba065cec6e92977de10 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Wed, 5 Feb 2020 10:16:42 -0500
Subject: about to pull

---
 src/client/views/animationtimeline/Timeline.scss   | 28 ++++++++++++++++++++--
 src/client/views/animationtimeline/Timeline.tsx    | 21 +++++++++++++---
 .../views/animationtimeline/TimelineOverview.scss  |  9 ++++++-
 .../views/animationtimeline/TimelineOverview.tsx   | 19 +++++++--------
 4 files changed, 61 insertions(+), 16 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index dbdade03f..ce8c845df 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -43,6 +43,8 @@ $timelineDark: #77a1aa;
         .time-box {
             margin-left: 5px;
             display: flex;
+            justify-content: center;
+            align-items: center;
         }
 
         .mode-box {
@@ -61,6 +63,12 @@ $timelineDark: #77a1aa;
         }
     }
 
+    .overview-tool {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+    }
+
     .animation-text {
         // font-size: 16px;
         height: auto;
@@ -179,13 +187,14 @@ $timelineDark: #77a1aa;
 
         .trackbox {
             top: 30px;
-            // TODO: where is this 30px coming from?
             height: calc(100% - 30px);
             // height: 100%;
+            // height: 100%;
             width: 100%;
             border-top: 2px solid black;
             border-bottom: 2px solid black;
             overflow: hidden;
+            // overflow-y: scroll;
             background-color: white;
             position: absolute;
             // box-shadow: -10px 0px 10px 10px red;
@@ -193,10 +202,25 @@ $timelineDark: #77a1aa;
 
     }
 
+    .currentTime {
+        // background: red;
+        font-size: 12px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        height: 40px;
+        top: 40px;
+        position: relative;
+        width: 100px;
+        margin-left: 20px;
+    }
+
     .title-container {
-        margin-top: 80px;
+        // margin-top: 80px;
+        margin-top: 40px;
         margin-left: 20px;
         height: calc(100% - 100px - 30px);
+        // height: 100%;
         width: 100px;
         background-color: white;
         overflow: hidden;
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index f0ca1c0ab..ae2dfafc9 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -312,6 +312,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         e.preventDefault();
         e.stopPropagation();
         let offset = e.clientY - this._timelineContainer.current!.getBoundingClientRect().bottom;
+        // let offset = 0;
         if (this._containerHeight + offset <= this.MIN_CONTAINER_HEIGHT) {
             this._containerHeight = this.MIN_CONTAINER_HEIGHT;
         } else if (this._containerHeight + offset >= this.MAX_CONTAINER_HEIGHT) {
@@ -326,7 +327,10 @@ export class Timeline extends React.Component<FieldViewProps> {
      */
     @action
     toReadTime = (time: number): string => {
-        const inSeconds = time / 1000;
+        time = time / 1000;
+        var inSeconds = Math.round((time * 100)) / 100;
+        // var inSeconds = parseFloat(time.toFixed(2));
+        // const inSeconds = (Math.floor(time) / 1000);
         let min: (string | number) = Math.floor(inSeconds / 60);
         let sec: (string | number) = inSeconds % 60;
 
@@ -451,7 +455,8 @@ export class Timeline extends React.Component<FieldViewProps> {
                     </div>
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
                         <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }}>{lengthString}</div>
-                        <input className="time-input" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
+                        <input className="time-input" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: !this.props.Document.isATOn ? "flex" : "none" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
+                        <div style={{ width: "100%", backgroundColor: "red", display: !this.props.Document.isATOn ? "flex" : "none" }}>Hello there</div>
                     </div>
                 </div>
             </div>
@@ -541,13 +546,22 @@ export class Timeline extends React.Component<FieldViewProps> {
         }
     }
 
+    // @computed
+    getCurrentTime = () => {
+        let current = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
+        // console.log(this._currentBarX)
+        return this.toReadTime(current); ``
+        // return (Math.floor(current) / 1000)
+        // return current / 1000.0;
+    }
+
 
     /**
      * if you have any question here, just shoot me an email or text. 
      * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
      */
     render() {
-        // console.log(this.props.PanelWidth());
+        console.log(this.props.Document.isATOn);
         runInAction(() => {
             this._panelWidth = this.props.PanelWidth();
             this.changeLenths();
@@ -568,6 +582,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                                     {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} check={this._check} />)}
                                 </div>
                             </div>
+                            <div className="currentTime">Current: {this.getCurrentTime()}</div>
                             <div key="timeline_title" className="title-container" ref={this._titleContainer}>
                                 {DocListCast(this.children).map(doc => <div style={{ height: `${(this._titleHeight)}px` }} className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)}
                             </div>
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index a0b9d462b..283163ea7 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -8,6 +8,13 @@ $timelineDark: #77a1aa;
     margin-right: 10px;
 }
 
+.timeline-flex {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+}
+
 .timeline-overview-container {
     // padding: 0px;
     margin-right: 5px;
@@ -93,7 +100,7 @@ $timelineDark: #77a1aa;
     height: 4px;
     width: 0px;
     z-index: 1000;
-    background-color: $timelineColor;
+    background-color: $timelineDark;
     border-radius: 20px;
     margin-top: -4px;
     cursor: pointer;
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 9a881264f..65fd8ff62 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -56,8 +56,11 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     @action
     setOverviewWidth() {
         let width = $("#timelineOverview").width();
+        // console.log($("timelineOverview"))
         if (width) this.overviewBarWidth = width;
         else this.overviewBarWidth = 0;
+
+        // console.log(this.overviewBarWidth)
     }
 
     @action
@@ -124,20 +127,14 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         this.visibleTime = vis;
         this.currentX = x;
         this.visibleStart = start;
+        // console.log("getting times")
+        // console.log(x)
+        // console.log(start)
     }
 
     render() {
-
+        this.setOverviewWidth();
         this.getTimes();
-        // calculates where everything should fall based on its size
-        // let percentVisible = this.props.visibleLength / this.props.totalLength;
-        // let visibleBarWidth = percentVisible * this.overviewBarWidth;
-
-        // let percentScrubberStart = this.props.currentBarX / this.props.totalLength;
-        // let scrubberStart = percentScrubberStart * this.overviewBarWidth;
-
-        // let percentBarStart = this.props.visibleStart / this.props.totalLength;
-        // let barStart = percentBarStart * this.overviewBarWidth;
 
         let percentVisible = this.visibleTime / this.props.time;
         let visibleBarWidth = percentVisible * this.overviewBarWidth;
@@ -163,9 +160,11 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
                 <div className="timeline-play-tail" style={{ width: `${(this.props.currentBarX / this.props.totalLength) * 294}px` }}></div>
             ];
         return (
+            <div className = "timeline-flex">
             <div className="timelineOverview-bounding">
                 {timeline}
             </div>
+            </div>
         );
     }
 
-- 
cgit v1.2.3-70-g09d2


From 4cc2472c5e2d16ac5bc60a919150d1df5d6f4129 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Wed, 5 Feb 2020 10:25:23 -0500
Subject: ready

---
 src/client/views/animationtimeline/Timeline.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 68b0ce80c..f74d4c71e 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -454,7 +454,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
                         <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{lengthString}</div>
                         <input className="time-input" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
-                        <div style={{ width: "100%", backgroundColor: "red", display: !this.props.Document.isATOn ? "flex" : "none" }}>{this.getCurrentTime()}</div>
+                        <div style={{ width: "100%", display: !this.props.Document.isATOn ? "flex" : "none" }}>Current: {this.getCurrentTime()}</div>
                     </div>
                 </div>
             </div>
-- 
cgit v1.2.3-70-g09d2


From e310c0fdcef6ac71ee492470d4ac689cbb094167 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sat, 8 Feb 2020 12:54:07 -0500
Subject: small changes

---
 src/client/views/animationtimeline/Timeline.tsx          | 15 +++++++--------
 src/client/views/animationtimeline/TimelineOverview.scss |  2 +-
 src/client/views/animationtimeline/TimelineOverview.tsx  |  8 ++++++--
 3 files changed, 14 insertions(+), 11 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index f74d4c71e..5d5e78652 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -453,7 +453,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                     </div>
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
                         <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{lengthString}</div>
-                        <input className="time-input" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
+                        <input className="time-input" disabled style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
                         <div style={{ width: "100%", display: !this.props.Document.isATOn ? "flex" : "none" }}>Current: {this.getCurrentTime()}</div>
                     </div>
                 </div>
@@ -466,12 +466,12 @@ export class Timeline extends React.Component<FieldViewProps> {
      */
     @action
     private onTimeInput = (e: React.KeyboardEvent) => {
-        if (e.keyCode === 13) {
-            let timeInput = this._timeInputRef.current!;
-            this._time = parseInt(timeInput.value, 10);
-            this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement);
-            this.props.Document.AnimationLength = this._time;
-        }
+        // if (e.keyCode === 13) {
+        //     let timeInput = this._timeInputRef.current!;
+        //     this._time = parseInt(timeInput.value, 10);
+        //     this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement);
+        //     this.props.Document.AnimationLength = this._time;
+        // }
     }
 
 
@@ -535,7 +535,6 @@ export class Timeline extends React.Component<FieldViewProps> {
      * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
      */
     render() {
-        console.log(this.props.Document.isATOn);
         runInAction(() => {
             this._panelWidth = this.props.PanelWidth();
             this.changeLenths();
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index 283163ea7..b54399307 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -72,7 +72,7 @@ $timelineDark: #77a1aa;
     position: relative;
     padding: 0px;
     margin: 0px;
-    width: 100%;
+    // width: 100%;
     height: 4px;
     background-color: $timelineColor;
     border-radius: 20px;
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 7ff78955e..5d6378068 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -58,7 +58,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         let width = $("#timelineOverview").width();
         // console.log($("timelineOverview"))
         if (width) this.overviewBarWidth = width;
-        else this.overviewBarWidth = 0;
+        // else this.overviewBarWidth = 0;
 
         // console.log(this.overviewBarWidth)
     }
@@ -95,10 +95,12 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     onScrubberDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
+        if (!this.props.isAuthoring) {
         document.removeEventListener("pointermove", this.onScrubberMove);
         document.removeEventListener("pointerup", this.onScrubberUp);
         document.addEventListener("pointermove", this.onScrubberMove);
         document.addEventListener("pointerup", this.onScrubberUp);
+        }
     }
 
     @action
@@ -107,8 +109,10 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         e.stopPropagation();
         let scrubberRef = this._scrubberRef.current!;
         let left = scrubberRef.getBoundingClientRect().left;
+        // left = e.screenX;
         let offsetX = Math.round(e.clientX - left);
         this.props.changeCurrentBarX((offsetX / (this.DEFAULT_WIDTH) * this.props.totalLength) + this.props.currentBarX);
+        // this.props.changeCurrentBarX(e.screenX)
     }
 
     @action
@@ -154,7 +158,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
                 </div>
             </div>
         ] : [
-                <div className="timeline-play-bar">
+                <div className="timeline-play-bar" style={{ width: this.overviewBarWidth }}>
                     <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${(this.props.currentBarX / this.props.totalLength) * 294}px` }} onPointerDown={this.onScrubberDown}></div>
                 </div>,
                 <div className="timeline-play-tail" style={{ width: `${(this.props.currentBarX / this.props.totalLength) * 294}px` }}></div>
-- 
cgit v1.2.3-70-g09d2


From 92068acedc3d6f5bed25dc1a0dacbe19d0338829 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 9 Feb 2020 14:06:54 -0500
Subject: reformatted

---
 package-lock.json                                  |  8 ++++-
 package.json                                       |  2 +-
 src/client/views/animationtimeline/Timeline.tsx    |  2 +-
 .../views/animationtimeline/TimelineOverview.scss  |  2 +-
 .../views/animationtimeline/TimelineOverview.tsx   | 35 +++++++++++-----------
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 33 ++++++++++----------
 6 files changed, 46 insertions(+), 36 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/package-lock.json b/package-lock.json
index 379cd3337..1f87e1493 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14244,7 +14244,8 @@
                 "fsevents": {
                     "version": "2.1.2",
                     "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
-                    "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA=="
+                    "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
+                    "optional": true
                 },
                 "get-caller-file": {
                     "version": "2.0.5",
@@ -16134,6 +16135,11 @@
                 "setimmediate": "^1.0.4"
             }
         },
+        "tiny-timer": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/tiny-timer/-/tiny-timer-1.4.0.tgz",
+            "integrity": "sha512-NZCayn+Y2OaDaBtVQmx8Lx/SggG9qGGINYoPNmXpqvj8ue7E24H9ZgI+02I9BZSMWCW8keOXsw2R3hSzk7aALQ=="
+        },
         "tinycolor2": {
             "version": "1.4.1",
             "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
diff --git a/package.json b/package.json
index b6beb5a3a..155026d2c 100644
--- a/package.json
+++ b/package.json
@@ -237,4 +237,4 @@
         "xoauth2": "^1.2.0",
         "youtube": "^0.1.0"
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 5d5e78652..2ac7e6c92 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -343,7 +343,7 @@ export class Timeline extends React.Component<FieldViewProps> {
      * context menu function. 
      * opens the timeline or closes the timeline. 
      */
-    timelineContextMenu = (e: MouseEvent): void => {
+    timelineContextMenu = (e: React.MouseEvent): void => {
         ContextMenu.Instance.addItem({
             description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
                 this._timelineVisible = !this._timelineVisible;
diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss
index b54399307..283163ea7 100644
--- a/src/client/views/animationtimeline/TimelineOverview.scss
+++ b/src/client/views/animationtimeline/TimelineOverview.scss
@@ -72,7 +72,7 @@ $timelineDark: #77a1aa;
     position: relative;
     padding: 0px;
     margin: 0px;
-    // width: 100%;
+    width: 100%;
     height: 4px;
     background-color: $timelineColor;
     border-radius: 20px;
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 5d6378068..6358982c4 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -55,7 +55,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
     @action
     setOverviewWidth() {
-        let width = $("#timelineOverview").width();
+        const width = $("#timelineOverview").width();
         // console.log($("timelineOverview"))
         if (width) this.overviewBarWidth = width;
         // else this.overviewBarWidth = 0;
@@ -77,7 +77,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     onPanX = (e: PointerEvent) => {
         e.stopPropagation();
         e.preventDefault();
-        let movX = (this.props.visibleStart / this.props.totalLength) * (this.DEFAULT_WIDTH) + e.movementX;
+        const movX = (this.props.visibleStart / this.props.totalLength) * (this.DEFAULT_WIDTH) + e.movementX;
         // let movX = (this.props.visibleStart / this.props.totalLength) * (this.overviewWidth) + e.movementX;
         this.props.movePanX((movX / (this.DEFAULT_WIDTH)) * this.props.totalLength);
         // this.props.movePanX((movX / (this.overviewWidth) * this.props.totalLength);
@@ -95,22 +95,22 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     onScrubberDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        if (!this.props.isAuthoring) {
+        // if (!this.props.isAuthoring) {
         document.removeEventListener("pointermove", this.onScrubberMove);
         document.removeEventListener("pointerup", this.onScrubberUp);
         document.addEventListener("pointermove", this.onScrubberMove);
         document.addEventListener("pointerup", this.onScrubberUp);
-        }
+        // }
     }
 
     @action
     onScrubberMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let scrubberRef = this._scrubberRef.current!;
-        let left = scrubberRef.getBoundingClientRect().left;
+        const scrubberRef = this._scrubberRef.current!;
+        const left = scrubberRef.getBoundingClientRect().left;
         // left = e.screenX;
-        let offsetX = Math.round(e.clientX - left);
+        const offsetX = Math.round(e.clientX - left);
         this.props.changeCurrentBarX((offsetX / (this.DEFAULT_WIDTH) * this.props.totalLength) + this.props.currentBarX);
         // this.props.changeCurrentBarX(e.screenX)
     }
@@ -125,9 +125,9 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
     @action
     getTimes() {
-        let vis = KeyframeFunc.convertPixelTime(this.props.visibleLength, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
-        let x = KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
-        let start = KeyframeFunc.convertPixelTime(this.props.visibleStart, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        const vis = KeyframeFunc.convertPixelTime(this.props.visibleLength, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        const x = KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        const start = KeyframeFunc.convertPixelTime(this.props.visibleStart, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         this.visibleTime = vis;
         this.currentX = x;
         this.visibleStart = start;
@@ -137,19 +137,20 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     }
 
     render() {
+        console.log("RERENDERED!"); 
         this.setOverviewWidth();
         this.getTimes();
 
-        let percentVisible = this.visibleTime / this.props.time;
-        let visibleBarWidth = percentVisible * this.overviewBarWidth;
+        const percentVisible = this.visibleTime / this.props.time;
+        const visibleBarWidth = percentVisible * this.overviewBarWidth;
 
-        let percentScrubberStart = this.currentX / this.props.time;
-        let scrubberStart = percentScrubberStart * this.overviewBarWidth;
+        const percentScrubberStart = this.currentX / this.props.time;
+        const scrubberStart = percentScrubberStart * this.overviewBarWidth;
 
-        let percentBarStart = this.visibleStart / this.props.time;
-        let barStart = percentBarStart * this.overviewBarWidth;
+        const percentBarStart = this.visibleStart / this.props.time;
+        const barStart = percentBarStart * this.overviewBarWidth;
 
-        let timeline = this.props.isAuthoring ? [
+        const timeline = this.props.isAuthoring ? [
 
             <div key="timeline-overview-container" className="timeline-overview-container" id="timelineOverview">
                 <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c61dcd21f..56b3b3bc0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -966,7 +966,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     onContextMenu = (e: React.MouseEvent) => {
         const layoutItems: ContextMenuProps[] = [];
-
         layoutItems.push({ description: "reset view", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
         layoutItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" });
         layoutItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
@@ -1019,6 +1018,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             icon: "eye"
         });
         ContextMenu.Instance.addItem({ description: "Freeform Options ...", subitems: layoutItems, icon: "eye" });
+        this._timelineRef.current!.timelineContextMenu(e); 
     }
 
 
@@ -1070,21 +1070,24 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         // if isAnnotationOverlay is set, then children will be stored in the extension document for the fieldKey.
         // otherwise, they are stored in fieldKey.  All annotations to this document are stored in the extension document
         // let lodarea = this.Document[WidthSym]() * this.Document[HeightSym]() / this.props.ScreenToLocalTransform().Scale / this.props.ScreenToLocalTransform().Scale;
-        return <div className={"collectionfreeformview-container"}
-            ref={this.createDashEventsTarget}
-            onWheel={this.onPointerWheel}//pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined,
-            onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onContextMenu={this.onContextMenu}
-            style={{
-                pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined,
-                transform: this.contentScaling ? `scale(${this.contentScaling})` : "",
-                transformOrigin: this.contentScaling ? "left top" : "",
-                width: this.contentScaling ? `${100 / this.contentScaling}%` : "",
-                height: this.contentScaling ? `${100 / this.contentScaling}%` : this.isAnnotationOverlay ? (this.props.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
-            }}>
-            {!this.Document._LODdisable && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? // && this.props.CollectionView && lodarea < NumCast(this.Document.LODarea, 100000) ?
-                this.placeholder : this.marqueeView}
+        return <div>
+            <div className={"collectionfreeformview-container"}
+                ref={this.createDashEventsTarget}
+                onWheel={this.onPointerWheel}//pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined,
+                onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onContextMenu={this.onContextMenu}
+                style={{
+                    pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined,
+                    transform: this.contentScaling ? `scale(${this.contentScaling})` : "",
+                    transformOrigin: this.contentScaling ? "left top" : "",
+                    width: this.contentScaling ? `${100 / this.contentScaling}%` : "",
+                    height: this.contentScaling ? `${100 / this.contentScaling}%` : this.isAnnotationOverlay ? (this.props.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
+                }}>            
+                {/* <Timeline ref={this._timelineRef} {...this.props} /> */}
+                {!this.Document._LODdisable && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? // && this.props.CollectionView && lodarea < NumCast(this.Document.LODarea, 100000) ?
+                    this.placeholder : this.marqueeView}
+                <CollectionFreeFormOverlayView elements={this.elementFunc} />
+            </div>            
             <Timeline ref={this._timelineRef} {...this.props} />
-            <CollectionFreeFormOverlayView elements={this.elementFunc} />
         </div>;
     }
 }
-- 
cgit v1.2.3-70-g09d2


From fb9cbca164800c26baee2d0bde171e9e052b7866 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sun, 9 Feb 2020 14:55:25 -0500
Subject: taking out right information

---
 package-lock.json                               | 142 +++++++++++++++---------
 package.json                                    |   4 +-
 src/client/views/animationtimeline/Timeline.tsx |  23 +++-
 3 files changed, 111 insertions(+), 58 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/package-lock.json b/package-lock.json
index 1f87e1493..5684789c1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6533,9 +6533,9 @@
             "dev": true
         },
         "https-proxy-agent": {
-            "version": "2.2.2",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
-            "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==",
+            "version": "2.2.4",
+            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
+            "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
             "requires": {
                 "agent-base": "^4.3.0",
                 "debug": "^3.1.0"
@@ -8844,9 +8844,9 @@
             "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
         },
         "npm": {
-            "version": "6.13.6",
-            "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.6.tgz",
-            "integrity": "sha512-NomC08kv7HIl1FOyLOe9Hp89kYsOsvx52huVIJ7i8hFW8Xp65lDwe/8wTIrh9q9SaQhA8hTrfXPh3BEL3TmMpw==",
+            "version": "6.13.7",
+            "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.7.tgz",
+            "integrity": "sha512-X967EKTT407CvgrWFjXusnPh0VLERcmR9hZFSVgkEquOomZkvpwLJ5zrQ3qrG9SpPLKJE4bPLUu76exKQ4a3Cg==",
             "requires": {
                 "JSONStream": "^1.3.5",
                 "abbrev": "~1.1.1",
@@ -8854,7 +8854,7 @@
                 "ansistyles": "~0.1.3",
                 "aproba": "^2.0.0",
                 "archy": "~1.0.0",
-                "bin-links": "^1.1.6",
+                "bin-links": "^1.1.7",
                 "bluebird": "^3.5.5",
                 "byte-size": "^5.0.1",
                 "cacache": "^12.0.3",
@@ -8897,7 +8897,7 @@
                 "libnpmorg": "^1.0.1",
                 "libnpmsearch": "^2.0.2",
                 "libnpmteam": "^1.0.2",
-                "libnpx": "^10.2.0",
+                "libnpx": "^10.2.2",
                 "lock-verify": "^2.1.0",
                 "lockfile": "^1.0.4",
                 "lodash._baseindexof": "*",
@@ -8916,7 +8916,7 @@
                 "mississippi": "^3.0.0",
                 "mkdirp": "~0.5.1",
                 "move-concurrently": "^1.0.1",
-                "node-gyp": "^5.0.5",
+                "node-gyp": "^5.0.7",
                 "nopt": "~4.0.1",
                 "normalize-package-data": "^2.5.0",
                 "npm-audit-report": "^1.3.2",
@@ -9113,7 +9113,7 @@
                     }
                 },
                 "bin-links": {
-                    "version": "1.1.6",
+                    "version": "1.1.7",
                     "bundled": true,
                     "requires": {
                         "bluebird": "^3.5.3",
@@ -9593,7 +9593,7 @@
                     }
                 },
                 "env-paths": {
-                    "version": "1.0.0",
+                    "version": "2.2.0",
                     "bundled": true
                 },
                 "err-code": {
@@ -9896,7 +9896,7 @@
                     }
                 },
                 "get-caller-file": {
-                    "version": "1.0.2",
+                    "version": "1.0.3",
                     "bundled": true
                 },
                 "get-stream": {
@@ -10091,7 +10091,7 @@
                     }
                 },
                 "invert-kv": {
-                    "version": "1.0.0",
+                    "version": "2.0.0",
                     "bundled": true
                 },
                 "ip": {
@@ -10249,10 +10249,10 @@
                     "bundled": true
                 },
                 "lcid": {
-                    "version": "1.0.0",
+                    "version": "2.0.0",
                     "bundled": true,
                     "requires": {
-                        "invert-kv": "^1.0.0"
+                        "invert-kv": "^2.0.0"
                     }
                 },
                 "libcipm": {
@@ -10411,7 +10411,7 @@
                     }
                 },
                 "libnpx": {
-                    "version": "10.2.0",
+                    "version": "10.2.2",
                     "bundled": true,
                     "requires": {
                         "dotenv": "^5.0.1",
@@ -10541,15 +10541,30 @@
                         "ssri": "^6.0.0"
                     }
                 },
+                "map-age-cleaner": {
+                    "version": "0.1.3",
+                    "bundled": true,
+                    "requires": {
+                        "p-defer": "^1.0.0"
+                    }
+                },
                 "meant": {
                     "version": "1.0.1",
                     "bundled": true
                 },
                 "mem": {
-                    "version": "1.1.0",
+                    "version": "4.3.0",
                     "bundled": true,
                     "requires": {
-                        "mimic-fn": "^1.0.0"
+                        "map-age-cleaner": "^0.1.1",
+                        "mimic-fn": "^2.0.0",
+                        "p-is-promise": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "mimic-fn": {
+                            "version": "2.1.0",
+                            "bundled": true
+                        }
                     }
                 },
                 "mime-db": {
@@ -10563,10 +10578,6 @@
                         "mime-db": "~1.35.0"
                     }
                 },
-                "mimic-fn": {
-                    "version": "1.2.0",
-                    "bundled": true
-                },
                 "minimatch": {
                     "version": "3.0.4",
                     "bundled": true,
@@ -10644,6 +10655,10 @@
                     "version": "0.0.7",
                     "bundled": true
                 },
+                "nice-try": {
+                    "version": "1.0.5",
+                    "bundled": true
+                },
                 "node-fetch-npm": {
                     "version": "2.0.2",
                     "bundled": true,
@@ -10654,33 +10669,20 @@
                     }
                 },
                 "node-gyp": {
-                    "version": "5.0.5",
+                    "version": "5.0.7",
                     "bundled": true,
                     "requires": {
-                        "env-paths": "^1.0.0",
-                        "glob": "^7.0.3",
-                        "graceful-fs": "^4.1.2",
-                        "mkdirp": "^0.5.0",
-                        "nopt": "2 || 3",
-                        "npmlog": "0 || 1 || 2 || 3 || 4",
-                        "request": "^2.87.0",
-                        "rimraf": "2",
-                        "semver": "~5.3.0",
+                        "env-paths": "^2.2.0",
+                        "glob": "^7.1.4",
+                        "graceful-fs": "^4.2.2",
+                        "mkdirp": "^0.5.1",
+                        "nopt": "^4.0.1",
+                        "npmlog": "^4.1.2",
+                        "request": "^2.88.0",
+                        "rimraf": "^2.6.3",
+                        "semver": "^5.7.1",
                         "tar": "^4.4.12",
-                        "which": "1"
-                    },
-                    "dependencies": {
-                        "nopt": {
-                            "version": "3.0.6",
-                            "bundled": true,
-                            "requires": {
-                                "abbrev": "1"
-                            }
-                        },
-                        "semver": {
-                            "version": "5.3.0",
-                            "bundled": true
-                        }
+                        "which": "^1.3.1"
                     }
                 },
                 "nopt": {
@@ -10874,12 +10876,38 @@
                     "bundled": true
                 },
                 "os-locale": {
-                    "version": "2.1.0",
+                    "version": "3.1.0",
                     "bundled": true,
                     "requires": {
-                        "execa": "^0.7.0",
-                        "lcid": "^1.0.0",
-                        "mem": "^1.1.0"
+                        "execa": "^1.0.0",
+                        "lcid": "^2.0.0",
+                        "mem": "^4.0.0"
+                    },
+                    "dependencies": {
+                        "cross-spawn": {
+                            "version": "6.0.5",
+                            "bundled": true,
+                            "requires": {
+                                "nice-try": "^1.0.4",
+                                "path-key": "^2.0.1",
+                                "semver": "^5.5.0",
+                                "shebang-command": "^1.2.0",
+                                "which": "^1.2.9"
+                            }
+                        },
+                        "execa": {
+                            "version": "1.0.0",
+                            "bundled": true,
+                            "requires": {
+                                "cross-spawn": "^6.0.0",
+                                "get-stream": "^4.0.0",
+                                "is-stream": "^1.1.0",
+                                "npm-run-path": "^2.0.0",
+                                "p-finally": "^1.0.0",
+                                "signal-exit": "^3.0.0",
+                                "strip-eof": "^1.0.0"
+                            }
+                        }
                     }
                 },
                 "os-tmpdir": {
@@ -10894,10 +10922,18 @@
                         "os-tmpdir": "^1.0.0"
                     }
                 },
+                "p-defer": {
+                    "version": "1.0.0",
+                    "bundled": true
+                },
                 "p-finally": {
                     "version": "1.0.0",
                     "bundled": true
                 },
+                "p-is-promise": {
+                    "version": "2.1.0",
+                    "bundled": true
+                },
                 "p-limit": {
                     "version": "1.2.0",
                     "bundled": true,
@@ -11872,14 +11908,14 @@
                     "bundled": true
                 },
                 "yargs": {
-                    "version": "11.0.0",
+                    "version": "11.1.1",
                     "bundled": true,
                     "requires": {
                         "cliui": "^4.0.0",
                         "decamelize": "^1.1.1",
                         "find-up": "^2.1.0",
                         "get-caller-file": "^1.0.1",
-                        "os-locale": "^2.0.0",
+                        "os-locale": "^3.1.0",
                         "require-directory": "^2.1.1",
                         "require-main-filename": "^1.0.1",
                         "set-blocking": "^2.0.0",
@@ -17955,7 +17991,7 @@
         },
         "wrap-ansi": {
             "version": "2.1.0",
-            "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
             "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
             "requires": {
                 "string-width": "^1.0.1",
diff --git a/package.json b/package.json
index 155026d2c..5b2818c33 100644
--- a/package.json
+++ b/package.json
@@ -176,7 +176,7 @@
         "nodemailer": "^5.1.1",
         "nodemon": "^1.19.4",
         "normalize.css": "^8.0.1",
-        "npm": "^6.13.6",
+        "npm": "^6.13.7",
         "p-limit": "^2.2.0",
         "passport": "^0.4.0",
         "passport-google-oauth20": "^2.0.0",
@@ -226,8 +226,8 @@
         "socket.io": "^2.3.0",
         "socket.io-client": "^2.3.0",
         "solr-node": "^1.2.1",
-        "tiny-timer": "^1.3.0",
         "standard-http-error": "^2.0.1",
+        "tiny-timer": "^1.3.0",
         "typescript-collections": "^1.3.3",
         "url-loader": "^1.1.2",
         "uuid": "^3.4.0",
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 2ac7e6c92..e4af43e0a 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -433,6 +433,8 @@ export class Timeline extends React.Component<FieldViewProps> {
             lengthString = "";
         }
 
+        // let rightInfo = this.timeIndicator;
+
         return (
             <div key="timeline_toolbox" className="timeline-toolbox" style={{ height: `${size}px` }}>
                 <div className="playbackControls">
@@ -452,15 +454,30 @@ export class Timeline extends React.Component<FieldViewProps> {
                         </div>
                     </div>
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
-                        <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{lengthString}</div>
-                        <input className="time-input" disabled style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
-                        <div style={{ width: "100%", display: !this.props.Document.isATOn ? "flex" : "none" }}>Current: {this.getCurrentTime()}</div>
+                        {this.timeIndicator(lengthString)}
+                        {/* {rightInfo} */}
                     </div>
                 </div>
             </div>
         );
     }
 
+    timeIndicator(lengthString: string) {
+        if (this.props.Document.isATOn) {
+            return (
+                <>
+                    <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{lengthString}</div>
+                    <input className="time-input" disabled style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
+                </>
+            );
+        }
+        else {
+            return (
+                <div style={{ width: "100%", display: !this.props.Document.isATOn ? "flex" : "none" }}>Current: {this.getCurrentTime()}</div>
+            );
+        }
+    }
+
     /**
      * manual time input (kinda broken right now)
      */
-- 
cgit v1.2.3-70-g09d2


From eea67eb24b944f13e307915d386f7745078e7d23 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 9 Feb 2020 15:06:45 -0500
Subject: const to let

---
 src/client/views/animationtimeline/Keyframe.tsx    | 74 +++++++++++-----------
 src/client/views/animationtimeline/Timeline.tsx    | 56 ++++++++--------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +-
 3 files changed, 67 insertions(+), 67 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index fd4a3f281..bb557289e 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -36,7 +36,7 @@ export namespace KeyframeFunc {
         let leftMost: (RegionData | undefined) = undefined;
         let rightMost: (RegionData | undefined) = undefined;
         DocListCast(regions).forEach(region => {
-            let neighbor = RegionData(region);
+            const neighbor = RegionData(region);
             if (currentRegion.position! > neighbor.position) {
                 if (!leftMost || neighbor.position > leftMost.position) {
                     leftMost = neighbor;
@@ -57,7 +57,7 @@ export namespace KeyframeFunc {
     export const calcMinLeft = async (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closet keyframe to the left
         let leftKf: (Doc | undefined) = undefined;
         let time: number = 0;
-        let keyframes = await DocListCastAsync(region.keyframes!);
+        const keyframes = await DocListCastAsync(region.keyframes!);
         keyframes!.forEach((kf) => {
             let compTime = currentBarX;
             if (ref) compTime = NumCast(ref.time);
@@ -73,7 +73,7 @@ export namespace KeyframeFunc {
     export const calcMinRight = async (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closest keyframe to the right 
         let rightKf: (Doc | undefined) = undefined;
         let time: number = Infinity;
-        let keyframes = await DocListCastAsync(region.keyframes!);
+        const keyframes = await DocListCastAsync(region.keyframes!);
         keyframes!.forEach((kf) => {
             let compTime = currentBarX;
             if (ref) compTime = NumCast(ref.time);
@@ -86,7 +86,7 @@ export namespace KeyframeFunc {
     };
 
     export const defaultKeyframe = () => {
-        let regiondata = new Doc(); //creating regiondata in MILI
+        const regiondata = new Doc(); //creating regiondata in MILI
         regiondata.duration = 4000;
         regiondata.position = 0;
         regiondata.fadeIn = 1000;
@@ -98,7 +98,7 @@ export namespace KeyframeFunc {
 
 
     export const convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time", tickSpacing: number, tickIncrement: number) => {
-        let time = dir === "pixel" ? (pos * tickSpacing) / tickIncrement : (pos / tickSpacing) * tickIncrement;
+        const time = dir === "pixel" ? (pos * tickSpacing) / tickIncrement : (pos / tickSpacing) * tickIncrement;
         switch (unit) {
             case "mili":
                 return time;
@@ -180,10 +180,10 @@ export class Keyframe extends React.Component<IProps> {
     componentDidMount() {
         setTimeout(() => {      //giving it a temporary 1sec delay... 
             if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();   
-            let start = this.props.makeKeyData(this.regiondata, this.regiondata.position,  KeyframeFunc.KeyframeType.end);
-            let fadeIn = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade);
-            let fadeOut = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade);
-            let finish = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration,KeyframeFunc.KeyframeType.end);
+            const start = this.props.makeKeyData(this.regiondata, this.regiondata.position,  KeyframeFunc.KeyframeType.end);
+            const fadeIn = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade);
+            const fadeOut = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade);
+            const finish = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration,KeyframeFunc.KeyframeType.end);
             (fadeIn.key as Doc).opacity = 1;
             (fadeOut.key as Doc).opacity = 1;
             (start.key as Doc).opacity = 0.1;
@@ -199,7 +199,7 @@ export class Keyframe extends React.Component<IProps> {
     onBarPointerDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let clientX = e.clientX;
+        const clientX = e.clientX;
         if (this._doubleClickEnabled) {
             this.createKeyframe(clientX);
             this._doubleClickEnabled = false;
@@ -224,10 +224,10 @@ export class Keyframe extends React.Component<IProps> {
         if (e.movementX !== 0) {
             this._mouseToggled = true;
         }
-        let left = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions)!;
-        let right = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions!);
-        let prevX = this.regiondata.position;
-        let futureX = this.regiondata.position + KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        const left = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions)!;
+        const right = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions!);
+        const prevX = this.regiondata.position;
+        const futureX = this.regiondata.position + KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         if (futureX <= 0) {
             this.regiondata.position = 0;
         } else if ((left && left.position + left.duration >= futureX)) {
@@ -237,7 +237,7 @@ export class Keyframe extends React.Component<IProps> {
         } else {
             this.regiondata.position = futureX;
         }
-        let movement = this.regiondata.position - prevX;
+        const movement = this.regiondata.position - prevX;
         this.keyframes.forEach(kf => {
             kf.time = NumCast(kf.time) + movement;
         });
@@ -267,9 +267,9 @@ export class Keyframe extends React.Component<IProps> {
     onDragResizeLeft = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let bar = this._bar.current!;
-        let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
-        let leftRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions);
+        const bar = this._bar.current!;
+        const offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        const leftRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions);
         if (leftRegion && this.regiondata.position + offset <= leftRegion.position + leftRegion.duration) {
             this.regiondata.position = leftRegion.position + leftRegion.duration;
             this.regiondata.duration = NumCast(this.keyframes[this.keyframes.length - 1].time) - (leftRegion.position + leftRegion.duration);
@@ -292,10 +292,10 @@ export class Keyframe extends React.Component<IProps> {
     onDragResizeRight = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let bar = this._bar.current!;
-        let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
-        let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions);
-        let fadeOutKeyframeTime = NumCast(this.keyframes[this.keyframes.length - 3].time);
+        const bar = this._bar.current!;
+        const offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        const rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions);
+        const fadeOutKeyframeTime = NumCast(this.keyframes[this.keyframes.length - 3].time);
         if (this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= fadeOutKeyframeTime) { //case 1: when third to last keyframe is in the way 
             this.regiondata.duration = fadeOutKeyframeTime - this.regiondata.position + this.regiondata.fadeOut;
         } else if (rightRegion && (this.regiondata.position + this.regiondata.duration + offset >= rightRegion.position)) {
@@ -311,10 +311,10 @@ export class Keyframe extends React.Component<IProps> {
     @action
     createKeyframe = async (clientX: number) => {
         this._mouseToggled = true;
-        let bar = this._bar.current!;
-        let offset = KeyframeFunc.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
+        const bar = this._bar.current!;
+        const offset = KeyframeFunc.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement);
         if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
-            let position = this.regiondata.position;
+            const position = this.regiondata.position;
             this.props.makeKeyData(this.regiondata, Math.round(position + offset), KeyframeFunc.KeyframeType.default);
             this.regiondata.hasData = true; 
             this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied
@@ -337,7 +337,7 @@ export class Keyframe extends React.Component<IProps> {
     makeKeyframeMenu = (kf: Doc, e: MouseEvent) => {
         TimelineMenu.Instance.addItem("button", "Show Data", () => {
             runInAction(() => {
-                let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { _width: 300, _height: 300 });
+                const kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { _width: 300, _height: 300 });
                 CollectionDockingView.AddRightSplit(kvp, (kf.key as Doc).data as Doc);
             });
         }),
@@ -350,7 +350,7 @@ export class Keyframe extends React.Component<IProps> {
             TimelineMenu.Instance.addItem("input", "Move", (val) => {
                 runInAction(() => {
                     let cannotMove: boolean = false;
-                    let kfIndex: number = this.keyframes.indexOf(kf);
+                    const kfIndex: number = this.keyframes.indexOf(kf);
                     if (val < 0 || (val < NumCast(this.keyframes[kfIndex - 1].time) || val > NumCast(this.keyframes[kfIndex + 1].time))) {
                         cannotMove = true;
                     }
@@ -401,7 +401,7 @@ export class Keyframe extends React.Component<IProps> {
             }),
             TimelineMenu.Instance.addItem("input", `position: ${this.regiondata.position}ms`, (val) => {
                 runInAction(() => {
-                    let prevPosition = this.regiondata.position;
+                    const prevPosition = this.regiondata.position;
                     let cannotMove: boolean = false;
                     DocListCast(this.regions).forEach(region => {
                         if (NumCast(region.position) !== this.regiondata.position) {
@@ -454,7 +454,7 @@ export class Keyframe extends React.Component<IProps> {
     onContainerOver = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
         e.preventDefault();
         e.stopPropagation();
-        let div = ref.current!;
+        const div = ref.current!;
         div.style.opacity = "1";
         Doc.BrushDoc(this.props.node);
     }
@@ -466,7 +466,7 @@ export class Keyframe extends React.Component<IProps> {
     onContainerOut = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
         e.preventDefault();
         e.stopPropagation();
-        let div = ref.current!;
+        const div = ref.current!;
         div.style.opacity = "0";
         Doc.UnBrushDoc(this.props.node);
     }
@@ -481,7 +481,7 @@ export class Keyframe extends React.Component<IProps> {
      */
     @action
     drawKeyframes = () => {
-        let keyframeDivs: JSX.Element[] = [];
+        const keyframeDivs: JSX.Element[] = [];
         DocListCast(this.regiondata.keyframes).forEach(kf => {
             if (kf.type as KeyframeFunc.KeyframeType !== KeyframeFunc.KeyframeType.end) {
                 keyframeDivs.push(
@@ -514,14 +514,14 @@ export class Keyframe extends React.Component<IProps> {
      */
     @action
     drawKeyframeDividers = () => {
-        let keyframeDividers: JSX.Element[] = [];
+        const keyframeDividers: JSX.Element[] = [];
         DocListCast(this.regiondata.keyframes).forEach(kf => {
-            let index = this.keyframes.indexOf(kf);
+            const index = this.keyframes.indexOf(kf);
             if (index !== this.keyframes.length - 1) {
-                let right = this.keyframes[index + 1];
-                let bodyRef = React.createRef<HTMLDivElement>();
-                let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
-                let rightPos = KeyframeFunc.convertPixelTime(NumCast(right.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
+                const right = this.keyframes[index + 1];
+                const bodyRef = React.createRef<HTMLDivElement>();
+                const kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
+                const rightPos = KeyframeFunc.convertPixelTime(NumCast(right.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);
                 keyframeDividers.push(
                     <div ref={bodyRef} className="body-container" style={{ left: `${kfPos - this.pixelPosition}px`, width: `${rightPos - kfPos}px` }}
                         onPointerOver={(e) => { e.preventDefault(); e.stopPropagation(); this.onContainerOver(e, bodyRef); }}
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 2ac7e6c92..dc381609e 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -86,7 +86,7 @@ export class Timeline extends React.Component<FieldViewProps> {
      */
     @computed
     private get children(): List<Doc> {
-        let extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type));
+        const extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type));
         if (extendedDocument) {
             if (this.props.Document.data_ext) {
                 return Cast((Cast(this.props.Document.data_ext, Doc) as Doc).annotations, listSpec(Doc)) as List<Doc>;
@@ -99,7 +99,7 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     /////////lifecycle functions////////////
     componentWillMount() {
-        let relativeHeight = window.innerHeight / 20; //sets height to arbitrary size, relative to innerHeight
+        const relativeHeight = window.innerHeight / 20; //sets height to arbitrary size, relative to innerHeight
         this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //check if relHeight is less than Maxheight. Else, just set relheight to max
         this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; //offset
         this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; //twice the titleheight + offset
@@ -133,7 +133,7 @@ export class Timeline extends React.Component<FieldViewProps> {
      */
     @action
     drawTicks = () => {
-        let ticks = [];
+        const ticks = [];
         for (let i = 0; i < this._time / this._tickIncrement; i++) {
             ticks.push(<div key={Utils.GenerateGuid()} className="tick" style={{ transform: `translate(${i * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p className="number-label">{this.toReadTime(i * this._tickIncrement)}</p></div>);
         }
@@ -226,9 +226,9 @@ export class Timeline extends React.Component<FieldViewProps> {
     onScrubberMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let scrubberbox = this._infoContainer.current!;
-        let left = scrubberbox.getBoundingClientRect().left;
-        let offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
+        const scrubberbox = this._infoContainer.current!;
+        const left = scrubberbox.getBoundingClientRect().left;
+        const offsetX = Math.round(e.clientX - left) * this.props.ScreenToLocalTransform().Scale;
         this.changeCurrentBarX(offsetX + this._visibleStart); //changes scrubber to clicked scrubber position
     }
 
@@ -239,7 +239,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     onPanDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let clientX = e.clientX;
+        const clientX = e.clientX;
         if (this._doubleClickEnabled) {
             this._doubleClickEnabled = false;
         } else {
@@ -270,8 +270,8 @@ export class Timeline extends React.Component<FieldViewProps> {
         if (e.movementX !== 0 || e.movementY !== 0) {
             this._mouseToggled = true;
         }
-        let trackbox = this._trackbox.current!;
-        let titleContainer = this._titleContainer.current!;
+        const trackbox = this._trackbox.current!;
+        const titleContainer = this._titleContainer.current!;
         this.movePanX(this._visibleStart - e.movementX);
         trackbox.scrollTop = trackbox.scrollTop - e.movementY;
         titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;
@@ -287,7 +287,7 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     @action
     movePanX = (pixel: number) => {
-        let infoContainer = this._infoContainer.current!;
+        const infoContainer = this._infoContainer.current!;
         infoContainer.scrollLeft = pixel;
         this._visibleStart = infoContainer.scrollLeft;
     }
@@ -309,7 +309,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     onResizeMove = (e: PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let offset = e.clientY - this._timelineContainer.current!.getBoundingClientRect().bottom;
+        const offset = e.clientY - this._timelineContainer.current!.getBoundingClientRect().bottom;
         // let offset = 0;
         if (this._containerHeight + offset <= this.MIN_CONTAINER_HEIGHT) {
             this._containerHeight = this.MIN_CONTAINER_HEIGHT;
@@ -326,10 +326,10 @@ export class Timeline extends React.Component<FieldViewProps> {
     @action
     toReadTime = (time: number): string => {
         time = time / 1000;
-        var inSeconds = Math.round((time * 100)) / 100;
+        const inSeconds = Math.round((time * 100)) / 100;
         // var inSeconds = parseFloat(time.toFixed(2));
         // const inSeconds = (Math.floor(time) / 1000);
-        let min: (string | number) = Math.floor(inSeconds / 60);
+        const min: (string | number) = Math.floor(inSeconds / 60);
         let sec: (string | number) = inSeconds % 60;
 
         if (Math.floor(sec / 10) === 0) {
@@ -360,12 +360,12 @@ export class Timeline extends React.Component<FieldViewProps> {
     onWheelZoom = (e: React.WheelEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        let offset = e.clientX - this._infoContainer.current!.getBoundingClientRect().left;
-        let prevTime = KeyframeFunc.convertPixelTime(this._visibleStart + offset, "mili", "time", this._tickSpacing, this._tickIncrement);
-        let prevCurrent = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
+        const offset = e.clientX - this._infoContainer.current!.getBoundingClientRect().left;
+        const prevTime = KeyframeFunc.convertPixelTime(this._visibleStart + offset, "mili", "time", this._tickSpacing, this._tickIncrement);
+        const prevCurrent = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
         e.deltaY < 0 ? this.zoom(true) : this.zoom(false);
-        let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement);
-        let currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, "mili", "pixel", this._tickSpacing, this._tickIncrement);
+        const currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement);
+        const currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, "mili", "pixel", this._tickSpacing, this._tickIncrement);
         this._infoContainer.current!.scrollLeft = currPixel - offset;
         this._visibleStart = currPixel - offset > 0 ? currPixel - offset : 0;
         this._visibleStart += this._visibleLength + this._visibleStart > this._totalLength ? this._totalLength - (this._visibleStart + this._visibleLength) : 0;
@@ -396,7 +396,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                 spacingChange -= 5;
             }
         }
-        let finalLength = spacingChange * (this._time / incrementChange);
+        const finalLength = spacingChange * (this._time / incrementChange);
         if (finalLength >= this._infoContainer.current!.getBoundingClientRect().width) {
             this._totalLength = finalLength;
             this._tickSpacing = spacingChange;
@@ -408,19 +408,19 @@ export class Timeline extends React.Component<FieldViewProps> {
      * tool box includes the toggle buttons at the top of the timeline (both editing mode and play mode)
      */
     private timelineToolBox = (scale: number) => {
-        let size = 40 * scale; //50 is default
-        let iconSize = 25;
+        const size = 40 * scale; //50 is default
+        const iconSize = 25;
 
         //decides if information should be omitted because the timeline is very small
         // if its less than 950 pixels then it's going to be overlapping
         let shouldCompress = false;
-        let width: number = this.props.PanelWidth();
+        const width: number = this.props.PanelWidth();
         if (width < 850) {
             shouldCompress = true;
         }
 
         let modeString, overviewString, lengthString;
-        let modeType = this.props.Document.isATOn ? "Author" : "Play";
+        const modeType = this.props.Document.isATOn ? "Author" : "Play";
 
         if (!shouldCompress) {
             modeString = "Mode: " + modeType;
@@ -489,9 +489,9 @@ export class Timeline extends React.Component<FieldViewProps> {
      * turns on the toggle button (the purple slide button that changes from editing mode and play mode
      */
     private toggleHandle = () => {
-        let roundToggle = this._roundToggleRef.current!;
-        let roundToggleContainer = this._roundToggleContainerRef.current!;
-        let timelineContainer = this._timelineContainer.current!;
+        const roundToggle = this._roundToggleRef.current!;
+        const roundToggleContainer = this._roundToggleContainerRef.current!;
+        const timelineContainer = this._timelineContainer.current!;
         if (BoolCast(this.props.Document.isATOn)) {
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff";
@@ -522,9 +522,9 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     // @computed
     getCurrentTime = () => {
-        let current = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
+        const current = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
         // console.log(this._currentBarX)
-        return this.toReadTime(current); ``
+        return this.toReadTime(current); 
         // return (Math.floor(current) / 1000)
         // return current / 1000.0;
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 56b3b3bc0..ef1ec5e78 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -809,7 +809,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     doFreeformLayout(poolData: Map<string, any>) {
         const layoutDocs = this.childLayoutPairs.map(pair => pair.layout);
         const initResult = this.Document.arrangeInit && this.Document.arrangeInit.script.run({ docs: layoutDocs, collection: this.Document }, console.log);
-        let state = initResult && initResult.success ? initResult.result.scriptState : undefined;
+        const state = initResult && initResult.success ? initResult.result.scriptState : undefined;
         const elements = initResult && initResult.success ? this.viewDefsToJSX(initResult.result.views) : [];
 
         this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map((pair, i) => {
@@ -1001,7 +1001,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             }
         });
         //@ts-ignore
-        let subitems: ContextMenuProps[] =
+        const subitems: ContextMenuProps[] =
             DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data).map((note, i) => ({
                 description: (i + 1) + ": " + StrCast(note.title),
                 event: () => console.log("Hi"),
-- 
cgit v1.2.3-70-g09d2


From 61d4938de06a09687eca4a1549d48b1009aa4134 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sun, 9 Feb 2020 15:07:55 -0500
Subject: rounding fix

---
 src/client/views/animationtimeline/Timeline.tsx | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index e4af43e0a..cbdbd07b149 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -326,15 +326,18 @@ export class Timeline extends React.Component<FieldViewProps> {
     @action
     toReadTime = (time: number): string => {
         time = time / 1000;
-        var inSeconds = Math.round((time * 100)) / 100;
+        const inSeconds = Math.round(time * 100) / 100;
+
+        // console.log(inSeconds)
         // var inSeconds = parseFloat(time.toFixed(2));
         // const inSeconds = (Math.floor(time) / 1000);
-        let min: (string | number) = Math.floor(inSeconds / 60);
-        let sec: (string | number) = inSeconds % 60;
+        const min: (string | number) = Math.floor(inSeconds / 60);
+        let sec: (string | number) = (Math.round((inSeconds % 60) * 100) / 100);
 
         if (Math.floor(sec / 10) === 0) {
             sec = "0" + sec;
         }
+        // sec = Number.parseFloat(sec).toFixed(2);
         return `${min}:${sec}`;
     }
 
-- 
cgit v1.2.3-70-g09d2


From ba835bbe5b31e2ad0badc9f960b75f639e0b02e0 Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Sun, 9 Feb 2020 15:50:43 -0500
Subject: moving...

---
 src/client/views/animationtimeline/Timeline.tsx    | 23 ++++++++++++++++++++--
 .../views/animationtimeline/TimelineOverview.tsx   |  1 -
 src/client/views/animationtimeline/Track.tsx       |  7 +++++++
 3 files changed, 28 insertions(+), 3 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index dc381609e..42bb02e85 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -342,6 +342,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     /**
      * context menu function. 
      * opens the timeline or closes the timeline. 
+     * Used in: Freeform
      */
     timelineContextMenu = (e: React.MouseEvent): void => {
         ContextMenu.Instance.addItem({
@@ -493,6 +494,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         const roundToggleContainer = this._roundToggleContainerRef.current!;
         const timelineContainer = this._timelineContainer.current!;
         if (BoolCast(this.props.Document.isATOn)) {
+            //turning on playmode...
             roundToggle.style.transform = "translate(0px, 0px)";
             roundToggle.style.animationName = "turnoff";
             roundToggleContainer.style.animationName = "turnoff";
@@ -500,7 +502,9 @@ export class Timeline extends React.Component<FieldViewProps> {
             timelineContainer.style.top = `${-this._containerHeight}px`;
             this.props.Document.isATOn = false;
             this._isAuthoring = false;
+            this.tracks();
         } else {
+            //turning on authoring mode...
             roundToggle.style.transform = "translate(20px, 0px)";
             roundToggle.style.animationName = "turnon";
             roundToggleContainer.style.animationName = "turnon";
@@ -524,12 +528,24 @@ export class Timeline extends React.Component<FieldViewProps> {
     getCurrentTime = () => {
         const current = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
         // console.log(this._currentBarX)
-        return this.toReadTime(current); 
+        return this.toReadTime(current);
         // return (Math.floor(current) / 1000)
         // return current / 1000.0;
     }
 
+    @observable private mapOfTracks: (Track | null)[] = [];
 
+    @action
+    tracks = () => {
+        console.log(this.mapOfTracks.length);
+        this.mapOfTracks.forEach(track => {
+            if (track !== null) {
+                track.getLastRegion();
+            } else {
+
+            }
+        });
+    }
     /**
      * if you have any question here, just shoot me an email or text. 
      * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
@@ -552,7 +568,10 @@ export class Timeline extends React.Component<FieldViewProps> {
                                     <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div>
                                 </div>
                                 <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
-                                    {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} />)}
+                                    {DocListCast(this.children).map(doc => {
+                                        const track = <Track ref={ref => { this.mapOfTracks.push(ref); }} node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} />
+                                        return track;
+                                    })}
                                 </div>
                             </div>
                             <div className="currentTime">Current: {this.getCurrentTime()}</div>
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 66f6a9482..b8c639825 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -135,7 +135,6 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     }
 
     render() {
-        console.log("RERENDERED!"); 
         this.setOverviewWidth();
         this.getTimes();
 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 84edc6e0a..620668db7 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -80,6 +80,13 @@ export class Track extends React.Component<IProps> {
     }
     ////////////////////////////////
 
+
+    getLastRegion = () => {
+
+        console.log((this.regions[this.regions.length - 1] as Doc).time); 
+        return this.regions[this.regions.length - 1] as Doc; 
+    }
+
     /**
      * keyframe save logic. Needs to be changed so it's more efficient
      * 
-- 
cgit v1.2.3-70-g09d2


From 79f70eebe0a29f8f3d759eff82dd3446ac3d5ed1 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sun, 9 Feb 2020 16:14:04 -0500
Subject: done with ui bugs

---
 src/client/views/animationtimeline/Timeline.scss   |  3 ++
 src/client/views/animationtimeline/Timeline.tsx    | 11 +++---
 .../views/animationtimeline/TimelineOverview.tsx   | 45 +++++++++++-----------
 3 files changed, 30 insertions(+), 29 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index ce8c845df..a99d017f4 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -42,14 +42,17 @@ $timelineDark: #77a1aa;
 
         .time-box {
             margin-left: 5px;
+            min-width: 140px;
             display: flex;
             justify-content: center;
             align-items: center;
+            // grid-column-start: line2;
         }
 
         .mode-box {
             display: flex;
             margin-left: 5px;
+            // grid-column-start: line3;
         }
 
         .overview-box {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index e0f70dd43..3c4c5c93f 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -458,7 +458,6 @@ export class Timeline extends React.Component<FieldViewProps> {
                     </div>
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
                         {this.timeIndicator(lengthString)}
-                        {/* {rightInfo} */}
                     </div>
                 </div>
             </div>
@@ -470,13 +469,16 @@ export class Timeline extends React.Component<FieldViewProps> {
             return (
                 <>
                     <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{lengthString}</div>
-                    <input className="time-input" disabled style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }} placeholder={String(Math.floor(this._time) / 1000) + " s"} ref={this._timeInputRef} onKeyDown={this.onTimeInput} />
+                    <div className="totalTime">1:40.07</div>
                 </>
             );
         }
         else {
             return (
-                <div style={{ width: "100%", display: !this.props.Document.isATOn ? "flex" : "none" }}>Current: {this.getCurrentTime()}</div>
+                <div style={{ flexDirection: "column" }}>
+                    <div className="animation-text" style={{ width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Current: ${this.getCurrentTime()}`}</div>
+                    <div className="animation-text" style={{ width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total: 1:40.07`}</div>
+                </div>
             );
         }
     }
@@ -543,10 +545,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     // @computed
     getCurrentTime = () => {
         const current = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
-        // console.log(this._currentBarX)
         return this.toReadTime(current);
-        // return (Math.floor(current) / 1000)
-        // return current / 1000.0;
     }
 
 
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 66f6a9482..94bbe7074 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -27,6 +27,8 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     @observable private _visibleRef = React.createRef<HTMLDivElement>();
     @observable private _scrubberRef = React.createRef<HTMLDivElement>();
     @observable private overviewBarWidth: number = 0;
+    @observable private playbarWidth: number = 0;
+    @observable private activeOverviewWidth: number = 0;
     @observable private _authoringReaction?: IReactionDisposer;
     @observable private visibleTime: number = 0;
     @observable private currentX: number = 0;
@@ -55,12 +57,17 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
     @action
     setOverviewWidth() {
-        const width = $("#timelineOverview").width();
-        // console.log($("timelineOverview"))
-        if (width) this.overviewBarWidth = width;
-        // else this.overviewBarWidth = 0;
-
-        // console.log(this.overviewBarWidth)
+        const width1 = $("#timelineOverview").width();
+        const width2 = $("#timelinePlay").width();
+        if (width1 && width1 !== 0) this.overviewBarWidth = width1;
+        if (width2 && width2 !== 0) this.playbarWidth = width2;
+
+        if (this.props.isAuthoring) {
+            this.activeOverviewWidth = this.overviewBarWidth;
+        }
+        else {
+            this.activeOverviewWidth = this.playbarWidth;
+        }
     }
 
     @action
@@ -78,9 +85,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         e.stopPropagation();
         e.preventDefault();
         const movX = (this.props.visibleStart / this.props.totalLength) * (this.DEFAULT_WIDTH) + e.movementX;
-        // let movX = (this.props.visibleStart / this.props.totalLength) * (this.overviewWidth) + e.movementX;
         this.props.movePanX((movX / (this.DEFAULT_WIDTH)) * this.props.totalLength);
-        // this.props.movePanX((movX / (this.overviewWidth) * this.props.totalLength);
     }
 
     @action
@@ -95,12 +100,10 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     onScrubberDown = (e: React.PointerEvent) => {
         e.preventDefault();
         e.stopPropagation();
-        // if (!this.props.isAuthoring) {
         document.removeEventListener("pointermove", this.onScrubberMove);
         document.removeEventListener("pointerup", this.onScrubberUp);
         document.addEventListener("pointermove", this.onScrubberMove);
         document.addEventListener("pointerup", this.onScrubberUp);
-        // }
     }
 
     @action
@@ -110,7 +113,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         const scrubberRef = this._scrubberRef.current!;
         const left = scrubberRef.getBoundingClientRect().left;
         const offsetX = Math.round(e.clientX - left);
-        this.props.changeCurrentBarX((((offsetX) / this.overviewBarWidth) * this.props.totalLength) + this.props.currentBarX);
+        this.props.changeCurrentBarX((((offsetX) / this.activeOverviewWidth) * this.props.totalLength) + this.props.currentBarX);
     }
 
     @action
@@ -129,38 +132,34 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         this.visibleTime = vis;
         this.currentX = x;
         this.visibleStart = start;
-        // console.log("getting times")
-        // console.log(x)
-        // console.log(start)
     }
 
     render() {
-        console.log("RERENDERED!"); 
         this.setOverviewWidth();
         this.getTimes();
 
         const percentVisible = this.visibleTime / this.props.time;
-        const visibleBarWidth = percentVisible * this.overviewBarWidth;
+        const visibleBarWidth = percentVisible * this.activeOverviewWidth;
 
         const percentScrubberStart = this.currentX / this.props.time;
-        const scrubberStart = percentScrubberStart * this.overviewBarWidth;
+        const scrubberStart = this.props.currentBarX / this.props.totalLength * this.activeOverviewWidth;
 
         const percentBarStart = this.visibleStart / this.props.time;
-        const barStart = percentBarStart * this.overviewBarWidth;
+        const barStart = percentBarStart * this.activeOverviewWidth;
 
         const timeline = this.props.isAuthoring ? [
 
-            <div key="timeline-overview-container" className="timeline-overview-container" id="timelineOverview">
+            <div key="timeline-overview-container" className="timeline-overview-container overviewBar" id="timelineOverview">
                 <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>,
-                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{left: `${(this.props.currentBarX / this.props.totalLength) * this.overviewBarWidth}px`}} onPointerDown={this.onScrubberDown}>
+                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}>
                     <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
                 </div>
             </div>
         ] : [
-                <div className="timeline-play-bar" style={{ width: this.overviewBarWidth }}>
-                    <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${(this.props.currentBarX / this.props.totalLength) * this.overviewBarWidth}px` }} onPointerDown={this.onScrubberDown}></div>
+                <div key="timeline-play-container" className="timeline-play-bar overviewBar" id="timelinePlay">
+                    <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}></div>
                 </div>,
-                <div className="timeline-play-tail" style={{ width: `${(this.props.currentBarX / this.props.totalLength) * this.overviewBarWidth}px` }}></div>
+                <div className="timeline-play-tail" style={{ width: `${(this.props.currentBarX / this.props.totalLength) * this.playbarWidth}px` }}></div>
             ];
         return (
             <div className="timeline-flex">
-- 
cgit v1.2.3-70-g09d2


From 8d28c35bb9cf6ec190dbfed2e2cda8b5d1454efb Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Sun, 9 Feb 2020 16:15:28 -0500
Subject: some changes

---
 src/client/views/animationtimeline/Timeline.tsx | 6 ++++--
 src/client/views/animationtimeline/Track.tsx    | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 42bb02e85..9e90cc764 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -539,8 +539,10 @@ export class Timeline extends React.Component<FieldViewProps> {
     tracks = () => {
         console.log(this.mapOfTracks.length);
         this.mapOfTracks.forEach(track => {
-            if (track !== null) {
-                track.getLastRegion();
+            console.log(track); 
+            if (track) {
+                const region = track.getLastRegion();
+                console.log(region.time); 
             } else {
 
             }
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 620668db7..9f63b3562 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -82,7 +82,7 @@ export class Track extends React.Component<IProps> {
 
 
     getLastRegion = () => {
-
+        console.log(this.regions.length); 
         console.log((this.regions[this.regions.length - 1] as Doc).time); 
         return this.regions[this.regions.length - 1] as Doc; 
     }
-- 
cgit v1.2.3-70-g09d2


From d3f9765c98595788eaeb8b5c0ef52af1cd3adab3 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Sun, 9 Feb 2020 17:01:37 -0500
Subject: reset view done

---
 src/client/views/animationtimeline/Keyframe.scss   |  4 ----
 src/client/views/animationtimeline/Timeline.scss   | 27 +++++++++++++++++-----
 src/client/views/animationtimeline/Timeline.tsx    | 11 +++++----
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 25 ++++++++++++++++----
 src/new_fields/Doc.ts                              | 19 +++++++++++++++
 5 files changed, 68 insertions(+), 18 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.scss b/src/client/views/animationtimeline/Keyframe.scss
index 8dcf71994..84c8de287 100644
--- a/src/client/views/animationtimeline/Keyframe.scss
+++ b/src/client/views/animationtimeline/Keyframe.scss
@@ -46,10 +46,6 @@ $timelineDark: #77a1aa;
         position: absolute;
     }
 
-    // .keyframe:hover~.keyframe-information {
-    //     display: flex;
-    // }
-
     .keyframe-information {
         display: none;
         position: relative;
diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss
index a99d017f4..f90249771 100644
--- a/src/client/views/animationtimeline/Timeline.scss
+++ b/src/client/views/animationtimeline/Timeline.scss
@@ -34,29 +34,44 @@ $timelineDark: #77a1aa;
     }
 
     .grid-box {
-        display: grid;
-        grid-template-columns: [first] 50% [line2] 25% [line3] 25%;
+        display: flex;
+        // grid-template-columns: [first] 20% [line2] 20% [line3] 60%;
         width: calc(100% - 150px);
         // width: 100%;
         margin-left: 10px;
 
         .time-box {
-            margin-left: 5px;
+            margin-left: 10px;
             min-width: 140px;
             display: flex;
             justify-content: center;
             align-items: center;
-            // grid-column-start: line2;
+
+            .resetView-tool {
+                width: 30px;
+                height: 30px;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                margin: 3px;
+                color: $timelineDark;
+            }
+
+            .resetView-tool:hover {
+                -webkit-transform: scale(1.1);
+                -ms-transform: scale(1.1);
+                transform: scale(1.1);
+                transition: .2s ease;
+            }
         }
 
         .mode-box {
             display: flex;
             margin-left: 5px;
-            // grid-column-start: line3;
         }
 
         .overview-box {
-            width: 100%;
+            width: 80%;
             display: flex;
         }
 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 3942499c9..256b98ffa 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -459,6 +459,9 @@ export class Timeline extends React.Component<FieldViewProps> {
                     </div>
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
                         {this.timeIndicator(lengthString)}
+                        <div className="resetView-tool" title="Return to Default View" onClick={() => Doc.resetView(this.props.Document)}><FontAwesomeIcon icon="compress-arrows-alt" size="lg" /></div>
+                        <div className="resetView-tool" style={{ display: this._isAuthoring ? "flex" : "none" }} title="Set Default View" onClick={() => Doc.setView(this.props.Document)}><FontAwesomeIcon icon="expand-arrows-alt" size="lg" /></div>
+
                     </div>
                 </div>
             </div>
@@ -477,8 +480,8 @@ export class Timeline extends React.Component<FieldViewProps> {
         else {
             return (
                 <div style={{ flexDirection: "column" }}>
-                    <div className="animation-text" style={{ width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Current: ${this.getCurrentTime()}`}</div>
-                    <div className="animation-text" style={{ width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total: 1:40.07`}</div>
+                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Current: ${this.getCurrentTime()}`}</div>
+                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total: 1:40.07`}</div>
                 </div>
             );
         }
@@ -539,7 +542,7 @@ export class Timeline extends React.Component<FieldViewProps> {
 
 
     @action.bound
-    changeLenths() {
+    changeLengths() {
         if (this._infoContainer.current) {
             this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; //the visible length of the timeline (the length that you current see)
             this._visibleStart = this._infoContainer.current!.scrollLeft; //where the div starts
@@ -572,7 +575,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     render() {
         runInAction(() => {
             this._panelWidth = this.props.PanelWidth();
-            this.changeLenths();
+            this.changeLengths();
         });
 
         // change visible and total width
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ef1ec5e78..81fca3b54 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -966,7 +966,24 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     onContextMenu = (e: React.MouseEvent) => {
         const layoutItems: ContextMenuProps[] = [];
-        layoutItems.push({ description: "reset view", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
+        const { Document } = this.props;
+
+        layoutItems.push({
+            description: "reset view", event: () => {
+                Doc.resetView(Document);
+            }, icon: "compress-arrows-alt"
+        });
+        layoutItems.push({
+            description: "set view origin", event: () => {
+                Doc.setView(Document);
+            }, icon: "expand-arrows-alt"
+        });
+        layoutItems.push({
+            description: "reset view to origin", event: () => {
+                Doc.resetViewToOrigin(Document);
+            }, icon: "expand-arrows-alt"
+        });
+
         layoutItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" });
         layoutItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
         layoutItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
@@ -1018,7 +1035,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             icon: "eye"
         });
         ContextMenu.Instance.addItem({ description: "Freeform Options ...", subitems: layoutItems, icon: "eye" });
-        this._timelineRef.current!.timelineContextMenu(e); 
+        this._timelineRef.current!.timelineContextMenu(e);
     }
 
 
@@ -1081,12 +1098,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     transformOrigin: this.contentScaling ? "left top" : "",
                     width: this.contentScaling ? `${100 / this.contentScaling}%` : "",
                     height: this.contentScaling ? `${100 / this.contentScaling}%` : this.isAnnotationOverlay ? (this.props.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
-                }}>            
+                }}>
                 {/* <Timeline ref={this._timelineRef} {...this.props} /> */}
                 {!this.Document._LODdisable && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? // && this.props.CollectionView && lodarea < NumCast(this.Document.LODarea, 100000) ?
                     this.placeholder : this.marqueeView}
                 <CollectionFreeFormOverlayView elements={this.elementFunc} />
-            </div>            
+            </div>
             <Timeline ref={this._timelineRef} {...this.props} />
         </div>;
     }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index f230abaf4..216005697 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -255,6 +255,25 @@ export namespace Doc {
     //         return Cast(field, ctor);
     //     });
     // }
+
+    export function resetView(doc: Doc) {
+        doc._panX = doc._customOriginX ?? 0;
+        doc._panY = doc._customOriginY ?? 0;
+        doc.scale = doc._customOriginScale ?? 1;
+    }
+
+    export function resetViewToOrigin(doc: Doc) {
+        doc._panX = 0;
+        doc._panY = 0;
+        doc.scale = 1;
+    }
+
+    export function setView(doc: Doc) {
+        doc._customOriginX = doc._panX;
+        doc._customOriginY = doc._panY;
+        doc._customOriginScale = doc.scale;
+    }
+
     export function RunCachedUpdate(doc: Doc, field: string) {
         const update = doc[CachedUpdates][field];
         if (update) {
-- 
cgit v1.2.3-70-g09d2


From cb140cb5387836de1e2287ed9519a132f0f9d28f Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Sun, 9 Feb 2020 18:10:26 -0500
Subject: kinda works

---
 src/client/views/animationtimeline/Timeline.tsx    | 42 +++++++++++++++++-----
 .../views/animationtimeline/TimelineOverview.tsx   |  8 +++--
 src/client/views/animationtimeline/Track.tsx       | 15 +++++---
 3 files changed, 50 insertions(+), 15 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index fc1a0ec3b..c52669879 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -14,6 +14,7 @@ import { TimelineOverview } from "./TimelineOverview";
 import { FieldViewProps } from "../nodes/FieldView";
 import { KeyframeFunc } from "./Keyframe";
 import { Utils } from "../../../Utils";
+import { createPromiseCapability } from "../../../../deploy/assets/pdf.worker";
 
 
 /**
@@ -470,7 +471,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             return (
                 <>
                     <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{lengthString}</div>
-                    <div className="totalTime">1:40.07</div>
+                    <div className="totalTime">{this.toReadTime(this._time)}</div>
                 </>
             );
         }
@@ -478,7 +479,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             return (
                 <div style={{ flexDirection: "column" }}>
                     <div className="animation-text" style={{ width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Current: ${this.getCurrentTime()}`}</div>
-                    <div className="animation-text" style={{ width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total: 1:40.07`}</div>
+                    <div className="animation-text" style={{ width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total: ${this.toReadTime(this._time)}`}</div>
                 </div>
             );
         }
@@ -524,7 +525,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             timelineContainer.style.top = `${-this._containerHeight}px`;
             this.props.Document.isATOn = false;
             this._isAuthoring = false;
-            this.tracks();
+            this.toPlay();
         } else {
             //turning on authoring mode...
             roundToggle.style.transform = "translate(20px, 0px)";
@@ -534,6 +535,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             timelineContainer.style.top = "0px";
             this.props.Document.isATOn = true;
             this._isAuthoring = true;
+            this.toAuthoring(); 
         }
     }
 
@@ -555,18 +557,40 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private mapOfTracks: (Track | null)[] = [];
 
     @action
-    tracks = () => {
-        console.log(this.mapOfTracks.length);
+    findLongestTime = () => {
+        let longestTime:number = 0; 
         this.mapOfTracks.forEach(track => {
-            console.log(track); 
             if (track) {
-                const region = track.getLastRegion();
-                console.log(region.time); 
+                const lastTime = track.getLastRegionTime();
+                if (this.children.length !== 0 ){
+                    if (longestTime <= lastTime){
+                        longestTime = lastTime; 
+                    }
+                }
             } else {
-
+                //TODO: remove undefineds and duplicates
             }
         });
+        return longestTime; 
+    }
+
+    @action 
+    toAuthoring = () => {
+        let longestTime = this.findLongestTime(); 
+        if (longestTime === 0) longestTime = 1;
+        const adjustedTime = Math.ceil(longestTime / 100000) * 100000; 
+        console.log(adjustedTime); 
+        this._totalLength = KeyframeFunc.convertPixelTime(adjustedTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
+        this._time = adjustedTime; 
+    }
+
+    @action 
+    toPlay = () => {
+        const longestTime = this.findLongestTime(); 
+        this._time = longestTime; 
+        this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement);
     }
+
     /**
      * if you have any question here, just shoot me an email or text. 
      * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index 94bbe7074..a587e1138 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -142,11 +142,15 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         const visibleBarWidth = percentVisible * this.activeOverviewWidth;
 
         const percentScrubberStart = this.currentX / this.props.time;
-        const scrubberStart = this.props.currentBarX / this.props.totalLength * this.activeOverviewWidth;
+        let scrubberStart = this.props.currentBarX / this.props.totalLength * this.activeOverviewWidth;
+        if (scrubberStart > this.activeOverviewWidth) scrubberStart = this.activeOverviewWidth; 
 
         const percentBarStart = this.visibleStart / this.props.time;
         const barStart = percentBarStart * this.activeOverviewWidth;
 
+        let playWidth = (this.props.currentBarX / this.props.totalLength) * this.activeOverviewWidth; 
+        if (playWidth > this.activeOverviewWidth) playWidth = this.activeOverviewWidth; 
+
         const timeline = this.props.isAuthoring ? [
 
             <div key="timeline-overview-container" className="timeline-overview-container overviewBar" id="timelineOverview">
@@ -159,7 +163,7 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
                 <div key="timeline-play-container" className="timeline-play-bar overviewBar" id="timelinePlay">
                     <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}></div>
                 </div>,
-                <div className="timeline-play-tail" style={{ width: `${(this.props.currentBarX / this.props.totalLength) * this.playbarWidth}px` }}></div>
+                <div className="timeline-play-tail" style={{ width: `${playWidth}px` }}></div>
             ];
         return (
             <div className="timeline-flex">
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 9f63b3562..69e65fbcf 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -81,10 +81,17 @@ export class Track extends React.Component<IProps> {
     ////////////////////////////////
 
 
-    getLastRegion = () => {
-        console.log(this.regions.length); 
-        console.log((this.regions[this.regions.length - 1] as Doc).time); 
-        return this.regions[this.regions.length - 1] as Doc; 
+    getLastRegionTime =  () => {
+        let lastTime:number = 0; 
+        let lastRegion:(Doc | undefined); 
+        DocListCast(this.regions).forEach(region => {
+            const time = NumCast(region.time); 
+            if (lastTime <= time) {
+                lastTime = time; 
+                lastRegion = region; 
+            }
+        }); 
+        return lastRegion ? lastTime + NumCast(lastRegion.duration) : 0;  
     }
 
     /**
-- 
cgit v1.2.3-70-g09d2


From d9990be832185b31375aaeb458c21addb389c32e Mon Sep 17 00:00:00 2001
From: andrewdkim <adkim414@gmail.com>
Date: Mon, 10 Feb 2020 20:30:59 -0500
Subject: fixed time

---
 package-lock.json                               | 2 +-
 src/client/views/animationtimeline/Timeline.tsx | 1 +
 src/client/views/animationtimeline/Track.tsx    | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/package-lock.json b/package-lock.json
index 5684789c1..0ae430be9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17991,7 +17991,7 @@
         },
         "wrap-ansi": {
             "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+            "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
             "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
             "requires": {
                 "string-width": "^1.0.1",
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 914c19b53..d27990bd6 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -574,6 +574,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                 //TODO: remove undefineds and duplicates
             }
         });
+        console.log(longestTime); 
         return longestTime; 
     }
 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 69e65fbcf..705cc33a2 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -85,7 +85,7 @@ export class Track extends React.Component<IProps> {
         let lastTime:number = 0; 
         let lastRegion:(Doc | undefined); 
         DocListCast(this.regions).forEach(region => {
-            const time = NumCast(region.time); 
+            const time = NumCast(region.position); 
             if (lastTime <= time) {
                 lastTime = time; 
                 lastRegion = region; 
-- 
cgit v1.2.3-70-g09d2


From 77ddee9b0d5697522894badc9df1d54a0a7f08c9 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Mon, 10 Feb 2020 20:38:37 -0500
Subject: fixed width

---
 src/client/views/animationtimeline/Timeline.tsx    | 32 +++++++++++-----------
 .../views/animationtimeline/TimelineOverview.tsx   | 16 ++++++-----
 2 files changed, 25 insertions(+), 23 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index d27990bd6..b1777bfa0 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -538,7 +538,7 @@ export class Timeline extends React.Component<FieldViewProps> {
             timelineContainer.style.top = "0px";
             this.props.Document.isATOn = true;
             this._isAuthoring = true;
-            this.toAuthoring(); 
+            this.toAuthoring();
         }
     }
 
@@ -561,37 +561,37 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     @action
     findLongestTime = () => {
-        let longestTime:number = 0; 
+        let longestTime: number = 0;
         this.mapOfTracks.forEach(track => {
             if (track) {
                 const lastTime = track.getLastRegionTime();
-                if (this.children.length !== 0 ){
-                    if (longestTime <= lastTime){
-                        longestTime = lastTime; 
+                if (this.children.length !== 0) {
+                    if (longestTime <= lastTime) {
+                        longestTime = lastTime;
                     }
                 }
             } else {
                 //TODO: remove undefineds and duplicates
             }
         });
-        console.log(longestTime); 
-        return longestTime; 
+        // console.log(longestTime); 
+        return longestTime;
     }
 
-    @action 
+    @action
     toAuthoring = () => {
-        let longestTime = this.findLongestTime(); 
+        let longestTime = this.findLongestTime();
         if (longestTime === 0) longestTime = 1;
-        const adjustedTime = Math.ceil(longestTime / 100000) * 100000; 
-        console.log(adjustedTime); 
-        this._totalLength = KeyframeFunc.convertPixelTime(adjustedTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); 
-        this._time = adjustedTime; 
+        const adjustedTime = Math.ceil(longestTime / 100000) * 100000;
+        // console.log(adjustedTime); 
+        this._totalLength = KeyframeFunc.convertPixelTime(adjustedTime, "mili", "pixel", this._tickSpacing, this._tickIncrement);
+        this._time = adjustedTime;
     }
 
-    @action 
+    @action
     toPlay = () => {
-        const longestTime = this.findLongestTime(); 
-        this._time = longestTime; 
+        const longestTime = this.findLongestTime();
+        this._time = longestTime;
         this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement);
     }
 
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index a587e1138..e3a276737 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -26,6 +26,8 @@ interface TimelineOverviewProps {
 export class TimelineOverview extends React.Component<TimelineOverviewProps>{
     @observable private _visibleRef = React.createRef<HTMLDivElement>();
     @observable private _scrubberRef = React.createRef<HTMLDivElement>();
+    @observable private authoringContainer = React.createRef<HTMLDivElement>();
+    @observable private playbackContainer = React.createRef<HTMLDivElement>();
     @observable private overviewBarWidth: number = 0;
     @observable private playbarWidth: number = 0;
     @observable private activeOverviewWidth: number = 0;
@@ -57,8 +59,8 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
     @action
     setOverviewWidth() {
-        const width1 = $("#timelineOverview").width();
-        const width2 = $("#timelinePlay").width();
+        const width1 = this.authoringContainer.current?.clientWidth;
+        const width2 = this.playbackContainer.current?.clientWidth;
         if (width1 && width1 !== 0) this.overviewBarWidth = width1;
         if (width2 && width2 !== 0) this.playbarWidth = width2;
 
@@ -143,24 +145,24 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
 
         const percentScrubberStart = this.currentX / this.props.time;
         let scrubberStart = this.props.currentBarX / this.props.totalLength * this.activeOverviewWidth;
-        if (scrubberStart > this.activeOverviewWidth) scrubberStart = this.activeOverviewWidth; 
+        if (scrubberStart > this.activeOverviewWidth) scrubberStart = this.activeOverviewWidth;
 
         const percentBarStart = this.visibleStart / this.props.time;
         const barStart = percentBarStart * this.activeOverviewWidth;
 
-        let playWidth = (this.props.currentBarX / this.props.totalLength) * this.activeOverviewWidth; 
-        if (playWidth > this.activeOverviewWidth) playWidth = this.activeOverviewWidth; 
+        let playWidth = (this.props.currentBarX / this.props.totalLength) * this.activeOverviewWidth;
+        if (playWidth > this.activeOverviewWidth) playWidth = this.activeOverviewWidth;
 
         const timeline = this.props.isAuthoring ? [
 
-            <div key="timeline-overview-container" className="timeline-overview-container overviewBar" id="timelineOverview">
+            <div key="timeline-overview-container" className="timeline-overview-container overviewBar" id="timelineOverview" ref={this.authoringContainer}>
                 <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>,
                 <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}>
                     <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
                 </div>
             </div>
         ] : [
-                <div key="timeline-play-container" className="timeline-play-bar overviewBar" id="timelinePlay">
+                <div key="timeline-play-container" className="timeline-play-bar overviewBar" id="timelinePlay" ref={this.playbackContainer}>
                     <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}></div>
                 </div>,
                 <div className="timeline-play-tail" style={{ width: `${playWidth}px` }}></div>
-- 
cgit v1.2.3-70-g09d2


From 02c8bdb41bc7daf8268fde3fe85a9e2f237c772d Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Mon, 10 Feb 2020 20:53:45 -0500
Subject: time fixed

---
 src/client/views/animationtimeline/Timeline.tsx | 38 +++++++++++--------------
 1 file changed, 16 insertions(+), 22 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index b1777bfa0..2b0525c6e 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -412,7 +412,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     /**
      * tool box includes the toggle buttons at the top of the timeline (both editing mode and play mode)
      */
-    private timelineToolBox = (scale: number) => {
+    private timelineToolBox = (scale: number, totalTime: number) => {
         const size = 40 * scale; //50 is default
         const iconSize = 25;
 
@@ -459,7 +459,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                         </div>
                     </div>
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
-                        {this.timeIndicator(lengthString)}
+                        {this.timeIndicator(lengthString, totalTime)}
                         <div className="resetView-tool" title="Return to Default View" onClick={() => Doc.resetView(this.props.Document)}><FontAwesomeIcon icon="compress-arrows-alt" size="lg" /></div>
                         <div className="resetView-tool" style={{ display: this._isAuthoring ? "flex" : "none" }} title="Set Default View" onClick={() => Doc.setView(this.props.Document)}><FontAwesomeIcon icon="expand-arrows-alt" size="lg" /></div>
 
@@ -469,12 +469,11 @@ export class Timeline extends React.Component<FieldViewProps> {
         );
     }
 
-    timeIndicator(lengthString: string) {
+    timeIndicator(lengthString: string, totalTime: number) {
         if (this.props.Document.isATOn) {
             return (
                 <>
-                    <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{lengthString}</div>
-                    <div className="totalTime">{this.toReadTime(this._time)}</div>
+                    <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{`Total: ${this.toReadTime(totalTime)}`}</div>
                 </>
             );
         }
@@ -482,26 +481,12 @@ export class Timeline extends React.Component<FieldViewProps> {
             return (
                 <div style={{ flexDirection: "column" }}>
                     <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Current: ${this.getCurrentTime()}`}</div>
-                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total:${this.toReadTime(this._time)}`}</div>
+                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total: ${this.toReadTime(this._time)}`}</div>
                 </div>
             );
         }
     }
 
-    /**
-     * manual time input (kinda broken right now)
-     */
-    @action
-    private onTimeInput = (e: React.KeyboardEvent) => {
-        // if (e.keyCode === 13) {
-        //     let timeInput = this._timeInputRef.current!;
-        //     this._time = parseInt(timeInput.value, 10);
-        //     this._totalLength = KeyframeFunc.convertPixelTime(this._time, "mili", "pixel", this._tickSpacing, this._tickIncrement);
-        //     this.props.Document.AnimationLength = this._time;
-        // }
-    }
-
-
     /**
      * when the user decides to click the toggle button (either user wants to enter editing mode or play mode)
      */
@@ -553,7 +538,10 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     // @computed
     getCurrentTime = () => {
-        const current = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
+        let current = KeyframeFunc.convertPixelTime(this._currentBarX, "mili", "time", this._tickSpacing, this._tickIncrement);
+        if (current > this._time) {
+            current = this._time;
+        }
         return this.toReadTime(current);
     }
 
@@ -603,8 +591,14 @@ export class Timeline extends React.Component<FieldViewProps> {
         runInAction(() => {
             this._panelWidth = this.props.PanelWidth();
             this.changeLengths();
+            // this.toPlay();
+
+
+            // this._time = longestTime;
         });
 
+        const longestTime = this.findLongestTime();
+
         // change visible and total width
         return (
             <div>
@@ -632,7 +626,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                             </div>
                         </div>
                     </div>
-                    {this.timelineToolBox(1)}
+                    {this.timelineToolBox(1, longestTime)}
                 </div>
             </div>
         );
-- 
cgit v1.2.3-70-g09d2


From 4ecf08b5c5cdc4ddb3a997e2f3a2188e921ff430 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 11 Feb 2020 19:29:19 -0500
Subject: number jitter fixed

---
 src/client/views/animationtimeline/Timeline.tsx | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 2b0525c6e..e9caa2b2a 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -329,17 +329,15 @@ export class Timeline extends React.Component<FieldViewProps> {
         time = time / 1000;
         const inSeconds = Math.round(time * 100) / 100;
 
-        // console.log(inSeconds)
-        // var inSeconds = parseFloat(time.toFixed(2));
-        // const inSeconds = (Math.floor(time) / 1000);
         const min: (string | number) = Math.floor(inSeconds / 60);
-        let sec: (string | number) = (Math.round((inSeconds % 60) * 100) / 100);
+        const sec: (string | number) = (Math.round((inSeconds % 60) * 100) / 100);
+        let secString = sec.toFixed(2);
 
         if (Math.floor(sec / 10) === 0) {
-            sec = "0" + sec;
+            secString = "0" + secString;
         }
-        // sec = Number.parseFloat(sec).toFixed(2);
-        return `${min}:${sec}`;
+
+        return `${min}:${secString}`;
     }
 
 
-- 
cgit v1.2.3-70-g09d2


From 0fb0341287cfed4c5b846f6bc7126623599b34f5 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 28 Apr 2020 20:16:45 -0400
Subject: small timeline fixes

---
 src/client/views/animationtimeline/Keyframe.tsx    | 103 ++++++++++-----------
 src/client/views/animationtimeline/Timeline.tsx    |  16 +---
 .../views/animationtimeline/TimelineOverview.tsx   |   8 +-
 src/client/views/animationtimeline/Track.tsx       |  60 ++++++------
 4 files changed, 92 insertions(+), 95 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index bb557289e..76c3e63be 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -3,7 +3,7 @@ import "./Keyframe.scss";
 import "./Timeline.scss";
 import "../globalCssVariables.scss";
 import { observer } from "mobx-react";
-import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction } from "mobx";
+import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction, trace } from "mobx";
 import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
 import { Cast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
@@ -13,6 +13,7 @@ import { TimelineMenu } from "./TimelineMenu";
 import { Docs } from "../../documents/Documents";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { emptyPath } from "../../../Utils";
 
 
 
@@ -32,10 +33,10 @@ export namespace KeyframeFunc {
         right = "right"
     }
 
-    export const findAdjacentRegion = (dir: KeyframeFunc.Direction, currentRegion: Doc, regions: List<Doc>): (RegionData | undefined) => {
+    export const findAdjacentRegion = (dir: KeyframeFunc.Direction, currentRegion: Doc, regions: Doc[]): (RegionData | undefined) => {
         let leftMost: (RegionData | undefined) = undefined;
         let rightMost: (RegionData | undefined) = undefined;
-        DocListCast(regions).forEach(region => {
+        regions.forEach(region => {
             const neighbor = RegionData(region);
             if (currentRegion.position! > neighbor.position) {
                 if (!leftMost || neighbor.position > leftMost.position) {
@@ -135,7 +136,7 @@ interface IProps {
     time: number;
     changeCurrentBarX: (x: number) => void;
     transform: Transform;
-    makeKeyData: (region:RegionData, pos: number, kftype:KeyframeFunc.KeyframeType) => Doc; 
+    makeKeyData: (region: RegionData, pos: number, kftype: KeyframeFunc.KeyframeType) => Doc;
 }
 
 
@@ -169,21 +170,24 @@ export class Keyframe extends React.Component<IProps> {
     @observable private _mouseToggled = false;
     @observable private _doubleClickEnabled = false;
 
-    @computed private get regiondata() { return RegionData(this.regions[this.regions.indexOf(this.props.RegionData)] as Doc); }
-    @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; }
+    @computed private get regiondata() { return RegionData(this.props.RegionData); }
+    @computed private get regions() { return DocListCast(this.props.node.regions); }
     @computed private get keyframes() { return DocListCast(this.regiondata.keyframes); }
     @computed private get pixelPosition() { return KeyframeFunc.convertPixelTime(this.regiondata.position, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed private get pixelDuration() { return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed private get pixelFadeIn() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
     @computed private get pixelFadeOut() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); }
-   
+
+    constructor(props: any) {
+        super(props);
+    }
     componentDidMount() {
         setTimeout(() => {      //giving it a temporary 1sec delay... 
-            if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();   
-            const start = this.props.makeKeyData(this.regiondata, this.regiondata.position,  KeyframeFunc.KeyframeType.end);
+            if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>();
+            const start = this.props.makeKeyData(this.regiondata, this.regiondata.position, KeyframeFunc.KeyframeType.end);
             const fadeIn = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade);
             const fadeOut = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade);
-            const finish = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration,KeyframeFunc.KeyframeType.end);
+            const finish = this.props.makeKeyData(this.regiondata, this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.end);
             (fadeIn.key as Doc).opacity = 1;
             (fadeOut.key as Doc).opacity = 1;
             (start.key as Doc).opacity = 0.1;
@@ -192,9 +196,6 @@ export class Keyframe extends React.Component<IProps> {
         }, 1000);
     }
 
-
-
-
     @action
     onBarPointerDown = (e: React.PointerEvent) => {
         e.preventDefault();
@@ -316,7 +317,7 @@ export class Keyframe extends React.Component<IProps> {
         if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends
             const position = this.regiondata.position;
             this.props.makeKeyData(this.regiondata, Math.round(position + offset), KeyframeFunc.KeyframeType.default);
-            this.regiondata.hasData = true; 
+            this.regiondata.hasData = true;
             this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied
 
         }
@@ -338,7 +339,7 @@ export class Keyframe extends React.Component<IProps> {
         TimelineMenu.Instance.addItem("button", "Show Data", () => {
             runInAction(() => {
                 const kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { _width: 300, _height: 300 });
-                CollectionDockingView.AddRightSplit(kvp, (kf.key as Doc).data as Doc);
+                CollectionDockingView.AddRightSplit(kvp, emptyPath);
             });
         }),
             TimelineMenu.Instance.addItem("button", "Delete", () => {
@@ -403,7 +404,7 @@ export class Keyframe extends React.Component<IProps> {
                 runInAction(() => {
                     const prevPosition = this.regiondata.position;
                     let cannotMove: boolean = false;
-                    DocListCast(this.regions).forEach(region => {
+                    this.regions.forEach(region => {
                         if (NumCast(region.position) !== this.regiondata.position) {
                             if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration) || (this.regiondata.duration + val > NumCast(region.position) && this.regiondata.duration + val < NumCast(region.position) + NumCast(region.duration)))) {
                                 cannotMove = true;
@@ -419,7 +420,7 @@ export class Keyframe extends React.Component<IProps> {
             TimelineMenu.Instance.addItem("input", `duration: ${this.regiondata.duration}ms`, (val) => {
                 runInAction(() => {
                     let cannotMove: boolean = false;
-                    DocListCast(this.regions).forEach(region => {
+                    this.regions.forEach(region => {
                         if (NumCast(region.position) !== this.regiondata.position) {
                             val += this.regiondata.position;
                             if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration))) {
@@ -479,34 +480,31 @@ export class Keyframe extends React.Component<IProps> {
      * drawing keyframe. Handles both keyframe with a circle (one that you create by double clicking) and one without circle (fades)
      * this probably needs biggest change, since everyone expected all keyframes to have a circle (and draggable)
      */
-    @action
     drawKeyframes = () => {
         const keyframeDivs: JSX.Element[] = [];
-        DocListCast(this.regiondata.keyframes).forEach(kf => {
+        return DocListCast(this.regiondata.keyframes).map(kf => {
             if (kf.type as KeyframeFunc.KeyframeType !== KeyframeFunc.KeyframeType.end) {
-                keyframeDivs.push(
-                    <><div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
-                        <div className="divider"></div>
-                        <div className="keyframeCircle keyframe-indicator" onPointerDown={(e) => { e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }} onContextMenu={(e: React.MouseEvent) => {
-                            e.preventDefault();
-                            e.stopPropagation();
-                            this.makeKeyframeMenu(kf, e.nativeEvent);
-                        }} onDoubleClick={(e) => { e.preventDefault(); e.stopPropagation(); }}></div>
-
-                    </div>
-                        <div className="keyframe-information"></div>
-                    </>
-
-                );
-            } else {
-                keyframeDivs.push(
+                return <>
                     <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
                         <div className="divider"></div>
+                        <div className="keyframeCircle keyframe-indicator"
+                            onPointerDown={(e) => { e.preventDefault(); e.stopPropagation(); this.moveKeyframe(e, kf); }}
+                            onContextMenu={(e: React.MouseEvent) => {
+                                e.preventDefault();
+                                e.stopPropagation();
+                                this.makeKeyframeMenu(kf, e.nativeEvent);
+                            }}
+                            onDoubleClick={(e) => { e.preventDefault(); e.stopPropagation(); }}>
+                        </div>
                     </div>
-                );
+                    <div className="keyframe-information" />
+                </>;
+            } else {
+                return <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}>
+                    <div className="divider" />
+                </div>
             }
         });
-        return keyframeDivs;
     }
 
     /**
@@ -546,22 +544,23 @@ export class Keyframe extends React.Component<IProps> {
      */
     //154, 206, 223
     render() {
+        trace();
+        console.log(this.props.RegionData.position);
+        console.log(this.regiondata.position);
+        console.log(this.pixelPosition);
         return (
-            <div>
-                <div className="bar" ref={this._bar} style={{
-                    transform: `translate(${this.pixelPosition}px)`,
-                    width: `${this.pixelDuration}px`,
-                    background: `linear-gradient(90deg, rgba(154, 206, 223, 0) 0%, rgba(154, 206, 223, 1) ${this.pixelFadeIn / this.pixelDuration * 100}%, rgba(154, 206, 223, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(154, 206, 223, 0) 100% )`
-                }}
-                    onPointerDown={this.onBarPointerDown
-                    }>
-                    <div className="leftResize keyframe-indicator" onPointerDown={this.onResizeLeft} ></div>
-                    {/* <div className="keyframe-information"></div> */}
-                    <div className="rightResize keyframe-indicator" onPointerDown={this.onResizeRight}></div>
-                    {/* <div className="keyframe-information"></div> */}
-                    {this.drawKeyframes()}
-                    {this.drawKeyframeDividers()}
-                </div>
+            <div className="bar" ref={this._bar} style={{
+                transform: `translate(${this.pixelPosition}px)`,
+                width: `${this.pixelDuration}px`,
+                background: `linear-gradient(90deg, rgba(154, 206, 223, 0) 0%, rgba(154, 206, 223, 1) ${this.pixelFadeIn / this.pixelDuration * 100}%, rgba(154, 206, 223, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(154, 206, 223, 0) 100% )`
+            }}
+                onPointerDown={this.onBarPointerDown}>
+                <div className="leftResize keyframe-indicator" onPointerDown={this.onResizeLeft} ></div>
+                {/* <div className="keyframe-information"></div> */}
+                <div className="rightResize keyframe-indicator" onPointerDown={this.onResizeRight}></div>
+                {/* <div className="keyframe-information"></div> */}
+                {this.drawKeyframes()}
+                {this.drawKeyframeDividers()}
             </div>
         );
     }
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index e9caa2b2a..7d245ab6f 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -3,7 +3,7 @@ import "./Timeline.scss";
 import { listSpec } from "../../../new_fields/Schema";
 import { observer } from "mobx-react";
 import { Track } from "./Track";
-import { observable, action, computed, runInAction, IReactionDisposer, reaction } from "mobx";
+import { observable, action, computed, runInAction, IReactionDisposer, reaction, trace } from "mobx";
 import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
@@ -14,8 +14,6 @@ import { TimelineOverview } from "./TimelineOverview";
 import { FieldViewProps } from "../nodes/FieldView";
 import { KeyframeFunc } from "./Keyframe";
 import { Utils } from "../../../Utils";
-import { createPromiseCapability } from "../../../../deploy/assets/pdf.worker";
-
 
 /**
  * Timeline class controls most of timeline functions besides individual keyframe and track mechanism. Main functions are 
@@ -80,7 +78,6 @@ export class Timeline extends React.Component<FieldViewProps> {
 
     // so a reaction can be made
     @observable public _isAuthoring = this.props.Document.isATOn;
-    @observable private _panelWidth = 0;
 
     /**
      * collection get method. Basically defines what defines collection's children. These will be tracked in the timeline. Do not edit. 
@@ -90,7 +87,7 @@ export class Timeline extends React.Component<FieldViewProps> {
         const extendedDocument = ["image", "video", "pdf"].includes(StrCast(this.props.Document.type));
         if (extendedDocument) {
             if (this.props.Document.data_ext) {
-                return Cast((Cast(this.props.Document.data_ext, Doc) as Doc).annotations, listSpec(Doc)) as List<Doc>;
+                return Cast((Cast(this.props.Document[Doc.LayoutFieldKey(this.props.Document) + "-annotations"], Doc) as Doc).annotations, listSpec(Doc)) as List<Doc>;
             } else {
                 return new List<Doc>();
             }
@@ -586,17 +583,14 @@ export class Timeline extends React.Component<FieldViewProps> {
      * basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
      */
     render() {
-        runInAction(() => {
-            this._panelWidth = this.props.PanelWidth();
+        setTimeout(() => {
             this.changeLengths();
             // this.toPlay();
-
-
             // this._time = longestTime;
-        });
+        }, 0);
 
         const longestTime = this.findLongestTime();
-
+        trace();
         // change visible and total width
         return (
             <div>
diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx
index e3a276737..31e248823 100644
--- a/src/client/views/animationtimeline/TimelineOverview.tsx
+++ b/src/client/views/animationtimeline/TimelineOverview.tsx
@@ -156,16 +156,16 @@ export class TimelineOverview extends React.Component<TimelineOverviewProps>{
         const timeline = this.props.isAuthoring ? [
 
             <div key="timeline-overview-container" className="timeline-overview-container overviewBar" id="timelineOverview" ref={this.authoringContainer}>
-                <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>,
-                <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}>
+                <div ref={this._visibleRef} key="1" className="timeline-overview-visible" style={{ left: `${barStart}px`, width: `${visibleBarWidth}px` }} onPointerDown={this.onPointerDown}></div>,
+                <div ref={this._scrubberRef} key="2" className="timeline-overview-scrubber-container" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}>
                     <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div>
                 </div>
             </div>
         ] : [
-                <div key="timeline-play-container" className="timeline-play-bar overviewBar" id="timelinePlay" ref={this.playbackContainer}>
+                <div key="1" className="timeline-play-bar overviewBar" id="timelinePlay" ref={this.playbackContainer}>
                     <div ref={this._scrubberRef} className="timeline-play-head" style={{ left: `${scrubberStart}px` }} onPointerDown={this.onScrubberDown}></div>
                 </div>,
-                <div className="timeline-play-tail" style={{ width: `${playWidth}px` }}></div>
+                <div key="2" className="timeline-play-tail" style={{ width: `${playWidth}px` }}></div>
             ];
         return (
             <div className="timeline-flex">
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 705cc33a2..0e3c209dc 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -29,7 +29,7 @@ export class Track extends React.Component<IProps> {
     @observable private _currentBarXReaction: any;
     @observable private _timelineVisibleReaction: any;
     @observable private _autoKfReaction: any;
-    @observable private _newKeyframe: boolean = false; 
+    @observable private _newKeyframe: boolean = false;
     private readonly MAX_TITLE_HEIGHT = 75;
     private _trackHeight = 0;
     private primitiveWhitelist = [
@@ -37,7 +37,7 @@ export class Track extends React.Component<IProps> {
         "y",
         "width",
         "height",
-        "opacity", 
+        "opacity",
     ];
     private objectWhitelist = [
         "data"
@@ -81,17 +81,17 @@ export class Track extends React.Component<IProps> {
     ////////////////////////////////
 
 
-    getLastRegionTime =  () => {
-        let lastTime:number = 0; 
-        let lastRegion:(Doc | undefined); 
+    getLastRegionTime = () => {
+        let lastTime: number = 0;
+        let lastRegion: (Doc | undefined);
         DocListCast(this.regions).forEach(region => {
-            const time = NumCast(region.position); 
+            const time = NumCast(region.position);
             if (lastTime <= time) {
-                lastTime = time; 
-                lastRegion = region; 
+                lastTime = time;
+                lastRegion = region;
             }
-        }); 
-        return lastRegion ? lastTime + NumCast(lastRegion.duration) : 0;  
+        });
+        return lastRegion ? lastTime + NumCast(lastRegion.duration) : 0;
     }
 
     /**
@@ -106,16 +106,16 @@ export class Track extends React.Component<IProps> {
         let kf = keyframes[kfIndex] as Doc; //index in the keyframe
         if (this._newKeyframe) {
             console.log("new keyframe registering");
-            let kfList = DocListCast(this.saveStateRegion!.keyframes); 
+            let kfList = DocListCast(this.saveStateRegion!.keyframes);
             kfList.forEach(kf => {
-                kf.key = this.makeCopy(); 
-                if (kfList.indexOf(kf) === 0  ||  kfList.indexOf(kf) === 3){
-                    (kf.key as Doc).opacity = 0.1; 
-                } else{
-                    (kf.key as Doc).opacity = 1; 
+                kf.key = this.makeCopy();
+                if (kfList.indexOf(kf) === 0 || kfList.indexOf(kf) === 3) {
+                    (kf.key as Doc).opacity = 0.1;
+                } else {
+                    (kf.key as Doc).opacity = 1;
                 }
             });
-            this._newKeyframe = false; 
+            this._newKeyframe = false;
         }
         if (!kf) return;
         if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
@@ -225,7 +225,7 @@ export class Track extends React.Component<IProps> {
                     }
                 });
             } else {
-                console.log("reverting state"); 
+                console.log("reverting state");
                 //this.revertState(); 
             }
         });
@@ -241,7 +241,7 @@ export class Track extends React.Component<IProps> {
     timeChange = async () => {
         if (this.saveStateKf !== undefined) {
             await this.saveKeyframe();
-        } else if (this._newKeyframe){
+        } else if (this._newKeyframe) {
             await this.saveKeyframe();
         }
         let regiondata = await this.findRegion(Math.round(this.time)); //finds a region that the scrubber is on
@@ -250,7 +250,7 @@ export class Track extends React.Component<IProps> {
             let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.time); //right keyframe, if it exists        
             let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
             if (currentkf) {
-                console.log("is current"); 
+                console.log("is current");
                 await this.applyKeys(currentkf);
                 this.saveStateKf = currentkf;
                 this.saveStateRegion = regiondata;
@@ -348,7 +348,7 @@ export class Track extends React.Component<IProps> {
     createRegion = async (time: number) => {
         if (await this.findRegion(time) === undefined) {  //check if there is a region where double clicking (prevents phantom regions)
             let regiondata = KeyframeFunc.defaultKeyframe(); //create keyframe data
-           
+
             regiondata.position = time; //set position
             let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, regiondata, this.regions);
 
@@ -356,9 +356,9 @@ export class Track extends React.Component<IProps> {
                 regiondata.duration = rightRegion.position - regiondata.position;
             }
             if (this.regions.length === 0 || !rightRegion || (rightRegion && rightRegion.position - regiondata.position >= NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut))) {
-                this.regions.push(regiondata); 
-                this._newKeyframe = true; 
-                this.saveStateRegion = regiondata; 
+                this.regions.push(regiondata);
+                this._newKeyframe = true;
+                this.saveStateRegion = regiondata;
                 return regiondata;
             }
         }
@@ -395,7 +395,7 @@ export class Track extends React.Component<IProps> {
         let doc = new Doc();
         this.primitiveWhitelist.forEach(key => {
             let originalVal = this.props.node[key];
-            if (key === "data"){
+            if (key === "data") {
                 console.log(originalVal);
             }
             doc[key] = originalVal instanceof ObjectField ? originalVal[Copy]() : this.props.node[key];
@@ -407,12 +407,16 @@ export class Track extends React.Component<IProps> {
      * UI sstuff here. Not really much to change
      */
     render() {
+        trace();
         return (
             <div className="track-container">
                 <div className="track">
-                    <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick} onPointerOver={() => { Doc.BrushDoc(this.props.node); }} onPointerOut={() => { Doc.UnBrushDoc(this.props.node); }} style={{ height: `${this._trackHeight}px` }}>
-                        {DocListCast(this.regions).map((region) => {
-                            return <Keyframe {...this.props} RegionData={region} makeKeyData={this.makeKeyData} />;
+                    <div className="inner" ref={this._inner} style={{ height: `${this._trackHeight}px` }}
+                        onDoubleClick={this.onInnerDoubleClick}
+                        onPointerOver={() => Doc.BrushDoc(this.props.node)}
+                        onPointerOut={() => Doc.UnBrushDoc(this.props.node)} >
+                        {DocListCast(this.regions).map((region, i) => {
+                            return <Keyframe key={`${i}`} {...this.props} RegionData={region} makeKeyData={this.makeKeyData} />;
                         })}
                     </div>
                 </div>
-- 
cgit v1.2.3-70-g09d2


From ab4297e59e142f70b420831a73c3f3e4506eee15 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 28 Apr 2020 23:00:15 -0400
Subject: more animation timeline cleanup

---
 src/client/views/animationtimeline/Keyframe.tsx |  43 ++---
 src/client/views/animationtimeline/Timeline.tsx |  41 ++--
 src/client/views/animationtimeline/Track.tsx    | 239 ++++++++++--------------
 3 files changed, 135 insertions(+), 188 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 76c3e63be..a3407f653 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -4,7 +4,7 @@ import "./Timeline.scss";
 import "../globalCssVariables.scss";
 import { observer } from "mobx-react";
 import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction, trace } from "mobx";
-import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
+import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc";
 import { Cast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new_fields/Schema";
@@ -55,11 +55,11 @@ export namespace KeyframeFunc {
         }
     };
 
-    export const calcMinLeft = async (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closet keyframe to the left
-        let leftKf: (Doc | undefined) = undefined;
+    export const calcMinLeft = (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closet keyframe to the left
+        let leftKf: Opt<Doc>;
         let time: number = 0;
-        const keyframes = await DocListCastAsync(region.keyframes!);
-        keyframes!.forEach((kf) => {
+        const keyframes = DocListCast(region.keyframes!);
+        keyframes.map((kf) => {
             let compTime = currentBarX;
             if (ref) compTime = NumCast(ref.time);
             if (NumCast(kf.time) < compTime && NumCast(kf.time) >= time) {
@@ -71,11 +71,10 @@ export namespace KeyframeFunc {
     };
 
 
-    export const calcMinRight = async (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closest keyframe to the right 
-        let rightKf: (Doc | undefined) = undefined;
+    export const calcMinRight = (region: Doc, currentBarX: number, ref?: Doc) => { //returns the time of the closest keyframe to the right 
+        let rightKf: Opt<Doc>;
         let time: number = Infinity;
-        const keyframes = await DocListCastAsync(region.keyframes!);
-        keyframes!.forEach((kf) => {
+        DocListCast(region.keyframes!).forEach((kf) => {
             let compTime = currentBarX;
             if (ref) compTime = NumCast(ref.time);
             if (NumCast(kf.time) > compTime && NumCast(kf.time) <= NumCast(time)) {
@@ -239,9 +238,7 @@ export class Keyframe extends React.Component<IProps> {
             this.regiondata.position = futureX;
         }
         const movement = this.regiondata.position - prevX;
-        this.keyframes.forEach(kf => {
-            kf.time = NumCast(kf.time) + movement;
-        });
+        this.keyframes.forEach(kf => kf.time = NumCast(kf.time) + movement);
     }
 
     @action
@@ -338,7 +335,7 @@ export class Keyframe extends React.Component<IProps> {
     makeKeyframeMenu = (kf: Doc, e: MouseEvent) => {
         TimelineMenu.Instance.addItem("button", "Show Data", () => {
             runInAction(() => {
-                const kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { _width: 300, _height: 300 });
+                const kvp = Docs.Create.KVPDocument(kf, { _width: 300, _height: 300 });
                 CollectionDockingView.AddRightSplit(kvp, emptyPath);
             });
         }),
@@ -370,12 +367,8 @@ export class Keyframe extends React.Component<IProps> {
      */
     @action
     makeRegionMenu = (kf: Doc, e: MouseEvent) => {
-        TimelineMenu.Instance.addItem("button", "Remove Region", () => {
-            runInAction(() => {
-                this.regions.splice(this.regions.indexOf(this.props.RegionData), 1);
-            }
-            );
-        }),
+        TimelineMenu.Instance.addItem("button", "Remove Region", () =>
+            Cast(this.props.node.regions, listSpec(Doc))?.splice(this.regions.indexOf(this.props.RegionData), 1)),
             TimelineMenu.Instance.addItem("input", `fadeIn: ${this.regiondata.fadeIn}ms`, (val) => {
                 runInAction(() => {
                     let cannotMove: boolean = false;
@@ -404,9 +397,9 @@ export class Keyframe extends React.Component<IProps> {
                 runInAction(() => {
                     const prevPosition = this.regiondata.position;
                     let cannotMove: boolean = false;
-                    this.regions.forEach(region => {
-                        if (NumCast(region.position) !== this.regiondata.position) {
-                            if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration) || (this.regiondata.duration + val > NumCast(region.position) && this.regiondata.duration + val < NumCast(region.position) + NumCast(region.duration)))) {
+                    this.regions.map(region => ({ pos: NumCast(region.position), dur: NumCast(region.duration) })).forEach(({ pos, dur }) => {
+                        if (pos !== this.regiondata.position) {
+                            if ((val < 0) || (val > pos && val < pos + dur || (this.regiondata.duration + val > pos && this.regiondata.duration + val < pos + dur))) {
                                 cannotMove = true;
                             }
                         }
@@ -420,10 +413,10 @@ export class Keyframe extends React.Component<IProps> {
             TimelineMenu.Instance.addItem("input", `duration: ${this.regiondata.duration}ms`, (val) => {
                 runInAction(() => {
                     let cannotMove: boolean = false;
-                    this.regions.forEach(region => {
-                        if (NumCast(region.position) !== this.regiondata.position) {
+                    this.regions.map(region => ({ pos: NumCast(region.position), dur: NumCast(region.duration) })).forEach(({ pos, dur }) => {
+                        if (pos !== this.regiondata.position) {
                             val += this.regiondata.position;
-                            if ((val < 0) || (val > NumCast(region.position) && val < NumCast(region.position) + NumCast(region.duration))) {
+                            if ((val < 0) || (val > pos && val < pos + dur)) {
                                 cannotMove = true;
                             }
                         }
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 7d245ab6f..234d560f1 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -593,33 +593,30 @@ export class Timeline extends React.Component<FieldViewProps> {
         trace();
         // change visible and total width
         return (
-            <div>
-                <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
-                    <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
-                        <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
-                            <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
-                                {this.drawTicks()}
-                                <div key="timeline_scrubber" className="scrubber" style={{ transform: `translate(${this._currentBarX}px)` }}>
-                                    <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div>
-                                </div>
-                                <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
-                                    {DocListCast(this.children).map(doc => {
-                                        const track = <Track ref={ref => { this.mapOfTracks.push(ref); }} node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} />
-                                        return track;
-                                    })}
-                                </div>
+            <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
+                <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
+                    <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
+                        <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
+                            {this.drawTicks()}
+                            <div key="timeline_scrubber" className="scrubber" style={{ transform: `translate(${this._currentBarX}px)` }}>
+                                <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} ></div>
                             </div>
-                            <div className="currentTime">Current: {this.getCurrentTime()}</div>
-                            <div key="timeline_title" className="title-container" ref={this._titleContainer}>
-                                {DocListCast(this.children).map(doc => <div style={{ height: `${(this._titleHeight)}px` }} className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)}
-                            </div>
-                            <div key="timeline_resize" onPointerDown={this.onResizeDown}>
-                                <FontAwesomeIcon className="resize" icon={faGripLines} />
+                            <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
+                                {DocListCast(this.children).map(doc =>
+                                    <Track ref={ref => this.mapOfTracks.push(ref)} node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} />
+                                )}
                             </div>
                         </div>
+                        <div className="currentTime">Current: {this.getCurrentTime()}</div>
+                        <div key="timeline_title" className="title-container" ref={this._titleContainer}>
+                            {DocListCast(this.children).map(doc => <div style={{ height: `${(this._titleHeight)}px` }} className="datapane" onPointerOver={() => { Doc.BrushDoc(doc); }} onPointerOut={() => { Doc.UnBrushDoc(doc); }}><p>{doc.title}</p></div>)}
+                        </div>
+                        <div key="timeline_resize" onPointerDown={this.onResizeDown}>
+                            <FontAwesomeIcon className="resize" icon={faGripLines} />
+                        </div>
                     </div>
-                    {this.timelineToolBox(1, longestTime)}
                 </div>
+                {this.timelineToolBox(1, longestTime)}
             </div>
         );
     }
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 0e3c209dc..9e2ec8886 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -1,15 +1,15 @@
-import * as React from "react";
+import { action, computed, intercept, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { observable, reaction, action, IReactionDisposer, computed, runInAction, autorun, toJS, isObservableArray, IObservableArray, trace, observe, intercept } from "mobx";
-import "./Track.scss";
-import { Doc, DocListCastAsync, DocListCast, Field } from "../../../new_fields/Doc";
-import { listSpec } from "../../../new_fields/Schema";
-import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_fields/Types";
-import { List } from "../../../new_fields/List";
-import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
-import { Transform } from "../../util/Transform";
+import * as React from "react";
+import { Doc, DocListCast, Opt } from "../../../new_fields/Doc";
 import { Copy } from "../../../new_fields/FieldSymbols";
+import { List } from "../../../new_fields/List";
 import { ObjectField } from "../../../new_fields/ObjectField";
+import { listSpec } from "../../../new_fields/Schema";
+import { Cast, NumCast } from "../../../new_fields/Types";
+import { Transform } from "../../util/Transform";
+import { Keyframe, KeyframeFunc, RegionData } from "./Keyframe";
+import "./Track.scss";
 
 interface IProps {
     node: Doc;
@@ -43,48 +43,41 @@ export class Track extends React.Component<IProps> {
         "data"
     ];
 
-    @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; }
+    @computed private get regions() { return DocListCast(this.props.node.regions); }
     @computed private get time() { return NumCast(KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement)); }
 
     ////////// life cycle functions///////////////
     componentWillMount() {
-        runInAction(() => {
-            if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); //if there is no region, then create new doc to store stuff
-            //these two lines are exactly same from timeline.tsx 
-            let relativeHeight = window.innerHeight / 20;
-            this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness
-        });
+        if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); //if there is no region, then create new doc to store stuff
+        //these two lines are exactly same from timeline.tsx 
+        const relativeHeight = window.innerHeight / 20;
+        this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness
     }
 
     componentDidMount() {
-        runInAction(async () => {
-            this._timelineVisibleReaction = this.timelineVisibleReaction();
-            this._currentBarXReaction = this.currentBarXReaction();
-            if (this.regions.length === 0) this.createRegion(this.time);
-            this.props.node.hidden = false;
-            this.props.node.opacity = 1;
-            // this.autoCreateKeyframe();
-        });
+        this._timelineVisibleReaction = this.timelineVisibleReaction();
+        this._currentBarXReaction = this.currentBarXReaction();
+        if (this.regions.length === 0) this.createRegion(this.time);
+        this.props.node.hidden = false;
+        this.props.node.opacity = 1;
+        // this.autoCreateKeyframe();
     }
 
     /**
      * mainly for disposing reactions
      */
     componentWillUnmount() {
-        runInAction(() => {
-            //disposing reactions 
-            if (this._currentBarXReaction) this._currentBarXReaction();
-            if (this._timelineVisibleReaction) this._timelineVisibleReaction();
-            if (this._autoKfReaction) this._autoKfReaction();
-        });
+        this._currentBarXReaction?.();
+        this._timelineVisibleReaction?.();
+        this._autoKfReaction?.();
     }
     ////////////////////////////////
 
 
     getLastRegionTime = () => {
         let lastTime: number = 0;
-        let lastRegion: (Doc | undefined);
-        DocListCast(this.regions).forEach(region => {
+        let lastRegion: Opt<Doc>;
+        this.regions.forEach(region => {
             const time = NumCast(region.position);
             if (lastTime <= time) {
                 lastTime = time;
@@ -100,41 +93,34 @@ export class Track extends React.Component<IProps> {
      */
     @action
     saveKeyframe = async () => {
-        console.log("saving keyframe");
-        let keyframes: List<Doc> = (Cast(this.saveStateRegion!.keyframes, listSpec(Doc)) as List<Doc>);
-        let kfIndex: number = keyframes.indexOf(this.saveStateKf!);
+        let keyframes = Cast(this.saveStateRegion?.keyframes, listSpec(Doc)) as List<Doc>;
+        let kfIndex = keyframes.indexOf(this.saveStateKf!);
         let kf = keyframes[kfIndex] as Doc; //index in the keyframe
         if (this._newKeyframe) {
-            console.log("new keyframe registering");
-            let kfList = DocListCast(this.saveStateRegion!.keyframes);
-            kfList.forEach(kf => {
-                kf.key = this.makeCopy();
-                if (kfList.indexOf(kf) === 0 || kfList.indexOf(kf) === 3) {
-                    (kf.key as Doc).opacity = 0.1;
-                } else {
-                    (kf.key as Doc).opacity = 1;
-                }
+            DocListCast(this.saveStateRegion?.keyframes).forEach((kf, index) => {
+                this.copyDocDataToKeyFrame(kf);
+                kf.opacity = (index === 0 || index === 3) ? 0.1 : 1;
             });
             this._newKeyframe = false;
         }
         if (!kf) return;
         if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
-            kf.key = this.makeCopy();
-            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, kf); // lef keyframe, if it exists
-            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, kf); //right keyframe, if it exists 
-            if (leftkf!.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
-                let edge: (Doc | undefined) = await KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, leftkf!);
-                edge!.key = this.makeCopy();
-                leftkf!.key = this.makeCopy();
-                (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
-                (Cast(leftkf!.key, Doc)! as Doc).opacity = 1;
+            this.copyDocDataToKeyFrame(kf);
+            let leftkf = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, kf); // lef keyframe, if it exists
+            let rightkf = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, kf); //right keyframe, if it exists 
+            if (leftkf?.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
+                let edge = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, leftkf);
+                edge && this.copyDocDataToKeyFrame(edge);
+                leftkf && this.copyDocDataToKeyFrame(leftkf);
+                edge && (edge!.opacity = 0.1);
+                leftkf && (leftkf!.opacity = 1);
             }
-            if (rightkf!.type === KeyframeFunc.KeyframeType.fade) {
-                let edge: (Doc | undefined) = await KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, rightkf!);
-                edge!.key = this.makeCopy();
-                rightkf!.key = this.makeCopy();
-                (Cast(edge!.key, Doc)! as Doc).opacity = 0.1;
-                (Cast(rightkf!.key, Doc)! as Doc).opacity = 1;
+            if (rightkf?.type === KeyframeFunc.KeyframeType.fade) {
+                let edge = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, rightkf);
+                edge && this.copyDocDataToKeyFrame(edge);
+                rightkf && this.copyDocDataToKeyFrame(rightkf);
+                edge && (edge.opacity = 0.1);
+                rightkf && (rightkf.opacity = 1);
             }
         }
         keyframes[kfIndex] = kf;
@@ -148,24 +134,22 @@ export class Track extends React.Component<IProps> {
      */
     @action
     autoCreateKeyframe = () => {
-        const { node } = this.props;
-        const objects = this.objectWhitelist.map(key => node[key]);
+        const objects = this.objectWhitelist.map(key => this.props.node[key]);
         intercept(this.props.node, change => {
             console.log(change);
             return change;
         });
         return reaction(() => {
-            return [...this.primitiveWhitelist.map(key => node[key]), ...objects];
+            return [...this.primitiveWhitelist.map(key => this.props.node[key]), ...objects];
         }, (changed, reaction) => {
             //check for region 
-            this.findRegion(this.time).then((region) => {
-                if (region !== undefined) { //if region at scrub time exist
-                    let r = region as any as RegionData; //for some region is returning undefined... which is not the case
-                    if (DocListCast(r.keyframes).find(kf => kf.time === this.time) === undefined) { //basically when there is no additional keyframe at that timespot 
-                        this.makeKeyData(r, this.time, KeyframeFunc.KeyframeType.default);
-                    }
+            const region = this.findRegion(this.time);
+            if (region !== undefined) { //if region at scrub time exist
+                let r = region as RegionData; //for some region is returning undefined... which is not the case
+                if (DocListCast(r.keyframes).find(kf => kf.time === this.time) === undefined) { //basically when there is no additional keyframe at that timespot 
+                    this.makeKeyData(r, this.time, KeyframeFunc.KeyframeType.default);
                 }
-            });
+            }
         }, { fireImmediately: false });
     }
 
@@ -188,20 +172,19 @@ export class Track extends React.Component<IProps> {
     @action
     currentBarXReaction = () => {
         return reaction(() => this.props.currentBarX, () => {
-            this.findRegion(this.time).then((regiondata: (Doc | undefined)) => {
-                if (regiondata) {
-                    this.props.node.hidden = false;
-                    // if (!this._autoKfReaction) {
-                    //     // console.log("creating another reaction"); 
-                    //     // this._autoKfReaction = this.autoCreateKeyframe(); 
-                    // }
-                    this.timeChange();
-                } else {
-                    this.props.node.hidden = true;
-                    this.props.node.opacity = 0;
-                    //if (this._autoKfReaction) this._autoKfReaction(); 
-                }
-            });
+            const regiondata = this.findRegion(this.time);
+            if (regiondata) {
+                this.props.node.hidden = false;
+                // if (!this._autoKfReaction) {
+                //     // console.log("creating another reaction"); 
+                //     // this._autoKfReaction = this.autoCreateKeyframe(); 
+                // }
+                this.timeChange();
+            } else {
+                this.props.node.hidden = true;
+                this.props.node.opacity = 0;
+                //if (this._autoKfReaction) this._autoKfReaction(); 
+            }
         });
     }
 
@@ -214,13 +197,11 @@ export class Track extends React.Component<IProps> {
             return this.props.timelineVisible;
         }, isVisible => {
             if (isVisible) {
-                DocListCast(this.regions).forEach(region => {
-                    if (!BoolCast((Cast(region, Doc) as Doc).hasData)) {
-                        for (let i = 0; i < 4; i++) {
-                            DocListCast(((Cast(region, Doc) as Doc).keyframes as List<Doc>))[i].key = this.makeCopy();
-                            if (i === 0 || i === 3) { //manually inputing fades
-                                (DocListCast(((Cast(region, Doc) as Doc).keyframes as List<Doc>))[i].key! as Doc).opacity = 0.1;
-                            }
+                this.regions.filter(region => !region.hasData).forEach(region => {
+                    for (let i = 0; i < 4; i++) {
+                        this.copyDocDataToKeyFrame(DocListCast(region.keyframes)[i]);
+                        if (i === 0 || i === 3) { //manually inputing fades
+                            DocListCast(region.keyframes)[i].opacity = 0.1;
                         }
                     }
                 });
@@ -266,12 +247,11 @@ export class Track extends React.Component<IProps> {
      */
     @action
     private applyKeys = async (kf: Doc) => {
-        let kfNode = await Cast(kf.key, Doc) as Doc;
         this.primitiveWhitelist.forEach(key => {
-            if (!kfNode[key]) {
+            if (!kf[key]) {
                 this.props.node[key] = undefined;
             } else {
-                let stored = kfNode[key];
+                let stored = kf[key];
                 this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
             }
         });
@@ -297,16 +277,14 @@ export class Track extends React.Component<IProps> {
      */
     @action
     interpolate = async (left: Doc, right: Doc) => {
-        let leftNode = await (left.key) as Doc;
-        let rightNode = await (right.key) as Doc;
         this.primitiveWhitelist.forEach(key => {
-            if (leftNode[key] && rightNode[key] && typeof (leftNode[key]) === "number" && typeof (rightNode[key]) === "number") { //if it is number, interpolate
-                let dif = NumCast(rightNode[key]) - NumCast(leftNode[key]);
+            if (left[key] && right[key] && typeof (left[key]) === "number" && typeof (right[key]) === "number") { //if it is number, interpolate
+                let dif = NumCast(right[key]) - NumCast(left[key]);
                 let deltaLeft = this.time - NumCast(left.time);
                 let ratio = deltaLeft / (NumCast(right.time) - NumCast(left.time));
-                this.props.node[key] = NumCast(leftNode[key]) + (dif * ratio);
+                this.props.node[key] = NumCast(left[key]) + (dif * ratio);
             } else { // case data 
-                let stored = leftNode[key];
+                let stored = left[key];
                 this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
             }
         });
@@ -316,17 +294,8 @@ export class Track extends React.Component<IProps> {
      * finds region that corresponds to specific time (is there a region at this time?)
      * linear O(n) (maybe possible to optimize this with other Data structures?)
      */
-    @action
-    findRegion = async (time: number) => {
-        let foundRegion: (Doc | undefined) = undefined;
-        let regions = await DocListCastAsync(this.regions);
-        regions!.forEach(region => {
-            region = region as RegionData;
-            if (time >= NumCast(region.position) && time <= (NumCast(region.position) + NumCast(region.duration))) {
-                foundRegion = region;
-            }
-        });
-        return foundRegion;
+    findRegion = (time: number) => {
+        return this.regions?.find(rd => (time >= NumCast(rd.position) && time <= (NumCast(rd.position) + NumCast(rd.duration))));
     }
 
 
@@ -345,8 +314,8 @@ export class Track extends React.Component<IProps> {
      * creates a region (KEYFRAME.TSX stuff). 
      */
     @action
-    createRegion = async (time: number) => {
-        if (await this.findRegion(time) === undefined) {  //check if there is a region where double clicking (prevents phantom regions)
+    createRegion = (time: number) => {
+        if (this.findRegion(time) === undefined) {  //check if there is a region where double clicking (prevents phantom regions)
             let regiondata = KeyframeFunc.defaultKeyframe(); //create keyframe data
 
             regiondata.position = time; //set position
@@ -356,7 +325,7 @@ export class Track extends React.Component<IProps> {
                 regiondata.duration = rightRegion.position - regiondata.position;
             }
             if (this.regions.length === 0 || !rightRegion || (rightRegion && rightRegion.position - regiondata.position >= NumCast(regiondata.fadeIn) + NumCast(regiondata.fadeOut))) {
-                this.regions.push(regiondata);
+                Cast(this.props.node.regions, listSpec(Doc))?.push(regiondata);
                 this._newKeyframe = true;
                 this.saveStateRegion = regiondata;
                 return regiondata;
@@ -366,48 +335,36 @@ export class Track extends React.Component<IProps> {
 
     @action
     makeKeyData = (regiondata: RegionData, time: number, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time 
-        let doclist = DocListCast(regiondata.keyframes)!;
-        let existingkf: (Doc | undefined) = undefined;
-        doclist.forEach(TK => {
-            if (TK.time === time) existingkf = TK;
-        });
+        const trackKeyFrames = DocListCast(regiondata.keyframes)!;
+        const existingkf = trackKeyFrames.find(TK => TK.time === time);
         if (existingkf) return existingkf;
         //else creates a new doc. 
-        let TK: Doc = new Doc();
-        TK.time = time;
-        TK.key = this.makeCopy();
-        TK.type = type;
+        const newKeyFrame: Doc = new Doc();
+        newKeyFrame.time = time;
+        newKeyFrame.type = type;
+        this.copyDocDataToKeyFrame(newKeyFrame);
         //assuming there are already keyframes (for keeping keyframes in order, sorted by time)
-        if (doclist.length === 0) regiondata.keyframes!.push(TK);
-        doclist.forEach(kf => {
-            let index = doclist.indexOf(kf);
-            let kfTime = NumCast(kf.time);
-            if ((kfTime < time && index === doclist.length - 1) || (kfTime < time && time < NumCast(doclist[index + 1].time))) {
-                regiondata.keyframes!.splice(index + 1, 0, TK);
-                return;
+        if (trackKeyFrames.length === 0) regiondata.keyframes!.push(newKeyFrame);
+        trackKeyFrames.map(kf => NumCast(kf.time)).forEach((kfTime, index) => {
+            if ((kfTime < time && index === trackKeyFrames.length - 1) || (kfTime < time && time < NumCast(trackKeyFrames[index + 1].time))) {
+                regiondata.keyframes!.splice(index + 1, 0, newKeyFrame);
             }
         });
-        return TK;
+        return newKeyFrame;
     }
 
     @action
-    makeCopy = () => {
-        let doc = new Doc();
-        this.primitiveWhitelist.forEach(key => {
-            let originalVal = this.props.node[key];
-            if (key === "data") {
-                console.log(originalVal);
-            }
-            doc[key] = originalVal instanceof ObjectField ? originalVal[Copy]() : this.props.node[key];
+    copyDocDataToKeyFrame = (doc: Doc) => {
+        this.primitiveWhitelist.map(key => {
+            const originalVal = this.props.node[key];
+            doc[key] = originalVal instanceof ObjectField ? originalVal[Copy]() : originalVal;
         });
-        return doc;
     }
 
     /**
      * UI sstuff here. Not really much to change
      */
     render() {
-        trace();
         return (
             <div className="track-container">
                 <div className="track">
@@ -415,7 +372,7 @@ export class Track extends React.Component<IProps> {
                         onDoubleClick={this.onInnerDoubleClick}
                         onPointerOver={() => Doc.BrushDoc(this.props.node)}
                         onPointerOut={() => Doc.UnBrushDoc(this.props.node)} >
-                        {DocListCast(this.regions).map((region, i) => {
+                        {this.regions?.map((region, i) => {
                             return <Keyframe key={`${i}`} {...this.props} RegionData={region} makeKeyData={this.makeKeyData} />;
                         })}
                     </div>
-- 
cgit v1.2.3-70-g09d2


From c0ec0efe6fb03096c9abbee9e5d72e8cab54bf6b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 28 Apr 2020 23:02:23 -0400
Subject: from last

---
 src/client/views/animationtimeline/Timeline.tsx | 4 +---
 src/client/views/animationtimeline/Track.tsx    | 4 ++--
 2 files changed, 3 insertions(+), 5 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 234d560f1..295c1e18c 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -467,9 +467,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     timeIndicator(lengthString: string, totalTime: number) {
         if (this.props.Document.isATOn) {
             return (
-                <>
-                    <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{`Total: ${this.toReadTime(totalTime)}`}</div>
-                </>
+                <div key="time-text" className="animation-text" style={{ visibility: this.props.Document.isATOn ? "visible" : "hidden", display: this.props.Document.isATOn ? "flex" : "none" }}>{`Total: ${this.toReadTime(totalTime)}`}</div>
             );
         }
         else {
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 9e2ec8886..382bf9b64 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -35,8 +35,8 @@ export class Track extends React.Component<IProps> {
     private primitiveWhitelist = [
         "x",
         "y",
-        "width",
-        "height",
+        "_width",
+        "_height",
         "opacity",
     ];
     private objectWhitelist = [
-- 
cgit v1.2.3-70-g09d2


From f78d614f99fed4555f7a1211e522e34efc19f809 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 29 Apr 2020 11:53:55 -0400
Subject: cleanup of timeline before merge

---
 src/client/views/animationtimeline/Timeline.tsx |  16 +-
 src/client/views/linking/LinkFollowBox.tsx      | 571 ------------------------
 src/new_fields/Doc.ts                           |  18 -
 3 files changed, 14 insertions(+), 591 deletions(-)
 delete mode 100644 src/client/views/linking/LinkFollowBox.tsx

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 295c1e18c..677267ca0 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -372,6 +372,18 @@ export class Timeline extends React.Component<FieldViewProps> {
         this.changeCurrentBarX(currCurrent);
     }
 
+
+    resetView(doc: Doc) {
+        doc._panX = doc._customOriginX ?? 0;
+        doc._panY = doc._customOriginY ?? 0;
+        doc.scale = doc._customOriginScale ?? 1;
+    }
+
+    setView(doc: Doc) {
+        doc._customOriginX = doc._panX;
+        doc._customOriginY = doc._panY;
+        doc._customOriginScale = doc.scale;
+    }
     /**
      * zooming mechanism (increment and spacing changes)
      */
@@ -455,8 +467,8 @@ export class Timeline extends React.Component<FieldViewProps> {
                     </div>
                     <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
                         {this.timeIndicator(lengthString, totalTime)}
-                        <div className="resetView-tool" title="Return to Default View" onClick={() => Doc.resetView(this.props.Document)}><FontAwesomeIcon icon="compress-arrows-alt" size="lg" /></div>
-                        <div className="resetView-tool" style={{ display: this._isAuthoring ? "flex" : "none" }} title="Set Default View" onClick={() => Doc.setView(this.props.Document)}><FontAwesomeIcon icon="expand-arrows-alt" size="lg" /></div>
+                        <div className="resetView-tool" title="Return to Default View" onClick={() => this.resetView(this.props.Document)}><FontAwesomeIcon icon="compress-arrows-alt" size="lg" /></div>
+                        <div className="resetView-tool" style={{ display: this._isAuthoring ? "flex" : "none" }} title="Set Default View" onClick={() => this.setView(this.props.Document)}><FontAwesomeIcon icon="expand-arrows-alt" size="lg" /></div>
 
                     </div>
                 </div>
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
deleted file mode 100644
index 705469fd2..000000000
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ /dev/null
@@ -1,571 +0,0 @@
-import { observable, computed, action, runInAction, reaction, IReactionDisposer } from "mobx";
-import React = require("react");
-import { observer } from "mobx-react";
-import { FieldViewProps, FieldView } from "../nodes/FieldView";
-import { Doc, DocListCastAsync, Opt } from "../../../new_fields/Doc";
-import { undoBatch } from "../../util/UndoManager";
-import { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types";
-import { CollectionViewType } from "../collections/CollectionView";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { SelectionManager } from "../../util/SelectionManager";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DocumentView } from "../nodes/DocumentView";
-import "./LinkFollowBox.scss";
-import { SearchUtil } from "../../util/SearchUtil";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { listSpec } from "../../../new_fields/Schema";
-import { DocServer } from "../../DocServer";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faTimes } from '@fortawesome/free-solid-svg-icons';
-import { docs_v1 } from "googleapis";
-import { Utils } from "../../../Utils";
-import { Link } from "@react-pdf/renderer";
-
-export enum FollowModes {
-    OPENTAB = "Open in Tab",
-    OPENRIGHT = "Open in Right Split",
-    OPENFULL = "Open Full Screen",
-    PAN = "Pan to Document",
-    INPLACE = "Open In Place"
-}
-
-enum FollowOptions {
-    ZOOM = "Zoom",
-    NOZOOM = "No Zoom",
-}
-
-@observer
-export class LinkFollowBox extends React.Component<FieldViewProps> {
-
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkFollowBox, fieldKey); }
-    public static Instance: LinkFollowBox | undefined;
-    @observable static linkDoc: Doc | undefined = undefined;
-    @observable static destinationDoc: Doc | undefined = undefined;
-    @observable static sourceDoc: Doc | undefined = undefined;
-    @observable selectedMode: string = "";
-    @observable selectedContext: Doc | undefined = undefined;
-    @observable selectedContextAliases: Doc[] | undefined = undefined;
-    @observable selectedOption: string = "";
-    @observable selectedContextString: string = "";
-    @observable sourceView: DocumentView | undefined = undefined;
-    @observable canPan: boolean = false;
-    @observable shouldUseOnlyParentContext = false;
-    _contextDisposer?: IReactionDisposer;
-
-    @observable private _docs: { col: Doc, target: Doc }[] = [];
-    @observable private _otherDocs: { col: Doc, target: Doc }[] = [];
-
-    constructor(props: FieldViewProps) {
-        super(props);
-        LinkFollowBox.Instance = this;
-        this.resetVars();
-        this.props.Document.isBackground = true;
-    }
-
-    componentDidMount = () => {
-        this.resetVars();
-
-        this._contextDisposer = reaction(
-            () => this.selectedContextString,
-            async () => {
-                const ref = await DocServer.GetRefField(this.selectedContextString);
-                runInAction(() => {
-                    if (ref instanceof Doc) {
-                        this.selectedContext = ref;
-                    }
-                });
-                if (this.selectedContext instanceof Doc) {
-                    const aliases = await SearchUtil.GetViewsOfDocument(this.selectedContext);
-                    runInAction(() => { this.selectedContextAliases = aliases; });
-                }
-            }
-        );
-    }
-
-    componentWillUnmount = () => {
-        this._contextDisposer && this._contextDisposer();
-    }
-
-    async resetPan() {
-        if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
-            runInAction(() => this.canPan = false);
-            if (this.sourceView.props.ContainingCollectionDoc._viewType === CollectionViewType.Freeform) {
-                const docs = Cast(this.sourceView.props.ContainingCollectionDoc.data, listSpec(Doc), []);
-                const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(LinkFollowBox.destinationDoc));
-
-                aliases.forEach(alias => {
-                    if (docs.filter(doc => doc === alias).length > 0) {
-                        runInAction(() => { this.canPan = true; });
-                    }
-                });
-            }
-        }
-    }
-
-    @action
-    resetVars = () => {
-        this.selectedContext = undefined;
-        this.selectedContextString = "";
-        this.selectedMode = "";
-        this.selectedOption = "";
-        LinkFollowBox.linkDoc = undefined;
-        LinkFollowBox.sourceDoc = undefined;
-        LinkFollowBox.destinationDoc = undefined;
-        this.sourceView = undefined;
-        this.canPan = false;
-        this.shouldUseOnlyParentContext = false;
-    }
-
-    async fetchDocuments() {
-        if (LinkFollowBox.destinationDoc) {
-            const dest: Doc = LinkFollowBox.destinationDoc;
-            const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(dest));
-            const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${dest[Id]}"` });
-            const map: Map<Doc, Doc> = new Map;
-            const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs)));
-            allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index])));
-            docs.forEach(doc => map.delete(doc));
-            runInAction(async () => {
-                this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: dest }));
-                this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target }));
-                const tcontext = LinkFollowBox.linkDoc && (await Cast(LinkFollowBox.linkDoc.anchor2Context, Doc)) as Doc;
-                runInAction(() => tcontext && this._docs.splice(0, 0, { col: tcontext, target: dest }));
-            });
-        }
-    }
-
-    @action
-    setLinkDocs = (linkDoc: Doc, source: Doc, dest: Doc) => {
-        this.resetVars();
-
-        LinkFollowBox.linkDoc = linkDoc;
-        LinkFollowBox.sourceDoc = source;
-        LinkFollowBox.destinationDoc = dest;
-        this.fetchDocuments();
-
-        SelectionManager.SelectedDocuments().forEach(dv => {
-            if (dv.props.Document === LinkFollowBox.sourceDoc) {
-                this.sourceView = dv;
-            }
-        });
-
-        this.resetPan();
-    }
-
-    highlightDoc = () => LinkFollowBox.destinationDoc && Doc.linkFollowHighlight(LinkFollowBox.destinationDoc);
-
-    @undoBatch
-    openFullScreen = () => {
-        if (LinkFollowBox.destinationDoc) {
-            const view = DocumentManager.Instance.getDocumentView(LinkFollowBox.destinationDoc);
-            view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
-        }
-    }
-
-    @undoBatch
-    openColFullScreen = (options: { context: Doc }) => {
-        if (LinkFollowBox.destinationDoc) {
-            if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
-                const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2;
-                const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2;
-                options.context._panX = newPanX;
-                options.context._panY = newPanY;
-            }
-            const view = DocumentManager.Instance.getDocumentView(options.context);
-            view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
-            this.highlightDoc();
-        }
-    }
-
-    // should container be a doc or documentview or what? This one needs work and is more long term
-    @undoBatch
-    openInContainer = (options: { container: Doc }) => {
-
-    }
-
-    static _addDocTab: (undefined | ((doc: Doc, dataDoc: Opt<Doc>, where: string) => boolean));
-
-    static setAddDocTab = (addFunc: (doc: Doc, dataDoc: Opt<Doc>, where: string) => boolean) => {
-        LinkFollowBox._addDocTab = addFunc;
-    }
-
-    @undoBatch
-    openLinkColRight = (options: { context: Doc, shouldZoom: boolean }) => {
-        if (LinkFollowBox.destinationDoc) {
-            options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
-            if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
-                const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2;
-                const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2;
-                options.context._panX = newPanX;
-                options.context._panY = newPanY;
-            }
-            (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "onRight");
-
-            if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom });
-
-            this.highlightDoc();
-            SelectionManager.DeselectAll();
-        }
-    }
-
-    @undoBatch
-    openLinkRight = () => {
-        if (LinkFollowBox.destinationDoc) {
-            const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
-            (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, undefined, "onRight");
-            this.highlightDoc();
-            SelectionManager.DeselectAll();
-        }
-
-    }
-
-    @undoBatch
-    jumpToLink = async (options: { shouldZoom: boolean }) => {
-        if (LinkFollowBox.sourceDoc && LinkFollowBox.linkDoc) {
-            const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
-            //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation));
-
-            DocumentManager.Instance.FollowLink(LinkFollowBox.linkDoc, LinkFollowBox.sourceDoc, focus, options && options.shouldZoom, false, undefined);
-        }
-    }
-
-    @undoBatch
-    openLinkTab = () => {
-        if (LinkFollowBox.destinationDoc) {
-            const fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
-            // this.prosp.addDocTab is empty -- use the link source's addDocTab 
-            (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, undefined, "inTab");
-
-            this.highlightDoc();
-            SelectionManager.DeselectAll();
-        }
-    }
-
-    @undoBatch
-    openLinkColTab = (options: { context: Doc, shouldZoom: boolean }) => {
-        if (LinkFollowBox.destinationDoc) {
-            options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
-            if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
-                const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2;
-                const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2;
-                options.context._panX = newPanX;
-                options.context._panY = newPanY;
-            }
-            (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "inTab");
-            if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom });
-
-            this.highlightDoc();
-            SelectionManager.DeselectAll();
-        }
-    }
-
-    @undoBatch
-    openLinkInPlace = (options: { shouldZoom: boolean }) => {
-
-        if (LinkFollowBox.destinationDoc && LinkFollowBox.sourceDoc) {
-            if (this.sourceView && this.sourceView.props.addDocument) {
-                const destViews = DocumentManager.Instance.getDocumentViews(LinkFollowBox.destinationDoc);
-                if (!destViews.find(dv => dv.props.ContainingCollectionView === this.sourceView!.props.ContainingCollectionView)) {
-                    const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
-                    const y = NumCast(LinkFollowBox.sourceDoc.y);
-                    const x = NumCast(LinkFollowBox.sourceDoc.x);
-
-                    const width = NumCast(LinkFollowBox.sourceDoc._width);
-                    const height = NumCast(LinkFollowBox.sourceDoc._height);
-
-                    alias.x = x + width + 30;
-                    alias.y = y;
-                    alias._width = width;
-                    alias._height = height;
-
-                    this.sourceView.props.addDocument(alias);
-                }
-            }
-
-            this.jumpToLink({ shouldZoom: options.shouldZoom });
-
-            this.highlightDoc();
-            SelectionManager.DeselectAll();
-        }
-    }
-
-    //set this to be the default link behavior, can be any of the above
-    public defaultLinkBehavior: (options?: any) => void = this.jumpToLink;
-
-    @action
-    currentLinkBehavior = () => {
-        // this.resetPan();
-        if (LinkFollowBox.destinationDoc) {
-            if (this.selectedContextString === "") {
-                this.selectedContextString = "self";
-                this.selectedContext = LinkFollowBox.destinationDoc;
-            }
-            if (this.selectedOption === "") this.selectedOption = FollowOptions.NOZOOM;
-            const shouldZoom: boolean = this.selectedOption === FollowOptions.NOZOOM ? false : true;
-            const notOpenInContext: boolean = this.selectedContextString === "self" || this.selectedContextString === LinkFollowBox.destinationDoc[Id];
-
-            if (this.selectedMode === FollowModes.INPLACE) {
-                if (shouldZoom !== undefined) this.openLinkInPlace({ shouldZoom: shouldZoom });
-            }
-            else if (this.selectedMode === FollowModes.OPENFULL) {
-                if (notOpenInContext) this.openFullScreen();
-                else this.selectedContext && this.openColFullScreen({ context: this.selectedContext });
-            }
-            else if (this.selectedMode === FollowModes.OPENRIGHT) {
-                if (notOpenInContext) this.openLinkRight();
-                else this.selectedContext && this.openLinkColRight({ context: this.selectedContext, shouldZoom: shouldZoom });
-            }
-            else if (this.selectedMode === FollowModes.OPENTAB) {
-                if (notOpenInContext) this.openLinkTab();
-                else this.selectedContext && this.openLinkColTab({ context: this.selectedContext, shouldZoom: shouldZoom });
-            }
-            else if (this.selectedMode === FollowModes.PAN) {
-                this.jumpToLink({ shouldZoom: shouldZoom });
-            }
-            else return;
-        }
-    }
-
-    @action
-    handleModeChange = (e: React.ChangeEvent) => {
-        const target = e.target as HTMLInputElement;
-        this.selectedMode = target.value;
-        this.selectedContext = undefined;
-        this.selectedContextString = "";
-
-        this.shouldUseOnlyParentContext = (this.selectedMode === FollowModes.INPLACE || this.selectedMode === FollowModes.PAN);
-
-        if (this.shouldUseOnlyParentContext) {
-            if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
-                this.selectedContext = this.sourceView.props.ContainingCollectionDoc;
-                this.selectedContextString = (StrCast(this.sourceView.props.ContainingCollectionDoc.title));
-            }
-        }
-    }
-
-    @action
-    handleOptionChange = (e: React.ChangeEvent) => {
-        const target = e.target as HTMLInputElement;
-        this.selectedOption = target.value;
-    }
-
-    @action
-    handleContextChange = (e: React.ChangeEvent) => {
-        const target = e.target as HTMLInputElement;
-        this.selectedContextString = target.value;
-        // selectedContext is updated in reaction
-        this.selectedOption = "";
-    }
-
-    @computed
-    get canOpenInPlace() {
-        if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
-            const colDoc = this.sourceView.props.ContainingCollectionDoc;
-            if (colDoc._viewType === CollectionViewType.Freeform) return true;
-        }
-        return false;
-    }
-
-    @computed
-    get availableModes() {
-        return (
-            <div>
-                <label><input
-                    type="radio"
-                    name="mode"
-                    value={FollowModes.OPENRIGHT}
-                    checked={this.selectedMode === FollowModes.OPENRIGHT}
-                    onChange={this.handleModeChange}
-                    disabled={false} />
-                    {FollowModes.OPENRIGHT}
-                </label><br />
-                <label><input
-                    type="radio"
-                    name="mode"
-                    value={FollowModes.OPENTAB}
-                    checked={this.selectedMode === FollowModes.OPENTAB}
-                    onChange={this.handleModeChange}
-                    disabled={false} />
-                    {FollowModes.OPENTAB}
-                </label><br />
-                <label><input
-                    type="radio"
-                    name="mode"
-                    value={FollowModes.OPENFULL}
-                    checked={this.selectedMode === FollowModes.OPENFULL}
-                    onChange={this.handleModeChange}
-                    disabled={false} />
-                    {FollowModes.OPENFULL}
-                </label><br />
-                <label><input
-                    type="radio"
-                    name="mode"
-                    value={FollowModes.PAN}
-                    checked={this.selectedMode === FollowModes.PAN}
-                    onChange={this.handleModeChange}
-                    disabled={!this.canPan} />
-                    {FollowModes.PAN}
-                </label><br />
-                <label><input
-                    type="radio"
-                    name="mode"
-                    value={FollowModes.INPLACE}
-                    checked={this.selectedMode === FollowModes.INPLACE}
-                    onChange={this.handleModeChange}
-                    disabled={!this.canOpenInPlace} />
-                    {FollowModes.INPLACE}
-                </label><br />
-            </div>
-        );
-    }
-
-    @computed
-    get parentName() {
-        if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
-            return this.sourceView.props.ContainingCollectionDoc.title;
-        }
-    }
-
-    @computed
-    get parentID(): string {
-        if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
-            return StrCast(this.sourceView.props.ContainingCollectionDoc[Id]);
-        }
-        return "col";
-    }
-
-    @computed
-    get availableContexts() {
-        return (
-            this.shouldUseOnlyParentContext ?
-                <label><input
-                    type="radio" disabled={true}
-                    name="context"
-                    value={this.parentID}
-                    checked={true} />
-                    {this.parentName} (Parent Collection)
-                </label>
-                :
-                <div>
-                    <label><input
-                        type="radio" disabled={LinkFollowBox.linkDoc ? false : true}
-                        name="context"
-                        value={LinkFollowBox.destinationDoc ? StrCast(LinkFollowBox.destinationDoc[Id]) : "self"}
-                        checked={LinkFollowBox.destinationDoc ? this.selectedContextString === StrCast(LinkFollowBox.destinationDoc[Id]) || this.selectedContextString === "self" : true}
-                        onChange={this.handleContextChange} />
-                        Open Self
-                </label><br />
-                    {[...this._docs, ...this._otherDocs].map(doc => {
-                        if (doc && doc.target && doc.col.title !== "Recently Closed") {
-                            return <div key={doc.col[Id] + doc.target[Id]}><label key={doc.col[Id] + doc.target[Id]}>
-                                <input
-                                    type="radio" disabled={LinkFollowBox.linkDoc ? false : true}
-                                    name="context"
-                                    value={StrCast(doc.col[Id])}
-                                    checked={this.selectedContextString === StrCast(doc.col[Id])}
-                                    onChange={this.handleContextChange} />
-                                {doc.col.title}
-                            </label><br /></div>;
-                        }
-                    })}
-                </div>
-        );
-    }
-
-    @computed
-    get shouldShowZoom(): boolean {
-        if (this.selectedMode === FollowModes.OPENFULL) return false;
-        if (this.shouldUseOnlyParentContext) return true;
-        if (LinkFollowBox.destinationDoc ? this.selectedContextString === LinkFollowBox.destinationDoc[Id] : "self") return false;
-
-        let contextMatch: boolean = false;
-        if (this.selectedContextAliases) {
-            this.selectedContextAliases.forEach(alias => {
-                if (alias._viewType === CollectionViewType.Freeform) contextMatch = true;
-            });
-        }
-        if (contextMatch) return true;
-
-        return false;
-    }
-
-    @computed
-    get availableOptions() {
-        if (LinkFollowBox.destinationDoc) {
-            return (
-                this.shouldShowZoom ?
-                    <div>
-                        <label><input
-                            type="radio"
-                            name="option"
-                            value={FollowOptions.ZOOM}
-                            checked={this.selectedOption === FollowOptions.ZOOM}
-                            onChange={this.handleOptionChange}
-                            disabled={false} />
-                            {FollowOptions.ZOOM}
-                        </label><br />
-                        <label><input
-                            type="radio"
-                            name="option"
-                            value={FollowOptions.NOZOOM}
-                            checked={this.selectedOption === FollowOptions.NOZOOM}
-                            onChange={this.handleOptionChange}
-                            disabled={false} />
-                            {FollowOptions.NOZOOM}
-                        </label><br />
-                    </div>
-                    :
-                    <div>No Available Options</div>
-            );
-        }
-        return null;
-    }
-
-    render() {
-        return (
-            <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document._height), width: NumCast(this.props.Document._width) }}>
-                <div className="linkFollowBox-header">
-                    <div className="topHeader">
-                        {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"}
-                        <div onClick={() => this.props.Document.isMinimized = true} className="closeDocument"><FontAwesomeIcon icon={faTimes} size="lg" /></div>
-                    </div>
-                    <div className=" direction-indicator">{LinkFollowBox.linkDoc ?
-                        LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc ? "Source: " + StrCast(LinkFollowBox.sourceDoc.title) + ", Destination: " + StrCast(LinkFollowBox.destinationDoc.title)
-                            : "" : ""}</div>
-                </div>
-                <div className="linkFollowBox-content" style={{ height: NumCast(this.props.Document._height) - 110 }}>
-                    <div className="linkFollowBox-item">
-                        <div className="linkFollowBox-item title">Mode</div>
-                        <div className="linkFollowBox-itemContent">
-                            {LinkFollowBox.linkDoc ? this.availableModes : "Please select a link to view modes"}
-                        </div>
-                    </div>
-                    <div className="linkFollowBox-item">
-                        <div className="linkFollowBox-item title">Context</div>
-                        <div className="linkFollowBox-itemContent">
-                            {this.selectedMode !== "" ? this.availableContexts : "Please select a mode to view contexts"}
-                        </div>
-                    </div>
-                    <div className="linkFollowBox-item">
-                        <div className="linkFollowBox-item title">Options</div>
-                        <div className="linkFollowBox-itemContent">
-                            {this.selectedContextString !== "" ? this.availableOptions : "Please select a context to view options"}
-                        </div>
-                    </div>
-                </div>
-                <div className="linkFollowBox-footer">
-                    <button
-                        onClick={this.resetVars}>
-                        Clear Link
-                    </button>
-                    <div style={{ width: 20 }}></div>
-                    <button
-                        onClick={this.currentLinkBehavior}
-                        disabled={(LinkFollowBox.linkDoc) ? false : true}>
-                        Follow Link
-                    </button>
-                </div>
-            </div>
-        );
-    }
-}
\ No newline at end of file
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 5eaaa3bae..153af933a 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -255,24 +255,6 @@ export namespace Doc {
     //     });
     // }
 
-    export function resetView(doc: Doc) {
-        doc._panX = doc._customOriginX ?? 0;
-        doc._panY = doc._customOriginY ?? 0;
-        doc.scale = doc._customOriginScale ?? 1;
-    }
-
-    export function resetViewToOrigin(doc: Doc) {
-        doc._panX = 0;
-        doc._panY = 0;
-        doc.scale = 1;
-    }
-
-    export function setView(doc: Doc) {
-        doc._customOriginX = doc._panX;
-        doc._customOriginY = doc._panY;
-        doc._customOriginScale = doc.scale;
-    }
-
     export function RunCachedUpdate(doc: Doc, field: string) {
         const update = doc[CachedUpdates][field];
         if (update) {
-- 
cgit v1.2.3-70-g09d2


From 43e573ea0cf4634b65b513c633f90be84846f8df Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 29 Apr 2020 21:08:37 -0400
Subject: changed detailedView template to be a layoutstring.  fixed text boxes
 to allow new templates from templated text boxes.  fixed __LAYOUT__ to work
 with comound layout strings

---
 src/client/documents/Documents.ts                    | 19 +++++++++++++++++--
 src/client/views/animationtimeline/Timeline.tsx      |  4 +---
 .../views/nodes/formattedText/FormattedTextBox.tsx   | 20 +++++++++++++++++---
 src/new_fields/Doc.ts                                |  2 +-
 .../authentication/models/current_user_utils.ts      |  2 +-
 5 files changed, 37 insertions(+), 10 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 811bb5fb2..0d1d73ca3 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -541,8 +541,23 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options);
         }
 
-        export function TextDocument(text: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.RTF), text, options, undefined, "text");
+        export function TextDocument(text: string, options: DocumentOptions = {}, fieldKey: string = "text") {
+            const rtf = {
+                doc: {
+                    type: "doc", content: [{
+                        type: "paragraph",
+                        content: [{
+                            type: "text",
+                            text
+                        }]
+                    }]
+                },
+                selection: { type: "text", anchor: 1, head: 1 },
+                storedMarks: []
+            };
+
+            const field = text ? new RichTextField(JSON.stringify(rtf), text) : undefined;
+            return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey);
         }
 
         export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 677267ca0..fe1e40778 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -119,9 +119,7 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
     componentWillUnmount() {
-        runInAction(() => {
-            this.props.Document.AnimationLength = this._time; //save animation length
-        });
+        this.props.Document.AnimationLength = this._time; //save animation length
     }
     /////////////////////////////////////////////////
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 782a91547..2038efbc6 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -419,14 +419,28 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
 
         const funcs: ContextMenuProps[] = [];
         this.rootDoc.isTemplateDoc && funcs.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.props.Document), icon: "eye" });
-        !this.rootDoc.isTemplateDoc && funcs.push({ description: "Show Template", event: async () => this.props.addDocTab(Doc.GetProto(this.layoutDoc), "onRight"), icon: "eye" });
         funcs.push({ description: "Reset Default Layout", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" });
-        !this.rootDoc.isTemplateDoc && funcs.push({
+        !this.layoutDoc.isTemplateDoc && funcs.push({
             description: "Make Template", event: () => {
-                this.props.Document.isTemplateDoc = makeTemplate(this.props.Document);
+                this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc);
                 Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.props.Document);
             }, icon: "eye"
         });
+        this.layoutDoc.isTemplateDoc && funcs.push({
+            description: "Make New Template", event: () => {
+                const title = this.rootDoc.title as string;
+                this.rootDoc.layout = (this.layoutDoc as Doc).layout as string;
+                this.rootDoc.title = this.layoutDoc.isTemplateForField as string;
+                this.rootDoc.isTemplateDoc = false;
+                this.rootDoc.isTemplateForField = "";
+                this.rootDoc.layoutKey = "layout";
+                this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
+                this.rootDoc._width = this.layoutDoc._width || 300;  // the width and height are stored on the template, since we're getting rid of the old template
+                this.rootDoc._height = this.layoutDoc._height || 200;  // we need to copy them over to the root.  This should probably apply to all '_' fields
+                this.rootDoc._backgroundColor = Cast(this.layoutDoc._backgroundColor, "string", null);
+                Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
+            }, icon: "eye"
+        });
         funcs.push({ description: "Toggle Single Line", event: () => this.props.Document._singleLine = !this.props.Document._singleLine, icon: "expand-arrows-alt" });
         funcs.push({ description: "Toggle Sidebar", event: () => this.props.Document._showSidebar = !this.props.Document._showSidebar, icon: "expand-arrows-alt" });
         funcs.push({ description: "Toggle Dictation Icon", event: () => this.props.Document._showAudio = !this.props.Document._showAudio, icon: "expand-arrows-alt" });
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 153af933a..77eee03ce 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -183,7 +183,7 @@ export class Doc extends RefField {
             let renderFieldKey: any;
             const layoutField = templateLayoutDoc[StrCast(templateLayoutDoc.layoutKey, "layout")];
             if (typeof layoutField === "string") {
-                renderFieldKey = layoutField.split("'")[1];
+                renderFieldKey = layoutField.split("fieldKey={'")[1].split("'")[0];//layoutField.split("'")[1];
             } else {
                 return Cast(layoutField, Doc, null);
             }
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 4b2aafac1..eedd3ee67 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -72,7 +72,7 @@ export class CurrentUserUtils {
         }
 
         if (doc["template-button-description"] === undefined) {
-            const descriptionTemplate = Docs.Create.TextDocument("", { title: "header", _height: 100 });
+            const descriptionTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created
             Doc.GetProto(descriptionTemplate).layout = "<div><FormattedTextBox {...props} background='orange' height='50px' fieldKey={'header'}/><FormattedTextBox {...props} height='calc(100% - 50px)' fieldKey={'text'}/></div>";
             descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView");
 
-- 
cgit v1.2.3-70-g09d2


From 90c45914694a971c1b3cb356921c04f337625db5 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 30 Apr 2020 00:06:08 -0400
Subject: fixes for snapping & timeline.  changed looi of document decorations

---
 src/client/util/DragManager.ts                     |  8 ++---
 src/client/views/DocumentDecorations.scss          | 34 +++++++++++++++++++++-
 src/client/views/DocumentDecorations.tsx           |  9 +++---
 src/client/views/MainView.tsx                      |  1 -
 src/client/views/MetadataEntryMenu.scss            |  9 +++---
 src/client/views/animationtimeline/Timeline.tsx    | 33 ++++++++-------------
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 14 ++++++---
 .../views/nodes/formattedText/FormattedTextBox.tsx |  8 +++--
 8 files changed, 74 insertions(+), 42 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 36c26fe2c..bccdf38ce 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -310,10 +310,10 @@ export namespace DragManager {
         const currTop = e.pageY - yFromTop;
         const currRight = e.pageX + xFromRight;
         const currBottom = e.pageY + yFromBottom;
-        const closestLeft = vertSnapLines.reduce((prev, curr) => Math.abs(prev - currLeft) > Math.abs(curr - currLeft) ? curr : prev);
-        const closestTop = horizSnapLines.reduce((prev, curr) => Math.abs(prev - currTop) > Math.abs(curr - currTop) ? curr : prev);
-        const closestRight = vertSnapLines.reduce((prev, curr) => Math.abs(prev - currRight) > Math.abs(curr - currRight) ? curr : prev);
-        const closestBottom = horizSnapLines.reduce((prev, curr) => Math.abs(prev - currBottom) > Math.abs(curr - currBottom) ? curr : prev);
+        const closestLeft = vertSnapLines.reduce((prev, curr) => Math.abs(prev - currLeft) > Math.abs(curr - currLeft) ? curr : prev, currLeft);
+        const closestTop = horizSnapLines.reduce((prev, curr) => Math.abs(prev - currTop) > Math.abs(curr - currTop) ? curr : prev, currTop);
+        const closestRight = vertSnapLines.reduce((prev, curr) => Math.abs(prev - currRight) > Math.abs(curr - currRight) ? curr : prev, currRight);
+        const closestBottom = horizSnapLines.reduce((prev, curr) => Math.abs(prev - currBottom) > Math.abs(curr - currBottom) ? curr : prev, currBottom);
         const distFromClosestLeft = Math.abs(e.pageX - xFromLeft - closestLeft);
         const distFromClosestTop = Math.abs(e.pageY - yFromTop - closestTop);
         const distFromClosestRight = Math.abs(e.pageX + xFromRight - closestRight);
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 28cf9fd47..61d517d43 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -21,9 +21,13 @@ $linkGap : 3px;
         background: none;
     }
 
+
     .documentDecorations-resizer {
         pointer-events: auto;
         background: $alt-accent;
+        opacity: 0.1;
+    }
+    .documentDecorations-resizer:hover {
         opacity: 1;
     }
 
@@ -80,7 +84,20 @@ $linkGap : 3px;
     #documentDecorations-topLeftResizer,
     #documentDecorations-bottomRightResizer {
         cursor: nwse-resize;
-        background: dimGray;
+        background: unset;
+        opacity: 1;
+    }
+    #documentDecorations-topLeftResizer {
+        border-left: black 2px solid;
+        border-top: black solid 2px;
+    }
+    #documentDecorations-bottomRightResizer {
+        border-right: black 2px solid;
+        border-bottom: black solid 2px;
+    }
+    #documentDecorations-topLeftResizer:hover,
+    #documentDecorations-bottomRightResizer:hover {
+        opacity: 1;
     }
 
     #documentDecorations-bottomRightResizer {
@@ -89,8 +106,23 @@ $linkGap : 3px;
 
     #documentDecorations-topRightResizer,
     #documentDecorations-bottomLeftResizer {
+        cursor: nesw-resize;
+        background: unset;
+        opacity: 1;
+    }
+    #documentDecorations-topRightResizer {
+        border-right: black 2px solid;
+        border-top: black 2px solid;
+    }
+    #documentDecorations-bottomLeftResizer {
+        border-left: black 2px solid;
+        border-bottom: black 2px solid;
+    }
+    #documentDecorations-topRightResizer:hover,
+    #documentDecorations-bottomLeftResizer:hover {
         cursor: nesw-resize;
         background: dimGray;
+        opacity: 1;
     }
 
     #documentDecorations-topResizer,
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 312acd5b2..973ec2e89 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -473,10 +473,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer"
                     onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) : <div id="documentDecorations-levelSelector" className="documentDecorations-selector" title="tap to select containing document"
-                    onPointerDown={this.onSelectorUp} onContextMenu={(e) => e.preventDefault()}>
-                    <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
-                </div>}
+                {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
+                    <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
+                        title="tap to select containing document" onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
+                        <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
+                    </div>}
                 <div id="documentDecorations-borderRadius" className="documentDecorations-radius"
                     onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}></div>
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 62b2d1d18..e5a8ebcb5 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -42,7 +42,6 @@ import { OverlayView } from './OverlayView';
 import PDFMenu from './pdf/PDFMenu';
 import { PreviewCursor } from './PreviewCursor';
 import { ScriptField } from '../../new_fields/ScriptField';
-import { DragManager } from '../util/DragManager';
 import { TimelineMenu } from './animationtimeline/TimelineMenu';
 
 @observer
diff --git a/src/client/views/MetadataEntryMenu.scss b/src/client/views/MetadataEntryMenu.scss
index 5776cf070..28de0b7a5 100644
--- a/src/client/views/MetadataEntryMenu.scss
+++ b/src/client/views/MetadataEntryMenu.scss
@@ -9,9 +9,10 @@
 }
 
 .metadataEntry-autoSuggester {
-    width: 100%;
+    width: 80%;
     height: 100%;
-    padding-right: 10px;
+    margin: 0;
+    display: inline-block;
 }
 
 #metadataEntry-outer {
@@ -25,7 +26,7 @@
     flex-direction: column;
 }
 .metadataEntry-inputArea {
-    display:flex;
+    display:inline-block;
     flex-direction: row;
 }
 
@@ -44,7 +45,7 @@
 .react-autosuggest__input {
     border: 1px solid #aaa;
     border-radius: 4px;
-    width: 100%;
+    width: 75%;
 }
 
 .react-autosuggest__input--focused {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index fe1e40778..77656b85f 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -71,7 +71,6 @@ export class Timeline extends React.Component<FieldViewProps> {
     @observable private _tickIncrement = this.DEFAULT_TICK_INCREMENT;
     @observable private _time = 100000; //DEFAULT
     @observable private _playButton = faPlayCircle;
-    @observable private _timelineVisible = false;
     @observable private _mouseToggled = false;
     @observable private _doubleClickEnabled = false;
     @observable private _titleHeight = 0;
@@ -336,20 +335,6 @@ export class Timeline extends React.Component<FieldViewProps> {
     }
 
 
-    /**
-     * context menu function. 
-     * opens the timeline or closes the timeline. 
-     * Used in: Freeform
-     */
-    timelineContextMenu = (e: React.MouseEvent): void => {
-        ContextMenu.Instance.addItem({
-            description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
-                this._timelineVisible = !this._timelineVisible;
-            }), icon: this._timelineVisible ? faEyeSlash : faEye
-        });
-    }
-
-
     /**
      * timeline zoom function 
      * use mouse middle button to zoom in/out the timeline
@@ -463,7 +448,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                             <div key="round-toggle-slider" ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown={this.toggleChecked}> </div>
                         </div>
                     </div>
-                    <div className="time-box overview-tool" style={{ display: this._timelineVisible ? "flex" : "none" }}>
+                    <div className="time-box overview-tool" style={{ display: "flex" }}>
                         {this.timeIndicator(lengthString, totalTime)}
                         <div className="resetView-tool" title="Return to Default View" onClick={() => this.resetView(this.props.Document)}><FontAwesomeIcon icon="compress-arrows-alt" size="lg" /></div>
                         <div className="resetView-tool" style={{ display: this._isAuthoring ? "flex" : "none" }} title="Set Default View" onClick={() => this.setView(this.props.Document)}><FontAwesomeIcon icon="expand-arrows-alt" size="lg" /></div>
@@ -481,10 +466,16 @@ export class Timeline extends React.Component<FieldViewProps> {
             );
         }
         else {
+            const ctime = `Current: ${this.getCurrentTime()}`;
+            const ttime = `Total: ${this.toReadTime(this._time)}`;
             return (
                 <div style={{ flexDirection: "column" }}>
-                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Current: ${this.getCurrentTime()}`}</div>
-                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>{`Total: ${this.toReadTime(this._time)}`}</div>
+                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>
+                        {ctime}
+                    </div>
+                    <div className="animation-text" style={{ fontSize: "10px", width: "100%", display: !this.props.Document.isATOn ? "block" : "none" }}>
+                        {ttime}
+                    </div>
                 </div>
             );
         }
@@ -601,8 +592,8 @@ export class Timeline extends React.Component<FieldViewProps> {
         trace();
         // change visible and total width
         return (
-            <div style={{ visibility: this._timelineVisible ? "visible" : "hidden" }}>
-                <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn && this._timelineVisible) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
+            <div style={{ visibility: "visible" }}>
+                <div key="timeline_wrapper" style={{ visibility: BoolCast(this.props.Document.isATOn) ? "visible" : "hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)" }}>
                     <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, top: `0px` }}>
                         <div key="timeline_info" className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}>
                             {this.drawTicks()}
@@ -611,7 +602,7 @@ export class Timeline extends React.Component<FieldViewProps> {
                             </div>
                             <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{ width: `${this._totalLength}px` }}>
                                 {DocListCast(this.children).map(doc =>
-                                    <Track ref={ref => this.mapOfTracks.push(ref)} node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={this._timelineVisible} />
+                                    <Track ref={ref => this.mapOfTracks.push(ref)} node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} collection={this.props.Document} timelineVisible={true} />
                                 )}
                             </div>
                         </div>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 0c9403429..77de486d9 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,5 +1,5 @@
 import { library } from "@fortawesome/fontawesome-svg-core";
-import { faEye } from "@fortawesome/free-regular-svg-icons";
+import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons";
 import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faFileUpload, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
 import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
@@ -1093,7 +1093,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const options = ContextMenu.Instance.findByDescription("Options...");
         const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
 
-        this._timelineRef.current!.timelineContextMenu(e);
         optionItems.push({ description: "reset view", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
         optionItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" });
         optionItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
@@ -1130,8 +1129,15 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             }
         });
         ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
-        this._timelineRef.current!.timelineContextMenu(e);
+
+
+        ContextMenu.Instance.addItem({
+            description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
+                this._timelineVisible = !this._timelineVisible;
+            }), icon: this._timelineVisible ? faEyeSlash : faEye
+        });
     }
+    @observable _timelineVisible = false;
 
     intersectRect(r1: { left: number, top: number, width: number, height: number },
         r2: { left: number, top: number, width: number, height: number }) {
@@ -1215,7 +1221,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 easing={this.easing} viewDefDivClick={this.props.viewDefDivClick} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
                 {this.children}
             </CollectionFreeFormViewPannableContents>
-            <Timeline ref={this._timelineRef} {...this.props} />
+            {this._timelineVisible ? <Timeline ref={this._timelineRef} {...this.props} /> : (null)}
         </MarqueeView>;
     }
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 2038efbc6..4df693c9a 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -435,9 +435,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 this.rootDoc.isTemplateForField = "";
                 this.rootDoc.layoutKey = "layout";
                 this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
-                this.rootDoc._width = this.layoutDoc._width || 300;  // the width and height are stored on the template, since we're getting rid of the old template
-                this.rootDoc._height = this.layoutDoc._height || 200;  // we need to copy them over to the root.  This should probably apply to all '_' fields
-                this.rootDoc._backgroundColor = Cast(this.layoutDoc._backgroundColor, "string", null);
+                setTimeout(() => {
+                    this.rootDoc._width = this.layoutDoc._width || 300;  // the width and height are stored on the template, since we're getting rid of the old template
+                    this.rootDoc._height = this.layoutDoc._height || 200;  // we need to copy them over to the root.  This should probably apply to all '_' fields
+                    this.rootDoc._backgroundColor = Cast(this.layoutDoc._backgroundColor, "string", null);
+                }, 10);
                 Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
             }, icon: "eye"
         });
-- 
cgit v1.2.3-70-g09d2


From 5e6352c78be5b2a9fe791bd87da9b2415ced4839 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 1 May 2020 19:35:37 -0400
Subject: added childLayoutTemplate to render collection children w/o modifying
 them. fixed docComponent's layoutDoc to use LayoutDoc prop.  change buxton
 template to use new template mechanisms. fixed   fixed lint errors.

---
 src/client/documents/Documents.ts                  |  5 +-
 src/client/util/DragManager.ts                     |  2 +-
 src/client/views/DocComponent.tsx                  |  2 +-
 src/client/views/animationtimeline/Timeline.tsx    |  4 +-
 .../views/animationtimeline/TimelineMenu.tsx       | 81 +++++++++++-----------
 src/client/views/animationtimeline/Track.tsx       | 50 ++++++-------
 .../views/collections/CollectionStackingView.tsx   |  2 +-
 src/client/views/collections/CollectionSubView.tsx | 17 -----
 .../views/collections/CollectionTreeView.tsx       | 36 ++++------
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 11 ++-
 src/client/views/nodes/PresBox.tsx                 |  2 +-
 .../views/nodes/formattedText/DashFieldView.tsx    |  2 +-
 src/new_fields/documentSchemas.ts                  |  2 +-
 13 files changed, 94 insertions(+), 122 deletions(-)

(limited to 'src/client/views/animationtimeline/Timeline.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a8b10bc7b..434b26312 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -93,7 +93,8 @@ export interface DocumentOptions {
     scale?: number;
     isDisplayPanel?: boolean; // whether the panel functions as GoldenLayout "stack" used to display documents
     forceActive?: boolean;
-    layout?: string | Doc;
+    layout?: string | Doc; // default layout string for a document
+    childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view)
     hideFilterView?: boolean; // whether to hide the filter popout on collections
     hideHeadings?: boolean; // whether stacking view column headings should be hidden
     isTemplateForField?: string; // the field key for which the containing document is a rendering template
@@ -123,7 +124,7 @@ export interface DocumentOptions {
     borderRounding?: string;
     boxShadow?: string;
     dontRegisterChildren?: boolean;
-    "onDoubleClick-rawScript"?: string // onDoubleClick script in raw text form
+    "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form
     "onClick-rawScript"?: string; // onClick script in raw text form
     "onCheckedClick-rawScript"?: string; // onChecked script in raw text form
     "onCheckedClick-params"?: List<string>; // parameter list for onChecked treeview functions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index c48611eff..c06ad3d60 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -316,7 +316,7 @@ export namespace DragManager {
                 return closestDists[minIndex] < snapThreshold ? closestPts[minIndex] + offs[minIndex] : drag;
             }
             return drag;
-        }
+        };
 
         return { thisX: snapVal([xFromLeft, xFromRight], e.pageX, vertSnapLines), thisY: snapVal([yFromTop, yFromBottom], e.pageY, horizSnapLines) };
     }
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 0a8f0c9a7..629b0f447 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -20,7 +20,7 @@ export function DocComponent<P extends DocComponentProps, T>(schemaCtor: (doc: D
         // This is the "The Document" -- it encapsulates, data, layout, and any templates
         @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
         // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
-        @computed get layoutDoc() { return Doc.Layout(this.props.Document); }
+        @computed get layoutDoc() { return Doc.Layout(this.props.Document, this.props.LayoutDoc?.()); }
         // This is the data part of a document -- ie, the data that is constant across all views of the document
         @computed get dataDoc() { return this.props.Document[DataSym] as Doc; }
 
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 77656b85f..466cbb867 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -525,8 +525,8 @@ export class Timeline extends React.Component<FieldViewProps> {
     @action.bound
     changeLengths() {
         if (this._infoContainer.current) {
-            this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; //the visible length of the timeline (the length that you current see)
-            this._visibleStart = this._infoContainer.current!.scrollLeft; //where the div starts
+            this._visibleLength = this._infoContainer.current.getBoundingClientRect().width; //the visible length of the timeline (the length that you current see)
+            this._visibleStart = this._infoContainer.current.scrollLeft; //where the div starts
         }
     }
 
diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx
index 59c25596e..53ca9acad 100644
--- a/src/client/views/animationtimeline/TimelineMenu.tsx
+++ b/src/client/views/animationtimeline/TimelineMenu.tsx
@@ -1,7 +1,7 @@
 import * as React from "react";
-import {observable, action, runInAction} from "mobx"; 
-import {observer} from "mobx-react"; 
-import "./TimelineMenu.scss"; 
+import { observable, action, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import "./TimelineMenu.scss";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { faChartLine, faRoad, faClipboard, faPen, faTrash, faTable } from "@fortawesome/free-solid-svg-icons";
 import { Utils } from "../../../Utils";
@@ -9,67 +9,66 @@ import { Utils } from "../../../Utils";
 
 @observer
 export class TimelineMenu extends React.Component {
-    public static Instance:TimelineMenu; 
+    public static Instance: TimelineMenu;
 
     @observable private _opacity = 0;
-    @observable private _x = 0; 
-    @observable private _y = 0; 
-    @observable private _currentMenu:JSX.Element[] = []; 
+    @observable private _x = 0;
+    @observable private _y = 0;
+    @observable private _currentMenu: JSX.Element[] = [];
 
-    constructor (props:Readonly<{}>){
-        super(props); 
-        TimelineMenu.Instance = this; 
+    constructor(props: Readonly<{}>) {
+        super(props);
+        TimelineMenu.Instance = this;
     }
-    
+
     @action
-    openMenu = (x?:number, y?:number) => {
-        this._opacity = 1; 
-        x ? this._x = x : this._x = 0; 
-        y ? this._y = y : this._y = 0; 
+    openMenu = (x?: number, y?: number) => {
+        this._opacity = 1;
+        x ? this._x = x : this._x = 0;
+        y ? this._y = y : this._y = 0;
     }
 
     @action
     closeMenu = () => {
-        this._opacity = 0; 
-        this._currentMenu = []; 
-        this._x = -1000000; 
-        this._y = -1000000; 
+        this._opacity = 0;
+        this._currentMenu = [];
+        this._x = -1000000;
+        this._y = -1000000;
     }
 
     @action
-    addItem = (type: "input" | "button", title: string, event: (e:any, ...args:any[]) => void) => {
-        if (type === "input"){
-            let inputRef = React.createRef<HTMLInputElement>(); 
-            let text = ""; 
-            this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {inputRef} placeholder={title} onChange={(e) => {
+    addItem = (type: "input" | "button", title: string, event: (e: any, ...args: any[]) => void) => {
+        if (type === "input") {
+            const inputRef = React.createRef<HTMLInputElement>();
+            let text = "";
+            this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg" /><input className="timeline-menu-input" ref={inputRef} placeholder={title} onChange={(e) => {
                 e.stopPropagation();
                 text = e.target.value;
             }} onKeyDown={(e) => {
                 if (e.keyCode === 13) {
-                    event(text); 
-                    this.closeMenu();                    
-                     e.stopPropagation(); 
-                } 
-            }}/></div>); 
+                    event(text);
+                    this.closeMenu();
+                    e.stopPropagation();
+                }
+            }} /></div>);
         } else if (type === "button") {
-            let buttonRef = React.createRef<HTMLDivElement>(); 
-            this._currentMenu.push( <div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={(e) => {
-                e.preventDefault(); 
-                e.stopPropagation(); 
-                event(e); 
-                this.closeMenu(); 
-            }}>{title}</p></div>); 
-        }  
+            this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine} size="lg" /><p className="timeline-menu-desc" onClick={(e) => {
+                e.preventDefault();
+                e.stopPropagation();
+                event(e);
+                this.closeMenu();
+            }}>{title}</p></div>);
+        }
     }
 
-    @action 
-    addMenu = (title:string) => {
-        this._currentMenu.unshift(<div key={Utils.GenerateGuid()} className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>);     
+    @action
+    addMenu = (title: string) => {
+        this._currentMenu.unshift(<div key={Utils.GenerateGuid()} className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>);
     }
 
     render() {
         return (
-            <div key={Utils.GenerateGuid()} className="timeline-menu-container" style={{opacity: this._opacity, left: this._x, top: this._y}} >
+            <div key={Utils.GenerateGuid()} className="timeline-menu-container" style={{ opacity: this._opacity, left: this._x, top: this._y }} >
                 {this._currentMenu}
             </div>
         );
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 79eb60fae..461db4858 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -90,9 +90,9 @@ export class Track extends React.Component<IProps> {
      */
     @action
     saveKeyframe = async () => {
-        let keyframes = Cast(this.saveStateRegion?.keyframes, listSpec(Doc)) as List<Doc>;
-        let kfIndex = keyframes.indexOf(this.saveStateKf!);
-        let kf = keyframes[kfIndex] as Doc; //index in the keyframe
+        const keyframes = Cast(this.saveStateRegion?.keyframes, listSpec(Doc)) as List<Doc>;
+        const kfIndex = keyframes.indexOf(this.saveStateKf!);
+        const kf = keyframes[kfIndex] as Doc; //index in the keyframe
         if (this._newKeyframe) {
             DocListCast(this.saveStateRegion?.keyframes).forEach((kf, index) => {
                 this.copyDocDataToKeyFrame(kf);
@@ -103,17 +103,17 @@ export class Track extends React.Component<IProps> {
         if (!kf) return;
         if (kf.type === KeyframeFunc.KeyframeType.default) { // only save for non-fades
             this.copyDocDataToKeyFrame(kf);
-            let leftkf = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, kf); // lef keyframe, if it exists
-            let rightkf = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, kf); //right keyframe, if it exists 
+            const leftkf = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, kf); // lef keyframe, if it exists
+            const rightkf = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, kf); //right keyframe, if it exists 
             if (leftkf?.type === KeyframeFunc.KeyframeType.fade) { //replicating this keyframe to fades
-                let edge = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, leftkf);
+                const edge = KeyframeFunc.calcMinLeft(this.saveStateRegion!, this.time, leftkf);
                 edge && this.copyDocDataToKeyFrame(edge);
                 leftkf && this.copyDocDataToKeyFrame(leftkf);
-                edge && (edge!.opacity = 0.1);
-                leftkf && (leftkf!.opacity = 1);
+                edge && (edge.opacity = 0.1);
+                leftkf && (leftkf.opacity = 1);
             }
             if (rightkf?.type === KeyframeFunc.KeyframeType.fade) {
-                let edge = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, rightkf);
+                const edge = KeyframeFunc.calcMinRight(this.saveStateRegion!, this.time, rightkf);
                 edge && this.copyDocDataToKeyFrame(edge);
                 rightkf && this.copyDocDataToKeyFrame(rightkf);
                 edge && (edge.opacity = 0.1);
@@ -142,7 +142,7 @@ export class Track extends React.Component<IProps> {
             //check for region 
             const region = this.findRegion(this.time);
             if (region !== undefined) { //if region at scrub time exist
-                let r = region as RegionData; //for some region is returning undefined... which is not the case
+                const r = region as RegionData; //for some region is returning undefined... which is not the case
                 if (DocListCast(r.keyframes).find(kf => kf.time === this.time) === undefined) { //basically when there is no additional keyframe at that timespot 
                     this.makeKeyData(r, this.time, KeyframeFunc.KeyframeType.default);
                 }
@@ -222,11 +222,11 @@ export class Track extends React.Component<IProps> {
         } else if (this._newKeyframe) {
             await this.saveKeyframe();
         }
-        let regiondata = await this.findRegion(Math.round(this.time)); //finds a region that the scrubber is on
+        const regiondata = await this.findRegion(Math.round(this.time)); //finds a region that the scrubber is on
         if (regiondata) {
-            let leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata, this.time); // lef keyframe, if it exists
-            let rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.time); //right keyframe, if it exists        
-            let currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
+            const leftkf: (Doc | undefined) = await KeyframeFunc.calcMinLeft(regiondata, this.time); // lef keyframe, if it exists
+            const rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.time); //right keyframe, if it exists        
+            const currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
             if (currentkf) {
                 console.log("is current");
                 await this.applyKeys(currentkf);
@@ -248,7 +248,7 @@ export class Track extends React.Component<IProps> {
             if (!kf[key]) {
                 this.props.node[key] = undefined;
             } else {
-                let stored = kf[key];
+                const stored = kf[key];
                 this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
             }
         });
@@ -261,7 +261,7 @@ export class Track extends React.Component<IProps> {
     @action
     calcCurrent = (region: Doc) => {
         let currentkf: (Doc | undefined) = undefined;
-        let keyframes = DocListCast(region.keyframes!);
+        const keyframes = DocListCast(region.keyframes!);
         keyframes.forEach((kf) => {
             if (NumCast(kf.time) === Math.round(this.time)) currentkf = kf;
         });
@@ -276,12 +276,12 @@ export class Track extends React.Component<IProps> {
     interpolate = async (left: Doc, right: Doc) => {
         this.primitiveWhitelist.forEach(key => {
             if (left[key] && right[key] && typeof (left[key]) === "number" && typeof (right[key]) === "number") { //if it is number, interpolate
-                let dif = NumCast(right[key]) - NumCast(left[key]);
-                let deltaLeft = this.time - NumCast(left.time);
-                let ratio = deltaLeft / (NumCast(right.time) - NumCast(left.time));
+                const dif = NumCast(right[key]) - NumCast(left[key]);
+                const deltaLeft = this.time - NumCast(left.time);
+                const ratio = deltaLeft / (NumCast(right.time) - NumCast(left.time));
                 this.props.node[key] = NumCast(left[key]) + (dif * ratio);
             } else { // case data 
-                let stored = left[key];
+                const stored = left[key];
                 this.props.node[key] = stored instanceof ObjectField ? stored[Copy]() : stored;
             }
         });
@@ -301,8 +301,8 @@ export class Track extends React.Component<IProps> {
      */
     @action
     onInnerDoubleClick = (e: React.MouseEvent) => {
-        let inner = this._inner.current!;
-        let offsetX = Math.round((e.clientX - inner.getBoundingClientRect().left) * this.props.transform.Scale);
+        const inner = this._inner.current!;
+        const offsetX = Math.round((e.clientX - inner.getBoundingClientRect().left) * this.props.transform.Scale);
         this.createRegion(KeyframeFunc.convertPixelTime(offsetX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement));
     }
 
@@ -313,10 +313,10 @@ export class Track extends React.Component<IProps> {
     @action
     createRegion = (time: number) => {
         if (this.findRegion(time) === undefined) {  //check if there is a region where double clicking (prevents phantom regions)
-            let regiondata = KeyframeFunc.defaultKeyframe(); //create keyframe data
+            const regiondata = KeyframeFunc.defaultKeyframe(); //create keyframe data
 
             regiondata.position = time; //set position
-            let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, regiondata, this.regions);
+            const rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, regiondata, this.regions);
 
             if (rightRegion && rightRegion.position - regiondata.position <= 4000) { //edge case when there is less than default 4000 duration space between this and right region
                 regiondata.duration = rightRegion.position - regiondata.position;
@@ -332,7 +332,7 @@ export class Track extends React.Component<IProps> {
 
     @action
     makeKeyData = (regiondata: RegionData, time: number, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time 
-        const trackKeyFrames = DocListCast(regiondata.keyframes)!;
+        const trackKeyFrames = DocListCast(regiondata.keyframes);
         const existingkf = trackKeyFrames.find(TK => TK.time === time);
         if (existingkf) return existingkf;
         //else creates a new doc. 
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 6c230d5b1..01766f65f 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -128,7 +128,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return layoutDoc._fitWidth ? wid * NumCast(layoutDoc.scrollHeight, nh) / (nw || 1) : layoutDoc[HeightSym]();
     }
     componentDidMount() {
-        super.componentDidMount();
+        super.componentDidMount?.();
 
         // reset section headers when a new filter is inputted
         this._pivotFieldDisposer = reaction(
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 8cc1af55b..e44bbae78 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -58,7 +58,6 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
         private dropDisposer?: DragManager.DragDropDisposer;
         private gestureDisposer?: GestureUtils.GestureEventDisposer;
         protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
-        private _childLayoutDisposer?: IReactionDisposer;
         protected _mainCont?: HTMLDivElement;
         protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
             this.dropDisposer?.();
@@ -75,25 +74,9 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
             this.createDashEventsTarget(ele);
         }
 
-        componentDidMount() {
-            this._childLayoutDisposer = reaction(() => ({ childDocs: this.childDocs, childLayout: Cast(this.props.Document.childLayout, Doc) }),
-                ({ childDocs, childLayout }) => {
-                    if (childLayout instanceof Doc) {
-                        childDocs.map(doc => {
-                            doc.layout_fromParent = childLayout;
-                            doc.layoutKey = "layout_fromParent";
-                        });
-                    }
-                    else if (!(childLayout instanceof Promise)) {
-                        childDocs.filter(d => !d.isTemplateForField).map(doc => doc.layoutKey === "layout_fromParent" && (doc.layoutKey = "layout"));
-                    }
-                }, { fireImmediately: true });
-
-        }
         componentWillUnmount() {
             this.gestureDisposer?.();
             this.multiTouchDisposer?.();
-            this._childLayoutDisposer?.();
         }
 
         @computed get dataDoc() {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 71358a8ec..296c1a39c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -725,14 +725,6 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         }
         ContextMenu.Instance.addItem({
             description: "Buxton Layout", icon: "eye", event: () => {
-                DocListCast(this.dataDoc[this.props.fieldKey]).map(d => {
-                    DocListCast(d.data).map((img, i) => {
-                        const caption = (d.captions as any)[i];
-                        if (caption) {
-                            Doc.GetProto(img).caption = caption;
-                        }
-                    });
-                });
                 const { ImageDocument } = Docs.Create;
                 const { Document } = this.props;
                 const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
@@ -742,21 +734,19 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                 heroView._showTitle = "title";
                 heroView._showTitleHover = "titlehover";
 
-                Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data",
-                    Docs.Create.FontIconDocument({
-                        title: "hero view", _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias",
-                        dragFactory: heroView, removeDropProperties: new List<string>(["dropAction"]), icon: "portrait",
-                        onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
-                    }));
-
-                Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data",
-                    Docs.Create.FontIconDocument({
-                        title: "detail view", _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias",
-                        dragFactory: detailView, removeDropProperties: new List<string>(["dropAction"]), icon: "file-alt",
-                        onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
-                    }));
-
-                Document.childLayout = heroView;
+                const doubleClickView = ImageDocument("http://cs.brown.edu/~bcz/face.gif", { _width: 400 });  // replace with desired double click target
+                DocListCast(this.dataDoc[this.props.fieldKey]).map(d => {
+                    DocListCast(d.data).map((img, i) => {
+                        const caption = (d.captions as any)[i];
+                        if (caption) {
+                            Doc.GetProto(img).caption = caption;
+                            Doc.GetProto(img).doubleClickView = doubleClickView;
+                        }
+                    });
+                    d.layout = ImageBox.LayoutString("hero");
+                });
+
+                Document.childLayoutTemplate = heroView;
                 Document.childDetailView = detailView;
                 Document._viewType = CollectionViewType.Time;
                 Document._forceActive = true;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b4eb22444..45ef0455e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -855,9 +855,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @computed get libraryPath() { return this.props.LibraryPath ? [...this.props.LibraryPath, this.props.Document] : []; }
     @computed get onChildClickHandler() { return this.props.childClickScript || ScriptCast(this.Document.onChildClick); }
     @computed get onChildDoubleClickHandler() { return this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); }
-    backgroundHalo = () => BoolCast(this.Document.useClusters);
     @computed get backgroundActive() { return this.layoutDoc.isBackground && (this.props.ContainingCollectionView?.active() || this.props.active()); }
+    backgroundHalo = () => BoolCast(this.Document.useClusters);
     parentActive = () => this.props.active() || this.backgroundActive ? true : false;
+    childLayoutFunc = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null);
     getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps {
         return {
             ...this.props,
@@ -867,12 +868,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             DataDoc: childData,
             Document: childLayout,
             LibraryPath: this.libraryPath,
+            LayoutDoc: this.childLayoutFunc,
             FreezeDimensions: this.props.freezeChildDimensions,
             layoutKey: undefined,
             setupDragLines: this.setupDragLines,
             rootSelected: childData ? this.rootSelected : returnFalse,
             dropAction: StrCast(this.props.Document.childDropAction) as dropActionType,
-            //onClick: undefined, // this.props.onClick,  // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them
             onClick: this.onChildClickHandler,
             onDoubleClick: this.onChildDoubleClickHandler,
             ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform,
@@ -999,7 +1000,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         return { newPool, computedElementData: this.doFreeformLayout(newPool) };
     }
 
-    childLayoutDocFunc = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null);
     get doLayoutComputation() {
         const { newPool, computedElementData } = this.doInternalLayoutComputation;
         runInAction(() =>
@@ -1025,7 +1025,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                     replica={entry[1].replica}
                     dataProvider={this.childDataProvider}
                     sizeProvider={this.childSizeProvider}
-                    LayoutDoc={this.childLayoutDocFunc}
                     pointerEvents={
                         this.backgroundActive ?
                             true :
@@ -1042,7 +1041,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     }
 
     componentDidMount() {
-        super.componentDidMount();
+        super.componentDidMount?.();
         this._layoutComputeReaction = reaction(() => this.doLayoutComputation,
             (elements) => this._layoutElements = elements || [],
             { fireImmediately: true, name: "doLayout" });
@@ -1156,7 +1155,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             if (this.intersectRect(docDims(doc), rect)) {
                 snappableDocs.push(doc);
             }
-        }
+        };
         const snappableDocs: Doc[] = [];  // the set of documents in the visible viewport that we will try to snap to;
         const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) };
         this.getActiveDocuments().filter(doc => !doc.isBackground && doc.z === undefined).map(doc => isDocInView(doc, selRect));  // first see if there are any foreground docs to snap to
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 72bbc9e4b..6e3420f22 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -260,7 +260,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     panelHeight = () => this.props.PanelHeight() - 20;
 
     active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.layoutDoc.isBackground) &&
-        (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false);
+        (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
 
     whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
 
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 1b22ed4cd..d87d6e424 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -104,7 +104,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
                     r?.addEventListener("pointerdown", action((e) => this._showEnumerables = true));
                 }} >
                     {strVal}
-                </span>
+                </span>;
             }
         }
     }
diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts
index 7bf1c03c8..fd9a304f9 100644
--- a/src/new_fields/documentSchemas.ts
+++ b/src/new_fields/documentSchemas.ts
@@ -78,7 +78,7 @@ export const positionSchema = createSchema({
 });
 
 export const collectionSchema = createSchema({
-    childLayout: Doc, // layout template for children of a collecion
+    childLayoutTemplate: Doc, // layout template for children of a collecion
     childDetailView: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to use this field)
     onChildClick: ScriptField, // script to run for each child when its clicked
     onChildDoubleClick: ScriptField, // script to run for each child when its clicked
-- 
cgit v1.2.3-70-g09d2

