From 216385c7e84febce8988ef1390845b0c661fb04f Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 8 Nov 2023 12:55:59 -0500 Subject: fixed bug where tableBox's didn't render all of the rows they receive. lots of code cleanup -- moving things from Doc.ts to better locations. Changed overlays and published docs to be local to their dashboard. changed treeview icons. --- src/client/views/OverlayView.tsx | 128 +++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 65 deletions(-) (limited to 'src/client/views/OverlayView.tsx') diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index c174befc0..c7b59a8e2 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; import ReactLoading from 'react-loading'; -import { Doc, DocListCast } from '../../fields/Doc'; +import { Doc } from '../../fields/Doc'; import { Height, Width } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { NumCast } from '../../fields/Types'; @@ -119,7 +119,7 @@ export class OverlayView extends React.Component { new _global.ResizeObserver( action((entries: any) => { for (const entry of entries) { - DocListCast(Doc.MyOverlayDocs?.data).forEach(doc => { + Doc.MyOverlayDocs.forEach(doc => { if (NumCast(doc.overlayX) > entry.contentRect.width - 10) { doc.overlayX = entry.contentRect.width - 10; } @@ -184,70 +184,68 @@ export class OverlayView extends React.Component { ); @computed get overlayDocs() { - return DocListCast(Doc.MyOverlayDocs?.data) - .filter(d => !LightboxView.LightboxDoc || d.type === DocumentType.PRES) - .map(d => { - let offsetx = 0, - offsety = 0; - const dref = React.createRef(); - const onPointerMove = action((e: PointerEvent, down: number[]) => { - if (e.cancelBubble) return false; // if the overlay doc processed the move event (e.g., to pan its contents), then the event should be marked as canceled since propagation can't be stopped - if (e.buttons === 1) { - d.overlayX = e.clientX + offsetx; - d.overlayY = e.clientY + offsety; - } - if (e.metaKey) { - const dragData = new DragManager.DocumentDragData([d]); - dragData.offset = [-offsetx, -offsety]; - dragData.dropAction = 'move'; - dragData.removeDocument = this.removeOverlayDoc; - dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { - return dragData.removeDocument!(doc) ? addDocument(doc) : false; - }; - DragManager.StartDocumentDrag([dref.current!], dragData, down[0], down[1]); - return true; - } - return false; - }); - - const onPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction, false); - offsetx = NumCast(d.overlayX) - e.clientX; - offsety = NumCast(d.overlayY) - e.clientY; - }; - return ( -
- -
- ); + return Doc.MyOverlayDocs.filter(d => !LightboxView.LightboxDoc || d.type === DocumentType.PRES).map(d => { + let offsetx = 0, + offsety = 0; + const dref = React.createRef(); + const onPointerMove = action((e: PointerEvent, down: number[]) => { + if (e.cancelBubble) return false; // if the overlay doc processed the move event (e.g., to pan its contents), then the event should be marked as canceled since propagation can't be stopped + if (e.buttons === 1) { + d.overlayX = e.clientX + offsetx; + d.overlayY = e.clientY + offsety; + } + if (e.metaKey) { + const dragData = new DragManager.DocumentDragData([d]); + dragData.offset = [-offsetx, -offsety]; + dragData.dropAction = 'move'; + dragData.removeDocument = this.removeOverlayDoc; + dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { + return dragData.removeDocument!(doc) ? addDocument(doc) : false; + }; + DragManager.StartDocumentDrag([dref.current!], dragData, down[0], down[1]); + return true; + } + return false; }); + + const onPointerDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction, false); + offsetx = NumCast(d.overlayX) - e.clientX; + offsety = NumCast(d.overlayY) - e.clientY; + }; + return ( +
+ +
+ ); + }); } public static ShowSpinner() { -- cgit v1.2.3-70-g09d2 From 33cfc91ed9a6a2fe8b4a5b55ebd9accc24eaa1ae Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 25 Nov 2023 22:57:16 -0500 Subject: cleanup of rootSelected to default to false. remove unused mobile classes. --- src/client/views/DocComponent.tsx | 2 - src/client/views/GestureOverlay.tsx | 2 +- src/client/views/LightboxView.tsx | 4 +- src/client/views/MainView.tsx | 12 +- src/client/views/OverlayView.tsx | 4 +- src/client/views/Palette.tsx | 69 --------- src/client/views/collections/CollectionMenu.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 4 +- src/client/views/collections/TreeView.tsx | 4 +- src/client/views/linking/LinkPopup.tsx | 2 +- src/client/views/newlightbox/NewLightboxView.tsx | 4 +- src/client/views/nodes/trails/PresElementBox.tsx | 4 +- src/client/views/topbar/TopBar.tsx | 2 +- src/mobile/AudioUpload.scss | 61 -------- src/mobile/AudioUpload.tsx | 162 --------------------- src/mobile/MobileInterface.tsx | 4 - 17 files changed, 23 insertions(+), 321 deletions(-) delete mode 100644 src/client/views/Palette.tsx delete mode 100644 src/mobile/AudioUpload.scss delete mode 100644 src/mobile/AudioUpload.tsx (limited to 'src/client/views/OverlayView.tsx') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 9ff27d9a0..fdaca8056 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -53,7 +53,6 @@ interface ViewBoxBaseProps { isSelected: () => boolean; isContentActive: () => boolean | undefined; renderDepth: number; - rootSelected: () => boolean; } export function ViewBoxBaseComponent

() { class Component extends React.Component> { @@ -90,7 +89,6 @@ export interface ViewBoxAnnotatableProps { select: (isCtrlPressed: boolean) => void; whenChildContentsActiveChanged: (isActive: boolean) => void; isSelected: () => boolean; - rootSelected: () => boolean; renderDepth: number; isAnnotationOverlay?: boolean; } diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index db6c00426..0882294a2 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -469,7 +469,7 @@ export class GestureOverlay extends React.Component { styleProvider={DefaultStyleProvider} ScreenToLocalTransform={this.lightboxScreenToLocal} renderDepth={0} - rootSelected={returnTrue} + rootSelected={returnFalse} docViewPath={returnEmptyDoclist} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f40f1f3e8..f42c17694 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -604,7 +604,7 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={DefaultStyleProvider} - rootSelected={returnTrue} + rootSelected={returnFalse} addDocument={this.addHeaderDoc} removeDocument={this.removeHeaderDoc} fitContentsToBox={returnTrue} @@ -641,7 +641,7 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={this._hideUI ? DefaultStyleProvider : undefined} - rootSelected={returnTrue} + rootSelected={returnFalse} isContentActive={returnTrue} removeDocument={undefined} ScreenToLocalTransform={this._hideUI ? this.mainScreenToLocalXf : Transform.Identity} @@ -737,7 +737,7 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={this._sidebarContent.proto === Doc.MyDashboards || this._sidebarContent.proto === Doc.MyFilesystem ? DashboardStyleProvider : DefaultStyleProvider} - rootSelected={returnTrue} + rootSelected={returnFalse} removeDocument={returnFalse} ScreenToLocalTransform={this.mainContainerXf} PanelWidth={this.leftMenuFlyoutWidth} @@ -766,7 +766,7 @@ export class MainView extends React.Component { addDocument={undefined} addDocTab={DocumentViewInternal.addDocTabFunc} pinToPres={emptyFunction} - rootSelected={returnTrue} + rootSelected={returnFalse} removeDocument={returnFalse} ScreenToLocalTransform={this.sidebarScreenToLocal} PanelWidth={this.leftMenuWidth} @@ -906,7 +906,7 @@ export class MainView extends React.Component { dropAction="embed" setHeight={returnFalse} styleProvider={DefaultStyleProvider} - rootSelected={returnTrue} + rootSelected={returnFalse} bringToFront={emptyFunction} select={emptyFunction} isAnyChildContentActive={returnFalse} @@ -993,7 +993,7 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={DefaultStyleProvider} - rootSelected={returnTrue} + rootSelected={returnFalse} addDocument={returnFalse} removeDocument={returnFalse} fitContentsToBox={returnTrue} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index c7b59a8e2..fbcefd460 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -7,7 +7,7 @@ import { Doc } from '../../fields/Doc'; import { Height, Width } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { NumCast } from '../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; @@ -222,7 +222,7 @@ export class OverlayView extends React.Component { style={{ top: d.type === DocumentType.PRES ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.overlayX}px, ${d.overlayY}px)` }}> { - private _selectedDisposer?: IReactionDisposer; - @observable private _selectedIndex: number = 0; - - componentDidMount = () => { - this._selectedDisposer = reaction( - () => NumCast(this.props.thumbDoc.selectedIndex), - i => (this._selectedIndex = i), - { fireImmediately: true } - ); - }; - - componentWillUnmount = () => { - this._selectedDisposer?.(); - }; - - render() { - return ( -

-
-
- window.screen.width} - PanelHeight={() => window.screen.height} - renderDepth={0} - isDocumentActive={returnTrue} - isContentActive={emptyFunction} - focus={emptyFunction} - docViewPath={returnEmptyDoclist} - styleProvider={returnEmptyString} - whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} - childFilters={returnEmptyFilter} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - /> -
-
-
-
- ); - } -} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index cf154be8d..b190eb23d 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -119,7 +119,7 @@ export class CollectionMenu extends AntimodeMenu { dropAction="embed" setHeight={returnFalse} styleProvider={DefaultStyleProvider} - rootSelected={returnTrue} + rootSelected={returnFalse} bringToFront={emptyFunction} select={emptyFunction} isContentActive={returnTrue} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 761192a22..54332a7fd 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -236,7 +236,7 @@ export class CollectionTreeView extends CollectionSubView { addDocTab={this.addDocTab} ScreenToLocalTransform={this.ScreenToLocalTransform} dontCenter={'y'} - rootSelected={returnTrue} + rootSelected={returnFalse} whenChildContentsActiveChanged={this.whenChildContentActiveChanges} focus={this.focusFunc} docViewPath={returnEmptyDoclist} @@ -598,7 +598,7 @@ export class TabMinimapView extends React.Component { dontRegisterView={true} fieldKey={Doc.LayoutFieldKey(this.props.document)} bringToFront={emptyFunction} - rootSelected={returnTrue} + rootSelected={returnFalse} addDocument={returnFalse} moveDocument={returnFalse} removeDocument={returnFalse} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 004857ed1..6e3f8e807 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -976,7 +976,7 @@ export class TreeView extends React.Component { treeViewDoc={this.props.treeView.props.Document} addDocument={undefined} addDocTab={this.props.addDocTab} - rootSelected={returnTrue} + rootSelected={returnFalse} pinToPres={emptyFunction} onClick={this.onChildClick} onDoubleClick={this.onChildDoubleClick} @@ -1082,7 +1082,7 @@ export class TreeView extends React.Component { ScreenToLocalTransform={this.docTransform} renderDepth={this.props.renderDepth + 1} treeViewDoc={this.props.treeView?.props.Document} - rootSelected={returnTrue} + rootSelected={returnFalse} docViewPath={this.props.treeView.props.docViewPath} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index 9a9a89732..f02a284da 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -74,7 +74,7 @@ export class LinkPopup extends React.Component { addDocument={undefined} addDocTab={returnTrue} pinToPres={emptyFunction} - rootSelected={returnTrue} + rootSelected={returnFalse} styleProvider={DefaultStyleProvider} removeDocument={undefined} ScreenToLocalTransform={Transform.Identity} diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx index ca90f6a0f..bde93c761 100644 --- a/src/client/views/newlightbox/NewLightboxView.tsx +++ b/src/client/views/newlightbox/NewLightboxView.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { LinkManager } from '../../util/LinkManager'; @@ -302,7 +302,7 @@ export class NewLightboxView extends React.Component { styleProvider={DefaultStyleProvider} ScreenToLocalTransform={this.newLightboxScreenToLocal} renderDepth={0} - rootSelected={returnTrue} + rootSelected={returnFalse} docViewPath={returnEmptyDoclist} childFilters={this.docFilters} childFiltersByRanges={returnEmptyFilter} diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index c667f126f..10a9395a0 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -110,7 +110,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { childFilters={this.props.childFilters} childFiltersByRanges={this.props.childFiltersByRanges} searchFilterDocs={this.props.searchFilterDocs} - rootSelected={returnTrue} + rootSelected={returnFalse} addDocument={returnFalse} removeDocument={returnFalse} fitContentsToBox={returnTrue} @@ -546,7 +546,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { return (
{ - for (let i = 1; i < 8; i++) { - this.setOpacity(i, '0.2'); - } - this._audioCol = FieldValue( - Cast( - Docs.Create.FreeformDocument( - [ - Cast( - Docs.Create.AudioDocument(nullAudio, { - title: 'mobile audio', - _width: 500, - _height: 100, - }), - Doc - ) as Doc, - ], - { title: 'mobile audio', _width: 300, _height: 300, _layout_fitContentsToBox: true, layout_boxShadow: '0 0' } - ), - Doc - ) - ) as Doc; - }; - - /** - * Handles the onClick of the 'Close' button - * Reset upload interface and toggle audio - */ - closeUpload = () => { - this.clearUpload(); - MobileInterface.Instance.toggleAudio(); - }; - - /** - * Handles the on click of the 'Upload' button. - * Pushing the audio doc onto Dash Web through the right side bar - */ - uploadAudio = () => { - const audioRightSidebar = Cast(Doc.SharingDoc(), Doc, null); - const audioDoc = this._audioCol; - const data = Cast(audioRightSidebar.data, listSpec(Doc)); - for (let i = 1; i < 8; i++) { - setTimeout(() => this.setOpacity(i, '1'), i * 200); - } - if (data) { - data.push(audioDoc); - } - // Resets uploader after 3 seconds - setTimeout(this.clearUpload, 3000); - }; - - // Returns the upload audio menu - private get uploadInterface() { - return ( - <> - - -
- -
-
this.closeUpload()}> - -
- -
- 600} - PanelHeight={() => 400} - renderDepth={0} - isDocumentActive={returnTrue} - isContentActive={emptyFunction} - focus={emptyFunction} - styleProvider={() => 'rgba(0,0,0,0)'} - docViewPath={returnEmptyDoclist} - whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} - /> -
-
- Restart -
-
- Upload -
-
-
-
-
-
-
-
-
-
- - ); - } - - // Handles the setting of the loading bar - setOpacity = (index: number, opacity: string) => { - const slab = document.getElementById('slab0' + index); - if (slab) { - slab.style.opacity = opacity; - } - }; - - @observable private dialogueBoxOpacity = 1; - @observable private overlayOpacity = 0.4; - - render() { - return ; - } -} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index e24bcd733..97f771c16 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -122,7 +122,6 @@ import { List } from '../fields/List'; import { ScriptField } from '../fields/ScriptField'; import { Cast, FieldValue, StrCast } from '../fields/Types'; import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero } from '../Utils'; -import { AudioUpload } from './AudioUpload'; import { Uploader } from './ImageUpload'; import './AudioUpload.scss'; import './ImageUpload.scss'; @@ -820,9 +819,6 @@ export class MobileInterface extends React.Component {
{this.uploadImage}
-
- -
{this.switchMenuView} {this.inkMenu} -- cgit v1.2.3-70-g09d2 From c918198a37e4ad5306b70a90ca1b3fcab2e28f76 Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 30 Nov 2023 16:00:13 -0500 Subject: fixed rootSelected prop to be optional. fixed fonticont toggle to pass 'self' even though it's deprecated. --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/GestureOverlay.tsx | 1 - src/client/views/LightboxView.tsx | 1 - src/client/views/MainView.tsx | 6 ------ src/client/views/OverlayView.tsx | 1 - src/client/views/PropertiesView.tsx | 1 - src/client/views/TemplateMenu.tsx | 1 - src/client/views/collections/CollectionMenu.tsx | 1 - .../collections/CollectionStackedTimeline.tsx | 1 - .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 4 ++-- .../views/collections/CollectionTreeView.tsx | 3 +-- src/client/views/collections/TabDocView.tsx | 2 -- src/client/views/collections/TreeView.tsx | 2 -- .../collectionLinear/CollectionLinearView.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 1 - src/client/views/newlightbox/NewLightboxView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 1 - src/client/views/nodes/LinkDocPreview.tsx | 1 - src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx | 1 - .../views/nodes/formattedText/DashDocView.tsx | 1 - .../views/nodes/formattedText/FormattedTextBox.tsx | 25 +++++++++++----------- .../views/nodes/formattedText/RichTextMenu.tsx | 10 ++++----- src/client/views/nodes/trails/PresElementBox.tsx | 1 - src/client/views/topbar/TopBar.tsx | 1 - src/mobile/MobileInterface.tsx | 1 - 28 files changed, 25 insertions(+), 53 deletions(-) (limited to 'src/client/views/OverlayView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index aba466d55..7070a47e8 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -480,7 +480,7 @@ export class CurrentUserUtils { const newDashboard = `createNewDashboard()`; const reqdBtnOpts:DocumentOptions = { _forceActive: true, _width: 30, _height: 30, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, - title: "new dashboard", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", isSystem: true }; + title: "new Dash", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", isSystem: true }; const reqdBtnScript = {onClick: newDashboard,} const newDashboardButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myDashboards?.layout_headerButton), reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), reqdBtnScript); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 0882294a2..09be95542 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -469,7 +469,6 @@ export class GestureOverlay extends React.Component { styleProvider={DefaultStyleProvider} ScreenToLocalTransform={this.lightboxScreenToLocal} renderDepth={0} - rootSelected={returnFalse} docViewPath={returnEmptyDoclist} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ce47a46c3..3b3b43469 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -604,7 +604,6 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={DefaultStyleProvider} - rootSelected={returnFalse} addDocument={this.addHeaderDoc} removeDocument={this.removeHeaderDoc} fitContentsToBox={returnTrue} @@ -641,7 +640,6 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={this._hideUI ? DefaultStyleProvider : undefined} - rootSelected={returnFalse} isContentActive={returnTrue} removeDocument={undefined} ScreenToLocalTransform={this._hideUI ? this.mainScreenToLocalXf : Transform.Identity} @@ -737,7 +735,6 @@ export class MainView extends React.Component { pinToPres={TabDocView.PinDoc} docViewPath={returnEmptyDoclist} styleProvider={this._sidebarContent.proto === Doc.MyDashboards || this._sidebarContent.proto === Doc.MyFilesystem || this._sidebarContent.proto === Doc.MyTrails ? DashboardStyleProvider : DefaultStyleProvider} - rootSelected={returnFalse} removeDocument={returnFalse} ScreenToLocalTransform={this.mainContainerXf} PanelWidth={this.leftMenuFlyoutWidth} @@ -766,7 +763,6 @@ export class MainView extends React.Component { addDocument={undefined} addDocTab={DocumentViewInternal.addDocTabFunc} pinToPres={emptyFunction} - rootSelected={returnFalse} removeDocument={returnFalse} ScreenToLocalTransform={this.sidebarScreenToLocal} PanelWidth={this.leftMenuWidth} @@ -906,7 +902,6 @@ export class MainView extends React.Component { dropAction="embed" setHeight={returnFalse} styleProvider={DefaultStyleProvider} - rootSelected={returnFalse} bringToFront={emptyFunction} select={emptyFunction} isAnyChildContentActive={returnFalse} @@ -993,7 +988,6 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={DefaultStyleProvider} - rootSelected={returnFalse} addDocument={returnFalse} removeDocument={returnFalse} fitContentsToBox={returnTrue} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index fbcefd460..dd547c549 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -222,7 +222,6 @@ export class OverlayView extends React.Component { style={{ top: d.type === DocumentType.PRES ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.overlayX}px, ${d.overlayY}px)` }}> { DataDoc={this.dataDoc} renderDepth={1} fitContentsToBox={returnTrue} - rootSelected={returnFalse} styleProvider={DefaultStyleProvider} docViewPath={returnEmptyDoclist} dontCenter={'y'} diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index a3884c9eb..6da228417 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -119,7 +119,6 @@ export class TemplateMenu extends React.Component { childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - rootSelected={returnFalse} onCheckedClick={this.scriptField} onChildClick={this.scriptField} isAnyChildContentActive={returnFalse} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 3c555e731..c3aba4754 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -102,7 +102,6 @@ export class CollectionMenu extends AntimodeMenu { dropAction="embed" setHeight={returnFalse} styleProvider={DefaultStyleProvider} - rootSelected={returnFalse} bringToFront={emptyFunction} select={emptyFunction} isContentActive={returnTrue} diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 552c19eb3..d4daf2baf 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -817,7 +817,6 @@ class StackedTimelineAnchor extends React.Component searchFilterDocs={returnEmptyDoclist} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} - rootSelected={returnFalse} onClick={script} onDoubleClick={this.props.layoutDoc.autoPlayAnchors ? undefined : doublescript} ignoreAutoHeight={false} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 57ff7515e..582baa7b5 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -678,7 +678,7 @@ export class CollectionStackingView extends CollectionSubView(moreProps?: X) { } // this returns whether either the collection is selected, or the template that it is part of is selected - rootSelected = () => this.props.isSelected() || this.props.rootSelected(); + rootSelected = () => this.props.isSelected() || BoolCast(this.Document.rootDocument && this.props.rootSelected?.()); // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc. // When a document has a DataDoc but it's not a template, then it contains its own rendering data, but needs to pass the DataDoc through diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 5bd5cef25..36ea14d92 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -236,7 +236,6 @@ export class CollectionTreeView extends CollectionSubView { addDocTab={this.addDocTab} ScreenToLocalTransform={this.ScreenToLocalTransform} dontCenter={'y'} - rootSelected={returnFalse} whenChildContentsActiveChanged={this.whenChildContentActiveChanges} focus={this.focusFunc} docViewPath={returnEmptyDoclist} @@ -599,7 +598,6 @@ export class TabMinimapView extends React.Component { dontRegisterView={true} fieldKey={Doc.LayoutFieldKey(this.props.document)} bringToFront={emptyFunction} - rootSelected={returnFalse} addDocument={returnFalse} moveDocument={returnFalse} removeDocument={returnFalse} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 03e82577e..ee5f9fd95 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -975,7 +975,6 @@ export class TreeView extends React.Component { treeViewDoc={this.props.treeView.props.Document} addDocument={undefined} addDocTab={this.props.addDocTab} - rootSelected={returnFalse} pinToPres={this.props.treeView.props.pinToPres} onClick={this.onChildClick} onDoubleClick={this.onChildDoubleClick} @@ -1081,7 +1080,6 @@ export class TreeView extends React.Component { ScreenToLocalTransform={this.docTransform} renderDepth={this.props.renderDepth + 1} treeViewDoc={this.props.treeView?.props.Document} - rootSelected={returnFalse} docViewPath={this.props.treeView.props.docViewPath} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index a06ed3a2d..96eabd88c 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -177,7 +177,7 @@ export class CollectionLinearView extends CollectionSubView() { addDocTab={this.props.addDocTab} pinToPres={emptyFunction} dragAction={(this.layoutDoc.childDragAction ?? this.props.childDragAction) as dropActionType} - rootSelected={this.props.isSelected} + rootSelected={this.rootSelected} removeDocument={this.props.removeDocument} ScreenToLocalTransform={docXf} PanelWidth={doc[Width]} diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 2c251d3cf..150b1b46e 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -72,7 +72,6 @@ export class SchemaTableCell extends React.Component { searchFilterDocs: returnEmptyDoclist, styleProvider: DefaultStyleProvider, docViewPath: returnEmptyDoclist, - rootSelected: returnFalse, isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx index bde93c761..22b996809 100644 --- a/src/client/views/newlightbox/NewLightboxView.tsx +++ b/src/client/views/newlightbox/NewLightboxView.tsx @@ -302,7 +302,6 @@ export class NewLightboxView extends React.Component { styleProvider={DefaultStyleProvider} ScreenToLocalTransform={this.newLightboxScreenToLocal} renderDepth={0} - rootSelected={returnFalse} docViewPath={returnEmptyDoclist} childFilters={this.docFilters} childFiltersByRanges={returnEmptyFilter} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6e50a6b0f..b6e90cbf4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -176,7 +176,7 @@ export interface DocumentViewSharedProps { searchFilterDocs: () => Doc[]; layout_showTitle?: () => string; whenChildContentsActiveChanged: (isActive: boolean) => void; - rootSelected: () => boolean; // whether the root of a template has been selected + rootSelected?: () => boolean; // whether the root of a template has been selected addDocTab: (doc: Doc, where: OpenWhere) => boolean; filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index ba5370360..7119ae235 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -324,7 +324,7 @@ export class FontIconBox extends DocComponent() { //background={SettingsManager.userBackgroundColor} icon={this.Icon(color)!} label={this.label} - onPointerDown={() => script.script.run({ this: this.Document, value: !toggleStatus, _readOnly_: false })} + onPointerDown={() => script.script.run({ this: this.Document, self:this.Document, value: !toggleStatus, _readOnly_: false })} /> ); } diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 6f99b7c28..39e0279fc 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -65,7 +65,6 @@ export class KeyValuePair extends React.Component { styleProvider: DefaultStyleProvider, docViewPath: returnEmptyDoclist, fieldKey: this.props.keyName, - rootSelected: returnFalse, isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 7e4f1da8e..ad5324b3e 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -260,7 +260,6 @@ export class LinkDocPreview extends React.Component { }} Document={this._targetDoc!} moveDocument={returnFalse} - rootSelected={returnFalse} styleProvider={this.props.docProps?.styleProvider} docViewPath={returnEmptyDoclist} ScreenToLocalTransform={Transform.Identity} diff --git a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx index 66c47d131..9608e2dd0 100644 --- a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx +++ b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx @@ -68,7 +68,6 @@ export class MapBoxInfoWindow extends React.Component { this.getAnchor(true), targetCreator), e.pageX, e.pageY); }); const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); - this.props.rootSelected() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom); + this.props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom); let ele: Opt = undefined; try { const contents = window.getSelection()?.getRangeAt(0).cloneContents(); @@ -390,7 +390,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this.props.rootSelected(), + () => this.props.rootSelected?.(), action(selected => { //selected && setTimeout(() => this.prepareForTyping()); if (FormattedTextBox._globalHighlights.has('Bold Text')) { @@ -1453,7 +1453,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent self.props.rootSelected() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView)); + runInAction(() => self.props.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView)); return new RichTextMenuPlugin({ editorProps: this.props }); }, }); @@ -1628,7 +1628,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { FormattedTextBoxComment.textBox = this; - if (e.button === 0 && this.props.rootSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) { + if (e.button === 0 && this.props.rootSelected?.() && !e.altKey && !e.ctrlKey && !e.metaKey) { if (e.clientX < this.ProseRef!.getBoundingClientRect().right) { // stop propagation if not in sidebar e.stopPropagation(); // if the text box is selected, then it consumes all click events @@ -1676,7 +1676,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - console.log('FOCUSED = ' + this.layoutDoc.title + ' ' + this.props.rootSelected()); + console.log('FOCUSED = ' + this.layoutDoc.title + ' ' + this.props.rootSelected?.()); //applyDevTools.applyDevTools(this._editorView); this.ProseRef?.children[0] === e.nativeEvent.target && this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props, this.layoutDoc); e.stopPropagation(); @@ -1723,7 +1723,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - console.log('BLUREd = ' + this.layoutDoc.title + ' ' + this.props.rootSelected()); if (this.ProseRef?.children[0] !== e.nativeEvent.target) return; if (!(this.EditorView?.state.selection instanceof NodeSelection) || this.EditorView.state.selection.node.type !== this.EditorView.state.schema.nodes.footnote) { const stordMarks = this._editorView?.state.storedMarks?.slice(); @@ -1787,7 +1786,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { // finds font sizes and families in selection getActiveAlignment() { - if (this.view && this.TextView?.props.rootSelected()) { + if (this.view && this.TextView?.props.rootSelected?.()) { const path = (this.view.state.selection.$from as any).path; for (let i = path.length - 3; i < path.length && i >= 0; i -= 3) { if (path[i]?.type === this.view.state.schema.nodes.paragraph || path[i]?.type === this.view.state.schema.nodes.heading) { @@ -199,7 +199,7 @@ export class RichTextMenu extends AntimodeMenu { // finds font sizes and families in selection getActiveListStyle() { - if (this.view && this.TextView?.props.rootSelected()) { + if (this.view && this.TextView?.props.rootSelected?.()) { const path = (this.view.state.selection.$from as any).path; for (let i = 0; i < path.length; i += 3) { if (path[i].type === this.view.state.schema.nodes.ordered_list) { @@ -219,7 +219,7 @@ export class RichTextMenu extends AntimodeMenu { const activeSizes = new Set(); const activeColors = new Set(); const activeHighlights = new Set(); - if (this.view && this.TextView?.props.rootSelected()) { + if (this.view && this.TextView?.props.rootSelected?.()) { const state = this.view.state; const pos = this.view.state.selection.$from; const marks: Mark[] = [...(state.storedMarks ?? [])]; @@ -254,7 +254,7 @@ export class RichTextMenu extends AntimodeMenu { //finds all active marks on selection in given group getActiveMarksOnSelection() { let activeMarks: MarkType[] = []; - if (!this.view || !this.TextView?.props.rootSelected()) return activeMarks; + if (!this.view || !this.TextView?.props.rootSelected?.()) return activeMarks; const markGroup = [schema.marks.noAutoLinkAnchor, schema.marks.strong, schema.marks.em, schema.marks.underline, schema.marks.strikethrough, schema.marks.superscript, schema.marks.subscript]; if (this.view.state.storedMarks) return this.view.state.storedMarks.map(mark => mark.type); @@ -447,7 +447,7 @@ export class RichTextMenu extends AntimodeMenu { this.layoutDoc && (this.layoutDoc.layout_centered = !this.layoutDoc.layout_centered); }; align = (view: EditorView, dispatch: any, alignment: 'left' | 'right' | 'center') => { - if (this.TextView?.props.rootSelected()) { + if (this.TextView?.props.rootSelected?.()) { var tr = view.state.tr; view.state.doc.nodesBetween(view.state.selection.from, view.state.selection.to, (node, pos, parent, index) => { if ([schema.nodes.paragraph, schema.nodes.heading].includes(node.type)) { diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 6a8edee0d..b104e8b70 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -116,7 +116,6 @@ export class PresElementBox extends ViewBoxBaseComponent() { childFilters={this.props.childFilters} childFiltersByRanges={this.props.childFiltersByRanges} searchFilterDocs={this.props.searchFilterDocs} - rootSelected={returnFalse} addDocument={returnFalse} removeDocument={returnFalse} fitContentsToBox={returnTrue} diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index f1686a6ea..1dfcf174e 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -105,7 +105,6 @@ export class TopBar extends React.Component { dropAction="embed" setHeight={returnFalse} styleProvider={DefaultStyleProvider} - rootSelected={returnFalse} bringToFront={emptyFunction} select={emptyFunction} isContentActive={returnTrue} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 97f771c16..791ce8d8f 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -388,7 +388,6 @@ export class MobileInterface extends React.Component { addDocument={returnFalse} addDocTab={returnFalse} pinToPres={emptyFunction} - rootSelected={returnFalse} removeDocument={undefined} ScreenToLocalTransform={Transform.Identity} PanelWidth={this.returnWidth} -- cgit v1.2.3-70-g09d2 From 2e56299ddfca9cc9e8466b45170ce3f05ee64f15 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 12 Dec 2023 12:49:58 -0500 Subject: fixed overlay view and scriptingRepl and all observable Doc arrays to be shallowly observed. --- src/client/util/DocumentManager.ts | 6 +-- src/client/util/LinkManager.ts | 2 +- src/client/util/Scripting.ts | 4 +- src/client/util/SelectionManager.ts | 2 +- src/client/views/ContextMenu.tsx | 2 +- src/client/views/OverlayView.tsx | 36 ++++++++------ src/client/views/ScriptingRepl.tsx | 71 ++++++++++++++++++++------- src/client/views/animationtimeline/Region.tsx | 4 +- src/client/views/nodes/DocumentIcon.tsx | 1 + src/fields/RichTextUtils.ts | 2 +- 10 files changed, 87 insertions(+), 43 deletions(-) (limited to 'src/client/views/OverlayView.tsx') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 17c915318..ba7a26a7a 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -22,8 +22,8 @@ const { Howl } = require('howler'); export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) @observable _documentViews = new Set(); - @observable public LinkAnchorBoxViews: DocumentView[] = observable([]); - @observable public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = observable([]); + @observable.shallow public LinkAnchorBoxViews: DocumentView[] = []; + @observable.shallow public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = []; @computed public get DocumentViews() { return Array.from(this._documentViews).filter(view => !(view.ComponentView instanceof KeyValueBox) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(view.docViewPath))); } @@ -38,7 +38,7 @@ export class DocumentManager { public static get Instance(): DocumentManager { return this._instance || (this._instance = new this()); } - @observable public CurrentlyLoading: Doc[] = observable([]); // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor + @observable.shallow public CurrentlyLoading: Doc[] = []; // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor //private constructor so no other class can create a nodemanager private constructor() { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 8346949ba..cacfcf856 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -22,7 +22,7 @@ import { ScriptingGlobals } from './ScriptingGlobals'; */ export class LinkManager { @observable static _instance: LinkManager; - @observable userLinkDBs: Doc[] = observable([]); + @observable.shallow userLinkDBs: Doc[] = []; @observable public static currentLink: Opt; @observable public static currentLinkAnchor: Opt; public static get Instance() { diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index f0a5f9ed9..dbb994dbd 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -160,7 +160,7 @@ class ScriptingCompilerHost { export type Traverser = (node: ts.Node, indentation: string) => boolean | void; export type TraverserParam = Traverser | { onEnter: Traverser; onLeave: Traverser }; export type Transformer = { - transformer: ts.TransformerFactory; + transformer: ts.TransformerFactory; getVars?: () => { [name: string]: Field }; }; export interface ScriptOptions { @@ -220,7 +220,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, }); - script = printer.printFile(transformed[0]); + script = printer.printFile(transformed[0].getSourceFile()); } result.dispose(); } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index d36a360a1..b837cdd08 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -12,7 +12,7 @@ import { UndoManager } from './UndoManager'; export namespace SelectionManager { class Manager { - @observable SelectedViews: DocumentView[] = observable([]); + @observable.shallow SelectedViews: DocumentView[] = []; @observable IsDragging: boolean = false; @observable SelectedSchemaDocument: Doc | undefined = undefined; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 831925054..118a2c5f5 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -17,7 +17,7 @@ export class ContextMenu extends React.Component { private _defaultItem: ((name: string) => void) | undefined; private _onDisplay?: () => void = undefined; - @observable _items: ContextMenuProps[] = observable([]); + @observable.shallow _items: ContextMenuProps[] = []; @observable _pageX: number = 0; @observable _pageY: number = 0; @observable _display: boolean = false; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index dd547c549..e41113ca4 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -1,21 +1,20 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, makeObservable, observable, toJS } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; import ReactLoading from 'react-loading'; +import { Utils, copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc } from '../../fields/Doc'; import { Height, Width } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { NumCast } from '../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; -import { CollectionFreeFormLinksView } from './collections/collectionFreeForm/CollectionFreeFormLinksView'; import { LightboxView } from './LightboxView'; -import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; import './OverlayView.scss'; import { DefaultStyleProvider } from './StyleProvider'; +import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; const _global = (window /* browser */ || global) /* node */ as any; export type OverlayDisposer = () => void; @@ -36,12 +35,17 @@ export interface OverlayWindowProps { @observer export class OverlayWindow extends React.Component { - @observable x: number; - @observable y: number; - @observable width: number; - @observable height: number; + @observable x: number = 0; + @observable y: number = 0; + @observable width: number = 0; + @observable height: number = 0; + + _prevProps: OverlayWindowProps; + @observable _props: OverlayWindowProps; constructor(props: OverlayWindowProps) { super(props); + this._props = this._prevProps = props; + makeObservable(this); const opts = props.overlayOptions; this.x = opts.x; @@ -50,6 +54,10 @@ export class OverlayWindow extends React.Component { this.height = opts.height || 200; } + componentDidUpdate() { + copyProps(this); + } + onPointerDown = (_: React.PointerEvent) => { document.removeEventListener('pointermove', this.onPointerMove); document.removeEventListener('pointerup', this.onPointerUp); @@ -94,8 +102,8 @@ export class OverlayWindow extends React.Component { return LightboxView.LightboxDoc ? null : (
- {this.props.overlayOptions.title || 'Untitled'} -
@@ -109,11 +117,11 @@ export class OverlayWindow extends React.Component { @observer export class OverlayView extends React.Component { public static Instance: OverlayView; - @observable.shallow - private _elements: JSX.Element[] = []; + @observable.shallow _elements: JSX.Element[] = []; constructor(props: any) { super(props); + makeObservable(this); if (!OverlayView.Instance) { OverlayView.Instance = this; new _global.ResizeObserver( @@ -139,7 +147,7 @@ export class OverlayView extends React.Component { const index = this._elements.indexOf(ele); if (index !== -1) this._elements.splice(index, 1); }); - ele = ( + this._elements.push(
); - this._elements.push(ele); return remove; } @@ -255,7 +262,6 @@ export class OverlayView extends React.Component { return (
{this._elements}
- {this.overlayDocs}
); diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 9966dbced..8251d20dc 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { DocumentManager } from '../util/DocumentManager'; @@ -10,24 +10,40 @@ import { undoable } from '../util/UndoManager'; import { DocumentIconContainer } from './nodes/DocumentIcon'; import { OverlayView } from './OverlayView'; import './ScriptingRepl.scss'; +import { copyProps } from '../../Utils'; -@observer -export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: () => void; value: { [key: string]: any }; name?: string }> { +interface ReplProps { + scrollToBottom: () => void; + value: { [key: string]: any }; + name?: string; +} +export class ScriptingObjectDisplay extends React.Component { @observable collapsed = true; + _prevProps: ReplProps; + @observable _props: ReplProps; + constructor(props: ReplProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidUpdate(): void { + copyProps(this); + } + @action toggle = () => { this.collapsed = !this.collapsed; - this.props.scrollToBottom(); + this._props.scrollToBottom(); }; render() { - const val = this.props.value; + const val = this._props.value; const proto = Object.getPrototypeOf(val); const name = (proto && proto.constructor && proto.constructor.name) || String(val); - const title = this.props.name ? ( + const title = this._props.name ? ( <> - {this.props.name} : + {this._props.name} : {name} ) : ( @@ -53,7 +69,7 @@ export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: ()
{Object.keys(val).map(key => ( - + ))}
@@ -62,17 +78,32 @@ export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: () } } +interface replValueProps { + scrollToBottom: () => void; + value: any; + name?: string; +} @observer -export class ScriptingValueDisplay extends React.Component<{ scrollToBottom: () => void; value: any; name?: string }> { +export class ScriptingValueDisplay extends React.Component { + _prevProps: replValueProps; + @observable _props: replValueProps; + constructor(props: replValueProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidUpdate() { + copyProps(this); + } render() { - const val = this.props.name ? this.props.value[this.props.name] : this.props.value; + const val = this._props.name ? this._props.value[this._props.name] : this._props.value; if (typeof val === 'object') { - return ; + return ; } else if (typeof val === 'function') { const name = '[Function]'; - const title = this.props.name ? ( + const title = this._props.name ? ( <> - {this.props.name} : + {this._props.name} : {name} ) : ( @@ -81,9 +112,9 @@ export class ScriptingValueDisplay extends React.Component<{ scrollToBottom: () return
{title}
; } else { const name = String(val); - const title = this.props.name ? ( + const title = this._props.name ? ( <> - {this.props.name} : + {this._props.name} : {name} ) : ( @@ -96,6 +127,11 @@ export class ScriptingValueDisplay extends React.Component<{ scrollToBottom: () @observer export class ScriptingRepl extends React.Component { + constructor(props: any) { + super(props); + makeObservable(this); + } + @observable private commands: { command: string; result: any }[] = []; private commandsHistory: string[] = []; @@ -136,7 +172,8 @@ export class ScriptingRepl extends React.Component { const m = parseInt(match[1]); usedDocuments.push(m); } else { - return ts.createPropertyAccess(ts.createIdentifier('args'), node); + return ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('args'), node); + // ts.createPropertyAccess(ts.createIdentifier('args'), node); } } } @@ -156,7 +193,7 @@ export class ScriptingRepl extends React.Component { case 'Enter': { e.stopPropagation(); const docGlobals: { [name: string]: any } = {}; - DocumentManager.Instance.DocumentViews.forEach((dv, i) => (docGlobals[`d${i}`] = dv.props.Document)); + DocumentManager.Instance.DocumentViews.forEach((dv, i) => (docGlobals[`d${i}`] = dv.Document)); const globals = ScriptingGlobals.makeMutableGlobalsCopy(docGlobals); const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: 'any' }, transformer: this.getTransformer(), globals }); if (!script.compiled) { diff --git a/src/client/views/animationtimeline/Region.tsx b/src/client/views/animationtimeline/Region.tsx index bc87dc94d..abbc8203d 100644 --- a/src/client/views/animationtimeline/Region.tsx +++ b/src/client/views/animationtimeline/Region.tsx @@ -31,11 +31,11 @@ export namespace RegionHelpers { let rightMost: RegionData | undefined = undefined; regions.forEach(region => { const neighbor = RegionData(region); - if (currentRegion.position! > neighbor.position) { + if (NumCast(currentRegion.position) > neighbor.position) { if (!leftMost || neighbor.position > leftMost.position) { leftMost = neighbor; } - } else if (currentRegion.position! < neighbor.position) { + } else if (NumCast(currentRegion.position) < neighbor.position) { if (!rightMost || neighbor.position < rightMost.position) { rightMost = neighbor; } diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 0c780af2a..9ec4d8c13 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -16,6 +16,7 @@ interface DocumentIconProps { view: DocumentView; index: number; } +@observer export class DocumentIcon extends React.Component { @observable _hovered = false; _prevProps: DocumentIconProps; diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts index dfd02dbc0..b84a91709 100644 --- a/src/fields/RichTextUtils.ts +++ b/src/fields/RichTextUtils.ts @@ -15,7 +15,7 @@ import { Doc, Opt } from './Doc'; import { Id } from './FieldSymbols'; import { RichTextField } from './RichTextField'; import { Cast, StrCast } from './Types'; -import Color = require('color'); +import * as Color from 'color'; export namespace RichTextUtils { const delimiter = '\n'; -- cgit v1.2.3-70-g09d2 From 6951e98f1b863fe1f404d8bf532a9241e2371ec2 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 12 Dec 2023 12:54:24 -0500 Subject: from last - fix to remove overlay elements (doucment icons) --- src/client/views/OverlayView.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/client/views/OverlayView.tsx') diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index e41113ca4..673432a60 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -143,11 +143,7 @@ export class OverlayView extends React.Component { @action addElement(ele: JSX.Element, options: OverlayElementOptions): OverlayDisposer { - const remove = action(() => { - const index = this._elements.indexOf(ele); - if (index !== -1) this._elements.splice(index, 1); - }); - this._elements.push( + const div = (
); - return remove; + this._elements.push(div); + return action(() => { + const index = this._elements.indexOf(div); + if (index !== -1) this._elements.splice(index, 1); + }); } @action -- cgit v1.2.3-70-g09d2 From 1cf241544f8063e3d71406238a584299b6ced794 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 13 Dec 2023 21:17:50 -0500 Subject: cleaned up props/_props handling by inherting from ObservableReactComponent --- .vscode/settings.json | 4 +- src/Utils.ts | 7 ++- src/client/util/DocumentManager.ts | 3 +- src/client/util/SelectionManager.ts | 22 +++---- src/client/views/AntimodeMenu.tsx | 13 +---- src/client/views/ContextMenu.tsx | 5 +- src/client/views/ContextMenuItem.tsx | 15 ++--- src/client/views/DashboardView.tsx | 4 +- src/client/views/DocComponent.tsx | 43 ++++++-------- src/client/views/DocumentButtonBar.tsx | 8 +-- src/client/views/DocumentDecorations.tsx | 6 +- src/client/views/EditableView.tsx | 14 ++--- src/client/views/MainView.tsx | 47 +++++++-------- src/client/views/MarqueeAnnotator.tsx | 20 +++---- src/client/views/ObservableReactComponent.tsx | 21 +++++++ src/client/views/OverlayView.tsx | 18 ++---- src/client/views/PreviewCursor.tsx | 13 +++-- src/client/views/PropertiesDocContextSelector.tsx | 17 ++---- src/client/views/PropertiesView.tsx | 26 ++++----- src/client/views/ScriptingRepl.tsx | 29 +++------- src/client/views/SidebarAnnos.tsx | 25 ++++---- .../views/collections/CollectionCarousel3DView.tsx | 6 +- .../views/collections/CollectionCarouselView.tsx | 7 ++- .../views/collections/CollectionDockingView.tsx | 15 ++--- .../collections/CollectionMasonryViewFieldRow.tsx | 18 +++--- src/client/views/collections/CollectionMenu.tsx | 2 +- .../views/collections/CollectionNoteTakingView.tsx | 8 ++- .../views/collections/CollectionPileView.tsx | 7 ++- .../collections/CollectionStackedTimeline.tsx | 22 ++----- .../views/collections/CollectionStackingView.tsx | 15 ++--- .../CollectionStackingViewFieldColumn.tsx | 20 +++---- src/client/views/collections/CollectionSubView.tsx | 19 +++--- .../views/collections/CollectionTimeView.tsx | 7 ++- .../views/collections/CollectionTreeView.tsx | 16 ++---- src/client/views/collections/CollectionView.tsx | 26 ++++----- src/client/views/collections/TabDocView.tsx | 41 ++++++------- src/client/views/collections/TreeView.tsx | 23 ++++---- .../CollectionFreeFormInfoState.tsx | 20 +++---- .../CollectionFreeFormInfoUI.tsx | 33 ++++------- .../CollectionFreeFormLinkView.tsx | 15 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 13 +---- .../collectionFreeForm/MarqueeOptionsMenu.tsx | 1 - .../collections/collectionFreeForm/MarqueeView.tsx | 23 ++++---- .../collectionGrid/CollectionGridView.tsx | 7 ++- .../collectionLinear/CollectionLinearView.tsx | 19 ++---- .../CollectionMulticolumnView.tsx | 11 +++- .../CollectionMultirowView.tsx | 11 +++- .../collectionSchema/CollectionSchemaView.tsx | 37 +++++------- .../collections/collectionSchema/SchemaRowBox.tsx | 14 ++--- .../collectionSchema/SchemaTableCell.tsx | 67 +++++++++------------- src/client/views/linking/LinkMenu.tsx | 9 +-- src/client/views/linking/LinkMenuItem.tsx | 26 ++++----- src/client/views/nodes/AudioBox.tsx | 20 +++---- .../views/nodes/CollectionFreeFormDocumentView.tsx | 29 ++++------ src/client/views/nodes/ComparisonBox.tsx | 20 ++----- src/client/views/nodes/DocumentContentsView.tsx | 32 ++++------- src/client/views/nodes/DocumentIcon.tsx | 26 ++++----- src/client/views/nodes/DocumentLinksButton.tsx | 19 ++---- src/client/views/nodes/DocumentView.tsx | 36 ++++-------- src/client/views/nodes/EquationBox.tsx | 14 +---- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 14 ++--- src/client/views/nodes/FunctionPlotBox.tsx | 14 +---- src/client/views/nodes/ImageBox.tsx | 12 +--- src/client/views/nodes/KeyValueBox.tsx | 27 ++++----- src/client/views/nodes/KeyValuePair.tsx | 29 ++++------ src/client/views/nodes/LabelBox.tsx | 14 ++--- src/client/views/nodes/LinkAnchorBox.tsx | 19 ++---- src/client/views/nodes/LinkBox.tsx | 15 ++--- src/client/views/nodes/LinkDocPreview.tsx | 21 +++---- src/client/views/nodes/MapBox/MapAnchorMenu.tsx | 5 +- src/client/views/nodes/MapBox/MapBox.tsx | 22 +++---- src/client/views/nodes/PDFBox.tsx | 12 +--- src/client/views/nodes/VideoBox.tsx | 13 +---- src/client/views/nodes/WebBox.tsx | 11 +--- src/client/views/nodes/audio/AudioWaveform.tsx | 17 ++---- .../views/nodes/formattedText/DashFieldView.tsx | 18 +++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 15 ++--- .../views/nodes/formattedText/RichTextMenu.tsx | 44 +++++--------- src/client/views/nodes/trails/PresElementBox.tsx | 17 ++---- src/client/views/pdf/AnchorMenu.tsx | 14 ++--- src/client/views/pdf/PDFViewer.tsx | 22 +++---- 81 files changed, 578 insertions(+), 911 deletions(-) create mode 100644 src/client/views/ObservableReactComponent.tsx (limited to 'src/client/views/OverlayView.tsx') diff --git a/.vscode/settings.json b/.vscode/settings.json index 8849f30dd..5239d22c0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,5 +13,7 @@ "editor.defaultFormatter": "esbenp.prettier-vscode", "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "terminal.integrated.shellIntegration.showWelcome": false, + "terminal.integrated.shellIntegration.enabled": true } diff --git a/src/Utils.ts b/src/Utils.ts index d54760100..3a2bbf9a1 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -440,7 +440,12 @@ export namespace Utils { socket.on(message, (room: any) => handler(socket, room)); } } -export function copyProps(thing: { _prevProps: any; props: any; _props: any }) { +export function copyProps(thing: { props: any; _props: any }, prevProps: any) { + Object.keys(prevProps).forEach(action(pkey => + (prevProps)[pkey] !== (thing.props as any)[pkey] && + ((thing._props as any)[pkey] = (thing.props as any)[pkey]))); // prettier-ignore +} +export function copyPropsFull(thing: { _prevProps: any; props: any; _props: any }) { Object.keys(thing._prevProps).forEach(action(pkey => (thing._prevProps as any)[pkey] !== (thing.props as any)[pkey] && ((thing._props as any)[pkey] = (thing.props as any)[pkey]))); // prettier-ignore diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 7fcda75cc..4816f3317 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,4 +1,4 @@ -import { action, computed, makeObservable, observable, ObservableSet, observe, reaction } from 'mobx'; +import { action, computed, makeObservable, observable, ObservableSet, observe } from 'mobx'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; @@ -13,7 +13,6 @@ import { LightboxView } from '../views/LightboxView'; import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod } from '../views/nodes/DocumentView'; import { KeyValueBox } from '../views/nodes/KeyValueBox'; import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox'; -import { LoadingBox } from '../views/nodes/LoadingBox'; import { PresBox } from '../views/nodes/trails'; import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 7cf0d62d0..4bd6647c0 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,4 +1,4 @@ -import { action, makeObservable, observable } from 'mobx'; +import { action, makeObservable, observable, runInAction } from 'mobx'; import { Doc, Opt } from '../../fields/Doc'; import { DocViews } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; @@ -26,13 +26,13 @@ export class SelectionManager { } @action - public static SelectSchemaViewDoc(doc: Opt, deselectAllFirst?: boolean) { + public static SelectSchemaViewDoc = (doc: Opt, deselectAllFirst?: boolean) => { if (deselectAllFirst) this.DeselectAll(); this.Instance.SelectedSchemaDocument = doc; - } + }; @action - public static SelectView(docView: DocumentView, extendSelection: boolean): void { + public static SelectView = (docView: DocumentView | undefined, extendSelection: boolean): void => { if (!docView) this.DeselectAll(); else if (!docView.SELECTED) { if (!extendSelection) this.DeselectAll(); @@ -40,29 +40,29 @@ export class SelectionManager { docView.SELECTED = true; docView._props.whenChildContentsActiveChanged(true); } - } + }; @action - public static DeselectView(docView?: DocumentView): void { + public static DeselectView = (docView?: DocumentView): void => { if (docView && this.Instance.SelectedViews.includes(docView)) { docView.SELECTED = false; this.Instance.SelectedViews.splice(this.Instance.SelectedViews.indexOf(docView), 1); docView._props.whenChildContentsActiveChanged(false); } - } - @action - public static DeselectAll(except?: Doc): void { + }; + + public static DeselectAll = (except?: Doc): void => { const found = this.Instance.SelectedViews.find(dv => dv.Document === except); LinkManager.currentLink = undefined; LinkManager.currentLinkAnchor = undefined; - this.Instance.SelectedSchemaDocument = undefined; + runInAction(() => (this.Instance.SelectedSchemaDocument = undefined)); this.Instance.SelectedViews.forEach(dv => { dv.SELECTED = false; dv._props.whenChildContentsActiveChanged(false); }); this.Instance.SelectedViews.length = 0; if (found) this.SelectView(found, false); - } + }; public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED); public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx index f89624941..4c82b10fd 100644 --- a/src/client/views/AntimodeMenu.tsx +++ b/src/client/views/AntimodeMenu.tsx @@ -1,32 +1,25 @@ import { action, makeObservable, observable, runInAction } from 'mobx'; import * as React from 'react'; import { SettingsManager } from '../util/SettingsManager'; -import { copyProps } from '../../Utils'; import './AntimodeMenu.scss'; +import { ObservableReactComponent } from './ObservableReactComponent'; export interface AntimodeMenuProps {} /** * This is an abstract class that serves as the base for a PDF-style or Marquee-style * menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example. */ -export abstract class AntimodeMenu extends React.Component { +export abstract class AntimodeMenu extends ObservableReactComponent { protected _offsetY: number = 0; protected _offsetX: number = 0; protected _mainCont: React.RefObject = React.createRef(); protected _dragging: boolean = false; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - @observable protected _top: number = -300; @observable protected _left: number = -300; @observable protected _opacity: number = 0; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 118a2c5f5..e55bf24a1 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -6,9 +6,10 @@ import { StrCast } from '../../fields/Types'; import { SettingsManager } from '../util/SettingsManager'; import './ContextMenu.scss'; import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem'; +import { ObservableReactComponent } from './ObservableReactComponent'; @observer -export class ContextMenu extends React.Component { +export class ContextMenu extends ObservableReactComponent<{}> { static Instance: ContextMenu; private _ignoreUp = false; @@ -36,8 +37,8 @@ export class ContextMenu extends React.Component { constructor(props: any) { super(props); - makeObservable(this); ContextMenu.Instance = this; + makeObservable(this); } public setIgnoreEvents(ignore: boolean) { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 59b223c14..3c9d821a9 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -5,7 +5,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { UndoManager } from '../util/UndoManager'; import { SettingsManager } from '../util/SettingsManager'; -import { copyProps } from '../../Utils'; +import { ObservableReactComponent } from './ObservableReactComponent'; export interface OriginalMenuProps { description: string; @@ -27,24 +27,17 @@ export interface SubmenuProps { export type ContextMenuProps = OriginalMenuProps | SubmenuProps; @observer -export class ContextMenuItem extends React.Component { +export class ContextMenuItem extends ObservableReactComponent { @observable private _items: Array = []; @observable private overItem = false; - _prevProps: ContextMenuProps & { selected?: boolean }; - @observable _props: ContextMenuProps & { selected?: boolean }; - constructor(props: ContextMenuProps & { selected?: boolean }) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { - runInAction(() => this._items.length = 0); + runInAction(() => (this._items.length = 0)); if ((this.props as SubmenuProps)?.subitems) { (this.props as SubmenuProps).subitems?.forEach(i => runInAction(() => this._items.push(i))); } diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 35c0d617b..85cee83d4 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -27,6 +27,7 @@ import './DashboardView.scss'; import { Colors } from './global/globalEnums'; import { MainViewModal } from './MainViewModal'; import { ButtonType } from './nodes/FontIconBox/FontIconBox'; +import { ObservableReactComponent } from './ObservableReactComponent'; enum DashboardGroup { MyDashboards, @@ -36,9 +37,8 @@ enum DashboardGroup { // DashboardView is the view with the dashboard previews, rendered when the app first loads @observer -export class DashboardView extends React.Component { +export class DashboardView extends ObservableReactComponent<{}> { public static _urlState: HistoryUtil.DocUrl; - constructor(props: any) { super(props); makeObservable(this); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 2ce0c085a..235b0dc68 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,17 +1,17 @@ -import { action, computed, makeObservable, observable, runInAction, untracked } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; +import * as React from 'react'; +import { returnFalse } from '../../Utils'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; -import { Cast } from '../../fields/Types'; import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util'; -import { returnFalse } from '../../Utils'; -import { DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; -import { DocumentView } from './nodes/DocumentView'; -import * as React from 'react'; +import { DocUtils } from '../documents/Documents'; import { DocumentManager } from '../util/DocumentManager'; +import { ObservableReactComponent } from './ObservableReactComponent'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; +import { DocumentView } from './nodes/DocumentView'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) export interface DocComponentProps { @@ -20,18 +20,14 @@ export interface DocComponentProps { LayoutTemplateString?: string; } export function DocComponent

() { - class Component extends React.Component> { - @observable _props!: React.PropsWithChildren

; - constructor(props: React.PropsWithChildren

) { + class Component extends ObservableReactComponent> { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } - componentDidUpdate() { - // untracked(() => (this._props = this.props)); - } + //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then - @computed get Document() { + get Document() { return this._props.Document; } // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info @@ -57,24 +53,18 @@ interface ViewBoxBaseProps { renderDepth: number; } export function ViewBoxBaseComponent

() { - class Component extends React.Component> { - @observable _props: React.PropsWithChildren

; - constructor(props: React.PropsWithChildren

) { - super(props); - this._props = props; - makeObservable(this); - } + class Component extends ObservableReactComponent> { //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then //@computed get Document(): T { return schemaCtor(this.props.Document); } get Document() { return this._props.Document; } // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info - get layoutDoc() { + @computed get layoutDoc() { return Doc.Layout(this.Document); } // This is the data part of a document -- ie, the data that is constant across all views of the document - get dataDoc() { + @computed get dataDoc() { return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData]; } // key where data is stored @@ -99,13 +89,12 @@ export interface ViewBoxAnnotatableProps { isAnnotationOverlay?: boolean; } export function ViewBoxAnnotatableComponent

() { - class Component extends React.Component> { - @observable _props: React.PropsWithChildren

; - constructor(props: React.PropsWithChildren

) { + class Component extends ObservableReactComponent> { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } + @observable _annotationKeySuffix = () => 'annotations'; @observable _isAnyChildContentActive = false; //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index a8ad4150e..50ca3af06 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -28,6 +28,7 @@ import { GoogleRef } from './nodes/formattedText/FormattedTextBox'; import { PinProps } from './nodes/trails'; import { TemplateMenu } from './TemplateMenu'; import * as React from 'react'; +import { ObservableReactComponent } from './ObservableReactComponent'; // import * as higflyout from '@hig/flyout'; // export const { anchorPoints } = higflyout; // export const Flyout = higflyout.default; @@ -42,12 +43,11 @@ enum UtilityButtonState { } @observer -export class DocumentButtonBar extends React.Component<{ views: () => (DocumentView | undefined)[]; stack?: any }, {}> { +export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: any }> { private _dragRef = React.createRef(); private _pullAnimating = false; private _pushAnimating = false; private _pullColorAnimating = false; - @observable private pushIcon: IconProp = 'arrow-alt-circle-up'; @observable private pullIcon: IconProp = 'arrow-alt-circle-down'; @observable private pullColor: string = 'white'; @@ -60,12 +60,10 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV public static hasPushedHack = false; public static hasPulledHack = false; - @observable _props: { views: () => (DocumentView | undefined)[] }; constructor(props: { views: () => (DocumentView | undefined)[] }) { super(props); - this._props = props; + DocumentButtonBar.Instance = this; makeObservable(this); - runInAction(() => (DocumentButtonBar.Instance = this)); } public startPullOutcome = action((success: boolean) => { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8bcc1cb56..7003485d2 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -34,6 +34,7 @@ import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import * as React from 'react'; +import { ObservableReactComponent } from './ObservableReactComponent'; interface DocumentDecorationsProps { PanelWidth: number; @@ -42,7 +43,7 @@ interface DocumentDecorationsProps { boundsTop: number; } @observer -export class DocumentDecorations extends React.Component { +export class DocumentDecorations extends ObservableReactComponent { static Instance: DocumentDecorations; private _resizeHdlId = ''; private _keyinput = React.createRef(); @@ -66,11 +67,10 @@ export class DocumentDecorations extends React.Component; constructor(props: React.PropsWithChildren) { super(props); - this._props = props; makeObservable(this); + DocumentDecorations.Instance = this; document.addEventListener('pointermove', // show decorations whenever pointer moves outside of selection bounds. action(e => { diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 3db77be71..836a184eb 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; import { action, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as Autosuggest from 'react-autosuggest'; import { ObjectField } from '../../fields/ObjectField'; import './EditableView.scss'; import { DocumentIconContainer } from './nodes/DocumentIcon'; -import { OverlayView } from './OverlayView'; -import { copyProps } from '../../Utils'; import { FieldView, FieldViewProps } from './nodes/FieldView'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import { OverlayView } from './OverlayView'; export interface EditableProps { /** @@ -60,18 +60,15 @@ export interface EditableProps { * of the content, and set the value based on the entered string. */ @observer -export class EditableView extends React.Component { +export class EditableView extends ObservableReactComponent { private _ref = React.createRef(); private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null; _overlayDisposer?: () => void; _editingDisposer?: IReactionDisposer; @observable _editing: boolean = false; - _prevProps: EditableProps; - @observable _props: EditableProps; constructor(props: EditableProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); this._editing = this._props.editing ? true : false; } @@ -96,8 +93,7 @@ export class EditableView extends React.Component { ); } - componentDidUpdate() { - copyProps(this); + componentDidUpdate(prevProps: Readonly) { if (this._editing && this._props.editing === false) { this._inputref?.value && this.finalizeEdit(this._inputref.value, false, true, false); } else if (this._props.editing !== undefined) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4f96b9234..f65675792 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -8,20 +8,19 @@ import { observer } from 'mobx-react'; import 'normalize.css'; import * as React from 'react'; import '../../../node_modules/browndash-components/dist/styles/global.min.css'; +import { Utils, emptyFunction, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../Utils'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { DocCast, StrCast } from '../../fields/Types'; -import { emptyFunction, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils'; -import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; -import { Docs } from '../documents/Documents'; +import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; +import { Docs } from '../documents/Documents'; import { CaptureManager } from '../util/CaptureManager'; import { DocumentManager } from '../util/DocumentManager'; import { DragManager } from '../util/DragManager'; import { GroupManager } from '../util/GroupManager'; import { HistoryUtil } from '../util/History'; import { Hypothesis } from '../util/HypothesisUtils'; -import { ReportManager } from '../util/reportManager/ReportManager'; import { RTFMarkup } from '../util/RTFMarkup'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { SelectionManager } from '../util/SelectionManager'; @@ -30,13 +29,7 @@ import { SettingsManager } from '../util/SettingsManager'; import { SharingManager } from '../util/SharingManager'; import { SnappingManager } from '../util/SnappingManager'; import { Transform } from '../util/Transform'; -import { TimelineMenu } from './animationtimeline/TimelineMenu'; -import { CollectionDockingView } from './collections/CollectionDockingView'; -import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; -import { CollectionLinearView } from './collections/collectionLinear'; -import { CollectionMenu } from './collections/CollectionMenu'; -import { TabDocView } from './collections/TabDocView'; -import './collections/TreeView.scss'; +import { ReportManager } from '../util/reportManager/ReportManager'; import { ComponentDecorations } from './ComponentDecorations'; import { ContextMenu } from './ContextMenu'; import { DashboardView } from './DashboardView'; @@ -45,15 +38,24 @@ import { DocumentDecorations } from './DocumentDecorations'; import { GestureOverlay } from './GestureOverlay'; import { KeyManager } from './GlobalKeyHandler'; import { LightboxView } from './LightboxView'; -import { LinkMenu } from './linking/LinkMenu'; import './MainView.scss'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import { OverlayView } from './OverlayView'; +import { PreviewCursor } from './PreviewCursor'; +import { PropertiesView } from './PropertiesView'; +import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; +import { TimelineMenu } from './animationtimeline/TimelineMenu'; +import { CollectionDockingView } from './collections/CollectionDockingView'; +import { CollectionMenu } from './collections/CollectionMenu'; +import { TabDocView } from './collections/TabDocView'; +import './collections/TreeView.scss'; +import { CollectionFreeFormLinksView } from './collections/collectionFreeForm'; +import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; +import { CollectionLinearView } from './collections/collectionLinear'; +import { LinkMenu } from './linking/LinkMenu'; import { AudioBox } from './nodes/AudioBox'; import { DocButtonState } from './nodes/DocumentLinksButton'; import { DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod } from './nodes/DocumentView'; -import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; -import GenerativeFill from './nodes/generativeFill/GenerativeFill'; import { ImageBox } from './nodes/ImageBox'; import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; import { LinkDocPreview, LinkInfo } from './nodes/LinkDocPreview'; @@ -61,20 +63,19 @@ import { MapAnchorMenu } from './nodes/MapBox/MapAnchorMenu'; import { MapBox } from './nodes/MapBox/MapBox'; import { RadialMenu } from './nodes/RadialMenu'; import { TaskCompletionBox } from './nodes/TaskCompletedBox'; +import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; +import GenerativeFill from './nodes/generativeFill/GenerativeFill'; import { PresBox } from './nodes/trails'; -import { OverlayView } from './OverlayView'; import { AnchorMenu } from './pdf/AnchorMenu'; import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; -import { PreviewCursor } from './PreviewCursor'; -import { PropertiesView } from './PropertiesView'; -import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; -import { CollectionFreeFormLinksView } from './collections/collectionFreeForm'; const { default: { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } } = require('./global/globalCssVariables.module.scss'); // prettier-ignore const _global = (window /* browser */ || global) /* node */ as any; @observer -export class MainView extends React.Component { +export class MainView extends ObservableReactComponent<{}> { public static Instance: MainView; public static Live: boolean = false; private _docBtnRef = React.createRef(); @@ -1064,7 +1065,7 @@ export class MainView extends React.Component { - {this.mapBoxHack} + {/* {this.mapBoxHack} */} {/* */} diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 3f0db4258..2e27d1f70 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -15,6 +15,7 @@ import './MarqueeAnnotator.scss'; import { DocumentView } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { AnchorMenu } from './pdf/AnchorMenu'; +import { ObservableReactComponent } from './ObservableReactComponent'; const _global = (window /* browser */ || global) /* node */ as any; export interface MarqueeAnnotatorProps { @@ -38,23 +39,18 @@ export interface MarqueeAnnotatorProps { highlightDragSrcColor?: string; } @observer -export class MarqueeAnnotator extends React.Component { +export class MarqueeAnnotator extends ObservableReactComponent { private _start: { x: number; y: number } = { x: 0, y: 0 }; - @observable private _width: number = 0; - @observable private _height: number = 0; - @computed get top() { return Math.min(this._start.y, this._start.y + this._height); } // prettier-ignore - @computed get left() { return Math.min(this._start.x, this._start.x + this._width);} // prettier-ignore - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidMount() { - copyProps(this); - } + + @observable private _width: number = 0; + @observable private _height: number = 0; + @computed get top() { return Math.min(this._start.y, this._start.y + this._height); } // prettier-ignore + @computed get left() { return Math.min(this._start.x, this._start.x + this._width);} // prettier-ignore @action static clearAnnotations(savedAnnotations: ObservableMap) { diff --git a/src/client/views/ObservableReactComponent.tsx b/src/client/views/ObservableReactComponent.tsx new file mode 100644 index 000000000..2d8dc9af9 --- /dev/null +++ b/src/client/views/ObservableReactComponent.tsx @@ -0,0 +1,21 @@ +import { makeObservable, observable } from 'mobx'; +import * as React from 'react'; +import { copyProps } from '../../Utils'; +import './AntimodeMenu.scss'; +export interface AntimodeMenuProps {} + +/** + * This is an abstract class that serves as the base for a PDF-style or Marquee-style + * menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example. + */ +export abstract class ObservableReactComponent extends React.Component { + @observable _props: React.PropsWithChildren; + constructor(props: React.PropsWithChildren) { + super(props); + this._props = props; + makeObservable(this); + } + componentDidUpdate(prevProps: Readonly): void { + copyProps(this, prevProps); + } +} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 673432a60..915c3c18f 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -1,9 +1,9 @@ -import { action, computed, makeObservable, observable, toJS } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; import ReactLoading from 'react-loading'; -import { Utils, copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../Utils'; +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc } from '../../fields/Doc'; import { Height, Width } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; @@ -12,6 +12,7 @@ import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { LightboxView } from './LightboxView'; +import { ObservableReactComponent } from './ObservableReactComponent'; import './OverlayView.scss'; import { DefaultStyleProvider } from './StyleProvider'; import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; @@ -34,19 +35,14 @@ export interface OverlayWindowProps { } @observer -export class OverlayWindow extends React.Component { +export class OverlayWindow extends ObservableReactComponent { @observable x: number = 0; @observable y: number = 0; @observable width: number = 0; @observable height: number = 0; - - _prevProps: OverlayWindowProps; - @observable _props: OverlayWindowProps; constructor(props: OverlayWindowProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); - const opts = props.overlayOptions; this.x = opts.x; this.y = opts.y; @@ -54,10 +50,6 @@ export class OverlayWindow extends React.Component { this.height = opts.height || 200; } - componentDidUpdate() { - copyProps(this); - } - onPointerDown = (_: React.PointerEvent) => { document.removeEventListener('pointermove', this.onPointerMove); document.removeEventListener('pointerup', this.onPointerUp); @@ -115,7 +107,7 @@ export class OverlayWindow extends React.Component { } @observer -export class OverlayView extends React.Component { +export class OverlayView extends ObservableReactComponent<{}> { public static Instance: OverlayView; @observable.shallow _elements: JSX.Element[] = []; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 6e1a2cfb1..5ec9a7d46 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -1,17 +1,18 @@ import { action, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, Opt } from '../../fields/Doc'; import { lightOrDark, returnFalse } from '../../Utils'; -import { Docs, DocumentOptions, DocUtils } from '../documents/Documents'; +import { Doc, Opt } from '../../fields/Doc'; +import { DocUtils, Docs, DocumentOptions } from '../documents/Documents'; import { ImageUtils } from '../util/Import & Export/ImageUtils'; import { Transform } from '../util/Transform'; -import { undoBatch, UndoManager } from '../util/UndoManager'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { UndoManager, undoBatch } from '../util/UndoManager'; +import { ObservableReactComponent } from './ObservableReactComponent'; import './PreviewCursor.scss'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; @observer -export class PreviewCursor extends React.Component<{}> { +export class PreviewCursor extends ObservableReactComponent<{}> { static _instance: PreviewCursor; public static get Instance() { return PreviewCursor._instance; @@ -28,8 +29,8 @@ export class PreviewCursor extends React.Component<{}> { public Doc: Opt; constructor(props: any) { super(props); - PreviewCursor._instance = this; makeObservable(this); + PreviewCursor._instance = this; this._clickPoint = observable([0, 0]); document.addEventListener('keydown', this.onKeyPress); document.addEventListener('paste', this.paste, true); diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index 5bde9d3c4..a710e7816 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -1,14 +1,14 @@ -import { computed, makeObservable, observable } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { Cast, StrCast } from '../../fields/Types'; import { DocFocusOrOpen } from '../util/DocumentManager'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import './PropertiesDocContextSelector.scss'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { DocumentView, OpenWhere } from './nodes/DocumentView'; -import './PropertiesDocContextSelector.scss'; -import { copyProps } from '../../Utils'; type PropertiesDocContextSelectorProps = { DocView?: DocumentView; @@ -18,17 +18,12 @@ type PropertiesDocContextSelectorProps = { }; @observer -export class PropertiesDocContextSelector extends React.Component { - _prevProps: PropertiesDocContextSelectorProps; - @observable _props: PropertiesDocContextSelectorProps; - constructor(props: PropertiesDocContextSelectorProps) { +export class PropertiesDocContextSelector extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + @computed get _docs() { if (!this._props.DocView) return []; const target = this._props.DocView._props.Document; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 442d09739..c857c2d6b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1,14 +1,15 @@ -import * as React from 'react'; import { IconLookup } from '@fortawesome/fontawesome-svg-core'; import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox, Tooltip } from '@mui/material'; import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components'; import { concat } from 'lodash'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { ColorResult, SketchPicker } from 'react-color'; import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs" +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc'; import { AclAdmin, DocAcl, DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; @@ -16,8 +17,7 @@ import { InkField } from '../../fields/InkField'; import { List } from '../../fields/List'; import { ComputedField } from '../../fields/ScriptField'; import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; -import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; +import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocumentManager } from '../util/DocumentManager'; import { GroupManager } from '../util/GroupManager'; @@ -26,19 +26,20 @@ import { SelectionManager } from '../util/SelectionManager'; import { SettingsManager } from '../util/SettingsManager'; import { SharingManager } from '../util/SharingManager'; import { Transform } from '../util/Transform'; -import { undoable, undoBatch, UndoManager } from '../util/UndoManager'; +import { UndoManager, undoBatch, undoable } from '../util/UndoManager'; import { EditableView } from './EditableView'; import { FilterPanel } from './FilterPanel'; import { InkStrokeProperties } from './InkStrokeProperties'; -import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView'; -import { KeyValueBox } from './nodes/KeyValueBox'; -import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; +import { ObservableReactComponent } from './ObservableReactComponent'; import { PropertiesButtons } from './PropertiesButtons'; import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector'; import { PropertiesDocContextSelector } from './PropertiesDocContextSelector'; import { PropertiesSection } from './PropertiesSection'; import './PropertiesView.scss'; import { DefaultStyleProvider } from './StyleProvider'; +import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView'; +import { KeyValueBox } from './nodes/KeyValueBox'; +import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; const _global = (window /* browser */ || global) /* node */ as any; interface PropertiesViewProps { @@ -49,15 +50,12 @@ interface PropertiesViewProps { } @observer -export class PropertiesView extends React.Component { +export class PropertiesView extends ObservableReactComponent { private _widthUndo?: UndoManager.Batch; public static Instance: PropertiesView | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); PropertiesView.Instance = this; } @@ -120,10 +118,6 @@ export class PropertiesView extends React.Component { ); } - componentDidUpdate() { - copyProps(this); - } - componentWillUnmount() { Object.values(this._disposers).forEach(disposer => disposer?.()); } diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 8251d20dc..5f20bc745 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable, makeObservable } from 'mobx'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { DocumentManager } from '../util/DocumentManager'; @@ -7,29 +7,23 @@ import { CompileScript, Transformer, ts } from '../util/Scripting'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { SettingsManager } from '../util/SettingsManager'; import { undoable } from '../util/UndoManager'; -import { DocumentIconContainer } from './nodes/DocumentIcon'; +import { ObservableReactComponent } from './ObservableReactComponent'; import { OverlayView } from './OverlayView'; import './ScriptingRepl.scss'; -import { copyProps } from '../../Utils'; +import { DocumentIconContainer } from './nodes/DocumentIcon'; interface ReplProps { scrollToBottom: () => void; value: { [key: string]: any }; name?: string; } -export class ScriptingObjectDisplay extends React.Component { +export class ScriptingObjectDisplay extends ObservableReactComponent { @observable collapsed = true; - _prevProps: ReplProps; - @observable _props: ReplProps; - constructor(props: ReplProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate(): void { - copyProps(this); - } @action toggle = () => { @@ -84,17 +78,12 @@ interface replValueProps { name?: string; } @observer -export class ScriptingValueDisplay extends React.Component { - _prevProps: replValueProps; - @observable _props: replValueProps; - constructor(props: replValueProps) { +export class ScriptingValueDisplay extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + render() { const val = this._props.name ? this._props.value[this._props.name] : this._props.value; if (typeof val === 'object') { @@ -126,7 +115,7 @@ export class ScriptingValueDisplay extends React.Component { } @observer -export class ScriptingRepl extends React.Component { +export class ScriptingRepl extends ObservableReactComponent<{}> { constructor(props: any) { super(props); makeObservable(this); diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 19473de2b..0f4a4260c 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -1,22 +1,23 @@ -import { computed, makeObservable, observable } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, returnAll, returnFalse, returnOne, returnZero } from '../../Utils'; import { Doc, DocListCast, Field, FieldResult, StrListCast } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { RichTextField } from '../../fields/RichTextField'; import { DocCast, NumCast, StrCast } from '../../fields/Types'; -import { copyProps, emptyFunction, returnAll, returnFalse, returnOne, returnTrue, returnZero } from '../../Utils'; -import { Docs, DocUtils } from '../documents/Documents'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; +import { DocUtils, Docs } from '../documents/Documents'; import { LinkManager } from '../util/LinkManager'; import { SearchUtil } from '../util/SearchUtil'; import { Transform } from '../util/Transform'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import './SidebarAnnos.scss'; +import { StyleProp } from './StyleProvider'; import { CollectionStackingView } from './collections/CollectionStackingView'; import { FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import './SidebarAnnos.scss'; -import { StyleProp } from './StyleProvider'; -import * as React from 'react'; interface ExtraProps { fieldKey: string; @@ -34,18 +35,12 @@ interface ExtraProps { moveDocument: (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean, annotationKey?: string) => boolean; } @observer -export class SidebarAnnos extends React.Component { - _prevProps: FieldViewProps & ExtraProps; - @observable _props: FieldViewProps & ExtraProps; - constructor(props: FieldViewProps & ExtraProps) { +export class SidebarAnnos extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); - // this._props.dataDoc[this.sidebarKey] = new List(); // bcz: can't do this here. it blows away existing things and isn't a robust solution for making sure the field exists -- instead this should happen when the document is created and/or shared - } - componentDidUpdate() { - copyProps(this); } + _stackRef = React.createRef(); @computed get allMetadata() { const keys = new Map>(); diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index f03e38850..a11c53d4d 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { computed } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Utils, returnFalse, returnZero } from '../../../Utils'; @@ -19,6 +19,10 @@ export class CollectionCarousel3DView extends CollectionSubView() { @computed get scrollSpeed() { return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed } + constructor(props: any) { + super(props); + makeObservable(this); + } private _dropDisposer?: DragManager.DragDropDisposer; diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 299a4d5d3..5d09f14ef 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { computed } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { StopEvent, emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils'; @@ -16,6 +16,11 @@ import { CollectionSubView } from './CollectionSubView'; export class CollectionCarouselView extends CollectionSubView() { private _dropDisposer?: DragManager.DragDropDisposer; + constructor(props: any) { + super(props); + makeObservable(this); + } + componentWillUnmount() { this._dropDisposer?.(); } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 4ddf9e69b..0d3ff8bba 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -1,5 +1,6 @@ -import { action, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { action, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import * as GoldenLayout from '../../../client/goldenLayout'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; @@ -10,7 +11,7 @@ import { List } from '../../../fields/List'; import { ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { GetEffectiveAcl, inheritParentAcls } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, incrementTitleCopy } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, incrementTitleCopy } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; @@ -19,6 +20,7 @@ import { DragManager } from '../../util/DragManager'; import { InteractionUtils } from '../../util/InteractionUtils'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; +import { SettingsManager } from '../../util/SettingsManager'; import { undoable, undoBatch, UndoManager } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; import { LightboxView } from '../LightboxView'; @@ -30,8 +32,6 @@ import './CollectionDockingView.scss'; import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; import { TabDocView } from './TabDocView'; -import * as React from 'react'; -import { SettingsManager } from '../../util/SettingsManager'; const _global = (window /* browser */ || global) /* node */ as any; @observer @@ -63,11 +63,8 @@ export class CollectionDockingView extends CollectionSubView() { private _goldenLayout: any = null; static _highlightStyleSheet: any = addStyleSheet(); - _prevProps: SubCollectionViewProps; - @override _props: SubCollectionViewProps; constructor(props: SubCollectionViewProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); if (this._props.renderDepth < 0) runInAction(() => (CollectionDockingView.Instance = this)); //Why is this here? @@ -77,10 +74,6 @@ export class CollectionDockingView extends CollectionSubView() { this.Document.myTrails; // this is equivalent to having a prefetchProxy for myTrails which is needed for the My Trails button in the UI which assumes that Doc.ActiveDashboard.myTrails is legit... } - componentDidUpdate() { - copyProps(this); - } - /** * Switches from dragging a document around a freeform canvas to dragging it as a tab to be docked. * diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 0905aa078..5dba9e72a 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, numberRange, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { ScriptField } from '../../../fields/ScriptField'; -import { emptyFunction, numberRange, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { CompileScript } from '../../util/Scripting'; @@ -14,6 +14,7 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { EditableView } from '../EditableView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { CollectionStackingView } from './CollectionStackingView'; import './CollectionStackingView.scss'; @@ -41,19 +42,18 @@ interface CMVFieldRowProps { } @observer -export class CollectionMasonryViewFieldRow extends React.Component { +export class CollectionMasonryViewFieldRow extends ObservableReactComponent { + constructor(props: any) { + super(props); + makeObservable(this); + } + @observable private _background = 'inherit'; @observable private _createEmbeddingSelected: boolean = false; @observable private heading: string = ''; @observable private color: string = '#f1efeb'; @observable private collapsed: boolean = false; @observable private _paletteOn = false; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = props; - makeObservable(this); - } private set _heading(value: string) { runInAction(() => this._props.headingObject && (this._props.headingObject.heading = this.heading = value)); } diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 08fcd544e..3ade2ab56 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -9,7 +9,7 @@ import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { RichTextField } from '../../../fields/RichTextField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; +import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 702775307..f9d258490 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Field, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; @@ -44,6 +44,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { public DividerWidth = 16; @observable docsDraggedRowCol: number[] = []; @observable _scroll = 0; + + constructor(props: any) { + super(props); + makeObservable(this); + } + @computed get chromeHidden() { return BoolCast(this.layoutDoc.chromeHidden) || this.props.onBrowseClick?.() ? true : false; } diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index a0f8b9c89..170b1f1ec 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, DocListCast } from '../../../fields/Doc'; import { ScriptField } from '../../../fields/ScriptField'; @@ -19,6 +19,11 @@ export class CollectionPileView extends CollectionSubView() { _originalChrome: any = ''; _disposers: { [name: string]: IReactionDisposer } = {}; + constructor(props: any) { + super(props); + makeObservable(this); + } + componentDidMount() { if (this.layoutEngine() !== computePassLayout.name && this.layoutEngine() !== computeStarburstLayout.name) { this.Document._freeform_pileEngine = computePassLayout.name; diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 1b14b31ac..d37a942d0 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -9,7 +9,7 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { Cast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { copyProps, emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils'; +import { emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; @@ -26,6 +26,7 @@ import { AudioWaveform } from '../nodes/audio/AudioWaveform'; import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from '../nodes/DocumentView'; import { LabelBox } from '../nodes/LabelBox'; import { VideoBox } from '../nodes/VideoBox'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import './CollectionStackedTimeline.scss'; export type CollectionStackedTimelineProps = { @@ -56,17 +57,10 @@ export enum TrimScope { export class CollectionStackedTimeline extends CollectionSubView() { @observable static SelectingRegion: CollectionStackedTimeline | undefined = undefined; @observable public static CurrentlyPlaying: DocumentView[]; - - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } static LabelScript: ScriptField; static LabelPlayScript: ScriptField; @@ -697,21 +691,15 @@ interface StackedTimelineAnchorProps { } @observer -class StackedTimelineAnchor extends React.Component { +class StackedTimelineAnchor extends ObservableReactComponent { _lastTimecode: number; _disposer: IReactionDisposer | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); this._lastTimecode = this._props.currentTimecode(); } - componentDidUpdate() { - copyProps(this); - } // updates marker document title to reflect correct timecodes computeTitle = () => { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index d6105c184..16adf4b96 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import * as CSS from 'csstype'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction, untracked } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -11,7 +11,7 @@ import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnFalse, returnNone, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnNone, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType } from '../../documents/DocumentTypes'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -31,7 +31,7 @@ import { StyleProp } from '../StyleProvider'; import { CollectionMasonryViewFieldRow } from './CollectionMasonryViewFieldRow'; import './CollectionStackingView.scss'; import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn'; -import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; +import { CollectionSubView } from './CollectionSubView'; const _global = (window /* browser */ || global) /* node */ as any; export type collectionStackingViewProps = { @@ -115,22 +115,15 @@ export class CollectionStackingView extends CollectionSubView>; - _props: React.PropsWithChildren>; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); - if (this.colHeaderData === undefined) { // TODO: what is a layout doc? Is it literally how this document is supposed to be layed out? // here we're making an empty list of column headers (again, what Mehek showed us) this.dataDoc['_' + this.fieldKey + '_columnHeaders'] = new List(); } } - componentDidUpdate() { - copyProps(this); - } // TODO: plj - these are the children children = (docs: Doc[]) => { diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 7ea146479..2302bfbc3 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction, untracked } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { RichTextField } from '../../../fields/RichTextField'; import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; +import { BoolCast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, setupMoveUpEvents, returnFalse, returnEmptyString } from '../../../Utils'; +import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; @@ -19,9 +19,9 @@ import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from '../EditableView'; -import './CollectionStackingView.scss'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; -import { Id } from '../../../fields/FieldSymbols'; +import './CollectionStackingView.scss'; +import { ObservableReactComponent } from '../ObservableReactComponent'; // So this is how we are storing a column interface CSVFieldColumnProps { @@ -49,7 +49,7 @@ interface CSVFieldColumnProps { } @observer -export class CollectionStackingViewFieldColumn extends React.Component { +export class CollectionStackingViewFieldColumn extends ObservableReactComponent { private dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; private _headerRef: React.RefObject = React.createRef(); @@ -58,10 +58,8 @@ export class CollectionStackingViewFieldColumn extends React.Component (this._props = this.props)); - } - @action componentDidMount() { this._disposers.collapser = reaction( diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 79b15fdb1..0131af6f2 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -1,5 +1,7 @@ -import { action, computed, makeObservable, observable, override, runInAction, untracked } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; +import * as React from 'react'; import * as rp from 'request-promise'; +import { Utils, returnFalse } from '../../../Utils'; import CursorField from '../../../fields/CursorField'; import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; import { AclPrivate } from '../../../fields/DocSymbols'; @@ -10,21 +12,19 @@ import { BoolCast, Cast, ScriptCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; -import { returnFalse, Utils } from '../../../Utils'; import { DocServer } from '../../DocServer'; -import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents'; -import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; +import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocUtils, Docs, DocumentOptions } from '../../documents/Documents'; import { DragManager, dropActionType } from '../../util/DragManager'; import { ImageUtils } from '../../util/Import & Export/ImageUtils'; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../util/UndoManager'; import { ViewBoxBaseComponent } from '../DocComponent'; -import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { LoadingBox } from '../nodes/LoadingBox'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { CollectionView, CollectionViewProps } from './CollectionView'; -import * as React from 'react'; export interface SubCollectionViewProps extends CollectionViewProps { isAnyChildContentActive: () => boolean; @@ -35,16 +35,11 @@ export function CollectionSubView(moreProps?: X) { private dropDisposer?: DragManager.DragDropDisposer; private gestureDisposer?: GestureUtils.GestureEventDisposer; protected _mainCont?: HTMLDivElement; - @override _props: X & SubCollectionViewProps; constructor(props: any) { super(props); - this._props = props; makeObservable(this); } - componentDidUpdate() { - // untracked(() => (this._props = this.props)); - } @observable _focusFilters: Opt; // childFilters that are overridden when previewing a link to an anchor which has childFilters set on it @observable _focusRangeFilters: Opt; // childFiltersByRanges that are overridden when previewing a link to an anchor which has childFiltersByRanges set on it diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index e65f24702..c440a7e3f 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -1,5 +1,5 @@ import { toUpper } from 'lodash'; -import { action, computed, observable, runInAction } from 'mobx'; +import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Opt, StrListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; @@ -32,6 +32,11 @@ export class CollectionTimeView extends CollectionSubView() { @observable _viewDefDivClick: Opt; @observable _focusPivotField: Opt; + constructor(props: any) { + super(props); + makeObservable(this); + } + async componentDidMount() { this.props.setContentView?.(this); runInAction(() => { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 658d60523..7f8d42088 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,5 +1,6 @@ -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -7,7 +8,7 @@ import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../Utils'; +import { emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -23,10 +24,9 @@ import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { StyleProp } from '../StyleProvider'; import { CollectionFreeFormView } from './collectionFreeForm'; -import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; +import { CollectionSubView } from './CollectionSubView'; import './CollectionTreeView.scss'; import { TreeView } from './TreeView'; -import * as React from 'react'; const _global = (window /* browser */ || global) /* node */ as any; export type collectionTreeViewProps = { @@ -59,16 +59,10 @@ export class CollectionTreeView extends CollectionSubView = new Set(); // list of tree view items to monitor for height changes private observer: any; // observer for monitoring tree view items. - _prevProps: React.PropsWithChildren>; - @override _props: React.PropsWithChildren>; - constructor(props: React.PropsWithChildren>) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } get dataDoc() { return this._props.TemplateDataDocument || this.Document; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index e84c12e02..f1ef52e60 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,14 +1,14 @@ -import { IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { returnEmptyString } from '../../../Utils'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { ObjectField } from '../../../fields/ObjectField'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, returnEmptyString } from '../../../Utils'; -import { DocUtils } from '../../documents/Documents'; import { CollectionViewType } from '../../documents/DocumentTypes'; +import { DocUtils } from '../../documents/Documents'; import { dropActionType } from '../../util/DragManager'; import { ImageUtils } from '../../util/Import & Export/ImageUtils'; import { ContextMenu } from '../ContextMenu'; @@ -19,19 +19,19 @@ import { FieldView, FieldViewProps } from '../nodes/FieldView'; import { CollectionCarousel3DView } from './CollectionCarousel3DView'; import { CollectionCarouselView } from './CollectionCarouselView'; import { CollectionDockingView } from './CollectionDockingView'; -import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; -import { CollectionGridView } from './collectionGrid/CollectionGridView'; -import { CollectionLinearView } from './collectionLinear'; -import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; -import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView'; import { CollectionNoteTakingView } from './CollectionNoteTakingView'; import { CollectionPileView } from './CollectionPileView'; -import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView'; import { CollectionStackingView } from './CollectionStackingView'; import { SubCollectionViewProps } from './CollectionSubView'; import { CollectionTimeView } from './CollectionTimeView'; import { CollectionTreeView } from './CollectionTreeView'; import './CollectionView.scss'; +import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; +import { CollectionGridView } from './collectionGrid/CollectionGridView'; +import { CollectionLinearView } from './collectionLinear'; +import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; +import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView'; +import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView'; const path = require('path'); interface CollectionViewProps_ extends FieldViewProps { @@ -78,16 +78,10 @@ export class CollectionView extends ViewBoxAnnotatableComponent; - @override _props: React.PropsWithChildren; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); - runInAction(() => (this._annotationKeySuffix = returnEmptyString)); - } - componentDidUpdate() { - copyProps(this); + this._annotationKeySuffix = returnEmptyString; } componentDidMount() { diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 8bc0f62dc..2eb13fd2f 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -2,40 +2,41 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Popup, Type } from 'browndash-components'; import { clamp } from 'lodash'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, reaction, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableSet, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; +import { DashColor, Utils, emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { FieldId } from '../../../fields/RefField'; +import { ComputedField } from '../../../fields/ScriptField'; import { Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { copyProps, DashColor, emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoable, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoable } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; -import { Colors } from '../global/globalEnums'; import { LightboxView } from '../LightboxView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; +import { Colors } from '../global/globalEnums'; import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, OpenWhereMod } from '../nodes/DocumentView'; -import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { KeyValueBox } from '../nodes/KeyValueBox'; +import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { PinProps, PresBox, PresMovement } from '../nodes/trails'; -import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; import { CollectionDockingView } from './CollectionDockingView'; -import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; import { CollectionView } from './CollectionView'; import './TabDocView.scss'; -import * as React from 'react'; -import { Docs } from '../../documents/Documents'; -import { ComputedField } from '../../../fields/ScriptField'; +import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; const _global = (window /* browser */ || global) /* node */ as any; interface TabDocViewProps { @@ -44,16 +45,13 @@ interface TabDocViewProps { glContainer: any; } @observer -export class TabDocView extends React.Component { +export class TabDocView extends ObservableReactComponent { static _allTabs = new ObservableSet(); _mainCont: HTMLDivElement | null = null; _tabReaction: IReactionDisposer | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } @@ -341,9 +339,8 @@ export class TabDocView extends React.Component { // { fireImmediately: true }); runInAction(() => TabDocView._allTabs.add(this)); } - componentDidUpdate() { + componentDidUpdate(prevProps: Readonly) { this._view && DocumentManager.Instance.AddView(this._view); - copyProps(this); } componentWillUnmount() { @@ -521,14 +518,14 @@ interface TabMiniThumbProps { miniTop: () => number; miniLeft: () => number; } -@observer + class TabMiniThumb extends React.Component { render() { return

; } } @observer -export class TabMinimapView extends React.Component { +export class TabMinimapView extends ObservableReactComponent { static miniStyleProvider = (doc: Opt, props: Opt, property: string): any => { if (doc) { switch (property.split(':')[0]) { @@ -556,12 +553,6 @@ export class TabMinimapView extends React.Component { } }; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = props; - makeObservable(this); - } @computed get renderBounds() { const compView = this._props.tabView()?.ComponentView as CollectionFreeFormView; const bounds = compView?.freeformData?.(true)?.bounds; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 224d74882..52ecdfbec 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1,8 +1,10 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconButton, Size } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +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 { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -12,9 +14,8 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils'; -import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocUtils, Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; @@ -22,19 +23,19 @@ import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SettingsManager } from '../../util/SettingsManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoable, undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch, undoable } from '../../util/UndoManager'; import { EditableView } from '../EditableView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { StyleProp } from '../StyleProvider'; import { DocumentView, DocumentViewInternal, DocumentViewProps, OpenWhere, StyleProviderFunc } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; +import { KeyValueBox } from '../nodes/KeyValueBox'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; -import { KeyValueBox } from '../nodes/KeyValueBox'; -import { StyleProp } from '../StyleProvider'; import { CollectionTreeView, TreeViewType } from './CollectionTreeView'; import { CollectionView } from './CollectionView'; import { TreeSort } from './TreeSort'; import './TreeView.scss'; -import * as React from 'react'; const { default: { TREE_BULLET_WIDTH } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore export interface TreeViewProps { @@ -86,7 +87,7 @@ const treeBulletWidth = function () { * treeView_ExpandedView : name of field whose contents are being displayed as the document's subtree */ @observer -export class TreeView extends React.Component { +export class TreeView extends ObservableReactComponent { static _editTitleOnLoad: Opt<{ id: string; parent: TreeView | CollectionTreeView | undefined }>; static _openTitleScript: Opt; static _openLevelScript: Opt; @@ -254,11 +255,8 @@ export class TreeView extends React.Component { static GetRunningChildren = new Map(); static ToggleChildrenRun = new Map void>(); - _prevProps: TreeViewProps; - @observable _props: TreeViewProps; constructor(props: TreeViewProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); if (!TreeView._openLevelScript) { TreeView._openTitleScript = ScriptField.MakeScript('scriptContext.setEditTitle(documentView)', { scriptContext: 'any', documentView: 'any' }); @@ -297,8 +295,7 @@ export class TreeView extends React.Component { this._props.hierarchyIndex !== undefined && this._props.RemFromMap?.(this.Document, this._props.hierarchyIndex); } - componentDidUpdate() { - copyProps(this); + componentDidUpdate(prevProps: Readonly) { this._disposers.opening = reaction( () => this.treeViewOpen, open => !open && (this._renderCount = 20) diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx index dd7e12e41..0d5fcdaeb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -1,8 +1,9 @@ -import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { IReactionDisposer, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { copyProps } from '../../../../Utils'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import './CollectionFreeFormView.scss'; +import { copyProps } from '../../../../Utils'; /** * An Fsa Arc. The first array element is a test condition function that will be observed. @@ -47,14 +48,11 @@ export interface CollectionFreeFormInfoStateProps { } @observer -export class CollectionFreeFormInfoState extends React.Component { +export class CollectionFreeFormInfoState extends ObservableReactComponent { _disposers: IReactionDisposer[] = []; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } @@ -62,7 +60,7 @@ export class CollectionFreeFormInfoState extends React.Component this.State[key]); + return Object.keys(this.State ?? []).map(key => this.State?.[key]); } clearState = () => this._disposers.map(disposer => disposer()); @@ -84,8 +82,8 @@ export class CollectionFreeFormInfoState extends React.Component) { + copyProps(this, prevProps); this.clearState(); this.initState(); } @@ -93,6 +91,6 @@ export class CollectionFreeFormInfoState extends React.Component{this.State[StateMessage]}
; + return
{this.State?.[StateMessage]}
; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index f0a052c1d..4d3752c02 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -1,21 +1,13 @@ -import { IReactionDisposer, computed, observable, reaction, action, runInAction, makeObservable } from 'mobx'; +import { IReactionDisposer, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { Doc } from '../../../../fields/Doc'; -import { ScriptField } from '../../../../fields/ScriptField'; -import { PresBox } from '../../nodes/trails/PresBox'; -import './CollectionFreeFormView.scss'; import * as React from 'react'; -import { CollectionFreeFormView } from './CollectionFreeFormView'; -import { NumCast } from '../../../../fields/Types'; +import { Doc } from '../../../../fields/Doc'; import { LinkManager } from '../../../util/LinkManager'; -import { InkTool } from '../../../../fields/InkField'; -import { LinkDocPreview } from '../../nodes/LinkDocPreview'; -import { DocumentLinksButton, DocButtonState } from '../../nodes/DocumentLinksButton'; -import { DocumentManager } from '../../../util/DocumentManager'; -import { CollectionFreeFormInfoState, infoState, StateMessage, infoArc, StateEntryFunc, InfoState } from './CollectionFreeFormInfoState'; -import { string32 } from 'pdfjs-dist/types/src/shared/util'; -import { any } from 'bluebird'; -import { copyProps } from '../../../../Utils'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { DocButtonState } from '../../nodes/DocumentLinksButton'; +import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState'; +import { CollectionFreeFormView } from './CollectionFreeFormView'; +import './CollectionFreeFormView.scss'; export interface CollectionFreeFormInfoUIProps { Document: Doc; @@ -23,7 +15,7 @@ export interface CollectionFreeFormInfoUIProps { } @observer -export class CollectionFreeFormInfoUI extends React.Component { +export class CollectionFreeFormInfoUI extends ObservableReactComponent { private _disposers: { [name: string]: IReactionDisposer } = {}; @observable _currState: infoState | undefined = undefined; @@ -33,17 +25,12 @@ export class CollectionFreeFormInfoUI extends React.Component; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + + constructor(props: any) { super(props); - this._props = this._prevProps = this.props; makeObservable(this); this.currState = this.setupStates(); } - componentDidUpdate() { - copyProps(this); - } setCurrState = (state: infoState) => { if (state) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index be3d2439c..6337c8d34 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,19 +1,20 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, Field } from '../../../../fields/Doc'; import { Brushed, DocCss } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { Cast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; import { LinkManager } from '../../../util/LinkManager'; import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../../nodes/DocumentView'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import './CollectionFreeFormLinkView.scss'; -import * as React from 'react'; export interface CollectionFreeFormLinkViewProps { A: DocumentView; @@ -24,22 +25,16 @@ export interface CollectionFreeFormLinkViewProps { // props.screentolocatransform @observer -export class CollectionFreeFormLinkView extends React.Component { +export class CollectionFreeFormLinkView extends ObservableReactComponent { @observable _opacity: number = 0; @observable _start = 0; _anchorDisposer: IReactionDisposer | undefined; _timeout: NodeJS.Timeout | undefined; - _prevProps: CollectionFreeFormLinkViewProps; - @observable _props: CollectionFreeFormLinkViewProps; - constructor(props: CollectionFreeFormLinkViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } componentWillUnmount() { this._anchorDisposer?.(); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index aa40fb809..1f4688729 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,6 @@ import { Bezier } from 'bezier-js'; import { Colors } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, toJS } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction, toJS } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -16,7 +16,7 @@ import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../ import { ImageField } from '../../../../fields/URLField'; import { TraceMobx } from '../../../../fields/util'; import { GestureUtils } from '../../../../pen-gestures/GestureUtils'; -import { aggregateBounds, copyProps, DashColor, emptyFunction, intersectRect, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CognitiveServices } from '../../../cognitive_services/CognitiveServices'; import { Docs, DocUtils } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; @@ -43,7 +43,7 @@ import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../../nodes/trails/PresBox'; import { CreateImage } from '../../nodes/WebBoxRenderer'; import { StyleProp } from '../../StyleProvider'; -import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; +import { CollectionSubView } from '../CollectionSubView'; import { TreeViewType } from '../CollectionTreeView'; import { CollectionFreeFormBackgroundGrid } from './CollectionFreeFormBackgroundGrid'; import { CollectionFreeFormInfoUI } from './CollectionFreeFormInfoUI'; @@ -72,17 +72,10 @@ export class CollectionFreeFormView extends CollectionSubView>; - @override _props: React.PropsWithChildren>; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - @observable public static ShowPresPaths = false; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx index 825bd5f19..7aa68b0d9 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx @@ -20,7 +20,6 @@ export class MarqueeOptionsMenu extends AntimodeMenu { public isShown = () => this._opacity > 0; constructor(props: Readonly<{}>) { super(props); - MarqueeOptionsMenu.Instance = this; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 10beb120a..2c65726b2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,5 +1,7 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Utils, intersectRect, lightOrDark, returnFalse } from '../../../../Utils'; import { Doc, Opt } from '../../../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; @@ -7,25 +9,24 @@ import { InkData, InkField, InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; import { RichTextField } from '../../../../fields/RichTextField'; import { Cast, FieldValue, NumCast, StrCast } from '../../../../fields/Types'; -import { ImageField, nullAudio } from '../../../../fields/URLField'; +import { ImageField } from '../../../../fields/URLField'; import { GetEffectiveAcl } from '../../../../fields/util'; -import { intersectRect, lightOrDark, returnFalse, Utils } from '../../../../Utils'; import { CognitiveServices } from '../../../cognitive_services/CognitiveServices'; -import { Docs, DocumentOptions, DocUtils } from '../../../documents/Documents'; import { DocumentType } from '../../../documents/DocumentTypes'; +import { DocUtils, Docs, DocumentOptions } from '../../../documents/Documents'; import { SelectionManager } from '../../../util/SelectionManager'; +import { freeformScrollMode } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; -import { undoBatch, UndoManager } from '../../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { PreviewCursor } from '../../PreviewCursor'; import { DocumentView, OpenWhere } from '../../nodes/DocumentView'; -import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { pasteImageBitmap } from '../../nodes/WebBoxRenderer'; -import { PreviewCursor } from '../../PreviewCursor'; +import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { SubCollectionViewProps } from '../CollectionSubView'; import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './MarqueeView.scss'; -import * as React from 'react'; -import { freeformScrollMode } from '../../../util/SettingsManager'; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -51,16 +52,14 @@ export interface MarqueeViewBounds { } @observer -export class MarqueeView extends React.Component { +export class MarqueeView extends ObservableReactComponent { public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) { const ps = NumCast(pinDoc._freeform_scale, 1); return { left: NumCast(pinDoc._freeform_panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._freeform_panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps }; } - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 697a11ccc..1e19964d7 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -1,4 +1,4 @@ -import { action, computed, Lambda, observable, reaction } from 'mobx'; +import { action, computed, Lambda, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, Opt } from '../../../../fields/Doc'; @@ -27,6 +27,11 @@ export class CollectionGridView extends CollectionSubView() { @observable private _scroll: number = 0; // required to make sure the decorations box container updates on scroll private dropLocation: object = {}; // sets the drop location for external drops + constructor(props: any) { + super(props); + makeObservable(this); + } + onChildClickHandler = () => ScriptCast(this.Document.onChildClick); @computed get numCols() { diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index a9782f699..f1fb68003 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -1,26 +1,26 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { Toggle, ToggleType, Type } from 'browndash-components'; -import { action, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { IReactionDisposer, action, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, emptyFunction, returnEmptyDoclist, returnTrue } from '../../../../Utils'; import { Doc, Opt } from '../../../../fields/Doc'; import { Height, Width } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { BranchingTrailManager } from '../../../util/BranchingTrailManager'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager, dropActionType } from '../../../util/DragManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; +import { UndoStack } from '../../UndoStack'; import { DocumentLinksButton } from '../../nodes/DocumentLinksButton'; import { DocumentView } from '../../nodes/DocumentView'; import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup'; -import { UndoStack } from '../../UndoStack'; import { CollectionStackedTimeline } from '../CollectionStackedTimeline'; -import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; +import { CollectionSubView } from '../CollectionSubView'; import './CollectionLinearView.scss'; /** @@ -33,24 +33,15 @@ import './CollectionLinearView.scss'; */ @observer export class CollectionLinearView extends CollectionSubView() { - @observable public addMenuToggle = React.createRef(); - @observable private _selectedIndex = -1; private _dropDisposer?: DragManager.DragDropDisposer; private _widthDisposer?: IReactionDisposer; private _selectedDisposer?: IReactionDisposer; - _prevProps: SubCollectionViewProps; - @override _props: SubCollectionViewProps; - constructor(props: SubCollectionViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentWillUnmount() { this._dropDisposer?.(); this._widthDisposer?.(); diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 037786abf..b951a4b17 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -1,7 +1,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { Button } from 'browndash-components'; -import { action, computed } from 'mobx'; +import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../../fields/Doc'; @@ -37,6 +37,11 @@ const resizerWidth = 8; @observer export class CollectionMulticolumnView extends CollectionSubView() { + constructor(props: any) { + super(props); + makeObservable(this); + } + /** * @returns the list of layout documents whose width unit is * *, denoting that it will be displayed with a ratio, not fixed pixel, value @@ -238,8 +243,8 @@ export class CollectionMulticolumnView extends CollectionSubView() { return this.props.isContentActive?.() === false || childDocsActive === false ? false // : this.props.isDocumentActive?.() && childDocsActive - ? true - : undefined; + ? true + : undefined; }; getDisplayDoc = (childLayout: Doc) => { const width = () => this.lookupPixels(childLayout); diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index bbf3481dd..f1c6c6e1e 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -1,4 +1,4 @@ -import { action, computed } from 'mobx'; +import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../../fields/Doc'; @@ -33,6 +33,11 @@ const resizerHeight = 8; @observer export class CollectionMultirowView extends CollectionSubView() { + constructor(props: any) { + super(props); + makeObservable(this); + } + /** * @returns the list of layout documents whose width unit is * *, denoting that it will be displayed with a ratio, not fixed pixel, value @@ -234,8 +239,8 @@ export class CollectionMultirowView extends CollectionSubView() { return this.props.isContentActive?.() === false || childDocsActive === false ? false // : this.props.isDocumentActive?.() && childDocsActive - ? true - : undefined; + ? true + : undefined; }; getDisplayDoc = (layout: Doc) => { const height = () => this.lookupPixels(layout); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 276415d56..2546f5b02 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, makeObservable, observable, ObservableMap, observe, override } from 'mobx'; +import { action, computed, makeObservable, observable, ObservableMap, observe } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; @@ -18,8 +18,9 @@ import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; import { DocFocusOptions, DocumentView, DocumentViewProps } from '../../nodes/DocumentView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; -import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; +import { CollectionSubView } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; @@ -57,6 +58,11 @@ export class CollectionSchemaView extends CollectionSubView() { private _tableContentRef: HTMLDivElement | null = null; private _menuTarget = React.createRef(); + constructor(props: any) { + super(props); + makeObservable(this); + } + static _rowHeight: number = 50; static _rowSingleLineHeight: number = 32; public static _minColWidth: number = 25; @@ -79,18 +85,6 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _filterSearchValue: string = ''; @observable _selectedCell: [Doc, number] | undefined = undefined; - _prevProps: SubCollectionViewProps; - @override _props: SubCollectionViewProps; - constructor(props: SubCollectionViewProps) { - super(props); - this._props = this._prevProps = props; - makeObservable(this); - } - - componentDidUpdate() { - copyProps(this); - } - // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { return this._menuTarget.current; @@ -959,17 +953,12 @@ interface CollectionSchemaViewDocProps { } @observer -class CollectionSchemaViewDoc extends React.Component { - _prevProps: CollectionSchemaViewDocProps; - @observable _props; - constructor(props: CollectionSchemaViewDocProps) { +class CollectionSchemaViewDoc extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + tableWidthFunc = () => this._props.schema.tableWidth; screenToLocalXf = () => this._props.schema._props.ScreenToLocalTransform().translate(0, -this._props.rowHeight() - this._props.index * this._props.rowHeight()); noOpacityStyleProvider = (doc: Opt, props: Opt, property: string) => { diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 737d7e0f4..5a3be826b 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; import { IconButton, Size } from 'browndash-components'; -import { computed, makeObservable, override } from 'mobx'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; +import * as React from 'react'; import { CgClose } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; +import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; import { Doc } from '../../../../fields/Doc'; import { BoolCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; import { DragManager } from '../../../util/DragManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; @@ -30,16 +30,10 @@ export class SchemaRowBox extends ViewBoxBaseComponent this._ref?.getBoundingClientRect(); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index bcfe2c232..85269028b 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -1,27 +1,28 @@ -import * as React from 'react'; -import Select, { MenuPlacement } from 'react-select'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; +import * as React from 'react'; import DatePicker from 'react-datepicker'; +import Select from 'react-select'; +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../Utils'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field } from '../../../../fields/Doc'; import { RichTextField } from '../../../../fields/RichTextField'; import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, Utils } from '../../../../Utils'; import { FInfo } from '../../../documents/Documents'; import { DocFocusOrOpen } from '../../../util/DocumentManager'; import { Transform } from '../../../util/Transform'; -import { undoable, undoBatch } from '../../../util/UndoManager'; +import { undoBatch, undoable } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { DefaultStyleProvider } from '../../StyleProvider'; import { Colors } from '../../global/globalEnums'; import { OpenWhere } from '../../nodes/DocumentView'; -import { FieldView, FieldViewProps } from '../../nodes/FieldView'; -import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; +import { FieldViewProps } from '../../nodes/FieldView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; -import { DefaultStyleProvider } from '../../StyleProvider'; -import { CollectionSchemaView, ColumnType, FInfotoColType } from './CollectionSchemaView'; +import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; +import { ColumnType, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; export interface SchemaTableCellProps { @@ -47,7 +48,12 @@ export interface SchemaTableCellProps { } @observer -export class SchemaTableCell extends React.Component { +export class SchemaTableCell extends ObservableReactComponent { + constructor(props: any) { + super(props); + makeObservable(this); + } + static addFieldDoc = (doc: Doc, where: OpenWhere) => { DocFocusOrOpen(doc); return true; @@ -95,12 +101,6 @@ export class SchemaTableCell extends React.Component { return { color, textDecoration, fieldProps, cursor, pointerEvents }; } - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = props; - } - @computed get selected() { const selected: [Doc, number] | undefined = this._props.selectedCell(); return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col; @@ -182,16 +182,14 @@ export class SchemaTableCell extends React.Component { // mj: most of this is adapted from old schema code so I'm not sure what it does tbh @observer -export class SchemaImageCell extends React.Component { - @observable _previewRef: HTMLImageElement | undefined = undefined; - - _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaImageCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } + @observable _previewRef: HTMLImageElement | undefined = undefined; + choosePath(url: URL) { if (url.protocol === 'data') return url.href; // if the url ises the data protocol, just return the href if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver @@ -251,16 +249,13 @@ export class SchemaImageCell extends React.Component { } @observer -export class SchemaDateCell extends React.Component { - @observable _pickingDate: boolean = false; - - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaDateCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } + @observable _pickingDate: boolean = false; @computed get date(): DateField { // if the cell is a date field, cast then contents to a date. Otherrwwise, make the contents undefined. return DateCast(this._props.Document[this._props.fieldKey]); @@ -282,11 +277,9 @@ export class SchemaDateCell extends React.Component { } } @observer -export class SchemaRTFCell extends React.Component { - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaRTFCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } @@ -306,11 +299,9 @@ export class SchemaRTFCell extends React.Component { } } @observer -export class SchemaBoolCell extends React.Component { - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaBoolCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } @@ -352,11 +343,9 @@ export class SchemaBoolCell extends React.Component { } } @observer -export class SchemaEnumerationCell extends React.Component { - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { +export class SchemaEnumerationCell extends ObservableReactComponent { + constructor(props: any) { super(props); - this._props = props; makeObservable(this); } diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index af22f41e1..b7376e901 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -1,13 +1,14 @@ import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc } from '../../../fields/Doc'; import { LinkManager } from '../../util/LinkManager'; +import { SettingsManager } from '../../util/SettingsManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentView } from '../nodes/DocumentView'; import { LinkInfo } from '../nodes/LinkDocPreview'; import './LinkMenu.scss'; import { LinkMenuGroup } from './LinkMenuGroup'; -import * as React from 'react'; -import { SettingsManager } from '../../util/SettingsManager'; interface Props { docView: DocumentView; @@ -20,10 +21,10 @@ interface Props { * the outermost component for the link menu of a node that contains a list of its linked nodes */ @observer -export class LinkMenu extends React.Component { +export class LinkMenu extends ObservableReactComponent { _editorRef = React.createRef(); @observable _linkMenuRef = React.createRef(); - constructor(props: Props) { + constructor(props: any) { super(props); makeObservable(this); } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index d77525e04..06073b52c 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -1,23 +1,24 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, observable, makeObservable } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; import { Cast, DocCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; -import { emptyFunction, returnFalse, setupMoveUpEvents, copyProps } from '../../../Utils'; -import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; -import { undoBatch } from '../../util/UndoManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentView, DocumentViewInternal, OpenWhere } from '../nodes/DocumentView'; -import { LinkDocPreview, LinkInfo } from '../nodes/LinkDocPreview'; +import { LinkInfo } from '../nodes/LinkDocPreview'; import './LinkMenuItem.scss'; -import * as React from 'react'; +import { undoBatch } from '../../util/UndoManager'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { DocumentType } from '../../documents/DocumentTypes'; interface LinkMenuItemProps { groupType: string; @@ -50,20 +51,13 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume } @observer -export class LinkMenuItem extends React.Component { +export class LinkMenuItem extends ObservableReactComponent { private _drag = React.createRef(); _editRef = React.createRef(); - - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } @observable private _showMore: boolean = false; @action toggleShowMore(e: React.PointerEvent) { diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 0c671f7e3..567cf193e 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { DateField } from '../../../fields/DateField'; import { Doc } from '../../../fields/Doc'; import { ComputedField } from '../../../fields/ScriptField'; import { Cast, DateCast, NumCast } from '../../../fields/Types'; import { AudioField, nullAudio } from '../../../fields/URLField'; -import { copyProps, emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { Networking } from '../../Network'; import { DragManager } from '../../util/DragManager'; @@ -17,7 +17,7 @@ import { undoBatch } from '../../util/UndoManager'; import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; import './AudioBox.scss'; import { DocFocusOptions } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; @@ -54,19 +54,13 @@ export class AudioBox extends ViewBoxAnnotatableComponent() { return FieldView.LayoutString(AudioBox, fieldKey); } - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + public static Enabled = false; + + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - public static Enabled = false; - static topControlsHeight = 30; // height of upper controls above timeline static bottomControlsHeight = 20; // height of lower controls below timeline diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 8e7a6914f..c97c879af 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,21 +1,21 @@ -import { action, computed, observable, makeObservable, reaction, runInAction, override } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { OmitKeys, numberRange } from '../../../Utils'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ComputedField } from '../../../fields/ScriptField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, numberRange, OmitKeys } from '../../../Utils'; import { DocumentManager } from '../../util/DocumentManager'; +import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; -import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { DocComponent } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; +import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import './CollectionFreeFormDocumentView.scss'; import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView'; -import * as React from 'react'; -import { ScriptingGlobals } from '../../util/ScriptingGlobals'; export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentViewProps { x: number; @@ -37,11 +37,8 @@ export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentView } @observer export class CollectionFreeFormDocumentViewWrapper extends DocComponent() implements CollectionFreeFormDocumentViewProps { - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } @observable X = this.props.x; @@ -79,7 +76,7 @@ export class CollectionFreeFormDocumentViewWrapper extends DocComponent this.Highlight; // prettier-ignore w_Width = () => this.Width; // prettier-ignore w_Height = () => this.Height; // prettier-ignore - w_AutoDim = () => this.AutoDim; + w_AutoDim = () => this.AutoDim; // prettier-ignore w_Transition = () => this.Transition; // prettier-ignore w_DataTransition = () => this.DataTransition; // prettier-ignore @@ -87,7 +84,6 @@ export class CollectionFreeFormDocumentViewWrapper extends DocComponent this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore componentDidUpdate() { - copyProps(this); this.WrapperKeys.forEach(action(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower]))); } render() { @@ -124,6 +120,10 @@ export interface CollectionFreeFormDocumentViewProps { @observer export class CollectionFreeFormDocumentView extends DocComponent() { + constructor(props: any) { + super(props); + makeObservable(this); + } get displayName() { // this makes mobx trace() statements more descriptive return 'CollectionFreeFormDocumentView(' + this.Document.title + ')'; } // prettier-ignore @@ -143,13 +143,6 @@ export class CollectionFreeFormDocumentView extends DocComponent (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames - _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { - super(props); - this._props = Object.assign({}, props); - makeObservable(this); - } - get CollectionFreeFormView() { return this._props.CollectionFreeFormView; } diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 62523ba00..de382fca5 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -1,10 +1,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, makeObservable, observable, override } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; -import { Docs, DocUtils } from '../../documents/Documents'; +import { DocUtils, Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; @@ -13,7 +14,6 @@ import './ComparisonBox.scss'; import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { PinProps, PresBox } from './trails'; -import * as React from 'react'; @observer export class ComparisonBox extends ViewBoxAnnotatableComponent() { @@ -21,20 +21,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { } @observer -export class DocumentContentsView extends React.Component< +export class DocumentContentsView extends ObservableReactComponent< DocumentViewProps & FieldViewProps & { setHeight?: (height: number) => void; layout_fieldKey: string; } > { - @observable _props!: DocumentViewProps & - FieldViewProps & { - setHeight?: (height: number) => void; - layout_fieldKey: string; - }; constructor(props: any) { super(props); - this._props = props; makeObservable(this); } - componentDidUpdate(prevProps: Readonly void) | undefined; layout_fieldKey: string }>, prevState: Readonly<{}>, snapshot?: any): void { - // untracked(() => (this._props = this.props)); - // Object.keys(prevProps).forEach(pkey => (prevProps as any)[pkey] !== (this._props as any)[pkey] && console.log(pkey + ' ' + (prevProps as any)[pkey] + ' ' + (this._props as any)[pkey])); - } - @computed get layout(): string { TraceMobx(); if (this._props.LayoutTemplateString) return this._props.LayoutTemplateString; diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 9ec4d8c13..dfd610581 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -1,34 +1,28 @@ +import { Tooltip } from '@mui/material'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { DocumentView } from './DocumentView'; -import { DocumentManager } from '../../util/DocumentManager'; -import { Transformer, ts } from '../../util/Scripting'; +import { factory } from 'typescript'; import { Field } from '../../../fields/Doc'; -import { Tooltip } from '@mui/material'; -import { action, makeObservable, observable } from 'mobx'; import { Id } from '../../../fields/FieldSymbols'; -import { factory } from 'typescript'; -import { LightboxView } from '../LightboxView'; +import { DocumentManager } from '../../util/DocumentManager'; +import { Transformer, ts } from '../../util/Scripting'; import { SettingsManager } from '../../util/SettingsManager'; -import { copyProps } from '../../../Utils'; +import { LightboxView } from '../LightboxView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { DocumentView } from './DocumentView'; interface DocumentIconProps { view: DocumentView; index: number; } @observer -export class DocumentIcon extends React.Component { +export class DocumentIcon extends ObservableReactComponent { @observable _hovered = false; - _prevProps: DocumentIconProps; - @observable _props: DocumentIconProps; - constructor(props: DocumentIconProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } static get DocViews() { return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v._props.docViewPath())) : DocumentManager.Instance.DocumentViews; diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 19b43fd52..165057d21 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -2,20 +2,21 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { StopEvent, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; import { StrCast } from '../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents, StopEvent } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { Hypothesis } from '../../util/HypothesisUtils'; import { LinkManager } from '../../util/LinkManager'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../util/UndoManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import './DocumentLinksButton.scss'; import { DocumentView } from './DocumentView'; import { LinkDescriptionPopup } from './LinkDescriptionPopup'; import { TaskCompletionBox } from './TaskCompletedBox'; import { PinProps } from './trails'; -import * as React from 'react'; interface DocumentLinksButtonProps { View: DocumentView; @@ -44,26 +45,18 @@ export class DocButtonState { } } @observer -export class DocumentLinksButton extends React.Component { +export class DocumentLinksButton extends ObservableReactComponent { private _linkButton = React.createRef(); public static get StartLink() { return DocButtonState.Instance.StartLink; } // prettier-ignore public static set StartLink(value) { runInAction(() => (DocButtonState.Instance.StartLink = value)); } // prettier-ignore @observable public static StartLinkView: DocumentView | undefined = undefined; @observable public static AnnotationId: string | undefined = undefined; @observable public static AnnotationUri: string | undefined = undefined; - - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - @undoBatch onLinkButtonMoved = (e: PointerEvent) => { if (this._props.InMenu && this._props.StartLink) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 08ee708f7..343f770d5 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,9 +1,11 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { Dropdown, DropdownType, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction, untracked } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; // import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; +import * as React from 'react'; +import { Utils, emptyFunction, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../Utils'; import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; import { AclPrivate, Animation, AudioPlay, DocViews } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -15,12 +17,11 @@ import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { AudioField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick, Utils } from '../../../Utils'; -import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { DocServer } from '../../DocServer'; -import { DocOptions, Docs, DocUtils, FInfo } from '../../documents/Documents'; -import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; +import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; +import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocOptions, DocUtils, Docs, FInfo } from '../../documents/Documents'; import { DictationManager } from '../../util/DictationManager'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -32,13 +33,14 @@ import { SettingsManager } from '../../util/SettingsManager'; import { SharingManager } from '../../util/SharingManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; +import { UndoManager, undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent } from '../DocComponent'; import { EditableView } from '../EditableView'; import { GestureOverlay } from '../GestureOverlay'; import { LightboxView } from '../LightboxView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { StyleProp } from '../StyleProvider'; import { UndoStack } from '../UndoStack'; import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; @@ -46,12 +48,11 @@ import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView' import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; import { FieldViewProps } from './FieldView'; -import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; +import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; -import * as React from 'react'; const { Howl } = require('howler'); interface Window { @@ -253,20 +254,11 @@ export class DocumentViewInternal extends DocComponent(); private _titleRef = React.createRef(); private _dropDisposer?: DragManager.DragDropDisposer; - - @override _props: DocumentViewInternalProps; - _prevProps: DocumentViewInternalProps; - - constructor(props: DocumentViewInternalProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - // untracked(() => (this._props = this._props)); - } - @observable _componentView: Opt; // needs to be accessed from DocumentView wrapper class @observable _animateScaleTime: Opt; // milliseconds for animating between views. defaults to 300 if not uset @observable _animateScalingTo = 0; @@ -1329,19 +1321,13 @@ export class DocumentViewInternal extends DocComponent { +export class DocumentView extends ObservableReactComponent { public static ROOT_DIV = 'documentView-effectsWrapper'; - @observable _props: DocumentViewProps; - _prevProps: DocumentViewProps; constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } @observable _selected = false; public get SELECTED() { diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 02ed56333..ff92c701f 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -1,5 +1,4 @@ -import EquationEditor from './formattedText/EquationEditor'; -import { action, makeObservable, override, reaction } from 'mobx'; +import { action, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Id } from '../../../fields/FieldSymbols'; @@ -11,7 +10,7 @@ import { ViewBoxBaseComponent } from '../DocComponent'; import { LightboxView } from '../LightboxView'; import './EquationBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; -import { copyProps } from '../../../Utils'; +import EquationEditor from './formattedText/EquationEditor'; @observer export class EquationBox extends ViewBoxBaseComponent() { @@ -21,18 +20,11 @@ export class EquationBox extends ViewBoxBaseComponent() { public static SelectOnLoad: string = ''; _ref: React.RefObject = React.createRef(); - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { this._props.setContentView?.(this); if (EquationBox.SelectOnLoad === this.Document[Id] && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath()))) { diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index d8b1f125c..5a8665aaf 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -1,13 +1,13 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, MultiToggle, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; -import { computed, makeObservable, observable, override } from 'mobx'; +import { computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc'; import { ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; @@ -45,16 +45,11 @@ export class FontIconBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); } - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } // // This controls whether fontIconButtons will display labels under their icons or not // @@ -64,6 +59,7 @@ export class FontIconBox extends ViewBoxBaseComponent() { public static set ShowIconLabels(show: boolean) { Doc.UserDoc()._showLabel = show; } + @observable noTooltip = false; showTemplate = (): void => { const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null); diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx index a04c27e01..29bffb583 100644 --- a/src/client/views/nodes/FunctionPlotBox.tsx +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -1,15 +1,12 @@ import functionPlot from 'function-plot'; -import { action, computed, makeObservable, override, reaction } from 'mobx'; +import { computed, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../fields/Doc'; -import { documentSchema } from '../../../fields/documentSchemas'; -import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; -import { createSchema, listSpec, makeInterface } from '../../../fields/Schema'; +import { listSpec } from '../../../fields/Schema'; import { Cast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { copyProps } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; @@ -27,19 +24,12 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent _plotId = ''; _plotEle: any; - _prevProps: React.PropsWithChildren; - @override _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); this._plotId = 'graph' + FunctionPlotBox.GraphCount++; } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { this._props.setContentView?.(this); reaction( diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 091c1a32f..b1ccd38ba 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; import * as React from 'react'; @@ -12,7 +12,7 @@ import { ObjectField } from '../../../fields/ObjectField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, DashColor, emptyFunction, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; +import { DashColor, emptyFunction, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; @@ -55,19 +55,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent(); @observable _curSuffix = ''; - _prevProps: ViewBoxAnnotatableProps & FieldViewProps; - @override _props: ViewBoxAnnotatableProps & FieldViewProps; constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { super(props); - this._props = this._prevProps = props; - makeObservable(this); this._props.setContentView?.(this); } - componentDidUpdate() { - copyProps(this); - } - protected createDropTarget = (ele: HTMLDivElement) => { this._dropDisposer?.(); ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.Document)); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 9aab53daf..73fdc3a23 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -1,26 +1,27 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { returnAlways, returnTrue } from '../../../Utils'; import { Doc, Field, FieldResult } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { RichTextField } from '../../../fields/RichTextField'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { DocCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { copyProps, returnAll, returnAlways, returnTrue } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; -import { CompiledScript, CompileScript, ScriptOptions } from '../../util/Scripting'; +import { CompileScript, CompiledScript, ScriptOptions } from '../../util/Scripting'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentIconContainer } from './DocumentIcon'; import { OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; -import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { ImageBox } from './ImageBox'; import './KeyValueBox.scss'; import { KeyValuePair } from './KeyValuePair'; -import * as React from 'react'; +import { FormattedTextBox } from './formattedText/FormattedTextBox'; export type KVPScript = { script: CompiledScript; @@ -28,28 +29,20 @@ export type KVPScript = { onDelegate: boolean; }; @observer -export class KeyValueBox extends React.Component { +export class KeyValueBox extends ObservableReactComponent { public static LayoutString() { return FieldView.LayoutString(KeyValueBox, 'data'); } + constructor(props: any) { + super(props); + makeObservable(this); + } private _mainCont = React.createRef(); private _keyHeader = React.createRef(); private _keyInput = React.createRef(); private _valInput = React.createRef(); - _prevProps: FieldViewProps; - @observable _props: FieldViewProps; - constructor(props: FieldViewProps) { - super(props); - this._props = this._prevProps = props; - makeObservable(this); - } - - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { this._props.setContentView?.(this); } diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 40991f371..fd8d8ef56 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,21 +1,23 @@ -import { action, makeObservable, observable, toJS } from 'mobx'; +import { Tooltip } from '@mui/material'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import { ObservableGroupMap } from 'mobx-utils'; +import * as React from 'react'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../Utils'; import { Doc, Field } from '../../../fields/Doc'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../Utils'; +import { DocCast } from '../../../fields/Types'; +import { DocumentOptions, FInfo } from '../../documents/Documents'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { EditableView } from '../EditableView'; import { DefaultStyleProvider } from '../StyleProvider'; -import { OpenWhere, OpenWhereMod } from './DocumentView'; -import { FieldView, FieldViewProps } from './FieldView'; +import { OpenWhere } from './DocumentView'; +import { FieldViewProps } from './FieldView'; import { KeyValueBox } from './KeyValueBox'; import './KeyValueBox.scss'; import './KeyValuePair.scss'; -import * as React from 'react'; -import { DocCast } from '../../../fields/Types'; -import { Tooltip } from '@mui/material'; -import { DocumentOptions, FInfo } from '../../documents/Documents'; +import { ObservableReactComponent } from '../ObservableReactComponent'; // Represents one row in a key value plane @@ -29,22 +31,15 @@ export interface KeyValuePairProps { addDocTab: (doc: Doc, where: OpenWhere) => boolean; } @observer -export class KeyValuePair extends React.Component { +export class KeyValuePair extends ObservableReactComponent { @observable private isPointerOver = false; @observable public isChecked = false; private checkbox = React.createRef(); - - _prevProps: KeyValuePairProps; - @observable _props: KeyValuePairProps; - constructor(props: KeyValuePairProps) { + constructor(props:any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } @action handleCheck = (e: React.ChangeEvent) => { diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 52ca8b5b1..934bce448 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -1,11 +1,10 @@ -import { action, computed, makeObservable, observable, override } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; -import { Cast, StrCast, NumCast, BoolCast } from '../../../fields/Types'; -import { copyProps } from '../../../Utils'; +import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; @@ -31,16 +30,11 @@ export class LabelBox extends ViewBoxBaseComponent; - @override _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + componentDidMount() { this._props.setContentView?.(this); } diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index a7e905fca..b86ba72a0 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -1,9 +1,9 @@ -import { action, computed, makeObservable, observable, override } from 'mobx'; -import { observer } from 'mobx-react'; +import { action, computed, makeObservable } from 'mobx'; +import * as React from 'react'; +import { Utils, emptyFunction, setupMoveUpEvents } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; import { NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, setupMoveUpEvents, Utils } from '../../../Utils'; import { DragManager } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { SelectionManager } from '../../util/SelectionManager'; @@ -12,11 +12,7 @@ import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; import { LinkInfo } from './LinkDocPreview'; -import * as React from 'react'; -const { - default: { MEDIUM_GRAY }, -} = require('../global/globalCssVariables.module.scss'); -@observer +const { default: { MEDIUM_GRAY }, } = require('../global/globalCssVariables.module.scss'); // prettier-ignore export class LinkAnchorBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkAnchorBox, fieldKey); @@ -26,14 +22,9 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { _ref = React.createRef(); _isOpen = false; _timeout: NodeJS.Timeout | undefined; - @observable _x = 0; - @observable _y = 0; - _prevProps: FieldViewProps; - @override _props: FieldViewProps; - constructor(props: FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index acafd6d09..134f2e14a 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; import { Bezier } from 'bezier-js'; -import { computed, IReactionDisposer, makeObservable, observable, override, reaction } from 'mobx'; +import { computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Id } from '../../../fields/FieldSymbols'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { aggregateBounds, copyProps, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils'; +import { aggregateBounds, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils'; import { DocumentManager } from '../../util/DocumentManager'; import { Transform } from '../../util/Transform'; import { CollectionFreeFormView } from '../collections/collectionFreeForm'; @@ -20,18 +20,11 @@ export class LinkBox extends ViewBoxBaseComponent() { return FieldView.LayoutString(LinkBox, fieldKey); } - _prevProps: FieldViewProps; - @override _props: FieldViewProps; - constructor(props: FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - onClickScriptDisable = returnAlways; @computed get anchor1() { const anchor1 = DocCast(this.dataDoc.link_anchor_1); diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 108930ad9..fa7a55bc7 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -19,6 +19,7 @@ import { Transform } from '../../util/Transform'; import { DocumentView, DocumentViewSharedProps, OpenWhere } from './DocumentView'; import './LinkDocPreview.scss'; import * as React from 'react'; +import { ObservableReactComponent } from '../ObservableReactComponent'; export class LinkInfo { private static _instance: Opt; @@ -49,15 +50,7 @@ interface LinkDocPreviewProps { noPreview?: boolean; } @observer -export class LinkDocPreview extends React.Component { - _prevProps: LinkDocPreviewProps; - @observable _props: LinkDocPreviewProps; - constructor(props: LinkDocPreviewProps) { - super(props); - this._props = this._prevProps = props; - makeObservable(this); - } - +export class LinkDocPreview extends ObservableReactComponent { _infoRef = React.createRef(); _linkDocRef = React.createRef(); @observable _targetDoc: Opt = undefined; @@ -66,6 +59,10 @@ export class LinkDocPreview extends React.Component { @observable _linkSrc: Opt = undefined; @observable _toolTipText = ''; @observable _hrefInd = 0; + constructor(props: any) { + super(props); + makeObservable(this); + } @action init() { @@ -84,9 +81,9 @@ export class LinkDocPreview extends React.Component { this._toolTipText = ''; this.updateHref(); } - componentDidUpdate(props: any) { - copyProps(this); - if (props.linkSrc !== this._props.linkSrc || props.linkDoc !== this._props.linkDoc || props.hrefs !== this._props.hrefs) this.init(); + componentDidUpdate(prevProps: Readonly) { + copyProps(this, prevProps); + if (prevProps.linkSrc !== this._props.linkSrc || prevProps.linkDoc !== this._props.linkDoc || prevProps.hrefs !== this._props.hrefs) this.init(); } componentDidMount() { this.init(); diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx index ee1ea3ceb..b458e5a28 100644 --- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx +++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IReactionDisposer, ObservableMap, reaction } from 'mobx'; import { observer } from 'mobx-react'; -import { Doc, Opt } from '../../../../fields/Doc'; +import * as React from 'react'; import { returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../../Utils'; +import { Doc, Opt } from '../../../../fields/Doc'; import { SelectionManager } from '../../../util/SelectionManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; // import { GPTPopup, GPTPopupMode } from './../../GPTPopup/GPTPopup'; @@ -36,7 +36,6 @@ export class MapAnchorMenu extends AntimodeMenu { constructor(props: Readonly<{}>) { super(props); - MapAnchorMenu.Instance = this; MapAnchorMenu.Instance._canFade = false; } diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 98a302834..a420e0101 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1,24 +1,24 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import BingMapsReact from 'bingmaps-react'; import { Button, EditableText, IconButton, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents } from '../../../../Utils'; import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc'; import { DocCss, Highlight } from '../../../../fields/DocSymbols'; import { DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils'; -import { Docs, DocUtils } from '../../../documents/Documents'; import { DocumentType } from '../../../documents/DocumentTypes'; +import { DocUtils, Docs } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; import { LinkManager } from '../../../util/LinkManager'; import { Transform } from '../../../util/Transform'; -import { undoable, UndoManager } from '../../../util/UndoManager'; -import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; +import { UndoManager, undoable } from '../../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; -import { Colors } from '../../global/globalEnums'; import { SidebarAnnos } from '../../SidebarAnnos'; +import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; +import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; @@ -67,18 +67,12 @@ export class MapBox extends ViewBoxAnnotatableComponent = React.createRef(); private _disposers: { [key: string]: IReactionDisposer } = {}; - _unmounting = false; - _prevProps: ViewBoxAnnotatableProps & FieldViewProps; - @override _props: ViewBoxAnnotatableProps & FieldViewProps; - constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + _unmounting = false; @observable private _savedAnnotations = new ObservableMap(); @computed get allSidebarDocs() { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index a453210eb..213f88177 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,8 +1,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as Pdfjs from 'pdfjs-dist'; import 'pdfjs-dist/web/pdf_viewer.css'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; @@ -10,7 +11,7 @@ import { ComputedField } from '../../../fields/ScriptField'; import { Cast, FieldValue, ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField, PdfField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents, Utils } from '../../../Utils'; +import { emptyFunction, returnFalse, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; @@ -31,7 +32,6 @@ import { FieldView, FieldViewProps } from './FieldView'; import { ImageBox } from './ImageBox'; import './PDFBox.scss'; import { PinProps, PresBox } from './trails'; -import * as React from 'react'; @observer export class PDFBox extends ViewBoxAnnotatableComponent() { @@ -58,11 +58,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent (this._pdf = pdf))); } } - componentDidUpdate() { - copyProps(this); - } replaceCanvases = (oldDiv: HTMLElement, newDiv: HTMLElement) => { if (oldDiv.childNodes) { diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index a4f4897ba..ebe86318d 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction, runInAction, untracked } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction, untracked } from 'mobx'; import { observer } from 'mobx-react'; import { basename } from 'path'; +import * as React from 'react'; import { Doc, StrListCast } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { AudioField, ImageField, VideoField } from '../../../fields/URLField'; -import { copyProps, emptyFunction, formatTime, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; +import { emptyFunction, formatTime, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; @@ -68,19 +68,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent(); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 995f9f6e0..2f92f1edb 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as WebRequest from 'web-request'; @@ -13,7 +13,7 @@ import { listSpec } from '../../../fields/Schema'; import { Cast, NumCast, StrCast, WebCast } from '../../../fields/Types'; import { ImageField, WebField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; @@ -98,19 +98,12 @@ export class WebBox extends ViewBoxAnnotatableComponent { if (!this._searching && !clear) { diff --git a/src/client/views/nodes/audio/AudioWaveform.tsx b/src/client/views/nodes/audio/AudioWaveform.tsx index 1b1a85800..01392c4a5 100644 --- a/src/client/views/nodes/audio/AudioWaveform.tsx +++ b/src/client/views/nodes/audio/AudioWaveform.tsx @@ -1,15 +1,16 @@ import axios from 'axios'; -import { computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { computed, IReactionDisposer, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, NumListCast } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { Cast } from '../../../../fields/Types'; -import { copyProps, numberRange } from '../../../../Utils'; +import { numberRange } from '../../../../Utils'; import { Colors } from './../../global/globalEnums'; import './AudioWaveform.scss'; import { WaveCanvas } from './WaveCanvas'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; /** * AudioWaveform @@ -35,21 +36,15 @@ export interface AudioWaveformProps { } @observer -export class AudioWaveform extends React.Component { +export class AudioWaveform extends ObservableReactComponent { public static NUMBER_OF_BUCKETS = 100; // number of buckets data is divided into to draw waveform lines _disposer: IReactionDisposer | undefined; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - get waveHeight() { return Math.max(50, this._props.PanelHeight); } diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index e2cceb906..555b752f0 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -2,22 +2,23 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import { Doc } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField'; -import { Cast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; +import { Cast } from '../../../../fields/Types'; +import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { CollectionViewType } from '../../../documents/DocumentTypes'; +import { Transform } from '../../../util/Transform'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; import { SchemaTableCell } from '../../collections/collectionSchema/SchemaTableCell'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import { OpenWhere } from '../DocumentView'; import './DashFieldView.scss'; import { FormattedTextBox } from './FormattedTextBox'; -import * as React from 'react'; -import { Transform } from '../../../util/Transform'; export class DashFieldView { dom: HTMLDivElement; // container for label and value @@ -92,7 +93,7 @@ interface IDashFieldViewInternal { } @observer -export class DashFieldViewInternal extends React.Component { +export class DashFieldViewInternal extends ObservableReactComponent { _reactionDisposer: IReactionDisposer | undefined; _textBoxDoc: Doc; _fieldKey: string; @@ -100,11 +101,8 @@ export class DashFieldViewInternal extends React.Component, prevState: Readonly<{}>, snapshot?: any): void { - copyProps(this); - } + componentWillUnmount() { this._reactionDisposer?.(); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 56bf15b09..997c3f86d 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { isEqual } from 'lodash'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { baseKeymap, selectAll } from 'prosemirror-commands'; import { history } from 'prosemirror-history'; @@ -14,7 +14,7 @@ import { EditorView } from 'prosemirror-view'; import { BsMarkdownFill } from 'react-icons/bs'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, DocData, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; +import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; @@ -24,7 +24,7 @@ import { RichTextUtils } from '../../../../fields/RichTextUtils'; import { ComputedField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils'; import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { DocServer } from '../../../DocServer'; @@ -55,7 +55,7 @@ import { StyleProp } from '../../StyleProvider'; import { media_state } from '../AudioBox'; import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; -import { LinkDocPreview, LinkInfo } from '../LinkDocPreview'; +import { LinkInfo } from '../LinkDocPreview'; import { PinProps, PresBox } from '../trails'; import { DashDocCommentView } from './DashDocCommentView'; import { DashDocView } from './DashDocView'; @@ -208,20 +208,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent; - @override _props: React.PropsWithChildren; constructor(props: React.PropsWithChildren) { super(props); - this._props = this._prevProps = props; makeObservable(this); FormattedTextBox.Instance = this; this._recordingStart = Date.now(); } - componentDidUpdate() { - copyProps(this); - } - // removes all hyperlink anchors for the removed linkDoc // TODO: bcz: Argh... if a section of text has multiple anchors, this should just remove the intended one. // but since removing one anchor from the list of attr anchors isn't implemented, this will end up removing nothing. diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 7de1eb717..4881070fd 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -1,21 +1,22 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { lift, wrapIn } from 'prosemirror-commands'; import { Mark, MarkType, Node as ProsNode, ResolvedPos } from 'prosemirror-model'; import { wrapInList } from 'prosemirror-schema-list'; import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; +import * as React from 'react'; import { Doc } from '../../../../fields/Doc'; import { BoolCast, Cast, StrCast } from '../../../../fields/Types'; -import { copyProps, numberRange } from '../../../../Utils'; +import { numberRange } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { LinkManager } from '../../../util/LinkManager'; import { SelectionManager } from '../../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import { EquationBox } from '../EquationBox'; import { FieldViewProps } from '../FieldView'; import { FormattedTextBox } from './FormattedTextBox'; @@ -63,18 +64,13 @@ export class RichTextMenu extends AntimodeMenu { @observable private showLinkDropdown: boolean = false; _reaction: IReactionDisposer | undefined; - _prevProps: AntimodeMenuProps; - @override _props: AntimodeMenuProps; constructor(props: AntimodeMenuProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); - runInAction(() => { - RichTextMenu.Instance = this; - this.updateMenu(undefined, undefined, props, this.layoutDoc); - this._canFade = false; - this.Pinned = true; - }); + RichTextMenu.Instance = this; + this.updateMenu(undefined, undefined, props, this.layoutDoc); + this._canFade = false; + this.Pinned = true; } @computed get noAutoLink() { @@ -111,9 +107,6 @@ export class RichTextMenu extends AntimodeMenu { return BoolCast(this.layoutDoc?.layout_centered); } _disposer: IReactionDisposer | undefined; - componentDidUpdate() { - copyProps(this); - } componentDidMount() { this._disposer = reaction( () => SelectionManager.Views.slice(), @@ -368,7 +361,7 @@ export class RichTextMenu extends AntimodeMenu { } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) { SelectionManager.Views.forEach(dv => (dv.Document._text_fontSize = fontSize)); } else Doc.UserDoc().fontSize = fontSize; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); }; setFontFamily = (family: string) => { @@ -377,7 +370,7 @@ export class RichTextMenu extends AntimodeMenu { this.setMark(fmark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(fmark)), true); this.view.focus(); } else Doc.UserDoc().fontFamily = family; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); }; setHighlight(color: string) { @@ -386,7 +379,7 @@ export class RichTextMenu extends AntimodeMenu { this.setMark(highlightMark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(highlightMark)), true); this.view.focus(); } else Doc.UserDoc()._fontHighlight = color; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); } setColor(color: string) { @@ -395,7 +388,7 @@ export class RichTextMenu extends AntimodeMenu { this.setMark(colorMark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(colorMark)), true); this.view.focus(); } else Doc.UserDoc().fontColor = color; - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); } // TODO: remove doesn't work @@ -436,7 +429,7 @@ export class RichTextMenu extends AntimodeMenu { } } this.view.focus(); - this.updateMenu(this.view, undefined, this._props, this.layoutDoc); + this.updateMenu(this.view, undefined, this.props, this.layoutDoc); }; insertSummarizer(state: EditorState, dispatch: any) { @@ -818,22 +811,15 @@ interface ButtonDropdownProps { } @observer -export class ButtonDropdown extends React.Component { +export class ButtonDropdown extends ObservableReactComponent { @observable private showDropdown: boolean = false; private ref: HTMLDivElement | null = null; - _prevProps: React.PropsWithChildren; - @observable _props: React.PropsWithChildren; - constructor(props: React.PropsWithChildren) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } - componentDidMount() { document.addEventListener('pointerdown', this.onBlur); } diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 9fcb496b8..ec5d090dd 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -1,12 +1,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { copyProps, emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { DocumentManager } from '../../../util/DocumentManager'; @@ -24,7 +25,6 @@ import { StyleProp } from '../../StyleProvider'; import { PresBox } from './PresBox'; import './PresElementBox.scss'; import { PresMovement } from './PresEnums'; -import * as React from 'react'; /** * This class models the view a document added to presentation will have in the presentation. * It involves some functionality for its buttons and options. @@ -41,19 +41,12 @@ export class PresElementBox extends ViewBoxBaseComponent() { readonly expandViewHeight = 100; readonly collapsedHeight = 35; - @observable _dragging = false; - - _prevProps: FieldViewProps; - @override _props: FieldViewProps; - constructor(props: FieldViewProps) { + constructor(props: any) { super(props); - this._props = this._prevProps = props; makeObservable(this); } - componentDidUpdate() { - copyProps(this); - } + @observable _dragging = false; // the presentation view that renders this slide @computed get presBoxView() { diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 0627876fa..a8c83ded6 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { ColorResult } from 'react-color'; +import { Utils, returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; -import { copyProps, returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from '../../../Utils'; -import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT'; +import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT'; import { DocumentType } from '../../documents/DocumentTypes'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; @@ -23,18 +23,12 @@ export class AnchorMenu extends AntimodeMenu { private _commentRef = React.createRef(); private _cropRef = React.createRef(); - _prevProps: AntimodeMenuProps; - @override _props: AntimodeMenuProps; constructor(props: AntimodeMenuProps) { super(props); - this._props = this._prevProps = props; makeObservable(this); AnchorMenu.Instance = this; AnchorMenu.Instance._canFade = false; } - componentDidUpdate() { - copyProps(this); - } @observable private highlightColor: string = 'rgba(245, 230, 95, 0.616)'; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index a581e9df6..e342c25b3 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,13 +1,16 @@ import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as Pdfjs from 'pdfjs-dist'; import 'pdfjs-dist/web/pdf_viewer.css'; +import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer.mjs'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Height } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, returnAll, returnFalse, returnNone, returnZero, smoothScroll, Utils } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, returnAll, returnFalse, returnNone, returnZero, smoothScroll, Utils } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; @@ -16,15 +19,13 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { DocFocusOptions, DocumentViewProps } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; -import { LinkDocPreview, LinkInfo } from '../nodes/LinkDocPreview'; +import { LinkInfo } from '../nodes/LinkDocPreview'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { StyleProp } from '../StyleProvider'; import { AnchorMenu } from './AnchorMenu'; import { Annotation } from './Annotation'; import { GPTPopup } from './GPTPopup/GPTPopup'; import './PDFViewer.scss'; -import * as React from 'react'; -import * as Pdfjs from 'pdfjs-dist'; -import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer.mjs'; const _global = (window /* browser */ || global) /* node */ as any; //pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`; @@ -49,14 +50,11 @@ interface IViewerProps extends FieldViewProps { * Handles rendering and virtualization of the pdf */ @observer -export class PDFViewer extends React.Component { +export class PDFViewer extends ObservableReactComponent { static _annotationStyle: any = addStyleSheet(); - _prevProps: IViewerProps; - @observable _props: IViewerProps; - constructor(props: IViewerProps) { + constructor(props: any) { super(props); - this._prevProps = this._props = props; makeObservable(this); } @@ -66,10 +64,6 @@ export class PDFViewer extends React.Component { @observable _showWaiting = true; @observable Index: number = -1; - componentDidUpdate() { - copyProps(this); - } - private _pdfViewer: any; private _styleRule: any; // stylesheet rule for making hyperlinks clickable private _retries = 0; // number of times tried to create the PDF viewer -- cgit v1.2.3-70-g09d2 From 5b5730a7df073659cbb6c326f748f7fcbe6625e8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 18 Jan 2024 15:05:53 -0500 Subject: lots of changes to try to simplify API for viewPaths and related --- src/Utils.ts | 3 +- src/client/documents/Documents.ts | 6 +- src/client/util/CurrentUserUtils.ts | 4 +- src/client/util/DocumentManager.ts | 15 +- .../util/Import & Export/DirectoryImportBox.tsx | 2 +- src/client/views/DocComponent.tsx | 56 +++- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 6 +- src/client/views/GestureOverlay.tsx | 2 +- src/client/views/InkControlPtHandles.tsx | 12 +- src/client/views/InkStrokeProperties.ts | 3 +- src/client/views/InkTangentHandles.tsx | 4 +- src/client/views/InkingStroke.tsx | 9 +- src/client/views/LightboxView.tsx | 2 +- src/client/views/MainView.tsx | 47 +--- src/client/views/MarqueeAnnotator.tsx | 2 +- src/client/views/OverlayView.tsx | 2 +- src/client/views/PreviewCursor.tsx | 25 +- src/client/views/PropertiesButtons.tsx | 46 ++- src/client/views/PropertiesDocContextSelector.tsx | 2 +- src/client/views/PropertiesView.tsx | 2 +- src/client/views/StyleProvider.tsx | 33 ++- src/client/views/TemplateMenu.tsx | 2 - .../views/collections/CollectionCarouselView.tsx | 4 +- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/collections/CollectionMenu.tsx | 2 - .../views/collections/CollectionNoteTakingView.tsx | 10 +- .../views/collections/CollectionPileView.tsx | 2 +- .../collections/CollectionStackedTimeline.tsx | 4 +- .../views/collections/CollectionStackingView.tsx | 12 +- src/client/views/collections/CollectionSubView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 4 +- src/client/views/collections/CollectionView.tsx | 10 +- src/client/views/collections/TabDocView.tsx | 9 +- src/client/views/collections/TreeView.tsx | 12 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 51 ++-- .../collectionLinear/CollectionLinearView.tsx | 6 +- .../CollectionMulticolumnView.tsx | 6 +- .../CollectionMultirowView.tsx | 7 +- .../collectionSchema/CollectionSchemaView.tsx | 7 +- .../collections/collectionSchema/SchemaRowBox.tsx | 8 +- .../collectionSchema/SchemaTableCell.tsx | 1 - src/client/views/global/globalScripts.ts | 4 +- src/client/views/linking/LinkMenuItem.tsx | 4 +- src/client/views/linking/LinkPopup.tsx | 2 - src/client/views/newlightbox/NewLightboxView.tsx | 2 +- src/client/views/nodes/AudioBox.tsx | 4 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 8 +- src/client/views/nodes/ComparisonBox.tsx | 5 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 41 +-- src/client/views/nodes/DocumentContentsView.tsx | 11 +- src/client/views/nodes/DocumentIcon.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 308 +++++++++++---------- src/client/views/nodes/EquationBox.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 9 +- src/client/views/nodes/ImageBox.tsx | 8 +- src/client/views/nodes/KeyValuePair.tsx | 65 ++--- src/client/views/nodes/LinkAnchorBox.tsx | 14 +- src/client/views/nodes/LinkBox.tsx | 9 +- src/client/views/nodes/LinkDocPreview.tsx | 12 +- src/client/views/nodes/MapBox/MapBox.tsx | 4 +- src/client/views/nodes/MapBox/MapPushpinBox.tsx | 4 +- .../views/nodes/MapboxMapBox/MapboxContainer.tsx | 4 +- src/client/views/nodes/PDFBox.tsx | 8 +- src/client/views/nodes/VideoBox.tsx | 18 +- src/client/views/nodes/WebBox.tsx | 36 +-- .../views/nodes/formattedText/DashDocView.tsx | 4 +- .../views/nodes/formattedText/DashFieldView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 16 +- .../formattedText/FormattedTextBoxComment.tsx | 3 +- src/client/views/nodes/trails/PresBox.tsx | 12 +- src/client/views/nodes/trails/PresElementBox.tsx | 10 +- src/client/views/pdf/PDFViewer.tsx | 12 +- src/client/views/topbar/TopBar.tsx | 2 - src/mobile/MobileInterface.tsx | 2 +- src/server/DashStats.ts | 4 +- 77 files changed, 566 insertions(+), 537 deletions(-) (limited to 'src/client/views/OverlayView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index b5c218e01..852083834 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -7,6 +7,7 @@ import { Socket } from '../node_modules/socket.io/dist/index'; import { DocumentType } from './client/documents/DocumentTypes'; import { Colors } from './client/views/global/globalEnums'; import { Message } from './server/Message'; +import { DocumentView } from './client/views/nodes/DocumentView'; export namespace Utils { export let CLICK_TIME = 300; @@ -583,7 +584,7 @@ export function returnEmptyDoclist() { return [] as any[]; } -export let emptyPath = []; +export let emptyPath: DocumentView[] = []; export function emptyFunction() { return undefined; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 92a9ddfe8..40cffcf45 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -244,7 +244,6 @@ export class DocumentOptions { _layout_reflowVertical?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); _layout_reflowHorizontal?: BOOLt = new BoolInfo('whether a doc with a native size can be horizonally resized, causing some form of reflow'); layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow - layout_maxAutoHeight?: NUMt = new NumInfo('maximum height for newly created (eg, from pasting) text documents', false); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document', false); _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds', false); @@ -290,7 +289,7 @@ export class DocumentOptions { dontPlayLinkOnSelect?: BOOLt = new BoolInfo('whether an audio/video should start playing when a link is followed to it.'); openFactoryLocation?: string; // an OpenWhere value to place the factory created document openFactoryAsDelegate?: boolean; // - updateContentsScript?: ScriptField; // reactive script invoked when viewing a document that can update contents of a collection (or do anything) + onViewMounted?: ScriptField; // reactive script invoked Doc is viewed (used by showBackLinks view to update collection of links to Doc) toolTip?: string; // tooltip to display on hover toolType?: string; // type of pen tool expertMode?: BOOLt = new BoolInfo('something available only in expert (not novice) mode'); @@ -1895,12 +1894,11 @@ export namespace DocUtils { } } - export function GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, maxHeight?: number, backgroundColor?: string) { + export function GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, backgroundColor?: string) { const tbox = Docs.Create.TextDocument('', { _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, - layout_maxAutoHeight: maxHeight, backgroundColor, _width: width || 200, _height: 35, diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 4391e87d6..2dfd91314 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -111,7 +111,7 @@ export class CurrentUserUtils { const tempClicks = DocCast(doc[field]); const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, isSystem: true}; const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [ - { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCastAsync(documentView?.props.docViewPath().lastElement()?.Document.target).then((target) => target && (target.proto.data = new List([self])))"}, + { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCastAsync(documentView?.containerViewPath().lastElement()?.Document.target).then((target) => target && (target.proto.data = new List([self])))"}, { opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: `openDoc(this.doubleClickView.${OpenWhere.addRight})`}]; const reqdClickList = reqdTempOpts.map(opts => { const allOpts = {...reqdClickOpts, ...opts.opts}; @@ -285,7 +285,7 @@ export class CurrentUserUtils { treeView_HasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true, dropAction:'move', treeView_Type: TreeViewType.outline, backgroundColor: "white", _xMargin: 0, _yMargin: 0, _createDocOnCR: true - }, funcs: {title: 'this.text?.Text'}}, + }, funcs: {title: 'pptSlide'}},//'this.text?.Text'}}, ]; emptyThings.forEach(thing => DocUtils.AssignDocField(doc, "empty"+thing.key, (opts) => thing.creator(opts), {...standardOps(thing.key), ...thing.opts}, undefined, thing.scripts, thing.funcs)); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 7fef5cc79..07357a764 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -153,8 +153,8 @@ export class DocumentManager { return passes.reduce( (toReturn, pass) => toReturn ?? - docViewArray.filter(view => view.Document === target).find(view => !pass || view._props.docViewPath().lastElement() === preferredCollection) ?? - docViewArray.filter(view => Doc.AreProtosEqual(view.Document, target)).find(view => !pass || view._props.docViewPath().lastElement() === preferredCollection), + docViewArray.filter(view => view.Document === target).find(view => !pass || view.containerViewPath?.().lastElement() === preferredCollection) ?? + docViewArray.filter(view => Doc.AreProtosEqual(view.Document, target)).find(view => !pass || view.containerViewPath?.().lastElement() === preferredCollection), undefined as Opt ); } @@ -224,7 +224,7 @@ export class DocumentManager { } public static removeOverlayViews() { - DocumentManager._overlayViews?.forEach(action(view => (view.textHtmlOverlay = undefined))); + DocumentManager._overlayViews?.forEach(view => view.setTextHtmlOverlay(undefined, undefined)); DocumentManager._overlayViews?.clear(); } static _overlayViews = new ObservableSet(); @@ -274,7 +274,7 @@ export class DocumentManager { // even if we found the document view, if the target is a lightbox, we try to open it in the lightbox to preserve lightbox semantics (eg, there's only one active doc in the lightbox) const target = DocCast(targetDoc.annotationOn, targetDoc); const contextView = this.getDocumentView(DocCast(target.embedContainer)); - if (contextView?.docView?._componentView?.addDocTab?.(target, OpenWhere.lightbox)) { + if (contextView?.ComponentView?.addDocTab?.(target, OpenWhere.lightbox)) { await new Promise(waitres => setTimeout(() => waitres())); } } @@ -327,15 +327,12 @@ export class DocumentManager { if (options.zoomTextSelections && Doc.UnhighlightTimer && contextView && targetDoc.text_html) { // if the docView is a text anchor, the contextView is the PDF/Web/Text doc - contextView.htmlOverlayEffect = options.effect; - contextView.textHtmlOverlayTime = options.zoomTime; - contextView.textHtmlOverlay = StrCast(targetDoc.text_html); + contextView.setTextHtmlOverlay(StrCast(targetDoc.text_html), options.effect); DocumentManager._overlayViews.add(contextView); } Doc.AddUnHighlightWatcher(() => { docView.Document[Animation] = undefined; DocumentManager.removeOverlayViews(); - contextView && (contextView.htmlOverlayEffect = undefined); }); } } @@ -344,7 +341,7 @@ export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCe const func = () => { const cv = DocumentManager.Instance.getDocumentView(containingDoc); const dv = DocumentManager.Instance.getDocumentView(doc, cv); - if (dv && (!containingDoc || dv._props.docViewPath().lastElement()?.Document === containingDoc)) { + if (dv && (!containingDoc || dv.containerViewPath?.().lastElement()?.Document === containingDoc)) { DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.Document)); } else { const container = DocCast(containingDoc ?? doc.embedContainer ?? Doc.BestEmbedding(doc)); diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index b6dbea33a..398ba3c04 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -156,7 +156,7 @@ // x: NumCast(doc.x), // y: NumCast(doc.y) + offset, // }; -// const parent = this.props.DocumentView?.()._props.docViewPath().lastElement(); +// const parent = this.props.DocumentView?.().containerViewPath().lastElement(); // if (parent?.Document.type === DocumentType.COL) { // let importContainer: Doc; // if (docs.length < 50) { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index dfc298840..fb8ef7c36 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,6 +1,6 @@ import { action, computed, makeObservable, observable } from 'mobx'; import * as React from 'react'; -import { returnFalse } from '../../Utils'; +import { emptyPath, returnFalse } from '../../Utils'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData } from '../../fields/DocSymbols'; @@ -9,17 +9,20 @@ import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util'; import { DocumentType } from '../documents/DocumentTypes'; import { DocUtils } from '../documents/Documents'; import { DocumentManager } from '../util/DocumentManager'; +import { Transform } from '../util/Transform'; import { ObservableReactComponent } from './ObservableReactComponent'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { DocumentView } from './nodes/DocumentView'; -import { Transform } from '../util/Transform'; -/// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) +/** + * DocComponent returns a generic React base class used by Doc views (not the 'Box' views that render the contents of Doc views) + * (e.g.,CollectionFreeFormDocumentView, DocumentViewInternal) + * + * */ export interface DocComponentProps { Document: Doc; LayoutTemplate?: () => Opt; LayoutTemplateString?: string; - ScreenToLocalTransform: () => Transform; } export function DocComponent

() { class Component extends ObservableReactComponent> { @@ -28,8 +31,6 @@ export function DocComponent

() { makeObservable(this); } - ScreenToLocalBoxXf = () => this._props.ScreenToLocalTransform(); - //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then get Document() { return this._props.Document; @@ -46,21 +47,40 @@ export function DocComponent

() { return Component; } -/// FieldViewBoxProps - a generic base class for field views that are not annotatable (e.g. InkingStroke, ColorBox) -interface ViewBoxBaseProps { +/** + * ViewBoxBaseComponent - base class for non-annotatable views that render the interior contents of a DocumentView + * (e.g. InkingStroke, ColorBox) + */ +export interface ViewBoxBaseProps { Document: Doc; TemplateDataDocument?: Doc; DocumentView?: () => DocumentView; + containerViewPath?: () => DocumentView[]; fieldKey: string; isSelected: () => boolean; isContentActive: () => boolean | undefined; ScreenToLocalTransform: () => Transform; renderDepth: number; } +function returnEmptyDocViewList() { + return [] as DocumentView[]; +} export function ViewBoxBaseComponent

() { class Component extends ObservableReactComponent> { ScreenToLocalBoxXf = () => this._props.ScreenToLocalTransform(); + get DocumentView() { + return this._props.DocumentView; + } + get docViewPath() { + return this.DocumentView?.().docViewPath ?? emptyPath; + } + get docViewPathFunc() { + return this.DocumentView?.().docViewPathFunc ?? returnEmptyDocViewList; + } + get containerViewPath() { + return this._props.containerViewPath; + } //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then get Document() { return this._props.Document; @@ -81,10 +101,15 @@ export function ViewBoxBaseComponent

() { return Component; } -/// DocAnnotatbleComponent -return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image) +/** + * DocAnnotatableComponent - base class for annotatable views that render the interior contents of a DocumentView + * (e.g., PdfBox, ImageBox) + * These views should be interactive (respond to pointerEvents) when their conatainer DocumentView is selected + */ export interface ViewBoxAnnotatableProps { Document: Doc; TemplateDataDocument?: Doc; + DocumentView?: () => DocumentView; fieldKey: string; filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) isContentActive: () => boolean | undefined; @@ -106,6 +131,19 @@ export function ViewBoxAnnotatableComponent

() @observable _annotationKeySuffix = () => 'annotations'; @observable _isAnyChildContentActive = false; + + get DocumentView() { + return this._props.DocumentView; + } + get docViewPath() { + return this.DocumentView?.().docViewPath ?? emptyPath; + } + get docViewPathFunc() { + return this.DocumentView?.().docViewPathFunc ?? returnEmptyDocViewList; + } + get containerViewPath() { + return this.DocumentView?.().containerViewPath ?? returnEmptyDocViewList; + } //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document() { return this._props.Document; diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index bb28d9ec9..8a4b42ae0 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -72,7 +72,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (

this._props.views().map(view => view?.docView?.toggleFollowLink(undefined, false)))}> + onClick={undoBatch(e => this._props.views().map(view => view?.toggleFollowLink(undefined, false)))}>
{followBtn( true, diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 788e78ed2..c96253405 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -303,7 +303,7 @@ export class DocumentDecorations extends ObservableReactComponent SelectionManager.Views?.[0]?._props.docViewPath?.().lastElement()?.select(false); + onSelectContainerDocClick = () => SelectionManager.Views?.[0]?.containerViewPath?.().lastElement()?.select(false); /** * sets up events when user clicks on the border radius editor */ @@ -677,7 +677,7 @@ export class DocumentDecorations extends ObservableReactComponent { - const collectionAcl = docView._props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView._props.docViewPath().lastElement().dataDoc) : AclEdit; + const collectionAcl = docView.containerViewPath?.()?.lastElement() ? GetEffectiveAcl(docView.containerViewPath?.().lastElement().dataDoc) : AclEdit; return collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.Document) !== AclAdmin; }); const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => ( @@ -805,7 +805,7 @@ export class DocumentDecorations extends ObservableReactComponent )} - {seldocview._props.renderDepth <= 1 || !seldocview._props.docViewPath().lastElement() ? null : topBtn('selector', 'arrow-alt-circle-up', undefined, this.onSelectContainerDocClick, 'tap to select containing document')} + {seldocview._props.renderDepth <= 1 || !seldocview.containerViewPath?.().lastElement() ? null : topBtn('selector', 'arrow-alt-circle-up', undefined, this.onSelectContainerDocClick, 'tap to select containing document')} {useRounding && (
{ @observable private _overControl = -1; get docView() { - return this.props.inkView.props.docViewPath().lastElement(); + return this.props.inkView.DocumentView?.(); } componentDidMount() { @@ -58,11 +58,11 @@ export class InkControlPtHandles extends React.Component { if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('drag ink ctrl pt'); const inkMoveEnd = ptFromScreen({ X: delta[0], Y: delta[1] }); const inkMoveStart = ptFromScreen({ X: 0, Y: 0 }); - InkStrokeProperties.Instance.moveControlPtHandle(this.docView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex, origInk); + this.docView && InkStrokeProperties.Instance.moveControlPtHandle(this.docView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex, origInk); return false; }), action(() => { - if (this.props.inkView.controlUndo) { + if (this.props.inkView.controlUndo && this.docView) { InkStrokeProperties.Instance.snapControl(this.docView, controlIndex); } this.props.inkView.controlUndo?.end(); @@ -78,11 +78,11 @@ export class InkControlPtHandles extends React.Component { } else { if (brokenIndices?.includes(equivIndex)) { if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('make smooth'); - InkStrokeProperties.Instance.snapHandleTangent(this.docView, equivIndex, handleIndexA, handleIndexB); + this.docView && InkStrokeProperties.Instance.snapHandleTangent(this.docView, equivIndex, handleIndexA, handleIndexB); } if (equivIndex !== controlIndex && brokenIndices?.includes(controlIndex)) { if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('make smooth'); - InkStrokeProperties.Instance.snapHandleTangent(this.docView, controlIndex, handleIndexA, handleIndexB); + this.docView && InkStrokeProperties.Instance.snapHandleTangent(this.docView, controlIndex, handleIndexA, handleIndexB); } } this.props.inkView.controlUndo?.end(); @@ -113,7 +113,7 @@ export class InkControlPtHandles extends React.Component { @action onDelete = (e: KeyboardEvent) => { if (['-', 'Backspace', 'Delete'].includes(e.key)) { - InkStrokeProperties.Instance.deletePoints(this.docView, e.shiftKey); + this.docView && InkStrokeProperties.Instance.deletePoints(this.docView, e.shiftKey); e.stopPropagation(); } }; diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index f31ea2994..52ea89cde 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -241,6 +241,7 @@ export class InkStrokeProperties { */ @undoBatch moveControlPtHandle = (inkView: DocumentView, deltaX: number, deltaY: number, controlIndex: number, origInk?: InkData) => + inkView && this.applyFunction(inkView, (view: DocumentView, ink: InkData) => { const order = controlIndex % 4; const closed = InkingStroke.IsClosed(ink); @@ -369,7 +370,7 @@ export class InkStrokeProperties { snapToAllCurves = (screenDragPt: { X: number; Y: number }, inkView: DocumentView, snapData: { nearestPt: { X: number; Y: number }; distance: number }, ink: InkData, controlIndex: number) => { const containingCollection = inkView.CollectionFreeFormView; - const containingDocView = containingCollection?.props.DocumentView?.(); + const containingDocView = containingCollection?.DocumentView?.(); containingCollection?.childDocs .filter(doc => doc.type === DocumentType.INK) .forEach(doc => { diff --git a/src/client/views/InkTangentHandles.tsx b/src/client/views/InkTangentHandles.tsx index a00c26a07..c20399698 100644 --- a/src/client/views/InkTangentHandles.tsx +++ b/src/client/views/InkTangentHandles.tsx @@ -23,7 +23,7 @@ export interface InkHandlesProps { @observer export class InkTangentHandles extends React.Component { get docView() { - return this.props.inkView.props.docViewPath().lastElement(); + return this.props.inkView.DocumentView?.(); } /** * Handles the movement of a selected handle point when the user clicks and drags. @@ -42,7 +42,7 @@ export class InkTangentHandles extends React.Component { if (e.altKey) this.onBreakTangent(controlIndex); const inkMoveEnd = this.props.inkView.ptFromScreen({ X: delta[0], Y: delta[1] }); const inkMoveStart = this.props.inkView.ptFromScreen({ X: 0, Y: 0 }); - InkStrokeProperties.Instance.moveTangentHandle(this.docView, -(inkMoveEnd.X - inkMoveStart.X), -(inkMoveEnd.Y - inkMoveStart.Y), handleIndex, oppositeHandleIndex, controlIndex); + this.docView && InkStrokeProperties.Instance.moveTangentHandle(this.docView, -(inkMoveEnd.X - inkMoveStart.X), -(inkMoveEnd.Y - inkMoveStart.Y), handleIndex, oppositeHandleIndex, controlIndex); return false; }), action(() => { diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index c652e8966..11b05352d 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -34,7 +34,7 @@ import { InteractionUtils } from '../util/InteractionUtils'; import { SnappingManager } from '../util/SnappingManager'; import { UndoManager } from '../util/UndoManager'; import { ContextMenu } from './ContextMenu'; -import { ViewBoxBaseComponent } from './DocComponent'; +import { ViewBoxBaseComponent, ViewBoxBaseProps } from './DocComponent'; import { Colors } from './global/globalEnums'; import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles'; import './InkStroke.scss'; @@ -48,7 +48,7 @@ import { StyleProp } from './StyleProvider'; import { Transform } from '../util/Transform'; const { default: { INK_MASK_SIZE } } = require('./global/globalCssVariables.module.scss'); // prettier-ignore @observer -export class InkingStroke extends ViewBoxBaseComponent() { +export class InkingStroke extends ViewBoxBaseComponent() { static readonly MaskDim = INK_MASK_SIZE; // choose a really big number to make sure mask fits over container (which in theory can be arbitrarily big) public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); @@ -122,7 +122,8 @@ export class InkingStroke extends ViewBoxBaseComponent() { @action onPointerDown = (e: React.PointerEvent) => { this._handledClick = false; - const inkView = this._props.docViewPath().lastElement(); + const inkView = this.DocumentView?.(); + if (!inkView) return; const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData(); const screenPts = inkData .map(point => @@ -162,7 +163,7 @@ export class InkingStroke extends ViewBoxBaseComponent() { InkStrokeProperties.Instance._currentPoint = -1; this._handledClick = true; // mark the double-click pseudo pointerevent so we can block the real mouse event from propagating to DocumentView if (isEditing) { - this._nearestT && this._nearestSeg !== undefined && InkStrokeProperties.Instance.addPoints(this._props.docViewPath().lastElement(), this._nearestT, this._nearestSeg, this.inkScaledData().inkData.slice()); + this._nearestT && this._nearestSeg !== undefined && InkStrokeProperties.Instance.addPoints(inkView, this._nearestT, this._nearestSeg, this.inkScaledData().inkData.slice()); } } }), diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index ab3be3d7a..aec9e32fc 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -257,7 +257,7 @@ export class LightboxView extends ObservableReactComponent { styleProvider={DefaultStyleProvider} ScreenToLocalTransform={this.lightboxScreenToLocal} renderDepth={0} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 35ffab337..cd6aeea41 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -606,7 +606,7 @@ export class MainView extends ObservableReactComponent<{}> { Document={this.headerBarDoc} addDocTab={DocumentViewInternal.addDocTabFunc} pinToPres={emptyFunction} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} styleProvider={DefaultStyleProvider} addDocument={this.addHeaderDoc} removeDocument={this.removeHeaderDoc} @@ -641,7 +641,7 @@ export class MainView extends ObservableReactComponent<{}> { addDocument={undefined} addDocTab={DocumentViewInternal.addDocTabFunc} pinToPres={emptyFunction} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} styleProvider={this._hideUI ? DefaultStyleProvider : undefined} isContentActive={returnTrue} removeDocument={undefined} @@ -735,7 +735,7 @@ export class MainView extends ObservableReactComponent<{}> { addDocument={undefined} addDocTab={DocumentViewInternal.addDocTabFunc} pinToPres={TabDocView.PinDoc} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} styleProvider={this._sidebarContent.proto === Doc.MyDashboards || this._sidebarContent.proto === Doc.MyFilesystem || this._sidebarContent.proto === Doc.MyTrails ? DashboardStyleProvider : DefaultStyleProvider} removeDocument={returnFalse} ScreenToLocalTransform={this.mainContainerXf} @@ -769,7 +769,7 @@ export class MainView extends ObservableReactComponent<{}> { PanelWidth={this.leftMenuWidth} PanelHeight={this.leftMenuHeight} renderDepth={0} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} focus={emptyFunction} styleProvider={DefaultStyleProvider} isContentActive={returnTrue} @@ -900,14 +900,13 @@ export class MainView extends ObservableReactComponent<{}> { Document={Doc.MyDockedBtns} fieldKey="data" dropAction="embed" - setHeight={returnFalse} styleProvider={DefaultStyleProvider} bringToFront={emptyFunction} select={emptyFunction} isAnyChildContentActive={returnFalse} isContentActive={emptyFunction} isSelected={returnFalse} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} moveDocument={this.moveButtonDoc} addDocument={this.addButtonDoc} addDocTab={DocumentViewInternal.addDocTabFunc} @@ -969,41 +968,6 @@ export class MainView extends ObservableReactComponent<{}> { ); } - @observable mapBoxHackBool = false; - @computed get mapBoxHack() { - return this.mapBoxHackBool ? null : ( - r && (this.mapBoxHackBool = true))} - fieldKey="data" - select={returnFalse} - isSelected={returnFalse} - Document={this.headerBarDoc} - addDocTab={returnFalse} - pinToPres={emptyFunction} - docViewPath={returnEmptyDoclist} - styleProvider={DefaultStyleProvider} - addDocument={returnFalse} - removeDocument={returnFalse} - fitContentsToBox={returnTrue} - isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events) - isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive - ScreenToLocalTransform={Transform.Identity} - childHideResizeHandles={true} - childDragAction="move" - dontRegisterView={true} - PanelWidth={this.headerBarDocWidth} - PanelHeight={this.headerBarDocHeight} - renderDepth={0} - focus={emptyFunction} - whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} - childFilters={returnEmptyFilter} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - /> - ); - } - render() { return (
{ - {/* {this.mapBoxHack} */} diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 9d828364d..cfdc648b4 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -198,7 +198,7 @@ export class MarqueeAnnotator extends ObservableReactComponent this.highlight(this.props.highlightDragSrcColor ?? 'rgba(173, 216, 230, 0.75)', true, undefined, true); // hyperlink color const targetCreator = (annotationOn: Doc | undefined) => { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.props.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.props.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 915c3c18f..89527c415 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -234,7 +234,7 @@ export class OverlayView extends ObservableReactComponent<{}> { whenChildContentsActiveChanged={emptyFunction} focus={emptyFunction} styleProvider={DefaultStyleProvider} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} addDocTab={DocumentViewInternal.addDocTabFunc} pinToPres={emptyFunction} childFilters={returnEmptyFilter} diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index a69a5f5e8..456b753b4 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -60,18 +60,17 @@ export class PreviewCursor extends ObservableReactComponent<{}> { } else if (re.test(plain)) { const url = plain; if (!url.startsWith(window.location.href)) { - undoBatch( - () => - this._addDocument?.( - Docs.Create.WebDocument(url, { - title: url, - _width: 500, - _height: 300, - data_useCors: true, - x: newPoint[0], - y: newPoint[1], - }) - ) + undoBatch(() => + this._addDocument?.( + Docs.Create.WebDocument(url, { + title: url, + _width: 500, + _height: 300, + data_useCors: true, + x: newPoint[0], + y: newPoint[1], + }) + ) )(); } else alert('cannot paste dash into itself'); } else if (plain.startsWith('__DashDocId(') || plain.startsWith('__DashCloneId(')) { @@ -86,7 +85,7 @@ export class PreviewCursor extends ObservableReactComponent<{}> { } else { FormattedTextBox.PasteOnLoad = e; if (e.clipboardData.getData('dash/pdfAnchor')) e.preventDefault(); - UndoManager.RunInBatch(() => this._addLiveTextDoc?.(DocUtils.GetNewTextDoc('', newPoint[0], newPoint[1], 500, undefined, undefined, undefined, 750)), 'paste'); + UndoManager.RunInBatch(() => this._addLiveTextDoc?.(DocUtils.GetNewTextDoc('', newPoint[0], newPoint[1], 500, undefined, undefined, undefined)), 'paste'); } } //pasting in images diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 5905f8dbc..bba6285c2 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -345,9 +345,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch handlePerspectiveChange = (e: any) => { this.selectedDoc && (this.selectedDoc._type_collection = e.target.value); - SelectionManager.Views.filter(dv => dv.docView) - .map(dv => dv.docView!) - .forEach(docView => (docView.layoutDoc._type_collection = e.target.value)); + SelectionManager.Views.forEach(docView => (docView.layoutDoc._type_collection = e.target.value)); }; @computed get onClickVal() { const linkButton = IsFollowLinkScript(this.selectedDoc.onClick); @@ -408,28 +406,26 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action handleOptionChange = (onClick: string) => { - SelectionManager.Views.filter(dv => dv.docView) - .map(dv => dv.docView!) - .forEach(docView => { - const linkButton = IsFollowLinkScript(docView.Document.onClick); - docView.noOnClick(); - switch (onClick) { - case 'enterPortal': - docView.makeIntoPortal(); - break; - case 'toggleDetail': - docView.setToggleDetail(); - break; - case 'linkInPlace': - docView.toggleFollowLink(false, false); - docView.Document.followLinkLocation = linkButton ? OpenWhere.lightbox : undefined; - break; - case 'linkOnRight': - docView.toggleFollowLink(false, false); - docView.Document.followLinkLocation = linkButton ? OpenWhere.addRight : undefined; - break; - } - }); + SelectionManager.Views.forEach(docView => { + const linkButton = IsFollowLinkScript(docView.Document.onClick); + docView.noOnClick(); + switch (onClick) { + case 'enterPortal': + docView.makeIntoPortal(); + break; + case 'toggleDetail': + docView.setToggleDetail(); + break; + case 'linkInPlace': + docView.toggleFollowLink(false, false); + docView.Document.followLinkLocation = linkButton ? OpenWhere.lightbox : undefined; + break; + case 'linkOnRight': + docView.toggleFollowLink(false, false); + docView.Document.followLinkLocation = linkButton ? OpenWhere.addRight : undefined; + break; + } + }); }; @undoBatch diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index a710e7816..54f141a36 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -27,7 +27,7 @@ export class PropertiesDocContextSelector extends ObservableReactComponent embedding.embedContainer && embedding.embedContainer instanceof Doc).reduce((set, embedding) => set.add(Cast(embedding.embedContainer, Doc, null)), new Set()); const containerSets = Array.from(containerProtos.keys()).map(container => DocListCast(container.proto_embeddings)); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 2fcb5d12a..13057ffbf 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -299,7 +299,7 @@ export class PropertiesView extends ObservableReactComponent, props: Opt, property: string): any { +export function DefaultStyleProvider(doc: Opt, props: Opt, property: string): any { const remoteDocHeader = 'author;author_date;noMargin'; const docProps = testDocProps(props) ? props : undefined; const fieldProps = testFieldProps(props) ? props : undefined; const isCaption = property.includes(':caption'); const isAnchor = property.includes(':anchor'); + const isNonTransparent = property.includes(':nonTransparent'); + const isNonTransparentLevel = isNonTransparent ? Number(property.replace(/.*:nonTransparent([0-9]+).*/, '$1')) : 0; // property.includes(':nonTransparent'); const isContent = property.includes(':content'); const isAnnotated = property.includes(':annotated'); const isInk = () => doc?._layout_isSvg && !docProps?.LayoutTemplateString; @@ -95,7 +97,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt doc && BoolCast(doc._lockedPosition); const titleHeight = () => props?.styleProvider?.(doc, props, StyleProp.TitleHeight); - const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor); + const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor + ':nonTransparent' + (isNonTransparentLevel + 1)); const color = () => props?.styleProvider?.(doc, props, StyleProp.Color); const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity); const layout_showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle); @@ -140,7 +142,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color)); if (docColor) return docColor; - const docView = props?.DocumentView?.(); - const backColor = backgroundCol() || docView?._props.styleProvider?.(docView._props.treeViewDoc, docView.docView?._props, StyleProp.BackgroundColor); + const parView = props?.DocumentView?.(); + const backColor = backgroundCol(); return backColor ? lightOrDark(backColor) : undefined; case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + 'borderRounding'], StrCast(doc?.layout_borderRounding, doc?._type_collection === CollectionViewType.Pile ? '50%' : '')); @@ -198,18 +200,18 @@ export function DefaultStyleProvider(doc: Opt, props: Opt = StrCast(doc?.[fieldKey + '_backgroundColor'], StrCast(doc?._backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : '')); + let docColor: Opt = StrCast(doc?.[fieldKey + 'backgroundColor'], StrCast(doc?._backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : '')); // prettier-ignore switch (doc?.type) { case DocumentType.PRESELEMENT: docColor = docColor || ""; break; case DocumentType.PRES: docColor = docColor || 'transparent'; break; case DocumentType.FONTICON: docColor = boxBackground ? undefined : docColor || Colors.DARK_GRAY; break; - case DocumentType.RTF: docColor = docColor || Colors.LIGHT_GRAY; break; + case DocumentType.RTF: docColor = docColor || Colors.LIGHT_GRAY; break; case DocumentType.LINK: docColor = (isAnchor ? docColor : undefined); break; case DocumentType.INK: docColor = doc?.stroke_isInkMask ? 'rgba(0,0,0,0.7)' : undefined; break; case DocumentType.EQUATION: docColor = docColor || 'transparent'; break; case DocumentType.LABEL: docColor = docColor || Colors.LIGHT_GRAY; break; - case DocumentType.BUTTON: docColor = docColor || Colors.LIGHT_GRAY; break; + case DocumentType.BUTTON: docColor = docColor || Colors.LIGHT_GRAY; break; case DocumentType.IMG: case DocumentType.WEB: case DocumentType.PDF: @@ -230,6 +232,9 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt, props: Opt { - if (props?.docViewPath().lastElement()?.Document?._type_collection === CollectionViewType.Freeform) { + if (props?.DocumentView?.().containerViewPath?.().lastElement()?.Document?._type_collection === CollectionViewType.Freeform) { return doc?.pointerEvents !== 'none' ? null : (
toggleLockedPosition(doc)}> @@ -321,7 +326,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt StrListCast(dv?.Document.childFilters).length || StrListCast(dv?.Document.childRangeFilters).length) .map(dv => ({ text: StrCast(dv?.Document.title), @@ -339,7 +344,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt{StrListCast(doc[Doc.LayoutFieldKey(doc) + '_audioAnnotations_text']).lastElement()}
}> -
DocumentManager.Instance.getFirstDocumentView(doc)?.docView?.playAnnotation()}> +
DocumentManager.Instance.getFirstDocumentView(doc)?.playAnnotation()}>
@@ -374,7 +379,7 @@ export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, /** * add hide button decorations for the "Dashboards" flyout TreeView */ -export function DashboardStyleProvider(doc: Opt, props: Opt, property: string) { +export function DashboardStyleProvider(doc: Opt, props: Opt, property: string) { if (doc && property.split(':')[0] === StyleProp.Decorations) { return doc._type_collection === CollectionViewType.Docking || Doc.IsSystem(doc) ? null diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index b42f3c1e9..e5154efcb 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -114,8 +114,6 @@ export class TemplateMenu extends React.Component { , property: string): any => { + captionStyleProvider = (doc: Doc | undefined, captionProps: Opt, property: string): any => { // first look for properties on the document in the carousel, then fallback to properties on the container const childValue = doc?.['caption-' + property] ? this._props.styleProvider?.(doc, captionProps, property) : undefined; return childValue ?? this._props.styleProvider?.(this.layoutDoc, captionProps, property); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 874cdffd9..1f867fc44 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -431,7 +431,7 @@ export class CollectionDockingView extends CollectionSubView() { }; public CaptureThumbnail() { - const content = this._props.DocumentView?.()?.ContentDiv; + const content = this.DocumentView?.()?.ContentDiv; if (content) { const _width = Number(getComputedStyle(content).width.replace('px', '')); const _height = Number(getComputedStyle(content).height.replace('px', '')); diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 98ae01591..a54a5ec81 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -97,14 +97,12 @@ export class CollectionMenu extends AntimodeMenu { Document={selDoc} fieldKey="data" dropAction="embed" - setHeight={returnFalse} styleProvider={DefaultStyleProvider} bringToFront={emptyFunction} select={emptyFunction} isContentActive={returnTrue} isAnyChildContentActive={returnFalse} isSelected={returnFalse} - docViewPath={returnEmptyDoclist} moveDocument={returnFalse} addDocument={returnFalse} addDocTab={DocumentViewInternal.addDocTabFunc} diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 302ccd2db..0795104d9 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -18,7 +18,7 @@ import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { LightboxView } from '../LightboxView'; -import { DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps } from '../nodes/DocumentView'; +import { DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { StyleProp } from '../StyleProvider'; @@ -203,7 +203,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } }; - styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { + styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { switch (property) { case StyleProp.BoxShadow: if (doc && DragManager.docsBeingDragged.includes(doc)) { @@ -238,7 +238,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { PanelWidth={width} PanelHeight={height} styleProvider={this.styleProvider} - docViewPath={this._props.docViewPath} + containerViewPath={this.docViewPathFunc} layout_fitWidth={this._props.childLayoutFitWidth} isContentActive={emptyFunction} onKey={this.onKeyDown} @@ -511,7 +511,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { action((entries: any) => { if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.IsDragging) { const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); - if (!LightboxView.IsLightboxDocView(this._props.docViewPath())) { + if (!LightboxView.IsLightboxDocView(this.docViewPath)) { this._props.setHeight?.(height); } } @@ -643,7 +643,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { onDragOver={e => this.onPointerMove(true, e.clientX, e.clientY)} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu} - onWheel={e => this._props.isContentActive(true) && e.stopPropagation()}> + onWheel={e => this._props.isContentActive() && e.stopPropagation()}> {this.renderedSections}
); diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index b1d379631..d0df77cbe 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -48,7 +48,7 @@ export class CollectionPileView extends CollectionSubView() { removePileDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { (doc instanceof Doc ? [doc] : doc).forEach(d => Doc.deiconifyView(d)); const ret = this._props.moveDocument?.(doc, targetCollection, addDoc) || false; - if (ret && !DocListCast(this.dataDoc[this.fieldKey ?? 'data']).length) this._props.DocumentView?.()._props.removeDocument?.(this.Document); + if (ret && !DocListCast(this.dataDoc[this.fieldKey ?? 'data']).length) this.DocumentView?.()._props.removeDocument?.(this.Document); return ret; }; diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 22a67c501..1239a038a 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -23,7 +23,7 @@ import { undoBatch, UndoManager } from '../../util/UndoManager'; import { CollectionSubView } from '../collections/CollectionSubView'; import { LightboxView } from '../LightboxView'; import { AudioWaveform } from '../nodes/audio/AudioWaveform'; -import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps, OpenWhere, StyleProviderFunc } from '../nodes/DocumentView'; +import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, StyleProviderFunc } from '../nodes/DocumentView'; import { LabelBox } from '../nodes/LabelBox'; import { VideoBox } from '../nodes/VideoBox'; import { ObservableReactComponent } from '../ObservableReactComponent'; @@ -825,7 +825,7 @@ class StackedTimelineAnchor extends ObservableReactComponent (anchor.view = r))} Document={mark} TemplateDataDocument={undefined} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} pointerEvents={this.noEvents ? returnNone : undefined} styleProvider={this._props.styleProvider} renderDepth={this._props.renderDepth + 1} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 995f071ca..11ca62b39 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -24,7 +24,7 @@ import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from '../EditableView'; import { LightboxView } from '../LightboxView'; import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; -import { DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps } from '../nodes/DocumentView'; +import { DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { StyleProp } from '../StyleProvider'; @@ -265,7 +265,7 @@ export class CollectionStackingView extends CollectionSubView, property: string) => { + styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { if (property === StyleProp.Opacity && doc) { if (this._props.childOpacity) { return this._props.childOpacity(); @@ -325,9 +325,9 @@ export class CollectionStackingView extends CollectionSubView { if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.IsDragging) { const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); - if (!LightboxView.IsLightboxDocView(this._props.docViewPath())) { + if (!LightboxView.IsLightboxDocView(this.docViewPath)) { this._props.setHeight?.(height); } } @@ -681,7 +681,7 @@ export class CollectionStackingView extends CollectionSubView(moreProps?: X) { - class CollectionSubView extends ViewBoxBaseComponent() { + class CollectionSubView extends ViewBoxBaseComponent() { private dropDisposer?: DragManager.DragDropDisposer; private gestureDisposer?: GestureUtils.GestureEventDisposer; protected _mainCont?: HTMLDivElement; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 18e0b98ef..76b934802 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -169,7 +169,7 @@ export class CollectionTreeView extends CollectionSubView 0 && prev) { FormattedTextBox.SetSelectOnLoad(prev); - DocumentManager.Instance.getDocumentView(prev, this._props.DocumentView?.())?.select(false); + DocumentManager.Instance.getDocumentView(prev, this.DocumentView?.())?.select(false); } return true; } @@ -347,7 +347,7 @@ export class CollectionTreeView extends CollectionSubView this._props.childLayoutTemplate?.() || Cast(this.Document.childLayoutTemplate, Doc, null); isContentActive = (outsideReaction?: boolean) => this._isContentActive; - pointerEvents = () => { - const viewPath = this._props.DocumentView?.()?._props.docViewPath(); - return ( - this.layoutDoc._lockedPosition && // - viewPath?.lastElement()?.Document?._type_collection === CollectionViewType.Freeform - ); - }; + pointerEvents = () => + this.layoutDoc._lockedPosition && // + this.Document?._type_collection === CollectionViewType.Freeform; render() { TraceMobx(); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 80808be92..2441c67e6 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -29,7 +29,7 @@ import { LightboxView } from '../LightboxView'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; import { Colors } from '../global/globalEnums'; -import { DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps, OpenWhere, OpenWhereMod } from '../nodes/DocumentView'; +import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, OpenWhereMod } from '../nodes/DocumentView'; import { KeyValueBox } from '../nodes/KeyValueBox'; import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { PinProps, PresBox, PresMovement } from '../nodes/trails'; @@ -469,7 +469,7 @@ export class TabDocView extends ObservableReactComponent { dontCenter={'y'} whenChildContentsActiveChanged={this.whenChildContentActiveChanges} focus={this.focusFunc} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} bringToFront={emptyFunction} pinToPres={TabDocView.PinDoc} /> @@ -528,7 +528,7 @@ class TabMiniThumb extends React.Component { } @observer export class TabMinimapView extends ObservableReactComponent { - static miniStyleProvider = (doc: Opt, props: Opt, property: string): any => { + static miniStyleProvider = (doc: Opt, props: Opt, property: string): any => { if (doc) { switch (property.split(':')[0]) { default: @@ -595,10 +595,9 @@ export class TabMinimapView extends ObservableReactComponent { const ind = DocListCast(this.dataDoc[key]).indexOf(doc instanceof Doc ? doc : doc.lastElement()); const res = (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); - res && ind > 0 && DocumentManager.Instance.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.treeView._props.DocumentView?.())?.select(false); + res && ind > 0 && DocumentManager.Instance.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.treeView.DocumentView?.())?.select(false); return res; }; @@ -867,7 +867,7 @@ export class TreeView extends ObservableReactComponent { e.preventDefault(); } }; - titleStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { + titleStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (!doc || doc !== this.Document) return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView const treeView = this.treeView; @@ -899,7 +899,7 @@ export class TreeView extends ObservableReactComponent { } return treeView._props.styleProvider?.(doc, props, property); }; - embeddedStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { + embeddedStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (property.startsWith(StyleProp.Decorations)) return null; return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView }; @@ -977,7 +977,7 @@ export class TreeView extends ObservableReactComponent { hideResizeHandles={this.treeView.outlineMode} styleProvider={this.titleStyleProvider} onClickScriptDisable="never" // tree docViews have a script to show fields, etc. - docViewPath={this.treeView._props.docViewPath} + containerViewPath={this.treeView.docViewPathFunc} treeViewDoc={this.treeView.Document} addDocument={undefined} addDocTab={this._props.addDocTab} @@ -1084,7 +1084,7 @@ export class TreeView extends ObservableReactComponent { ScreenToLocalTransform={this.docTransform} renderDepth={this._props.renderDepth + 1} treeViewDoc={this.treeView?.Document} - docViewPath={this.treeView._props.docViewPath} + containerViewPath={this.treeView.docViewPathFunc} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8268a47d8..a8f22aaae 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -38,7 +38,7 @@ import { ActiveInkWidth, InkingStroke, SetActiveInkColor, SetActiveInkWidth } fr import { LightboxView } from '../../LightboxView'; import { CollectionFreeFormDocumentView, CollectionFreeFormDocumentViewWrapper } from '../../nodes/CollectionFreeFormDocumentView'; import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp'; -import { DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps, OpenWhere } from '../../nodes/DocumentView'; +import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from '../../nodes/DocumentView'; import { FieldViewProps } from '../../nodes/FieldView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../../nodes/trails/PresBox'; @@ -162,7 +162,7 @@ export class CollectionFreeFormView extends CollectionSubView { SelectionManager.DeselectAll(); - docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this._props.DocumentView?.())).forEach(dv => dv && SelectionManager.SelectView(dv, true)); + docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).forEach(dv => dv && SelectionManager.SelectView(dv, true)); }; addDocument = (newBox: Doc | Doc[]) => { let retVal = false; @@ -409,7 +409,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).filter(cd => (this._props.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === cluster); - const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this._props.DocumentView?.())!); + const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.DocumentView?.())!); const { left, top } = clusterDocs[0].getBounds() || { left: 0, top: 0 }; const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'embed' : undefined); de.moveDocument = this._props.moveDocument; @@ -586,7 +586,7 @@ export class CollectionFreeFormView extends CollectionSubView, props: Opt, property: string) => { + clusterStyleProvider = (doc: Opt, props: Opt, property: string) => { let styleProp = this._props.styleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1 if (doc && this.childDocList?.includes(doc)) switch (property) { @@ -629,7 +629,7 @@ export class CollectionFreeFormView extends CollectionSubView { - this._deleteList.forEach(ink => ink.props.removeDocument?.(ink.Document)); + this._deleteList.forEach(ink => ink._props.removeDocument?.(ink.Document)); this._deleteList = []; this._batch?.end(); }; @@ -714,7 +714,7 @@ export class CollectionFreeFormView extends CollectionSubView DocumentManager.Instance.getDocumentView(doc, this._props.DocumentView?.())) + .map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())) .filter(inkView => inkView?.ComponentView instanceof InkingStroke) .map(inkView => ({ inkViewBounds: inkView!.getBounds(), inkStroke: inkView!.ComponentView as InkingStroke, inkView: inkView! })) .filter( @@ -905,7 +905,7 @@ export class CollectionFreeFormView extends CollectionSubView doc.type === DocumentType.INK && !doc.dontIntersect) .forEach(doc => { - const otherInk = DocumentManager.Instance.getDocumentView(doc, this._props.DocumentView?.())?.ComponentView as InkingStroke; + const otherInk = DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())?.ComponentView as InkingStroke; const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] }; const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point)); const otherCtrlPts = otherScreenPts.map(spt => (ink.ComponentView as InkingStroke).ptFromScreen(spt)); @@ -979,7 +979,7 @@ export class CollectionFreeFormView extends CollectionSubView { - const collectionDoc = this._props.docViewPath().lastElement().Document; + const collectionDoc = this.Document; if (collectionDoc?._type_collection !== CollectionViewType.Freeform) { this.setPan( NumCast(this.layoutDoc[this.panXFieldKey]) + ((this._props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale @@ -1244,7 +1244,7 @@ export class CollectionFreeFormView extends CollectionSubView CollectionFreeFormView.UpdateIcon( this.layoutDoc[Id] + '-icon' + new Date().getTime(), - this._props.docViewPath().lastElement().ContentDiv!, + this.DocumentView?.().ContentDiv!, NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._height), this._props.PanelWidth(), @@ -1741,7 +1741,7 @@ export class CollectionFreeFormView extends CollectionSubView this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id])).length !== 0; incrementalRender = action(() => { - if (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath())) { + if (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.docViewPath)) { const layout_unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id])); const loadIncrement = 5; for (var i = 0; i < Math.min(layout_unrendered.length, loadIncrement); i++) { @@ -1755,7 +1755,7 @@ export class CollectionFreeFormView extends CollectionSubView {this.underlayViews} {this.contentViews} @@ -1896,6 +1896,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (!focused) { const selfFfview = !dv.Document.isGroup && dv.ComponentView instanceof CollectionFreeFormView ? dv.ComponentView : undefined; - let containers = dv.props.docViewPath(); + let containers = dv.containerViewPath?.() ?? []; let parFfview = dv.CollectionFreeFormView; for (var cont of containers) { parFfview = parFfview ?? cont.CollectionFreeFormView; } - while (parFfview?.Document.isGroup) parFfview = parFfview.props.DocumentView?.().CollectionFreeFormView; + while (parFfview?.Document.isGroup) parFfview = parFfview.DocumentView?.().CollectionFreeFormView; const ffview = selfFfview && selfFfview.layoutDoc[selfFfview.scaleFieldKey] !== 0.5 ? selfFfview : parFfview; // if focus doc is a freeform that is not at it's default 0.5 scale, then zoom out on it. Otherwise, zoom out on the parent ffview ffview?.zoomSmoothlyAboutPt(ffview.screenToFreeformContentsXf.transformPoint(clientX, clientY), ffview?.isAnnotationOverlay ? 1 : 0.5, browseTransitionTime); - Doc.linkFollowHighlight(dv?.props.Document, false); + Doc.linkFollowHighlight(dv?.Document, false); } }); } @@ -1968,13 +1969,13 @@ ScriptingGlobals.add(function curKeyFrame(readOnly: boolean) { }); ScriptingGlobals.add(function pinWithView(pinContent: boolean) { SelectionManager.Views.forEach(view => - view.props.pinToPres(view.Document, { + view._props.pinToPres(view.Document, { currentFrame: Cast(view.Document.currentFrame, 'number', null), pinData: { poslayoutview: pinContent, dataview: pinContent, }, - pinViewport: MarqueeView.CurViewBounds(view.Document, view.props.PanelWidth(), view.props.PanelHeight()), + pinViewport: MarqueeView.CurViewBounds(view.Document, view._props.PanelWidth(), view._props.PanelHeight()), }) ); }); diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index d105b04f7..54ade031b 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -147,8 +147,8 @@ export class CollectionLinearView extends CollectionSubView() { switch (doc.layout) { case '': return this.getLinkUI(); case '': return this.getCurrentlyPlayingUI(); - case '': return ; - case '': return Doc.UserDoc().isBranchingMode ? : null; + case '': return ; + case '': return Doc.UserDoc().isBranchingMode ? : null; } const nested = doc._type_collection === CollectionViewType.Linear; @@ -189,7 +189,7 @@ export class CollectionLinearView extends CollectionSubView() { dontRegisterView={BoolCast(this.Document.childDontRegisterViews)} focus={emptyFunction} styleProvider={this._props.styleProvider} - docViewPath={returnEmptyDoclist} + containerViewPath={this.docViewPathFunc} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} childFilters={this._props.childFilters} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 563084af8..dd1305465 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -127,7 +127,7 @@ export class CollectionMulticolumnView extends CollectionSubView() { private get totalRatioAllocation(): number | undefined { const layoutInfoLen = this.resolvedLayoutInformation.widthSpecifiers.length; if (layoutInfoLen > 0 && this.totalFixedAllocation !== undefined) { - return this._props.PanelWidth() - (this.totalFixedAllocation + resizerWidth * (layoutInfoLen - 1)) - 2 * NumCast(this._props.Document._xMargin); + return this._props.PanelWidth() - (this.totalFixedAllocation + resizerWidth * (layoutInfoLen - 1)) - 2 * NumCast(this.Document._xMargin); } } @@ -259,14 +259,14 @@ export class CollectionMulticolumnView extends CollectionSubView() { Document={childLayout} TemplateDataDocument={childLayout.resolvedDataDoc as Doc} styleProvider={this._props.styleProvider} - docViewPath={this._props.docViewPath} + containerViewPath={this.docViewPathFunc} LayoutTemplate={this._props.childLayoutTemplate} LayoutTemplateString={this._props.childLayoutString} renderDepth={this._props.renderDepth + 1} PanelWidth={width} PanelHeight={height} rootSelected={this.rootSelected} - dragAction={(this._props.Document.childDragAction ?? this._props.childDragAction) as dropActionType} + dragAction={StrCast(this.Document.childDragAction, this._props.childDragAction) as dropActionType} onClick={this.onChildClickHandler} onDoubleClick={this.onChildDoubleClickHandler} suppressSetHeight={true} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index bf0d39197..48c4173d6 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -122,7 +122,7 @@ export class CollectionMultirowView extends CollectionSubView() { private get totalRatioAllocation(): number | undefined { const layoutInfoLen = this.resolvedLayoutInformation.heightSpecifiers.length; if (layoutInfoLen > 0 && this.totalFixedAllocation !== undefined) { - return this._props.PanelHeight() - (this.totalFixedAllocation + resizerHeight * (layoutInfoLen - 1)) - 2 * NumCast(this._props.Document._yMargin); + return this._props.PanelHeight() - (this.totalFixedAllocation + resizerHeight * (layoutInfoLen - 1)) - 2 * NumCast(this.Document._yMargin); } } @@ -254,14 +254,14 @@ export class CollectionMultirowView extends CollectionSubView() { Document={layout} TemplateDataDocument={layout.resolvedDataDoc as Doc} styleProvider={this._props.styleProvider} - docViewPath={this._props.docViewPath} + containerViewPath={this.docViewPathFunc} LayoutTemplate={this._props.childLayoutTemplate} LayoutTemplateString={this._props.childLayoutString} renderDepth={this._props.renderDepth + 1} PanelWidth={width} PanelHeight={height} rootSelected={this.rootSelected} - dropAction={StrCast(this.Document.childDragAction) as dropActionType} + dragAction={StrCast(this.Document.childDragAction, this._props.childDragAction) as dropActionType} onClick={this.onChildClickHandler} onDoubleClick={this.onChildDoubleClickHandler} ScreenToLocalTransform={dxf} @@ -270,7 +270,6 @@ export class CollectionMultirowView extends CollectionSubView() { hideResizeHandles={layout.layout_fitWidth || this._props.childHideResizeHandles ? true : false} hideDecorationTitle={this._props.childHideDecorationTitle} fitContentsToBox={this._props.fitContentsToBox} - dragAction={this._props.childDragAction} focus={this._props.focus} childFilters={this.childDocFilters} childFiltersByRanges={this.childDocRangeFilters} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 492aed0ea..09352d7a4 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -16,7 +16,7 @@ import { undoable, undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; -import { DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps } from '../../nodes/DocumentView'; +import { DocFocusOptions, DocumentView } from '../../nodes/DocumentView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; @@ -907,7 +907,7 @@ export class CollectionSchemaView extends CollectionSubView() { childFiltersByRanges={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} styleProvider={DefaultStyleProvider} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} moveDocument={this._props.moveDocument} addDocument={this.addRow} removeDocument={this._props.removeDocument} @@ -962,7 +962,7 @@ class CollectionSchemaViewDoc extends ObservableReactComponent this._props.schema.tableWidth; screenToLocalXf = () => this._props.schema.ScreenToLocalBoxXf().translate(0, -this._props.rowHeight() - this._props.index * this._props.rowHeight()); - noOpacityStyleProvider = (doc: Opt, props: Opt, property: string) => { + noOpacityStyleProvider = (doc: Opt, props: Opt, property: string) => { if (property === StyleProp.Opacity) return 1; return DefaultStyleProvider(doc, props, property); }; @@ -971,6 +971,7 @@ class CollectionSchemaViewDoc extends ObservableReactComponent() { +export class SchemaRowBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string, rowIndex: number) { return FieldView.LayoutString(SchemaRowBox, fieldKey).replace('fieldKey', `rowIndex={${rowIndex}} fieldKey`); } @@ -38,11 +38,11 @@ export class SchemaRowBox extends ViewBoxBaseComponent this._ref?.getBoundingClientRect(); @computed get schemaView() { - return this._props.DocumentView?.()._props.docViewPath().lastElement()?.ComponentView as CollectionSchemaView; + return this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionSchemaView; } @computed get schemaDoc() { - return this._props.DocumentView?.()._props.docViewPath().lastElement()?.Document; + return this.DocumentView?.().containerViewPath?.().lastElement()?.Document; } @computed get rowIndex() { diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 85269028b..422c4155d 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -77,7 +77,6 @@ export class SchemaTableCell extends ObservableReactComponent dv.ComponentView instanceof InkingStroke) && SetActiveFillColor(color ?? 'transparent'); selectedViews.forEach(dv => { const fieldKey = dv.Document.type === DocumentType.INK ? 'fillColor' : 'backgroundColor'; - const layoutFrameNumber = Cast(dv._props.docViewPath().lastElement()?.Document?._currentFrame, 'number'); // frame number that container is at which determines layout frame values + const layoutFrameNumber = Cast(dv.containerViewPath?.().lastElement()?.Document?._currentFrame, 'number'); // frame number that container is at which determines layout frame values const contentFrameNumber = Cast(dv.Document?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed if (contentFrameNumber !== undefined) { const obj: { [key: string]: Opt } = {}; diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 85e97f95f..dc4aee1ca 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -136,6 +136,7 @@ export class LinkMenuItem extends ObservableReactComponent { deleteLink = (e: React.PointerEvent): void => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => LinkManager.Instance.deleteLink(this._props.linkDoc)))); @observable _hover = false; + docView = () => this.props.docView; render() { const destinationIcon = Doc.toIcon(this._props.destinationDoc) as any as IconProp; @@ -179,7 +180,8 @@ export class LinkMenuItem extends ObservableReactComponent { this._props.linkDoc && this._props.clearLinkEditor && LinkInfo.SetLinkInfo({ - docProps: this._props.docView._props, + DocumentView: this.docView, + styleProvider: this._props.docView._props.styleProvider, linkSrc: this._props.sourceDoc, linkDoc: this._props.linkDoc, showHeader: false, diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index 7e344dd7a..31841c596 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -69,7 +69,6 @@ export class LinkPopup extends React.Component { isSelected={returnTrue} isContentActive={returnTrue} select={returnTrue} - setHeight={returnFalse} addDocument={undefined} addDocTab={returnTrue} pinToPres={emptyFunction} @@ -81,7 +80,6 @@ export class LinkPopup extends React.Component { PanelHeight={this.getPHeight} renderDepth={0} focus={emptyFunction} - docViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} childFilters={returnEmptyFilter} diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx index 3d159c3e3..6760a0b1e 100644 --- a/src/client/views/newlightbox/NewLightboxView.tsx +++ b/src/client/views/newlightbox/NewLightboxView.tsx @@ -302,7 +302,7 @@ export class NewLightboxView extends React.Component { styleProvider={DefaultStyleProvider} ScreenToLocalTransform={this.newLightboxScreenToLocal} renderDepth={0} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} childFilters={this.docFilters} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 908cd5dc0..1729af191 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -211,7 +211,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent() { // removes from currently playing display @action removeCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (CollectionStackedTimeline.CurrentlyPlaying && docView) { const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView); index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1); @@ -221,7 +221,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent() { // adds doc to currently playing display @action addCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (!CollectionStackedTimeline.CurrentlyPlaying) { CollectionStackedTimeline.CurrentlyPlaying = []; } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index ad5aabc21..83cabf355 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -15,7 +15,7 @@ import { DocComponent } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import './CollectionFreeFormDocumentView.scss'; -import { DocumentView, DocumentViewInternalProps, DocumentViewProps, OpenWhere } from './DocumentView'; +import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView'; import { FieldViewProps } from './FieldView'; export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentViewProps { @@ -149,7 +149,7 @@ export class CollectionFreeFormDocumentView extends DocComponent, property: string) => { + styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { if (doc === this.layoutDoc) { switch (property) { case StyleProp.Opacity: return this._props.w_Opacity(); // only change the opacity for this specific document, not its children @@ -229,7 +229,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { const topDoc = this.Document; - const containerDocView = this._props.docViewPath().lastElement(); + const containerDocView = this._props.containerViewPath?.().lastElement(); const screenXf = containerDocView?.screenToContentsTransform(); if (screenXf) { SelectionManager.DeselectAll(); @@ -252,7 +252,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { - const [locX, locY] = this.ScreenToLocalBoxXf().transformDirection(x, y); + const [locX, locY] = this._props.ScreenToLocalTransform().transformDirection(x, y); this._props.Document.x = this._props.w_X() + locX; this._props.Document.y = this._props.w_Y() + locY; }; diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 5e7e568b0..b171db17c 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -11,7 +11,7 @@ import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import './ComparisonBox.scss'; -import { DocumentView, DocumentViewInternalProps, DocumentViewProps } from './DocumentView'; +import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { PinProps, PresBox } from './trails'; @@ -148,7 +148,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent this.clearDoc(which) ); }; - docStyleProvider = (doc: Opt, props: Opt, property: string): any => { + docStyleProvider = (doc: Opt, props: Opt, property: string): any => { if (property === StyleProp.PointerEvents) return 'none'; return this._props.styleProvider?.(doc, props, property); }; @@ -178,6 +178,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() { +export class DataVizBox extends ViewBoxAnnotatableComponent() { private _mainCont: React.RefObject = React.createRef(); - private _ffref = React.createRef(); private _marqueeref = React.createRef(); private _annotationLayer: React.RefObject = React.createRef(); anchorMenuClick?: () => undefined | ((anchor: Doc) => void); crop: ((region: Doc | undefined, addCrop?: boolean) => Doc | undefined) | undefined; - @observable schemaDataVizChildren: any = undefined; + @observable _schemaDataVizChildren: any = undefined; @observable _marqueeing: number[] | undefined = undefined; @observable _savedAnnotations = new ObservableMap(); + + constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { + super(props); + makeObservable(this); + this._props.setContentView?.(this); + } + @computed get annotationLayer() { TraceMobx(); return
; } marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.Document._freeform_scale, 1) <= NumCast(this.Document.freeform_scaleMin, 1) && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.Document._freeform_scale, 1) <= NumCast(this.Document.freeform_scaleMin, 1) && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -211,12 +216,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { .ScreenToLocalTransform() .scale(this._props.NativeDimScaling?.() || 1) .transformDirection(delta[0], delta[1]); - const fullWidth = this._props.width; - const mapWidth = fullWidth! - this.sidebarWidth(); + const fullWidth = NumCast(this.layoutDoc._width); + const mapWidth = fullWidth - this.sidebarWidth(); if (this.sidebarWidth() + localDelta[0] > 0) { this.layoutDoc._layout_showSidebar = true; - this.layoutDoc._width = fullWidth! + localDelta[0]; - this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth! + localDelta[0])).toString() + '%'; + this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; + this.layoutDoc._width = fullWidth + localDelta[0]; } else { this.layoutDoc._layout_showSidebar = false; this.layoutDoc._width = mapWidth; @@ -269,12 +274,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { axes: this.axes, //width: this.SidebarShown? this._props.PanelWidth()*.9/1.2: this._props.PanelWidth() * 0.9, height: (this._props.PanelHeight() / scale - 32) /* height of 'change view' button */ * 0.9, - width: (this._props.PanelWidth() / scale) * 0.9, + width: ((this._props.PanelWidth() - this.sidebarWidth()) / scale) * 0.9, margin: { top: 10, right: 25, bottom: 75, left: 45 }, }; if (!this.records.length) return 'no data/visualization'; switch (this.dataVizView) { - case DataVizView.TABLE: return ; + case DataVizView.TABLE: return ; case DataVizView.LINECHART: return (this._vizRenderer = r ?? undefined)} vizBox={this} />; case DataVizView.HISTOGRAM: return (this._vizRenderer = r ?? undefined)} />; case DataVizView.PIECHART: return (this._vizRenderer = r ?? undefined)} @@ -285,7 +290,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @action onPointerDown = (e: React.PointerEvent): void => { if ((this.Document._freeform_scale || 1) !== 1) return; - if (!e.altKey && e.button === 0 && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { this._props.select(false); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; @@ -345,7 +350,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { render() { if (this.layoutDoc && this.layoutDoc.dataViz_asSchema) { - this.schemaDataVizChildren = DocListCast(DocCast(this.layoutDoc.dataViz_asSchema)[Doc.LayoutFieldKey(DocCast(this.layoutDoc.dataViz_asSchema))]).length; + this._schemaDataVizChildren = DocListCast(DocCast(this.layoutDoc.dataViz_asSchema)[Doc.LayoutFieldKey(DocCast(this.layoutDoc.dataViz_asSchema))]).length; this.updateSchemaViz(); } @@ -366,7 +371,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { }} onWheel={e => e.stopPropagation()} ref={this._mainCont}> -
+
(this.layoutDoc._dataViz = DataVizView.TABLE)} toggleStatus={this.layoutDoc._dataViz === DataVizView.TABLE} /> (this.layoutDoc._dataViz = DataVizView.LINECHART)} toggleStatus={this.layoutDoc._dataViz === DataVizView.LINECHART} /> (this.layoutDoc._dataViz = DataVizView.HISTOGRAM)} toggleStatus={this.layoutDoc._dataViz === DataVizView.HISTOGRAM} /> @@ -414,7 +419,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() {
{this.sidebarHandle} {this.annotationLayer} - {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : ( () { scrollTop={0} annotationLayerScrollTop={NumCast(this.Document._layout_scrollTop)} scaling={returnOne} - docView={this._props.DocumentView!} + docView={this.DocumentView} addDocument={this.sidebarAddDocument} finishMarquee={this.finishMarquee} savedAnnotations={this.savedAnnotations} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 4cc7fe4c8..0d76959af 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -116,11 +116,12 @@ export class HTMLtag extends React.Component { @observer export class DocumentContentsView extends ObservableReactComponent< - DocumentViewProps & - FieldViewProps & { - setHeight?: (height: number) => void; - layout_fieldKey: string; - } + FieldViewProps & { + layout_fieldKey: string; + LayoutTemplateString?: string; + onClick?: () => ScriptField; + LayoutTemplate?: () => Opt; + } > { constructor(props: any) { super(props); diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index dfd610581..25f56e69a 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -25,7 +25,7 @@ export class DocumentIcon extends ObservableReactComponent { } static get DocViews() { - return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v._props.docViewPath())) : DocumentManager.Instance.DocumentViews; + return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v.docViewPath)) : DocumentManager.Instance.DocumentViews; } render() { const view = this._props.view; diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index c549a146a..f5949a451 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -152,8 +152,8 @@ export class DocumentLinksButton extends ObservableReactComponent Opt; -export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; +export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; export interface DocComponentView { fieldKey?: string; annotationKey?: string; @@ -143,20 +143,31 @@ export interface DocComponentView { snapPt?: (pt: { X: number; Y: number }, excludeSegs?: number[]) => { nearestPt: { X: number; Y: number }; distance: number }; search?: (str: string, bwd?: boolean, clear?: boolean) => boolean; } -// These props are passed to both FieldViews and DocumentViews +/** + * props that DocumentViews, DocumentInternalViews and FieldViews all can use + * */ export interface DocumentViewSharedProps { - renderDepth: number; Document: Doc; TemplateDataDocument?: Doc; + renderDepth: number; scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document - DocumentView?: () => DocumentView; + treeViewDoc?: Doc; + xPadding?: number; + yPadding?: number; + dontRegisterView?: boolean; + dropAction?: dropActionType; + dragAction?: dropActionType; + forceAutoHeight?: boolean; + ignoreAutoHeight?: boolean; + disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document isGroupActive?: () => string | undefined; // is this document part of a group that is active setContentView?: (view: DocComponentView) => any; PanelWidth: () => number; PanelHeight: () => number; - docViewPath: () => DocumentView[]; + isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events + isContentActive: () => boolean | undefined; // whether document contents should handle pointer events childFilters: () => string[]; childFiltersByRanges: () => string[]; styleProvider: Opt; @@ -178,29 +189,12 @@ export interface DocumentViewSharedProps { waitForDoubleClickToClick?: () => 'never' | 'always' | undefined; defaultDoubleClick?: () => 'default' | 'ignore' | undefined; pointerEvents?: () => Opt; - treeViewDoc?: Doc; - xPadding?: number; - yPadding?: number; - dontRegisterView?: boolean; - childHideDecorationTitle?: boolean; - childHideResizeHandles?: boolean; - childDragAction?: dropActionType; // allows child documents to be dragged out of collection without holding the embedKey or dragging the doc decorations title bar. - dropAction?: dropActionType; - dragAction?: dropActionType; - dragWhenActive?: boolean; - dontHideOnDrag?: boolean; - hideLinkButton?: boolean; - hideCaptions?: boolean; - ignoreAutoHeight?: boolean; - forceAutoHeight?: boolean; - suppressSetHeight?: boolean; - disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. - onClickScriptDisable?: 'never' | 'always'; // undefined = only when selected } -// these props are specific to DocuentViews +/** + * props that are used by DocumentViews and DocumentInternalViews but not by the contents of those views (FieldViews). + */ export interface DocumentViewProps extends DocumentViewSharedProps { - // properties specific to DocumentViews but not to FieldView hideDecorations?: boolean; // whether to suppress all DocumentDecorations when doc is selected hideResizeHandles?: boolean; // whether to suppress resized handles on doc decorations when this document is selected hideTitle?: boolean; // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings @@ -209,15 +203,22 @@ export interface DocumentViewProps extends DocumentViewSharedProps { hideOpenButton?: boolean; hideDeleteButton?: boolean; hideLinkAnchors?: boolean; + hideLinkButton?: boolean; + hideCaptions?: boolean; contentPointerEvents?: 'none' | 'all' | undefined; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents LayoutTemplateString?: string; dontCenter?: 'x' | 'y' | 'xy'; - isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events - isContentActive: () => boolean | undefined; // whether document contents should handle pointer events + childHideDecorationTitle?: boolean; + childHideResizeHandles?: boolean; + childDragAction?: dropActionType; // allows child documents to be dragged out of collection without holding the embedKey or dragging the doc decorations title bar. + dragWhenActive?: boolean; + dontHideOnDrag?: boolean; + suppressSetHeight?: boolean; + onClickScriptDisable?: 'never' | 'always'; // undefined = only when selected NativeWidth?: () => number; NativeHeight?: () => number; - NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps LayoutTemplate?: () => Opt; + containerViewPath?: () => DocumentView[]; contextMenuItems?: () => { script: ScriptField; filter?: ScriptField; label: string; icon: string }[]; onClick?: () => ScriptField; onDoubleClick?: () => ScriptField; @@ -229,12 +230,18 @@ export interface DocumentViewProps extends DocumentViewSharedProps { dragEnding?: () => void; } -// these props are only available in DocumentViewIntenral -export interface DocumentViewInternalProps extends DocumentViewProps { - isSelected: () => boolean; +/** + * props used by DocInternalViews and FieldViews but not DocumentViews + * these props correspond to things that the DocumentView creates and thus doesn't need to receive as a prop + */ +export interface DocumentViewInternalSharedProps { + DocumentView?: () => DocumentView; select: (ctrlPressed: boolean, shiftPress?: boolean) => void; - DocumentView: () => DocumentView; - viewPath: () => DocumentView[]; + isSelected: () => boolean; + NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal +} +export interface DocumentViewInternalProps extends DocumentViewProps, DocumentViewInternalSharedProps { + docViewPath: () => DocumentView[]; } @observer @@ -265,17 +272,24 @@ export class DocumentViewInternal extends DocComponent; + return this._props.styleProvider?.(this.layoutDoc, this.styleProps, StyleProp.ShowTitle) as Opt; } @computed get NativeDimScaling() { return this._props.NativeDimScaling?.() || 1; @@ -284,32 +298,32 @@ export class DocumentViewInternal extends DocComponent this._props.styleProvider?.(this.Document, this._props, StyleProp.PointerEvents), + () => this._props.styleProvider?.(this.Document, this.styleProps, StyleProp.PointerEvents), pointerevents => (this._pointerEvents = pointerevents), { fireImmediately: true } ); @@ -378,32 +392,32 @@ export class DocumentViewInternal extends DocComponent disposer?.()); } startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) { if (this._mainCont.current) { - const views = SelectionManager.Views.filter(dv => dv.docView?._mainCont.current); - const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [this._props.DocumentView()]; + const views = SelectionManager.Views.filter(dv => dv.ContentDiv); + const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [this.DocumentView()]; const dragData = new DragManager.DocumentDragData(selected.map(dv => dv.Document)); - const screenXf = this.props.DocumentView().screenToViewTransform(); + const screenXf = this.DocumentView().screenToViewTransform(); const [left, top] = screenXf.inverse().transformPoint(0, 0); dragData.offset = screenXf.transformDirection(x - left, y - top); dragData.dropAction = dropAction; dragData.treeViewDoc = this._props.treeViewDoc; dragData.removeDocument = this._props.removeDocument; dragData.moveDocument = this._props.moveDocument; - dragData.draggedViews = [this._props.DocumentView()]; + dragData.draggedViews = [this.DocumentView()]; dragData.canEmbed = this.Document.dragAction ?? this._props.dragAction ? true : false; DragManager.StartDocumentDrag( - selected.map(dv => dv.docView!._mainCont.current!), + selected.map(dv => dv.ContentDiv!), dragData, x, y, @@ -443,7 +457,7 @@ export class DocumentViewInternal extends DocComponent this.onDoubleClickHandler.script.run( { this: this.Document, scriptContext: this._props.scriptContext, - documentView: this._props.DocumentView(), + documentView: this.DocumentView(), clientX, clientY, altKey, shiftKey, ctrlKey, value: undefined, }, console.log ); @@ -451,7 +465,7 @@ export class DocumentViewInternal extends DocComponent LightboxView.Instance.AddDocTab(this.Document, OpenWhere.lightbox), 'double tap'); SelectionManager.DeselectAll(); - Doc.UnBrushDoc(this._props.Document); + Doc.UnBrushDoc(this.Document); } else { this._singleClickFunc?.(); } @@ -474,7 +488,7 @@ export class DocumentViewInternal extends DocComponent (sendToBack ? this._props.DocumentView()._props.bringToFront(this.Document, true) : + clickFunc ?? (() => (sendToBack ? this.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; @@ -522,7 +536,7 @@ export class DocumentViewInternal extends DocComponent this._props.removeDocument?.(this._props.Document); + @undoBatch deleteClicked = () => this._props.removeDocument?.(this.Document); @undoBatch setToggleDetail = () => (this.Document.onClick = ScriptField.MakeScript( `toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey) @@ -612,7 +626,7 @@ export class DocumentViewInternal extends DocComponent { if (this._props.dontRegisterView || this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return false; - if (this._props.Document === Doc.ActiveDashboard) { + if (this.Document === Doc.ActiveDashboard) { e.stopPropagation(); e.preventDefault(); alert( @@ -634,7 +648,7 @@ export class DocumentViewInternal extends DocComponent { - const portalLink = this.allLinks.find(d => d.link_anchor_1 === this._props.Document && d.link_relationship === 'portal to:portal from'); + const portalLink = this.allLinks.find(d => d.link_anchor_1 === this.Document && d.link_relationship === 'portal to:portal from'); if (!portalLink) { DocUtils.MakeLink( - this._props.Document, + this.Document, Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: Math.max(NumCast(this.layoutDoc._height), NumCast(this.layoutDoc._width) + 10), _isLightbox: true, _layout_fitWidth: true, - title: StrCast(this._props.Document.title) + ' [Portal]', + title: StrCast(this.Document.title) + ' [Portal]', }), { link_relationship: 'portal to:portal from' } ); @@ -686,7 +700,7 @@ export class DocumentViewInternal extends DocComponent { - if (this.Document.type !== DocumentType.MAP) DocumentViewInternal.SelectAfterContextMenu && !this._props.isSelected() && SelectionManager.SelectView(this._props.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + if (this.Document.type !== DocumentType.MAP) DocumentViewInternal.SelectAfterContextMenu && !this._props.isSelected() && SelectionManager.SelectView(this.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. setTimeout(() => simulateMouseClick(document.elementFromPoint(e.clientX, e.clientY), e.clientX, e.clientY, e.screenX, e.screenY)); }; if (navigator.userAgent.includes('Macintosh')) { @@ -719,14 +733,14 @@ export class DocumentViewInternal extends DocComponent cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.Document, scriptContext: this._props.scriptContext }), icon: 'sticky-note' }) ); this._props.contextMenuItems?.().forEach(item => item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.Document, scriptContext: this._props.scriptContext }), icon: item.icon as IconProp })); - if (!this._props.Document.isFolder) { - const templateDoc = Cast(this._props.Document[StrCast(this._props.Document.layout_fieldKey)], Doc, null); + if (!this.Document.isFolder) { + const templateDoc = Cast(this.Document[StrCast(this.Document.layout_fieldKey)], Doc, null); const appearance = cm.findByDescription('Appearance...'); const appearanceItems: ContextMenuProps[] = appearance && 'subitems' in appearance ? appearance.subitems : []; @@ -764,7 +778,7 @@ export class DocumentViewInternal extends DocComponent this.toggleFollowLink(false, false), icon: 'link' }); - !Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this._props.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); + !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' }); @@ -786,15 +800,15 @@ export class DocumentViewInternal extends DocComponent Doc.MakeMetadataFieldTemplate(this._props.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' }); + moreItems.push({ description: 'Make View of Metadata Field', event: () => Doc.MakeMetadataFieldTemplate(this.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' }); moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => (this.Document._chromeHidden = !this.Document._chromeHidden), icon: 'project-diagram' }); - if (Cast(Doc.GetProto(this._props.Document).data, listSpec(Doc))) { - moreItems.push({ description: 'Export to Google Photos Album', event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this._props.Document }).then(console.log), icon: 'caret-square-right' }); - moreItems.push({ description: 'Tag Child Images via Google Photos', event: () => GooglePhotos.Query.TagChildImages(this._props.Document), icon: 'caret-square-right' }); - moreItems.push({ description: 'Write Back Link to Album', event: () => GooglePhotos.Transactions.AddTextEnrichment(this._props.Document), icon: 'caret-square-right' }); + if (Cast(Doc.GetProto(this.Document).data, listSpec(Doc))) { + moreItems.push({ description: 'Export to Google Photos Album', event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.Document }).then(console.log), icon: 'caret-square-right' }); + moreItems.push({ description: 'Tag Child Images via Google Photos', event: () => GooglePhotos.Query.TagChildImages(this.Document), icon: 'caret-square-right' }); + moreItems.push({ description: 'Write Back Link to Album', event: () => GooglePhotos.Transactions.AddTextEnrichment(this.Document), icon: 'caret-square-right' }); } - moreItems.push({ description: 'Copy ID', event: () => Utils.CopyText(Doc.globalServerPath(this._props.Document)), icon: 'fingerprint' }); + moreItems.push({ description: 'Copy ID', event: () => Utils.CopyText(Doc.globalServerPath(this.Document)), icon: 'fingerprint' }); } } @@ -802,14 +816,14 @@ export class DocumentViewInternal extends DocComponent Doc.Zip(this._props.Document) }); - (this.Document._type_collection !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this._props.DocumentView()), icon: 'users' }); - if (this._props.removeDocument && Doc.ActiveDashboard !== this._props.Document) { + constantItems.push({ description: 'Zip Export', icon: 'download', event: async () => Doc.Zip(this.Document) }); + (this.Document._type_collection !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.DocumentView()), icon: 'users' }); + if (this._props.removeDocument && Doc.ActiveDashboard !== this.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions) constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' }); } } - constantItems.push({ description: 'Show Metadata', event: () => this._props.addDocTab(this._props.Document, OpenWhere.addRightKeyvalue), icon: 'table-columns' }); + constantItems.push({ description: 'Show Metadata', event: () => this._props.addDocTab(this.Document, OpenWhere.addRightKeyvalue), icon: 'table-columns' }); cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' }); const help = cm.findByDescription('Help...'); @@ -820,7 +834,7 @@ export class DocumentViewInternal extends DocComponent this._rootSelected; panelHeight = () => this._props.PanelHeight() - this.headerMargin; - screenToLocalContent = () => this.ScreenToLocalBoxXf().translate(0, -this.headerMargin); + screenToLocalContent = () => this._props.ScreenToLocalTransform().translate(0, -this.headerMargin); onClickFunc: any = () => (this.disableClickScriptFunc ? undefined : this.onClickHandler); setHeight = (height: number) => !this._props.suppressSetHeight && (this.layoutDoc._height = height); setContentView = action((view: { getAnchor?: (addAsAnnotation: boolean) => Doc; forward?: () => boolean; back?: () => boolean }) => (this._componentView = view)); @@ -912,7 +926,6 @@ export class DocumentViewInternal extends DocComponent this._props.PanelWidth() || 1; anchorPanelHeight = () => this._props.PanelHeight() || 1; - anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { + anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { // prettier-ignore switch (property.split(':')[0]) { case StyleProp.ShowTitle: return ''; @@ -976,7 +989,7 @@ export class DocumentViewInternal extends DocComponent, props: Opt, property: string) => this._props?.styleProvider?.(doc, props, property + ':caption'); + captionStyleProvider = (doc: Opt, props: Opt, property: string) => this._props?.styleProvider?.(doc, props, property + ':caption'); @observable _changingTitleField = false; @observable _dropDownInnerWidth = 0; fieldsDropdown = (inputOptions: string[], dropdownWidth: number, placeholder: string, onChange: (val: string | number) => void, onClose: () => void) => { @@ -1266,10 +1279,10 @@ export class DocumentViewInternal extends DocComponent { @computed public static get exploreMode() { return () => (SnappingManager.ExploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined); } - @observable public docView: DocumentViewInternal | undefined | null = undefined; - @observable public textHtmlOverlay: Opt = undefined; - @observable public textHtmlOverlayTime: Opt = undefined; + @observable private _docViewInternal: DocumentViewInternal | undefined | null = undefined; + @observable private _htmlOverlayText: Opt = undefined; @observable private _isHovering = false; + private _htmlOverlayEffect: Opt; - public htmlOverlayEffect: Opt; public get displayName() { - return 'DocumentView(' + this._props.Document?.title + ')'; + return 'DocumentView(' + this.Document?.title + ')'; } // this makes mobx trace() statements more descriptive public ContentRef = React.createRef(); public ViewTimer: NodeJS.Timeout | undefined; // timer for res @@ -1349,10 +1361,26 @@ export class DocumentView extends ObservableReactComponent { this.ViewTimer && clearTimeout(this.ViewTimer); this.layoutDoc._viewTransition = undefined; }; - public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this.docView?.startDragging(x, y, dropAction, hideSource); - - public showContextMenu = (pageX: number, pageY: number) => this.docView?.onContextMenu(undefined, pageX, pageY); - + playAnnotation = () => this._docViewInternal?.playAnnotation(); + noOnClick = () => this._docViewInternal?.noOnClick(); + makeIntoPortal = () => this._docViewInternal?.makeIntoPortal(); + setToggleDetail = () => this._docViewInternal?.setToggleDetail(); + onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => this._docViewInternal?.onContextMenu?.(e, pageX, pageY); + cleanupPointerEvents = () => this._docViewInternal?.cleanupPointerEvents(); + public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this._docViewInternal?.startDragging(x, y, dropAction, hideSource); + + public showContextMenu = (pageX: number, pageY: number) => this._docViewInternal?.onContextMenu(undefined, pageX, pageY); + + public setTextHtmlOverlay = action((text: string | undefined, effect?: Doc) => { + this._htmlOverlayText = text; + this._htmlOverlayEffect = effect; + }); + public setAnimateScaling = action((scale: number, time?: number) => { + if (this._docViewInternal) { + this._docViewInternal._animateScalingTo = scale; + this._docViewInternal._animateScaleTime = time; + } + }); public setAnimEffect = (presEffect: Doc, timeInMs: number, afterTrans?: () => void) => { this.AnimEffectTimer && clearTimeout(this.AnimEffectTimer); this.Document[Animation] = presEffect; @@ -1391,10 +1419,11 @@ export class DocumentView extends ObservableReactComponent { DocServer.GetRefField(docId).then(docx => LightboxView.Instance.SetLightboxDoc( (docx as Doc) ?? // reuse existing pivot view of documents, or else create a new collection - Docs.Create.StackingDocument([], { title: linkAnchor.title + '-pivot', _width: 500, _height: 500, target: linkAnchor, updateContentsScript: ScriptField.MakeScript('updateLinkCollection(this, this.target)') }, docId) + Docs.Create.StackingDocument([], { title: linkAnchor.title + '-pivot', _width: 500, _height: 500, target: linkAnchor, onViewMounted: ScriptField.MakeScript('updateLinkCollection(this, this.target)') }, docId) ) ); } + toggleFollowLink = (zoom?: boolean, setTargetToggle?: boolean): void => this._docViewInternal?.toggleFollowLink(zoom, setTargetToggle); get Document() { return this._props.Document; @@ -1403,19 +1432,19 @@ export class DocumentView extends ObservableReactComponent { return this._props.renderDepth === 0; } get dataDoc() { - return this.docView?.dataDoc ?? this.Document; + return this._docViewInternal?.dataDoc ?? this.Document; } get ContentDiv() { - return this.docView?.ContentDiv; + return this._docViewInternal?.ContentDiv; } get ComponentView() { - return this.docView?._componentView; + return this._docViewInternal?._componentView; } get allLinks() { - return (this.docView?.allLinks || []).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document); + return (this._docViewInternal?.allLinks || []).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document); } get LayoutFieldKey() { - return this.docView?.LayoutFieldKey || 'layout'; + return this._docViewInternal?.LayoutFieldKey || 'layout'; } @computed get layout_fitWidth() { return this._props.layout_fitWidth?.(this.layoutDoc) ?? this.layoutDoc?.layout_fitWidth; @@ -1439,8 +1468,17 @@ export class DocumentView extends ObservableReactComponent { @computed get linkCountView() { return ; } + /** + * path of DocumentViews terminating in the DocumentView that contains this DocumentView + */ + @computed get containerViewPath() { + return this._props.containerViewPath; + } + /** + * path of DocumentViews terminating in this DocumentView + */ @computed get docViewPath(): DocumentView[] { - return this._props.docViewPath ? [...this._props.docViewPath(), this] : [this]; + return this.containerViewPath ? [...this.containerViewPath(), this] : [this]; } @computed get layoutDoc() { return Doc.Layout(this.Document, this._props.LayoutTemplate?.()); @@ -1502,19 +1540,19 @@ export class DocumentView extends ObservableReactComponent { return this._props.CollectionFreeFormDocumentView?.(); } - public toggleNativeDimensions = () => this.docView && this.Document.type !== DocumentType.INK && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this._props.PanelWidth(), this._props.PanelHeight()); + public toggleNativeDimensions = () => this._docViewInternal && this.Document.type !== DocumentType.INK && Doc.toggleNativeDimensions(this.layoutDoc, this._docViewInternal.NativeDimScaling, this._props.PanelWidth(), this._props.PanelHeight()); public getBounds = () => { - if (!this.docView?.ContentDiv || this._props.treeViewDoc || Doc.AreProtosEqual(this._props.Document, Doc.UserDoc())) { + if (!this._docViewInternal?.ContentDiv || this._props.treeViewDoc || Doc.AreProtosEqual(this.Document, Doc.UserDoc())) { return undefined; } - if (this.docView._componentView?.screenBounds?.()) { - return this.docView._componentView.screenBounds(); + if (this._docViewInternal._componentView?.screenBounds?.()) { + return this._docViewInternal._componentView.screenBounds(); } - const xf = this.docView.ScreenToLocalBoxXf().scale(this.nativeScaling).inverse(); + const xf = this._docViewInternal._props.ScreenToLocalTransform().scale(this.nativeScaling).inverse(); const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)]; - if (this.docView._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { - const docuBox = this.docView.ContentDiv.getElementsByClassName('linkAnchorBox-cont'); + if (this._docViewInternal._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { + const docuBox = this._docViewInternal.ContentDiv.getElementsByClassName('linkAnchorBox-cont'); if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), center: undefined }; } return { left, top, right, bottom }; @@ -1522,11 +1560,11 @@ export class DocumentView extends ObservableReactComponent { public iconify(finished?: () => void, animateTime?: number) { this.ComponentView?.updateIcon?.(); - const animTime = this.docView?._animateScaleTime; - runInAction(() => this.docView && animateTime !== undefined && (this.docView._animateScaleTime = animateTime)); + const animTime = this._docViewInternal?._animateScaleTime; + runInAction(() => this._docViewInternal && animateTime !== undefined && (this._docViewInternal._animateScaleTime = animateTime)); const finalFinished = action(() => { finished?.(); - this.docView && (this.docView._animateScaleTime = animTime); + this._docViewInternal && (this._docViewInternal._animateScaleTime = animTime); }); const layout_fieldKey = Cast(this.Document.layout_fieldKey, 'string', null); if (layout_fieldKey !== 'layout_icon') { @@ -1541,12 +1579,12 @@ export class DocumentView extends ObservableReactComponent { } @undoBatch setCustomView = (custom: boolean, layout: string): void => { - Doc.setNativeView(this._props.Document); - custom && DocUtils.makeCustomViewClicked(this._props.Document, Docs.Create.StackingDocument, layout, undefined); + Doc.setNativeView(this.Document); + custom && DocUtils.makeCustomViewClicked(this.Document, Docs.Create.StackingDocument, layout, undefined); }; switchViews = (custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => { - runInAction(() => this.docView && (this.docView._animateScalingTo = 0.1)); // shrink doc + runInAction(() => this._docViewInternal && (this._docViewInternal._animateScalingTo = 0.1)); // shrink doc setTimeout( action(() => { if (useExistingLayout && custom && this.Document['layout_' + view]) { @@ -1554,16 +1592,16 @@ export class DocumentView extends ObservableReactComponent { } else { this.setCustomView(custom, view); } - this.docView && (this.docView._animateScalingTo = 1); // expand it + this._docViewInternal && (this._docViewInternal._animateScalingTo = 1); // expand it setTimeout( action(() => { - this.docView && (this.docView._animateScalingTo = 0); + this._docViewInternal && (this._docViewInternal._animateScalingTo = 0); finished?.(); }), - this.docView ? Math.max(0, this.docView.animateScaleTime - 10) : 0 + this._docViewInternal ? Math.max(0, this._docViewInternal.animateScaleTime - 10) : 0 ); }), - this.docView ? Math.max(0, this.docView?.animateScaleTime - 10) : 0 + this._docViewInternal ? Math.max(0, this._docViewInternal?.animateScaleTime - 10) : 0 ); }; @@ -1606,29 +1644,21 @@ export class DocumentView extends ObservableReactComponent { componentDidMount() { runInAction(() => this.Document[DocViews].add(this)); - this._disposers.updateContentsScript = reaction(() => ScriptCast(this.Document.updateContentsScript)?.script?.run({ this: this.Document }).result, emptyFunction); - this._disposers.height = reaction( - // increase max auto height if document has been resized to be greater than current max - () => NumCast(this.layoutDoc._height), - action(height => { - const docMax = NumCast(this.layoutDoc.layout_maxAutoHeight); - if (docMax && docMax < height) this.layoutDoc.layout_maxAutoHeight = height; - }) - ); - !BoolCast(this._props.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.AddView(this); + this._disposers.onViewMounted = reaction(() => ScriptCast(this.Document.onViewMounted)?.script?.run({ this: this.Document }).result, emptyFunction); + !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.AddView(this); } componentWillUnmount() { - this.Document[DocViews].delete(this); + runInAction(() => this.Document[DocViews].delete(this)); Object.values(this._disposers).forEach(disposer => disposer?.()); - !BoolCast(this._props.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); + !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); } // want the htmloverlay to be able to fade in but we also want it to be display 'none' until it is needed. // unfortunately, CSS can't transition animate any properties for something that is display 'none'. // so we need to first activate the div, then, after a render timeout, start the opacity transition. @observable enableHtmlOverlayTransitions: boolean = false; @computed get htmlOverlay() { - const effect = StrCast(this.htmlOverlayEffect?.presentation_effect, StrCast(this.htmlOverlayEffect?.followLinkAnimEffect)); + const effect = StrCast(this._htmlOverlayEffect?.presentation_effect, StrCast(this._htmlOverlayEffect?.followLinkAnimEffect)); return (
{ setTimeout(action(() => (this.enableHtmlOverlayTransitions = val))); } }} - style={{ display: !this.textHtmlOverlay ? 'none' : undefined }}> + style={{ display: !this._htmlOverlayText ? 'none' : undefined }}>
{DocumentViewInternal.AnimationEffect(
- console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this.textHtmlOverlay)} /> + console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this._htmlOverlayText)} />
, - { ...(this.htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc, + { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc, this.Document )}
@@ -1663,7 +1693,7 @@ export class DocumentView extends ObservableReactComponent { return (
(this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))}> - {!this._props.Document || !this._props.PanelWidth() ? null : ( + {!this.Document || !this._props.PanelWidth() ? null : (
{ { layout_fitWidth={this.layout_fitWidthFunc} ScreenToLocalTransform={this.screenToContentsTransform} focus={this._props.focus || emptyFunction} - ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))} + ref={action((r: DocumentViewInternal | null) => r && (this._docViewInternal = r))} /> {this.htmlOverlay} {this.infoUI} diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index ff92c701f..ebad257ac 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -27,7 +27,7 @@ export class EquationBox extends ViewBoxBaseComponent() { componentDidMount() { this._props.setContentView?.(this); - if (EquationBox.SelectOnLoad === this.Document[Id] && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath()))) { + if (EquationBox.SelectOnLoad === this.Document[Id] && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.docViewPath))) { this._props.select(false); this._ref.current!.mathField.focus(); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 008f10f26..b456807d7 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -6,23 +6,18 @@ import { Doc, Field, FieldResult, Opt } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { ScriptField } from '../../../fields/ScriptField'; import { WebField } from '../../../fields/URLField'; -import { DocumentViewSharedProps } from './DocumentView'; +import { DocumentView, DocumentViewInternalSharedProps, DocumentViewSharedProps } from './DocumentView'; // // these properties get assigned through the render() method of the DocumentView when it creates this node. // However, that only happens because the properties are "defined" in the markup for the field view. // See the LayoutString method on each field view : ImageBox, FormattedTextBox, etc. // -export interface FieldViewProps extends DocumentViewSharedProps { +export interface FieldViewProps extends DocumentViewSharedProps, DocumentViewInternalSharedProps { // FieldView specific props that are not part of DocumentView props fieldKey: string; - select: (isCtrlPressed: boolean) => void; - isContentActive: (outsideReaction?: boolean) => boolean | undefined; - isDocumentActive?: () => boolean | undefined; - isSelected: () => boolean; setHeight?: (height: number) => void; - NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to DocumentViewInternalsProps onBrowseClick?: () => ScriptField | undefined; onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => boolean | undefined; pointerEvents?: () => Opt; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index a5853499f..4483d12ce 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -158,7 +158,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { - const scaling = (this._props.DocumentView?.().screenToViewTransform().Scale || 1) / NumCast(this.layoutDoc._freeform_scale, 1); + const scaling = (this.DocumentView?.().screenToViewTransform().Scale || 1) / NumCast(this.layoutDoc._freeform_scale, 1); const nscale = NumCast(this._props.PanelWidth()) / scaling; const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); this.dataDoc[this.fieldKey + '_nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']) * nw; @@ -368,7 +368,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop) * this.ScreenToLocalBoxXf().Scale); marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) <= NumCast(this.dataDoc.freeform_scaleMin, 1) && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) <= NumCast(this.dataDoc.freeform_scaleMin, 1) && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -444,7 +444,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent {this.annotationLayer} - {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : ( { }; render() { - const props: FieldViewProps = { - Document: this._props.doc, - childFilters: returnEmptyFilter, - childFiltersByRanges: returnEmptyFilter, - searchFilterDocs: returnEmptyDoclist, - styleProvider: DefaultStyleProvider, - docViewPath: returnEmptyDoclist, - fieldKey: this._props.keyName, - isSelected: returnFalse, - setHeight: returnFalse, - select: emptyFunction, - bringToFront: emptyFunction, - renderDepth: 1, - isContentActive: returnFalse, - whenChildContentsActiveChanged: emptyFunction, - ScreenToLocalTransform: Transform.Identity, - focus: emptyFunction, - PanelWidth: this._props.PanelWidth, - PanelHeight: this._props.PanelHeight, - addDocTab: returnFalse, - pinToPres: returnZero, - }; // let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")"; let protoCount = 0; - let doc: Doc | undefined = props.Document; + let doc = this._props.doc; while (doc) { - if (Object.keys(doc).includes(props.fieldKey)) { + if (Object.keys(doc).includes(this._props.keyName)) { break; } protoCount++; @@ -106,17 +84,17 @@ export class KeyValuePair extends ObservableReactComponent { style={hover} className="keyValuePair-td-key-delete" onClick={undoBatch(() => { - if (Object.keys(props.Document).indexOf(props.fieldKey) !== -1) { - delete props.Document[props.fieldKey]; - } else delete DocCast(props.Document.proto)?.[props.fieldKey]; + if (Object.keys(this._props.doc).indexOf(this._props.keyName) !== -1) { + delete this._props.doc[this._props.keyName]; + } else delete DocCast(this._props.doc.proto)?.[this._props.keyName]; })}> X - pair[0].replace(/^_/, '') === props.fieldKey)?.[1].description ?? ''}> -
+ pair[0].replace(/^_/, '') === this._props.keyName)?.[1].description ?? ''}> +
{'('.repeat(parenCount)} - {props.fieldKey} + {this._props.keyName} {')'.repeat(parenCount)}
@@ -124,7 +102,32 @@ export class KeyValuePair extends ObservableReactComponent {
- Field.toKeyValueString(props.Document, props.fieldKey)} SetValue={(value: string) => KeyValueBox.SetField(props.Document, props.fieldKey, value)} /> + Field.toKeyValueString(this._props.doc, this._props.keyName)} + SetValue={(value: string) => KeyValueBox.SetField(this._props.doc, this._props.keyName, value)} + />
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index b86ba72a0..864c1955b 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -7,13 +7,13 @@ import { TraceMobx } from '../../../fields/util'; import { DragManager } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { SelectionManager } from '../../util/SelectionManager'; -import { ViewBoxBaseComponent } from '../DocComponent'; +import { ViewBoxBaseComponent, ViewBoxBaseProps } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; import { LinkInfo } from './LinkDocPreview'; const { default: { MEDIUM_GRAY }, } = require('../global/globalCssVariables.module.scss'); // prettier-ignore -export class LinkAnchorBox extends ViewBoxBaseComponent() { +export class LinkAnchorBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkAnchorBox, fieldKey); } @@ -33,12 +33,13 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { } @computed get linkSource() { - return this._props.docViewPath()[this._props.docViewPath().length - 2].Document; // this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.LinkSource); + return this.containerViewPath?.().lastElement().Document; // this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.LinkSource); } onPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (e, doubleTap) => { - if (doubleTap) LinkFollower.FollowLink(this.Document, this.linkSource, false); + const linkSource = this.linkSource; + linkSource && setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (e, doubleTap) => { + if (doubleTap) LinkFollower.FollowLink(this.Document, linkSource, false); else this._props.select(false); }); }; @@ -86,7 +87,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { className={`linkAnchorBox-cont${small ? '-small' : ''}`} onPointerEnter={e => LinkInfo.SetLinkInfo({ - docProps: this._props, + DocumentView: this.DocumentView, + styleProvider: this._props.styleProvider, linkSrc: this.linkSource, linkDoc: this.Document, showHeader: true, diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 7f1d41547..4221f464d 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -29,12 +29,12 @@ export class LinkBox extends ViewBoxBaseComponent() { @computed get anchor1() { const anchor1 = DocCast(this.dataDoc.link_anchor_1); const anchor_1 = anchor1?.layout_unrendered ? DocCast(anchor1.annotationOn) : anchor1; - return DocumentManager.Instance.getDocumentView(anchor_1, this._props.docViewPath()[this._props.docViewPath().length - 2]); // this._props.docViewPath().lastElement()); + return DocumentManager.Instance.getDocumentView(anchor_1, this.containerViewPath?.().lastElement()); } @computed get anchor2() { const anchor2 = DocCast(this.dataDoc.link_anchor_2); const anchor_2 = anchor2?.layout_unrendered ? DocCast(anchor2.annotationOn) : anchor2; - return DocumentManager.Instance.getDocumentView(anchor_2, this._props.docViewPath()[this._props.docViewPath().length - 2]); // this._props.docViewPath().lastElement()); + return DocumentManager.Instance.getDocumentView(anchor_2, this.containerViewPath?.().lastElement()); } screenBounds = () => { if (this.layoutDoc._layout_isSvg && this.anchor1 && this.anchor2 && this.anchor1.CollectionFreeFormView) { @@ -66,7 +66,7 @@ export class LinkBox extends ViewBoxBaseComponent() { const a = (this.anchor1 ?? this.anchor2)!; const b = (this.anchor2 ?? this.anchor1)!; - const parxf = this._props.docViewPath()[this._props.docViewPath().length - 2].ComponentView as CollectionFreeFormView; + const parxf = this.containerViewPath?.().lastElement().ComponentView as CollectionFreeFormView; const this_xf = parxf?.screenToFreeformContentsXf ?? Transform.Identity; //this.ScreenToLocalTransform(); const a_invXf = a.screenToViewTransform().inverse(); const b_invXf = b.screenToViewTransform().inverse(); @@ -161,12 +161,11 @@ export class LinkBox extends ViewBoxBaseComponent() { return (
; @@ -43,7 +44,8 @@ export class LinkInfo { interface LinkDocPreviewProps { linkDoc?: Doc; linkSrc?: Doc; - docProps: DocumentViewSharedProps; + DocumentView?: () => DocumentView; + styleProvider?: StyleProviderFunc; location: number[]; hrefs?: string[]; showHeader?: boolean; @@ -152,7 +154,7 @@ export class LinkDocPreview extends ObservableReactComponent { LinkManager.currentLink = this._linkDoc; LinkManager.currentLinkAnchor = this._linkSrc; - this._props.docProps.DocumentView?.().select(false); + this._props.DocumentView?.().select(false); if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) { SettingsManager.Instance.propertiesWidth = 250; } @@ -269,8 +271,8 @@ export class LinkDocPreview extends ObservableReactComponent { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); docView && DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { diff --git a/src/client/views/nodes/MapBox/MapPushpinBox.tsx b/src/client/views/nodes/MapBox/MapPushpinBox.tsx index 34e237007..fc5b4dd18 100644 --- a/src/client/views/nodes/MapBox/MapPushpinBox.tsx +++ b/src/client/views/nodes/MapBox/MapPushpinBox.tsx @@ -18,10 +18,10 @@ export class MapPushpinBox extends ViewBoxBaseComponent() { } get mapBoxView() { - return this._props.DocumentView?.()?._props.docViewPath().lastElement()?.ComponentView as MapBox; + return this.DocumentView?.()?.containerViewPath?.().lastElement()?.ComponentView as MapBox; } get mapBox() { - return this._props.DocumentView?.()._props.docViewPath().lastElement()?.Document; + return this.DocumentView?.().containerViewPath?.().lastElement()?.Document; } render() { diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index ea8496c99..e079f7457 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -228,11 +228,11 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); docView && DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 959d5d88d..71c1b6a4c 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -102,7 +102,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { // currently we render pdf icons as text labels - const docViewContent = this._props.docViewPath().lastElement().ContentDiv!; + const docViewContent = this.DocumentView?.().ContentDiv!; const filename = this.layoutDoc[Id] + '-icon' + new Date().getTime(); this._pdfViewer?._mainCont.current && CollectionFreeFormView.UpdateIcon( @@ -304,7 +304,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { this._pdfViewer = pdfViewer; - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (this._initialScrollTarget && docView) { this.focus(this._initialScrollTarget, { instant: true }); this._initialScrollTarget = undefined; @@ -525,7 +525,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent ) : ( -
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this._props.DocumentView?.()!, false), true)}> +
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}> () { +export class VideoBox extends ViewBoxAnnotatableComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(VideoBox, fieldKey); } @@ -608,7 +608,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { // removes from currently playing display @action removeCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (CollectionStackedTimeline.CurrentlyPlaying && docView) { const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView); index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1); @@ -617,7 +617,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { // adds doc to currently playing display @action addCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (!CollectionStackedTimeline.CurrentlyPlaying) { CollectionStackedTimeline.CurrentlyPlaying = []; } @@ -749,7 +749,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { // starts marquee selection marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) === 1 && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) === 1 && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -941,7 +941,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { style={{ pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined, borderRadius, - overflow: this._props.docViewPath?.().slice(-1)[0].layout_fitWidth ? 'auto' : undefined, + overflow: this.DocumentView?.().layout_fitWidth ? 'auto' : undefined, }}>
() {
{this.annotationLayer} - {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : ( () { annotationLayerScrollTop={0} scaling={returnOne} annotationLayerScaling={this._props.NativeDimScaling} - docView={this._props.DocumentView!} + docView={this.DocumentView} containerOffset={this.marqueeOffset} addDocument={this.addDocWithTimecode} finishMarquee={this.finishMarquee} @@ -1004,7 +1004,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { } @computed get UIButtons() { - const bounds = this._props.docViewPath().lastElement().getBounds(); + const bounds = this.DocumentView?.().getBounds(); const width = (bounds?.right || 0) - (bounds?.left || 0); const curTime = NumCast(this.layoutDoc._layout_currentTimecode); return ( diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index c3be2b390..86709e4d7 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -33,7 +33,7 @@ import { Annotation } from '../pdf/Annotation'; import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; import { SidebarAnnos } from '../SidebarAnnos'; import { StyleProp } from '../StyleProvider'; -import { DocComponentView, DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps, OpenWhere } from './DocumentView'; +import { DocComponentView, DocFocusOptions, DocumentView, OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { LinkInfo } from './LinkDocPreview'; import { PinProps, PresBox } from './trails'; @@ -250,7 +250,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { if (this._mainCont.current && selRange) { - if (this.dataDoc[this._props.fieldKey] instanceof HtmlField) this._mainCont.current.style.transform = `rotate(${NumCast(this._props.DocumentView!().screenToContentsTransform().RotateDeg)}deg)`; + if (this.dataDoc[this._props.fieldKey] instanceof HtmlField) this._mainCont.current.style.transform = `rotate(${NumCast(this.DocumentView!().screenToContentsTransform().RotateDeg)}deg)`; const clientRects = selRange.getClientRects(); for (let i = 0; i < clientRects.length; i++) { const rect = clientRects.item(i); @@ -274,7 +274,8 @@ export class WebBox extends ViewBoxAnnotatableComponent { - if (Doc.AreProtosEqual(doc, this.Document)) return new Promise>(res => res(this._props.DocumentView?.())); - if (this.Document.layout_fieldKey === 'layout_icon') this._props.DocumentView?.().iconify(); + if (Doc.AreProtosEqual(doc, this.Document)) return new Promise>(res => res(this.DocumentView?.())); + if (this.Document.layout_fieldKey === 'layout_icon') this.DocumentView?.().iconify(); const webUrl = WebCast(doc.config_data)?.url; if (this._url && webUrl && webUrl.href !== this._url) this.setData(webUrl.href); if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false); @@ -343,7 +344,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { this._getAnchor = AnchorMenu.Instance?.GetAnchor; // need to save AnchorMenu's getAnchor since a subsequent selection on another doc will overwrite this value this._textAnnotationCreator = undefined; - this._props.docViewPath().lastElement()?.docView?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here. + this.DocumentView?.()?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here. if (this._iframe?.contentWindow && this._iframe.contentDocument && !this._iframe.contentWindow.getSelection()?.isCollapsed) { const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); const scale = (this._props.NativeDimScaling?.() || 1) * mainContBounds.scale; @@ -364,7 +365,8 @@ export class WebBox extends ViewBoxAnnotatableComponent iframeHeight ? iframeHeight : scrollTop; - if (!LinkInfo.Instance?.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath()))) { + if (!LinkInfo.Instance?.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.docViewPath))) { this.layoutDoc.thumb = undefined; this.layoutDoc.thumbScrollTop = undefined; this.layoutDoc.thumbNativeWidth = undefined; @@ -723,10 +725,11 @@ export class WebBox extends ViewBoxAnnotatableComponent { const sel = this._url ? this._iframe?.contentDocument?.getSelection() : window.document.getSelection(); this._textAnnotationCreator = undefined; - if (sel?.empty) sel.empty(); // Chrome + if (sel?.empty) + sel.empty(); // Chrome else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox this.marqueeing = [e.clientX, e.clientY]; - if (!e.altKey && e.button === 0 && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -750,7 +753,8 @@ export class WebBox extends ViewBoxAnnotatableComponent { // if menu comes up right away, the down event can still be active causing a menu item to be selected this.specificContextMenu(undefined as any); - this._props.docViewPath().lastElement().docView?.onContextMenu(undefined, x, y); + this.DocumentView?.().onContextMenu(undefined, x, y); }); } } @@ -908,7 +912,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { - if (this._props.isContentActive(true)) { + if (this._props.isContentActive()) { e.stopPropagation(); } }; @@ -1065,7 +1069,7 @@ export class WebBox extends ViewBoxAnnotatableComponent this._sidebarRef.current?.anchorMenuClick; transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter]; opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.CanEmbed ? [] : [Utils.OpaqueBackgroundFilter])]; - childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { + childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc)) return 'none'; } @@ -1099,7 +1103,7 @@ export class WebBox extends ViewBoxAnnotatableComponent {this.webpage}
- {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : (
{ - let container = this._props.tbox._props.DocumentView?.()._props.docViewPath().lastElement(); + let container = this._props.tbox.containerViewPath?.().lastElement(); if (container) { const embedding = Doc.MakeEmbedding(container.Document); embedding._type_collection = CollectionViewType.Time; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index ae26f170b..6a6cec094 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -42,7 +42,7 @@ import { CollectionStackingView } from '../../collections/CollectionStackingView import { CollectionTreeView } from '../../collections/CollectionTreeView'; import { ContextMenu } from '../../ContextMenu'; import { ContextMenuProps } from '../../ContextMenuItem'; -import { ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { LightboxView } from '../../LightboxView'; import { AnchorMenu } from '../../pdf/AnchorMenu'; @@ -71,7 +71,7 @@ import { SummaryView } from './SummaryView'; export interface FormattedTextBoxProps {} @observer -export class FormattedTextBox extends ViewBoxAnnotatableComponent() { +export class FormattedTextBox extends ViewBoxAnnotatableComponent() { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); } @@ -123,7 +123,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this.getAnchor(true), targetCreator), e.pageX, e.pageY); + DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.DocumentView?.()!, () => this.getAnchor(true), targetCreator), e.pageX, e.pageY); }); const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); this._props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom); @@ -1410,7 +1410,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent 0 && !state.doc.resolve(xpos).node()?.isTextblock) { @@ -1764,7 +1764,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent p + toHgt(child), margins); - const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.layout_maxAutoHeight, proseHeight), proseHeight); + const scrollHeight = this.ProseRef && proseHeight; if (this._props.setHeight && scrollHeight && !this._props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation const setScrollHeight = () => (this.dataDoc[this.fieldKey + '_scrollHeight'] = scrollHeight); @@ -1852,7 +1852,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent ) : ( -
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this._props.DocumentView?.()!, false), true)}> +
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}> [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - Math.max(0, nbef - 1))), diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 6fa64a765..645ac08e1 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -294,13 +294,9 @@ export class PresBox extends ViewBoxBaseComponent() { listItemDoc.presentation_effect = this.activeItem.presBulletEffect; listItemDoc.presentation_transition = 500; targetView?.setAnimEffect(listItemDoc, 500); - if (targetView?.docView && this.activeItem.presBulletExpand) { - targetView.docView._animateScalingTo = 1.2; - targetView.docView._animateScaleTime = 400; - Doc.AddUnHighlightWatcher(() => { - targetView.docView!._animateScaleTime = undefined; - targetView!.docView!._animateScalingTo = 0; - }); + if (targetView && this.activeItem.presBulletExpand) { + targetView.setAnimateScaling(1.2, 400); + Doc.AddUnHighlightWatcher(() => targetView?.setAnimateScaling(0, undefined)); } listItemDoc.opacity = undefined; this.activeItem.presentation_indexed = presIndexed + 1; @@ -2622,7 +2618,7 @@ export class PresBox extends ViewBoxBaseComponent() { ScreenToLocalTransform={this.getTransform} AddToMap={this.AddToMap} RemFromMap={this.RemFromMap} - hierarchyIndex={emptyPath} + hierarchyIndex={emptyPath as any as number[]} /> ) : null}
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 4945d66c8..8cf01b9de 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -19,7 +19,7 @@ import { TreeView } from '../../collections/TreeView'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; -import { DocumentView, DocumentViewInternalProps, DocumentViewProps } from '../../nodes/DocumentView'; +import { DocumentView } from '../../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../../nodes/FieldView'; import { StyleProp } from '../../StyleProvider'; import { PresBox } from './PresBox'; @@ -50,7 +50,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { // the presentation view that renders this slide @computed get presBoxView() { - return this._props.DocumentView?.()?._props.docViewPath().lastElement()?.ComponentView as PresBox; + return this.containerViewPath?.().lastElement()?.ComponentView as PresBox; } // the presentation view document that renders this slide @@ -97,7 +97,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { presExpandDocumentClick = () => (this.slideDoc.presentation_expandInlineButton = !this.slideDoc.presentation_expandInlineButton); embedHeight = () => this.collapsedHeight + this.expandViewHeight; embedWidth = () => this._props.PanelWidth() / 2; - styleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { + styleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { return property === StyleProp.Opacity ? 1 : this._props.styleProvider?.(doc, props, property); }; /** @@ -116,7 +116,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { hideLinkButton={true} ScreenToLocalTransform={Transform.Identity} renderDepth={this._props.renderDepth + 1} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} childFilters={this._props.childFilters} childFiltersByRanges={this._props.childFiltersByRanges} searchFilterDocs={this._props.searchFilterDocs} @@ -196,7 +196,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { const dragArray = this.presBoxView?._dragArray ?? []; const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []); if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.slideDoc); - dragData.treeViewDoc = this.presBox?._type_collection === CollectionViewType.Tree ? this.presBox : undefined; // this._props.DocumentView?.()?._props.treeViewDoc; + dragData.treeViewDoc = this.presBox?._type_collection === CollectionViewType.Tree ? this.presBox : undefined; // this.DocumentView?.()?._props.treeViewDoc; dragData.moveDocument = this._props.moveDocument; const dragItem: HTMLElement[] = []; const classesToRestore = new Map(); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 4a7e35c16..89e5944f2 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -17,7 +17,7 @@ import { SnappingManager } from '../../util/SnappingManager'; import { MarqueeOptionsMenu } from '../collections/collectionFreeForm'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; -import { DocFocusOptions, DocumentViewInternalProps, DocumentViewProps } from '../nodes/DocumentView'; +import { DocFocusOptions, DocumentViewProps } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { LinkInfo } from '../nodes/LinkDocPreview'; import { ObservableReactComponent } from '../ObservableReactComponent'; @@ -30,7 +30,7 @@ const _global = (window /* browser */ || global) /* node */ as any; //pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`; // The workerSrc property shall be specified. -Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.0.269/build/pdf.worker.mjs'; +Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.0.379/build/pdf.worker.mjs'; interface IViewerProps extends FieldViewProps { Document: Doc; @@ -364,10 +364,10 @@ export class PDFViewer extends ObservableReactComponent { this._downX = e.clientX; this._downY = e.clientY; if ((this._props.Document._freeform_scale || 1) !== 1) return; - if ((e.button !== 0 || e.altKey) && this._props.isContentActive(true)) { + if ((e.button !== 0 || e.altKey) && this._props.isContentActive()) { this._setPreviewCursor?.(e.clientX, e.clientY, true, false, this._props.Document); } - if (!e.altKey && e.button === 0 && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { this._props.select(false); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeref.current?.onInitiateSelection([e.clientX, e.clientY]); @@ -465,7 +465,7 @@ export class PDFViewer extends ObservableReactComponent { @action onZoomWheel = (e: React.WheelEvent) => { - if (this._props.isContentActive(true)) { + if (this._props.isContentActive()) { e.stopPropagation(); if (e.ctrlKey) { const curScale = Number(this._pdfViewer.currentScaleValue); @@ -497,7 +497,7 @@ export class PDFViewer extends ObservableReactComponent { panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter]; opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.CanEmbed && this._props.isContentActive() ? [] : [Utils.OpaqueBackgroundFilter])]; - childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { + childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { const docProps = testDocProps(props) ? props : undefined; if (this.inlineTextAnnotations.includes(doc) || this._props.isContentActive() === false) return 'none'; diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index 575d5849e..188b2eba4 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -102,14 +102,12 @@ export class TopBar extends React.Component { Document={selDoc} fieldKey="data" dropAction="embed" - setHeight={returnFalse} styleProvider={DefaultStyleProvider} bringToFront={emptyFunction} select={emptyFunction} isContentActive={returnTrue} isAnyChildContentActive={returnFalse} isSelected={returnFalse} - docViewPath={returnEmptyDoclist} moveDocument={returnFalse} addDocument={returnFalse} addDocTab={DocumentViewInternal.addDocTabFunc} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index a1ce55314..9d68ea731 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -396,7 +396,7 @@ export class MobileInterface extends React.Component { isContentActive={emptyFunction} focus={emptyFunction} styleProvider={this.whitebackground} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} childFilters={returnEmptyFilter} diff --git a/src/server/DashStats.ts b/src/server/DashStats.ts index b6164832f..a9e6af67c 100644 --- a/src/server/DashStats.ts +++ b/src/server/DashStats.ts @@ -15,7 +15,8 @@ export namespace DashStats { export const SAMPLING_INTERVAL = 1000; // in milliseconds (ms) - Time interval to update the frontend. export const RATE_INTERVAL = 10; // in seconds (s) - Used to calculate rate - const statsCSVFilename = './src/server/stats/userLoginStats.csv'; + const statsCSVDirectory = './src/server/stats/'; + const statsCSVFilename = statsCSVDirectory + 'userLoginStats.csv'; const columns = ['USERNAME', 'ACTION', 'TIME']; /** @@ -153,6 +154,7 @@ export namespace DashStats { TIME: currentDate.toISOString(), }; + if (!fs.existsSync(statsCSVDirectory)) fs.mkdirSync(statsCSVDirectory); let statsFile = fs.createWriteStream(statsCSVFilename, { flags: 'a' }); statsFile.write(convertToCSV(toWrite)); statsFile.end(); -- cgit v1.2.3-70-g09d2 From c8be94244bcd094efba739e5a46034bceccea80f Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 24 Jan 2024 16:13:27 -0500 Subject: several fixes to drag/drop so that dropAction's set on target work for tree views, notetaking, formattedText, etc. make bringToFront an optional prop. --- src/client/documents/Documents.ts | 3 +- src/client/util/DragManager.ts | 8 +- src/client/views/DocComponent.tsx | 6 +- src/client/views/GestureOverlay.tsx | 1 - src/client/views/LightboxView.tsx | 1 - src/client/views/MainView.tsx | 5 -- src/client/views/OverlayView.tsx | 1 - src/client/views/PropertiesView.tsx | 1 - src/client/views/StyleProvider.tsx | 2 +- src/client/views/TemplateMenu.tsx | 1 - .../views/collections/CollectionCarousel3DView.tsx | 3 +- .../views/collections/CollectionCarouselView.tsx | 1 - .../collections/CollectionMasonryViewFieldRow.tsx | 2 +- src/client/views/collections/CollectionMenu.tsx | 1 - .../views/collections/CollectionNoteTakingView.tsx | 1 - .../collections/CollectionNoteTakingViewColumn.tsx | 6 +- .../collections/CollectionStackedTimeline.tsx | 1 - .../views/collections/CollectionStackingView.tsx | 2 - .../CollectionStackingViewFieldColumn.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 11 +-- src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 2 - src/client/views/collections/TreeView.tsx | 72 +++++++++++------- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 - .../collectionLinear/CollectionLinearView.tsx | 17 ++--- .../CollectionMulticolumnView.tsx | 3 +- .../CollectionMultirowView.tsx | 3 +- .../collectionSchema/CollectionSchemaView.tsx | 2 - .../collectionSchema/SchemaTableCell.tsx | 1 - src/client/views/linking/LinkPopup.tsx | 4 +- src/client/views/newlightbox/NewLightboxView.tsx | 1 - src/client/views/nodes/AudioBox.tsx | 4 +- src/client/views/nodes/DocumentContentsView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 87 +++++++++++----------- src/client/views/nodes/FieldView.tsx | 4 +- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 1 - src/client/views/nodes/LinkDocPreview.tsx | 1 - src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 3 +- src/client/views/nodes/WebBox.tsx | 1 - .../views/nodes/formattedText/DashDocView.tsx | 1 - .../views/nodes/formattedText/FormattedTextBox.tsx | 15 +++- src/client/views/nodes/trails/PresBox.tsx | 1 + src/client/views/nodes/trails/PresElementBox.tsx | 1 - src/client/views/pdf/PDFViewer.tsx | 1 - src/client/views/topbar/TopBar.tsx | 1 - src/mobile/MobileInterface.tsx | 1 - 49 files changed, 138 insertions(+), 160 deletions(-) (limited to 'src/client/views/OverlayView.tsx') 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).detail); const preDropHandler = (e: Event) => { const de = (e as CustomEvent).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

() { } @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

() { 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

() { } 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 { 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)` }}>

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, props: Opt 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 { 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} />
{!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 { 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 { + 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 ), 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 ); @@ -682,7 +681,6 @@ export class CollectionStackingView extends CollectionSubView(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 { - 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 ); } @@ -349,7 +344,6 @@ export class CollectionTreeView extends CollectionSubView {this.content} 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 { whenChildContentsActiveChanged={this.whenChildContentActiveChanges} focus={this.focusFunc} containerViewPath={returnEmptyDoclist} - bringToFront={emptyFunction} pinToPres={TabDocView.PinDoc} /> {this.disableMinimap() ? null : } @@ -604,7 +603,6 @@ export class TabMinimapView extends ObservableReactComponent { _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 { 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 { 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 { 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 { }; 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 { 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 { 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 { ? 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 { 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 { 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 { 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}>
{ 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 { addDocTab={this._props.addDocTab} pinToPres={this.treeView._props.pinToPres} disableBrushing={this.treeView._props.disableBrushing} - bringToFront={returnFalse} scriptContext={this} />
@@ -1143,7 +1161,7 @@ export class TreeView extends ObservableReactComponent { 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 { - 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() { {'Toggle description pop-up'}
} placement="top"> - Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : 'ON'} + Labels: {LinkDescriptionPopup.Instance.showDescriptions ? LinkDescriptionPopup.Instance.showDescriptions : 'ON'} @@ -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} /> )}
@@ -989,7 +988,6 @@ class CollectionSchemaViewDoc extends ObservableReactComponent { { 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 { 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() { 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() { 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 { - 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= 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 (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 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 window.open(documentationLink, '_blank'), @@ -996,12 +994,11 @@ export class DocumentViewInternal extends DocComponent() { } @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() { 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; @@ -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() 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 { 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 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() 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() 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() 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() 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 = React.createRef(); private _editorView: Opt; 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; + 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() { 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() { whenChildContentsActiveChanged={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} - bringToFront={returnFalse} />
); 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 { isAnnotationOverlayScrollable={true} childFilters={childFilters} select={emptyFunction} - bringToFront={emptyFunction} styleProvider={this.childStyleProvider} />
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} -- cgit v1.2.3-70-g09d2