From 380ee1acac1c0b7972d7d423cf804af146dc0edf Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 10 Dec 2023 20:19:27 -0500
Subject: massive changes to use mobx 6 which means not accessing props
 directly in @computed functions.

---
 src/client/views/nodes/DocumentLinksButton.tsx | 106 +++++++++++++++----------
 1 file changed, 65 insertions(+), 41 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 90b044374..19b43fd52 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -1,10 +1,10 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@mui/material';
-import { action, computed, observable, runInAction } from 'mobx';
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc } from '../../../fields/Doc';
 import { StrCast } from '../../../fields/Types';
-import { emptyFunction, returnFalse, setupMoveUpEvents, StopEvent } from '../../../Utils';
+import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents, StopEvent } from '../../../Utils';
 import { DocUtils } from '../../documents/Documents';
 import { DragManager } from '../../util/DragManager';
 import { Hypothesis } from '../../util/HypothesisUtils';
@@ -16,7 +16,6 @@ import { LinkDescriptionPopup } from './LinkDescriptionPopup';
 import { TaskCompletionBox } from './TaskCompletedBox';
 import { PinProps } from './trails';
 import * as React from 'react';
-import * as _ from 'lodash';
 
 interface DocumentLinksButtonProps {
     View: DocumentView;
@@ -29,25 +28,51 @@ interface DocumentLinksButtonProps {
     scaling?: () => number; // how uch doc is scaled so that link buttons can invert it
     hideCount?: () => boolean;
 }
+
+export class DocButtonState {
+    @observable public StartLink: Doc | undefined = undefined; //origin's Doc, if defined
+    @observable public StartLinkView: DocumentView | undefined = undefined;
+    @observable public AnnotationId: string | undefined = undefined;
+    @observable public AnnotationUri: string | undefined = undefined;
+    @observable public LinkEditorDocView: DocumentView | undefined = undefined;
+    public static _instance: DocButtonState | undefined;
+    public static get Instance() {
+        return DocButtonState._instance ?? (DocButtonState._instance = new DocButtonState());
+    }
+    constructor() {
+        makeObservable(this);
+    }
+}
 @observer
 export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> {
     private _linkButton = React.createRef<HTMLDivElement>();
-    @observable public static StartLink: Doc | undefined; //origin's Doc, if defined
-    @observable public static StartLinkView: DocumentView | undefined;
-    @observable public static AnnotationId: string | undefined;
-    @observable public static AnnotationUri: string | undefined;
-    @observable public static LinkEditorDocView: DocumentView | undefined;
+    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<DocumentLinksButtonProps>;
+    @observable _props: React.PropsWithChildren<DocumentLinksButtonProps>;
+    constructor(props: React.PropsWithChildren<DocumentLinksButtonProps>) {
+        super(props);
+        this._props = this._prevProps = props;
+        makeObservable(this);
+    }
+
+    componentDidUpdate() {
+        copyProps(this);
+    }
 
-    @action
     @undoBatch
     onLinkButtonMoved = (e: PointerEvent) => {
-        if (this.props.InMenu && this.props.StartLink) {
+        if (this._props.InMenu && this._props.StartLink) {
             if (this._linkButton.current !== null) {
                 const linkDrag = UndoManager.StartBatch('Drag Link');
-                this.props.View &&
-                    DragManager.StartLinkDrag(this._linkButton.current, this.props.View, this.props.View.ComponentView?.getAnchor, e.pageX, e.pageY, {
+                this._props.View &&
+                    DragManager.StartLinkDrag(this._linkButton.current, this._props.View, this._props.View.ComponentView?.getAnchor, e.pageX, e.pageY, {
                         dragComplete: dropEv => {
-                            if (this.props.View && dropEv.linkDocument) {
+                            if (this._props.View && dropEv.linkDocument) {
                                 // dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
                                 !dropEv.linkDocument.link_relationship && (Doc.GetProto(dropEv.linkDocument).link_relationship = 'hyperlink');
                             }
@@ -69,11 +94,11 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             this.onLinkButtonMoved,
             emptyFunction,
             action((e, doubleTap) => {
-                doubleTap && DocumentView.showBackLinks(this.props.View.Document);
+                doubleTap && DocumentView.showBackLinks(this._props.View.Document);
             }),
             undefined,
             undefined,
-            action(() => (DocumentLinksButton.LinkEditorDocView = this.props.View))
+            action(() => (DocButtonState.Instance.LinkEditorDocView = this._props.View))
         );
     };
 
@@ -84,33 +109,32 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             this.onLinkButtonMoved,
             emptyFunction,
             action((e, doubleTap) => {
-                if (doubleTap && this.props.InMenu && this.props.StartLink) {
-                    //action(() => Doc.BrushDoc(this.props.View.Document));
-                    if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
+                if (doubleTap && this._props.InMenu && this._props.StartLink) {
+                    //action(() => Doc.BrushDoc(this._props.View.Document));
+                    if (DocumentLinksButton.StartLink === this._props.View.Document) {
                         DocumentLinksButton.StartLink = undefined;
                         DocumentLinksButton.StartLinkView = undefined;
                     } else {
-                        DocumentLinksButton.StartLink = this.props.View.props.Document;
-                        DocumentLinksButton.StartLinkView = this.props.View;
+                        DocumentLinksButton.StartLink = this._props.View.Document;
+                        DocumentLinksButton.StartLinkView = this._props.View;
                     }
                 }
             })
         );
     };
 
-    @action
     @undoBatch
     onLinkClick = (e: React.MouseEvent): void => {
-        if (this.props.InMenu && this.props.StartLink) {
+        if (this._props.InMenu && this._props.StartLink) {
             DocumentLinksButton.AnnotationId = undefined;
             DocumentLinksButton.AnnotationUri = undefined;
-            if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
+            if (DocumentLinksButton.StartLink === this._props.View.Document) {
                 DocumentLinksButton.StartLink = undefined;
                 DocumentLinksButton.StartLinkView = undefined;
             } else {
                 //if this LinkButton's Document is undefined
-                DocumentLinksButton.StartLink = this.props.View.props.Document;
-                DocumentLinksButton.StartLinkView = this.props.View;
+                DocumentLinksButton.StartLink = this._props.View.Document;
+                DocumentLinksButton.StartLinkView = this._props.View;
             }
         }
     };
@@ -121,7 +145,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             e,
             returnFalse,
             emptyFunction,
-            action(e => DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View))
+            action(e => DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this._props.View.Document, true, this._props.View))
         );
     };
 
@@ -133,7 +157,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 DocumentLinksButton.StartLinkView = undefined;
                 DocumentLinksButton.AnnotationId = undefined;
                 DocumentLinksButton.AnnotationUri = undefined;
-                //!this.props.StartLink
+                //!this._props.StartLink
             } else if (startLink !== endLink) {
                 endLink = endLinkView?.docView?._componentView?.getAnchor?.(true, pinProps) || endLink;
                 startLink = DocumentLinksButton.StartLinkView?.docView?._componentView?.getAnchor?.(true) || startLink;
@@ -190,8 +214,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
     @computed get filteredLinks() {
         const results = [] as Doc[];
-        const filters = this.props.View.props.childFilters();
-        Array.from(new Set<Doc>(this.props.View.allLinks)).forEach(link => {
+        const filters = this._props.View._props.childFilters();
+        Array.from(new Set<Doc>(this._props.View.allLinks)).forEach(link => {
             if (DocUtils.FilterDocs([link], filters, []).length || DocUtils.FilterDocs([link.link_anchor_2 as Doc], filters, []).length || DocUtils.FilterDocs([link.link_anchor_1 as Doc], filters, []).length) {
                 results.push(link);
             }
@@ -206,8 +230,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
      */
     @computed get linkButtonInner() {
         const btnDim = 30;
-        const isActive = DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink;
-        const scaling = Math.min(1, this.props.scaling?.() || 1);
+        const isActive = DocumentLinksButton.StartLink === this._props.View.Document && this._props.StartLink;
+        const scaling = Math.min(1, this._props.scaling?.() || 1);
         const showLinkCount = (onHover?: boolean, offset?: boolean) => (
             <div
                 className="documentLinksButton-showCount"
@@ -221,16 +245,16 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 <span style={{ width: '100%', display: 'inline-block', textAlign: 'center' }}>{Array.from(this.filteredLinks).length}</span>
             </div>
         );
-        return this.props.ShowCount ? (
-            showLinkCount(this.props.OnHover, this.props.Bottom)
+        return this._props.ShowCount ? (
+            showLinkCount(this._props.OnHover, this._props.Bottom)
         ) : (
             <div className="documentLinksButton-menu">
-                {this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
+                {this._props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
                     <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? StopEvent : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}>
                         <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
                     </div>
                 ) : null}
-                {!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node
+                {!this._props.StartLink && DocumentLinksButton.StartLink !== this._props.View.Document ? ( //if the origin node is not this node
                     <div className={'documentLinksButton-endLink'} ref={this._linkButton} onPointerDown={DocumentLinksButton.StartLink && this.completeLink}>
                         <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
                     </div>
@@ -240,21 +264,21 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     }
 
     render() {
-        if (this.props.hideCount?.()) return null;
-        const menuTitle = this.props.StartLink ? 'Drag or tap to start link' : 'Tap to complete link';
+        if (this._props.hideCount?.()) return null;
+        const menuTitle = this._props.StartLink ? 'Drag or tap to start link' : 'Tap to complete link';
         const buttonTitle = 'Tap to view links; double tap to open link collection';
-        const title = this.props.ShowCount ? buttonTitle : menuTitle;
+        const title = this._props.ShowCount ? buttonTitle : menuTitle;
 
         //render circular tooltip if it isn't set to invisible and show the number of doc links the node has, and render inner-menu link button for starting/stopping links if currently in menu
-        return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? null : (
+        return !Array.from(this.filteredLinks).length && !this._props.AlwaysOn ? null : (
             <div
                 className="documentLinksButton-wrapper"
                 style={{
-                    position: this.props.InMenu ? 'relative' : 'absolute',
+                    position: this._props.InMenu ? 'relative' : 'absolute',
                     top: 0,
                     pointerEvents: 'none',
                 }}>
-                {DocumentLinksButton.LinkEditorDocView ? this.linkButtonInner : <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>}
+                {DocButtonState.Instance.LinkEditorDocView ? this.linkButtonInner : <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2

