aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/GlobalKeyHandler.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/GlobalKeyHandler.ts')
-rw-r--r--src/client/views/GlobalKeyHandler.ts279
1 files changed, 156 insertions, 123 deletions
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index f5122df3f..73e0c9933 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -1,39 +1,38 @@
-import { random } from "lodash";
-import { action, observable, runInAction } from "mobx";
-import { DateField } from "../../fields/DateField";
-import { Doc, DocListCast } from "../../fields/Doc";
-import { Id } from "../../fields/FieldSymbols";
-import { InkTool } from "../../fields/InkField";
-import { List } from "../../fields/List";
-import { ScriptField } from "../../fields/ScriptField";
-import { Cast, PromiseValue } from "../../fields/Types";
-import { GoogleAuthenticationManager } from "../apis/GoogleAuthenticationManager";
-import { DocServer } from "../DocServer";
-import { DocumentType } from "../documents/DocumentTypes";
-import { CurrentUserUtils } from "../util/CurrentUserUtils";
-import { DragManager } from "../util/DragManager";
-import { GroupManager } from "../util/GroupManager";
-import { SelectionManager } from "../util/SelectionManager";
-import { SettingsManager } from "../util/SettingsManager";
-import { SharingManager } from "../util/SharingManager";
-import { SnappingManager } from "../util/SnappingManager";
-import { undoBatch, UndoManager } from "../util/UndoManager";
-import { CollectionDockingView } from "./collections/CollectionDockingView";
-import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu";
-import { CollectionStackedTimeline } from "./collections/CollectionStackedTimeline";
-import { ContextMenu } from "./ContextMenu";
-import { DocumentDecorations } from "./DocumentDecorations";
-import { InkStrokeProperties } from "./InkStrokeProperties";
-import { LightboxView } from "./LightboxView";
-import { MainView } from "./MainView";
-import { DocumentLinksButton } from "./nodes/DocumentLinksButton";
-import { AnchorMenu } from "./pdf/AnchorMenu";
+import { random } from 'lodash';
+import { action, observable, runInAction } from 'mobx';
+import { DateField } from '../../fields/DateField';
+import { Doc, DocListCast } from '../../fields/Doc';
+import { Id } from '../../fields/FieldSymbols';
+import { InkTool } from '../../fields/InkField';
+import { List } from '../../fields/List';
+import { ScriptField } from '../../fields/ScriptField';
+import { Cast, PromiseValue } from '../../fields/Types';
+import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
+import { DocServer } from '../DocServer';
+import { DocumentType } from '../documents/DocumentTypes';
+import { DragManager } from '../util/DragManager';
+import { GroupManager } from '../util/GroupManager';
+import { SelectionManager } from '../util/SelectionManager';
+import { SettingsManager } from '../util/SettingsManager';
+import { SharingManager } from '../util/SharingManager';
+import { SnappingManager } from '../util/SnappingManager';
+import { undoBatch, UndoManager } from '../util/UndoManager';
+import { CollectionDockingView } from './collections/CollectionDockingView';
+import { CollectionFreeFormViewChrome } from './collections/CollectionMenu';
+import { CollectionStackedTimeline } from './collections/CollectionStackedTimeline';
+import { ContextMenu } from './ContextMenu';
+import { DocumentDecorations } from './DocumentDecorations';
+import { InkStrokeProperties } from './InkStrokeProperties';
+import { LightboxView } from './LightboxView';
+import { MainView } from './MainView';
+import { DocumentLinksButton } from './nodes/DocumentLinksButton';
+import { AnchorMenu } from './pdf/AnchorMenu';
-const modifiers = ["control", "meta", "shift", "alt"];
+const modifiers = ['control', 'meta', 'shift', 'alt'];
type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo;
type KeyControlInfo = {
- preventDefault: boolean,
- stopPropagation: boolean
+ preventDefault: boolean;
+ stopPropagation: boolean;
};
export class KeyManager {
@@ -41,22 +40,22 @@ export class KeyManager {
private router = new Map<string, KeyHandler>();
constructor() {
- const isMac = navigator.platform.toLowerCase().indexOf("mac") >= 0;
+ const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0;
// SHIFT CONTROL ALT META
- this.router.set("0000", this.unmodified);
- this.router.set(isMac ? "0001" : "0100", this.ctrl);
- this.router.set(isMac ? "0100" : "0010", this.alt);
- this.router.set(isMac ? "1001" : "1100", this.ctrl_shift);
- this.router.set("1000", this.shift);
+ this.router.set('0000', this.unmodified);
+ this.router.set(isMac ? '0001' : '0100', this.ctrl);
+ this.router.set(isMac ? '0100' : '0010', this.alt);
+ this.router.set(isMac ? '1001' : '1100', this.ctrl_shift);
+ this.router.set('1000', this.shift);
}
public unhandle = action((e: KeyboardEvent) => {
- if (e.key?.toLowerCase() === "shift") runInAction(() => DocumentDecorations.Instance.AddToSelection = false);
+ if (e.key?.toLowerCase() === 'shift') runInAction(() => (DocumentDecorations.Instance.AddToSelection = false));
});
public handle = action((e: KeyboardEvent) => {
- if (e.key?.toLowerCase() === "shift") DocumentDecorations.Instance.AddToSelection = true;
+ if (e.key?.toLowerCase() === 'shift') DocumentDecorations.Instance.AddToSelection = true;
//if (!Doc.noviceMode && e.key.toLocaleLowerCase() === "shift") DocServer.UPDATE_SERVER_CACHE(true);
const keyname = e.key && e.key.toLowerCase();
this.handleGreedy(keyname);
@@ -65,7 +64,7 @@ export class KeyManager {
return;
}
- const bit = (value: boolean) => value ? "1" : "0";
+ const bit = (value: boolean) => (value ? '1' : '0');
const modifierIndex = bit(e.shiftKey) + bit(e.ctrlKey) + bit(e.altKey) + bit(e.metaKey);
const handleConstrained = this.router.get(modifierIndex);
@@ -86,33 +85,33 @@ export class KeyManager {
private unmodified = action((keyname: string, e: KeyboardEvent) => {
switch (keyname) {
- case "u":
- if (document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA") {
+ case 'u':
+ if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {
return { stopPropagation: false, preventDefault: false };
}
const ungroupings = SelectionManager.Views().slice();
- UndoManager.RunInBatch(() => ungroupings.map(dv => dv.layoutDoc.group = undefined), "ungroup");
+ UndoManager.RunInBatch(() => ungroupings.map(dv => (dv.layoutDoc.group = undefined)), 'ungroup');
SelectionManager.DeselectAll();
break;
- case "g":
- if (document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA") {
+ case 'g':
+ if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {
return { stopPropagation: false, preventDefault: false };
}
const groupings = SelectionManager.Views().slice();
const randomGroup = random(0, 1000);
- UndoManager.RunInBatch(() => groupings.map(dv => dv.layoutDoc.group = randomGroup), "group");
+ UndoManager.RunInBatch(() => groupings.map(dv => (dv.layoutDoc.group = randomGroup)), 'group');
SelectionManager.DeselectAll();
break;
- case " ":
+ case ' ':
// MarqueeView.DragMarquee = !MarqueeView.DragMarquee; // bcz: this needs a better disclosure UI
break;
- case "escape":
+ case 'escape':
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
InkStrokeProperties.Instance._controlButton = false;
- CurrentUserUtils.ActiveTool = InkTool.None;
+ Doc.ActiveTool = InkTool.None;
DragManager.CompleteWindowDrag?.(true);
var doDeselect = true;
if (SnappingManager.GetIsDragging()) {
@@ -138,20 +137,19 @@ export class KeyManager {
window.getSelection()?.empty();
document.body.focus();
break;
- case "enter": {
+ case 'enter': {
DocumentDecorations.Instance.onCloseClick(false);
break;
}
- case "delete":
- case "backspace":
- if (document.activeElement?.tagName !== "INPUT" && document.activeElement?.tagName !== "TEXTAREA") {
+ case 'delete':
+ case 'backspace':
+ if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
UndoManager.RunInBatch(() => {
if (LightboxView.LightboxDoc) {
LightboxView.SetLightboxDoc(undefined);
SelectionManager.DeselectAll();
- }
- else DocumentDecorations.Instance.onCloseClick(true);
- }, "backspace");
+ } else DocumentDecorations.Instance.onCloseClick(true);
+ }, 'backspace');
// const selected = SelectionManager.Views().filter(dv => !dv.topMost);
// UndoManager.RunInBatch(() => {
// SelectionManager.DeselectAll();
@@ -160,15 +158,23 @@ export class KeyManager {
return { stopPropagation: true, preventDefault: true };
}
break;
- case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), "nudge left"); break;
- case "arrowright": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), "nudge right"); break;
- case "arrowup": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), "nudge up"); break;
- case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), "nudge down"); break;
+ case 'arrowleft':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), 'nudge left');
+ break;
+ case 'arrowright':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), 'nudge right');
+ break;
+ case 'arrowup':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), 'nudge up');
+ break;
+ case 'arrowdown':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), 'nudge down');
+ break;
}
return {
stopPropagation: false,
- preventDefault: false
+ preventDefault: false,
};
});
@@ -177,15 +183,23 @@ export class KeyManager {
const preventDefault = false;
switch (keyname) {
- case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(-10, 0)), "nudge left"); break;
- case "arrowright": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(10, 0)), "nudge right"); break;
- case "arrowup": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -10)), "nudge up"); break;
- case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 10)), "nudge down"); break;
+ case 'arrowleft':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(-10, 0)), 'nudge left');
+ break;
+ case 'arrowright':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(10, 0)), 'nudge right');
+ break;
+ case 'arrowup':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -10)), 'nudge up');
+ break;
+ case 'arrowdown':
+ UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 10)), 'nudge down');
+ break;
}
return {
stopPropagation: stopPropagation,
- preventDefault: preventDefault
+ preventDefault: preventDefault,
};
});
@@ -194,15 +208,15 @@ export class KeyManager {
const preventDefault = true;
switch (keyname) {
- case "ƒ":
- case "f":
+ case 'ƒ':
+ case 'f':
const dv = SelectionManager.Views()?.[0];
- UndoManager.RunInBatch(() => dv.props.CollectionFreeFormDocumentView?.().float(), "float");
+ UndoManager.RunInBatch(() => dv.props.CollectionFreeFormDocumentView?.().float(), 'float');
}
return {
stopPropagation: stopPropagation,
- preventDefault: preventDefault
+ preventDefault: preventDefault,
};
});
@@ -211,83 +225,97 @@ export class KeyManager {
let preventDefault = true;
switch (keyname) {
- case "arrowright":
- if (document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA") {
+ case 'arrowright':
+ if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {
return { stopPropagation: false, preventDefault: false };
}
- MainView.Instance.mainFreeform && CollectionDockingView.AddSplit(MainView.Instance.mainFreeform, "right");
+ MainView.Instance.mainFreeform && CollectionDockingView.AddSplit(MainView.Instance.mainFreeform, 'right');
break;
- case "arrowleft":
- if (document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA") {
+ case 'arrowleft':
+ if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {
return { stopPropagation: false, preventDefault: false };
}
MainView.Instance.mainFreeform && CollectionDockingView.CloseSplit(MainView.Instance.mainFreeform);
break;
- case "backspace":
- if (document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA") {
+ case 'backspace':
+ if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {
return { stopPropagation: false, preventDefault: false };
}
break;
- case "t":
- PromiseValue(Cast(Doc.UserDoc()["tabs-button-tools"], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+ case 't':
+ PromiseValue(Cast(Doc.UserDoc()['tabs-button-tools'], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
break;
- case "f":
+ case 'f':
if (SelectionManager.Views().length === 1 && SelectionManager.Views()[0].ComponentView?.search) {
- SelectionManager.Views()[0].ComponentView?.search?.("", false, false);
+ SelectionManager.Views()[0].ComponentView?.search?.('', false, false);
} else {
- const searchBtn = CurrentUserUtils.MySearcher;
+ const searchBtn = Doc.MySearcher;
if (searchBtn) {
MainView.Instance.selectMenu(searchBtn);
}
}
break;
- case "e": CurrentUserUtils.ActiveTool = InkTool.Eraser;
+ case 'e':
+ Doc.ActiveTool = InkTool.Eraser;
break;
- case "p": CurrentUserUtils.ActiveTool = InkTool.Pen;
+ case 'p':
+ Doc.ActiveTool = InkTool.Pen;
break;
- case "o":
+ case 'o':
const target = SelectionManager.Docs().lastElement();
target && CollectionDockingView.OpenFullScreen(target);
break;
- case "r":
+ case 'r':
preventDefault = false;
break;
- case "y":
+ case 'y':
SelectionManager.DeselectAll();
UndoManager.Redo();
stopPropagation = false;
break;
- case "z":
+ case 'z':
SelectionManager.DeselectAll();
UndoManager.Undo();
stopPropagation = false;
break;
- case "a":
+ case 'a':
if (e.target !== document.body) {
stopPropagation = false;
preventDefault = false;
}
break;
- case "v":
+ case 'v':
stopPropagation = false;
preventDefault = false;
break;
- case "x":
+ case 'x':
if (SelectionManager.Views().length) {
const bds = DocumentDecorations.Instance.Bounds;
- const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
- const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":");
+ const pt = SelectionManager.Views()[0]
+ .props.ScreenToLocalTransform()
+ .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
+ const text =
+ `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` +
+ SelectionManager.Views()
+ .map(dv => dv.Document[Id])
+ .join(':');
SelectionManager.Views().length && navigator.clipboard.writeText(text);
DocumentDecorations.Instance.onCloseClick(true);
stopPropagation = false;
preventDefault = false;
}
break;
- case "c":
+ case 'c':
if (!AnchorMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
const bds = DocumentDecorations.Instance.Bounds;
- const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
- const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":");
+ const pt = SelectionManager.Views()[0]
+ .props.ScreenToLocalTransform()
+ .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
+ const text =
+ `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` +
+ SelectionManager.Views()
+ .map(dv => dv.Document[Id])
+ .join(':');
SelectionManager.Views().length && navigator.clipboard.writeText(text);
stopPropagation = false;
}
@@ -297,58 +325,63 @@ export class KeyManager {
return {
stopPropagation: stopPropagation,
- preventDefault: preventDefault
+ preventDefault: preventDefault,
};
});
public paste(e: ClipboardEvent) {
- const plain = e.clipboardData?.getData("text/plain");
- const clone = plain?.startsWith("__DashCloneId(");
- if (plain && (plain.startsWith("__DashDocId(") || clone)) {
+ const plain = e.clipboardData?.getData('text/plain');
+ const clone = plain?.startsWith('__DashCloneId(');
+ if (plain && (plain.startsWith('__DashDocId(') || clone)) {
const first = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
if (first?.props.Document.type === DocumentType.COL) {
- const docids = plain.split(":");
+ const docids = plain.split(':');
let count = 1;
const list: Doc[] = [];
const targetDataDoc = Doc.GetProto(first.props.Document);
const fieldKey = first.LayoutFieldKey;
const docList = DocListCast(targetDataDoc[fieldKey]);
- docids.map((did, i) => i && DocServer.GetRefField(did).then(async doc => {
- count++;
- if (doc instanceof Doc) {
- list.push(doc);
- }
- if (count === docids.length) {
- const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? (await Doc.MakeClone(d)).clone : d));
- if (added.length) {
- added.map(doc => doc.context = targetDataDoc);
- undoBatch(() => {
- targetDataDoc[fieldKey] = new List<Doc>([...docList, ...added]);
- targetDataDoc[fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
- })();
- }
- }
- }));
+ docids.map(
+ (did, i) =>
+ i &&
+ DocServer.GetRefField(did).then(async doc => {
+ count++;
+ if (doc instanceof Doc) {
+ list.push(doc);
+ }
+ if (count === docids.length) {
+ const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => (clone ? (await Doc.MakeClone(d)).clone : d)));
+ if (added.length) {
+ added.map(doc => (doc.context = targetDataDoc));
+ undoBatch(() => {
+ targetDataDoc[fieldKey] = new List<Doc>([...docList, ...added]);
+ targetDataDoc[fieldKey + '-lastModified'] = new DateField(new Date(Date.now()));
+ })();
+ }
+ }
+ })
+ );
}
}
}
- getClipboard() { return navigator.clipboard.readText(); }
+ getClipboard() {
+ return navigator.clipboard.readText();
+ }
private ctrl_shift = action((keyname: string) => {
const stopPropagation = true;
const preventDefault = true;
switch (keyname) {
- case "z":
+ case 'z':
UndoManager.Redo();
break;
}
return {
stopPropagation: stopPropagation,
- preventDefault: preventDefault
+ preventDefault: preventDefault,
};
});
-
}