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 --- 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 +++---- 80 files changed, 575 insertions(+), 910 deletions(-) create mode 100644 src/client/views/ObservableReactComponent.tsx (limited to 'src') 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