aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
authorandrewdkim <adkim414@gmail.com>2019-08-01 17:00:10 -0400
committerandrewdkim <adkim414@gmail.com>2019-08-01 17:00:10 -0400
commitbf3d45f8a16d23384a308f65adfa9a2baee495af (patch)
tree15e8d74c57436a5987133bf5732764a8155bb282 /src/client/views/nodes
parent59f3d2405870135314d00ea80acae0dc17b99955 (diff)
prosemirror
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx10
-rw-r--r--src/client/views/nodes/Keyframe.scss94
-rw-r--r--src/client/views/nodes/Keyframe.tsx550
-rw-r--r--src/client/views/nodes/Timeline.scss170
-rw-r--r--src/client/views/nodes/Timeline.tsx530
-rw-r--r--src/client/views/nodes/Track.scss15
-rw-r--r--src/client/views/nodes/Track.tsx266
7 files changed, 7 insertions, 1628 deletions
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index f019868aa..9b37a6491 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,6 +1,6 @@
import { library } from '@fortawesome/fontawesome-svg-core';
import { faEdit, faSmile, faTextHeight } from '@fortawesome/free-solid-svg-icons';
-import { action, IReactionDisposer, observable, reaction, runInAction, computed, trace } from "mobx";
+import { action, IReactionDisposer, observable, reaction, runInAction, computed, trace, toJS } from "mobx";
import { observer } from "mobx-react";
import { baseKeymap } from "prosemirror-commands";
import { history } from "prosemirror-history";
@@ -35,6 +35,7 @@ import "./FormattedTextBox.scss";
import React = require("react");
import { DateField } from '../../../new_fields/DateField';
import { Utils } from '../../../Utils';
+import { toSvgDataURL } from 'html-to-image';
library.add(faEdit);
library.add(faSmile, faTextHeight);
@@ -122,13 +123,14 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
if (this.props.isOverlay) {
DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined);
}
+ toJS(console.log(this.props.Document));
document.addEventListener("paste", this.paste);
}
@computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "dummy"); }
- @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
+ @computed get dataDoc() {return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
paste = (e: ClipboardEvent) => {
if (e.clipboardData && this._editorView) {
@@ -163,7 +165,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this._applyingChange = true;
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.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/client/views/nodes/Keyframe.scss b/src/client/views/nodes/Keyframe.scss
deleted file mode 100644
index b1e8b0b65..000000000
--- a/src/client/views/nodes/Keyframe.scss
+++ /dev/null
@@ -1,94 +0,0 @@
-@import "./../globalCssVariables.scss";
-
-.bar {
- height: 100%;
- width: 5px;
- position: absolute;
-
- // pointer-events: none;
- .menubox {
- width: 200px;
- height:200px;
- top: 50%;
- 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;
- }
- .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;
- }
- .fadeLeft{
- left:0px;
- height:100%;
- position:absolute;
- pointer-events: none;
- background: linear-gradient(to left, #4d9900 10%, $light-color);
- }
-
- .fadeRight{
- right:0px;
- height:100%;
- position:absolute;
- pointer-events: none;
- background: linear-gradient(to right, #4d9900 10%, $light-color);
- }
- .divider{
- height:100%;
- width: 1px;
- position: absolute;
- background-color:black;
- cursor: col-resize;
- pointer-events:none;
- }
- .keyframe{
- height:100%;
- position:absolute;
- }
- .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;
- }
-
- .fadeIn-container, .fadeOut-container, .body-container{
- position:absolute;
- height:100%;
- background-color: rgba(0, 0, 0, 0.5);
- opacity: 0;
- }
-
-
-}
-
-
-
diff --git a/src/client/views/nodes/Keyframe.tsx b/src/client/views/nodes/Keyframe.tsx
deleted file mode 100644
index 780928e77..000000000
--- a/src/client/views/nodes/Keyframe.tsx
+++ /dev/null
@@ -1,550 +0,0 @@
-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 { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
-import { Cast, FieldValue, StrCast, 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 { number } from "prop-types";
-
-export namespace KeyframeFunc {
- export enum KeyframeType {
- 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;
- DocListCast(regions).forEach(region => {
- let neighbor = RegionData(region as Doc);
- if (currentRegion.position! > neighbor.position) {
- if (!leftMost || neighbor.position > leftMost.position) {
- leftMost = neighbor;
- }
- } else if (currentRegion.position! < neighbor.position) {
- if (!rightMost || neighbor.position < rightMost.position) {
- rightMost = neighbor;
- }
- }
- });
- if (dir === Direction.left) {
- return leftMost;
- } else if (dir === Direction.right) {
- return rightMost;
- }
- };
-
- 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!);
- keyframes!.forEach((kf) => {
- let compTime = currentBarX;
- if (ref) {
- compTime = NumCast(ref.time);
- }
- if (NumCast(kf.time) < compTime && NumCast(kf.time) >= time) {
- leftKf = kf;
- time = NumCast(kf.time);
- }
- });
- return leftKf;
- };
-
-
- 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!);
- keyframes!.forEach((kf) => {
- let compTime = currentBarX;
- if (ref) {
- compTime = NumCast(ref.time);
- }
- if (NumCast(kf.time) > compTime && NumCast(kf.time) <= NumCast(time)) {
- rightKf = kf;
- time = NumCast(kf.time);
- }
- });
- return rightKf;
- };
-
- export const defaultKeyframe = () => {
- let regiondata = new Doc(); //creating regiondata
- regiondata.duration = 200;
- regiondata.position = 0;
- regiondata.fadeIn = 20;
- regiondata.fadeOut = 20;
- regiondata.functions = new List<Doc>();
- return regiondata;
- };
-}
-
-export const RegionDataSchema = createSchema({
- position: defaultSpec("number", 0),
- duration: defaultSpec("number", 0),
- keyframes: listSpec(Doc),
- fadeIn: defaultSpec("number", 0),
- fadeOut: defaultSpec("number", 0),
- functions: listSpec(Doc)
-});
-export type RegionData = makeInterface<[typeof RegionDataSchema]>;
-export const RegionData = makeInterface(RegionDataSchema);
-
-interface IProps {
- node: Doc;
- RegionData: Doc;
- collection: Doc;
- changeCurrentBarX: (x: number) => void;
- setFlyout: (props: FlyoutProps) => any;
- transform: Transform;
-}
-
-@observer
-export class Keyframe extends React.Component<IProps> {
-
- @observable private _bar = React.createRef<HTMLDivElement>();
- @observable private _gain = 20; //default
-
- @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 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;
- }
- }
- }
-
- 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;
-
- 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
- makeKeyData = async (kfpos: number, type: KeyframeFunc.KeyframeType = KeyframeFunc.KeyframeType.default) => { //Kfpos is mouse offsetX, representing time
- 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;
- let TK: Doc = new Doc();
- TK.time = kfpos;
- TK.key = Doc.MakeCopy(this.props.node, true);
- TK.type = type;
- this.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>();
-
- this.regiondata.functions!.push(interpolationFunctions);
- let found:boolean = false;
- this.regiondata.keyframes!.forEach(compkf => {
- compkf = compkf as Doc;
- if (kfpos < NumCast(compkf.time) && !found) {
- runInAction(() => {
- this.regiondata.keyframes!.splice(doclist.indexOf(compkf as Doc), 0, TK);
- this.regiondata.keyframes!.pop();
- found = true;
- });
- return;
- }
- });
-
- let index = this.regiondata.keyframes!.indexOf(TK);
- console.log(toJS(this.regiondata.keyframes!));
-
- return TK;
- }
-
- @action
- onBarPointerDown = (e: React.PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- document.addEventListener("pointermove", this.onBarPointerMove);
- document.addEventListener("pointerup", (e: PointerEvent) => {
- document.removeEventListener("pointermove", this.onBarPointerMove);
- });
- }
-
-
- @action
- onBarPointerMove = (e: PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- 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;
- 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 {
- 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();
- }
-
- @action
- onResizeLeft = (e: React.PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- document.addEventListener("pointermove", this.onDragResizeLeft);
- document.addEventListener("pointerup", () => {
- document.removeEventListener("pointermove", this.onDragResizeLeft);
- });
- }
-
- @action
- onResizeRight = (e: React.PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- document.addEventListener("pointermove", this.onDragResizeRight);
- document.addEventListener("pointerup", () => {
- document.removeEventListener("pointermove", this.onDragResizeRight);
- });
- }
-
- @action
- onDragResizeLeft = (e: PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let bar = this._bar.current!;
- let offset = Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale);
- 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);
- 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
- 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) {
- let dif = this.regiondata.position - (leftRegion.position + leftRegion.duration);
- this.regiondata.position = leftRegion.position + leftRegion.duration;
- this.regiondata.duration += dif;
-
- } else {
- this.regiondata.duration -= offset;
- this.regiondata.position += offset;
- }
- }
-
-
- @action
- onDragResizeRight = (e: PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let bar = this._bar.current!;
- let offset = Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale);
- 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);
- 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;
- } 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 (e: React.MouseEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let bar = this._bar.current!;
- let offset = Math.round((e.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));
- 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
- }
- }
-
-
- @action
- moveKeyframe = async (e: React.MouseEvent, kf: Doc) => {
- e.preventDefault();
- e.stopPropagation();
- this.props.changeCurrentBarX(NumCast(kf.time!));
- }
-
-
- @action
- onKeyframeOver = (e: React.PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- this.props.node.backgroundColor = "#000000";
-
- }
- @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="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf as Doc); }} onContextMenu={(e: React.MouseEvent) => {
- e.preventDefault();
- e.stopPropagation();
- }}></div>
- </div>);
- }
- return (
- <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}>
- {this.createDivider()}
- </div>
- );
- }
-
- onContainerOver = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
- e.preventDefault();
- e.stopPropagation();
- let div = ref.current!;
- div.style.opacity = "1";
- }
-
- onContainerOut = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
- e.preventDefault();
- e.stopPropagation();
- let div = ref.current!;
- div.style.opacity = "0";
- }
-
-
- private _reac: (undefined | IReactionDisposer) = undefined;
- private _plotList: ([string, StrokeData] | undefined) = undefined;
- private _interpolationKeyframe: (Doc | undefined) = undefined;
- private _type: string = "";
-
- @action
- onContainerDown = (e: React.MouseEvent, kf: Doc) => {
- e.preventDefault();
- e.stopPropagation();
- let listenerCreated = false;
- let type = prompt("Type? (interpolate or path)");
- if (type) {
- if (type !== "interpolate" && type !=="path") {
- alert("Wrong type. Try again.");
- return;
- }
- 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;
- document.addEventListener("pointerup", this.onReactionListen);
- listenerCreated = true;
- }
- });
- }
-
- }
-
-
-
-
- @action
- onReactionListen = (e: PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let message = prompt("GRAPHING MODE: Enter gain");
- if (message) {
- let messageContent = parseInt(message, 10);
- if (messageContent === NaN) {
- this._gain = Infinity;
- } else {
- this._gain = messageContent;
- }
-
- }
- 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;
- this._type = "";
- document.removeEventListener("pointerup", this.onReactionListen);
- }
- }
-
-
- 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% )` }}
- onPointerDown={this.onBarPointerDown}
- onDoubleClick={this.createKeyframe}
- onContextMenu={action((e: React.MouseEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let offsetLeft = this._bar.current!.getBoundingClientRect().left - this._bar.current!.parentElement!.getBoundingClientRect().left;
- let offsetTop = this._bar.current!.getBoundingClientRect().top; //+ this._bar.current!.parentElement!.getBoundingClientRect().top;
- this.props.setFlyout({ x: offsetLeft * this.props.transform.Scale, y: offsetTop * this.props.transform.Scale, display: "block", regiondata: this.regiondata, regions: this.regions });
- })}>
- <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 => {
- 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); }}
- onContextMenu={(e) => { this.onContainerDown(e, kf); }}>
- </div>
- );
- }
- })}
-
- </div>
- </div>
- );
- }
-} \ No newline at end of file
diff --git a/src/client/views/nodes/Timeline.scss b/src/client/views/nodes/Timeline.scss
deleted file mode 100644
index 47f448adb..000000000
--- a/src/client/views/nodes/Timeline.scss
+++ /dev/null
@@ -1,170 +0,0 @@
-@import "./../globalCssVariables.scss";
-
-.minimize{
- position:relative;
- z-index: 1000;
- 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%;
- }
- }
- .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;
- position:absolute;
- height: calc(100% - 100px);
- width: calc(100% - 140px);
- overflow: hidden;
-
- .scrubberbox{
- position:absolute;
- background-color: transparent;
- height: 30px;
- width:100%;
-
- .tick{
- height:100%;
- width: 1px;
- background-color:black;
-
- }
- }
- .scrubber{
- top:30px;
- height: 100%;
- width: 2px;
- position:absolute;
- z-index: 1001;
- background-color:black;
- .scrubberhead{
- top: -30px;
- height: 30px;
- width: 30px;
- background-color:transparent;
- border-radius: 50%;
- border: 5px solid black;
- left: -15px;
- 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;
- }
-
- }
- .title-container{
- margin-top: 80px;
- margin-left: 20px;
- height: calc(100% - 100px - 30px);
- width: 100px;
- background-color:white;
- overflow: hidden;
- .datapane{
- top:0px;
- width: 100px;
- height: 75px;
- border: 1px solid $dark-color;
- background-color: $intermediate-color;
- color: white;
- position:relative;
- float:left;
- border-style:solid;
- }
- }
- .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;
- }
-} \ No newline at end of file
diff --git a/src/client/views/nodes/Timeline.tsx b/src/client/views/nodes/Timeline.tsx
deleted file mode 100644
index 923e99e63..000000000
--- a/src/client/views/nodes/Timeline.tsx
+++ /dev/null
@@ -1,530 +0,0 @@
-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 "./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
diff --git a/src/client/views/nodes/Track.scss b/src/client/views/nodes/Track.scss
deleted file mode 100644
index c8d56edf6..000000000
--- a/src/client/views/nodes/Track.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-@import "./../globalCssVariables.scss";
-
-.track-container{
-
- .track {
- .inner {
- top:0px;
- height: 75px;
- width: calc(100%);
- background-color: $light-color;
- border: 1px solid $dark-color;
- position:relative;
- }
- }
-} \ No newline at end of file
diff --git a/src/client/views/nodes/Track.tsx b/src/client/views/nodes/Track.tsx
deleted file mode 100644
index b12dabadf..000000000
--- a/src/client/views/nodes/Track.tsx
+++ /dev/null
@@ -1,266 +0,0 @@
-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 "./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 { AddComparisonParameters } from "../../northstar/model/idea/idea";
-import { CollectionSchemaBooleanCell } from "../collections/CollectionSchemaCells";
-
-interface IProps {
- node: Doc;
- currentBarX: number;
- transform: Transform;
- collection: Doc;
- changeCurrentBarX: (x: number) => void;
- setFlyout: (props: FlyoutProps) => any;
-}
-
-@observer
-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;
-
- @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>();
- }
- this.props.node.opacity = 1;
- }
-
- componentDidMount() {
- runInAction(() => {
- this._currentBarXReaction = this.currentBarXReaction();
- if (this.regions.length === 0) this.createRegion(this.props.currentBarX);
- this.props.node.hidden = false;
- });
- }
-
- 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 () => {
- 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;
- }
- }
- });
- }
- }, {fireImmediately: true});
- }
-
- @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;
- await this.timeChange(this.props.currentBarX);
- } else {
- this.props.node.hidden = true;
- }
- }, { fireImmediately: true });
- }
-
-
- @action
- timeChange = async (time: number) => {
- 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 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.
- } else if (leftkf && rightkf) {
- await this.interpolate(leftkf, rightkf, regiondata);
- }
- }
- }
-
- @action
- private applyKeys = async (kf: Doc) => {
- let kfNode = await Cast(kf.key, Doc) as Doc;
- 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 {
- this.props.node[key] = kfNode[key];
- }
- });
- }
-
-
- @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);
- return acc;
- }, []) as string[];
- }
-
- @action
- calcCurrent = async (region: Doc) => {
- 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;
- });
- 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);
- 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 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]);
- }
-
- }
-
-
- 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];
- }
- });
- }
-
- @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;
- }
-
- @action
- 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);
- }
-
- 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)) {
- regiondata.duration = rightRegion.position - regiondata.position;
- }
- this.regions.push(regiondata);
- return regiondata;
- }
-
-
- render() {
- return (
- <div className="track-container">
- <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}/>;
- })}
- </div>
- </div>
- </div>
- );
- }
-} \ No newline at end of file