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.

---
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 109 ++++++++++++---------
 1 file changed, 65 insertions(+), 44 deletions(-)

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

diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 624f28413..8e7a6914f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed, observable, makeObservable, reaction, runInAction, override } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc, DocListCast, Opt } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
@@ -6,7 +6,7 @@ import { listSpec } from '../../../fields/Schema';
 import { ComputedField } from '../../../fields/ScriptField';
 import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { numberRange, OmitKeys } from '../../../Utils';
+import { copyProps, numberRange, OmitKeys } from '../../../Utils';
 import { DocumentManager } from '../../util/DocumentManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
@@ -37,6 +37,13 @@ export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentView
 }
 @observer
 export class CollectionFreeFormDocumentViewWrapper extends DocComponent<CollectionFreeFormDocumentViewWrapperProps & { fieldKey: string }>() implements CollectionFreeFormDocumentViewProps {
+    _prevProps: React.PropsWithChildren<CollectionFreeFormDocumentViewWrapperProps & { fieldKey: string }>;
+    @override _props: React.PropsWithChildren<CollectionFreeFormDocumentViewWrapperProps & { fieldKey: string }>;
+    constructor(props: React.PropsWithChildren<CollectionFreeFormDocumentViewWrapperProps & { fieldKey: string }>) {
+        super(props);
+        this._props = this._prevProps = props;
+        makeObservable(this);
+    }
     @observable X = this.props.x;
     @observable Y = this.props.y;
     @observable Z = this.props.z;
@@ -64,11 +71,11 @@ export class CollectionFreeFormDocumentViewWrapper extends DocComponent<Collecti
     w_X = ()               => this.X; // prettier-ignore
     w_Y = ()               => this.Y; // prettier-ignore
     w_Z = ()               => this.Z; // prettier-ignore
-    w_ZIndex = ()          => this.ZIndex ?? NumCast(this.props.Document.zIndex); // prettier-ignore
-    w_Rotation = ()        => this.Rotation ?? NumCast(this.props.Document._rotation); // prettier-ignore
+    w_ZIndex = ()          => this.ZIndex ?? NumCast(this.Document.zIndex); // prettier-ignore
+    w_Rotation = ()        => this.Rotation ?? NumCast(this.Document._rotation); // prettier-ignore
     w_Opacity = ()         => this.Opacity; // prettier-ignore
-    w_BackgroundColor = () => this.BackgroundColor ?? Cast(this.props.Document._backgroundColor, 'string', null); // prettier-ignore
-    w_Color = ()           => this.Color ?? Cast(this.props.Document._color, 'string', null); // prettier-ignore
+    w_BackgroundColor = () => this.BackgroundColor ?? Cast(this.Document._backgroundColor, 'string', null); // prettier-ignore
+    w_Color = ()           => this.Color ?? Cast(this.Document._color, 'string', null); // prettier-ignore
     w_Highlight = ()       => this.Highlight; // prettier-ignore
     w_Width = ()           => this.Width; // prettier-ignore
     w_Height = ()          => this.Height; // prettier-ignore
@@ -76,17 +83,18 @@ export class CollectionFreeFormDocumentViewWrapper extends DocComponent<Collecti
     w_Transition = ()      => this.Transition; // prettier-ignore
     w_DataTransition = ()  => this.DataTransition; // prettier-ignore
 
-    PanelWidth = ()        => this.props.autoDim ? this.props.PanelWidth?.() : this.Width; // prettier-ignore
-    PanelHeight = ()       => this.props.autoDim ? this.props.PanelHeight?.() : this.Height; // prettier-ignore
-    @action
+    PanelWidth = ()        => this._props.autoDim ? this._props.PanelWidth?.() : this.Width; // prettier-ignore
+    PanelHeight = ()       => this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore
+
     componentDidUpdate() {
-        this.WrapperKeys.forEach(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower]));
+        copyProps(this);
+        this.WrapperKeys.forEach(action(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower])));
     }
     render() {
         const layoutProps = this.WrapperKeys.reduce((val, keys) => [(val['w_' + keys.upper] = (this as any)['w_' + keys.upper]), val][1], {} as { [key: string]: Function });
         return (
             <CollectionFreeFormDocumentView
-                {...OmitKeys(this.props, this.WrapperKeys.map(keys => keys.lower) ).omit} // prettier-ignore
+                {...OmitKeys(this._props, this.WrapperKeys.map(keys => keys.lower) ).omit} // prettier-ignore
                 {...layoutProps}
                 PanelWidth={this.PanelWidth}
                 PanelHeight={this.PanelHeight}
@@ -115,7 +123,7 @@ export interface CollectionFreeFormDocumentViewProps {
 }
 
 @observer
-export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps & DocumentViewProps & { fieldKey: string }>() {
+export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps & DocumentViewProps>() {
     get displayName() { // this makes mobx trace() statements more descriptive
         return 'CollectionFreeFormDocumentView(' + this.Document.title + ')';
     } // prettier-ignore
@@ -135,33 +143,46 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     public static animStringFields = ['backgroundColor', 'color', 'fillColor']; // fields that are configured to be animatable using animation frames
     public static animDataFields = (doc: Doc) => (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames
 
+    _props: React.PropsWithChildren<CollectionFreeFormDocumentViewProps & DocumentViewProps>;
+    constructor(props: React.PropsWithChildren<CollectionFreeFormDocumentViewProps & DocumentViewProps>) {
+        super(props);
+        this._props = Object.assign({}, props);
+        makeObservable(this);
+    }
+
     get CollectionFreeFormView() {
-        return this.props.CollectionFreeFormView;
+        return this._props.CollectionFreeFormView;
     }
 
     styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
         if (doc === this.layoutDoc) {
             switch (property) {
-                case StyleProp.Opacity:         return this.props.w_Opacity(); // only change the opacity for this specific document, not its children
-                case StyleProp.BackgroundColor: return this.props.w_BackgroundColor();
-                case StyleProp.Color:           return this.props.w_Color();
+                case StyleProp.Opacity:         return this._props.w_Opacity(); // only change the opacity for this specific document, not its children
+                case StyleProp.BackgroundColor: return this._props.w_BackgroundColor();
+                case StyleProp.Color:           return this._props.w_Color();
             } // prettier-ignore
         }
-        return this.props.styleProvider?.(doc, props, property);
+        return this._props.styleProvider?.(doc, props, property);
     };
 
     public static getValues(doc: Doc, time: number, fillIn: boolean = true) {
-        return CollectionFreeFormDocumentView.animFields.reduce((p, val) => {
-            p[val.key] = Cast(doc[`${val.key}_indexed`], listSpec('number'), fillIn ? [NumCast(doc[val.key], val.val)] : []).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number);
-            return p;
-        }, {} as { [val: string]: Opt<number> });
+        return CollectionFreeFormDocumentView.animFields.reduce(
+            (p, val) => {
+                p[val.key] = Cast(doc[`${val.key}_indexed`], listSpec('number'), fillIn ? [NumCast(doc[val.key], val.val)] : []).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number);
+                return p;
+            },
+            {} as { [val: string]: Opt<number> }
+        );
     }
 
     public static getStringValues(doc: Doc, time: number) {
-        return CollectionFreeFormDocumentView.animStringFields.reduce((p, val) => {
-            p[val] = Cast(doc[`${val}_indexed`], listSpec('string'), [StrCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as string);
-            return p;
-        }, {} as { [val: string]: Opt<string> });
+        return CollectionFreeFormDocumentView.animStringFields.reduce(
+            (p, val) => {
+                p[val] = Cast(doc[`${val}_indexed`], listSpec('string'), [StrCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as string);
+                return p;
+            },
+            {} as { [val: string]: Opt<string> }
+        );
     }
 
     public static setStringValues(time: number, d: Doc, vals: { [val: string]: Opt<string> }) {
@@ -213,7 +234,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
 
     @action public float = () => {
         const topDoc = this.Document;
-        const containerDocView = this.props.docViewPath().lastElement();
+        const containerDocView = this._props.docViewPath().lastElement();
         const screenXf = containerDocView?.screenToLocalTransform();
         if (screenXf) {
             SelectionManager.DeselectAll();
@@ -222,8 +243,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                 topDoc.z = 0;
                 topDoc.x = spt[0];
                 topDoc.y = spt[1];
-                this.props.removeDocument?.(topDoc);
-                this.props.addDocTab(topDoc, OpenWhere.inParentFromScreen);
+                this._props.removeDocument?.(topDoc);
+                this._props.addDocTab(topDoc, OpenWhere.inParentFromScreen);
             } else {
                 const spt = this.screenToLocalTransform().inverse().transformPoint(0, 0);
                 const fpt = screenXf.transformPoint(spt[0], spt[1]);
@@ -236,15 +257,15 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     };
 
     nudge = (x: number, y: number) => {
-        const [locX, locY] = this.props.ScreenToLocalTransform().transformDirection(x, y);
-        this.props.Document.x = this.props.w_X() + locX;
-        this.props.Document.y = this.props.w_Y() + locY;
+        const [locX, locY] = this._props.ScreenToLocalTransform().transformDirection(x, y);
+        this._props.Document.x = this._props.w_X() + locX;
+        this._props.Document.y = this._props.w_Y() + locY;
     };
     screenToLocalTransform = () =>
-        this.props
+        this._props
             .ScreenToLocalTransform()
-            .translate(-this.props.w_X(), -this.props.w_Y())
-            .rotateDeg(-(this.props.w_Rotation?.() || 0));
+            .translate(-this._props.w_X(), -this._props.w_Y())
+            .rotateDeg(-(this._props.w_Rotation?.() || 0));
     returnThis = () => this;
 
     /// this indicates whether the doc view is activated because of its relationshop to a group
@@ -255,25 +276,25 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     isGroupActive = () => {
         if (this.CollectionFreeFormView.isAnyChildContentActive()) return undefined;
         const isGroup = this.dataDoc.isGroup && (!this.layoutDoc.backgroundColor || this.layoutDoc.backgroundColor === 'transparent');
-        return isGroup ? (this.props.isDocumentActive?.() ? 'group' : this.props.isGroupActive?.() ? 'child' : 'inactive') : this.props.isGroupActive?.() ? 'child' : undefined;
+        return isGroup ? (this._props.isDocumentActive?.() ? 'group' : this._props.isGroupActive?.() ? 'child' : 'inactive') : this._props.isGroupActive?.() ? 'child' : undefined;
     };
     public static CollectionFreeFormDocViewClassName = 'collectionFreeFormDocumentView-container';
     render() {
         TraceMobx();
-        const passOnProps = OmitKeys(this.props, Object.keys(this.props).filter(key => key.startsWith('w_'))).omit; // prettier-ignore
+        const passOnProps = OmitKeys(this._props, Object.keys(this._props).filter(key => key.startsWith('w_'))).omit; // prettier-ignore
         return (
             <div
                 className={CollectionFreeFormDocumentView.CollectionFreeFormDocViewClassName}
                 style={{
-                    width: this.props.PanelWidth(),
-                    height: this.props.PanelHeight(),
-                    transform: `translate(${this.props.w_X()}px, ${this.props.w_Y()}px) rotate(${NumCast(this.props.w_Rotation?.())}deg)`,
-                    transition: this.props.w_Transition?.() ?? (this.props.w_DataTransition?.() || this.props.w_Transition?.()),
-                    zIndex: this.props.w_ZIndex?.(),
-                    display: this.props.w_Width?.() ? undefined : 'none',
+                    width: this._props.PanelWidth(),
+                    height: this._props.PanelHeight(),
+                    transform: `translate(${this._props.w_X()}px, ${this._props.w_Y()}px) rotate(${NumCast(this._props.w_Rotation?.())}deg)`,
+                    transition: this._props.w_Transition?.() ?? (this._props.w_DataTransition?.() || this._props.w_Transition?.()),
+                    zIndex: this._props.w_ZIndex?.(),
+                    display: this._props.w_Width?.() ? undefined : 'none',
                 }}>
-                {this.props.RenderCutoffProvider(this.props.Document) ? (
-                    <div style={{ position: 'absolute', width: this.props.PanelWidth(), height: this.props.PanelHeight(), background: 'lightGreen' }} />
+                {this._props.RenderCutoffProvider(this._props.Document) ? (
+                    <div style={{ position: 'absolute', width: this._props.PanelWidth(), height: this._props.PanelHeight(), background: 'lightGreen' }} />
                 ) : (
                     <DocumentView {...passOnProps} CollectionFreeFormDocumentView={this.returnThis} styleProvider={this.styleProvider} ScreenToLocalTransform={this.screenToLocalTransform} isGroupActive={this.isGroupActive} />
                 )}
-- 
cgit v1.2.3-70-g09d2

