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.ts178
1 files changed, 75 insertions, 103 deletions
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 7b693c8da..d134d9e7b 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -1,5 +1,5 @@
import { random } from 'lodash';
-import { action, runInAction } from 'mobx';
+import { action } from 'mobx';
import { Doc, DocListCast } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { InkTool } from '../../fields/InkField';
@@ -15,7 +15,6 @@ import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { CollectionFreeFormView } from './collections/collectionFreeForm';
-import { CollectionFreeFormViewChrome } from './collections/CollectionMenu';
import { CollectionStackedTimeline } from './collections/CollectionStackedTimeline';
import { ContextMenu } from './ContextMenu';
import { DocumentDecorations } from './DocumentDecorations';
@@ -33,6 +32,7 @@ type KeyControlInfo = {
stopPropagation: boolean;
};
+export let CtrlKey = false;
export class KeyManager {
public static Instance: KeyManager = new KeyManager();
private router = new Map<string, KeyHandler>();
@@ -49,11 +49,19 @@ export class KeyManager {
}
public unhandle = action((e: KeyboardEvent) => {
- if (e.key?.toLowerCase() === 'shift') runInAction(() => (DocumentDecorations.Instance.AddToSelection = false));
+ e.key === 'Control' && (CtrlKey = false);
+ });
+ public handleModifiers = action((e: KeyboardEvent) => {
+ if (e.shiftKey) SnappingManager.SetShiftKey(true);
+ if (e.ctrlKey) SnappingManager.SetCtrlKey(true);
+ });
+ public unhandleModifiers = action((e: KeyboardEvent) => {
+ if (!e.shiftKey) SnappingManager.SetShiftKey(false);
+ if (!e.ctrlKey) SnappingManager.SetCtrlKey(false);
});
public handle = action((e: KeyboardEvent) => {
- if (e.key?.toLowerCase() === 'shift') DocumentDecorations.Instance.AddToSelection = true;
+ e.key === 'Control' && (CtrlKey = true);
//if (!Doc.noviceMode && e.key.toLocaleLowerCase() === "shift") DocServer.UPDATE_SERVER_CACHE(true);
const keyname = e.key && e.key.toLowerCase();
this.handleGreedy(keyname);
@@ -81,41 +89,32 @@ export class KeyManager {
}
});
+ nudge = (x: number, y: number, label: string) => {
+ const nudgeable = SelectionManager.Views.some(dv => dv.CollectionFreeFormDocumentView?.nudge);
+ nudgeable && UndoManager.RunInBatch(() => SelectionManager.Views.map(dv => dv.CollectionFreeFormDocumentView?.nudge(x, y)), label);
+ return { stopPropagation: nudgeable, preventDefault: nudgeable };
+ };
+
private unmodified = action((keyname: string, e: KeyboardEvent) => {
- const hasFffView = SelectionManager.Views().some(dv => dv.props.CollectionFreeFormDocumentView?.());
switch (keyname) {
case 'u':
- if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {
- return { stopPropagation: false, preventDefault: false };
+ if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
+ const ungroupings = SelectionManager.Views;
+ UndoManager.RunInBatch(() => ungroupings.map(dv => (dv.layoutDoc.group = undefined)), 'ungroup');
+ SelectionManager.DeselectAll();
}
-
- const ungroupings = SelectionManager.Views().slice();
- UndoManager.RunInBatch(() => ungroupings.map(dv => (dv.layoutDoc.group = undefined)), 'ungroup');
- SelectionManager.DeselectAll();
break;
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);
- const collectionView = groupings.reduce(
- (col, g) => (col === null || g.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView === col ? g.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView : undefined),
- null as null | undefined | CollectionFreeFormView
- );
- if (collectionView) {
- UndoManager.RunInBatch(() => {
- collectionView._marqueeViewRef.current?.collection(
- e,
- true,
- groupings.map(g => g.rootDoc)
- );
- }, 'grouping');
- break;
+ if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
+ const selected = SelectionManager.Views;
+ const collectionView = selected.reduce((col, dv) => (col === null || dv.CollectionFreeFormView === col ? dv.CollectionFreeFormView : undefined), null as null | undefined | CollectionFreeFormView);
+ if (collectionView) {
+ UndoManager.RunInBatch(() =>
+ collectionView._marqueeViewRef.current?.collection(e, true, SelectionManager.Docs)
+ , 'grouping');
+ break;
+ }
}
- UndoManager.RunInBatch(() => groupings.map(dv => (dv.layoutDoc.group = randomGroup)), 'group');
- SelectionManager.DeselectAll();
break;
case ' ':
// MarqueeView.DragMarquee = !MarqueeView.DragMarquee; // bcz: this needs a better disclosure UI
@@ -127,26 +126,27 @@ export class KeyManager {
Doc.ActiveTool = InkTool.None;
DragManager.CompleteWindowDrag?.(true);
var doDeselect = true;
- if (SnappingManager.GetIsDragging()) {
+ if (SnappingManager.IsDragging) {
DragManager.AbortDrag();
- } else if (CollectionDockingView.Instance?.HasFullScreen) {
+ }
+ if (CollectionDockingView.Instance?.HasFullScreen) {
CollectionDockingView.Instance?.CloseFullScreen();
- } else if (CollectionStackedTimeline.SelectingRegion) {
- CollectionStackedTimeline.SelectingRegion = undefined;
+ }
+ if (CollectionStackedTimeline.SelectingRegions.size) {
+ CollectionStackedTimeline.StopSelecting();
doDeselect = false;
} else {
doDeselect = !ContextMenu.Instance.closeMenu();
}
if (doDeselect) {
SelectionManager.DeselectAll();
- LightboxView.SetLightboxDoc(undefined);
+ LightboxView.Instance.SetLightboxDoc(undefined);
}
// DictationManager.Controls.stop();
GoogleAuthenticationManager.Instance.cancel();
SharingManager.Instance.close();
if (!GroupManager.Instance.isOpen) SettingsManager.Instance.close();
GroupManager.Instance.close();
- CollectionFreeFormViewChrome.Instance?.clearKeepPrimitiveMode();
window.getSelection()?.empty();
document.body.focus();
break;
@@ -158,25 +158,17 @@ export class KeyManager {
case 'backspace':
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
if (LightboxView.LightboxDoc) {
- LightboxView.SetLightboxDoc(undefined);
+ LightboxView.Instance.SetLightboxDoc(undefined);
SelectionManager.DeselectAll();
} else DocumentDecorations.Instance.onCloseClick(true);
return { stopPropagation: true, preventDefault: true };
}
break;
- case 'arrowleft':
- UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), 'nudge left');
- return { stopPropagation: hasFffView, preventDefault: hasFffView };
- case 'arrowright':
- UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), 'nudge right');
- return { stopPropagation: hasFffView, preventDefault: hasFffView };
- case 'arrowup':
- UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), 'nudge up');
- return { stopPropagation: hasFffView, preventDefault: hasFffView };
- case 'arrowdown':
- UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), 'nudge down');
- return { stopPropagation: hasFffView, preventDefault: hasFffView };
- }
+ case 'arrowleft': return this.nudge(-1,0, 'nudge left')
+ case 'arrowright': return this.nudge(1,0, 'nudge right');
+ case 'arrowup': return this.nudge(0, -1, 'nudge up');
+ case 'arrowdown': return this.nudge(0, 1, 'nudge down');
+ } // prettier-ignore
return {
stopPropagation: false,
@@ -185,37 +177,29 @@ export class KeyManager {
});
private shift = action((keyname: string) => {
- const stopPropagation = false;
- 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');
+ case 'arrowleft': return this.nudge(-10,0, 'nudge left');
+ case 'arrowright': return this.nudge(10, 0, 'nudge right');
+ case 'arrowup': return this.nudge(0, -10, 'nudge up');
+ case 'arrowdown': return this.nudge(0, 10, 'nudge down');
+ case 'u' :
+ if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
+ UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => (doc.group = undefined)), 'unggroup');
+ SelectionManager.DeselectAll();
+ }
break;
case 'g':
- if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {
- return { stopPropagation: false, preventDefault: false };
+ if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
+ const randomGroup = random(0, 1000);
+ UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => (doc.group = randomGroup)), 'group');
+ SelectionManager.DeselectAll();
}
-
- const groupings = SelectionManager.Views().slice();
- const randomGroup = random(0, 1000);
- UndoManager.RunInBatch(() => groupings.map(dv => (dv.layoutDoc.group = randomGroup)), 'group');
- SelectionManager.DeselectAll();
break;
- }
+ } // prettier-ignore
return {
- stopPropagation: stopPropagation,
- preventDefault: preventDefault,
+ stopPropagation: false,
+ preventDefault: false,
};
});
@@ -226,8 +210,8 @@ export class KeyManager {
switch (keyname) {
case 'ƒ':
case 'f':
- const dv = SelectionManager.Views()?.[0];
- UndoManager.RunInBatch(() => dv.props.CollectionFreeFormDocumentView?.().float(), 'float');
+ const dv = SelectionManager.Views?.[0];
+ UndoManager.RunInBatch(() => dv.CollectionFreeFormDocumentView?.float(), 'float');
}
return {
@@ -262,7 +246,7 @@ export class KeyManager {
PromiseValue(Cast(Doc.UserDoc()['tabs-button-tools'], Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
break;
case 'i':
- const importBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MyImports);
+ const importBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MyImports);
if (importBtn) {
MainView.Instance.selectMenu(importBtn);
}
@@ -274,8 +258,8 @@ export class KeyManager {
}
break;
case 'f':
- if (SelectionManager.Views().length === 1 && SelectionManager.Views()[0].ComponentView?.search) {
- SelectionManager.Views()[0].ComponentView?.search?.('', false, false);
+ if (SelectionManager.Views.length === 1 && SelectionManager.Views[0].ComponentView?.search) {
+ SelectionManager.Views[0].ComponentView?.search?.('', false, false);
} else {
const searchBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MySearcher);
if (searchBtn) {
@@ -284,10 +268,10 @@ export class KeyManager {
}
break;
case 'e':
- Doc.ActiveTool = (Doc.ActiveTool === InkTool.Eraser ? InkTool.None : InkTool.Eraser);
+ Doc.ActiveTool = Doc.ActiveTool === InkTool.Eraser ? InkTool.None : InkTool.Eraser;
break;
case 'p':
- Doc.ActiveTool = (Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen);
+ Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen;
break;
case 'r':
preventDefault = false;
@@ -317,17 +301,11 @@ export class KeyManager {
preventDefault = false;
break;
case 'x':
- if (SelectionManager.Views().length) {
+ 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(':');
- SelectionManager.Views().length && navigator.clipboard.writeText(text);
+ const pt = SelectionManager.Views[0].screenToViewTransform().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;
@@ -336,15 +314,9 @@ export class KeyManager {
case 'c':
if ((document.activeElement as any)?.type !== 'text' && !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(':');
- SelectionManager.Views().length && navigator.clipboard.writeText(text);
+ const pt = SelectionManager.Views[0].screenToViewTransform().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;
}
preventDefault = false;
@@ -362,7 +334,7 @@ export class KeyManager {
if (!plain) return;
const clone = plain.startsWith('__DashCloneId(');
const docids = plain.split(':'); // hack! docids[0] is the top left of the selection rectangle
- const addDocument = SelectionManager.Views().lastElement()?.ComponentView?.addDocument;
+ const addDocument = SelectionManager.Views.lastElement()?.ComponentView?.addDocument;
if (addDocument && (plain.startsWith('__DashDocId(') || clone)) {
Doc.Paste(docids.slice(1), clone, addDocument);
}