diff options
-rw-r--r-- | src/client/documents/Documents.ts | 1 | ||||
-rw-r--r-- | src/client/util/SnappingManager.ts | 3 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 9 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 65 |
5 files changed, 44 insertions, 40 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2dcf8a54c..b96fdb4bd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -849,6 +849,7 @@ export namespace Docs { I.text_align = 'center'; I.rotation = 0; I.defaultDoubleClick = 'ignore'; + I.keepZWhenDragged = true; I.author_date = new DateField(); I.acl_Guest = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View; // I.acl_Override = SharingPermissions.Unset; diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 1337d271f..cc0366c5b 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -11,6 +11,7 @@ export class SnappingManager { return SnappingManager._manager ?? new SnappingManager(); } + @observable _longPress = false; @observable _shiftKey = false; @observable _ctrlKey = false; @observable _metaKey = false; @@ -43,6 +44,7 @@ export class SnappingManager { public static get HorizSnapLines() { return this.Instance._horizSnapLines; } // prettier-ignore public static get VertSnapLines() { return this.Instance._vertSnapLines; } // prettier-ignore + public static get LongPress() { return this.Instance._longPress; } // prettier-ignore public static get ShiftKey() { return this.Instance._shiftKey; } // prettier-ignore public static get CtrlKey() { return this.Instance._ctrlKey; } // prettier-ignore public static get MetaKey() { return this.Instance._metaKey; } // prettier-ignore @@ -58,6 +60,7 @@ export class SnappingManager { public static get PropertiesWidth(){ return this.Instance._propertyWid; } // prettier-ignore public static get PrintToConsole() { return this.Instance._printToConsole; } // prettier-ignore + public static SetLongPress = (press: boolean) => runInAction(() => {this.Instance._longPress = press}); // prettier-ignore public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore public static SetCtrlKey = (down: boolean) => runInAction(() => {this.Instance._ctrlKey = down}); // prettier-ignore public static SetMetaKey = (down: boolean) => runInAction(() => {this.Instance._metaKey = down}); // prettier-ignore diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 31d88fb87..ef1bcfb64 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -555,16 +555,16 @@ export class MainView extends ObservableReactComponent<{}> { private longPressTimer: NodeJS.Timeout | undefined; globalPointerClick = action(() => { this.longPressTimer && clearTimeout(this.longPressTimer); - DocumentView.LongPress = false; + SnappingManager.SetLongPress(false); }); globalPointerMove = action((e: PointerEvent) => { if (e.movementX > 3 || e.movementY > 3) this.longPressTimer && clearTimeout(this.longPressTimer); }); globalPointerDown = action((e: PointerEvent) => { - DocumentView.LongPress = false; + SnappingManager.SetLongPress(false); this.longPressTimer = setTimeout( action(() => { - DocumentView.LongPress = true; + SnappingManager.SetLongPress(true); }), 1000 ); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 034a38e9c..29a499035 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -20,6 +20,11 @@ import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldViewProps } from './FieldView'; import { OpenWhere } from './OpenWhere'; +export enum GroupActive { // flags for whether a view is activate because of its relationship to a group + group = 'group', // this is a group that is activated because it's on an active canvas, but is not part of some other group + child = 'child', // this is a group child that is activated because its containing group is activated + inactive = 'inactive', // this is a group child but it is not active +} /// Ugh, typescript has no run-time way of iterating through the keys of an interface. so we need /// manaully keep this list of keys in synch wih the fields of the freeFormProps interface const freeFormPropsKeys = ['x', 'y', 'z', 'zIndex', 'rotation', 'opacity', 'backgroundColor', 'color', 'highlight', 'width', 'height', 'autoDim', 'transition']; @@ -274,7 +279,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF if (this._props.isAnyChildContentActive()) return undefined; const backColor = this.BackgroundColor; const isGroup = this.dataDoc.isGroup && (!backColor || backColor === 'transparent'); - return isGroup ? (this._props.isDocumentActive?.() ? 'group' : this._props.isGroupActive?.() ? 'child' : 'inactive') : this._props.isGroupActive?.() ? 'child' : undefined; + return isGroup ? (this._props.isDocumentActive?.() ? GroupActive.group : + this._props.isGroupActive?.() ? GroupActive.child : GroupActive.inactive) : + this._props.isGroupActive?.() ? GroupActive.child : undefined; // prettier-ignore }; localRotation = () => this._props.rotation; render() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 0ded01c80..3cf40c087 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -43,6 +43,7 @@ import { ObserverJsxParser } from '../ObservableReactComponent'; import { PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProp'; import { ViewBoxInterface } from '../ViewBoxInterface'; +import { GroupActive } from './CollectionFreeFormDocumentView'; import { DocumentContentsView } from './DocumentContentsView'; import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; @@ -153,7 +154,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document @computed get disableClickScriptFunc() { const onScriptDisable = this._props.onClickScriptDisable ?? this._componentView?.onClickScriptDisable?.() ?? this.layoutDoc.onClickScriptDisable; - return (DocumentView.LongPress || + return (SnappingManager.LongPress || onScriptDisable === 'always' || (onScriptDisable !== 'never' && (this.rootSelected() || this._componentView?.isAnyChildContentActive?.()))); // prettier-ignore } @@ -297,17 +298,15 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document e.stopPropagation(); }; onClick = action((e: React.MouseEvent | React.PointerEvent) => { - if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return; - const documentView = this._docView; - if (documentView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) { + if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return; + if (this._docView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) { let stopPropagate = true; let preventDefault = true; - !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document); const scriptProps = { this: this.Document, _readOnly_: false, scriptContext: this._props.scriptContext, - documentView, + documentView: this._docView, clientX: e.clientX, clientY: e.clientY, shiftKey: e.shiftKey, @@ -317,44 +316,39 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document }; if (this._doubleTap) { const defaultDblclick = this._props.defaultDoubleClick?.() || this.Document.defaultDoubleClick; - if (this.onDoubleClickHdlr?.script) { - UndoManager.RunInBatch(() => this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title); - } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') { - UndoManager.RunInBatch(() => this._props.addDocTab(this.Document, OpenWhere.lightboxAlways), 'double tap'); - DocumentView.DeselectAll(); - Doc.UnBrushDoc(this.Document); - } else { - this._singleClickFunc?.(); - } + undoable(() => { + if (this.onDoubleClickHdlr?.script) { + this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false); + } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') { + this._props.addDocTab(this.Document, OpenWhere.lightboxAlways); + DocumentView.DeselectAll(); + Doc.UnBrushDoc(this.Document); + } else this._singleClickFunc?.(); + }, 'on double click: ' + this.Document.title)(); this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout); this._doubleClickTimeout = undefined; this._singleClickFunc = undefined; } else { - let clickFunc: undefined | (() => any); - if (!this.disableClickScriptFunc && this.onClickHdlr?.script) { - clickFunc = undoable(() => { - this.onClickHdlr?.script.run(scriptProps, console.log).result?.select && this._props.select(false); - }, 'click ' + this.Document.title); - } else { - // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part - if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) { - stopPropagate = false; - } - preventDefault = false; - } - const sendToBack = e.altKey ? () => documentView._props.bringToFront?.(this.Document, true) : undefined; + const sendToBack = e.altKey ? () => this._props.bringToFront?.(this.Document, true) : undefined; const selectFunc = () => { + !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document); // selecting a view that is part of a template proxies the selection back to the root of the template const templateRoot = !(e.ctrlKey || e.button > 0) && this._props.docViewPath?.().reverse().find(dv => !dv._props.TemplateDataDocument); // prettier-ignore (templateRoot || this._docView)?.select(e.ctrlKey || e.shiftKey, e.metaKey); }; - this._singleClickFunc = clickFunc ?? sendToBack ?? selectFunc; - const waitFordblclick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; - if ((clickFunc && waitFordblclick !== 'never') || waitFordblclick === 'always') { + const clickFunc = this.onClickFunc?.()?.script ? () => (this.onClickFunc?.()?.script.run(scriptProps, console.log).result as Opt<{ select: boolean }>)?.select && this._props.select(false) : undefined; + if (!clickFunc) { + // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part + if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) stopPropagate = false; + preventDefault = false; + } + this._singleClickFunc = undoable(clickFunc ?? sendToBack ?? selectFunc, 'click: ' + this.Document.title); + const waitForDblClick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; + if ((clickFunc && waitForDblClick !== 'never') || waitForDblClick === 'always') { this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout); this._doubleClickTimeout = setTimeout(this._singleClickFunc, 300); // eslint-disable-next-line no-use-before-define - } else if (!DocumentView.LongPress) { + } else if (!SnappingManager.LongPress) { this._singleClickFunc(); this._singleClickFunc = undefined; } @@ -365,9 +359,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document }); onPointerDown = (e: React.PointerEvent): void => { - if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return; + if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return; // eslint-disable-next-line no-use-before-define - this._longPressSelector = setTimeout(() => DocumentView.LongPress && this._props.select(false), 1000); + this._longPressSelector = setTimeout(() => SnappingManager.LongPress && this._props.select(false), 1000); if (!DocumentView.DownDocView) DocumentView.DownDocView = this._docView; this._downX = e.clientX; @@ -418,7 +412,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (!this.isContentActive()) this._lastTap = Date.now(); // don't want to process the start of a double tap if the doucment is selected } // eslint-disable-next-line no-use-before-define - if (DocumentView.LongPress) e.preventDefault(); + if (SnappingManager.LongPress) e.preventDefault(); }; toggleFollowLink = undoable((): void => { @@ -1124,7 +1118,6 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { @observable private _htmlOverlayText: Opt<string> = undefined; @observable private _isHovering = false; @observable private _selected = false; - @observable public static LongPress = false; @computed private get shouldNotScale() { return (this.layout_fitWidth && !this.nativeWidth) || this.ComponentView?.isUnstyledView?.(); |