aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/PreviewCursor.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/PreviewCursor.tsx')
-rw-r--r--src/client/views/PreviewCursor.tsx127
1 files changed, 68 insertions, 59 deletions
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index e3a43d45f..456b753b4 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -1,41 +1,50 @@
-import { action, observable, runInAction } from 'mobx';
+import { action, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, Opt } from '../../fields/Doc';
import { lightOrDark, returnFalse } from '../../Utils';
-import { Docs, DocumentOptions, DocUtils } from '../documents/Documents';
+import { Doc, Opt } from '../../fields/Doc';
+import { DocUtils, Docs, DocumentOptions } from '../documents/Documents';
import { ImageUtils } from '../util/Import & Export/ImageUtils';
import { Transform } from '../util/Transform';
-import { undoBatch, UndoManager } from '../util/UndoManager';
-import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import { UndoManager, undoBatch } from '../util/UndoManager';
+import { ObservableReactComponent } from './ObservableReactComponent';
import './PreviewCursor.scss';
+import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
@observer
-export class PreviewCursor extends React.Component<{}> {
- static _onKeyPress?: (e: KeyboardEvent) => void;
- static _getTransform: () => Transform;
- static _addDocument: (doc: Doc | Doc[]) => boolean;
- static _addLiveTextDoc: (doc: Doc) => void;
- static _nudge?: undefined | ((x: number, y: number) => boolean);
- static _slowLoadDocuments?: (files: File[] | string, options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: ((doc: Doc[]) => void) | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => Promise<void>;
- @observable static _clickPoint = [0, 0];
- @observable public static Visible = false;
- public static Doc: Opt<Doc>;
+export class PreviewCursor extends ObservableReactComponent<{}> {
+ static _instance: PreviewCursor;
+ public static get Instance() {
+ return PreviewCursor._instance;
+ }
+
+ _onKeyPress?: (e: KeyboardEvent) => void;
+ _getTransform?: () => Transform;
+ _addDocument?: (doc: Doc | Doc[]) => boolean;
+ _addLiveTextDoc?: (doc: Doc) => void;
+ _nudge?: undefined | ((x: number, y: number) => boolean);
+ _slowLoadDocuments?: (files: File[] | string, options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: ((doc: Doc[]) => void) | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => Promise<void>;
+ @observable _clickPoint: number[] = [];
+ @observable public Visible = false;
+ public Doc: Opt<Doc>;
constructor(props: any) {
super(props);
+ makeObservable(this);
+ PreviewCursor._instance = this;
+ this._clickPoint = observable([0, 0]);
document.addEventListener('keydown', this.onKeyPress);
document.addEventListener('paste', this.paste, true);
}
paste = async (e: ClipboardEvent) => {
- if (PreviewCursor.Visible && e.clipboardData) {
- const newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]);
- runInAction(() => (PreviewCursor.Visible = false));
+ if (this.Visible && e.clipboardData) {
+ const newPoint = this._getTransform?.().transformPoint(this._clickPoint[0], this._clickPoint[1]);
+ runInAction(() => (this.Visible = false));
// tests for URL and makes web document
const re: any = /^https?:\/\//g;
const plain = e.clipboardData.getData('text/plain');
- if (plain) {
+ if (plain && newPoint) {
// tests for youtube and makes video document
if (plain.indexOf('www.youtube.com/watch') !== -1) {
const batch = UndoManager.StartBatch('youtube upload');
@@ -47,12 +56,12 @@ export class PreviewCursor extends React.Component<{}> {
x: newPoint[0],
y: newPoint[1],
};
- PreviewCursor._slowLoadDocuments?.(plain.split('v=')[1].split('&')[0], options, generatedDocuments, '', undefined, PreviewCursor._addDocument).then(batch.end);
+ this._slowLoadDocuments?.(plain.split('v=')[1].split('&')[0], options, generatedDocuments, '', undefined, this._addDocument ?? returnFalse).then(batch.end);
} else if (re.test(plain)) {
const url = plain;
- if (url.startsWith(window.location.href)) {
+ if (!url.startsWith(window.location.href)) {
undoBatch(() =>
- PreviewCursor._addDocument(
+ this._addDocument?.(
Docs.Create.WebDocument(url, {
title: url,
_width: 500,
@@ -70,13 +79,13 @@ export class PreviewCursor extends React.Component<{}> {
const strs = docids[0].split(','); // hack! docids[0] is the top left of the selection rectangle
const ptx = Number(strs[0].substring((clone ? '__DashCloneId(' : '__DashDocId(').length));
const pty = Number(strs[1].substring(0, strs[1].length - 1));
- Doc.Paste(docids.slice(1), clone, PreviewCursor._addDocument, ptx, pty, newPoint);
+ this._addDocument && Doc.Paste(docids.slice(1), clone, this._addDocument, ptx, pty, newPoint);
e.stopPropagation();
} else {
FormattedTextBox.PasteOnLoad = e;
if (e.clipboardData.getData('dash/pdfAnchor')) e.preventDefault();
- UndoManager.RunInBatch(() => PreviewCursor._addLiveTextDoc(DocUtils.GetNewTextDoc('', newPoint[0], newPoint[1], 500, undefined, undefined, undefined, 750)), 'paste');
+ UndoManager.RunInBatch(() => this._addLiveTextDoc?.(DocUtils.GetNewTextDoc('', newPoint[0], newPoint[1], 500, undefined, undefined, undefined)), 'paste');
}
}
//pasting in images
@@ -84,17 +93,19 @@ export class PreviewCursor extends React.Component<{}> {
const re: any = /<img src="(.*?)"/g;
const arr: any[] = re.exec(e.clipboardData.getData('text/html'));
- undoBatch(() => {
- const doc = Docs.Create.ImageDocument(arr[1], {
- _width: 300,
- title: arr[1],
- x: newPoint[0],
- y: newPoint[1],
- });
- ImageUtils.ExtractExif(doc);
- PreviewCursor._addDocument(doc);
- })();
- } else if (e.clipboardData.items.length) {
+ if (newPoint) {
+ undoBatch(() => {
+ const doc = Docs.Create.ImageDocument(arr[1], {
+ _width: 300,
+ title: arr[1],
+ x: newPoint[0],
+ y: newPoint[1],
+ });
+ ImageUtils.ExtractImgInfo(doc);
+ this._addDocument?.(doc);
+ })();
+ }
+ } else if (e.clipboardData.items.length && newPoint) {
const batch = UndoManager.StartBatch('collection view drop');
const files: File[] = [];
Array.from(e.clipboardData.items).forEach(item => {
@@ -102,7 +113,7 @@ export class PreviewCursor extends React.Component<{}> {
file && files.push(file);
});
const generatedDocuments = await DocUtils.uploadFilesToDocs(files, { x: newPoint[0], y: newPoint[1] });
- generatedDocuments.forEach(PreviewCursor._addDocument);
+ this._addDocument && generatedDocuments.forEach(this._addDocument);
batch.end();
}
}
@@ -135,25 +146,25 @@ export class PreviewCursor extends React.Component<{}> {
) {
if ((!e.metaKey && !e.ctrlKey) || (e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode >= 65 && e.keyCode <= 90)) {
// /^[a-zA-Z0-9$*^%#@+-=_|}{[]"':;?/><.,}]$/.test(e.key)) {
- PreviewCursor.Visible && PreviewCursor._onKeyPress?.(e);
- ((!e.ctrlKey && !e.metaKey) || e.key !== 'v') && (PreviewCursor.Visible = false);
+ this.Visible && this._onKeyPress?.(e);
+ ((!e.ctrlKey && !e.metaKey) || e.key !== 'v') && (this.Visible = false);
}
- } else if (PreviewCursor.Visible) {
+ } else if (this.Visible) {
if (e.key === 'ArrowRight') {
- PreviewCursor._nudge?.(1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation();
+ this._nudge?.(1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation();
} else if (e.key === 'ArrowLeft') {
- PreviewCursor._nudge?.(-1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation();
+ this._nudge?.(-1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation();
} else if (e.key === 'ArrowUp') {
- PreviewCursor._nudge?.(0, 1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation();
+ this._nudge?.(0, 1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation();
} else if (e.key === 'ArrowDown') {
- PreviewCursor._nudge?.(0, -1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation();
+ this._nudge?.(0, -1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation();
}
}
};
//when focus is lost, this will remove the preview cursor
@action onBlur = (): void => {
- PreviewCursor.Visible = false;
+ this.Visible = false;
};
@action
@@ -167,23 +178,21 @@ export class PreviewCursor extends React.Component<{}> {
nudge: undefined | ((nudgeX: number, nudgeY: number) => boolean),
slowLoadDocuments: (files: File[] | string, options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: ((doc: Doc[]) => void) | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => Promise<void>
) {
- this._clickPoint = [x, y];
- this._onKeyPress = onKeyPress;
- this._addLiveTextDoc = addLiveText;
- this._getTransform = getTransform;
- this._addDocument = addDocument || returnFalse;
- this._nudge = nudge;
- this._slowLoadDocuments = slowLoadDocuments;
- this.Visible = true;
+ const self = PreviewCursor.Instance;
+ if (self) {
+ self._clickPoint = [x, y];
+ self._onKeyPress = onKeyPress;
+ self._addLiveTextDoc = addLiveText;
+ self._getTransform = getTransform;
+ self._addDocument = addDocument || returnFalse;
+ self._nudge = nudge;
+ self._slowLoadDocuments = slowLoadDocuments;
+ self.Visible = true;
+ }
}
render() {
- return !PreviewCursor._clickPoint || !PreviewCursor.Visible ? null : (
- <div
- className="previewCursor"
- onBlur={this.onBlur}
- tabIndex={0}
- ref={e => e?.focus()}
- style={{ color: lightOrDark(PreviewCursor.Doc?.backgroundColor ?? 'white'), transform: `translate(${PreviewCursor._clickPoint[0]}px, ${PreviewCursor._clickPoint[1]}px)` }}>
+ return !this._clickPoint || !this.Visible ? null : (
+ <div className="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={e => e?.focus()} style={{ color: lightOrDark(this.Doc?.backgroundColor ?? 'white'), transform: `translate(${this._clickPoint[0]}px, ${this._clickPoint[1]}px)` }}>
I
</div>
);