From 98567999b9882ed093bb0d750504a1bd10aa9a94 Mon Sep 17 00:00:00 2001
From: Aubrey Li <Aubrey-Li>
Date: Tue, 12 Apr 2022 19:21:53 -0400
Subject: revert presbox & treeview onclick focus

---
 src/client/views/collections/TreeView.tsx | 94 +++++++++++++++++++++++++++++--
 1 file changed, 90 insertions(+), 4 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index ff5c4bab1..751ae631b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1,5 +1,5 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { DataSym, Doc, DocListCast, DocListCastOrNull, Field, HeightSym, Opt, WidthSym, StrListCast } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
@@ -13,7 +13,7 @@ import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString
 import { Docs, DocUtils } from '../../documents/Documents';
 import { DocumentType } from "../../documents/DocumentTypes";
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
-import { DocumentManager } from '../../util/DocumentManager';
+import { DocumentManager, DocFocusOrOpen } from '../../util/DocumentManager';
 import { DragManager, dropActionType } from "../../util/DragManager";
 import { SelectionManager } from '../../util/SelectionManager';
 import { SnappingManager } from '../../util/SnappingManager';
@@ -31,6 +31,8 @@ import { CollectionTreeView } from './CollectionTreeView';
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TreeView.scss";
 import React = require("react");
+import { PresMovement } from '../nodes/trails/PresEnums';
+import { PresBox } from '../nodes/trails';
 
 export interface TreeViewProps {
     treeView: CollectionTreeView;
@@ -112,13 +114,24 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get dataDoc() { return this.doc[DataSym]; }
     @computed get layoutDoc() { return Doc.Layout(this.doc); }
     @computed get fieldKey() { return Doc.LayoutFieldKey(this.doc); }
-    @computed get childDocs() { return this.childDocList(this.fieldKey); }
+    // @computed get childDocs() { return this.childDocList(this.fieldKey); }
+    @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); }
     @computed get childLinks() { return this.childDocList("links"); }
     @computed get childAliases() { return this.childDocList("aliases"); }
     @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); }
     @computed get selected() { return SelectionManager.IsSelected(this._docRef); }
     //      SelectionManager.Views().lastElement()?.props.Document === this.props.document; }
 
+    @observable _presTimer!: NodeJS.Timeout;
+    @observable _presKeyEventsActive: boolean = false;
+
+    @observable _selectedArray: ObservableMap = new ObservableMap<Doc, any>();
+    // the selected item's index
+    @computed get itemIndex() { return NumCast(this.doc._itemIndex); }
+    // the item that's active 
+    @computed get activeItem() { return Cast(this.childDocs[NumCast(this.doc._itemIndex)], Doc, null); }
+    @computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); }
+
     childDocList(field: string) {
         const layout = Cast(Doc.LayoutField(this.doc), Doc, null);
         return (this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
@@ -546,7 +559,80 @@ export class TreeView extends React.Component<TreeViewProps> {
         const icons = StrListCast(this.doc.childContextMenuIcons);
         return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     }
-    onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
+
+    // TODO: currently doc focus works, but can't seem to edit title
+    // onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
+    onChildClick = () => {
+        return this.props.onChildClick?.() ?? (ScriptField.MakeFunction(`DocFocusOrOpen(self)`)! || this._editTitleScript?.())
+    }
+
+    //Regular click zoom to document on canvas
+    @action
+    selectElement = async (doc: Doc) => {
+        const context = Cast(doc.context, Doc, null);
+        this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem);
+        if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0);
+        else this.updateCurrentPresentation(context);
+
+        if (this.activeItem.setPosition &&
+            this.activeItem.y !== undefined &&
+            this.activeItem.x !== undefined &&
+            this.targetDoc.x !== undefined &&
+            this.targetDoc.y !== undefined) {
+            const timer = (ms: number) => new Promise(res => this._presTimer = setTimeout(res, ms));
+            const time = 10;
+            const ydiff = NumCast(this.activeItem.y) - NumCast(this.targetDoc.y);
+            const xdiff = NumCast(this.activeItem.x) - NumCast(this.targetDoc.x);
+
+            for (let i = 0; i < time; i++) {
+                this.targetDoc.x = NumCast(this.targetDoc.x) + xdiff / time;
+                this.targetDoc.y = NumCast(this.targetDoc.y) + ydiff / time;
+                await timer(0.1);
+            }
+        }
+    }
+
+    static keyEventsWrapper = (e: KeyboardEvent) => {
+        PresBox.Instance.keyEvents(e);
+    }
+
+    @action
+    updateCurrentPresentation = (pres?: Doc) => {
+        if (pres) Doc.UserDoc().activePresentation = pres;
+        else Doc.UserDoc().activePresentation = this.doc;
+        document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+        document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
+        this._presKeyEventsActive = true;
+        // PresBox.Instance = this;
+    }
+
+    //The function that is called when a document is clicked or reached through next or back.
+    //it'll also execute the necessary actions if presentation is playing.
+    public gotoDocument = action((index: number, from?: Doc, group?: boolean) => {
+        Doc.UnBrushAllDocs();
+        if (index >= 0 && index < this.childDocs.length) {
+            this.doc._itemIndex = index;
+            const activeItem: Doc = this.activeItem;
+            const targetDoc: Doc = this.targetDoc;
+
+            if (targetDoc) {
+                targetDoc && runInAction(() => {
+                    if (activeItem.presMovement === PresMovement.Jump) targetDoc.focusSpeed = 0;
+                    else targetDoc.focusSpeed = activeItem.presTransition ? activeItem.presTransition : 500;
+                });
+                setTimeout(() => targetDoc.focusSpeed = 500, this.activeItem.presTransition ? NumCast(this.activeItem.presTransition) + 10 : 510);
+            }
+            if (targetDoc?.lastFrame !== undefined) {
+                targetDoc._currentFrame = 0;
+            }
+            if (!group) this._selectedArray.clear();
+            this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //TODO: needs more work on selected arrayUpdate selected array
+            // if (this.layoutDoc._viewType === "stacking" && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
+            // this.onHideDocument(); //Handles hide after/before
+        }
+    });
+
+
 
     onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
 
-- 
cgit v1.2.3-70-g09d2


From 5d9487362545d451b80240a894e84bedd68d2e15 Mon Sep 17 00:00:00 2001
From: Aubrey-Li <aubreylys@hotmail.com>
Date: Wed, 27 Apr 2022 00:35:39 -0400
Subject: tree view presentation move to slide

---
 src/client/views/collections/TreeView.tsx | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 12bab3cd1..c0037ff1b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -102,7 +102,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     get defaultExpandedView() {
         return this.doc.viewType === CollectionViewType.Docking ? this.fieldKey :
             this.props.treeView.dashboardMode ? this.fieldKey :
-                this.props.treeView.fileSysMode ? (this.doc.isFolder ? this.fieldKey : "aliases") :
+                this.props.treeView.fileSysMode ? (this.doc.isFolder ? this.fieldKey : "aliases") : // for displaying 
                     this.props.treeView.outlineMode || this.childDocs ? this.fieldKey : Doc.UserDoc().noviceMode ? "layout" : StrCast(this.props.treeView.doc.treeViewExpandedView, "fields");
     }
 
@@ -811,6 +811,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             fitContentsToDoc={returnTrue}
             hideDecorationTitle={this.props.treeView.outlineMode}
             hideResizeHandles={this.props.treeView.outlineMode}
+            onClick={this.onChildClick}
             focus={this.refocus}
             ContentScaling={returnOne}
             hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
@@ -879,7 +880,8 @@ export class TreeView extends React.Component<TreeViewProps> {
                 ref={this.createTreeDropTarget}
                 onDrop={this.onTreeDrop}
                 //onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
-                onKeyDown={this.onKeyDown}>
+                onKeyDown={this.onKeyDown}
+            >
                 <li className="collection-child">
                     {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader ? // should test for prop 'treeViewRenderDocWithBulletAsHeader"
                         this.renderEmbeddedDocument(false, returnFalse) :
-- 
cgit v1.2.3-70-g09d2


From 314ed039ea4d5128c84de8ec1f06c1ccb0d0e3ec Mon Sep 17 00:00:00 2001
From: Aubrey-Li <aubreylys@hotmail.com>
Date: Mon, 2 May 2022 20:29:48 -0400
Subject: PresBox indexing rework

---
 .../views/collections/CollectionTreeView.tsx       | 10 +++-
 src/client/views/collections/CollectionView.tsx    |  4 ++
 src/client/views/collections/TreeView.tsx          | 35 ++++++++++++--
 src/client/views/nodes/trails/PresBox.tsx          | 54 ++++++++++++++++++----
 tsconfig.json                                      |  1 +
 5 files changed, 92 insertions(+), 12 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 41970eb96..5dafb08c0 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -37,6 +37,10 @@ export type collectionTreeViewProps = {
     treeViewSkipFields?: string[]; // prevents specific fields from being displayed (see LinkBox)
     onCheckedClick?: () => ScriptField;
     onChildClick?: () => ScriptField;
+    // TODO: [AL] add these fields
+    AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+    RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+    hierarchyIndex?: number[];
 };
 
 @observer
@@ -250,7 +254,11 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             this.props.dontRegisterView || Cast(this.props.Document.childDontRegisterViews, "boolean", null),
             this.observeHeight,
             this.unobserveHeight,
-            this.childContextMenuItems()
+            this.childContextMenuItems(),
+            //TODO: [AL] add these
+            this.props.AddToMap,
+            this.props.RemFromMap,
+            this.props.hierarchyIndex,
         );
     }
     @computed get titleBar() {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index ee2c28b5f..07bd3957c 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -79,6 +79,10 @@ export interface CollectionViewProps extends FieldViewProps {
     childIgnoreNativeSize?: boolean;
     childClickScript?: ScriptField;
     childDoubleClickScript?: ScriptField;
+    //TODO: [AL] add these fields
+    AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+    RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+    hierarchyIndex?: number[];
 }
 @observer
 export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & CollectionViewProps>() {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index c0037ff1b..304d68a20 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -63,6 +63,10 @@ export interface TreeViewProps {
     onChildClick?: () => ScriptField;
     skipFields?: string[];
     firstLevel: boolean;
+    // TODO: [AL] add these
+    AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+    RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+    hierarchyIndex?: number[];
 }
 
 const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("px", "")); };
@@ -190,6 +194,13 @@ export class TreeView extends React.Component<TreeViewProps> {
         this._treeEle && this.props.unobserveHeight(this._treeEle);
         document.removeEventListener("pointermove", this.onDragMove, true);
         document.removeEventListener("pointermove", this.onDragUp, true);
+        // TODO: [AL] add these
+        this.props.RemFromMap?.(this.doc, this.props.hierarchyIndex!);
+    }
+
+    componentDidMount() {
+        // TODO: [AL] add these
+        this.props.AddToMap?.(this.doc, this.props.hierarchyIndex!);
     }
 
     onDragUp = (e: PointerEvent) => {
@@ -356,7 +367,12 @@ export class TreeView extends React.Component<TreeViewProps> {
                     this.props.dropAction, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform, this.props.isContentActive,
                     this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields,
                     [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged,
-                    this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems());
+                    this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems(),
+                    // TODO: [AL] Add these
+                    this.props.AddToMap,
+                    this.props.RemFromMap,
+                    this.props.hierarchyIndex
+                );
             } else {
                 contentElement = <EditableView key="editableView"
                     contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
@@ -444,7 +460,12 @@ export class TreeView extends React.Component<TreeViewProps> {
                         StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform,
                         this.props.isContentActive, this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields,
                         [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged,
-                        this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems())}
+                        this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems(),
+                        // TODO: [AL] add these
+                        this.props.AddToMap,
+                        this.props.RemFromMap,
+                        this.props.hierarchyIndex,
+                    )}
             </ul >;
         } else if (this.treeViewExpandedView === "fields") {
             return <ul key={this.doc[Id] + this.doc.title}>
@@ -946,7 +967,11 @@ export class TreeView extends React.Component<TreeViewProps> {
         dontRegisterView: boolean | undefined,
         observerHeight: (ref: any) => void,
         unobserveHeight: (ref: any) => void,
-        contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string, icon: string }[])
+        contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string, icon: string }[]),
+        // TODO: [AL] add these
+        AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[],
+        RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[],
+        hierarchyIndex?: number[],
     ) {
         const viewSpecScript = Cast(containerCollection.viewSpecScript, ScriptField);
         if (viewSpecScript) {
@@ -987,6 +1012,10 @@ export class TreeView extends React.Component<TreeViewProps> {
                 dataDoc={pair.data}
                 containerCollection={containerCollection}
                 prevSibling={docs[i]}
+                // TODO: [AL] add these
+                hierarchyIndex={[...hierarchyIndex!, i]}
+                AddToMap={AddToMap}
+                RemFromMap={RemFromMap}
                 treeView={treeView}
                 indentDocument={indent}
                 outdentDocument={outdent}
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 4fa52565e..60d54c433 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -98,7 +98,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @observable private openMovementDropdown: boolean = false;
     @observable private openEffectDropdown: boolean = false;
     @observable private presentTools: boolean = false;
-    @computed get childDocs() { return DocListCast(this.rootDoc[this.fieldKey]); }
+    // @computed get childDocs() { return DocListCast(this.rootDoc[this.fieldKey]); }
+    // TODO: [AL] add childDocs() and treeMap fields
+    // @computed get childDocs() { return DocListCast(this.rootDoc.presentationaLinearizedDocuments); }
+    //_treeViewMap:Map<number[], Doc>
+    @computed get childDocs() { return DocListCast(this.rootDoc.presentationLinearizedDocuments); }
+    @observable _treeViewMap: Map<string, Doc> = new Map<string, Doc>();
+
     @computed get tagDocs() {
         const tagDocs: Doc[] = [];
         for (const doc of this.childDocs) {
@@ -134,6 +140,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 { field: "string", data: Doc.name, container: Doc.name });
         }
         this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox
+        //TODO: [AL] change this
+        this.props.Document.presentationLinearizedDocuments = new List<Doc>();
     }
     @computed get selectedDocumentView() {
         if (SelectionManager.Views().length) return SelectionManager.Views()[0];
@@ -214,6 +222,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
 
     //TODO: al: it seems currently that tempMedia doesn't stop onslidechange after clicking the button; the time the tempmedia stop depends on the start & end time 
+    // TODO: to handle child slides (entering into subtrail and exiting), also the next() and back() functions
     // No more frames in current doc and next slide is defined, therefore move to next slide 
     nextSlide = (activeNext: Doc) => {
         const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null);
@@ -741,7 +750,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     //Regular click
     @action
     selectElement = async (doc: Doc) => {
-        console.log("got here", this.childDocs.indexOf(doc))
+        console.log("child docs are:", doc);
+        console.log("got here", this.childDocs.indexOf(doc));
         const context = Cast(doc.context, Doc, null);
         this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem);
         if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0);
@@ -2416,6 +2426,29 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         PresBox.startMarquee = true;
     }
 
+    AddToMap = (treeViewDoc: Doc, index: number[]): Doc[] => {
+        this._treeViewMap.set(String(index), treeViewDoc);
+        this.props.Document.presentationaLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap)); // this is a flat array of Docs
+        return this.childDocs;
+    }
+
+    RemFromMap = (treeViewDoc: Doc, index: number[]): Doc[] => {
+        this._treeViewMap.delete(String(index))
+        this.props.Document.presentationaLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap));
+        return this.childDocs;
+    }
+
+    // TODO: [AL] implement sort function for an array of numbers (e.g. arr[1,2,4] v arr[1,2,1])
+    sort = (treeViewMap: Map<string, Doc>): Doc[] => {
+        // TODO
+        const sortedMap = [...treeViewMap.entries()].sort();
+        var sortedDocs = [];
+        for (var kv of sortedMap) {
+            sortedDocs.push(kv[1]);
+        }
+        return sortedDocs;
+    }
+
     render() {
         // calling this method for keyEvents
         this.isPres;
@@ -2465,6 +2498,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 dontRegisterView={true}
                                 focus={this.selectElement}
                                 ScreenToLocalTransform={this.getTransform}
+                                // TODO: [AL] implement AddToMap, RemFromMap functions (outside this)
+                                AddToMap={this.AddToMap}
+                                RemFromMap={this.RemFromMap}
+                                hierarchyIndex={[]}
                             /> : (null)
                         }
                     </div>
@@ -2480,11 +2517,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             </div>;
     }
 }
-ScriptingGlobals.add(function lookupPresBoxField(container: Doc, field: string, data: Doc) {
-    if (field === 'indexInPres') return DocListCast(container[StrCast(container.presentationFieldKey)]).indexOf(data);
-    if (field === 'presCollapsedHeight') return [CollectionViewType.Tree || CollectionViewType.Stacking].includes(container._viewType as any) ? 35 : 31;
-    if (field === 'presStatus') return container.presStatus;
-    if (field === '_itemIndex') return container._itemIndex;
-    if (field === 'presBox') return container;
+// this func communicates with PresBoxElement to send information of the doc
+ScriptingGlobals.add(function lookupPresBoxField(presBoxDoc: Doc, field: string, presEleDoc: Doc) {
+    if (field === 'indexInPres') return DocListCast(presBoxDoc.presentationLinearizedDocuments).indexOf(presEleDoc);
+    if (field === 'presCollapsedHeight') return [CollectionViewType.Tree || CollectionViewType.Stacking].includes(presBoxDoc._viewType as any) ? 35 : 31;
+    if (field === 'presStatus') return presBoxDoc.presStatus;
+    if (field === '_itemIndex') return presBoxDoc._itemIndex;
+    if (field === 'presBox') return presBoxDoc;
     return undefined;
 });
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index f688f18ea..993ab13b9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,7 @@
 {
     "compilerOptions": {
         "target": "es5",
+        "downlevelIteration": true,
         // "module": "system",
         "removeComments": true,
         "experimentalDecorators": true,
-- 
cgit v1.2.3-70-g09d2


From ca26b43095622d07ae81fc08d4037be38d9a8b28 Mon Sep 17 00:00:00 2001
From: Aubrey-Li <aubreylys@hotmail.com>
Date: Tue, 3 May 2022 18:10:55 -0400
Subject: implement child slide sorting

---
 src/client/views/collections/TreeView.tsx |  2 +-
 src/client/views/nodes/trails/PresBox.tsx | 27 ++++++++++++++++++++-------
 2 files changed, 21 insertions(+), 8 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 304d68a20..f9497eb4a 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1013,7 +1013,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 containerCollection={containerCollection}
                 prevSibling={docs[i]}
                 // TODO: [AL] add these
-                hierarchyIndex={[...hierarchyIndex!, i]}
+                hierarchyIndex={[...hierarchyIndex!, i + 1]}
                 AddToMap={AddToMap}
                 RemFromMap={RemFromMap}
                 treeView={treeView}
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 60d54c433..cfc7b0416 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -103,7 +103,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     // @computed get childDocs() { return DocListCast(this.rootDoc.presentationaLinearizedDocuments); }
     //_treeViewMap:Map<number[], Doc>
     @computed get childDocs() { return DocListCast(this.rootDoc.presentationLinearizedDocuments); }
-    @observable _treeViewMap: Map<string, Doc> = new Map<string, Doc>();
+    @observable _treeViewMap: Map<number, Doc> = new Map<number, Doc>();
 
     @computed get tagDocs() {
         const tagDocs: Doc[] = [];
@@ -750,7 +750,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     //Regular click
     @action
     selectElement = async (doc: Doc) => {
-        console.log("child docs are:", doc);
+        console.log("tree docs are:", this._treeViewMap);
+        console.log("child docs are:", this.childDocs);
+        console.log("linearized docs:", this.rootDoc.presentationLinearizedDocuments);
         console.log("got here", this.childDocs.indexOf(doc));
         const context = Cast(doc.context, Doc, null);
         this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem);
@@ -2427,19 +2429,30 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
 
     AddToMap = (treeViewDoc: Doc, index: number[]): Doc[] => {
-        this._treeViewMap.set(String(index), treeViewDoc);
-        this.props.Document.presentationaLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap)); // this is a flat array of Docs
+        var indexNum = 0;
+        for (let i = 0; i < index.length; i++) {
+            indexNum += (index[i] * (10 ** (-i)));
+        }
+        this._treeViewMap.set(indexNum, treeViewDoc);
+        console.log(String(index), treeViewDoc)
+        this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap)); // this is a flat array of Docs
+        console.log(this.props.Document.presentationLinearizedDocuments)
         return this.childDocs;
     }
 
     RemFromMap = (treeViewDoc: Doc, index: number[]): Doc[] => {
-        this._treeViewMap.delete(String(index))
-        this.props.Document.presentationaLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap));
+        var indexNum = 0;
+        for (let i = 0; i < index.length; i++) {
+            indexNum += (index[i] * (10 ** (-i)));
+        }
+        console.log(String(index), treeViewDoc)
+        this._treeViewMap.delete(indexNum)
+        this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap));
         return this.childDocs;
     }
 
     // TODO: [AL] implement sort function for an array of numbers (e.g. arr[1,2,4] v arr[1,2,1])
-    sort = (treeViewMap: Map<string, Doc>): Doc[] => {
+    sort = (treeViewMap: Map<number, Doc>): Doc[] => {
         // TODO
         const sortedMap = [...treeViewMap.entries()].sort();
         var sortedDocs = [];
-- 
cgit v1.2.3-70-g09d2


From 31b2606fa6ac49b0a78e46fcedff05fd2e2366b7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 3 Jun 2022 09:49:15 -0400
Subject: fixed tree view crash

---
 src/client/views/collections/CollectionView.tsx | 2 +-
 src/client/views/collections/TreeView.tsx       | 9 +++++----
 2 files changed, 6 insertions(+), 5 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 0de61c9b2..965f0a352 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -82,7 +82,7 @@ export interface CollectionViewProps extends FieldViewProps {
     //TODO: [AL] add these fields
     AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
     RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
-    hierarchyIndex?: number[];
+    hierarchyIndex?: number[]; // hierarchical index of a document up to the rendering root (primarily used for tree views) 
 }
 @observer
 export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & CollectionViewProps>() {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 3840afb04..661db7997 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -213,12 +213,12 @@ export class TreeView extends React.Component<TreeViewProps> {
         document.removeEventListener("pointermove", this.onDragMove, true);
         document.removeEventListener("pointermove", this.onDragUp, true);
         // TODO: [AL] add these
-        this.props.RemFromMap?.(this.doc, this.props.hierarchyIndex!);
+        this.props.hierarchyIndex !== undefined && this.props.RemFromMap?.(this.doc, this.props.hierarchyIndex);
     }
 
     componentDidMount() {
         // TODO: [AL] add these
-        this.props.AddToMap?.(this.doc, this.props.hierarchyIndex!);
+        this.props.hierarchyIndex !== undefined && this.props.AddToMap?.(this.doc, this.props.hierarchyIndex);
     }
 
     onDragUp = (e: PointerEvent) => {
@@ -293,7 +293,8 @@ export class TreeView extends React.Component<TreeViewProps> {
     @undoBatch
     treeDrop = (e: Event, de: DragManager.DropEvent) => {
         const pt = [de.x, de.y];
-        const rect = this._header.current!.getBoundingClientRect();
+        if (!this._header.current) return;
+        const rect = this._header.current.getBoundingClientRect();
         const before = pt[1] < rect.top + rect.height / 2;
         const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
         if (de.complete.linkDragData) {
@@ -978,7 +979,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 containerCollection={containerCollection}
                 prevSibling={docs[i]}
                 // TODO: [AL] add these
-                hierarchyIndex={[...hierarchyIndex!, i + 1]}
+                hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined}
                 AddToMap={AddToMap}
                 RemFromMap={RemFromMap}
                 treeView={treeView}
-- 
cgit v1.2.3-70-g09d2


From ba7824a91da113cc813c58b678719092c96d79a2 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 3 Jun 2022 16:02:24 -0400
Subject: fixed opening closed tabs from Files sidebar to re-use best Alias
 before making a new alias.

---
 src/.DS_Store                                      | Bin 8196 -> 8196 bytes
 src/client/util/CurrentUserUtils.ts                |   2 +-
 src/client/util/DocumentManager.ts                 |  28 ++++++++++-----------
 src/client/views/LightboxView.tsx                  |   5 ++--
 src/client/views/collections/TabDocView.tsx        |  15 ++++++++++-
 src/client/views/collections/TreeView.tsx          |   4 +--
 src/client/views/nodes/DocumentIcon.tsx            |   4 +--
 src/client/views/nodes/DocumentView.tsx            |   4 ---
 src/client/views/nodes/button/FontIconBox.tsx      |  11 ++++----
 .../views/nodes/formattedText/DashFieldView.tsx    |   6 ++---
 .../views/nodes/formattedText/FormattedTextBox.tsx |   2 +-
 src/client/views/nodes/trails/PresBox.tsx          |  14 ++---------
 src/client/views/pdf/PDFViewer.tsx                 |   2 +-
 13 files changed, 48 insertions(+), 49 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/.DS_Store b/src/.DS_Store
index b0987293b..4bf9cdac7 100644
Binary files a/src/.DS_Store and b/src/.DS_Store differ
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 2ed6c3cbe..85ad58726 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -869,7 +869,7 @@ export class CurrentUserUtils {
                             Doc.AddDocToList(menuBtnDoc, "data", newSubMenuBtnDoc, after, false, !prevSub);
                         }
                         prevSub = params.title;
-                    })
+                    });
                 }
                 prev = params.title;
             });
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index aeddc3249..a82f99d5a 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -16,7 +16,7 @@ import { SelectionManager } from './SelectionManager';
 export class DocumentManager {
 
     //global holds all of the nodes (regardless of which collection they're in)
-    @observable public DocumentViews: DocumentView[] = [];
+    @observable public DocumentViews = new Set<DocumentView>();
     @observable public LinkAnchorBoxViews: DocumentView[] = [];
     @observable public RecordingEvent = 0;
     @observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = [];
@@ -46,7 +46,7 @@ export class DocumentManager {
             // this.LinkedDocumentViews.forEach(view => console.log("  LV = " + view.a.props.Document.title + "/" + view.a.props.LayoutTemplateString + " --> " +
             //     view.b.props.Document.title + "/" + view.b.props.LayoutTemplateString));
         } else {
-            this.DocumentViews.push(view);
+            this.DocumentViews.add(view);
         }
     }
     public RemoveView = action((view: DocumentView) => {
@@ -61,8 +61,7 @@ export class DocumentManager {
             const index = this.LinkAnchorBoxViews.indexOf(view);
             this.LinkAnchorBoxViews.splice(index, 1);
         } else {
-            const index = this.DocumentViews.indexOf(view);
-            index !== -1 && this.DocumentViews.splice(index, 1);
+            this.DocumentViews.delete(view);
         }
         SelectionManager.DeselectView(view);
     });
@@ -70,13 +69,13 @@ export class DocumentManager {
     //gets all views
     public getDocumentViewsById(id: string) {
         const toReturn: DocumentView[] = [];
-        DocumentManager.Instance.DocumentViews.map(view => {
+        Array.from(DocumentManager.Instance.DocumentViews).map(view => {
             if (view.rootDoc[Id] === id) {
                 toReturn.push(view);
             }
         });
         if (toReturn.length === 0) {
-            DocumentManager.Instance.DocumentViews.map(view => {
+            Array.from(DocumentManager.Instance.DocumentViews).map(view => {
                 const doc = view.rootDoc.proto;
                 if (doc && doc[Id] && doc[Id] === id) {
                     toReturn.push(view);
@@ -96,14 +95,14 @@ export class DocumentManager {
         const passes = preferredCollection ? [preferredCollection, undefined] : [undefined];
 
         for (const pass of passes) {
-            DocumentManager.Instance.DocumentViews.map(view => {
+            Array.from(DocumentManager.Instance.DocumentViews).map(view => {
                 if (view.rootDoc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) {
                     toReturn = view;
                     return;
                 }
             });
             if (!toReturn) {
-                DocumentManager.Instance.DocumentViews.map(view => {
+                Array.from(DocumentManager.Instance.DocumentViews).map(view => {
                     const doc = view.rootDoc.proto;
                     if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) {
                         toReturn = view;
@@ -122,9 +121,8 @@ export class DocumentManager {
     }
 
     public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
-        const docViews = DocumentManager.Instance.DocumentViews;
         const views: DocumentView[] = [];
-        docViews.map(view => LightboxView.IsLightboxDocView(view.docViewPath) && Doc.AreProtosEqual(view.rootDoc, toFind) && views.push(view));
+        Array.from(DocumentManager.Instance.DocumentViews).map(view => LightboxView.IsLightboxDocView(view.docViewPath) && Doc.AreProtosEqual(view.rootDoc, toFind) && views.push(view));
         return views?.find(view => view.ContentDiv?.getBoundingClientRect().width && view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse) || (views.length ? views[0] : undefined);
     }
     public getFirstDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
@@ -133,8 +131,8 @@ export class DocumentManager {
     }
     public getDocumentViews(toFind: Doc): DocumentView[] {
         const toReturn: DocumentView[] = [];
-        const docViews = DocumentManager.Instance.DocumentViews.filter(view => !LightboxView.IsLightboxDocView(view.docViewPath));
-        const lightViews = DocumentManager.Instance.DocumentViews.filter(view => LightboxView.IsLightboxDocView(view.docViewPath));
+        const docViews = Array.from(DocumentManager.Instance.DocumentViews).filter(view => !LightboxView.IsLightboxDocView(view.docViewPath));
+        const lightViews = Array.from(DocumentManager.Instance.DocumentViews).filter(view => LightboxView.IsLightboxDocView(view.docViewPath));
 
         // heuristic to return the "best" documents first:
         //   choose a document in the lightbox first
@@ -290,7 +288,7 @@ export class DocumentManager {
         }
     }
 }
-export function DocFocusOrOpen(doc: any, collectionDoc?: Doc) {
+export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) {
     const cv = collectionDoc && DocumentManager.Instance.getDocumentView(collectionDoc);
     const dv = DocumentManager.Instance.getDocumentView(doc, (cv?.ComponentView as CollectionFreeFormView)?.props.CollectionView);
     if (dv && Doc.AreProtosEqual(dv.props.Document, doc)) {
@@ -300,7 +298,9 @@ export function DocFocusOrOpen(doc: any, collectionDoc?: Doc) {
     else {
         const context = doc.context !== Doc.UserDoc().myFilesystem && Cast(doc.context, Doc, null);
         const showDoc = context || doc;
-        CollectionDockingView.AddSplit(showDoc === Doc.GetProto(showDoc) ? Doc.MakeAlias(showDoc) : showDoc, "right") && context &&
+        const bestAlias = showDoc === Doc.GetProto(showDoc) ? DocListCast(showDoc.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail) : showDoc;
+
+        CollectionDockingView.AddSplit(bestAlias ? bestAlias : Doc.MakeAlias(showDoc), "right") && context &&
             setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc));
     }
 }
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index ddfc8b249..3d2769f66 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -275,9 +275,8 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                 <div className="lightboxView-tabBtn" title={"open in tab"}
                     onClick={e => {
                         e.stopPropagation();
-                        // CollectionDockingView.AddSplit(LightboxView._docTarget || LightboxView._doc!, "");
-                        LightboxView.openInTabFunc(LightboxView._docTarget || LightboxView._doc!, "inPlace");
-                        console.log("lightbox to tab triggered")
+                        CollectionDockingView.AddSplit(LightboxView._docTarget || LightboxView._doc!, "");
+                        //LightboxView.openInTabFunc(LightboxView._docTarget || LightboxView._doc!, "inPlace");
                         SelectionManager.DeselectAll();
                         LightboxView.SetLightboxDoc(undefined);
                     }}>
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 8d84e9a56..d64cb2fd7 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -66,6 +66,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     get stack() { return (this.props as any).glContainer.parent.parent; }
     get tab() { return (this.props as any).glContainer.tab; }
     get view() { return this._view; }
+    _lastTab: any;
+    _lastView: DocumentView | undefined;
 
     @action
     init = (tab: any, doc: Opt<Doc>) => {
@@ -266,6 +268,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
     componentWillUnmount() {
         this._tabReaction?.();
+        this._view && DocumentManager.Instance.RemoveView(this._view);
         this.tab && CollectionDockingView.Instance.tabMap.delete(this.tab);
 
         this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
@@ -353,7 +356,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
     @computed get docView() {
         return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) :
-            <><DocumentView key={this._document[Id]} ref={action((r: DocumentView) => this._view = r)}
+            <><DocumentView key={this._document[Id]} ref={action((r: DocumentView) => {
+                this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
+                this._view = r;
+                this._lastView = this._view;
+            })}
                 renderDepth={0}
                 Document={this._document}
                 DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
@@ -409,6 +416,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 height: "100%", width: "100%"
             }} ref={ref => {
                 if (this._mainCont = ref) {
+                    if (this._lastTab) {
+                        console.log("DUP tab")
+                        this._view && DocumentManager.Instance.RemoveView(this._view);
+                        CollectionDockingView.Instance.tabMap.delete(this._lastTab);
+                    }
+                    this._lastTab = this.tab;
                     (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
                     DocServer.GetRefField(this.props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document)));
                     new _global.ResizeObserver(action((entries: any) => this._forceInvalidateScreenToLocal++)).observe(ref);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 661db7997..9de44fb00 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -183,7 +183,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             this.treeViewOpen = !this.treeViewOpen;
         } else {
             // choose an appropriate alias or make one. --- choose the first alias that (1) user owns,  (2) has no context field ... otherwise make a new alias
-            const bestAlias = docView.props.Document.author === Doc.CurrentUserEmail ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
+            const bestAlias = docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsPrototype(docView.props.Document) ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
             const nextBestAlias = DocListCast(this.props.document.aliases).find(doc => doc.author === Doc.CurrentUserEmail);
             this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), "lightbox");
         }
@@ -609,7 +609,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     // TODO: currently doc focus works, but can't seem to edit title
     // onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
     onChildClick = () => {
-        return this.props.onChildClick?.() ?? (ScriptField.MakeFunction(`DocFocusOrOpen(self)`)! || this._editTitleScript?.())
+        return this.props.onChildClick?.() ?? (ScriptField.MakeFunction(`DocFocusOrOpen(self)`)! || this._editTitleScript?.());
     }
 
     onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index a9c998757..56de2d1fc 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -52,7 +52,7 @@ export class DocumentIconContainer extends React.Component {
                 };
             },
             getVars() {
-                const docs = DocumentManager.Instance.DocumentViews;
+                const docs = Array.from(DocumentManager.Instance.DocumentViews);
                 const capturedVariables: { [name: string]: Field } = {};
                 usedDocuments.forEach(index => capturedVariables[`d${index}`] = docs[index].props.Document);
                 return { capturedVariables };
@@ -60,6 +60,6 @@ export class DocumentIconContainer extends React.Component {
         };
     }
     render() {
-        return DocumentManager.Instance.DocumentViews.map((dv, i) => <DocumentIcon key={i} index={i} view={dv} />);
+        return Array.from(DocumentManager.Instance.DocumentViews).map((dv, i) => <DocumentIcon key={i} index={i} view={dv} />);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 14ededaf8..6e4d6a52e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -242,7 +242,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); }
     @computed get onPointerUpHandler() { return this.props.onPointerUp?.() ?? ScriptCast(this.Document.onPointerUp); }
 
-
     componentWillUnmount() { this.cleanupHandlers(true); }
     componentDidMount() { this.setupHandlers(); }
     //componentDidUpdate() { this.setupHandlers(); }
@@ -1126,9 +1125,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     render() {
         TraceMobx();
         const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : Doc.DocBrushStatus.unbrushed) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString
-        if (highlightIndex === 6) {
-            console.log("")
-        }
         const highlightColor = ["transparent", "rgb(68, 118, 247)", "rgb(68, 118, 247)", "orange", "lightBlue"][highlightIndex];
         const highlightStyle = ["solid", "dashed", "solid", "solid", "solid"][highlightIndex];
         const excludeTypes = !this.props.treeViewDoc ? [DocumentType.FONTICON, DocumentType.INK] : [DocumentType.FONTICON];
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index d29160458..b21a28d8e 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -231,7 +231,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
 
         const script = ScriptCast(this.rootDoc.script);
-        if (!script) { return null };
+        if (!script) { return null; }
 
         let noviceList: string[] = [];
         let text: string | undefined;
@@ -459,7 +459,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const buttonText = StrCast(this.rootDoc.buttonText);
 
         // TODO:glr Add label of button type
-        let button = this.defaultButton;
+        let button: JSX.Element | null = this.defaultButton;
 
         switch (this.type) {
             case ButtonType.TextButton:
@@ -527,9 +527,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         }
 
         return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button :
-            <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
-                {button}
-            </Tooltip>;
+            button !== null ?
+                <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
+                    {button}
+                </Tooltip > : null
     }
 }
 
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 6a3f9ed00..bb3791f1e 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -86,7 +86,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
     public static fieldContent(textBoxDoc: Doc, dashDoc: Doc, fieldKey: string) {
         const dashVal = dashDoc[fieldKey] ?? dashDoc[DataSym][fieldKey] ?? (fieldKey === "PARAMS" ? textBoxDoc[fieldKey] : "");
         const fval = dashVal instanceof List ? dashVal.join(DashFieldViewInternal.multiValueDelimeter) : StrCast(dashVal).startsWith(":=") || dashVal === "" ? Doc.Layout(textBoxDoc)[fieldKey] : dashVal;
-        return { boolVal: Cast(fval, "boolean", null), strVal: Field.toString(fval as Field) || "" }
+        return { boolVal: Cast(fval, "boolean", null), strVal: Field.toString(fval as Field) || "" };
     }
 
     // set the display of the field's value (checkbox for booleans, span of text for strings)
@@ -241,8 +241,8 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
         const hideMenu = () => {
             this.fadeOut(true);
             document.removeEventListener("pointerdown", hideMenu);
-        }
-        document.addEventListener("pointerdown", hideMenu)
+        };
+        document.addEventListener("pointerdown", hideMenu);
     }
     render() {
         const buttons = [
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ce82821b6..434fccf8d 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1202,7 +1202,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 const tr = this._editorView.state.tr.setStoredMarks(storedMarks).insertText(FormattedTextBox.SelectOnLoadChar, this._editorView.state.doc.content.size - 1, this._editorView.state.doc.content.size).setStoredMarks(storedMarks);
                 this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size))));
             } else if (this._editorView && curText && !FormattedTextBox.DontSelectInitialText) {
-                selectAll(this._editorView.state, this._editorView?.dispatch)
+                selectAll(this._editorView.state, this._editorView?.dispatch);
                 this.startUndoTypingBatch();
             } else if (this._editorView) {
                 this._editorView.dispatch(this._editorView.state.tr.addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })));
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index f4e792acd..0af7715fe 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -2435,9 +2435,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             indexNum += (index[i] * (10 ** (-i)));
         }
         this._treeViewMap.set(indexNum, treeViewDoc);
-        console.log(String(index), treeViewDoc)
         this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap)); // this is a flat array of Docs
-        console.log(this.props.Document.presentationLinearizedDocuments)
         return this.childDocs;
     }
 
@@ -2447,21 +2445,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             indexNum += (index[i] * (10 ** (-i)));
         }
         console.log(String(index), treeViewDoc)
-        this._treeViewMap.delete(indexNum)
+        this._treeViewMap.delete(indexNum);
         this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap));
         return this.childDocs;
     }
 
     // TODO: [AL] implement sort function for an array of numbers (e.g. arr[1,2,4] v arr[1,2,1])
-    sort = (treeViewMap: Map<number, Doc>): Doc[] => {
-        // TODO
-        const sortedMap = [...treeViewMap.entries()].sort();
-        var sortedDocs = [];
-        for (var kv of sortedMap) {
-            sortedDocs.push(kv[1]);
-        }
-        return sortedDocs;
-    }
+    sort = (treeViewMap: Map<number, Doc>) => [...treeViewMap.entries()].sort().map(kv => kv[1]);
 
     render() {
         // calling this method for keyEvents
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 6db36f36a..d5fd425ad 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -154,7 +154,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         if (doc !== this.props.rootDoc && mainCont) {
             const windowHeight = this.props.PanelHeight() / (this.props.scaling?.() || 1);
             const scrollTo = doc.unrendered ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, .1 * windowHeight, NumCast(this.props.Document.scrollHeight));
-            if (scrollTo !== undefined && scrollTo != this.props.layoutDoc._scrollTop) {
+            if (scrollTo !== undefined && scrollTo !== this.props.layoutDoc._scrollTop) {
                 focusSpeed = 500;
 
                 if (!this._pdfViewer) this._initialScroll = scrollTo;
-- 
cgit v1.2.3-70-g09d2


From 9acba91baa0ee2ee43106d344392039a2cbd0e46 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 6 Jun 2022 10:16:13 -0400
Subject: fixed range filtering, filtering by string,

---
 src/client/documents/Documents.ts                  |  5 ++--
 src/client/views/collections/TreeView.tsx          |  2 +-
 src/client/views/nodes/FilterBox.tsx               | 33 ++++++++++++++++++++--
 .../views/nodes/formattedText/FormattedTextBox.tsx |  4 ++-
 4 files changed, 37 insertions(+), 7 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ecacc9fd5..2ca9cdb71 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1048,11 +1048,10 @@ export namespace DocUtils {
                 const key = docRangeFilters[i];
                 const min = Number(docRangeFilters[i + 1]);
                 const max = Number(docRangeFilters[i + 2]);
-                const val = Cast(d[key], "number", null);
-                if (val < min || val > max) return false;
+                const val = typeof d[key] === "string" ? (Number(StrCast(d[key])).toString() === StrCast(d[key]) ? Number(StrCast(d[key])) : undefined) : Cast(d[key], "number", null);
                 if (val === undefined) {
                     //console.log("Should 'undefined' pass range filter or not?")
-                }
+                } else if (val < min || val > max) return false;
             }
             return true;
         });
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 9de44fb00..23b6a7f72 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -499,7 +499,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 </div>
             </ul>;
         }
-        return <ul onPointerDown={e => { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, returnFalse)}</ul>; // "layout"
+        return <ul onPointerDown={e => { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, this.props.treeView.props.childDocumentsActive ?? returnFalse)}</ul>; // "layout"
     }
 
     get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); }
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index a47e17dfc..28834a202 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -206,7 +206,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
             facetValues.strings.map(val => {
                 const num = val ? Number(val) : Number.NaN;
                 if (Number.isNaN(num)) {
-                    nonNumbers++;
+                    num && nonNumbers++;
                 } else {
                     minVal = Math.min(num, minVal);
                     maxVal = Math.max(num, maxVal);
@@ -216,8 +216,9 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (facetHeader === "text" || facetValues.rtFields / allCollectionDocs.length > 0.1) {
                 newFacet = Docs.Create.TextDocument("", {
                     title: facetHeader, system: true, target: targetDoc, _width: 100, _height: 25, _stayInCollection: true,
-                    treeViewExpandedView: "layout", _treeViewOpen: true, _forceActive: true, ignoreClick: true
+                    treeViewExpandedView: "layout", _treeViewOpen: true, _forceActive: true, ignoreClick: true,
                 });
+                Doc.GetProto(newFacet).forceActive = true; // required for FormattedTextBox to be able to gain focus since it will never be 'selected'
                 Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
                 newFacet._textBoxPaddingX = newFacet._textBoxPaddingY = 4;
                 const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`;
@@ -238,6 +239,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 Doc.GetProto(newFacet)[newFacetField + "-maxThumb"] = extendedMaxVal;
                 const scriptText = `setDocRangeFilter(this?.target, "${facetHeader}", range)`;
                 newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" });
+                newFacet.data = ComputedField.MakeFunction(`readNumFacetData(self.target, self, "${FilterBox.targetDocChildKey}", "${facetHeader}")`);
             } else {
                 newFacet = new Doc();
                 newFacet.system = true;
@@ -401,6 +403,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     docFilters={returnEmptyFilter}
                     docRangeFilters={returnEmptyFilter}
                     searchFilterDocs={returnEmptyDoclist}
+                    childDocumentsActive={returnTrue}
                     ContainingCollectionDoc={this.props.ContainingCollectionDoc}
                     ContainingCollectionView={this.props.ContainingCollectionView}
                     PanelWidth={this.props.PanelWidth}
@@ -479,6 +482,32 @@ ScriptingGlobals.add(function determineCheckedState(layoutDoc: Doc, facetHeader:
     }
     return undefined;
 });
+ScriptingGlobals.add(function readNumFacetData(layoutDoc: Doc, facetDoc: Doc, childKey: string, facetHeader: string) {
+    const allCollectionDocs = new Set<Doc>();
+    const activeTabs = DocListCast(layoutDoc[childKey]);
+    SearchBox.foreachRecursiveDoc(activeTabs, (depth: number, doc: Doc) => allCollectionDocs.add(doc));
+    const set = new Set<string>();
+    if (facetHeader === "tags") allCollectionDocs.forEach(child => Field.toString(child[facetHeader] as Field).split(":").forEach(key => set.add(key)));
+    else allCollectionDocs.forEach(child => set.add(Field.toString(child[facetHeader] as Field)));
+    const facetValues = Array.from(set).filter(v => v);
+
+    let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE;
+    facetValues.map(val => {
+        const num = val ? Number(val) : Number.NaN;
+        if (!Number.isNaN(num)) {
+            minVal = Math.min(num, minVal);
+            maxVal = Math.max(num, maxVal);
+        }
+    });
+    const newFacetField = Doc.LayoutFieldKey(facetDoc);
+    const ranged = Doc.readDocRangeFilter(layoutDoc, facetHeader);
+    const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * .1));
+    const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * .05)));
+    facetDoc[newFacetField + "-min"] = ranged === undefined ? extendedMinVal : ranged[0];
+    facetDoc[newFacetField + "-max"] = ranged === undefined ? extendedMaxVal : ranged[1];
+    Doc.GetProto(facetDoc)[newFacetField + "-minThumb"] = extendedMinVal;
+    Doc.GetProto(facetDoc)[newFacetField + "-maxThumb"] = extendedMaxVal;
+})
 ScriptingGlobals.add(function readFacetData(layoutDoc: Doc, childKey: string, facetHeader: string) {
     const allCollectionDocs = new Set<Doc>();
     const activeTabs = DocListCast(layoutDoc[childKey]);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index bf3c01d1f..7a500ac88 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -283,6 +283,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                         this.dataDoc[this.props.fieldKey] = undefined;
                         this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((curProto || curTemp).Data)));
                         this.dataDoc[this.props.fieldKey + "-noTemplate"] = undefined; // mark the data field as not being split from any template it might have
+                        ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText });
                         unchanged = false;
                     }
                     this._applyingChange = "";
@@ -1248,6 +1249,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     onPointerDown = (e: React.PointerEvent): void => {
+        if (this.Document.forceActive) e.stopPropagation();
         this.tryUpdateScrollHeight(); // if a doc a fitwidth doc is being viewed in different context (eg freeform & lightbox), then it will have conflicting heights.  so when the doc is clicked on, we want to make sure it has the appropriate height for the selected view.
         if ((e.target as any).tagName === "AUDIOTAG") {
             e.preventDefault();
@@ -1641,7 +1643,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
     render() {
         TraceMobx();
-        const selected = this.props.isSelected();
+        const selected = this.props.isSelected() || this.Document.forceActive;
         const active = this.props.isContentActive();
         const scale = (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
         const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
-- 
cgit v1.2.3-70-g09d2


From 076dbb1b7a17c077936e0bb291de363277173369 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 6 Jun 2022 18:13:37 -0400
Subject: fixed slide #'ing for TreeView presentations

---
 src/client/views/collections/TreeView.tsx |  5 ++++-
 src/client/views/nodes/trails/PresBox.tsx | 30 +++++++++++++++---------------
 2 files changed, 19 insertions(+), 16 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 23b6a7f72..a85b2a0d4 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -216,8 +216,11 @@ export class TreeView extends React.Component<TreeViewProps> {
         this.props.hierarchyIndex !== undefined && this.props.RemFromMap?.(this.doc, this.props.hierarchyIndex);
     }
 
+    componentDidUpdate() {
+        this.props.hierarchyIndex !== undefined && this.props.AddToMap?.(this.doc, this.props.hierarchyIndex);
+    }
+
     componentDidMount() {
-        // TODO: [AL] add these
         this.props.hierarchyIndex !== undefined && this.props.AddToMap?.(this.doc, this.props.hierarchyIndex);
     }
 
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index dea6b818f..aa89b8b6c 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -103,7 +103,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     // @computed get childDocs() { return DocListCast(this.rootDoc.presentationaLinearizedDocuments); }
     //_treeViewMap:Map<number[], Doc>
     @computed get childDocs() { return this.layoutDoc._viewType === CollectionViewType.Tree ? DocListCast(this.rootDoc.presentationLinearizedDocuments) : DocListCast(this.rootDoc[this.fieldKey]); }
-    @observable _treeViewMap: Map<number, Doc> = new Map<number, Doc>();
+    @observable _treeViewMap: Map<Doc, number> = new Map();
 
     @computed get tagDocs() {
         const tagDocs: Doc[] = [];
@@ -2454,27 +2454,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         for (let i = 0; i < index.length; i++) {
             indexNum += (index[i] * (10 ** (-i)));
         }
-        this._treeViewMap.set(indexNum, treeViewDoc);
-        this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap)); // this is a flat array of Docs
+        if (this._treeViewMap.get(treeViewDoc) !== indexNum) {
+            this._treeViewMap.set(treeViewDoc, indexNum);
+            this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap)); // this is a flat array of Docs
+        }
         return this.childDocs;
     }
 
     RemFromMap = (treeViewDoc: Doc, index: number[]): Doc[] => {
-        var indexNum = 0;
-        for (let i = 0; i < index.length; i++) {
-            indexNum += (index[i] * (10 ** (-i)));
-        }
-        console.log(String(index), treeViewDoc)
-        this._treeViewMap.delete(indexNum);
-        const overlay = (Doc.UserDoc().myOverlayDocs as Doc);
-        if (!DocListCast(overlay[Doc.LayoutFieldKey(overlay)]).includes(this.rootDoc)) {
-            this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap));
-        }
+        this._treeViewMap.delete(treeViewDoc);
+        this.props.Document.presentationLinearizedDocuments = new List<Doc>(this.sort(this._treeViewMap));
         return this.childDocs;
     }
 
     // TODO: [AL] implement sort function for an array of numbers (e.g. arr[1,2,4] v arr[1,2,1])
-    sort = (treeViewMap: Map<number, Doc>) => [...treeViewMap.entries()].sort().map(kv => kv[1]);
+    sort = (treeViewMap: Map<Doc, number>) => [...treeViewMap.entries()].sort((a: [Doc, number], b: [Doc, number]) => a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0).map(kv => kv[0]);
 
     render() {
         // calling this method for keyEvents
@@ -2552,7 +2546,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
 }
 // this func communicates with PresBoxElement to send information of the doc
 ScriptingGlobals.add(function lookupPresBoxField(presBoxDoc: Doc, field: string, presEleDoc: Doc) {
-    if (field === 'indexInPres') return DocListCast(presBoxDoc._viewType === CollectionViewType.Tree ? presBoxDoc.presentationLinearizedDocuments : presBoxDoc[StrCast(presBoxDoc.presentationFieldKey)]).indexOf(presEleDoc);
+    if (field === 'indexInPres') {
+        const ind = DocListCast(presBoxDoc._viewType === CollectionViewType.Tree ? presBoxDoc.presentationLinearizedDocuments : presBoxDoc[StrCast(presBoxDoc.presentationFieldKey)]).indexOf(presEleDoc);
+        if (ind === -1) {
+            console.log();
+        }
+        return ind;
+    }
     if (field === 'presCollapsedHeight') return [CollectionViewType.Tree || CollectionViewType.Stacking].includes(presBoxDoc._viewType as any) ? 35 : 31;
     if (field === 'presStatus') return presBoxDoc.presStatus;
     if (field === '_itemIndex') return presBoxDoc._itemIndex;
-- 
cgit v1.2.3-70-g09d2


From c29b7151e390f8e5b2090a6e3cd858249703bea7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 6 Jun 2022 20:55:52 -0400
Subject: removed sort ui from pres box tree view.  made expanding/closing text
 hierarchies simpler (not sure what it might break though).

---
 src/client/views/collections/TreeView.tsx                 | 2 +-
 src/client/views/nodes/formattedText/FormattedTextBox.tsx | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index a85b2a0d4..befd2020c 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -471,7 +471,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
             let downX = 0, downY = 0;
             return <>
-                {!docs?.length ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} >
+                {!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} >
                     {sortings[sorting]?.label}
                 </div>}
                 <ul key={expandKey + "more"} title="click to change sort order" className={this.doc.treeViewHideTitle ? "no-indent" : ""}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 2ae9acfc8..7d0302b26 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1411,9 +1411,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             const listNode = this._editorView?.state.doc.nodeAt(clickPos.pos);
             if (olistNode && olistNode.type === this._editorView?.state.schema.nodes.ordered_list && listNode) {
                 if (!highlightOnly) {
-                    if (selectOrderedList || (!collapse && listNode.attrs.visibility)) {
+                    if (selectOrderedList) {
                         this._editorView.dispatch(this._editorView.state.tr.setSelection(new NodeSelection(selectOrderedList ? $olistPos! : listPos!)));
-                    } else if (!listNode.attrs.visibility || downNode === listNode) {
+                    } else {
                         const tr = this._editorView.state.tr.setNodeMarkup(clickPos.pos, listNode.type, { ...listNode.attrs, visibility: !listNode.attrs.visibility });
                         this._editorView.dispatch(tr.setSelection(TextSelection.create(tr.doc, clickPos.pos)));
                     }
-- 
cgit v1.2.3-70-g09d2


From f8840672a7bcb3f337d8e50098f374a1b2d441ce Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Jun 2022 01:17:24 -0400
Subject: added ability to make thumbnails of dashboards. started to cleanup
 dockingView/goldenlayout undo event handling.  cleaned up tab doc list in
 docking view.  made titles editable again in treeview.  fixed overlay view to
 work with image docs etc by setting top/left in css

---
 src/client/documents/Documents.ts                  |  6 +--
 src/client/goldenLayout.js                         |  2 +-
 src/client/util/CurrentUserUtils.ts                | 26 ++++++++---
 src/client/views/DocumentButtonBar.tsx             | 53 ++++++++++------------
 src/client/views/MainView.tsx                      | 12 +----
 src/client/views/OverlayView.scss                  |  2 +
 src/client/views/OverlayView.tsx                   |  2 +-
 .../views/collections/CollectionDockingView.tsx    | 21 ++++++---
 src/client/views/collections/TabDocView.tsx        | 28 ++++--------
 src/client/views/collections/TreeView.tsx          |  4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 45 ++++++++++--------
 src/client/views/nodes/WebBoxRenderer.js           |  4 +-
 src/client/views/topbar/TopBar.tsx                 |  6 +--
 13 files changed, 108 insertions(+), 103 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 817478b2f..acc1e341a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -671,9 +671,9 @@ export namespace Docs {
             return viewDoc;
         }
 
-        export function ImageDocument(url: string, options: DocumentOptions = {}) {
-            const imgField = new ImageField(url);
-            return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(url), ...options });
+        export function ImageDocument(url: string|ImageField, options: DocumentOptions = {}) {
+            const imgField =  url instanceof ImageField ? url : new ImageField(url);
+            return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(imgField.url.href), ...options });
         }
 
         export function PresDocument(options: DocumentOptions = {}) {
diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index 82b10608d..4735f216f 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -1431,7 +1431,7 @@
             this.root.callDownwards('_$init');
 
             if (config.maximisedItemId === '__glMaximised') {
-                this.root.getItemsById(config.maximisedItemId)[0].toggleMaximise();
+                this.root.getItemsById(config.maximisedItemId)[0]?.toggleMaximise();
             }
         },
 
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 51bfdbbd2..885679b64 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -8,7 +8,7 @@ import { PrefetchProxy } from "../../fields/Proxy";
 import { RichTextField } from "../../fields/RichTextField";
 import { ComputedField, ScriptField } from "../../fields/ScriptField";
 import { BoolCast, Cast, DateCast, NumCast, PromiseValue, StrCast } from "../../fields/Types";
-import { nullAudio } from "../../fields/URLField";
+import { ImageField, nullAudio } from "../../fields/URLField";
 import { SharingPermissions } from "../../fields/util";
 import { Utils } from "../../Utils";
 import { DocServer } from "../DocServer";
@@ -22,11 +22,10 @@ import { TreeView } from "../views/collections/TreeView";
 import { Colors } from "../views/global/globalEnums";
 import { MainView } from "../views/MainView";
 import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox";
-import { LabelBox } from "../views/nodes/LabelBox";
 import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView";
 import { OverlayView } from "../views/OverlayView";
 import { DocumentManager } from "./DocumentManager";
-import { DragManager, dropActionType } from "./DragManager";
+import { DragManager } from "./DragManager";
 import { makeTemplate, MakeTemplate } from "./DropConverter";
 import { HistoryUtil } from "./History";
 import { LinkManager } from "./LinkManager";
@@ -1185,9 +1184,24 @@ export class CurrentUserUtils {
     }
 
     public static async snapshotDashboard(userDoc: Doc) {
-        const copy = await CollectionDockingView.Copy(CurrentUserUtils.ActiveDashboard);
-        Doc.AddDocToList(Cast(userDoc.myDashboards, Doc, null), "data", copy);
-        CurrentUserUtils.openDashboard(userDoc, copy);
+        const docView = CollectionDockingView.Instance.props.DocumentView?.();
+        const content = docView?.ContentDiv;
+        if (docView && content) {
+            const _width = Number(getComputedStyle(content).width.replace("px",""));
+            const _height = Number(getComputedStyle(content).height.replace("px",""));
+            CollectionFreeFormView.UpdateIcon(
+                docView.layoutDoc[Id] + "-icon" + (new Date()).getTime(),
+                content,
+                _width, _height,
+                _width, _height, 0,
+                (iconFile, _nativeWidth, _nativeHeight) => {
+                    const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: docView.rootDoc.title+"-icon", _width, _height, _nativeWidth, _nativeHeight});
+                    const proto = Cast(img.proto, Doc, null)!;
+                    proto["data-nativeWidth"] = _width;
+                    proto["data-nativeHeight"] = _height;
+                    docView.dataDoc.thumb = img;
+                });
+        }
     }
 
     public static createNewDashboard = async (userDoc: Doc, id?: string) => {
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index c0645f0ab..103734b9b 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -213,34 +213,31 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     @undoBatch
     @action
     pinWithView = (targetDoc: Doc) => {
-        if (targetDoc) {
-            TabDocView.PinDoc(targetDoc);
-            setTimeout(() => {
-                const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1];
-                const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(targetDoc.type as any) || targetDoc._viewType === CollectionViewType.Stacking;
-                const pannable: boolean = ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG);
-                if (scrollable) {
-                    const scroll = targetDoc._scrollTop;
-                    activeDoc.presPinView = true;
-                    activeDoc.presPinViewScroll = scroll;
-                } else if ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) {
-                    activeDoc.presPinView = true;
-                    activeDoc.presStartTime = targetDoc._currentTimecode;
-                    activeDoc.presEndTime = NumCast(targetDoc._currentTimecode) + 0.1;
-                } else if (pannable) {
-                    const x = targetDoc._panX;
-                    const y = targetDoc._panY;
-                    const scale = targetDoc._viewScale;
-                    activeDoc.presPinView = true;
-                    activeDoc.presPinViewX = x;
-                    activeDoc.presPinViewY = y;
-                    activeDoc.presPinViewScale = scale;
-                } else if (targetDoc.type === DocumentType.COMPARISON) {
-                    const width = targetDoc._clipWidth;
-                    activeDoc.presPinClipWidth = width;
-                    activeDoc.presPinView = true;
-                }
-            });
+        const activeDoc = targetDoc && TabDocView.PinDoc(targetDoc);
+        if (activeDoc) {
+            const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(targetDoc.type as any) || targetDoc._viewType === CollectionViewType.Stacking;
+            const pannable: boolean = ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG);
+            if (scrollable) {
+                const scroll = targetDoc._scrollTop;
+                activeDoc.presPinView = true;
+                activeDoc.presPinViewScroll = scroll;
+            } else if ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) {
+                activeDoc.presPinView = true;
+                activeDoc.presStartTime = targetDoc._currentTimecode;
+                activeDoc.presEndTime = NumCast(targetDoc._currentTimecode) + 0.1;
+            } else if (pannable) {
+                const x = targetDoc._panX;
+                const y = targetDoc._panY;
+                const scale = targetDoc._viewScale;
+                activeDoc.presPinView = true;
+                activeDoc.presPinViewX = x;
+                activeDoc.presPinViewY = y;
+                activeDoc.presPinViewScale = scale;
+            } else if (targetDoc.type === DocumentType.COMPARISON) {
+                const width = targetDoc._clipWidth;
+                activeDoc.presPinClipWidth = width;
+                activeDoc.presPinView = true;
+            }
         }
     }
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index cdf85c905..a30db66e4 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -226,17 +226,7 @@ export class MainView extends React.Component {
         if (received && !this.userDoc) {
             reaction(() => CurrentUserUtils.GuestTarget, target => target && CurrentUserUtils.createNewDashboard(Doc.UserDoc()), { fireImmediately: true });
         } else {
-            if (received && CurrentUserUtils._urlState.sharing) {
-                reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized,
-                    initialized => initialized && received && DocServer.GetRefField(received).then(docField => {
-                        if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) {
-                            CollectionDockingView.AddSplit(docField, "right");
-                        }
-                    }),
-                );
-            }
-            const activeDash = PromiseValue(this.userDoc.activeDashboard);
-            activeDash.then(dash => {
+            PromiseValue(this.userDoc.activeDashboard).then(dash => {
                 if (dash instanceof Doc) CurrentUserUtils.openDashboard(this.userDoc, dash);
                 else CurrentUserUtils.createNewDashboard(this.userDoc);
             });
diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss
index 555f4298d..f22e68ff5 100644
--- a/src/client/views/OverlayView.scss
+++ b/src/client/views/OverlayView.scss
@@ -46,4 +46,6 @@
 .overlayView-doc {
     z-index: 9002; //so that it appears above chroma 
     position: absolute;
+    top: 0;
+    left: 0;
 }
\ No newline at end of file
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index c3c103b50..f5e686473 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -200,7 +200,7 @@ export class OverlayView extends React.Component {
                     ScreenToLocalTransform={this.docScreenToLocalXf(d)}
                     renderDepth={1}
                     isDocumentActive={returnTrue}
-                    isContentActive={retu}
+                    isContentActive={returnTrue}
                     whenChildContentsActiveChanged={emptyFunction}
                     focus={DocUtils.DefaultFocus}
                     styleProvider={DefaultStyleProvider}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index de2106e4a..5af72b7d1 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -26,6 +26,7 @@ import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
 import { CollectionViewType } from './CollectionView';
 import { TabDocView } from './TabDocView';
 import React = require("react");
+import { SelectionManager } from '../../util/SelectionManager';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
@@ -50,9 +51,8 @@ export class CollectionDockingView extends CollectionSubView() {
     public _flush: UndoManager.Batch | undefined;
     private _ignoreStateChange = "";
     public tabMap: Set<any> = new Set();
-    public get initialized() { return this._goldenLayout !== null; }
     public get HasFullScreen() { return this._goldenLayout._maximisedItem !== null; }
-    @observable private _goldenLayout: any = null;
+    private _goldenLayout: any = null;
 
     constructor(props: SubCollectionViewProps) {
         super(props);
@@ -118,6 +118,7 @@ export class CollectionDockingView extends CollectionSubView() {
 
     @undoBatch
     public static OpenFullScreen(doc: Doc) {
+        SelectionManager.DeselectAll();
         const instance = CollectionDockingView.Instance;
         if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") {
             return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
@@ -271,7 +272,7 @@ export class CollectionDockingView extends CollectionSubView() {
         return true;
     }
 
-    async setupGoldenLayout() {
+    setupGoldenLayout = async () => {
         const config = StrCast(this.props.Document.dockingConfig);
         if (config) {
             const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g);
@@ -291,7 +292,7 @@ export class CollectionDockingView extends CollectionSubView() {
             }
             this.tabMap.clear();
             this._goldenLayout?.destroy();
-            runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config)));
+            this._goldenLayout = new GoldenLayout(JSON.parse(config));
             this._goldenLayout.on('tabCreated', this.tabCreated);
             this._goldenLayout.on('tabDestroyed', this.tabDestroyed);
             this._goldenLayout.on('stackCreated', this.stackCreated);
@@ -322,7 +323,7 @@ export class CollectionDockingView extends CollectionSubView() {
                     }
                     this._ignoreStateChange = "";
                 });
-            setTimeout(() => this.setupGoldenLayout(), 0);
+            setTimeout(this.setupGoldenLayout);
             //window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
         }
     }
@@ -413,19 +414,25 @@ export class CollectionDockingView extends CollectionSubView() {
         const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
         const changesMade = this.props.Document.dockcingConfig !== json;
         if (changesMade && !this._flush) {
-            this.props.Document.dockingConfig = json;
-            this.props.Document.data = new List<Doc>(docs);
+            UndoManager.RunInBatch(() => {
+                this.props.Document.dockingConfig = json;
+                this.props.Document.data = new List<Doc>(docs);
+            }, "state changed");
         }
         return changesMade;
     }
 
     tabDestroyed = (tab: any) => {
+        const dview = CollectionDockingView.Instance.props.Document;
+        const fieldKey = CollectionDockingView.Instance.props.fieldKey;
+        Doc.RemoveDocFromList(dview, fieldKey, tab.DashDoc);
         this.tabMap.delete(tab);
         tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
         tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
         this.stateChanged();
     }
     tabCreated = (tab: any) => {
+        this.tabMap.add(tab);
         tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab);  // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
     }
 
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 0141724ea..75a8207dd 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -82,7 +82,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             const iconWrap = document.createElement("div");
             const closeWrap = document.createElement("div");
 
-
             titleEle.size = StrCast(doc.title).length + 3;
             titleEle.value = doc.title;
             titleEle.onkeydown = (e: KeyboardEvent) => {
@@ -185,14 +184,13 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab");
                 });
         }
-        CollectionDockingView.Instance.tabMap.add(tab);
     }
 
     /**
      * Adds a document to the presentation view
      **/
     @action
-    public static async PinDoc(doc: Doc, pinProps?: PinProps) {
+    public static PinDoc(doc: Doc, pinProps?: PinProps) {
         //add this new doc to props.Document
 
         // all docs will be added to the ActivePresentation as stored on CurrentUserUtils
@@ -246,19 +244,14 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 pinDoc.presMovement = PresMovement.None;
             }
             if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
-            const dview = CollectionDockingView.Instance.props.Document;
-            const fieldKey = CollectionDockingView.Instance.props.fieldKey;
-            const tabdocs = await DocListCastAsync(dview[fieldKey]);
-            runInAction(() => {
-                if (!pinProps?.hidePresBox && !tabdocs?.includes(curPres)) {
-                    tabdocs?.push(curPres);  // bcz: Argh! this is annoying.  if multiple documents are pinned, this will get called multiple times before the presentation view is drawn.  Thus it won't be in the tabdocs list and it will get created multple times.  so need to explicilty add the presbox to the list of open tabs
-                    CollectionDockingView.AddSplit(curPres, "right");
-                }
-                PresBox.Instance?._selectedArray.clear();
-                pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
-                DocumentManager.Instance.jumpToDocument(doc, false, undefined, []);
-                batch.end();
-            });
+            if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
+                CollectionDockingView.AddSplit(curPres, "right");
+                setTimeout(() => DocumentManager.Instance.jumpToDocument(doc, false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
+            }
+            PresBox.Instance?._selectedArray.clear();
+            pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
+            setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
+            return pinDoc;
         }
     }
 
@@ -282,7 +275,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     componentWillUnmount() {
         this._tabReaction?.();
         this._view && DocumentManager.Instance.RemoveView(this._view);
-        this.tab && CollectionDockingView.Instance.tabMap.delete(this.tab);
 
         this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
     }
@@ -430,9 +422,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             }} ref={ref => {
                 if (this._mainCont = ref) {
                     if (this._lastTab) {
-                        console.log("DUP tab")
                         this._view && DocumentManager.Instance.RemoveView(this._view);
-                        CollectionDockingView.Instance.tabMap.delete(this._lastTab);
                     }
                     this._lastTab = this.tab;
                     (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index befd2020c..09f05f69a 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -609,10 +609,8 @@ export class TreeView extends React.Component<TreeViewProps> {
         return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     }
 
-    // TODO: currently doc focus works, but can't seem to edit title
-    // onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
     onChildClick = () => {
-        return this.props.onChildClick?.() ?? (ScriptField.MakeFunction(`DocFocusOrOpen(self)`)! || this._editTitleScript?.());
+        return this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!);
     }
 
     onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 77cf0fc84..5f927a2a9 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1489,7 +1489,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         }));
     }
 
-    replaceCanvases = (oldDiv: HTMLElement, newDiv: HTMLElement) => {
+    static replaceCanvases(oldDiv: HTMLElement, newDiv: HTMLElement) {
         if (oldDiv.childNodes && newDiv) {
             for (let i = 0; i < oldDiv.childNodes.length; i++) {
                 this.replaceCanvases(oldDiv.childNodes[i] as HTMLElement, newDiv.childNodes[i] as HTMLElement);
@@ -1508,32 +1508,39 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         }
     }
 
-    updateIcon = () => {
-        const docViewContent = this.props.docViewPath().lastElement().ContentDiv!;
+    updateIcon = () => CollectionFreeFormView.UpdateIcon(
+        this.layoutDoc[Id] + "-icon" + (new Date()).getTime(),
+        this.props.docViewPath().lastElement().ContentDiv!,
+        this.layoutDoc[WidthSym](), this.layoutDoc[HeightSym](), 
+        this.props.PanelWidth(), this.props.PanelHeight(), 0, 
+        (iconFile, nativeWidth, nativeHeight) => {
+                    this.dataDoc.icon = new ImageField(iconFile);
+                    this.dataDoc["icon-nativeWidth"] = nativeWidth;
+                    this.dataDoc["icon-nativeHeight"] = nativeHeight;
+        });
+
+    public static UpdateIcon(filename:string, docViewContent:HTMLElement, width: number, height: number, 
+        panelWidth:number, panelHeight: number, scrollTop:number, cb:(iconFile:string, nativeWidth:number, nativeHeight:number) => any) {
         const newDiv = docViewContent.cloneNode(true) as HTMLDivElement;
-        newDiv.style.width = (this.layoutDoc[WidthSym]()).toString();
-        newDiv.style.height = (this.layoutDoc[HeightSym]()).toString();
+        newDiv.style.width = width.toString();
+        newDiv.style.height = height.toString();
         this.replaceCanvases(docViewContent, newDiv);
-        const htmlString = this._mainCont && new XMLSerializer().serializeToString(newDiv);
-        const nativeWidth = this.layoutDoc[WidthSym]();
-        const nativeHeight = this.layoutDoc[HeightSym]();
-
+        const htmlString = new XMLSerializer().serializeToString(newDiv);
+        const nativeWidth = width;
+        const nativeHeight = height;
         CreateImage(
-            "",
+            Utils.prepend(""),
             document.styleSheets,
             htmlString,
             nativeWidth,
-            nativeWidth * this.props.PanelHeight() / this.props.PanelWidth(),
-            NumCast(this.layoutDoc._scrollTop)
+            nativeWidth * panelHeight / panelWidth,
+            scrollTop
         ).then
             ((data_url: any) => {
-                VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + "-icon" + (new Date()).getTime(), true, this.layoutDoc[Id] + "-icon").then(
-                    returnedfilename => setTimeout(action(() => {
-
-                        this.dataDoc.icon = new ImageField(returnedfilename);
-                        this.dataDoc["icon-nativeWidth"] = nativeWidth;
-                        this.dataDoc["icon-nativeHeight"] = nativeHeight;
-                    }), 500));
+                VideoBox.convertDataUri(data_url, filename).then(
+                    returnedfilename => setTimeout(() => {
+                        cb(returnedfilename as string, nativeWidth, nativeHeight);
+                    }, 500));
             })
             .catch(function (error: any) {
                 console.error('oops, something went wrong!', error);
diff --git a/src/client/views/nodes/WebBoxRenderer.js b/src/client/views/nodes/WebBoxRenderer.js
index d9524dd6e..f3f1bcf5c 100644
--- a/src/client/views/nodes/WebBoxRenderer.js
+++ b/src/client/views/nodes/WebBoxRenderer.js
@@ -214,8 +214,8 @@ var ForeignHtmlRenderer = function (styleSheets) {
                 .replace(/noscript/g, "div").replace(/<div class="mediaset"><\/div>/g, "")  // when scripting isn't available (ie, rendering web pages here), <noscript> tags should become <div>'s.  But for Brown CS, there's a layout problem if you leave the empty <mediaset> tag
                 .replace(/<link[^>]*>/g, "")  // don't need to keep any linked style sheets because we've already processed all style sheets above
                 .replace(/srcset="([^ "]*)[^"]*"/g, "src=\"$1\""); // instead of converting each item in the srcset to a data url, just convert the first one and use that
-            let urlsFoundInHtml = getImageUrlsFromFromHtml(contentHtml);
-            const fetchedResources = await getMultipleResourcesAsBase64(webUrl, urlsFoundInHtml);
+            let urlsFoundInHtml = getImageUrlsFromFromHtml(contentHtml).filter(url => !url.startsWith("data:"));
+            const fetchedResources = webUrl ? await getMultipleResourcesAsBase64(webUrl, urlsFoundInHtml) : [];
             for (let i = 0; i < fetchedResources.length; i++) {
                 const r = fetchedResources[i];
                 if (r.resourceUrl) {
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index be248ab92..e486bcb52 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -48,7 +48,7 @@ export class TopBar extends React.Component {
                                 await CurrentUserUtils.createNewDashboard(Doc.UserDoc());
                                 batch.end();
                             }}>
-                                {"New"}<FontAwesomeIcon icon="plus" />
+                                New<FontAwesomeIcon icon="plus" />
                             </div>
                             </Tooltip>
                             <Tooltip title={<div className="dash-tooltip">Work on a copy of the dashboard layout</div>} placement="bottom">
@@ -57,12 +57,12 @@ export class TopBar extends React.Component {
                                     await CurrentUserUtils.snapshotDashboard(Doc.UserDoc());
                                     batch.end();
                                 }}>
-                                    {"Snapshot"}<FontAwesomeIcon icon="camera" />
+                                    Snapshot<FontAwesomeIcon icon="camera" />
                                 </div>
                             </Tooltip>
                             <Tooltip title={<div className="dash-tooltip">Browsing mode for directly navigating to documents</div>} placement="bottom">
                                 <div className="topbar-icon" style={{ background: MainView.Instance._exploreMode ? Colors.LIGHT_BLUE : undefined }} onClick={action(() => MainView.Instance._exploreMode = !MainView.Instance._exploreMode)}>
-                                    {"Explore"}<FontAwesomeIcon icon="map" />
+                                    Explore<FontAwesomeIcon icon="map" />
                                 </div>
                             </Tooltip>
                         </div>
-- 
cgit v1.2.3-70-g09d2


From 3213c24210d67af0a4b027863773ad383404a59c Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 9 Jun 2022 11:07:34 -0400
Subject: renamed fitToBox to fitContentsToBox.  fixed pinning multiple
 documents at same time to not bring up presBox multiple times.

---
 src/client/documents/Documents.ts                  |  3 +-
 src/client/views/DocumentButtonBar.tsx             | 21 ++----------
 src/client/views/LightboxView.tsx                  |  2 --
 src/client/views/MainView.tsx                      |  2 +-
 src/client/views/PropertiesButtons.tsx             |  2 +-
 src/client/views/PropertiesView.tsx                |  2 +-
 src/client/views/collections/CollectionMenu.tsx    |  4 +--
 .../views/collections/CollectionTimeView.tsx       |  2 +-
 src/client/views/collections/TabDocView.tsx        | 25 +++++++--------
 src/client/views/collections/TreeView.tsx          |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 37 +++++++---------------
 .../collections/collectionFreeForm/MarqueeView.tsx |  2 +-
 .../CollectionMulticolumnView.tsx                  |  2 +-
 .../CollectionMultirowView.tsx                     |  2 +-
 .../collectionSchema/CollectionSchemaView.tsx      |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  4 +--
 src/client/views/nodes/MapBox/MapBox.tsx           |  6 ++--
 .../views/nodes/formattedText/FormattedTextBox.tsx |  6 ++--
 src/client/views/nodes/trails/PresBox.tsx          | 14 ++++----
 src/client/views/nodes/trails/PresElementBox.tsx   |  2 +-
 src/fields/documentSchemas.ts                      |  6 ++--
 src/mobile/AudioUpload.tsx                         |  4 +--
 22 files changed, 60 insertions(+), 92 deletions(-)

(limited to 'src/client/views/collections/TreeView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index acc1e341a..144a3d9cf 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -113,7 +113,8 @@ export class DocumentOptions {
     _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true);
     _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true);
     _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true);
-    _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
+    _fitContentsToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
+    _contentBounds?: List<number>; // the (forced) bounds of the document to display. format is: [left, top, right, bottom]
     _lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
     _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
     _isPushpin?: boolean; // whether document, when clicked, toggles display of its link target
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 41224b1c5..0bbe473d7 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -204,27 +204,13 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             <div className="dash-tooltip">{SelectionManager.Views().length > 1 ? "Pin multiple documents to presentation" : "Pin to presentation"}</div>}>
             <div className="documentButtonBar-icon"
                 style={{ color: "white" }}
-                onClick={undoBatch(e => this.props.views().map(view => view && this.pinWithView(view.props.Document)))}>
+                onClick={(e => TabDocView.PinDoc(this.props.views().filter(v => v).map(dv => dv!.rootDoc), {pinDocView: true}))}
+             >
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" />
             </div>
         </Tooltip>;
     }
 
-    @undoBatch
-    @action
-    pinWithView = (targetDoc: Doc) =>  targetDoc && TabDocView.PinDoc(targetDoc, {pinDocView: true});
-
-    @computed
-    get pinWithViewButton() {
-        const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ margin: "auto", width: 17, transform: 'translate(0, 1px)' }} />;
-        const targetDoc = this.view0?.props.Document;
-        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin with current view"}</div></>}>
-            <div className="documentButtonBar-icon" onClick={() => this.pinWithView(targetDoc)}>
-                {presPinWithViewIcon}
-            </div>
-        </Tooltip>;
-    }
-
     @computed
     get shareButton() {
         const targetDoc = this.view0?.props.Document;
@@ -349,9 +335,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             <div className="documentButtonBar-button">
                 {this.pinButton}
             </div>
-            {/* <div className="documentButtonBar-button">
-                {this.pinWithViewButton}
-            </div> */}
             {!Doc.UserDoc()["documentLinksButton-fullMenu"] ? (null) : <div className="documentButtonBar-button">
                 {this.shareButton}
             </div>}
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index f67f37bfb..fcc4aea13 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -207,7 +207,6 @@ export class LightboxView extends React.Component<LightboxViewProps> {
 
     future = () => LightboxView._future;
     tourMap = () => LightboxView._tourMap;
-    fitToBox = () => LightboxView._docTarget === LightboxView.LightboxDoc;
     render() {
         let downx = 0, downy = 0;
         return !LightboxView.LightboxDoc ? (null) :
@@ -241,7 +240,6 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                         DataDoc={undefined}
                         LayoutTemplate={LightboxView.LightboxDocTemplate}
                         addDocument={undefined}
-                        // fitContentsToDoc={this.fitToBox} // bcz: why do we want this?  when we initially open a colletion, we shrinkwrap it which allows for user navigation.  if we later encounter a collection, it's not clear to me that we want to make it either shrinkwrap or fitContents...
                         isDocumentActive={returnFalse}
                         isContentActive={returnTrue}
                         addDocTab={this.addDocTab}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 641178cd9..84a131a57 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -287,7 +287,7 @@ export class MainView extends React.Component {
                 styleProvider={DefaultStyleProvider}
                 rootSelected={returnTrue}
                 removeDocument={returnFalse}
-                fitContentsToDoc={returnTrue}
+                fitContentsToBox={returnTrue}
                 isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events)
                 isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive
                 ScreenToLocalTransform={this.headerBarScreenXf}
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index f24ff09db..74055f057 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -71,7 +71,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         return this.propertyToggleBtn("Lock\xA0View", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => "lock");
     }
     @computed get fitContentButton() {
-        return this.propertyToggleBtn("View All", "_fitToBox", on => `${on ? "Don't" : "Do"} fit content to container visible area`, on => "eye");
+        return this.propertyToggleBtn("View All", "_fitContentsToBox", on => `${on ? "Don't" : "Do"} fit content to container visible area`, on => "eye");
     }
     @computed get fitWidthButton() {
         return this.propertyToggleBtn("Fit\xA0Width", "_fitWidth", on => `${on ? "Don't" : "Do"} fit content to width of container`, on => "arrows-alt-h");
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index bcfd2dd56..16eb95cf4 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -300,7 +300,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     Document={layoutDoc}
                     DataDoc={this.dataDoc}
                     renderDepth={1}
-                    fitContentsToDoc={returnTrue}
+                    fitContentsToBox={returnTrue}
                     rootSelected={returnFalse}
                     styleProvider={DefaultStyleProvider}
                     docViewPath={returnEmptyDoclist}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 01e77f342..39f6466d6 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -252,8 +252,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
     };
     _clusterCommand = {
         params: ["target"], title: "fit content",
-        script: "self.target._fitToBox = !self.target._fitToBox;",
-        immediate: undoBatch((source: Doc[]) => this.target._fitToBox = !this.target._fitToBox),
+        script: "self.target._fitContentsToBox = !self.target._fitContentsToBox;",
+        immediate: undoBatch((source: Doc[]) => this.target._fitContentsToBox = !this.target._fitContentsToBox),
         initialize: emptyFunction
     };
     _fitContentCommand = {
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 4f6f45d2f..7573b938a 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -135,7 +135,7 @@ export class CollectionTimeView extends CollectionSubView() {
             onClick={this.contentsDown}>
             <CollectionFreeFormView {...this.props}
                 engineProps={{ pivotField: this.pivotField, docFilters: this.childDocFilters, docRangeFilters: this.childDocRangeFilters }}
-                fitContentsToDoc={returnTrue}
+                fitContentsToBox={returnTrue}
                 childClickScript={this._childClickedScript}
                 viewDefDivClick={this._viewDefDivClick}
                 childFreezeDimensions={true}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f6a75e2db..5cc92a305 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -192,15 +192,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
      * Adds a document to the presentation view
      **/
     @action
-    public static PinDoc(doc: Doc, pinProps?: PinProps) {
-        //add this new doc to props.Document
+    public static PinDoc(docs: Doc|Doc[], pinProps?: PinProps) {
+        const docList = ((docs instanceof Doc) ? [docs]: docs);
+        const batch = UndoManager.StartBatch("pinning doc");
 
         // all docs will be added to the ActivePresentation as stored on CurrentUserUtils
         const curPres = CurrentUserUtils.ActivePresentation;
-        if (curPres) {
+        curPres && docList.forEach(doc => {
             // Edge Case 1: Cannot pin document to itself
             if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; }
-            const batch = UndoManager.StartBatch("pinning doc");
             const pinDoc = Doc.MakeAlias(doc);
             pinDoc.presentationTargetDoc = doc;
             pinDoc.title = doc.title + " - Slide";
@@ -279,17 +279,16 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 pinDoc.presMovement = PresMovement.None;
             }
             if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
-            if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
-                const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []);
-                if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
-                CollectionDockingView.AddSplit(curPres, "right");
-                setTimeout(() => DocumentManager.Instance.jumpToDocument(doc, false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
-            }
             PresBox.Instance?._selectedArray.clear();
             pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
-            setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
-            return pinDoc;
+        });
+        if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
+            const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []);
+            if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
+            CollectionDockingView.AddSplit(curPres, "right");
+            setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
         }
+        setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
     }
 
     componentDidMount() {
@@ -572,7 +571,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                     docFilters={CollectionDockingView.Instance.childDocFilters}
                     docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
                     searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
-                    fitContentsToDoc={returnTrue}
+                    fitContentsToBox={returnTrue}
                 />
                 <div className="miniOverlay" onPointerDown={this.miniDown} >
                     <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% `, }} />
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 09f05f69a..8824750a3 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -796,7 +796,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             isDocumentActive={isActive}
             styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
             hideTitle={asText}
-            fitContentsToDoc={returnTrue}
+            fitContentsToBox={returnTrue}
             hideDecorationTitle={this.props.treeView.outlineMode}
             hideResizeHandles={this.props.treeView.outlineMode}
             onClick={this.onChildClick}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b70e6ff98..ec3cf1fe8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -9,7 +9,7 @@ import { InkData, InkField, InkTool, PointData, Segment } from "../../../../fiel
 import { List } from "../../../../fields/List";
 import { ObjectField } from "../../../../fields/ObjectField";
 import { RichTextField } from "../../../../fields/RichTextField";
-import { createSchema, listSpec } from "../../../../fields/Schema";
+import { listSpec } from "../../../../fields/Schema";
 import { ScriptField } from "../../../../fields/ScriptField";
 import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
 import { ImageField } from "../../../../fields/URLField";
@@ -41,6 +41,7 @@ import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveIn
 import { LightboxView } from "../../LightboxView";
 import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
 import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment, ViewSpecPrefix } from "../../nodes/DocumentView";
+import { FieldViewProps } from "../../nodes/FieldView";
 import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
 import { PresBox } from "../../nodes/trails/PresBox";
 import { VideoBox } from "../../nodes/VideoBox";
@@ -50,27 +51,13 @@ import { CollectionDockingView } from "../CollectionDockingView";
 import { CollectionSubView } from "../CollectionSubView";
 import { TreeViewType } from "../CollectionTreeView";
 import { CollectionViewType } from "../CollectionView";
+import { TabDocView } from "../TabDocView";
 import { computePivotLayout, computerPassLayout, computerStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult } from "./CollectionFreeFormLayoutEngines";
 import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
 import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
-import { FieldView, FieldViewProps } from "../../nodes/FieldView";
-import { TabDocView } from "../TabDocView";
 
-export const panZoomSchema = createSchema({
-    _panX: "number",
-    _panY: "number",
-    _currentTimecode: "number",
-    _timecodeToShow: "number",
-    _currentFrame: "number",
-    _useClusters: "boolean",
-    _viewTransition: "string",
-    _xPadding: "number",         // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
-    _yPadding: "number",         // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
-    _fitToBox: "boolean",
-    scrollHeight: "number"    // this will be set when the collection is an annotation overlay for a PDF/Webpage
-});
 
 export type collectionFreeformViewProps = {
     annotationLayerHostsContent?: boolean; // whether to force scaling of content (needed by ImageBox)
@@ -138,20 +125,20 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x))
         };
     }
-    @computed get fitToContent() { return (this.props.fitContentsToDoc?.() || this.Document._fitToBox) && !this.isAnnotationOverlay; }
+    @computed get fitContentsToBox() { return (this.props.fitContentsToBox?.() || this.Document._fitContentsToBox) && !this.isAnnotationOverlay; }
     @computed get contentBounds() { 
         const cb = Cast(this.rootDoc.contentBounds, listSpec("number"));
         return cb ? {x:cb[0], y:cb[1], r:cb[2], b: cb[3]} : 
             this.props.contentBounds?.() ?? aggregateBounds(this._layoutElements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); 
     }
-    @computed get nativeWidth() { return this.fitToContent ? 0 : Doc.NativeWidth(this.Document); }
-    @computed get nativeHeight() { return this.fitToContent ? 0 : Doc.NativeHeight(this.Document); }
+    @computed get nativeWidth() { return this.fitContentsToBox ? 0 : Doc.NativeWidth(this.Document); }
+    @computed get nativeHeight() { return this.fitContentsToBox ? 0 : Doc.NativeHeight(this.Document); }
     @computed get cachedCenteringShiftX(): number {
-        const scaling = this.fitToContent || !this.contentScaling ? 1 : this.contentScaling;
+        const scaling = this.fitContentsToBox || !this.contentScaling ? 1 : this.contentScaling;
         return this.props.isAnnotationOverlay ? 0 : this.props.PanelWidth() / 2 / scaling;  // shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedCenteringShiftY(): number {
-        const scaling = this.fitToContent || !this.contentScaling ? 1 : this.contentScaling;
+        const scaling = this.fitContentsToBox || !this.contentScaling ? 1 : this.contentScaling;
         return this.props.isAnnotationOverlay ? 0 : this.props.PanelHeight() / 2 / scaling;// shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedGetLocalTransform(): Transform {
@@ -176,8 +163,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         this.layoutDoc._panY = vals.bounds.cy;
         this.layoutDoc._viewScale = vals.scale;
     }
-    freeformData = (force?: boolean) => !this._firstRender && (this.fitToContent || force) ? this.fitToContentVals : undefined;
-    reverseNativeScaling = () => this.fitToContent ? true : false;
+    freeformData = (force?: boolean) => !this._firstRender && (this.fitContentsToBox || force) ? this.fitToContentVals : undefined;
+    reverseNativeScaling = () => this.fitContentsToBox ? true : false;
     panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document._panX);
     panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document._panY);
     zoomScaling = () => (this.freeformData()?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1));
@@ -1272,7 +1259,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
             pointerEvents={this.pointerEvents}
             jitterRotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
-        //fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
+        //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
         />;
     }
     addDocTab = action((doc: Doc, where: string) => {
@@ -1616,7 +1603,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : [];
         appearanceItems.push({ description: "Reset View", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document[this.scaleFieldKey] = 1; }, icon: "compress-arrows-alt" });
         !Doc.UserDoc().noviceMode && Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: "Reset default note style", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" });
-        appearanceItems.push({ description: `${this.fitToContent ? "Make Zoomable" : "Scale to Window"}`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
+        appearanceItems.push({ description: `${this.fitContentsToBox ? "Make Zoomable" : "Scale to Window"}`, event: () => this.Document._fitContentsToBox = !this.fitContentsToBox, icon: !this.fitContentsToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
         appearanceItems.push({ description: `Pin View`, event: () => TabDocView.PinDoc(this.rootDoc, {pinDocView:true, panelWidth: this.props.PanelWidth(), panelHeight:this.props.PanelHeight()}), icon: "map-pin" });
         //appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: "compress-arrows-alt" });
         this.props.ContainingCollectionView &&
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 3fac3350a..6df2bb102 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -516,7 +516,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             d.y = NumCast(d.y) - this.Bounds.top;
             return d;
         });
-        const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, isPushpin: true, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" });
+        const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, isPushpin: true, _width: 200, _height: 200, _fitContentsToBox: true, _showSidebar: true, title: "overview" });
         const portal = Docs.Create.FreeformDocument(selected, { x: this.Bounds.left + 200, y: this.Bounds.top, isGroup: true, backgroundColor: "transparent" });
         DocUtils.MakeLink({ doc: summary }, { doc: portal }, "summary of:summarized by", "");
 
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index e2dfb25e2..7147ae485 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -257,7 +257,7 @@ export class CollectionMulticolumnView extends CollectionSubView() {
             isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.isContentActive}
             hideResizeHandles={this.props.childHideResizeHandles?.()}
             hideDecorationTitle={this.props.childHideDecorationTitle?.()}
-            fitContentsToDoc={this.props.fitContentsToDoc}
+            fitContentsToBox={this.props.fitContentsToBox}
             PanelWidth={width}
             PanelHeight={height}
             rootSelected={this.rootSelected}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 3010e36aa..3bda56c33 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -264,7 +264,7 @@ export class CollectionMultirowView extends CollectionSubView() {
             isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.isContentActive}
             hideResizeHandles={this.props.childHideResizeHandles?.()}
             hideDecorationTitle={this.props.childHideDecorationTitle?.()}
-            fitContentsToDoc={this.props.fitContentsToDoc}
+            fitContentsToBox={this.props.fitContentsToBox}
             focus={this.props.focus}
             docFilters={this.childDocFilters}
             docRangeFilters={this.childDocRangeFilters}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index b731479a5..f45068b6a 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -402,7 +402,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                 <DocumentView
                     Document={this.previewDocument}
                     DataDoc={undefined}
-                    fitContentsToDoc={returnTrue}
+                    fitContentsToBox={returnTrue}
                     freezeDimensions={true}
                     dontCenter={"y"}
                     focus={DocUtils.DefaultFocus}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 26dec3bd5..2a518bb57 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -85,7 +85,7 @@ export interface DocComponentView {
     getAnchor?: () => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
     scrollFocus?: (doc: Doc, smooth: boolean) => Opt<number>; // returns the duration of the focus
     setViewSpec?: (anchor: Doc, preview: boolean) => void;  // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document
-    reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height.  However, some content views (e.g., FreeFormView w/ fitToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.
+    reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height.  However, some content views (e.g., FreeFormView w/ fitContentsToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.
     shrinkWrap?: () => void;  // requests a document to display all of its contents with no white space.  currently only implemented (needed?) for freeform views
     menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected.
     isAnyChildContentActive?: () => boolean; // is any child content of the document active
@@ -113,7 +113,7 @@ export interface DocumentViewSharedProps {
     Document: Doc;
     DataDoc?: Doc;
     contentBounds?: () => (undefined|{x:number, y:number, r:number, b:number});
-    fitContentsToDoc?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitToBox property on a Document
+    fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitContentsToBox property on a Document
     ContainingCollectionView: Opt<CollectionView>;
     ContainingCollectionDoc: Opt<Doc>;
     suppressSetHeight?: boolean;
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 9f1c019fe..5f4c17ee6 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -259,7 +259,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
 
             if (this._loadPending && this._map.getBounds()) {
                 this._loadPending = false;
-                this.layoutDoc.fitToBox && this.fitBounds(this._map);
+                this.layoutDoc.fitContentsToBox && this.fitBounds(this._map);
             }
         }, 250);
         // listener to addmarker event
@@ -274,7 +274,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     centered = () => {
         if (this._loadPending && this._map.getBounds()) {
             this._loadPending = false;
-            this.layoutDoc.fitToBox && this.fitBounds(this._map);
+            this.layoutDoc.fitContentsToBox && this.fitBounds(this._map);
         }
         this.dataDoc.mapLat = this._map.getCenter()?.lat();
         this.dataDoc.mapLng = this._map.getCenter()?.lng();
@@ -284,7 +284,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     zoomChanged = () => {
         if (this._loadPending && this._map.getBounds()) {
             this._loadPending = false;
-            this.layoutDoc.fitToBox && this.fitBounds(this._map);
+            this.layoutDoc.fitContentsToBox && this.fitBounds(this._map);
         }
         this.dataDoc.mapZoom = this._map.getZoom();
     }
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 7d0302b26..4e431e7bd 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -495,7 +495,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 // embed document when dragg marked as embed
             } else if (de.embedKey) {
                 const target = dragData.droppedDocuments[0];
-                target._fitToBox = true;
+                target._fitContentsToBox = true;
                 const node = schema.nodes.dashDoc.create({
                     width: target[WidthSym](),
                     height: target[HeightSym](),
@@ -1557,7 +1557,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             }
         }
     }
-    fitToBox = () => this.props.Document._fitToBox;
+    fitContentsToBox = () => this.props.Document._fitContentsToBox;
     sidebarContentScaling = () => (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
     sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
         if (!this.layoutDoc._showSidebar) this.toggleSidebar();
@@ -1632,7 +1632,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     ScreenToLocalTransform={this.sidebarScreenToLocal}
                     renderDepth={this.props.renderDepth + 1}
                     setHeight={this.setSidebarHeight}
-                    fitContentsToDoc={this.fitToBox}
+                    fitContentsToBox={this.fitContentsToBox}
                     noSidebar={true}
                     fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : `${this.fieldKey}-annotations`} />;
         };
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 6de04bd31..cebf9487a 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -35,8 +35,8 @@ export interface PinProps {
     setPosition?: boolean;
     hidePresBox?: boolean;
     pinWithView?: PinViewProps;
-    pinDocView?: boolean;
-    panelWidth?: number;
+    pinDocView?: boolean;  // whether the current view specs of the document should be saved the pinned document
+    panelWidth?: number;  // panel width and height of the document (used to compute the bounds of the pinned view area)
     panelHeight?: number
 }
 
@@ -997,7 +997,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     /**
      * Method called for viewing paths which adds a single line with
      * points at the center of each document added.
-     * Design choice: When this is called it sets _fitToBox as true so the
+     * Design choice: When this is called it sets _fitContentsToBox as true so the
      * user can have an overview of all of the documents in the collection.
      * (Design needed for when documents in presentation trail are in another
      * collection)
@@ -1800,16 +1800,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 doc = Docs.Create.FreeformDocument([], { title: input ? input : "Blank slide", _width: 400, _height: 225, x: x, y: y });
                 break;
             case 'title':
-                doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
                 break;
             case 'header':
-                doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
                 break;
             case 'content':
-                doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
                 break;
             case 'twoColumns':
-                doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
                 break;
             default:
                 break;
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 5eff47a86..ba0193e4b 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -85,7 +85,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     isContentActive={this.props.isContentActive}
                     addDocTab={returnFalse}
                     pinToPres={returnFalse}
-                    fitContentsToDoc={returnTrue}
+                    fitContentsToBox={returnTrue}
                     PanelWidth={this.embedWidth}
                     PanelHeight={this.embedHeight}
                     ScreenToLocalTransform={Transform.Identity}
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index e532becb5..be39e0709 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -36,8 +36,8 @@ export const documentSchema = createSchema({
     _nativeHeight: "number",    // "
     _width: "number",           // width of document in its container's coordinate system
     _height: "number",          // "
-    _xPadding: "number",        // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
-    _yPadding: "number",        // pixels of padding on top/bottom of collectionfreeformview contents when fitToBox is set
+    _xPadding: "number",        // pixels of padding on left/right of collectionfreeformview contents when fitContentsToBox is set
+    _yPadding: "number",        // pixels of padding on top/bottom of collectionfreeformview contents when fitContentsToBox is set
     _xMargin: "number",         // margin added on left/right of most documents to add separation from their container
     _yMargin: "number",         // margin added on top/bottom of most documents to add separation from their container
     _overflow: "string",        // sets overflow behvavior for CollectionFreeForm views
@@ -59,7 +59,7 @@ export const documentSchema = createSchema({
     borderRounding: "string",   // border radius rounding of document
     boxShadow: "string",        // the amount of shadow around the perimeter of a document
     color: "string",            // foreground color of document
-    fitToBox: "boolean",        // whether freeform view contents should be zoomed/panned to fill the area of the document view
+    fitContentsToBox: "boolean",// whether freeform view contents should be zoomed/panned to fill the area of the document view box
     fontSize: "string",
     hidden: "boolean",          // whether a document should not be displayed
     isInkMask: "boolean",       // is the document a mask (ie, sits on top of other documents, has an unbounded width/height that is dark, and content uses 'hard-light' mix-blend-mode to let other documents pop through)
diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx
index 418464f0e..64baa351c 100644
--- a/src/mobile/AudioUpload.tsx
+++ b/src/mobile/AudioUpload.tsx
@@ -19,7 +19,7 @@ import React = require('react');
 
 @observer
 export class AudioUpload extends React.Component {
-    @observable public _audioCol: Doc = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
+    @observable public _audioCol: Doc = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitContentsToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
 
     /**
      * Handles the onclick functionality for the 'Restart' button
@@ -36,7 +36,7 @@ export class AudioUpload extends React.Component {
                     title: "mobile audio",
                     _width: 500,
                     _height: 100
-                }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
+                }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitContentsToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
     }
 
     /** 
-- 
cgit v1.2.3-70-g09d2

