From f8d4fa3d161da88e63e51c4a8940a3c44d0ae62e Mon Sep 17 00:00:00 2001 From: Hannah Chow Date: Tue, 9 Apr 2019 22:01:44 -0400 Subject: for now --- .../collectionFreeForm/CollectionFreeFormView.scss | 140 ++++++++++++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 15 ++- 2 files changed, 93 insertions(+), 62 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 81f2146e4..f9d786c9b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,92 +1,110 @@ @import "../../global_variables"; + .collectionfreeformview-measure { position: absolute; top: 0; left: 0; width: 100%; height: 100%; - } -.collectionfreeformview { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - transform-origin: left top; } -.collectionfreeformview-container { - .collectionfreeformview > .jsx-parser { + +.collectionfreeformview-ease { position: absolute; + top: 0; + left: 0; + width: 100%; height: 100%; + transform-origin: left top; + transition: transform 2s; +} + +.collectionfreeformview-none { + position: absolute; + top: 0; + left: 0; width: 100%; - } + height: 100%; + transform-origin: left top; +} + +.collectionfreeformview-container { + .collectionfreeformview>.jsx-parser { + position: absolute; + height: 100%; + width: 100%; + } - //nested freeform views - // .collectionfreeformview-container { + //nested freeform views + // .collectionfreeformview-container { // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px), // linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px); // background-size: 30px 30px; - // } + // } - box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; - border: 0px solid $light-color-secondary; - border-radius: $border-radius; - box-sizing: border-box; - position: absolute; - overflow: hidden; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.collectionfreeformview-overlay { - .collectionfreeformview > .jsx-parser { + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; + border: 0px solid $light-color-secondary; + border-radius: $border-radius; + box-sizing: border-box; position: absolute; + overflow: hidden; + top: 0; + left: 0; + width: 100%; height: 100%; - } - .formattedTextBox-cont { - background: $light-color-secondary; - } - - opacity: 0.99; - border: 0px solid transparent; - border-radius: $border-radius; - box-sizing: border-box; - position:absolute; - overflow: hidden; - top: 0; - left: 0; - width: 100%; - height: 100%; - .collectionfreeformview { +} + +.collectionfreeformview-overlay { + .collectionfreeformview>.jsx-parser { + position: absolute; + height: 100%; + } + .formattedTextBox-cont { - background:yellow; + background: $light-color-secondary; + } + + opacity: 0.99; + border: 0px solid transparent; + border-radius: $border-radius; + box-sizing: border-box; + position:absolute; + overflow: hidden; + top: 0; + left: 0; + width: 100%; + height: 100%; + + .collectionfreeformview { + .formattedTextBox-cont { + background: yellow; + } } - } } // selection border...? .border { - border-style: solid; - box-sizing: border-box; - width: 98%; - height: 98%; - border-radius: $border-radius; + border-style: solid; + box-sizing: border-box; + width: 98%; + height: 98%; + border-radius: $border-radius; } //this is an animation for the blinking cursor! @keyframes blink { - 0% { - opacity: 0; - } - 49% { - opacity: 0; - } - 50% { - opacity: 1; - } + 0% { + opacity: 0; + } + + 49% { + opacity: 0; + } + + 50% { + opacity: 1; + } } #prevCursor { - animation: blink 1s infinite; -} + animation: blink 1s infinite; +} \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1feb30db1..4562fd8a7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -206,6 +206,7 @@ export class CollectionFreeFormView extends CollectionSubView { const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY)); this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX); this.props.Document.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY); + } @action @@ -249,10 +250,16 @@ export class CollectionFreeFormView extends CollectionSubView { } focusDocument = (doc: Document) => { + this.props.Document.SetText(KeyStore.PanTransformType, "Ease"); let x = doc.GetNumber(KeyStore.X, 0) + doc.GetNumber(KeyStore.Width, 0) / 2; let y = doc.GetNumber(KeyStore.Y, 0) + doc.GetNumber(KeyStore.Height, 0) / 2; this.SetPan(x, y); this.props.focus(this.props.Document); + // if(this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease") { + // setTimeout(function(){ + // this.props.Document.SetText(KeyStore.PanTransformType, "None"); + // }.bind(this),5000); // wait 5 seconds, then reset to false + // } } getDocumentViewProps(document: Document): DocumentViewProps { @@ -311,6 +318,12 @@ export class CollectionFreeFormView extends CollectionSubView { const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0); + if (this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease") { + var freeformclass = "collectionfreeformview-ease"; + } else { + var freeformclass = "collectionfreeformview-none"; + } + return ( runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height })}> {({ measureRef }) => ( @@ -324,7 +337,7 @@ export class CollectionFreeFormView extends CollectionSubView { getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}> -
{this.backgroundView} -- cgit v1.2.3-70-g09d2 From 20e34ca5a76eb90b7be5b0ac27daf088013712b6 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 18 Apr 2019 16:32:59 -0400 Subject: left buttons --- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/collections/collectionFreeForm/MarqueeView.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c50597655..17ae20a03 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -112,7 +112,7 @@ export class CollectionFreeFormView extends CollectionSubView { var dv = DocumentManager.Instance.getDocumentView(doc); return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); }, false); - if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || (e.button === 0 && e.altKey)) && (childSelected || this.props.active())) { + if (((e.button === 0 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || (e.button === 0 && e.altKey)) && (childSelected || this.props.active())) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 8b94374fa..3163c2e72 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -70,7 +70,7 @@ export class MarqueeView extends React.Component } @action onPointerDown = (e: React.PointerEvent): void => { - if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) { + if (!e.altKey && !e.metaKey && this.props.container.props.active()) { this._downX = this._lastX = e.pageX; this._downY = this._lastY = e.pageY; this._used = false; @@ -91,12 +91,12 @@ export class MarqueeView extends React.Component this._showOnUp = false; PreviewCursor.Visible = false; } - if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey && + if (!this._used && e.buttons === 2 && !e.altKey && !e.metaKey && (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) { this._visible = true; + e.stopPropagation(); + e.preventDefault(); } - e.stopPropagation(); - e.preventDefault(); } } @@ -107,7 +107,7 @@ export class MarqueeView extends React.Component if (this._showOnUp) { PreviewCursor.Show(this.hideCursor, this._downX, this._downY); document.addEventListener("keypress", this.onKeyPress, false); - } else { + } else if (e.button === 2) { let mselect = this.marqueeSelect(); if (!e.shiftKey) { SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document); -- cgit v1.2.3-70-g09d2 From ac9111d3c06685ef295f7e15481738132eb470f8 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 18 Apr 2019 19:05:56 -0400 Subject: fixed for macbook --- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 17ae20a03..23c268622 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -112,7 +112,7 @@ export class CollectionFreeFormView extends CollectionSubView { var dv = DocumentManager.Instance.getDocumentView(doc); return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); }, false); - if (((e.button === 0 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || (e.button === 0 && e.altKey)) && (childSelected || this.props.active())) { + if ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 3163c2e72..143e7b917 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -70,7 +70,7 @@ export class MarqueeView extends React.Component } @action onPointerDown = (e: React.PointerEvent): void => { - if (!e.altKey && !e.metaKey && this.props.container.props.active()) { + if (!e.metaKey && this.props.container.props.active()) { this._downX = this._lastX = e.pageX; this._downY = this._lastY = e.pageY; this._used = false; @@ -79,6 +79,8 @@ export class MarqueeView extends React.Component document.addEventListener("pointermove", this.onPointerMove, true); document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); + if (e.button == 2 || e.altKey) + e.stopPropagation(); } } @@ -91,7 +93,7 @@ export class MarqueeView extends React.Component this._showOnUp = false; PreviewCursor.Visible = false; } - if (!this._used && e.buttons === 2 && !e.altKey && !e.metaKey && + if (!this._used && (e.buttons === 2 || e.altKey) && !e.metaKey && (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) { this._visible = true; e.stopPropagation(); @@ -107,7 +109,7 @@ export class MarqueeView extends React.Component if (this._showOnUp) { PreviewCursor.Show(this.hideCursor, this._downX, this._downY); document.addEventListener("keypress", this.onKeyPress, false); - } else if (e.button === 2) { + } else if (e.button === 2 || e.altKey) { let mselect = this.marqueeSelect(); if (!e.shiftKey) { SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document); -- cgit v1.2.3-70-g09d2 From 5ce44593a1edb4de4254f8fc7e323ae1d9f9e896 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 19 Apr 2019 00:17:02 -0400 Subject: alt key fixes --- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 8 +++++++- src/client/views/nodes/DocumentView.tsx | 8 ++------ 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 143e7b917..cb655d4e8 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -70,7 +70,7 @@ export class MarqueeView extends React.Component } @action onPointerDown = (e: React.PointerEvent): void => { - if (!e.metaKey && this.props.container.props.active()) { + if (!e.metaKey && (e.altKey || this.props.container.props.active())) { this._downX = this._lastX = e.pageX; this._downY = this._lastY = e.pageY; this._used = false; @@ -82,6 +82,8 @@ export class MarqueeView extends React.Component if (e.button == 2 || e.altKey) e.stopPropagation(); } + if (e.altKey) + e.preventDefault(); } @action @@ -100,6 +102,8 @@ export class MarqueeView extends React.Component e.preventDefault(); } } + if (e.altKey) + e.preventDefault(); } @action @@ -116,6 +120,8 @@ export class MarqueeView extends React.Component } this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]); } + if (e.altKey) + e.preventDefault(); } intersectRect(r1: { left: number, top: number, width: number, height: number }, diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3ada3252c..c62dbd59a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -178,7 +178,7 @@ export class DocumentView extends React.Component { if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - if (!this.topMost || e.buttons === 2 || e.altKey) { + if (!e.altKey && (!this.topMost || e.buttons === 2)) { this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey); } } @@ -222,12 +222,8 @@ export class DocumentView extends React.Component { } @action - public minimize = (where: number[]): void => { + public minimize = (): void => { this.props.Document.SetBoolean(KeyStore.Minimized, true); - if (where[0] !== 0 || where[1] !== 0) - this.props.Document.SetNumber(KeyStore.MinimizedX, where[0]); - if (where[1] !== 0 || where[0] !== 0) - this.props.Document.SetNumber(KeyStore.MinimizedY, where[1]); } @undoBatch -- cgit v1.2.3-70-g09d2 From 8ddec1c70c01b3d7d919908299e1168b75698dc7 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 20 Apr 2019 19:06:28 -0400 Subject: More refactoring --- .../views/collections/CollectionDockingView.tsx | 65 +++++++++++----------- src/new_fields/Doc.ts | 13 +++-- src/new_fields/List.ts | 2 +- src/new_fields/Proxy.ts | 20 +++---- src/new_fields/Types.ts | 2 - src/new_fields/URLField.ts | 12 ++-- src/new_fields/util.ts | 4 +- 7 files changed, 59 insertions(+), 59 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index e4c647635..b6c87231f 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -4,11 +4,8 @@ import 'golden-layout/src/css/goldenlayout-dark-theme.css'; import { action, observable, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import * as ReactDOM from 'react-dom'; -import { Document } from "../../../fields/Document"; -import { KeyStore } from "../../../fields/KeyStore"; import Measure from "react-measure"; -import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field"; -import { Utils, returnTrue, emptyFunction, emptyDocFunction, returnOne } from "../../../Utils"; +import { Utils, returnTrue, emptyFunction, returnOne } from "../../../Utils"; import { Server } from "../../Server"; import { undoBatch } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; @@ -17,20 +14,22 @@ import React = require("react"); import { SubCollectionViewProps } from "./CollectionSubView"; import { ServerUtils } from "../../../server/ServerUtil"; import { DragManager, DragLinksAsDocuments } from "../../util/DragManager"; -import { TextField } from "../../../fields/TextField"; -import { ListField } from "../../../fields/ListField"; -import { Transform } from '../../util/Transform' +import { Transform } from '../../util/Transform'; +import { Doc, Id, Opt, Field, FieldId } from "../../../new_fields/Doc"; +import { Cast, FieldValue } from "../../../new_fields/Types"; +import { List } from "../../../new_fields/List"; +import { DocServer } from "../../DocServer"; @observer export class CollectionDockingView extends React.Component { public static Instance: CollectionDockingView; - public static makeDocumentConfig(document: Document) { + public static makeDocumentConfig(document: Doc) { return { type: 'react-component', component: 'DocumentFrameRenderer', - title: document.Title, + title: document.title, props: { - documentId: document.Id, + documentId: document[Id], //collectionDockingView: CollectionDockingView.Instance } }; @@ -48,14 +47,14 @@ export class CollectionDockingView extends React.Component this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener. onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 })); } @action - public OpenFullScreen(document: Document) { + public OpenFullScreen(document: Doc) { let newItemStackConfig = { type: 'stack', content: [CollectionDockingView.makeDocumentConfig(document)] @@ -83,7 +82,7 @@ export class CollectionDockingView extends React.Component void = () => { if (this._containerRef.current) { reaction( - () => this.props.Document.GetText(KeyStore.Data, ""), + () => Cast(this.props.Document.data, "string", ""), () => { if (!this._goldenLayout || this._ignoreStateChange !== JSON.stringify(this._goldenLayout.toConfig())) { setTimeout(() => this.setupGoldenLayout(), 1); @@ -203,7 +202,7 @@ export class CollectionDockingView extends React.Component) => - (sourceDoc instanceof Document) && DragLinksAsDocuments(tab, x, y, sourceDoc))); + (sourceDoc instanceof Doc) && DragLinksAsDocuments(tab, x, y, sourceDoc))); } else if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) { e.stopPropagation(); @@ -213,11 +212,11 @@ export class CollectionDockingView extends React.Component) => { - if (f instanceof Document) { + if (f instanceof Doc) { DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), x, y, { handlers: { - dragComplete: action(emptyFunction), + dragComplete: emptyFunction, }, hideSource: false }); @@ -235,7 +234,7 @@ export class CollectionDockingView extends React.Component { var json = JSON.stringify(this._goldenLayout.toConfig()); - this.props.Document.SetText(KeyStore.Data, json); + this.props.Document.data = json; } itemDropped = () => { @@ -264,10 +263,9 @@ export class CollectionDockingView extends React.Component${count}
`); tab.element.append(counter); counter.DashDocId = tab.contentItem.config.props.documentId; - tab.reactionDisposer = reaction(() => [f.GetT(KeyStore.LinkedFromDocs, ListField), f.GetT(KeyStore.LinkedToDocs, ListField)], - (lists) => { - let count = (lists.length > 0 && lists[0] && lists[0]!.Data ? lists[0]!.Data.length : 0) + - (lists.length > 1 && lists[1] && lists[1]!.Data ? lists[1]!.Data.length : 0); + tab.reactionDisposer = reaction((): [List | null | undefined, List | null | undefined] => [Cast(f.linkedFromDocs, List), Cast(f.linkedToDocs, List)], + ([linkedFrom, linkedTo]) => { + let count = (linkedFrom ? linkedFrom.length : 0) + (linkedTo ? linkedTo.length : 0); counter.innerHTML = count; }); })); @@ -319,19 +317,22 @@ export class DockedFrameRenderer extends React.Component { _mainCont = React.createRef(); @observable private _panelWidth = 0; @observable private _panelHeight = 0; - @observable private _document: Opt; + @observable private _document: Opt; constructor(props: any) { super(props); - Server.GetField(this.props.documentId, action((f: Opt) => this._document = f as Document)); + DocServer.GetRefField(this.props.documentId).then(action((f: Opt) => this._document = f as Doc)); } - nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth); - nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight); + nativeWidth = () => Cast(this._document!.nativeWidth, "number", this._panelWidth); + nativeHeight = () => Cast(this._document!.nativeHeight, "number", this._panelHeight); contentScaling = () => { - let wscale = this._panelWidth / (this.nativeWidth() ? this.nativeWidth() : this._panelWidth); - if (wscale * this.nativeHeight() > this._panelHeight) - return this._panelHeight / (this.nativeHeight() ? this.nativeHeight() : this._panelHeight); + const nativeH = this.nativeHeight(); + const nativeW = this.nativeWidth(); + let wscale = this._panelWidth / nativeW; + if (wscale * nativeH > this._panelHeight) { + return this._panelHeight / nativeH; + } return wscale; } @@ -349,7 +350,7 @@ export class DockedFrameRenderer extends React.Component { return (
- { selectOnLoad={false} parentActive={returnTrue} whenActiveChanged={emptyFunction} - focus={emptyDocFunction} + focus={emptyFunction} ContainingCollectionView={undefined} />
); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index e0eb44ee9..8cbd8cf38 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -6,14 +6,15 @@ import { DocServer } from "../client/DocServer"; import { setter, getter, getField } from "./util"; import { Cast, FieldCtor } from "./Types"; +export type FieldId = string; export const HandleUpdate = Symbol("HandleUpdate"); export const Id = Symbol("Id"); export abstract class RefField { @serializable(alias("id", primitive())) - private __id: string; - readonly [Id]: string; + private __id: FieldId; + readonly [Id]: FieldId; - constructor(id?: string) { + constructor(id?: FieldId) { this.__id = id || Utils.GenerateGuid(); this[Id] = this.__id; } @@ -39,7 +40,7 @@ export const Self = Symbol("Self"); @Deserializable("doc").withFields(["id"]) export class Doc extends RefField { - constructor(id?: string, forceSave?: boolean) { + constructor(id?: FieldId, forceSave?: boolean) { super(id); const doc = new Proxy(this, { set: setter, @@ -53,7 +54,7 @@ export class Doc extends RefField { return doc; } - [key: string]: Field | null | undefined; + [key: string]: Field | FieldWaiting | undefined; @serializable(alias("fields", map(autoObject()))) @observable @@ -72,7 +73,6 @@ export namespace Doc { return new Promise(res => getField(self, key, ignoreProto, res)); } export function GetTAsync(doc: Doc, key: string, ctor: FieldCtor, ignoreProto: boolean = false): Promise { - const self = doc[Self]; return new Promise(async res => { const field = await GetAsync(doc, key, ignoreProto); return Cast(field, ctor); @@ -90,6 +90,7 @@ export namespace Doc { return undefined; } const delegate = new Doc(); + //TODO Does this need to be doc[Self]? delegate.prototype = doc; return delegate; } diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts index a1a623f83..58b252f7b 100644 --- a/src/new_fields/List.ts +++ b/src/new_fields/List.ts @@ -9,7 +9,7 @@ class ListImpl extends ObjectField { constructor() { super(); const list = new Proxy(this, { - set: function (a, b, c, d) { return setter(a, b, c, d); }, + set: setter, get: getter, deleteProperty: () => { throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); }, defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); }, diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index 3b4b2e452..6a78388c1 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -1,7 +1,8 @@ import { Deserializable } from "../client/util/SerializationHelper"; -import { RefField, Id, ObjectField } from "./Doc"; +import { RefField, Id, ObjectField, FieldWaiting } from "./Doc"; import { primitive, serializable } from "serializr"; -import { observable } from "mobx"; +import { observable, action } from "mobx"; +import { DocServer } from "../client/DocServer"; @Deserializable("proxy") export class ProxyField extends ObjectField { @@ -32,7 +33,7 @@ export class ProxyField extends ObjectField { private failed = false; private promise?: Promise; - value(callback?: ((field: T | undefined) => void)): T | undefined | null { + value(callback?: ((field: T | undefined) => void)): T | undefined | FieldWaiting { if (this.cache) { callback && callback(this.cache); return this.cache; @@ -41,13 +42,12 @@ export class ProxyField extends ObjectField { return undefined; } if (!this.promise) { - // this.promise = Server.GetField(this.fieldId).then(action((field: any) => { - // this.promise = undefined; - // this.cache = field; - // if (field === undefined) this.failed = true; - // return field; - // })); - this.promise = new Promise(r => r()); + this.promise = DocServer.GetRefField(this.fieldId).then(action((field: any) => { + this.promise = undefined; + this.cache = field; + if (field === undefined) this.failed = true; + return field; + })); } callback && this.promise.then(callback); return null; diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 6ffb3e02f..0fbd8984c 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -50,8 +50,6 @@ export function Cast>(field: Field | null | undefined } else if (field instanceof (ctor as any)) { return field as ToType; } - } else { - return defaultVal; } return defaultVal; } diff --git a/src/new_fields/URLField.ts b/src/new_fields/URLField.ts index d27a2b692..e456a7d16 100644 --- a/src/new_fields/URLField.ts +++ b/src/new_fields/URLField.ts @@ -1,16 +1,16 @@ import { Deserializable } from "../client/util/SerializationHelper"; -import { serializable } from "serializr"; +import { serializable, custom } from "serializr"; import { ObjectField } from "./Doc"; function url() { - return { - serializer: function (value: URL) { + return custom( + function (value: URL) { return value.href; }, - deserializer: function (jsonValue: string, done: (err: any, val: any) => void) { - done(undefined, new URL(jsonValue)); + function (jsonValue: string) { + return new URL(jsonValue); } - }; + ); } @Deserializable("url") diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 0f08ecf03..3806044bd 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -22,6 +22,7 @@ export function setter(target: any, prop: string | symbol | number, value: any, value = new ProxyField(value); } if (value instanceof ObjectField) { + //TODO Instead of target, maybe use target[Self] if (value[Parent] && value[Parent] !== target) { throw new Error("Can't put the same object in multiple documents at the same time"); } @@ -51,7 +52,7 @@ export function getter(target: any, prop: string | symbol | number, receiver: an if (SerializationHelper.IsSerializing()) { return target[prop]; } - return getField(target, prop, receiver); + return getField(target, prop); } export function getField(target: any, prop: string | number, ignoreProto: boolean = false, callback?: (field: Field | undefined) => void): any { @@ -69,5 +70,4 @@ export function getField(target: any, prop: string | number, ignoreProto: boolea } callback && callback(field); return field; - } -- cgit v1.2.3-70-g09d2 From 5a4be44ac6b9fdc10a5464623a02891bc2cc4444 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 20 Apr 2019 19:23:27 -0400 Subject: fixed input text scaling --- src/client/views/MainOverlayTextBox.tsx | 27 +++++++++------------- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 - src/client/views/nodes/FormattedTextBox.tsx | 6 +++-- 3 files changed, 15 insertions(+), 19 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index a6c7eabf7..af74efc9d 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -21,8 +21,8 @@ export class MainOverlayTextBox extends React.Component public static Instance: MainOverlayTextBox; @observable public TextDoc?: Document = undefined; public TextScroll: number = 0; - private _textRect: any; - private _textXf: Transform = Transform.Identity(); + @observable _textRect: any; + @observable _textXf: () => Transform = () => Transform.Identity(); private _textFieldKey: Key = KeyStore.Data; private _textColor: string | null = null; private _textTargetDiv: HTMLDivElement | undefined; @@ -35,14 +35,14 @@ export class MainOverlayTextBox extends React.Component } @action - SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: Transform) { + SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: () => Transform) { if (this._textTargetDiv) { this._textTargetDiv.style.color = this._textColor; } this.TextDoc = textDoc; this._textFieldKey = textFieldKey!; - this._textXf = tx ? tx : Transform.Identity(); + this._textXf = tx ? tx : () => Transform.Identity(); this._textTargetDiv = div; if (div) { this._textColor = div.style.color; @@ -89,22 +89,17 @@ export class MainOverlayTextBox extends React.Component document.removeEventListener('pointerup', this.textBoxUp); } - textXf = () => this._textXf; - render() { if (this.TextDoc) { - let x: number = this._textRect.x; - let y: number = this._textRect.y; - let w: number = this._textRect.width; - let h: number = this._textRect.height; - let t = this._textXf.transformPoint(0, 0); - let s = this._textXf.transformPoint(1, 0); - s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1])); - return
-
+ let toScreenXf = this._textXf().inverse(); + let pt = toScreenXf.transformPoint(0, 0); + let s = 1 / this._textXf().Scale; + return
+
+ ScreenToLocalTransform={this._textXf} focus={emptyDocFunction} />
; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 945c01059..9730fc27b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -204,7 +204,6 @@ export class CollectionFreeFormView extends CollectionSubView { @action setPan(panX: number, panY: number) { - MainOverlayTextBox.Instance.SetTextDoc(); var scale = this.getLocalTransform().inverse().Scale; const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX)); const newPanY = Math.min((1 - 1 / scale) * this.nativeHeight, Math.max(0, panY)); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index ae05c2dad..29ed2da13 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -115,7 +115,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte ); } else { this._proxyReactionDisposer = reaction(() => this.props.isSelected(), - () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform())); + () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform)); } @@ -186,7 +186,9 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte onFocused = (e: React.FocusEvent): void => { if (!this.props.isOverlay) { - MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform()); + if (MainOverlayTextBox.Instance.TextDoc != this.props.Document) { + MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform); + } } else { if (this._ref.current) { this._ref.current.scrollTop = MainOverlayTextBox.Instance.TextScroll; -- cgit v1.2.3-70-g09d2 From b63bcb791013766d5d16e4f38964499268f904c4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 21 Apr 2019 00:03:52 -0400 Subject: fixed a bunch of issues related to moving documents with different zoom bases. --- src/client/documents/Documents.ts | 2 + src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainOverlayTextBox.tsx | 4 +- .../views/collections/CollectionBaseView.tsx | 78 ++++++++++------------ src/client/views/collections/CollectionSubView.tsx | 38 +++-------- .../collectionFreeForm/CollectionFreeFormView.tsx | 7 +- .../collections/collectionFreeForm/MarqueeView.tsx | 10 +-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 19 +++--- src/fields/KeyStore.ts | 4 +- 10 files changed, 72 insertions(+), 94 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b0bb74d89..0e6661819 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -54,6 +54,7 @@ export interface DocumentOptions { viewType?: number; backgroundColor?: string; copyDraggedItems?: boolean; + documentText?: string; } export namespace Documents { @@ -97,6 +98,7 @@ export namespace Documents { if (options.nativeHeight !== undefined) { doc.SetNumber(KeyStore.NativeHeight, options.nativeHeight); } if (options.title !== undefined) { doc.SetText(KeyStore.Title, options.title); } if (options.page !== undefined) { doc.SetNumber(KeyStore.Page, options.page); } + if (options.documentText !== undefined) { doc.SetText(KeyStore.DocumentText, options.documentText); } if (options.scale !== undefined) { doc.SetNumber(KeyStore.Scale, options.scale); } if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); } if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 32cf985ce..2af6cb353 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -246,7 +246,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> selViews.map(selDoc => { let minDoc = selDoc.props.Document.Get(KeyStore.MinimizedDoc); if (minDoc instanceof Document) { - let zoom = selDoc.props.Document.GetNumber(KeyStore.Zoom, 1); + let zoom = selDoc.props.Document.GetNumber(KeyStore.ZoomBasis, 1); let where = (selDoc.props.ScreenToLocalTransform()).scale(selDoc.props.ContentScaling()).scale(1 / zoom). transformPoint(this._minimizedX - 12, this._minimizedY - 12); minDoc.SetNumber(KeyStore.X, where[0] + selDoc.props.Document.GetNumber(KeyStore.X, 0)); diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index af74efc9d..2b72b09c6 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -71,9 +71,7 @@ export class MainOverlayTextBox extends React.Component document.removeEventListener("pointermove", this.textBoxMove); document.removeEventListener('pointerup', this.textBoxUp); let dragData = new DragManager.DocumentDragData([this.TextDoc!]); - const [left, top] = this._textXf - .inverse() - .transformPoint(0, 0); + const [left, top] = this._textXf.inverse().transformPoint(0, 0); dragData.xOffset = e.clientX - left; dragData.yOffset = e.clientY - top; DragManager.StartDocumentDrag([this._textTargetDiv!], dragData, e.clientX, e.clientY, { diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 0c1cd7b8f..eec01bb3f 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -8,6 +8,7 @@ import { ListField } from '../../../fields/ListField'; import { NumberField } from '../../../fields/NumberField'; import { ContextMenu } from '../ContextMenu'; import { FieldViewProps } from '../nodes/FieldView'; +import { TextField } from '../../../fields/TextField'; export enum CollectionViewType { Invalid, @@ -87,57 +88,50 @@ export class CollectionBaseView extends React.Component { @action.bound addDocument(doc: Document, allowDuplicates: boolean = false): boolean { - let props = this.props; - var curPage = props.Document.GetNumber(KeyStore.CurPage, -1); + var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); doc.SetOnPrototype(KeyStore.Page, new NumberField(curPage)); if (curPage >= 0) { - doc.SetOnPrototype(KeyStore.AnnotationOn, props.Document); + doc.SetOnPrototype(KeyStore.AnnotationOn, this.props.Document); } - if (props.Document.Get(props.fieldKey) instanceof Field) { - //TODO This won't create the field if it doesn't already exist - const value = props.Document.GetData(props.fieldKey, ListField, new Array()); - if (!this.createsCycle(doc, props.Document)) { + if (this.props.Document.Get(this.props.fieldKey) instanceof Field) { + const value = this.props.Document.GetList(this.props.fieldKey, [] as Document[]); + if (!this.createsCycle(doc, this.props.Document)) { if (!value.some(v => v.Id === doc.Id) || allowDuplicates) { value.push(doc); + doc.SetNumber(KeyStore.ZoomBasis, this.props.Document.GetNumber(KeyStore.Scale, 1)); } return true; } - else { - return false; - } - } else { - let proto = props.Document.GetPrototype(); - if (!proto || proto === FieldWaiting || !this.createsCycle(proto, doc)) { - const field = new ListField([doc]); - // const script = CompileScript(` - // if(added) { - // console.log("added " + field.Title + " " + doc.Title); - // } else { - // console.log("removed " + field.Title + " " + doc.Title); - // } - // `, { - // addReturn: false, - // params: { - // field: Document.name, - // added: "boolean" - // }, - // capturedVariables: { - // doc: this.props.Document - // } - // }); - // if (script.compiled) { - // field.addScript(new ScriptField(script)); - // } - props.Document.SetOnPrototype(props.fieldKey, field); - } - else { - return false; - } - } - if (true || this.isAnnotationOverlay) { - doc.SetNumber(KeyStore.Zoom, this.props.Document.GetNumber(KeyStore.Scale, 1)); } - return true; + // bcz: What is this code trying to do? + // else { + // let proto = props.Document.GetPrototype(); + // if (!proto || proto === FieldWaiting || !this.createsCycle(proto, doc)) { + // const field = new ListField([doc]); + // // const script = CompileScript(` + // // if(added) { + // // console.log("added " + field.Title + " " + doc.Title); + // // } else { + // // console.log("removed " + field.Title + " " + doc.Title); + // // } + // // `, { + // // addReturn: false, + // // params: { + // // field: Document.name, + // // added: "boolean" + // // }, + // // capturedVariables: { + // // doc: this.props.Document + // // } + // // }); + // // if (script.compiled) { + // // field.addScript(new ScriptField(script)); + // // } + // props.Document.SetOnPrototype(props.fieldKey, field); + // return true; + // } + // } + return false; } @action.bound diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5c3b2e586..ead559bd9 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -159,10 +159,7 @@ export class CollectionSubView extends React.Component { e.preventDefault(); if (html && html.indexOf(" { let type = item.type; if (item.kind === "file") { let file = item.getAsFile(); - let formData = new FormData(); - - if (file) { - formData.append('file', file); - } let dropFileName = file ? file.name : "-empty-"; + let formData = new FormData(); + if (file) formData.append('file', file); - let prom = fetch(upload, { + promises.push(fetch(upload, { method: 'POST', body: formData - }).then(async (res: Response) => { - (await res.json()).map(action((file: any) => { - let path = window.location.origin + file; - let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName }); - - docPromise.then(action((doc?: Document) => { - let docs = this.props.Document.GetT(KeyStore.Data, ListField); - if (docs !== FieldWaiting) { - if (!docs) { - docs = new ListField(); - this.props.Document.Set(KeyStore.Data, docs); - } - if (doc) { - docs.Data.push(doc); - } - } - })); - })); - }); - promises.push(prom); + }).then(async (res: Response) => + (await res.json()).map(action((file: any) => + this.getDocumentFromType(type, window.location.origin + file, { ...options, nativeWidth: 600, width: 300, title: dropFileName }). + then(doc => doc && this.props.addDocument(doc, false)))))); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9730fc27b..83b7f9be4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -49,7 +49,6 @@ export class CollectionFreeFormView extends CollectionSubView { this.addDocument(newBox, false); } private addDocument = (newBox: Document, allowDuplicates: boolean) => { - newBox.SetNumber(KeyStore.Zoom, this.props.Document.GetNumber(KeyStore.Scale, 1)); return this.props.addDocument(this.bringToFront(newBox), false); } private selectDocuments = (docs: Document[]) => { @@ -72,9 +71,13 @@ export class CollectionFreeFormView extends CollectionSubView { @action drop = (e: Event, de: DragManager.DropEvent) => { if (super.drop(e, de) && de.data instanceof DragManager.DocumentDragData) { - const [x, y] = this.getTransform().transformPoint(de.x - de.data.xOffset, de.y - de.data.yOffset); if (de.data.droppedDocuments.length) { let dragDoc = de.data.droppedDocuments[0]; + let zoom = dragDoc.GetNumber(KeyStore.ZoomBasis, 1); + let [xp, yp] = this.getTransform().transformPoint(de.x, de.y); + let x = xp - de.data.xOffset / zoom; + let y = yp - de.data.yOffset / zoom; + let dropX = dragDoc.GetNumber(KeyStore.X, 0); let dropY = dragDoc.GetNumber(KeyStore.Y, 0); de.data.droppedDocuments.map(d => { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index bf918beba..318adbe85 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -152,20 +152,20 @@ export class MarqueeView extends React.Component }); let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined; - //setTimeout(() => { + let zoomBasis = this.props.container.props.Document.GetNumber(KeyStore.Scale, 1); let newCollection = Documents.FreeformDocument(selected, { x: bounds.left, y: bounds.top, panx: 0, pany: 0, - width: bounds.width, - height: bounds.height, + scale: zoomBasis, + width: bounds.width * zoomBasis, + height: bounds.height * zoomBasis, ink: inkData ? this.marqueeInkSelect(inkData) : undefined, title: "a nested collection" }); this.props.addDocument(newCollection, false); this.marqueeInkDelete(inkData); - // }, 100); this.cleanupInteractions(); SelectionManager.DeselectAll(); } @@ -208,7 +208,7 @@ export class MarqueeView extends React.Component let selRect = this.Bounds; let selection: Document[] = []; this.props.activeDocuments().map(doc => { - var z = doc.GetNumber(KeyStore.Zoom, 1); + var z = doc.GetNumber(KeyStore.ZoomBasis, 1); var x = doc.GetNumber(KeyStore.X, 0); var y = doc.GetNumber(KeyStore.Y, 0); var w = doc.Width() / z; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 01a9f26bf..12e5bdf1f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -20,7 +20,7 @@ export class CollectionFreeFormDocumentView extends React.Component { } e.stopPropagation(); } else { - if (this.active) { + let maxdoc = this.props.Document.GetT(KeyStore.MaximizedDoc, Document); + if (this.active || + maxdoc instanceof Document // bcz: need a better way of allowing a document to handle pointer events when its not active (ie. be a top-level widget) + ) { e.stopPropagation(); document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); @@ -149,11 +152,12 @@ export class DocumentView extends React.Component { startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) { if (this._mainCont.current) { - const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); + const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); let dragData = new DragManager.DocumentDragData([this.props.Document]); + const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); dragData.aliasOnDrop = dropAliasOfDraggedDoc; - dragData.xOffset = x - left; - dragData.yOffset = y - top; + dragData.xOffset = xoff; + dragData.yOffset = yoff; dragData.moveDocument = this.props.moveDocument; DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { handlers: { @@ -185,7 +189,7 @@ export class DocumentView extends React.Component { if (!SelectionManager.IsSelected(this) && e.button !== 2 && Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { this.props.Document.GetTAsync(KeyStore.MaximizedDoc, Document).then(maxdoc => { - if (maxdoc instanceof Document) { + if (maxdoc instanceof Document) { // bcz: need a better way to associate behaviors with click events on widget-documents this.props.addDocument && this.props.addDocument(maxdoc, false); this.toggleIcon(); } else @@ -202,9 +206,8 @@ export class DocumentView extends React.Component { } fieldsClicked = (e: React.MouseEvent): void => { - if (this.props.addDocument) { - this.props.addDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false); - } + let kvp = Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }); + CollectionDockingView.Instance.AddRightSplit(kvp); } fullScreenClicked = (e: React.MouseEvent): void => { CollectionDockingView.Instance.OpenFullScreen((this.props.Document.GetPrototype() as Document).MakeDelegate()); diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index a347f8bcf..0a96beb50 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -15,7 +15,7 @@ export namespace KeyStore { export const Width = new Key("Width"); export const Height = new Key("Height"); export const ZIndex = new Key("ZIndex"); - export const Zoom = new Key("Zoom"); + export const ZoomBasis = new Key("ZoomBasis"); export const Data = new Key("Data"); export const Annotations = new Key("Annotations"); export const ViewType = new Key("ViewType"); @@ -51,7 +51,7 @@ export namespace KeyStore { export const CopyDraggedItems = new Key("CopyDraggedItems"); export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight, - Width, Height, ZIndex, Zoom, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys, + Width, Height, ZIndex, ZoomBasis, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys, LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs, LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection, Archives, Workspaces, IsMinimized, MinimizedDoc, MaximizedDoc, CopyDraggedItems -- cgit v1.2.3-70-g09d2 From 3556aae6d063d8b654509330e70bc67606f16613 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 21 Apr 2019 00:39:09 -0400 Subject: More changes --- .../views/collections/CollectionDockingView.tsx | 38 +++++++++---------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 43 +++++++++++++--------- src/new_fields/Doc.ts | 9 ++--- src/new_fields/Proxy.ts | 2 +- src/new_fields/Types.ts | 22 ++++++++--- 5 files changed, 65 insertions(+), 49 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index b6c87231f..7b204cbdc 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -250,28 +250,26 @@ export class CollectionDockingView extends React.Component { if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") { - Server.GetField(tab.contentItem.config.props.documentId, action((f: Opt) => { - if (f !== undefined && f instanceof Document) { - f.GetTAsync(KeyStore.Title, TextField, (tfield) => { - if (tfield !== undefined) { - tab.titleElement[0].textContent = f.Title; - } - }); - f.GetTAsync(KeyStore.LinkedFromDocs, ListField).then(lf => - f.GetTAsync(KeyStore.LinkedToDocs, ListField).then(lt => { - let count = (lf ? lf.Data.length : 0) + (lt ? lt.Data.length : 0); - let counter: any = this.htmlToElement(`
${count}
`); - tab.element.append(counter); - counter.DashDocId = tab.contentItem.config.props.documentId; - tab.reactionDisposer = reaction((): [List | null | undefined, List | null | undefined] => [Cast(f.linkedFromDocs, List), Cast(f.linkedToDocs, List)], - ([linkedFrom, linkedTo]) => { - let count = (linkedFrom ? linkedFrom.length : 0) + (linkedTo ? linkedTo.length : 0); - counter.innerHTML = count; - }); - })); + DocServer.GetRefField(tab.contentItem.config.props.documentId).then(async f => { + if (f instanceof Doc) { + const tfield = await Cast(f.title, "string"); + if (tfield !== undefined) { + tab.titleElement[0].textContent = f.Title; + } + const lf = await Cast(f.linkedFromDocs, List); + const lt = await Cast(f.linkedToDocs, List); + let count = (lf ? lf.length : 0) + (lt ? lt.length : 0); + let counter: any = this.htmlToElement(`
${count}
`); + tab.element.append(counter); + counter.DashDocId = tab.contentItem.config.props.documentId; + tab.reactionDisposer = reaction((): [List | null | undefined, List | null | undefined] => [lf, lt], + ([linkedFrom, linkedTo]) => { + let count = (linkedFrom ? linkedFrom.length : 0) + (linkedTo ? linkedTo.length : 0); + counter.innerHTML = count; + }); tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId; } - })); + }); } tab.closeElement.off('click') //unbind the current click handler .click(function () { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 1d42b3899..27fd25b5c 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,18 +1,27 @@ import { computed, trace } from "mobx"; import { observer } from "mobx-react"; -import { KeyStore } from "../../../fields/KeyStore"; -import { NumberField } from "../../../fields/NumberField"; import { Transform } from "../../util/Transform"; -import { DocumentView, DocumentViewProps } from "./DocumentView"; +import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"; import "./DocumentView.scss"; import React = require("react"); import { OmitKeys } from "../../../Utils"; +import { DocComponent } from "../DocComponent"; +import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { FieldValue } from "../../../new_fields/Types"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { } +const schema = createSchema({ + zoom: "number", + zIndex: "number" +}); + +type FreeformDocument = makeInterface<[typeof schema, typeof positionSchema]>; +const FreeformDocument = makeInterface([schema, positionSchema]); + @observer -export class CollectionFreeFormDocumentView extends React.Component { +export class CollectionFreeFormDocumentView extends DocComponent(FreeformDocument) { private _mainCont = React.createRef(); @computed @@ -20,36 +29,36 @@ export class CollectionFreeFormDocumentView extends React.Component this.props.ScreenToLocalTransform() diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 8cbd8cf38..10e8fe7ec 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -32,9 +32,8 @@ export class ObjectField { export type Field = number | string | boolean | ObjectField | RefField; export type Opt = T | undefined; -export type FieldWaiting = null; -export const FieldWaiting: FieldWaiting = null; -export type FieldValue = Opt | FieldWaiting; +export type FieldWaiting = Promise; +export type FieldValue = Opt | FieldWaiting; export const Self = Symbol("Self"); @@ -58,7 +57,7 @@ export class Doc extends RefField { @serializable(alias("fields", map(autoObject()))) @observable - private __fields: { [key: string]: Field | null | undefined } = {}; + private __fields: { [key: string]: Field | FieldWaiting | undefined } = {}; private [Update] = (diff: any) => { DocServer.UpdateField(this[Id], diff); @@ -78,7 +77,7 @@ export namespace Doc { return Cast(field, ctor); }); } - export function Get(doc: Doc, key: string, ignoreProto: boolean = false): Field | null | undefined { + export function Get(doc: Doc, key: string, ignoreProto: boolean = false): FieldValue { const self = doc[Self]; return getField(self, key, ignoreProto); } diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index 6a78388c1..2aa78731e 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -50,6 +50,6 @@ export class ProxyField extends ObjectField { })); } callback && this.promise.then(callback); - return null; + return this.promise; } } diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 0fbd8984c..0392dc2fb 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -1,4 +1,4 @@ -import { Field, Opt } from "./Doc"; +import { Field, Opt, FieldWaiting, FieldValue } from "./Doc"; import { List } from "./List"; export type ToType = @@ -6,7 +6,7 @@ export type ToType = T extends "number" ? number : T extends "boolean" ? boolean : T extends ListSpec ? List : - T extends { new(...args: any[]): infer R } ? R : never; + T extends { new(...args: any[]): infer R } ? (R | Promise) : never; export type ToConstructor = T extends string ? "string" : @@ -35,10 +35,13 @@ export interface Interface { export type FieldCtor = T extends List ? ListSpec : ToConstructor; -export function Cast>(field: Field | null | undefined, ctor: T): ToType | null | undefined; -export function Cast>(field: Field | null | undefined, ctor: T, defaultVal: ToType): ToType; -export function Cast>(field: Field | null | undefined, ctor: T, defaultVal?: ToType): ToType | null | undefined { - if (field !== undefined && field !== null) { +export function Cast>(field: Field | FieldWaiting | undefined, ctor: T): FieldValue>; +export function Cast>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal: ToType): ToType; +export function Cast>(field: Field | FieldWaiting | undefined, ctor: T, defaultVal?: ToType): FieldValue> | undefined { + if (field instanceof Promise) { + return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) : defaultVal; + } + if (field !== undefined && !(field instanceof Promise)) { if (typeof ctor === "string") { if (typeof field === ctor) { return field as ToType; @@ -59,3 +62,10 @@ export function FieldValue(field: Opt | Promise>): Op export function FieldValue(field: Opt | Promise>, defaultValue?: T): Opt { return field instanceof Promise ? defaultValue : field; } + +export interface PromiseLike { + then(callback: (field: Opt | PromiseLike) => void): void; +} +export function PromiseValue(field: FieldValue): PromiseLike> { + return field instanceof Promise ? field : { then(cb: ((field: Opt) => void)) { return cb(field); } }; +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From ab8b4ffd7f3b89600a71d3167490c40a59be433e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 21 Apr 2019 01:46:02 -0400 Subject: More changes/fixes --- src/client/views/collections/CollectionSubView.tsx | 354 +++++++++++---------- .../collectionFreeForm/CollectionFreeFormView.tsx | 21 +- src/client/views/nodes/FieldView.tsx | 8 +- src/new_fields/Schema.ts | 15 +- src/new_fields/Types.ts | 2 +- 5 files changed, 210 insertions(+), 190 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5c3b2e586..3add288fd 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -18,11 +18,13 @@ import * as rp from 'request-promise'; import { CollectionView } from "./CollectionView"; import { CollectionPDFView } from "./CollectionPDFView"; import { CollectionVideoView } from "./CollectionVideoView"; +import { Doc } from "../../../new_fields/Doc"; +import { DocComponent } from "../DocComponent"; export interface CollectionViewProps extends FieldViewProps { - addDocument: (document: Document, allowDuplicates?: boolean) => boolean; - removeDocument: (document: Document) => boolean; - moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean; + addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; + removeDocument: (document: Doc) => boolean; + moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; PanelWidth: () => number; PanelHeight: () => number; } @@ -33,198 +35,202 @@ export interface SubCollectionViewProps extends CollectionViewProps { export type CursorEntry = TupleField<[string, string], [number, number]>; -export class CollectionSubView extends React.Component { - private dropDisposer?: DragManager.DragDropDisposer; - protected createDropTarget = (ele: HTMLDivElement) => { - if (this.dropDisposer) { - this.dropDisposer(); +export function CollectionSubView(schemaCtor: (doc: Doc) => T) { + class CollectionSubView extends DocComponent(schemaCtor) { + private dropDisposer?: DragManager.DragDropDisposer; + protected createDropTarget = (ele: HTMLDivElement) => { + if (this.dropDisposer) { + this.dropDisposer(); + } + if (ele) { + this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + } } - if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + protected CreateDropTarget(ele: HTMLDivElement) { + this.createDropTarget(ele); } - } - protected CreateDropTarget(ele: HTMLDivElement) { - this.createDropTarget(ele); - } - @action - protected setCursorPosition(position: [number, number]) { - let ind; - let doc = this.props.Document; - let id = CurrentUserUtils.id; - let email = CurrentUserUtils.email; - if (id && email) { - let textInfo: [string, string] = [id, email]; - doc.GetTAsync(KeyStore.Prototype, Document).then(proto => { - if (!proto) { - return; - } - proto.GetOrCreateAsync>(KeyStore.Cursors, ListField, action((field: ListField) => { - let cursors = field.Data; - if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.Data[0][0] === id)) > -1) { - cursors[ind].Data[1] = position; - } else { - let entry = new TupleField<[string, string], [number, number]>([textInfo, position]); - cursors.push(entry); + @action + protected setCursorPosition(position: [number, number]) { + let ind; + let doc = this.props.Document; + let id = CurrentUserUtils.id; + let email = CurrentUserUtils.email; + if (id && email) { + let textInfo: [string, string] = [id, email]; + doc.GetTAsync(KeyStore.Prototype, Document).then(proto => { + if (!proto) { + return; } - })); - }); + proto.GetOrCreateAsync>(KeyStore.Cursors, ListField, action((field: ListField) => { + let cursors = field.Data; + if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.Data[0][0] === id)) > -1) { + cursors[ind].Data[1] = position; + } else { + let entry = new TupleField<[string, string], [number, number]>([textInfo, position]); + cursors.push(entry); + } + })); + }); + } } - } - @undoBatch - @action - protected drop(e: Event, de: DragManager.DropEvent): boolean { - if (de.data instanceof DragManager.DocumentDragData) { - if (de.data.aliasOnDrop || de.data.copyOnDrop) { - [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key => - de.data.draggedDocuments.map((draggedDocument: Document, i: number) => - draggedDocument.GetTAsync(key, NumberField, (f: Opt) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null))); - } - let added = false; - if (de.data.aliasOnDrop || de.data.copyOnDrop) { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); - } else if (de.data.moveDocument) { - const move = de.data.moveDocument; - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = move(d, this.props.Document, this.props.addDocument); - return moved || added; - }, false); - } else { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); + @undoBatch + @action + protected drop(e: Event, de: DragManager.DropEvent): boolean { + if (de.data instanceof DragManager.DocumentDragData) { + if (de.data.aliasOnDrop || de.data.copyOnDrop) { + [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key => + de.data.draggedDocuments.map((draggedDocument: Document, i: number) => + draggedDocument.GetTAsync(key, NumberField, (f: Opt) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null))); + } + let added = false; + if (de.data.aliasOnDrop || de.data.copyOnDrop) { + added = de.data.droppedDocuments.reduce((added: boolean, d) => { + let moved = this.props.addDocument(d); + return moved || added; + }, false); + } else if (de.data.moveDocument) { + const move = de.data.moveDocument; + added = de.data.droppedDocuments.reduce((added: boolean, d) => { + let moved = move(d, this.props.Document, this.props.addDocument); + return moved || added; + }, false); + } else { + added = de.data.droppedDocuments.reduce((added: boolean, d) => { + let moved = this.props.addDocument(d); + return moved || added; + }, false); + } + e.stopPropagation(); + return added; } - e.stopPropagation(); - return added; + return false; } - return false; - } - protected async getDocumentFromType(type: string, path: string, options: DocumentOptions): Promise> { - let ctor: ((path: string, options: DocumentOptions) => (Document | Promise)) | undefined = undefined; - if (type.indexOf("image") !== -1) { - ctor = Documents.ImageDocument; - } - if (type.indexOf("video") !== -1) { - ctor = Documents.VideoDocument; - } - if (type.indexOf("audio") !== -1) { - ctor = Documents.AudioDocument; - } - if (type.indexOf("pdf") !== -1) { - ctor = Documents.PdfDocument; - options.nativeWidth = 1200; - } - if (type.indexOf("excel") !== -1) { - ctor = Documents.DBDocument; - options.copyDraggedItems = true; - } - if (type.indexOf("html") !== -1) { - if (path.includes('localhost')) { - let s = path.split('/'); - let id = s[s.length - 1]; - Server.GetField(id).then(field => { - if (field instanceof Document) { - let alias = field.CreateAlias(); - alias.SetNumber(KeyStore.X, options.x || 0); - alias.SetNumber(KeyStore.Y, options.y || 0); - alias.SetNumber(KeyStore.Width, options.width || 300); - alias.SetNumber(KeyStore.Height, options.height || options.width || 300); - this.props.addDocument(alias, false); - } - }); - return undefined; + protected async getDocumentFromType(type: string, path: string, options: DocumentOptions): Promise> { + let ctor: ((path: string, options: DocumentOptions) => (Document | Promise)) | undefined = undefined; + if (type.indexOf("image") !== -1) { + ctor = Documents.ImageDocument; + } + if (type.indexOf("video") !== -1) { + ctor = Documents.VideoDocument; + } + if (type.indexOf("audio") !== -1) { + ctor = Documents.AudioDocument; + } + if (type.indexOf("pdf") !== -1) { + ctor = Documents.PdfDocument; + options.nativeWidth = 1200; + } + if (type.indexOf("excel") !== -1) { + ctor = Documents.DBDocument; + options.copyDraggedItems = true; } - ctor = Documents.WebDocument; - options = { height: options.width, ...options, title: path }; + if (type.indexOf("html") !== -1) { + if (path.includes('localhost')) { + let s = path.split('/'); + let id = s[s.length - 1]; + Server.GetField(id).then(field => { + if (field instanceof Document) { + let alias = field.CreateAlias(); + alias.SetNumber(KeyStore.X, options.x || 0); + alias.SetNumber(KeyStore.Y, options.y || 0); + alias.SetNumber(KeyStore.Width, options.width || 300); + alias.SetNumber(KeyStore.Height, options.height || options.width || 300); + this.props.addDocument(alias, false); + } + }); + return undefined; + } + ctor = Documents.WebDocument; + options = { height: options.width, ...options, title: path }; + } + return ctor ? ctor(path, options) : undefined; } - return ctor ? ctor(path, options) : undefined; - } - @undoBatch - @action - protected onDrop(e: React.DragEvent, options: DocumentOptions): void { - let html = e.dataTransfer.getData("text/html"); - let text = e.dataTransfer.getData("text/plain"); + @undoBatch + @action + protected onDrop(e: React.DragEvent, options: DocumentOptions): void { + let html = e.dataTransfer.getData("text/html"); + let text = e.dataTransfer.getData("text/plain"); - if (text && text.startsWith("[] = []; - // tslint:disable-next-line:prefer-for-of - for (let i = 0; i < e.dataTransfer.items.length; i++) { - const upload = window.location.origin + RouteStore.upload; - let item = e.dataTransfer.items[i]; - if (item.kind === "string" && item.type.indexOf("uri") !== -1) { - let str: string; - let prom = new Promise(resolve => e.dataTransfer.items[i].getAsString(resolve)) - .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s))))) - .then(result => { - let type = result.headers["content-type"]; - if (type) { - this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }) - .then(doc => doc && this.props.addDocument(doc, false)); - } - }); - promises.push(prom); + if (html && html.indexOf("[] = []; + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < e.dataTransfer.items.length; i++) { + const upload = window.location.origin + RouteStore.upload; + let item = e.dataTransfer.items[i]; + if (item.kind === "string" && item.type.indexOf("uri") !== -1) { + let str: string; + let prom = new Promise(resolve => e.dataTransfer.items[i].getAsString(resolve)) + .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s))))) + .then(result => { + let type = result.headers["content-type"]; + if (type) { + this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }) + .then(doc => doc && this.props.addDocument(doc, false)); + } + }); + promises.push(prom); } - let dropFileName = file ? file.name : "-empty-"; - - let prom = fetch(upload, { - method: 'POST', - body: formData - }).then(async (res: Response) => { - (await res.json()).map(action((file: any) => { - let path = window.location.origin + file; - let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName }); - - docPromise.then(action((doc?: Document) => { - let docs = this.props.Document.GetT(KeyStore.Data, ListField); - if (docs !== FieldWaiting) { - if (!docs) { - docs = new ListField(); - this.props.Document.Set(KeyStore.Data, docs); - } - if (doc) { - docs.Data.push(doc); + let type = item.type; + if (item.kind === "file") { + let file = item.getAsFile(); + let formData = new FormData(); + + if (file) { + formData.append('file', file); + } + let dropFileName = file ? file.name : "-empty-"; + + let prom = fetch(upload, { + method: 'POST', + body: formData + }).then(async (res: Response) => { + (await res.json()).map(action((file: any) => { + let path = window.location.origin + file; + let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName }); + + docPromise.then(action((doc?: Document) => { + let docs = this.props.Document.GetT(KeyStore.Data, ListField); + if (docs !== FieldWaiting) { + if (!docs) { + docs = new ListField(); + this.props.Document.Set(KeyStore.Data, docs); + } + if (doc) { + docs.Data.push(doc); + } } - } + })); })); - })); - }); - promises.push(prom); + }); + promises.push(prom); + } } - } - if (promises.length) { - Promise.all(promises).finally(() => batch.end()); - } else { - batch.end(); + if (promises.length) { + Promise.all(promises).finally(() => batch.end()); + } else { + batch.end(); + } } } + return CollectionSubView; } + diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 945c01059..32104b49d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,7 +1,5 @@ import { action, computed, observable, trace } from "mobx"; import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { KeyStore } from "../../../../fields/KeyStore"; import { emptyFunction, returnFalse, returnOne } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager } from "../../../util/DragManager"; @@ -13,7 +11,7 @@ import { InkingCanvas } from "../../InkingCanvas"; import { MainOverlayTextBox } from "../../MainOverlayTextBox"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "../../nodes/DocumentContentsView"; -import { DocumentViewProps } from "../../nodes/DocumentView"; +import { DocumentViewProps, positionSchema } from "../../nodes/DocumentView"; import { CollectionSubView } from "../CollectionSubView"; import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; @@ -21,17 +19,28 @@ import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); -import { BooleanField } from "../../../../fields/BooleanField"; +import { createSchema, makeInterface } from "../../../../new_fields/Schema"; +import { Doc } from "../../../../new_fields/Doc"; +import { FieldValue } from "../../../../new_fields/Types"; + +export const panZoomSchema = createSchema({ + panX: "number", + panY: "number", + zoom: "number" +}); + +type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof positionSchema]>; +const PanZoomDocument: (doc: Doc) => PanZoomDocument = makeInterface(panZoomSchema, positionSchema); @observer -export class CollectionFreeFormView extends CollectionSubView { +export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) private _lastX: number = 0; private _lastY: number = 0; private get _pwidth() { return this.props.PanelWidth(); } private get _pheight() { return this.props.PanelHeight(); } - @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } + @computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); } @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's? diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index d8de5afec..845213366 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -31,13 +31,13 @@ export interface FieldViewProps { select: (isCtrlPressed: boolean) => void; isTopMost: boolean; selectOnLoad: boolean; - addDocument?: (document: Document, allowDuplicates?: boolean) => boolean; - removeDocument?: (document: Document) => boolean; - moveDocument?: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean; + addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean; + removeDocument?: (document: Doc) => boolean; + moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; active: () => boolean; whenActiveChanged: (isActive: boolean) => void; - focus: (doc: Document) => void; + focus: (doc: Doc) => void; } @observer diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts index 1d1f56844..6022716be 100644 --- a/src/new_fields/Schema.ts +++ b/src/new_fields/Schema.ts @@ -1,9 +1,10 @@ import { Interface, ToInterface, Cast, FieldCtor, ToConstructor, HasTail, Head, Tail } from "./Types"; -import { Doc } from "./Doc"; +import { Doc, Field, ObjectField } from "./Doc"; +import { URLField } from "./URLField"; -type All = { - 1: makeInterface, U> & All, U>, - 0: makeInterface, U> +type All = { + 1: makeInterface<[Head], U> & All, U>, + 0: makeInterface<[Head], U> }[HasTail extends true ? 1 : 0]; type AllToInterface = { @@ -11,10 +12,14 @@ type AllToInterface = { 0: ToInterface> }[HasTail extends true ? 1 : 0]; +export const emptySchema = createSchema({}); +export const Document = makeInterface(emptySchema); +export type Document = makeInterface<[typeof emptySchema]>; + export type makeInterface = Partial> & U; // export function makeInterface(schemas: T): (doc: U) => All; // export function makeInterface(schema: T): (doc: U) => makeInterface; -export function makeInterface(schemas: T): (doc: U) => All { +export function makeInterface(...schemas: T): (doc: U) => makeInterface { let schema: Interface = {}; for (const s of schemas) { for (const key in s) { diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 0392dc2fb..e4d15e276 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -11,7 +11,7 @@ export type ToType = export type ToConstructor = T extends string ? "string" : T extends number ? "number" : - T extends boolean ? "boolean" : { new(...args: any[]): T }; + T extends boolean ? "boolean" : new (...args: any[]) => T; export type ToInterface = { [P in keyof T]: ToType; -- cgit v1.2.3-70-g09d2 From ee08f0ebcf3f911cf529e990c2c70aa0648a4f80 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 21 Apr 2019 09:36:09 -0400 Subject: added rightbtndrag code back as comments --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 1 + src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 69a3aac67..fa4d7c611 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -114,6 +114,7 @@ export class CollectionFreeFormView extends CollectionSubView { var dv = DocumentManager.Instance.getDocumentView(doc); return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); }, false); + //if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || (e.button === 0 && e.altKey)) && (childSelected || this.props.active())) { if ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index fb4396c05..b44cc9d37 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -70,6 +70,8 @@ export class MarqueeView extends React.Component } @action onPointerDown = (e: React.PointerEvent): void => { + // bcz:RightBtnDrag + //if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) { if (!e.metaKey && (e.altKey || this.props.container.props.active())) { this._downX = this._lastX = e.pageX; this._downY = this._lastY = e.pageY; @@ -95,6 +97,8 @@ export class MarqueeView extends React.Component this._showOnUp = false; PreviewCursor.Visible = false; } + //bcz:RightBtnDrag + //if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey && if (!this._used && (e.buttons === 2 || e.altKey) && !e.metaKey && (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) { this._visible = true; @@ -113,6 +117,8 @@ export class MarqueeView extends React.Component if (this._showOnUp) { PreviewCursor.Show(this.hideCursor, this._downX, this._downY); document.addEventListener("keypress", this.onKeyPress, false); + //bcz:RightBtnDrag + // } else { } else if (e.button === 2 || e.altKey) { let mselect = this.marqueeSelect(); if (!e.shiftKey) { -- cgit v1.2.3-70-g09d2 From 8dc47674365bb8fcff2cef0e91d26ff83923ecb8 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 21 Apr 2019 09:36:54 -0400 Subject: from last --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index fa4d7c611..2d1982b0a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -114,6 +114,7 @@ export class CollectionFreeFormView extends CollectionSubView { var dv = DocumentManager.Instance.getDocumentView(doc); return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); }, false); + // bcz:RightBtnDrag //if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || (e.button === 0 && e.altKey)) && (childSelected || this.props.active())) { if ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())) { document.removeEventListener("pointermove", this.onPointerMove); -- cgit v1.2.3-70-g09d2 From 393d351420b3a0d28f4cd1ea8b674fa5d04bfcde Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 21 Apr 2019 23:40:48 -0400 Subject: More fixes --- .../views/collections/CollectionDockingView.tsx | 6 ++-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 8 ++--- src/client/views/nodes/ImageBox.tsx | 15 +++++----- src/client/views/nodes/VideoBox.tsx | 35 ++++++++++++---------- src/client/views/nodes/WebBox.tsx | 4 +-- src/debug/Test.tsx | 12 ++++---- src/new_fields/Doc.ts | 4 +-- src/new_fields/Schema.ts | 22 +++----------- src/new_fields/Types.ts | 11 +++---- src/new_fields/URLField.ts | 9 ++++-- 12 files changed, 62 insertions(+), 68 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 7b204cbdc..86ee7cea9 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -16,7 +16,7 @@ import { ServerUtils } from "../../../server/ServerUtil"; import { DragManager, DragLinksAsDocuments } from "../../util/DragManager"; import { Transform } from '../../util/Transform'; import { Doc, Id, Opt, Field, FieldId } from "../../../new_fields/Doc"; -import { Cast, FieldValue } from "../../../new_fields/Types"; +import { Cast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { DocServer } from "../../DocServer"; @@ -336,8 +336,8 @@ export class DockedFrameRenderer extends React.Component { ScreenToLocalTransform = () => { if (this._mainCont.current && this._mainCont.current.children) { - let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!.children[0].firstChild as HTMLElement); - scale = Utils.GetScreenTransform(this._mainCont.current!).scale; + let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current.children[0].firstChild as HTMLElement); + scale = Utils.GetScreenTransform(this._mainCont.current).scale; return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this.contentScaling()); } return Transform.Identity(); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 27fd25b5c..c6eea5623 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -18,7 +18,7 @@ const schema = createSchema({ }); type FreeformDocument = makeInterface<[typeof schema, typeof positionSchema]>; -const FreeformDocument = makeInterface([schema, positionSchema]); +const FreeformDocument = makeInterface(schema, positionSchema); @observer export class CollectionFreeFormDocumentView extends DocComponent(FreeformDocument) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f1a12e6db..c0afc192e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -56,7 +56,7 @@ export const positionSchema = createSchema({ }); type Document = makeInterface<[typeof schema]>; -const Document = makeInterface([schema]); +const Document = makeInterface(schema); @observer export class DocumentView extends DocComponent(Document) { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 845213366..b11a87d75 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -3,19 +3,19 @@ import { observer } from "mobx-react"; import { computed } from "mobx"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; -import { WebBox } from "./WebBox"; import { VideoBox } from "./VideoBox"; import { AudioBox } from "./AudioBox"; import { DocumentContentsView } from "./DocumentContentsView"; import { Transform } from "../../util/Transform"; -import { returnFalse, emptyFunction, returnOne } from "../../../Utils"; +import { returnFalse, emptyFunction } from "../../../Utils"; import { CollectionView } from "../collections/CollectionView"; import { CollectionPDFView } from "../collections/CollectionPDFView"; import { CollectionVideoView } from "../collections/CollectionVideoView"; import { IconField } from "../../../fields/IconFIeld"; import { IconBox } from "./IconBox"; -import { Opt, Doc, Field, FieldValue, FieldWaiting } from "../../../new_fields/Doc"; +import { Opt, Doc, FieldResult } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; +import { ImageField, VideoField, AudioField } from "../../../new_fields/URLField"; // @@ -47,7 +47,7 @@ export class FieldView extends React.Component { } @computed - get field(): FieldValue { + get field(): FieldResult { const { Document, fieldKey } = this.props; return Document[fieldKey]; } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 3b72e9f39..c11aee56e 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -14,16 +14,15 @@ import { createSchema, makeInterface } from '../../../new_fields/Schema'; import { DocComponent } from '../DocComponent'; import { positionSchema } from './DocumentView'; import { FieldValue, Cast } from '../../../new_fields/Types'; -import { URLField } from '../../../new_fields/URLField'; -import { Doc, FieldWaiting } from '../../../new_fields/Doc'; +import { ImageField } from '../../../new_fields/URLField'; import { List } from '../../../new_fields/List'; -const schema = createSchema({ +export const pageSchema = createSchema({ curPage: "number" }); -type ImageDocument = makeInterface<[typeof schema, typeof positionSchema]>; -const ImageDocument = makeInterface([schema, positionSchema]); +type ImageDocument = makeInterface<[typeof pageSchema, typeof positionSchema]>; +const ImageDocument = makeInterface(pageSchema, positionSchema); @observer export class ImageBox extends DocComponent(ImageDocument) { @@ -135,7 +134,7 @@ export class ImageBox extends DocComponent(ImageD } specificContextMenu = (e: React.MouseEvent): void => { - let field = Cast(this.Document[this.props.fieldKey], URLField); + let field = Cast(this.Document[this.props.fieldKey], ImageField); if (field && field !== FieldWaiting) { let url = field.url.href; ContextMenu.Instance.addItem({ @@ -167,8 +166,8 @@ export class ImageBox extends DocComponent(ImageD let field = this.Document[this.props.fieldKey]; let paths: string[] = ["http://www.cs.brown.edu/~bcz/face.gif"]; if (field === FieldWaiting) paths = ["https://image.flaticon.com/icons/svg/66/66163.svg"]; - else if (field instanceof URLField) paths = [field.url.href]; - else if (field instanceof List) paths = field.filter(val => val instanceof URLField).map(p => (p as URLField).url.href); + else if (field instanceof ImageField) paths = [field.url.href]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); let nativeWidth = FieldValue(this.Document.nativeWidth, 1); return (
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 9d7c2bc56..7b922b620 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -1,18 +1,22 @@ import React = require("react"); import { observer } from "mobx-react"; -import { FieldWaiting, Opt } from '../../../fields/Field'; -import { VideoField } from '../../../fields/VideoField'; import { FieldView, FieldViewProps } from './FieldView'; import "./VideoBox.scss"; import Measure from "react-measure"; -import { action, trace, observable, IReactionDisposer, computed, reaction } from "mobx"; -import { KeyStore } from "../../../fields/KeyStore"; -import { number } from "prop-types"; +import { action, computed } from "mobx"; +import { DocComponent } from "../DocComponent"; +import { positionSchema } from "./DocumentView"; +import { makeInterface } from "../../../new_fields/Schema"; +import { pageSchema } from "./ImageBox"; +import { Cast, FieldValue } from "../../../new_fields/Types"; +import { VideoField } from "../../../new_fields/URLField"; + +type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; +const VideoDocument = makeInterface(positionSchema, pageSchema); @observer -export class VideoBox extends React.Component { +export class VideoBox extends DocComponent(VideoDocument) { - private _reactionDisposer: Opt; private _videoRef = React.createRef(); public static LayoutString() { return FieldView.LayoutString(VideoBox); } @@ -20,7 +24,7 @@ export class VideoBox extends React.Component { super(props); } - @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); } + @computed private get curPage() { return FieldValue(this.Document.curPage, -1); } _loaded: boolean = false; @@ -31,12 +35,12 @@ export class VideoBox extends React.Component { // bcz: the nativeHeight should really be set when the document is imported. // also, the native dimensions could be different for different pages of the PDF // so this design is flawed. - var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); - var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); + var nativeWidth = FieldValue(this.Document.nativeWidth, 0); + var nativeHeight = FieldValue(this.Document.nativeHeight, 0); var newNativeHeight = nativeWidth * r.entry.height / r.entry.width; if (!nativeHeight && newNativeHeight !== nativeHeight && !isNaN(newNativeHeight)) { - this.props.Document.SetNumber(KeyStore.Height, newNativeHeight / nativeWidth * this.props.Document.GetNumber(KeyStore.Width, 0)); - this.props.Document.SetNumber(KeyStore.NativeHeight, newNativeHeight); + this.Document.height = newNativeHeight / nativeWidth * FieldValue(this.Document.width, 0); + this.Document.nativeHeight = newNativeHeight; } } else { this._loaded = true; @@ -56,12 +60,11 @@ export class VideoBox extends React.Component { } render() { - let field = this.props.Document.GetT(this.props.fieldKey, VideoField); - if (!field || field === FieldWaiting) { + let field = FieldValue(Cast(this.Document[this.props.fieldKey], VideoField)); + if (!field) { return
Loading
; } - let path = field.Data.href; - trace(); + let path = field.url.href; return ( {({ measureRef }) => diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index e3b6e1c05..63778fa50 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -4,7 +4,7 @@ import { FieldViewProps, FieldView } from './FieldView'; import { observer } from "mobx-react"; import { computed } from 'mobx'; import { HtmlField } from "../../../new_fields/HtmlField"; -import { URLField } from "../../../new_fields/URLField"; +import { WebField } from "../../../new_fields/URLField"; @observer export class WebBox extends React.Component { @@ -37,7 +37,7 @@ export class WebBox extends React.Component { let view; if (field instanceof HtmlField) { view = - } else if (field instanceof URLField) { + } else if (field instanceof WebField) { view =