diff options
author | bobzel <zzzman@gmail.com> | 2024-01-24 16:13:27 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-01-24 16:13:27 -0500 |
commit | c8be94244bcd094efba739e5a46034bceccea80f (patch) | |
tree | fa9648c3ecad6f9725173f0847d4ab0c26af234c /src | |
parent | af380979349308077e13fc12a2d09255b7f05f28 (diff) |
several fixes to drag/drop so that dropAction's set on target work for tree views, notetaking, formattedText, etc. make bringToFront an optional prop.
Diffstat (limited to 'src')
49 files changed, 138 insertions, 160 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bcc016391..2cbc90387 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -259,6 +259,7 @@ export class DocumentOptions { _layout_showCaption?: string; // which field to display in the caption area. leave empty to have no caption _chromeHidden?: BOOLt = new BoolInfo('whether the editing chrome for a document is hidden'); + hideClickBehaviors?: BOOLt = new BoolInfo('whether to hide click behaviors in context menu'); _gridGap?: NUMt = new NumInfo('gap between items in masonry view', false); _xMargin?: NUMt = new NumInfo('gap between left edge of document and start of masonry/stacking layouts', false); _yMargin?: NUMt = new NumInfo('gap between top edge of dcoument and start of masonry/stacking layouts', false); @@ -658,7 +659,7 @@ export namespace Docs { DocumentType.PRES, { layout: { view: PresBox, dataField: defaultDataKey }, - options: { defaultDoubleClick: 'ignore', layout_hideLinkAnchors: true }, + options: { defaultDoubleClick: 'ignore', hideClickBehaviors: true, layout_hideLinkAnchors: true }, }, ], [ diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 70c40c54e..a6ad0f1b3 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -181,7 +181,7 @@ export namespace DragManager { } }; - export function MakeDropTarget(element: HTMLElement, dropFunc: (e: Event, de: DropEvent) => void, doc?: Doc, preDropFunc?: (e: Event, de: DropEvent, targetAction: dropActionType) => void): DragDropDisposer { + export function MakeDropTarget(element: HTMLElement, dropFunc: (e: Event, de: DropEvent) => void, doc: Doc, preDropFunc?: (e: Event, de: DropEvent, targetAction: dropActionType) => void): DragDropDisposer { if ('canDrop' in element.dataset) { throw new Error("Element is already droppable, can't make it droppable again"); } @@ -189,13 +189,13 @@ export namespace DragManager { const handler = (e: Event) => dropFunc(e, (e as CustomEvent<DropEvent>).detail); const preDropHandler = (e: Event) => { const de = (e as CustomEvent<DropEvent>).detail; - (preDropFunc ?? defaultPreDropFunc)(e, de, StrCast(doc?.dropAction) as dropActionType); + (preDropFunc ?? defaultPreDropFunc)(e, de, StrCast(doc.dropAction) as dropActionType); }; element.addEventListener('dashOnDrop', handler); - doc && element.addEventListener('dashPreDrop', preDropHandler); + element.addEventListener('dashPreDrop', preDropHandler); return () => { element.removeEventListener('dashOnDrop', handler); - doc && element.removeEventListener('dashPreDrop', preDropHandler); + element.removeEventListener('dashPreDrop', preDropHandler); delete element.dataset.canDrop; }; } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 0e5a4f013..e7469a37c 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -172,7 +172,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() { } @action.bound - removeDocument(doc: Doc | Doc[], annotationKey?: string, leavePushpin?: boolean): boolean { + removeDocument(doc: Doc | Doc[], annotationKey?: string, leavePushpin?: boolean, dontAddToRemoved?: boolean): boolean { const effectiveAcl = GetEffectiveAcl(this.dataDoc); const indocs = doc instanceof Doc ? [doc] : doc; const docs = indocs.filter(doc => [AclEdit, AclAdmin].includes(effectiveAcl) || GetEffectiveAcl(doc) === AclAdmin); @@ -189,7 +189,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() { Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc); Doc.RemoveDocFromList(doc[DocData], 'proto_embeddings', doc); doc.embedContainer = undefined; - if (recent) { + if (recent && !dontAddToRemoved) { doc.type !== DocumentType.LOADING && Doc.AddDocToList(recent, 'data', doc, undefined, true, true); } }); @@ -214,7 +214,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() { } const first = doc instanceof Doc ? doc : doc[0]; if (!first?._dragOnlyWithinContainer && addDocument !== returnFalse) { - return this.removeDocument(doc, annotationKey, false) && addDocument(doc, annotationKey); + return this.removeDocument(doc, annotationKey, false, true) && addDocument(doc, annotationKey); } return false; }; diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 3c7b5eeca..86b9f5e40 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -479,7 +479,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil containerViewPath={returnEmptyDoclist} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFiltersByRanges={returnEmptyFilter} childFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 530fd3121..c7ff7ce47 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -266,7 +266,6 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> { whenChildContentsActiveChanged={emptyFunction} addDocTab={this.AddDocTab} pinToPres={TabDocView.PinDoc} - bringToFront={emptyFunction} onBrowseClickScript={DocumentView.exploreMode} focus={emptyFunction} /> diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9061e98d4..eca0aca4c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -632,7 +632,6 @@ export class MainView extends ObservableReactComponent<{}> { renderDepth={0} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} @@ -661,7 +660,6 @@ export class MainView extends ObservableReactComponent<{}> { PanelHeight={this.mainDocViewHeight} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} @@ -756,7 +754,6 @@ export class MainView extends ObservableReactComponent<{}> { isContentActive={returnTrue} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} @@ -785,7 +782,6 @@ export class MainView extends ObservableReactComponent<{}> { styleProvider={DefaultStyleProvider} isContentActive={returnTrue} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} @@ -913,7 +909,6 @@ export class MainView extends ObservableReactComponent<{}> { fieldKey="data" dropAction="embed" styleProvider={DefaultStyleProvider} - bringToFront={emptyFunction} select={emptyFunction} isAnyChildContentActive={returnFalse} isContentActive={emptyFunction} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 89527c415..20dc6c9fa 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -221,7 +221,6 @@ export class OverlayView extends ObservableReactComponent<{}> { style={{ top: d.type === DocumentType.PRES ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.overlayX}px, ${d.overlayY}px)` }}> <DocumentView Document={d} - bringToFront={emptyFunction} addDocument={undefined} removeDocument={this.removeOverlayDoc} PanelWidth={d[Width]} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 952c8f0b4..208ed56c9 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -319,7 +319,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps whenChildContentsActiveChanged={emptyFunction} addDocTab={returnFalse} pinToPres={emptyFunction} - bringToFront={returnFalse} dontRegisterView={true} /> </div> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 2aba439c8..58f9784d4 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -259,7 +259,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & if (opacity() === 0) return 'none'; if (props?.isGroupActive?.() ) return isInk() ? 'visiblePainted': (doc?. isGroup )? undefined: 'all' - if (props?.isDocumentActive?.() && !props.treeViewDoc) return isInk() ? 'visiblePainted' : 'all'; + if (props?.isDocumentActive?.()) return isInk() ? 'visiblePainted' : 'all'; return undefined; // fixes problem with tree view elements getting pointer events when the tree view is not active case StyleProp.Decorations: const lock = () => doc?.pointerEvents !== 'none' ? null : ( diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index ba7120b93..5fc33207e 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -123,7 +123,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { onChildClick={this.scriptField} isAnyChildContentActive={returnFalse} isContentActive={returnTrue} - bringToFront={emptyFunction} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} ScreenToLocalTransform={Transform.Identity} diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 2d2cb4860..7e484f3df 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Utils, returnFalse, returnZero } from '../../../Utils'; +import { Utils, emptyFunction, returnFalse, returnZero } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; @@ -81,7 +81,6 @@ export class CollectionCarousel3DView extends CollectionSubView() { isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} PanelWidth={this.panelWidth} PanelHeight={this.panelHeight} - bringToFront={returnFalse} /> ); }; diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 79f5baabe..dbe1536f2 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -78,7 +78,6 @@ export class CollectionCarouselView extends CollectionSubView() { Document={curDoc.layout} TemplateDataDocument={DocCast(curDoc.layout.resolvedDataDoc)} PanelHeight={this.panelHeight} - bringToFront={returnFalse} /> </div> {!carouselShowsCaptions ? null : ( diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 8627ba650..41c5d5b42 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -71,7 +71,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF if (ele) { this._ele = ele; this._props.observeHeight(ele); - this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this)); + this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this), this._props.Document); } }; @action diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 2dad377e0..0f90818ef 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -93,7 +93,6 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { fieldKey="data" dropAction="embed" styleProvider={DefaultStyleProvider} - bringToFront={emptyFunction} select={emptyFunction} isContentActive={returnTrue} isAnyChildContentActive={returnFalse} diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index e6ce5baab..3a9892ed0 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -270,7 +270,6 @@ export class CollectionNoteTakingView extends CollectionSubView() { contentPointerEvents={StrCast(this.layoutDoc.contentPointerEvents) as any} whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} addDocTab={this._props.addDocTab} - bringToFront={returnFalse} pinToPres={this._props.pinToPres} /> ); diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index 3f6d3c82e..38846c79d 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -81,7 +81,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV if (ele) { this._ele = ele; this._props.observeHeight(ele); - this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this)); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); } }; @@ -90,11 +90,11 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV } @undoBatch - columnDrop = action((e: Event, de: DragManager.DropEvent) => { + columnDrop = (e: Event, de: DragManager.DropEvent) => { const drop = { docs: de.complete.docDragData?.droppedDocuments, val: this.getValue(this._heading) }; drop.docs?.forEach(d => Doc.SetInPlace(d, this._props.pivotField, drop.val, false)); return true; - }); + }; getValue = (value: string): any => { const parsed = parseInt(value); diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 1394e62ba..5c47d4b9e 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -847,7 +847,6 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch onDoubleClickScript={this._props.layoutDoc.autoPlayAnchors ? undefined : doublescript} ignoreAutoHeight={false} hideResizeHandles={true} - bringToFront={emptyFunction} contextMenuItems={this.contextMenuItems} /> ), diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 0da32a9e0..d436d3c2f 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -358,7 +358,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection contentPointerEvents={StrCast(this.layoutDoc.contentPointerEvents) as any} whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} addDocTab={this._props.addDocTab} - bringToFront={returnFalse} pinToPres={this._props.pinToPres} /> ); @@ -682,7 +681,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection styleProvider={this._props.styleProvider} containerViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={this._props.childFilters} childFiltersByRanges={this._props.childFiltersByRanges} searchFilterDocs={this._props.searchFilterDocs} diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 69f1c332d..c455f20d8 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -74,7 +74,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< if (ele) { this._ele = ele; this._props.observeHeight(ele); - this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this)); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); } }; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 0aa74aaba..fdbd1cc90 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -196,10 +196,8 @@ export function CollectionSubView<X>(moreProps?: X) { @undoBatch protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {} - protected onInternalPreDrop(e: Event, de: DragManager.DropEvent) { + protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, dropAction: dropActionType) { if (de.complete.docDragData) { - // override the dropEvent's dropAction - const dropAction = this.layoutDoc.dropAction as dropActionType; // if the dropEvent's dragAction is, say 'embed', but we're just dragging within a collection, we may not actually want to make an embedding. // so we check if our collection has a dropAction set on it and if so, we use that instead. if (dropAction && !de.complete.docDragData.draggedDocuments.some(d => d.embedContainer === this.Document && this.childDocs.includes(d))) { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4696d7948..cc2cf87aa 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -140,15 +140,11 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree if ((this._mainEle = ele)) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.Document, this.onInternalPreDrop.bind(this)); }; - protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent) => { - const dropAction = this.layoutDoc.dropAction as dropActionType; + protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, dropAction: dropActionType) => { const dragData = de.complete.docDragData; if (dragData) { const sameTree = Doc.AreProtosEqual(dragData.treeViewDoc, this.Document) ? true : false; const isAlreadyInTree = () => sameTree || dragData.draggedDocuments.some(d => d.embedContainer === this.Document && this.childDocs.includes(d)); - if (isAlreadyInTree() !== sameTree) { - console.log('WHAAAT'); - } dragData.dropAction = dropAction && !isAlreadyInTree() ? dropAction : sameTree && dragData.dropAction !== 'inSame' ? 'same' : dragData.dropAction; e.stopPropagation(); } @@ -254,7 +250,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree moveDocument={returnFalse} removeDocument={returnFalse} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} - bringToFront={returnFalse} /> ); } @@ -349,7 +344,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree styleProvider={this._props.styleProvider} containerViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={this._props.childFilters} childFiltersByRanges={this._props.childFiltersByRanges} searchFilterDocs={this._props.searchFilterDocs} @@ -453,14 +447,13 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree pointerEvents={this._props.isContentActive() && SnappingManager.IsDragging ? returnAll : returnNone} isAnnotationOverlay={true} isAnnotationOverlayScrollable={true} - childDocumentsActive={this._props.isDocumentActive} + childDocumentsActive={this._props.isContentActive} fieldKey={this._props.fieldKey + '_annotations'} dropAction="move" select={emptyFunction} addDocument={this.addAnnotationDocument} removeDocument={this.remAnnotationDocument} moveDocument={this.moveAnnotationDocument} - bringToFront={emptyFunction} renderDepth={this._props.renderDepth + 1}> {this.content} </CollectionFreeFormView> diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 26ff5cc06..6cef469b6 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -189,7 +189,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'hand-point-right' }); - if (!Doc.noviceMode && !this.Document.annotationOn) { + if (!Doc.noviceMode && !this.Document.annotationOn && !this.Document.hideClickBehaviors) { const existingOnClick = cm.findByDescription('OnClick...'); const onClicks = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : []; const funcs = [ diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index da15f8dc5..9bc3ef822 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -470,7 +470,6 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> { whenChildContentsActiveChanged={this.whenChildContentActiveChanges} focus={this.focusFunc} containerViewPath={returnEmptyDoclist} - bringToFront={emptyFunction} pinToPres={TabDocView.PinDoc} /> {this.disableMinimap() ? null : <TabMinimapView key="minimap" addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />} @@ -604,7 +603,6 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps isSelected={returnFalse} dontRegisterView={true} fieldKey={Doc.LayoutFieldKey(this._props.document)} - bringToFront={emptyFunction} addDocument={returnFalse} moveDocument={returnFalse} removeDocument={returnFalse} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 38a2fe978..40933321f 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -4,7 +4,7 @@ import { IconButton, Size } from 'browndash-components'; import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Utils, emptyFunction, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick } from '../../../Utils'; +import { Utils, emptyFunction, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../Utils'; import { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -282,12 +282,13 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { _treeEle: any; protected createTreeDropTarget = (ele: HTMLDivElement) => { this._treedropDisposer?.(); - ele && ((this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this))), this.Document); + ele && ((this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), this.Document, this.preTreeDrop.bind(this))), this.Document); if (this._treeEle) this._props.unobserveHeight(this._treeEle); this._props.observeHeight((this._treeEle = ele)); }; componentWillUnmount() { + this._treedropDisposer?.(); this._renderTimer && clearTimeout(this._renderTimer); Object.values(this._disposers).forEach(disposer => disposer?.()); this._treeEle && this._props.unobserveHeight(this._treeEle); @@ -339,11 +340,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const before = pt[1] < rect.top + rect.height / 2; const inside = pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length); this._header.current!.className = 'treeView-header'; - if (!this.treeView.outlineMode || DragManager.DocDragData?.treeViewDoc === this.treeView.Document) { - if (inside) this._header.current!.className += ' treeView-header-inside'; - else if (before) this._header.current!.className += ' treeView-header-above'; - else if (!before) this._header.current!.className += ' treeView-header-below'; - } + if (inside) this._header.current!.className += ' treeView-header-inside'; + else if (before) this._header.current!.className += ' treeView-header-above'; + else if (!before) this._header.current!.className += ' treeView-header-below'; e.stopPropagation(); }; @@ -387,9 +386,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { return this._props.addDocument(folder); }; - preTreeDrop = (e: Event, de: DragManager.DropEvent) => { - const dragData = de.complete.docDragData; - dragData && (dragData.dropAction = this.treeView.Document === dragData.treeViewDoc ? 'same' : dragData.dropAction); + preTreeDrop = (e: Event, de: DragManager.DropEvent, docDropAction: dropActionType) => { + // fall through and let the CollectionTreeView handle this since treeView items have no special properties of their own }; @undoBatch @@ -416,7 +414,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { docDragData.dropAction, docDragData.removeDocument, docDragData.moveDocument, - docDragData.treeViewDoc === this.treeView.Document + docDragData.treeViewDoc === this.treeView.Document, + de.embedKey ); e.stopPropagation(); !added && e.preventDefault(); @@ -426,7 +425,16 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { }; dropping: boolean = false; - dropDocuments(droppedDocuments: Doc[], before: boolean, inside: number | boolean, dropAction: dropActionType, removeDocument: DragManager.RemoveFunction | undefined, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean) { + dropDocuments( + droppedDocuments: Doc[], + before: boolean, + inside: number | boolean, + dropAction: dropActionType, + removeDocument: DragManager.RemoveFunction | undefined, + moveDocument: DragManager.MoveFunction | undefined, + forceAdd: boolean, + canEmbed?: boolean + ) { const parentAddDoc = (doc: Doc | Doc[]) => this._props.addDocument(doc, undefined, undefined, before); const localAdd = (doc: Doc | Doc[]) => { const innerAdd = (doc: Doc) => { @@ -438,9 +446,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); }; const addDoc = inside ? localAdd : parentAddDoc; - const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same' || dropAction === 'inSame') && moveDocument; const canAdd = (!this.treeView.outlineMode && !StrCast((inside ? this.Document : this._props.treeViewParent)?.treeView_FreezeChildren).includes('add')) || forceAdd; if (canAdd && (dropAction !== 'inSame' || droppedDocuments.every(d => d.embedContainer === this._props.parentTreeView?.Document))) { + const move = (!dropAction || canEmbed || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same' || dropAction === 'inSame') && moveDocument; this._props.parentTreeView instanceof TreeView && (this._props.parentTreeView.dropping = true); const res = droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false); this._props.parentTreeView instanceof TreeView && (this._props.parentTreeView.dropping = false); @@ -602,7 +610,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { docs.sort((a, b) => (NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1)).forEach((d, i) => (d.zIndex = i)); } const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField; - const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); + const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false); !dataIsComputed && added && Doc.SetContainer(doc, this.Document); return added; @@ -841,7 +849,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { ? folderOp : Doc.IsSystem(this.Document) ? [] - : this.treeView.fileSysMode && this.Document === Doc.GetProto(this.Document) + : this.treeView.fileSysMode && this.Document === this.Document[DocData] ? [openEmbedding, makeFolder] : this.Document._type_collection === CollectionViewType.Docking ? [] @@ -974,8 +982,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { Document={this.Document} layout_fitWidth={returnTrue} scriptContext={this} - hideDecorationTitle={this.treeView.outlineMode} - hideResizeHandles={this.treeView.outlineMode} + hideDecorations={true} + hideClickBehaviors={true} styleProvider={this.titleStyleProvider} onClickScriptDisable="never" // tree docViews have a script to show fields, etc. containerViewPath={this.treeView.childContainerViewPath} @@ -999,7 +1007,6 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { isDocumentActive={this._props.isContentActive} focus={this.refocus} whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} - bringToFront={emptyFunction} disableBrushing={this.treeView._props.disableBrushing} hideLinkButton={BoolCast(this.treeView.Document.childHideLinkButton)} dontRegisterView={BoolCast(this.treeView.Document.childDontRegisterViews, this._props.dontRegisterView)} @@ -1041,7 +1048,19 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { key="titleheader" ref={this._header} onClick={this.ignoreEvent} - onPointerDown={this.ignoreEvent} + onPointerDown={e => { + this.treeView.isContentActive() && + setupMoveUpEvents( + this, + e, + () => { + this._dref?.startDragging(e.clientX, e.clientY, '' as any); + return true; + }, + returnFalse, + emptyFunction + ); + }} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> <div @@ -1073,22 +1092,22 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { isContentActive={isActive} isDocumentActive={isActive} styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider} - hideTitle={asText} fitContentsToBox={returnTrue} - hideDecorationTitle={this.treeView.outlineMode} - hideResizeHandles={this.treeView.outlineMode} - onClickScript={this.onChildClick} - focus={this.refocus} - onKey={this.onKeyDown} + hideTitle={asText} + hideDecorations={true} + hideClickBehaviors={true} hideLinkButton={BoolCast(this.treeView.Document.childHideLinkButton)} dontRegisterView={BoolCast(this.treeView.Document.childDontRegisterViews, this._props.dontRegisterView)} ScreenToLocalTransform={this.docTransform} renderDepth={this._props.renderDepth + 1} + onClickScript={this.onChildClick} + onKey={this.onKeyDown} treeViewDoc={this.treeView?.Document} containerViewPath={this.treeView.childContainerViewPath} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} + focus={this.refocus} addDocument={this._props.addDocument} moveDocument={this.move} removeDocument={this._props.removeDoc} @@ -1098,7 +1117,6 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { addDocTab={this._props.addDocTab} pinToPres={this.treeView._props.pinToPres} disableBrushing={this.treeView._props.disableBrushing} - bringToFront={returnFalse} scriptContext={this} /> </div> @@ -1143,7 +1161,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const before = pt[1] < rect.top + rect.height / 2; const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false); - const docs = this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, undefined, false)); + const docs = this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, undefined, false, false)); }; render() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7203041e0..53dc389b4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1243,7 +1243,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection pinToPres={this._props.pinToPres} whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} dragAction={(this.Document.childDragAction ?? this._props.childDragAction) as dropActionType} - bringToFront={this.bringToFront} layout_showTitle={this._props.childlayout_showTitle} dontRegisterView={this._props.dontRegisterView} pointerEvents={this.childPointerEventsFunc} diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index 72bdb9b6b..228af78aa 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -79,16 +79,16 @@ export class CollectionLinearView extends CollectionSubView() { @action changeDescriptionSetting = () => { - if (LinkDescriptionPopup.showDescriptions) { - if (LinkDescriptionPopup.showDescriptions === 'ON') { - LinkDescriptionPopup.showDescriptions = 'OFF'; - LinkDescriptionPopup.descriptionPopup = false; + if (LinkDescriptionPopup.Instance.showDescriptions) { + if (LinkDescriptionPopup.Instance.showDescriptions === 'ON') { + LinkDescriptionPopup.Instance.showDescriptions = 'OFF'; + LinkDescriptionPopup.Instance.display = false; } else { - LinkDescriptionPopup.showDescriptions = 'ON'; + LinkDescriptionPopup.Instance.showDescriptions = 'ON'; } } else { - LinkDescriptionPopup.showDescriptions = 'OFF'; - LinkDescriptionPopup.descriptionPopup = false; + LinkDescriptionPopup.Instance.showDescriptions = 'OFF'; + LinkDescriptionPopup.Instance.display = false; } }; @@ -110,7 +110,7 @@ export class CollectionLinearView extends CollectionSubView() { <Tooltip title={<div className="dash-tooltip">{'Toggle description pop-up'} </div>} placement="top"> <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}> - Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : 'ON'} + Labels: {LinkDescriptionPopup.Instance.showDescriptions ? LinkDescriptionPopup.Instance.showDescriptions : 'ON'} </span> </Tooltip> @@ -191,7 +191,6 @@ export class CollectionLinearView extends CollectionSubView() { styleProvider={this._props.styleProvider} containerViewPath={this.childContainerViewPath} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={this._props.childFilters} childFiltersByRanges={this._props.childFiltersByRanges} searchFilterDocs={this._props.searchFilterDocs} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 1fa106b45..b181b59ce 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -4,7 +4,7 @@ import { Button } from 'browndash-components'; import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { returnFalse } from '../../../../Utils'; +import { emptyFunction, returnFalse } from '../../../../Utils'; import { Doc, DocListCast } from '../../../../fields/Doc'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { DragManager, dropActionType } from '../../../util/DragManager'; @@ -287,7 +287,6 @@ export class CollectionMulticolumnView extends CollectionSubView() { whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} addDocTab={this._props.addDocTab} pinToPres={this._props.pinToPres} - bringToFront={returnFalse} dontCenter={StrCast(this.layoutDoc.layout_dontCenter) as any} // 'y', 'x', 'xy' /> ); diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 97a444b8c..659f7ccdc 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -1,7 +1,7 @@ import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { returnFalse } from '../../../../Utils'; +import { emptyFunction, returnFalse } from '../../../../Utils'; import { Doc, DocListCast } from '../../../../fields/Doc'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { DragManager, dropActionType } from '../../../util/DragManager'; @@ -281,7 +281,6 @@ export class CollectionMultirowView extends CollectionSubView() { whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} addDocTab={this._props.addDocTab} pinToPres={this._props.pinToPres} - bringToFront={returnFalse} dontCenter={StrCast(this.layoutDoc.layout_dontCenter) as any} // 'y', 'x', 'xy' /> ); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ec91b25f8..581425d77 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -914,7 +914,6 @@ export class CollectionSchemaView extends CollectionSubView() { whenChildContentsActiveChanged={returnFalse} addDocTab={this._props.addDocTab} pinToPres={this._props.pinToPres} - bringToFront={returnFalse} /> )} </div> @@ -989,7 +988,6 @@ class CollectionSchemaViewDoc extends ObservableReactComponent<CollectionSchemaV searchFilterDocs={this._props.schema.searchFilterDocs} rootSelected={this._props.schema.rootSelected} ScreenToLocalTransform={this.screenToLocalXf} - bringToFront={emptyFunction} dragWhenActive={true} isDocumentActive={this._props.schema._props.childDocumentsActive?.() ? this._props.schema._props.isDocumentActive : this._props.schema.isContentActive} isContentActive={emptyFunction} diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index fda5764dd..dbaa6e110 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -82,7 +82,6 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro setHeight: returnFalse, select: emptyFunction, dragAction: 'move', - bringToFront: emptyFunction, renderDepth: 1, isContentActive: returnFalse, whenChildContentsActiveChanged: emptyFunction, diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index 31841c596..c9e3c203d 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -7,7 +7,7 @@ import { Doc } from '../../../fields/Doc'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { DefaultStyleProvider } from '../StyleProvider'; -import { OpenWhere } from '../nodes/DocumentView'; +import { OpenWhere, returnEmptyDocViewList } from '../nodes/DocumentView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { SearchBox } from '../search/SearchBox'; import './LinkPopup.scss'; @@ -61,6 +61,7 @@ export class LinkPopup extends React.Component<LinkPopupProps> { <SearchBox Document={Doc.MySearcher} + docViewPath={returnEmptyDocViewList} linkFrom={linkDoc} linkCreateAnchor={this.props.linkCreateAnchor} linkSearch={true} @@ -81,7 +82,6 @@ export class LinkPopup extends React.Component<LinkPopupProps> { renderDepth={0} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx index ed575c329..12b9870ca 100644 --- a/src/client/views/newlightbox/NewLightboxView.tsx +++ b/src/client/views/newlightbox/NewLightboxView.tsx @@ -311,7 +311,6 @@ export class NewLightboxView extends React.Component<LightboxViewProps> { whenChildContentsActiveChanged={emptyFunction} addDocTab={this.addDocTab} pinToPres={TabDocView.PinDoc} - bringToFront={emptyFunction} onBrowseClickScript={DocumentView.exploreMode} focus={emptyFunction} /> diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 2b71fd156..8a38ef663 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -568,8 +568,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { const [xp, yp] = this.ScreenToLocalBoxXf().transformPoint(de.x, de.y); de.complete.docDragData && this.timeline?.internalDocDrop(e, de, de.complete.docDragData, xp); }, - this.layoutDoc, - undefined + this.layoutDoc ); } }; @@ -718,7 +717,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { renderDepth={this._props.renderDepth + 1} startTag={'_timecodeToShow' /* audioStart */} endTag={'_timecodeToHide' /* audioEnd */} - bringToFront={emptyFunction} playFrom={this.playFrom} setTime={this.setPlayheadTime} playing={this.playing} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 9538cebb2..d1e141061 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -150,6 +150,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte // these are the properties in DocumentViewProps that need to be removed to pass on only DocumentSharedViewProps to the FieldViews 'hideResizeHandles', 'hideTitle', + 'bringToFront', 'contentPointerEvents', 'LayoutTemplateString', 'LayoutTemplate', diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3e5e43b47..76ad29f60 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -255,17 +255,17 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document { fireImmediately: true } ); } - preDropFunc = (e: Event, de: DragManager.DropEvent) => { - const dropAction = this.layoutDoc.dropAction as dropActionType; - if (de.complete.docDragData && this.isContentActive() && !this._props.treeViewDoc) { - dropAction && (de.complete.docDragData.dropAction = dropAction); + preDrop = (e: Event, de: DragManager.DropEvent, dropAction: dropActionType) => { + const dragData = de.complete.docDragData; + if (dragData && this.isContentActive() && !this.props.dontRegisterView) { + dragData.dropAction = dropAction ? dropAction : dragData.dropAction; e.stopPropagation(); } }; setupHandlers() { this.cleanupHandlers(false); if (this._mainCont.current) { - this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.Document, this.preDropFunc); + this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.Document, this.preDrop); } } @@ -311,7 +311,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (documentView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && Utils.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); + !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document); if (this._doubleTap) { const defaultDblclick = this._props.defaultDoubleClick?.() || this.Document.defaultDoubleClick; if (this.onDoubleClickHandler?.script) { @@ -375,7 +375,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document const sendToBack = e.altKey; this._singleClickFunc = // prettier-ignore - clickFunc ?? (() => (sendToBack ? documentView._props.bringToFront(this.Document, true) : + clickFunc ?? (() => (sendToBack ? documentView._props.bringToFront?.(this.Document, true) : this._componentView?.select?.(e.ctrlKey || e.metaKey, e.shiftKey) ?? this._props.select(e.ctrlKey||e.shiftKey, e.metaKey))); const waitFordblclick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; @@ -610,40 +610,38 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document !Doc.noviceMode && templateDoc && appearanceItems.push({ description: 'Open Template ', event: () => this._props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); !appearance && appearanceItems.length && cm.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'compass' }); - if (!Doc.IsSystem(this.Document) && this.Document.type !== DocumentType.PRES && ![CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._type_collection as any)) { + if (this._props.bringToFront) { + const zorders = cm.findByDescription('ZOrder...'); + const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : []; + zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, false)), icon: 'arrow-up' }); + zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, true)), icon: 'arrow-down' }); + zorderItems.push({ + description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged', + event: undoBatch(action(() => (this.layoutDoc._keepZWhenDragged = !this.layoutDoc._keepZWhenDragged))), + icon: 'hand-point-up', + }); + !zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'layer-group' }); + } + + if (!Doc.IsSystem(this.Document) && !this.Document.hideClickBehaviors && !this._props.hideClickBehaviors) { const existingOnClick = cm.findByDescription('OnClick...'); const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : []; - if (this._props.bringToFront !== emptyFunction) { - const zorders = cm.findByDescription('ZOrder...'); - const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : []; - zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront(dv.Document, false)), icon: 'arrow-up' }); - zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront(dv.Document, true)), icon: 'arrow-down' }); - zorderItems.push({ - description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged', - event: undoBatch(action(() => (this.layoutDoc._keepZWhenDragged = !this.layoutDoc._keepZWhenDragged))), - icon: 'hand-point-up', - }); - !zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'layer-group' }); - } - onClicks.push({ description: 'Enter Portal', event: this.makeIntoPortal, icon: 'window-restore' }); !Doc.noviceMode && onClicks.push({ description: 'Toggle Detail', event: this.setToggleDetail, icon: 'concierge-bell' }); - if (!this._props.treeViewDoc) { - if (!this.Document.annotationOn) { - const options = cm.findByDescription('Options...'); - const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : []; - !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' }); - - onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' }); - !Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); - !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); - } else if (LinkManager.Links(this.Document).length) { - onClicks.push({ description: 'Restore On Click default', event: () => this.noOnClick(), icon: 'link' }); - onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(), icon: 'link' }); - !existingOnClick && cm.addItem({ description: 'OnClick...', subitems: onClicks, icon: 'mouse-pointer' }); - } + if (!this.Document.annotationOn) { + const options = cm.findByDescription('Options...'); + const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : []; + !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' }); + + onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' }); + !Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); + !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); + } else if (LinkManager.Links(this.Document).length) { + onClicks.push({ description: 'Restore On Click default', event: () => this.noOnClick(), icon: 'link' }); + onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(), icon: 'link' }); + !existingOnClick && cm.addItem({ description: 'OnClick...', subitems: onClicks, icon: 'mouse-pointer' }); } } @@ -727,8 +725,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/dataViz/'; break; } - // Add link to help documentation - if (!this._props.treeViewDoc && documentationDescription && documentationLink) { + // Add link to help documentation (unless the doc contents have been overriden in which case the documentation isn't relevant) + if (!this.docContents && documentationDescription && documentationLink) { helpItems.push({ description: documentationDescription, event: () => window.open(documentationLink, '_blank'), @@ -996,12 +994,11 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document TraceMobx(); const highlighting = this.highlighting; const borderPath = this.borderPath; - const boxShadow = - this._props.treeViewDoc || !highlighting - ? this.boxShadow - : highlighting && this.borderRounding && highlighting.highlightStyle !== 'dashed' - ? `0 0 0 ${highlighting.highlightIndex}px ${highlighting.highlightColor}` - : this.boxShadow || (this.Document.isTemplateForField ? 'black 0.2vw 0.2vw 0.8vw' : undefined); + const boxShadow = !highlighting + ? this.boxShadow + : highlighting && this.borderRounding && highlighting.highlightStyle !== 'dashed' + ? `0 0 0 ${highlighting.highlightIndex}px ${highlighting.highlightColor}` + : this.boxShadow || (this.Document.isTemplateForField ? 'black 0.2vw 0.2vw 0.8vw' : undefined); const renderDoc = this.renderDoc({ borderRadius: this.borderRounding, outline: highlighting && !this.borderRounding && !highlighting.highlightStroke ? `${highlighting.highlightColor} ${highlighting.highlightStyle} ${highlighting.highlightIndex}px` : 'solid 0px', @@ -1219,7 +1216,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { } @computed get getBounds() { - if (!this._docViewInternal?._contentDiv || this._props.treeViewDoc || Doc.AreProtosEqual(this.Document, Doc.UserDoc())) { + if (!this._docViewInternal?._contentDiv || Doc.AreProtosEqual(this.Document, Doc.UserDoc())) { return undefined; } if (this._docViewInternal._componentView?.screenBounds?.()) { @@ -1282,7 +1279,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { const deiconifyLayout = Cast(this.Document.deiconifyLayout, 'string', null); this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finalFinished); this.Document.deiconifyLayout = undefined; - this._props.bringToFront(this.Document); + this._props.bringToFront?.(this.Document); } } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 5bb295565..3cf0fabc2 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -54,6 +54,7 @@ export interface FieldViewSharedProps { forceAutoHeight?: boolean; ignoreAutoHeight?: boolean; disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. + hideClickBehaviors?: boolean; // whether to suppress menu item options for changing click behaviors CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; containerViewPath?: () => DocumentView[]; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document @@ -86,7 +87,7 @@ export interface FieldViewSharedProps { moveDocument?: (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => boolean; pinToPres: (document: Doc, pinProps: PinProps) => void; ScreenToLocalTransform: () => Transform; - bringToFront: (doc: Doc, sendToBack?: boolean) => void; + bringToFront?: (doc: Doc, sendToBack?: boolean) => void; waitForDoubleClickToClick?: () => 'never' | 'always' | undefined; defaultDoubleClick?: () => 'default' | 'ignore' | undefined; pointerEvents?: () => Opt<string>; @@ -108,7 +109,6 @@ export interface FieldViewProps extends FieldViewSharedProps { // See currentUserUtils headerTemplate for examples of creating text boxes from html which set some of these fields // Also, see InkingStroke for examples of creating text boxes from render() methods which set some of these fields backgroundColor?: string; - treeViewDoc?: Doc; color?: string; height?: number; width?: number; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 2a10bd766..923aead64 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -227,7 +227,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl this._props.addDocTab(cropping, OpenWhere.inParent); } DocumentManager.Instance.AddViewRenderedCb(cropping, dv => setTimeout(() => (dv.ComponentView as ImageBox).setNativeSize(), 200)); - this._props.bringToFront(cropping); + this._props.bringToFront?.(cropping); return cropping; }; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 7c532f33f..f9e8ce4f3 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -114,7 +114,6 @@ export class KeyValuePair extends ObservableReactComponent<KeyValuePairProps> { isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, - bringToFront: emptyFunction, renderDepth: 1, isContentActive: returnFalse, whenChildContentsActiveChanged: emptyFunction, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 2d54da0ed..4b242649a 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -293,7 +293,6 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps focus={emptyFunction} whenChildContentsActiveChanged={returnFalse} ignoreAutoHeight={true} // need to ignore layout_autoHeight otherwise layout_autoHeight text boxes will expand beyond the preview panel size. - bringToFront={returnFalse} NativeWidth={Doc.NativeWidth(this._targetDoc) ? () => Doc.NativeWidth(this._targetDoc) : undefined} NativeHeight={Doc.NativeHeight(this._targetDoc) ? () => Doc.NativeHeight(this._targetDoc) : undefined} /> diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 0eb3ffc3d..1274220b6 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -134,7 +134,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem if (addCrop) { DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' }); } - this._props.bringToFront(cropping); + this._props.bringToFront?.(cropping); CreateImage( '', diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index a6c524881..40647feff 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -855,7 +855,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl renderDepth={this._props.renderDepth + 1} startTag={'_timecodeToShow' /* videoStart */} endTag={'_timecodeToHide' /* videoEnd */} - bringToFront={emptyFunction} playFrom={this.playFrom} setTime={this.setPlayheadTime} playing={this.playing} @@ -928,7 +927,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl if (addCrop) { DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' }); } - this._props.bringToFront(cropping); + this._props.bringToFront?.(cropping); return cropping; }; savedAnnotations = () => this._savedAnnotations; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 5776cf6a6..5a07540da 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -983,7 +983,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem childFilters={childFilters} select={emptyFunction} isAnyChildContentActive={returnFalse} - bringToFront={emptyFunction} styleProvider={this.childStyleProvider} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} removeDocument={this.removeDocument} diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index bc49ed23d..7335c9286 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -217,7 +217,6 @@ export class DashDocViewInternal extends ObservableReactComponent<IDashDocViewIn PanelHeight={this._dashDoc[Height]} focus={this.outerFocus} whenChildContentsActiveChanged={this._props.tbox.whenChildContentsActiveChanged} - bringToFront={emptyFunction} dontRegisterView={false} childFilters={this._props.tbox?._props.childFilters} childFiltersByRanges={this._props.tbox?._props.childFiltersByRanges} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 38400d2e7..731ab1d53 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -89,6 +89,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef(); private _editorView: Opt<EditorView>; public _applyingChange: string = ''; + private _inDrop = false; private _finishingLink = false; private _searchIndex = 0; private _lastTimedMark: Mark | undefined = undefined; @@ -355,7 +356,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now()))); if ((!prevData && !protoData) || newText || (!newText && !templateData)) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) - if ((this._finishingLink || this._props.isContentActive()) && removeSelection(newJson) !== removeSelection(prevData?.Data)) { + if ((this._finishingLink || this._props.isContentActive() || this._inDrop) && removeSelection(newJson) !== removeSelection(prevData?.Data)) { const numstring = NumCast(dataDoc[this.fieldKey], null); dataDoc[this.fieldKey] = numstring !== undefined ? Number(newText) : new RichTextField(newJson, newText); dataDoc[this.fieldKey + '_noTemplate'] = true; // mark the data field as being split from the template if it has been edited @@ -571,8 +572,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (dragData) { const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc; const effectiveAcl = GetEffectiveAcl(dataDoc); - const draggedDoc = dragData.draggedDocuments.lastElement(); + const draggedDoc = dragData.droppedDocuments.lastElement(); let added: Opt<boolean>; + const dropAction = dragData.dropAction || dragData.userDropAction; if ([AclEdit, AclAdmin, AclSelfEdit].includes(effectiveAcl)) { // replace text contents when dragging with Alt if (de.altKey) { @@ -582,7 +584,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } // embed document when drag marked as embed - } else if (de.embedKey) { + } else if (de.embedKey || dropAction) { const node = schema.nodes.dashDoc.create({ width: NumCast(draggedDoc._width), height: NumCast(draggedDoc._height), @@ -590,20 +592,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps docId: draggedDoc[Id], float: 'unset', }); - if (!['embed', 'copy'].includes((dragData.dropAction ?? '') as any)) { + if (!['embed', 'copy'].includes((dropAction ?? '') as any)) { added = dragData.removeDocument?.(draggedDoc) ? true : false; + } else { + added = true; } if (added) { draggedDoc._freeform_fitContentsToBox = true; Doc.SetContainer(draggedDoc, this.Document); const view = this._editorView!; try { + this._inDrop = true; const pos = view.posAtCoords({ left: de.x, top: de.y })?.pos; pos && view.dispatch(view.state.tr.insert(pos, node)); added = pos ? true : false; // pos will be null if you don't drop onto an actual text location } catch (e) { console.log('Drop failed', e); added = false; + } finally { + this._inDrop = false; } } } diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 9e5ea9524..667bc2f5c 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -2607,6 +2607,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { ignoreUnrendered={true} childDragAction="move" setContentViewBox={emptyFunction} + hideClickBehaviors={true} //childLayoutFitWidth={returnTrue} childOpacity={returnOne} childClickScript={PresBox.navigateToDocScript} diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 7e68711fa..5b2aa1cde 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -128,7 +128,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { whenChildContentsActiveChanged={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} - bringToFront={returnFalse} /> </div> ); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index ba7286111..0d4cfda88 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -535,7 +535,6 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> { isAnnotationOverlayScrollable={true} childFilters={childFilters} select={emptyFunction} - bringToFront={emptyFunction} styleProvider={this.childStyleProvider} /> </div> diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index 5828313c8..4155800b8 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -104,7 +104,6 @@ export class TopBar extends React.Component { fieldKey="data" dropAction="embed" styleProvider={DefaultStyleProvider} - bringToFront={emptyFunction} select={emptyFunction} isContentActive={returnTrue} isAnyChildContentActive={returnFalse} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 9d68ea731..c31e73b42 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -398,7 +398,6 @@ export class MobileInterface extends React.Component { styleProvider={this.whitebackground} containerViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} |