diff options
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/DocumentDecorations.tsx | 3 | ||||
| -rw-r--r-- | src/client/views/InkingCanvas.tsx | 24 | ||||
| -rw-r--r-- | src/client/views/InkingControl.tsx | 3 | ||||
| -rw-r--r-- | src/client/views/Main.tsx | 8 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 1 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionView.tsx | 7 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionViewBase.tsx | 39 | ||||
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 2 |
9 files changed, 61 insertions, 28 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index deed0fa7c..285d145a2 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -379,6 +379,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> // } render() { var bounds = this.Bounds; + if (bounds.x === Number.MAX_VALUE) { + return (null); + } // console.log(this._documents.length) // let test = this._documents[0].props.Document.Title; if (this.Hidden) { diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index 4b3ea48c5..4ecc44119 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -10,6 +10,7 @@ import "./InkingCanvas.scss"; import { InkingControl } from "./InkingControl"; import { InkingStroke } from "./InkingStroke"; import React = require("react"); +import { undoBatch, UndoManager } from "../util/UndoManager"; interface InkCanvasProps { getScreenTransform: () => Transform; @@ -22,6 +23,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> { maxCanvasDim = 8192 / 2; // 1/2 of the maximum canvas dimension for Chrome @observable inkMidX: number = 0; @observable inkMidY: number = 0; + private previousState?: StrokeMap; private _currentStrokeId: string = ""; public static IntersectStrokeRect(stroke: StrokeData, selRect: { left: number, top: number, width: number, height: number }): boolean { return stroke.pathData.reduce((inside: boolean, val) => inside || @@ -59,23 +61,28 @@ export class InkingCanvas extends React.Component<InkCanvasProps> { if (e.button !== 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) { return; } + document.addEventListener("pointermove", this.onPointerMove, true); document.addEventListener("pointerup", this.onPointerUp, true); e.stopPropagation(); e.preventDefault(); + this.previousState = this.inkData; + if (InkingControl.Instance.selectedTool !== InkTool.Eraser) { // start the new line, saves a uuid to represent the field of the stroke this._currentStrokeId = Utils.GenerateGuid(); - this.inkData.set(this._currentStrokeId, { + const data = this.inkData; + data.set(this._currentStrokeId, { pathData: [this.relativeCoordinatesForEvent(e.clientX, e.clientY)], color: InkingControl.Instance.selectedColor, width: InkingControl.Instance.selectedWidth, tool: InkingControl.Instance.selectedTool, page: this.props.Document.GetNumber(KeyStore.CurPage, -1) }); + this.inkData = data; } - } + }; @action onPointerUp = (e: PointerEvent): void => { @@ -88,6 +95,16 @@ export class InkingCanvas extends React.Component<InkCanvasProps> { } e.stopPropagation(); e.preventDefault(); + + const batch = UndoManager.StartBatch("One ink stroke"); + const oldState = this.previousState || new Map; + this.previousState = undefined; + const newState = this.inkData; + UndoManager.AddEvent({ + undo: () => this.inkData = oldState, + redo: () => this.inkData = newState, + }); + batch.end(); } @action @@ -103,13 +120,14 @@ export class InkingCanvas extends React.Component<InkCanvasProps> { } this.inkData = data; } - } + }; relativeCoordinatesForEvent = (ex: number, ey: number): { x: number, y: number } => { let [x, y] = this.props.getScreenTransform().transformPoint(ex, ey); return { x, y }; } + @undoBatch @action removeLine = (id: string): void => { let data = this.inkData; diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 13f0a0acc..64ee66ec7 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -21,7 +21,7 @@ export class InkingControl extends React.Component { @observable private _selectedColor: string = "rgb(244, 67, 54)"; @observable private _selectedWidth: string = "25"; @observable private _open: boolean = false; - @observable private _colorPickerDisplay: boolean = false; + @observable private _colorPickerDisplay = false; constructor(props: Readonly<{}>) { super(props); @@ -76,6 +76,7 @@ export class InkingControl extends React.Component { this._open = !this._open; } + @action toggleColorPicker = () => { this._colorPickerDisplay = !this._colorPickerDisplay; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 9868f6c74..6376fd694 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -321,7 +321,7 @@ export class Main extends React.Component { isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} /> } return ( - [ + <> <div id="main-div"> <DocumentDecorations /> <Measure onResize={(r: any) => runInAction(() => { @@ -339,9 +339,9 @@ export class Main extends React.Component { {this.miscButtons} {workspaceMenu} <InkingControl /> - </div>, - this.activeTextBox - ] + </div> + {this.activeTextBox} + </> ); } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 6640c843e..c5e1e7f4b 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -226,6 +226,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp itemDropped = () => { this.stateChanged(); } + tabCreated = (tab: any) => { if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") { if (tab.titleElement[0].textContent.indexOf("-waiting") !== -1) { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 1b0cfd57b..b31dcc888 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -9,6 +9,7 @@ import { ContextMenu } from '../ContextMenu'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { KeyStore } from '../../../fields/KeyStore'; import { observer } from 'mobx-react'; +import { undoBatch } from '../../util/UndoManager'; @observer export class CollectionView extends React.Component<FieldViewProps> { @@ -29,9 +30,9 @@ export class CollectionView extends React.Component<FieldViewProps> { onContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) - ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) - ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) }) + ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) }) + ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) }) + ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) }) } } diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 84d378e1c..ad1294f76 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -4,20 +4,17 @@ import { ListField } from "../../../fields/ListField"; import React = require("react"); import { KeyStore } from "../../../fields/KeyStore"; import { FieldWaiting, Opt } from "../../../fields/Field"; -import { undoBatch } from "../../util/UndoManager"; +import { undoBatch, UndoManager } from "../../util/UndoManager"; import { DragManager } from "../../util/DragManager"; import { Documents, DocumentOptions } from "../../documents/Documents"; -import { Key } from "../../../fields/Key"; -import { Transform } from "../../util/Transform"; -import { CollectionView } from "./CollectionView"; import { RouteStore } from "../../../server/RouteStore"; import { TupleField } from "../../../fields/TupleField"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { NumberField } from "../../../fields/NumberField"; -import request = require("request"); import { ServerUtils } from "../../../server/ServerUtil"; import { Server } from "../../Server"; import { FieldViewProps } from "../nodes/FieldView"; +import * as rp from 'request-promise' export interface CollectionViewProps extends FieldViewProps { addDocument: (document: Document, allowDuplicates?: boolean) => boolean; @@ -145,6 +142,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> return ctor ? ctor(path, options) : undefined; } + @undoBatch @action protected onDrop(e: React.DragEvent, options: DocumentOptions): void { let html = e.dataTransfer.getData("text/html"); @@ -164,23 +162,29 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> return; } + let batch = UndoManager.StartBatch("collection view drop"); + let promises: Promise<void>[] = []; // 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) { - e.dataTransfer.items[i].getAsString(action((s: string) => { - request.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s), (err, res, body) => { + let str: string; + let prom = new Promise<string>(res => + e.dataTransfer.items[i].getAsString(res)).then(action((s: string) => { + str = s; + return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s)) + })).then(res => { let type = res.headers["content-type"]; if (type) { - let doc = this.getDocumentFromType(type, s, { ...options, width: 300, nativeWidth: 300 }) + let doc = this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }) if (doc) { this.props.addDocument(doc, false); } } }); - // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false) - })) + promises.push(prom); + // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false) } let type = item.type if (item.kind === "file") { @@ -191,7 +195,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> formData.append('file', file) } - fetch(upload, { + let prom = fetch(upload, { method: 'POST', body: formData }).then(async (res: Response) => { @@ -211,10 +215,17 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> docs.Data.push(doc); } } - }) - }) - }) + }); + }); + }); + promises.push(prom); } } + + if (promises.length) { + Promise.all(promises).catch(() => { }).then(() => batch.end()); + } else { + batch.end(); + } } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d542b8bc2..731ba3332 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -209,7 +209,7 @@ export class CollectionFreeFormView extends CollectionViewBase { onDrop = (e: React.DragEvent): void => { var pt = this.getTransform().transformPoint(e.pageX, e.pageY); super.onDrop(e, { x: pt[0], y: pt[1] }); - } + }; onDragOver = (): void => { } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index ebac61c78..7a94be12b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -153,8 +153,6 @@ export class FormattedTextBox extends React.Component<FieldViewProps> { if (e.buttons === 1 && this.props.isSelected() && !e.altKey) { e.stopPropagation(); } - if (e.buttons === 1 && this.props.fieldKey !== KeyStore.Archives) - e.preventDefault(); }; onPointerUp = (e: React.PointerEvent): void => { if (e.buttons === 1 && this.props.isSelected() && !e.altKey) { |
