diff options
Diffstat (limited to 'src/client/views/GlobalKeyHandler.ts')
-rw-r--r-- | src/client/views/GlobalKeyHandler.ts | 178 |
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); } |