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 32d46a0b641022cf0dd1fe0cf15629cf75057b59 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 4 May 2022 16:03:51 -0400
Subject: cleaned up treeview sorting.

---
 src/client/views/StyleProvider.tsx        | 10 +++++++
 src/client/views/collections/TreeView.tsx | 46 +++++++++++++++++--------------
 src/client/views/nodes/FilterBox.tsx      |  2 ++
 3 files changed, 37 insertions(+), 21 deletions(-)

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

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index a530ff90a..ca9826ab9 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -24,6 +24,7 @@ import { SliderBox } from './nodes/SliderBox';
 import "./StyleProvider.scss";
 import React = require("react");
 import { InkingStroke } from './InkingStroke';
+import { TreeSort } from './collections/TreeView';
 
 export enum StyleLayers {
     Background = "background"
@@ -31,6 +32,7 @@ export enum StyleLayers {
 
 export enum StyleProp {
     TreeViewIcon = "treeViewIcon",
+    TreeViewSortings = "treeViewSortings",// options for how to sort tree view items
     DocContents = "docContents",          // when specified, the JSX returned will replace the normal rendering of the document view
     Opacity = "opacity",                  // opacity of the document view
     Hidden = "hidden",                    // whether the document view should not be isplayed
@@ -98,6 +100,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 return <img src={url} width={20} height={15} style={{ margin: "auto", display: "block", objectFit: "contain" }} />;
             }
             return Doc.toIcon(doc, isOpen);
+
+        case StyleProp.TreeViewSortings:
+            const allSorts: { [key: string]: { color: string, label: string } | undefined } = {};
+            allSorts[TreeSort.Down] = { color: "blue", label: "↓" };
+            allSorts[TreeSort.Up] = { color: "crimson", label: "↑" };
+            if (doc?._viewType === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: "green", label: "z" };
+            allSorts[TreeSort.None] = { color: "darkgray", label: '\u00A0\u00A0\u00A0' };
+            return allSorts;
         case StyleProp.DocContents: return undefined;
         case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? "lightgrey" : "dimgrey";
         case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 647476784..72480b094 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -67,7 +67,12 @@ export interface TreeViewProps {
 
 const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("px", "")); };
 
-@observer
+export enum TreeSort {
+    Up = "up",
+    Down = "down",
+    Zindex = "z",
+    None = "none"
+};
 /**
  * Renders a treeView of a collection of documents
  * 
@@ -75,11 +80,11 @@ const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("p
  * treeViewOpen : flag denoting whether the documents sub-tree (contents) is visible or hidden
  * treeViewExpandedView : name of field whose contents are being displayed as the document's subtree
  */
+@observer
 export class TreeView extends React.Component<TreeViewProps> {
     static _editTitleOnLoad: Opt<{ id: string, parent: TreeView | CollectionTreeView | undefined }>;
     static _openTitleScript: Opt<ScriptField | undefined>;
     static _openLevelScript: Opt<ScriptField | undefined>;
-    static _sortUIMap = [["up", "crimson", "↑"], ["down", "blue", "↓"], ["z", "green", "z"], ["x", "darkgray", '\u00A0\u00A0\u00A0']];
     private _header: React.RefObject<HTMLDivElement> = React.createRef();
     private _tref = React.createRef<HTMLDivElement>();
     @observable _docRef: Opt<DocumentView>;
@@ -410,17 +415,18 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get renderContent() {
         TraceMobx();
         const expandKey = this.treeViewExpandedView;
+        const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string, label: string } };
         if (["links", "annotations", "aliases", this.fieldKey].includes(expandKey)) {
-            const sorting = StrCast(this.doc.treeViewSortCriterion);
-            const color = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[1];
-            const label = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[2];
+            const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
+            const sortKeys = Object.keys(sortings);
+            const curSortIndex = Math.max(0, sortKeys.findIndex(val => val === sorting));
             const key = (expandKey === "annotations" ? `${this.fieldKey}-` : "") + expandKey;
             const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
             const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
                 // if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't),
                 // then the modification would be done here
                 const ordering = StrCast(this.doc.treeViewSortCriterion);
-                if (ordering === "z") {
+                if (ordering === TreeSort.Zindex) {
                     const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering);
                     doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000;
                     docs.push(doc);
@@ -433,17 +439,15 @@ export class TreeView extends React.Component<TreeViewProps> {
             const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
             const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
             let downX = 0, downY = 0;
-            const sortings = this.props.treeView.rootDoc === Doc.UserDoc().myFilesystem ? ["up", "down", "x"] : ["up", "down", "z", "x"];
-            const curSort = Math.max(0, sortings.indexOf(Cast(this.doc.treeViewSortCriterion, "string", null)));
             return <>
-                {!docs?.length ? (null) : <div className={'treeView-sorting'} style={{ background: color }} >
-                    {label}
+                {!docs?.length ? (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" : ""}
                     onPointerDown={e => { downX = e.clientX; downY = e.clientY; e.stopPropagation(); }}
                     onClick={(e) => {
                         if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
-                            !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortings[(curSort + 1) % sortings.length]);
+                            !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
                             e.stopPropagation();
                         }
                     }}>
@@ -791,9 +795,9 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     @computed get renderBorder() {
-        const sorting = StrCast(this.doc.treeViewSortCriterion);
-        const color = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[1];
-        return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`} style={{ borderColor: color }}>
+        const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
+        const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string, label: string } };
+        return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`} style={{ borderColor: sortings[sorting]?.color }}>
             {!this.treeViewOpen ? (null) : this.renderContent}
         </div>;
     }
@@ -827,11 +831,11 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     public static sortDocs(childDocs: Doc[], criterion: string | undefined) {
         const docs = childDocs.slice();
-        if (criterion) {
+        if (criterion !== TreeSort.None) {
             const sortAlphaNum = (a: string, b: string): 0 | 1 | -1 => {
                 const reN = /[0-9]*$/;
-                const aA = a.replace(reN, ""); // get rid of trailing numbers
-                const bA = b.replace(reN, "");
+                const aA = a.replace(reN, "") ? a.replace(reN, "") : +a; // get rid of trailing numbers
+                const bA = b.replace(reN, "") ? b.replace(reN, "") : +b;
                 if (aA === bA) {  // if header string matches, then compare numbers numerically
                     const aN = parseInt(a.match(reN)![0], 10);
                     const bN = parseInt(b.match(reN)![0], 10);
@@ -841,10 +845,10 @@ export class TreeView extends React.Component<TreeViewProps> {
                 }
             };
             docs.sort(function (d1, d2): 0 | 1 | -1 {
-                const a = (criterion === "up" ? d2 : d1);
-                const b = (criterion === "down" ? d1 : d2);
-                const first = a[criterion === "z" ? "zIndex" : "title"];
-                const second = b[criterion === "z" ? "zIndex" : "title"];
+                const a = (criterion === TreeSort.Up ? d2 : d1);
+                const b = (criterion === TreeSort.Up ? d1 : d2);
+                const first = a[criterion === TreeSort.Zindex ? "zIndex" : "title"];
+                const second = b[criterion === TreeSort.Zindex ? "zIndex" : "title"];
                 if (typeof first === 'number' && typeof second === 'number') return (first - second) > 0 ? 1 : -1;
                 if (typeof first === 'string' && typeof second === 'string') return sortAlphaNum(first, second);
                 return criterion ? 1 : -1;
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index ba65acee0..dc0ab5ec2 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -386,6 +386,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     options={options}
                     isMulti={false}
                     onChange={val => this.facetClick((val as UserOptions).value)}
+                    onKeyDown={e => e.stopPropagation()}
                     value={null}
                     closeMenuOnSelect={true}
                 />
@@ -420,6 +421,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     whenChildContentsActiveChanged={returnFalse}
                     treeViewHideTitle={true}
                     focus={returnFalse}
+                    onCheckedClick={this.scriptField}
                     treeViewHideHeaderFields={false}
                     dontRegisterView={true}
                     styleProvider={this.FilterStyleProvider}
-- 
cgit v1.2.3-70-g09d2


From f072a9f2c1ad69eb8ae4242fa5d2e18bbd94f6ef Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 6 May 2022 11:45:44 -0400
Subject: changed following links to open up icons all the way down to the
 target document. allow StartLink to work with webBox w/ text selection. 
 fixed web clippings to have a cursor and grab keyDown events.

---
 src/client/util/DocumentManager.ts                 | 42 +++++++++++++++-------
 .../util/Import & Export/DirectoryImportBox.tsx    |  2 +-
 src/client/util/LinkManager.ts                     | 11 +++---
 src/client/util/SharingManager.tsx                 | 30 ++++++++--------
 src/client/views/DocumentDecorations.tsx           | 13 ++++---
 src/client/views/MainView.tsx                      |  2 +-
 src/client/views/collections/TabDocView.tsx        |  2 +-
 src/client/views/collections/TreeView.tsx          |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 .../collectionLinear/CollectionLinearView.tsx      |  2 +-
 .../collectionSchema/CollectionSchemaCells.tsx     |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  3 +-
 src/client/views/nodes/LinkDescriptionPopup.tsx    |  1 +
 src/client/views/nodes/PDFBox.tsx                  |  1 +
 src/client/views/nodes/WebBox.scss                 |  3 ++
 src/client/views/nodes/WebBox.tsx                  | 11 +++---
 src/client/views/nodes/trails/PresBox.tsx          |  4 +--
 src/client/views/search/SearchBox.tsx              |  2 +-
 18 files changed, 84 insertions(+), 51 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index b6c28d2fe..aeddc3249 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -156,7 +156,7 @@ export class DocumentManager {
         targetDoc: Doc,        // document to display
         willZoom: boolean,     // whether to zoom doc to take up most of screen
         createViewFunc = DocumentManager.addView, // how to create a view of the doc if it doesn't exist
-        docContext?: Doc,  // context to load that should contain the target
+        docContext: Doc[],  // context to load that should contain the target
         linkDoc?: Doc,   // link that's being followed
         closeContextIfNotFound: boolean = false, // after opening a context where the document should be, this determines whether the context should be closed if the Doc isn't actually there
         originatingDoc: Opt<Doc> = undefined, // doc that initiated the display of the target odoc
@@ -190,31 +190,40 @@ export class DocumentManager {
             finished?.();
         };
         const annoContainerView = (!wasHidden || resolvedTarget !== annotatedDoc) && annotatedDoc && getFirstDocView(annotatedDoc);
-        const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined;
-        const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined;
+        const contextDocs = docContext.length ? await DocListCastAsync(docContext[0].data) : undefined;
+        const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext.lastElement() : undefined;
         const targetDocContext = contextDoc || annotatedDoc;
         const targetDocContextView = (targetDocContext && getFirstDocView(targetDocContext)) ||
             (wasHidden && annoContainerView);// if we have an annotation container and the target was hidden, then try again because we just un-hid the document above
         const focusView = !docView && targetDoc.type === DocumentType.MARKER && annoContainerView ? annoContainerView : docView;
-        if ((!docView && targetDoc.type !== DocumentType.MARKER) && annoContainerView) {
+        if (annoContainerView) {
             if (annoContainerView.props.Document.layoutKey === "layout_icon") {
-                annoContainerView.iconify(() => this.jumpToDocument(
-                    targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc,
-                    finished, originalTarget, noSelect, presZoom));
+                annoContainerView.iconify(() => annoContainerView.focus(targetDoc, {
+                    originalTarget, willZoom, scale: presZoom, afterFocus: (didFocus: boolean) =>
+                        new Promise<ViewAdjustment>(res => {
+                            focusAndFinish(true);
+                            res(ViewAdjustment.doNothing);
+                        })
+                }));
                 return;
-            } else {
+            } else if (!docView && targetDoc.type !== DocumentType.MARKER) {
                 annoContainerView.focus(targetDoc);  // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
             }
         }
         if (focusView) {
             !noSelect && Doc.linkFollowHighlight(focusView.rootDoc); //TODO:glr make this a setting in PresBox
-            focusView.focus(targetDoc, {
+            const doFocus = (forceDidFocus: boolean) => focusView.focus(originalTarget ?? targetDoc, {
                 originalTarget, willZoom, scale: presZoom, afterFocus: (didFocus: boolean) =>
                     new Promise<ViewAdjustment>(res => {
-                        focusAndFinish(didFocus);
+                        focusAndFinish(forceDidFocus || didFocus);
                         res(ViewAdjustment.doNothing);
                     })
             });
+            if (focusView.props.Document.layoutKey === "layout_icon") {
+                focusView.iconify(() => doFocus(true));
+            } else {
+                doFocus(false);
+            }
         } else {
             if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default
                 createViewFunc(Doc.BrushDoc(targetDoc), finished); // bcz: should we use this?: Doc.MakeAlias(targetDoc)));
@@ -228,7 +237,7 @@ export class DocumentManager {
                             targetDocContext._viewTransition = undefined;
                             if (targetDocContext.layoutKey === "layout_icon") {
                                 targetDocContextView.iconify(() => this.jumpToDocument(
-                                    targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc,
+                                    resolvedTarget ?? targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc,
                                     finished, originalTarget, noSelect, presZoom));
                             }
                             return ViewAdjustment.doNothing;
@@ -263,7 +272,16 @@ export class DocumentManager {
                         };
                         setTimeout(() => findView(0), 0);
                     }
-                } else {  // there's no context view so we need to create one first and try again when that finishes
+                } else {
+                    if (docContext.length && docContext[0]?.layoutKey === "layout_icon") {
+                        const docContextView = this.getFirstDocumentView(docContext[0]);
+                        if (docContextView) {
+                            return docContextView.iconify(() => this.jumpToDocument(
+                                targetDoc, willZoom, createViewFunc, docContext.slice(1, docContext.length), linkDoc, closeContextIfNotFound, originatingDoc,
+                                finished, originalTarget, noSelect, presZoom));
+                        }
+                    }
+                    // there's no context view so we need to create one first and try again when that finishes
                     const finishFunc = () => this.jumpToDocument(targetDoc, true, createViewFunc, docContext, linkDoc, true /* if we don't find the target, we want to get rid of the context just created */, undefined, finished, originalTarget);
                     createViewFunc(targetDocContext, // after creating the context, this calls the finish function that will retry looking for the target
                         finishFunc);
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 39e9251a5..37571ae01 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx	
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx	
@@ -161,7 +161,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
             await GooglePhotos.Export.CollectionToAlbum({ collection: importContainer });
             Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer);
             !this.persistent && this.props.removeDocument && this.props.removeDocument(doc);
-            DocumentManager.Instance.jumpToDocument(importContainer, true);
+            DocumentManager.Instance.jumpToDocument(importContainer, true, undefined, []);
         }
 
         runInAction(() => {
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 9445533dc..b28662a57 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -1,3 +1,4 @@
+import { validationResult } from "express-validator/check";
 import { action, observable, observe } from "mobx";
 import { computedFn } from "mobx-utils";
 import { DirectLinksSym, Doc, DocListCast, Field, Opt } from "../../fields/Doc";
@@ -241,10 +242,12 @@ export class LinkManager {
                     } else {
                         const containerAnnoDoc = Cast(target.annotationOn, Doc, null);
                         const containerDoc = containerAnnoDoc || target;
-                        const containerDocContext = Cast(containerDoc?.context, Doc, null);
-                        const targetContext = LightboxView.LightboxDoc ? containerAnnoDoc || containerDocContext : containerDocContext;
-                        const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
-                        DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetNavContext, linkDoc, undefined, sourceDoc, allFinished);
+                        var containerDocContext = containerDoc?.context ? [Cast(containerDoc?.context, Doc, null)] : [] as Doc[];
+                        while (containerDocContext.length && !DocumentManager.Instance.getDocumentView(containerDocContext[0]) && containerDocContext[0].context) {
+                            containerDocContext = [Cast(containerDocContext[0].context, Doc, null), ...containerDocContext];
+                        }
+                        const targetContexts = LightboxView.LightboxDoc ? [containerAnnoDoc || containerDocContext[0]] : containerDocContext;
+                        DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetContexts, linkDoc, undefined, sourceDoc, allFinished);
                     }
                 } else {
                     allFinished();
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 6d7f7e8df..11450309a 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -370,11 +370,11 @@ export class SharingManager extends React.Component<{}> {
         if (!uniform) dropdownValues.unshift("-multiple-");
         if (override) dropdownValues.unshift("None");
         return dropdownValues.filter(permission => !Doc.UserDoc().noviceMode || ![SharingPermissions.View, SharingPermissions.SelfEdit].includes(permission as any)).map(permission =>
-            (
-                <option key={permission} value={permission}>
-                    {permission}
-                </option>
-            )
+        (
+            <option key={permission} value={permission}>
+                {permission}
+            </option>
+        )
         );
     }
 
@@ -388,7 +388,7 @@ export class SharingManager extends React.Component<{}> {
                 onClick={() => {
                     let context: Opt<CollectionView>;
                     if (this.targetDoc && this.targetDocView && docs.length === 1 && (context = this.targetDocView.props.ContainingCollectionView)) {
-                        DocumentManager.Instance.jumpToDocument(this.targetDoc, true, undefined, context.props.Document);
+                        DocumentManager.Instance.jumpToDocument(this.targetDoc, true, undefined, [context.props.Document]);
                     }
                 }}
                 onPointerEnter={action(() => {
@@ -548,10 +548,10 @@ export class SharingManager extends React.Component<{}> {
                                 {this.sharingOptions(uniform)}
                             </select>
                         ) : (
-                                <div className={"permissions-dropdown"}>
-                                    {permissions}
-                                </div>
-                            )}
+                            <div className={"permissions-dropdown"}>
+                                {permissions}
+                            </div>
+                        )}
                     </div>
                 </div>
             );
@@ -572,7 +572,7 @@ export class SharingManager extends React.Component<{}> {
                         <div className="edit-actions">
                             <div className={"permissions-dropdown"}>
                                 Owner
-                        </div>
+                            </div>
                         </div>
                     </div>
                 ) : null,
@@ -622,10 +622,10 @@ export class SharingManager extends React.Component<{}> {
                                 {this.sharingOptions(uniform, group.title === "Override")}
                             </select>
                         ) : (
-                                <div className={"permissions-dropdown"}>
-                                    {permissions}
-                                </div>
-                            )}
+                            <div className={"permissions-dropdown"}>
+                                {permissions}
+                            </div>
+                        )}
                     </div>
                 </div>
             );
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index eb2bcc18c..936946df0 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -113,7 +113,12 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
         }
     }
 
-    titleEntered = (e: React.KeyboardEvent) => e.key === "Enter" && (e.target as any).blur();
+    titleEntered = (e: React.KeyboardEvent) => {
+        if (e.key === "Enter") {
+            e.stopPropagation();
+            (e.target as any).blur();
+        }
+    }
 
     @action onTitleDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), (e) => { }, action((e) => {
@@ -288,7 +293,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
         if (fixedAspect && (resizeHdl === "documentDecorations-bottomRightResizer" || resizeHdl === "documentDecorations-topLeftResizer")) { // need to generalize for bl and tr drag handles
             const project = (p: number[], a: number[], b: number[]) => {
                 const atob = [b[0] - a[0], b[1] - a[1]];
-                const atop = [p[0] - a[0], p[1] - a[1]]; first
+                const atop = [p[0] - a[0], p[1] - a[1]];
                 const len = atob[0] * atob[0] + atob[1] * atob[1];
                 let dot = atop[0] * atob[0] + atop[1] * atob[1];
                 const t = dot / len;
@@ -501,7 +506,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
                     value={this._accumulatedTitle}
                     onBlur={e => this.titleBlur()}
                     onChange={action(e => this._accumulatedTitle = e.target.value)}
-                    onKeyPress={this.titleEntered} /> :
+                    onKeyDown={this.titleEntered} /> :
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
                     <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
                 </div>;
@@ -521,7 +526,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
         const useRotation = seldoc.ComponentView instanceof InkingStroke || seldoc.ComponentView instanceof ImageBox;
         const resizerScheme = colorScheme ? "documentDecorations-resizer" + colorScheme : "";
 
-        const rotation = NumCast(seldoc.rootDoc._jitterRotation)
+        const rotation = NumCast(seldoc.rootDoc._jitterRotation);
         const rdeg = rotation / 180 * Math.PI;
 
         return (<div className={`documentDecorations${colorScheme}`}>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index c794c73db..db51c54f8 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -133,7 +133,7 @@ export class MainView extends React.Component {
         window.addEventListener("paste", KeyManager.Instance.paste as any);
         document.addEventListener("dash", (e: any) => {  // event used by chrome plugin to tell Dash which document to focus on
             const id = FormattedTextBox.GetDocFromUrl(e.detail);
-            DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined) : (null));
+            DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined, []) : (null));
         });
         document.addEventListener("linkAnnotationToDash", Hypothesis.linkListener);
         this.initEventListeners();
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 78b125e07..8dfc7edc7 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -256,7 +256,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 }
                 PresBox.Instance?._selectedArray.clear();
                 pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
-                DocumentManager.Instance.jumpToDocument(doc, false, undefined);
+                DocumentManager.Instance.jumpToDocument(doc, false, undefined, []);
                 batch.end();
             });
         }
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 72480b094..164021358 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -72,7 +72,7 @@ export enum TreeSort {
     Down = "down",
     Zindex = "z",
     None = "none"
-};
+}
 /**
  * Renders a treeView of a collection of documents
  * 
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 5d1e1892c..5b3a7db41 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1423,7 +1423,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     }
 
     replaceCanvases = (oldDiv: HTMLElement, newDiv: HTMLElement) => {
-        if (oldDiv.childNodes) {
+        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);
             }
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index e3d4f86c1..c615bfb8e 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -231,7 +231,7 @@ export class CollectionLinearView extends CollectionSubView() {
                         <span className="bottomPopup-text">
                             Currently playing:
                             {CollectionStackedTimeline.CurrentlyPlaying.map((clip, i) =>
-                                <span className="audio-title" onPointerDown={() => DocumentManager.Instance.jumpToDocument(clip, true)}>
+                                <span className="audio-title" onPointerDown={() => DocumentManager.Instance.jumpToDocument(clip, true, undefined, [])}>
                                     {clip.title + (i === CollectionStackedTimeline.CurrentlyPlaying.length - 1 ? "" : ",")}
                                 </span>)}
                         </span>
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
index c2bb3b3ac..adcd9e1e3 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
@@ -199,7 +199,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             const aliasdoc = await SearchUtil.GetAliasesOfDocument(this._rowDataDoc);
             const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null);
             // Jump to the this document
-            DocumentManager.Instance.jumpToDocument(this._rowDoc, false, emptyFunction, targetContext,
+            DocumentManager.Instance.jumpToDocument(this._rowDoc, false, emptyFunction, targetContext ? [targetContext] : [],
                 undefined, undefined, undefined, () => this.props.setPreviewDoc(this._rowDoc));
         }
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8570f6fff..02ea87103 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -663,7 +663,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             }
             if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) {
                 const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.() ?? this.props.Document;
-                de.complete.linkDocument = DocUtils.MakeLink({ doc: linkdrag.linkSourceDoc }, { doc: dropDoc }, undefined, undefined, undefined, undefined, [de.x, de.y]);
+                de.complete.linkDocument = DocUtils.MakeLink({ doc: linkdrag.linkSourceDoc }, { doc: dropDoc }, undefined, undefined, undefined, undefined, [de.x, de.y - 50]);
             }
         }
     }
@@ -857,6 +857,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     }
     @observable _retryThumb = 1;
     thumbShown = () => !this.props.isSelected() && LightboxView.LightboxDoc !== this.rootDoc && this.thumb &&
+        !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) &&
         !this._componentView?.isAnyChildContentActive?.() ? true : false
     @computed get contents() {
         TraceMobx();
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx
index a9d33f161..ccac66996 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.tsx
+++ b/src/client/views/nodes/LinkDescriptionPopup.tsx
@@ -54,6 +54,7 @@ export class LinkDescriptionPopup extends React.Component<{}> {
                 top: LinkDescriptionPopup.popupY ? LinkDescriptionPopup.popupY : 350,
             }}>
             <input className="linkDescriptionPopup-input"
+                onKeyDown={e => e.stopPropagation()}
                 onKeyPress={e => e.key === "Enter" && this.onDismiss(true)}
                 placeholder={"(Optional) Enter link description..."}
                 onChange={(e) => this.descriptionChanged(e)}>
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 69662d53a..48465976a 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -75,6 +75,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     updateIcon = () => {
+        return; // currently we render pdf icons as text labels
         const docViewContent = this.props.docViewPath().lastElement().ContentDiv!;
         const newDiv = docViewContent.cloneNode(true) as HTMLDivElement;
         newDiv.style.width = (this.layoutDoc[WidthSym]()).toString();
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index b037e7220..d8dd074a5 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -156,6 +156,9 @@
             position: absolute;
             top: 0;
             left: 0;
+            cursor: text;
+            padding: 15px;
+            height: 100%
         }
 
         .webBox-cont {
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 80961c92f..f441e5d36 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -207,8 +207,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     @action
-    createTextAnnotation = (sel: Selection, selRange: Range) => {
-        if (this._mainCont.current) {
+    createTextAnnotation = (sel: Selection, selRange: Range | undefined) => {
+        if (this._mainCont.current && selRange) {
             const clientRects = selRange.getClientRects();
             for (let i = 0; i < clientRects.length; i++) {
                 const rect = clientRects.item(i);
@@ -235,7 +235,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     menuControls = () => this.urlEditor; // controls to be added to the top bar when a document of this type is selected
 
     scrollFocus = (doc: Doc, smooth: boolean) => {
-        this.props.select(true);
+        this.props.select(false); // hack to preven the webBox from being replaced with a thumbnail that currently doesn't show the the anchors
         if (StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl), !smooth);
         if (DocListCast(this.props.Document[this.fieldKey + "-sidebar"]).includes(doc) && !this.SidebarShown) {
             this.toggleSidebar(!smooth);
@@ -252,7 +252,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             }
         }
         this._initialScroll = NumCast(this.layoutDoc._scrollTop);
-        return 0;
+        return undefined;
     }
 
     getAnchor = () => {
@@ -279,7 +279,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             const scale = (this.props.scaling?.() || 1) * mainContBounds.scale;
             const sel = this._iframe.contentWindow.getSelection();
             if (sel) {
-                this._textAnnotationCreator = () => this.createTextAnnotation(sel, sel.getRangeAt(0));
+                this._textAnnotationCreator = () => this.createTextAnnotation(sel, !sel.isCollapsed ? sel.getRangeAt(0) : undefined);
                 AnchorMenu.Instance.jumpTo(e.clientX * scale + mainContBounds.translateX,
                     e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._scrollTop) * scale);
             }
@@ -650,6 +650,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     @computed get content() {
         const interactive = !this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.props.isContentActive() && this.props.pointerEvents !== "none" && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting;
         return <div className={"webBox-cont" + (interactive ? "-interactive" : "")}
+            onKeyDown={e => e.stopPropagation()}
             style={{ width: !this.layoutDoc.forceReflow ? NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]) || `100%` : "100%", }}>
             {this.urlContent}
         </div>;
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 30ad43562..820d7ef96 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -389,11 +389,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             LightboxView.SetLightboxDoc(targetDoc);
         } else if (curDoc.presMovement === PresMovement.Pan && targetDoc) {
             LightboxView.SetLightboxDoc(undefined);
-            await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right
+            await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, [srcContext], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right
         } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) {
             LightboxView.SetLightboxDoc(undefined);
             //awaiting jump so that new scale can be found, since jumping is async     
-            await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true, NumCast(curDoc.presZoom)); // documents open in new tab instead of on right    
+            await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, [srcContext], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true, NumCast(curDoc.presZoom)); // documents open in new tab instead of on right    
         }
         // After navigating to the document, if it is added as a presPinView then it will
         // adjust the pan and scale to that of the pinView when it was added.
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 9257cb75e..3d36efbc4 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -365,7 +365,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
      * or opening it in a new tab.
      */
     selectElement = async (doc: Doc, finishFunc: () => void) => {
-        await DocumentManager.Instance.jumpToDocument(doc, true, undefined, undefined, undefined, undefined, undefined, finishFunc);
+        await DocumentManager.Instance.jumpToDocument(doc, true, undefined, [], undefined, undefined, undefined, finishFunc);
     }
 
     /**
-- 
cgit v1.2.3-70-g09d2


From 57c1b8235b26a1b6a315922b4dc2926e1e597674 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 13 May 2022 18:17:10 -0400
Subject: removed layerProvider functionality.

---
 src/client/documents/Documents.ts                  |  3 +-
 src/client/views/DocComponent.tsx                  |  4 --
 src/client/views/GestureOverlay.tsx                |  1 -
 src/client/views/InkingStroke.tsx                  |  2 +-
 src/client/views/LightboxView.tsx                  |  1 -
 src/client/views/MainView.tsx                      |  6 ---
 src/client/views/OverlayView.tsx                   |  1 -
 src/client/views/Palette.tsx                       |  1 -
 src/client/views/PropertiesView.tsx                |  2 -
 src/client/views/StyleProvider.tsx                 | 52 +++-------------------
 src/client/views/TemplateMenu.tsx                  |  1 -
 src/client/views/collections/CollectionMenu.tsx    |  1 -
 .../collections/CollectionStackedTimeline.tsx      |  2 +-
 .../views/collections/CollectionStackingView.tsx   |  2 -
 .../views/collections/CollectionTreeView.tsx       |  1 -
 src/client/views/collections/CollectionView.tsx    |  2 +-
 src/client/views/collections/TabDocView.tsx        | 19 +-------
 src/client/views/collections/TreeView.tsx          |  2 -
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 24 +++++-----
 .../collections/collectionFreeForm/MarqueeView.tsx | 10 ++---
 .../collectionLinear/CollectionLinearView.tsx      |  1 -
 .../CollectionMulticolumnView.tsx                  |  1 -
 .../CollectionMultirowView.tsx                     |  1 -
 .../collectionSchema/CollectionSchemaView.tsx      |  1 -
 .../collections/collectionSchema/SchemaTable.tsx   |  1 -
 src/client/views/linking/LinkPopup.tsx             |  3 +-
 src/client/views/nodes/AudioBox.tsx                |  2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  2 -
 src/client/views/nodes/DocumentView.tsx            |  5 +--
 src/client/views/nodes/FilterBox.tsx               |  1 -
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 src/client/views/nodes/KeyValuePair.tsx            |  1 -
 src/client/views/nodes/LinkAnchorBox.tsx           |  1 -
 src/client/views/nodes/LinkDocPreview.tsx          |  1 -
 src/client/views/nodes/VideoBox.tsx                |  2 +-
 src/client/views/nodes/WebBox.tsx                  |  6 +--
 .../views/nodes/formattedText/DashDocView.tsx      |  1 -
 .../views/nodes/formattedText/FormattedTextBox.tsx |  2 +-
 src/client/views/nodes/trails/PresBox.tsx          |  2 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |  1 -
 src/client/views/pdf/Annotation.tsx                |  2 +-
 src/client/views/search/SearchBox.tsx              |  2 +-
 src/fields/Doc.ts                                  |  2 +-
 src/mobile/AudioUpload.tsx                         |  1 -
 src/mobile/MobileInterface.tsx                     |  1 -
 src/server/server_Initialization.ts                |  2 +-
 46 files changed, 41 insertions(+), 143 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d9c2e0d8b..797a129c4 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -122,7 +122,6 @@ export class DocumentOptions {
     _scrollTop?: number; // scroll location for pdfs
     _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged
     _chromeHidden?: boolean; // whether the editing chrome for a document is hidden
-    _layerTags?: List<string>; // layer tags a document has (used for tab filtering "layers" in document tab)
     _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view)
     _forceActive?: boolean; // flag to handle pointer events when not selected (or otherwise active)
     _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere
@@ -426,7 +425,7 @@ export namespace Docs {
                     childDontRegisterViews: true, _isLinkButton: true, _height: 150, description: "", showCaption: "description",
                     backgroundColor: "lightblue", // lightblue is default color for linking dot and link documents text comment area
                     links: "@links(self)",
-                    _removeDropProperties: new List(["_layerTags", "isLinkButton"]),
+                    _removeDropProperties: new List(["isLinkButton"]),
                 }
             }],
             [DocumentType.LINKDB, {
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 79aaf2158..9c176a4fd 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -44,7 +44,6 @@ interface ViewBoxBaseProps {
     ContainingCollectionDoc: Opt<Doc>;
     DocumentView?: () => DocumentView;
     fieldKey: string;
-    layerProvider?: (doc: Doc, assign?: boolean) => boolean;
     isSelected: (outsideReaction?: boolean) => boolean;
     isContentActive: () => boolean | undefined;
     renderDepth: number;
@@ -85,7 +84,6 @@ export interface ViewBoxAnnotatableProps {
     DataDoc?: Doc;
     fieldKey: string;
     filterAddDocument?: (doc: Doc[]) => boolean;  // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
-    layerProvider?: (doc: Doc, assign?: boolean) => boolean;
     isContentActive: () => boolean | undefined;
     select: (isCtrlPressed: boolean) => void;
     whenChildContentsActiveChanged: (isActive: boolean) => void;
@@ -209,13 +207,11 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
                             if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))) inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc);
                             doc.context = this.props.Document;
                             if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document;
-                            this.props.layerProvider?.(doc, true);
                             Doc.AddDocToList(targetDataDoc, annotationKey ?? this.annotationKey, doc);
                         });
                     }
                     else {
                         added.filter(doc => [AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))).map(doc => {  // only make a pushpin if we have acl's to edit the document
-                            this.props.layerProvider?.(doc, true);
                             //DocUtils.LeavePushpin(doc);
                             doc._stayInCollection = undefined;
                             doc.context = this.props.Document;
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 50dca0a99..482b62479 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -881,7 +881,6 @@ export class GestureOverlay extends Touchable {
                 isContentActive={returnFalse}
                 renderDepth={0}
                 styleProvider={returnEmptyString}
-                layerProvider={undefined}
                 docViewPath={returnEmptyDoclist}
                 focus={DocUtils.DefaultFocus}
                 whenChildContentsActiveChanged={emptyFunction}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 3d9c048e5..d0f01c363 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -332,7 +332,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
             inkStrokeWidth, inkStrokeWidth + (highlightIndex && closed && fillColor && (new Color(fillColor)).alpha() < 1 ? 6 : 15),
             StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap),
             StrCast(this.layoutDoc.strokeBezier), !closed ? "none" : fillColor === "transparent" || suppressFill ? "none" : fillColor, startMarker, endMarker,
-            markerScale, undefined, inkScaleX, inkScaleY, "", this.props.pointerEvents?.() ?? (this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted"), 0.0,
+            markerScale, undefined, inkScaleX, inkScaleY, "", this.props.pointerEvents?.() ?? (this.rootDoc._lockedPosition ? "none" : "visiblepainted"), 0.0,
             false, downHdlr);
         const fsize = +(StrCast(this.props.Document.fontSize, "12px").replace("px", ""));
         // bootsrap 3 style sheet sets line height to be 20px for default 14 point font size. 
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 59ed0dc92..9882693ee 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -246,7 +246,6 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                         docFilters={this.docFilters}
                         removeDocument={undefined}
                         styleProvider={DefaultStyleProvider}
-                        layerProvider={returnTrue}
                         ScreenToLocalTransform={this.lightboxScreenToLocal}
                         PanelWidth={this.lightboxWidth}
                         PanelHeight={this.lightboxHeight}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index db51c54f8..2e1d10955 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -281,7 +281,6 @@ export class MainView extends React.Component {
             addDocTab={this.addDocTabFunc}
             pinToPres={emptyFunction}
             docViewPath={returnEmptyDoclist}
-            layerProvider={undefined}
             styleProvider={undefined}
             rootSelected={returnTrue}
             isContentActive={returnTrue}
@@ -361,7 +360,6 @@ export class MainView extends React.Component {
                         addDocTab={this.addDocTabFunc}
                         pinToPres={emptyFunction}
                         docViewPath={returnEmptyDoclist}
-                        layerProvider={undefined}
                         styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards || this._sidebarContent.proto === Doc.UserDoc().myFilesystem ? DashboardStyleProvider : DefaultStyleProvider}
                         rootSelected={returnTrue}
                         removeDocument={returnFalse}
@@ -402,7 +400,6 @@ export class MainView extends React.Component {
                 docViewPath={returnEmptyDoclist}
                 focus={DocUtils.DefaultFocus}
                 styleProvider={DefaultStyleProvider}
-                layerProvider={undefined}
                 isContentActive={returnTrue}
                 whenChildContentsActiveChanged={emptyFunction}
                 bringToFront={emptyFunction}
@@ -516,7 +513,6 @@ export class MainView extends React.Component {
                     dropAction={"alias"}
                     setHeight={returnFalse}
                     styleProvider={DefaultStyleProvider}
-                    layerProvider={undefined}
                     rootSelected={returnTrue}
                     bringToFront={emptyFunction}
                     select={emptyFunction}
@@ -591,7 +587,6 @@ export class MainView extends React.Component {
                     ContainingCollectionDoc={undefined}
                     Document={DocumentLinksButton.invisibleWebDoc}
                     dropAction={"move"}
-                    layerProvider={undefined}
                     styleProvider={undefined}
                     isSelected={returnFalse}
                     select={returnFalse}
@@ -673,7 +668,6 @@ export class MainView extends React.Component {
                             rootSelected={returnFalse}
                             renderDepth={0}
                             setHeight={returnFalse}
-                            layerProvider={undefined}
                             styleProvider={undefined}
                             addDocTab={returnFalse}
                             pinToPres={returnFalse}
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 0f51cf9b2..ebad2981d 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -195,7 +195,6 @@ export class OverlayView extends React.Component {
                     whenChildContentsActiveChanged={emptyFunction}
                     focus={DocUtils.DefaultFocus}
                     styleProvider={DefaultStyleProvider}
-                    layerProvider={undefined}
                     docViewPath={returnEmptyDoclist}
                     addDocTab={returnFalse}
                     pinToPres={emptyFunction}
diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx
index 529697f71..954529bc9 100644
--- a/src/client/views/Palette.tsx
+++ b/src/client/views/Palette.tsx
@@ -54,7 +54,6 @@ export default class Palette extends React.Component<PaletteProps> {
                             focus={emptyFunction}
                             docViewPath={returnEmptyDoclist}
                             styleProvider={returnEmptyString}
-                            layerProvider={undefined}
                             whenChildContentsActiveChanged={emptyFunction}
                             bringToFront={emptyFunction}
                             docFilters={returnEmptyFilter}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 21c688421..bba2ac211 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -303,7 +303,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     fitContentsToDoc={returnTrue}
                     rootSelected={returnFalse}
                     styleProvider={DefaultStyleProvider}
-                    layerProvider={undefined}
                     docViewPath={returnEmptyDoclist}
                     freezeDimensions={true}
                     dontCenter={"y"}
@@ -1010,7 +1009,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             createNewFilterDoc={this.createNewFilterDoc}
                             updateFilterDoc={this.updateFilterDoc}
                             docViewPath={returnEmptyDoclist}
-                            layerProvider={undefined}
                             dontCenter="y"
                         />
                     </div>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 5056dedaf..334415b38 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -26,10 +26,6 @@ import React = require("react");
 import { InkingStroke } from './InkingStroke';
 import { TreeSort } from './collections/TreeView';
 
-export enum StyleLayers {
-    Background = "background"
-}
-
 export enum StyleProp {
     TreeViewIcon = "treeViewIcon",
     TreeViewSortings = "treeViewSortings",// options for how to sort tree view items
@@ -56,14 +52,9 @@ export enum StyleProp {
 
 function darkScheme() { return CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark; }
 
-function toggleBackground(doc: Doc) {
+function toggleLockedPosition(doc: Doc) {
     UndoManager.RunInBatch(() => runInAction(() => {
-        const layers = StrListCast(doc._layerTags);
-        if (!layers.includes(StyleLayers.Background)) {
-            if (!layers.length) doc._layerTags = new List<string>([StyleLayers.Background]);
-            else layers.push(StyleLayers.Background);
-        }
-        else layers.splice(layers.indexOf(StyleLayers.Background), 1);
+        doc._lockedPosition = !doc._lockedPosition;
     }), "toggleBackground");
 }
 
@@ -86,7 +77,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     const isOpen = property.includes(":open");
     const fieldKey = props?.fieldKey ? props.fieldKey + "-" : isCaption ? "caption-" : "";
     const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === "comic";
-    const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background);
+    const isBackground = () => doc && BoolCast(doc._lockedPosition);
     const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
     const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
     const showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle);
@@ -177,7 +168,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
                 default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
             }
-            if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = DashColor(docColor).fade(0.5).toString();
+            if (docColor && !doc) docColor = DashColor(docColor).fade(0.5).toString();
             return docColor;
         }
         case StyleProp.BoxShadow: {
@@ -205,17 +196,15 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.PointerEvents:
             if (doc?.type === DocumentType.MARKER) return "none";
             if (props?.pointerEvents?.() === "none") return "none";
-            const layer = doc && props?.layerProvider?.(doc);
             const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name);
-            if (opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
-            if (layer === false && !selected && !SnappingManager.GetIsDragging()) return "none";
-            if (!isInk && layer === true) return "all";
+            if (doc?._lockedPosition || opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
+            if (!isInk) return "all";
             return undefined;
         case StyleProp.Decorations:
             if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform || doc?.x !== undefined || doc?.y !== undefined) {
                 return doc && (isBackground() || selected) && (props?.renderDepth || 0) > 0 &&
                     ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ?
-                    <div className="styleProvider-lock" onClick={() => toggleBackground(doc)}>
+                    <div className="styleProvider-lock" onClick={() => toggleLockedPosition(doc)}>
                         <FontAwesomeIcon icon={isBackground() ? "lock" : "unlock"} style={{ color: isBackground() ? "red" : undefined }} size="lg" />
                     </div>
                     : (null);
@@ -251,30 +240,3 @@ export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps
     }
     return DefaultStyleProvider(doc, props, property);
 }
-
-//
-// a preliminary semantic-"layering/grouping" mechanism for determining interactive properties of documents
-//  currently, the provider tests whether the docuemnt's layer field matches the activeLayer field of the tab.
-//     if it matches, then the document gets pointer events, otherwise it does not.
-//
-export function DefaultLayerProvider(thisDoc: Doc) {
-    return (doc: Doc, assign?: boolean) => {
-        if (doc.z) return true;
-        if (assign) {
-            const activeLayer = StrCast(thisDoc?.activeLayer);
-            if (activeLayer) {
-                const layers = Cast(doc._layerTags, listSpec("string"), []);
-                if (layers.length && !layers.includes(activeLayer)) layers.push(activeLayer);
-                else if (!layers.length) doc._layerTags = new List<string>([activeLayer]);
-                if (activeLayer === "red" || activeLayer === "green" || activeLayer === "blue") doc._backgroundColor = activeLayer;
-            }
-            return true;
-        } else {
-            if (Doc.AreProtosEqual(doc, thisDoc)) return true;
-            const layers = StrListCast(doc._layerTags);
-            if (!layers.length && !thisDoc?.activeLayer) return true;
-            if (layers.includes(StrCast(thisDoc?.activeLayer))) return true;
-            return false;
-        }
-    };
-}
\ No newline at end of file
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index b3a24e031..636f7042f 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -131,7 +131,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 ContainingCollectionDoc={undefined}
                 ContainingCollectionView={undefined}
                 styleProvider={DefaultStyleProvider}
-                layerProvider={undefined}
                 setHeight={returnFalse}
                 docViewPath={returnEmptyDoclist}
                 docFilters={returnEmptyFilter}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 364a2440e..b3fbd4ca4 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -108,7 +108,6 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps>{
                 dropAction={"alias"}
                 setHeight={returnFalse}
                 styleProvider={DefaultStyleProvider}
-                layerProvider={undefined}
                 rootSelected={returnTrue}
                 bringToFront={emptyFunction}
                 select={emptyFunction}
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index de307416f..683b6d51d 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -392,7 +392,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
     // handles dragging and dropping markers in timeline
     @action
     internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number) {
-        if (!de.embedKey && this.props.layerProvider?.(this.props.Document) !== false && this.props.Document._isGroup) return false;
+        if (!de.embedKey && this.props.Document._isGroup) return false;
         if (!super.onInternalDrop(e, de)) return false;
 
         // determine x coordinate of drop and assign it to the documents being dragged  --- see internalDocDrop of collectionFreeFormView.tsx for how it's done when dropping onto a 2D freeform view
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 509005b45..4338dedcc 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -222,7 +222,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
             PanelWidth={width}
             PanelHeight={height}
             styleProvider={this.styleProvider}
-            layerProvider={this.props.layerProvider}
             docViewPath={this.props.docViewPath}
             fitWidth={this.props.childFitWidth}
             isContentActive={emptyFunction}
@@ -543,7 +542,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                     renderDepth={this.props.renderDepth}
                     focus={emptyFunction}
                     styleProvider={this.props.styleProvider}
-                    layerProvider={this.props.layerProvider}
                     docViewPath={returnEmptyDoclist}
                     whenChildContentsActiveChanged={emptyFunction}
                     bringToFront={emptyFunction}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 41970eb96..5e89016db 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -296,7 +296,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                     renderDepth={this.props.renderDepth + 1}
                     focus={emptyFunction}
                     styleProvider={this.props.styleProvider}
-                    layerProvider={this.props.layerProvider}
                     docViewPath={returnEmptyDoclist}
                     whenChildContentsActiveChanged={emptyFunction}
                     bringToFront={emptyFunction}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index ee2c28b5f..7c5f49b42 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -261,7 +261,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
             CollectionView: this,
         };
         return (<div className={"collectionView"} onContextMenu={this.onContextMenu}
-            style={{ pointerEvents: this.props.layerProvider?.(this.rootDoc) === false ? "none" : undefined }}>
+            style={{ pointerEvents: this.rootDoc._lockedPosition ? "none" : undefined }}>
             {this.showIsTagged()}
             {this.renderSubView(this.collectionViewType, props)}
         </div>);
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 8dfc7edc7..73e5a9178 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -26,7 +26,7 @@ import { Colors, Shadows } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
 import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
 import { PinProps, PresBox, PresMovement } from '../nodes/trails';
-import { DefaultLayerProvider, DefaultStyleProvider, StyleLayers, StyleProp } from '../StyleProvider';
+import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
 import { CollectionDockingView } from './CollectionDockingView';
 import { CollectionDockingViewMenu } from './CollectionDockingViewMenu';
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
@@ -94,20 +94,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
 
             if (tab.element[0].children[1].children.length === 1) {
-                const toggle = document.createElement("div");
-                toggle.style.width = "10px";
-                toggle.style.height = "calc(100% - 2px)";
-                toggle.style.left = "-2px";
-                toggle.style.bottom = "1px";
-                toggle.style.borderTopRightRadius = "7px";
-                toggle.style.position = "relative";
-                toggle.style.display = "inline-block";
-                toggle.style.background = "transparent";
-                toggle.onclick = (e: MouseEvent) => {
-                    if (tab.contentItem === tab.header.parent.getActiveContentItem()) {
-                        tab.DashDoc.activeLayer = tab.DashDoc.activeLayer ? undefined : StyleLayers.Background;
-                    }
-                };
                 iconWrap.className = "lm_iconWrap";
                 iconWrap.id = "lm_iconWrap";
                 closeWrap.className = "lm_iconWrap";
@@ -357,7 +343,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     disableMinimap = () => !this._document || (this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform);
     hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap);
 
-    @computed get layerProvider() { return this._document && DefaultLayerProvider(this._document); }
     @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)}
@@ -369,7 +354,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 isContentActive={returnTrue}
                 PanelWidth={this.PanelWidth}
                 PanelHeight={this.PanelHeight}
-                layerProvider={this.layerProvider}
                 styleProvider={DefaultStyleProvider}
                 docFilters={CollectionDockingView.Instance.childDocFilters}
                 docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
@@ -520,7 +504,6 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                     whenChildContentsActiveChanged={emptyFunction}
                     focus={DocUtils.DefaultFocus}
                     styleProvider={TabMinimapView.miniStyleProvider}
-                    layerProvider={undefined}
                     addDocTab={this.props.addDocTab}
                     pinToPres={TabDocView.PinDoc}
                     docFilters={CollectionDockingView.Instance.childDocFilters}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 164021358..d608f800c 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -663,7 +663,6 @@ export class TreeView extends React.Component<TreeViewProps> {
                 hideDecorationTitle={this.props.treeView.outlineMode}
                 hideResizeHandles={this.props.treeView.outlineMode}
                 styleProvider={this.titleStyleProvider}
-                layerProvider={returnTrue}
                 docViewPath={returnEmptyDoclist}
                 treeViewDoc={this.props.treeView.props.Document}
                 addDocument={undefined}
@@ -760,7 +759,6 @@ export class TreeView extends React.Component<TreeViewProps> {
             renderDepth={this.props.renderDepth + 1}
             treeViewDoc={this.props.treeView?.props.Document}
             rootSelected={returnTrue}
-            layerProvider={returnTrue}
             docViewPath={this.props.treeView.props.docViewPath}
             docFilters={returnEmptyFilter}
             docRangeFilters={returnEmptyFilter}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 4f79d19ad..322944d92 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -44,7 +44,7 @@ import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
 import { PresBox } from "../../nodes/trails/PresBox";
 import { VideoBox } from "../../nodes/VideoBox";
 import { CreateImage } from "../../nodes/WebBoxRenderer";
-import { StyleLayers, StyleProp } from "../../StyleProvider";
+import { StyleProp } from "../../StyleProvider";
 import { CollectionDockingView } from "../CollectionDockingView";
 import { CollectionSubView } from "../CollectionSubView";
 import { CollectionViewType } from "../CollectionView";
@@ -122,8 +122,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @observable ChildDrag: DocumentView | undefined; // child document view being dragged.  needed to update drop areas of groups when a group item is dragged.
 
     @computed get views() { return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); }
-    @computed get backgroundEvents() { return this.props.layerProvider?.(this.layoutDoc) === false && SnappingManager.GetIsDragging(); }
-    @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && this.props.isContentActive(); }
     @computed get fitToContentVals() {
         return {
             bounds: { ...this.contentBounds, cx: (this.contentBounds.x + this.contentBounds.r) / 2, cy: (this.contentBounds.y + this.contentBounds.b) / 2 },
@@ -222,8 +220,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number, yp: number) {
-        if (!de.embedKey && !this.ChildDrag && this.props.layerProvider?.(this.props.Document) !== false && this.props.Document._isGroup) return false;
-        if (!super.onInternalDrop(e, de)) return false;
+        if (!de.embedKey && !this.ChildDrag && this.rootDoc._isGroup) return false;
+        if (this.rootDoc._lockedPosition || !super.onInternalDrop(e, de)) return false;
         const refDoc = docDragData.droppedDocuments[0];
         const [xpo, ypo] = this.getContainerTransform().transformPoint(de.x, de.y);
         const z = NumCast(refDoc.z);
@@ -251,7 +249,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             const nd = [Doc.NativeWidth(layoutDoc), Doc.NativeHeight(layoutDoc)];
             layoutDoc._width = NumCast(layoutDoc._width, 300);
             layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? nd[1] / nd[0] * NumCast(layoutDoc._width) : 300);
-            !StrListCast(d._layerTags).includes(StyleLayers.Background) && (d._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : d._raiseWhenDragged) && (d.zIndex = zsorted.length + 1 + i); // bringToFront
+            (d._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : d._raiseWhenDragged) && (d.zIndex = zsorted.length + 1 + i); // bringToFront
         }
 
         (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(docDragData.droppedDocuments);
@@ -418,8 +416,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 styleProp = colors[cluster % colors.length];
                 const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
                 // override the cluster color with an explicitly set color on a non-background document.  then override that with an explicitly set color on a background document
-                set?.filter(s => !StrListCast(s._layerTags).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor));
-                set?.filter(s => StrListCast(s._layerTags).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor));
+                set?.map(s => styleProp = StrCast(s.backgroundColor));
             }
         } //else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray";
         return styleProp;
@@ -1017,7 +1014,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     bringToFront = (doc: Doc, sendToBack?: boolean) => {
-        if (sendToBack || StrListCast(doc._layerTags).includes(StyleLayers.Background)) {
+        if (sendToBack) {
             doc.zIndex = 0;
         } else if (doc.isInkMask) {
             doc.zIndex = 5000;
@@ -1155,7 +1152,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     pointerEvents = () => {
         const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine);
-        const pointerEvents = this.props.isContentActive() === false ? "none" : this.backgroundActive || this.props.childPointerEvents ? "all" :
+        const pointerEvents = this.props.isContentActive() === false ? "none" : this.props.childPointerEvents ? "all" :
             (this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? "none" : this.props.pointerEvents?.();
         return pointerEvents;
     }
@@ -1195,7 +1192,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
             docViewPath={this.props.docViewPath}
             styleProvider={this.getClusterColor}
-            layerProvider={this.props.layerProvider}
             dataProvider={this.childDataProvider}
             sizeProvider={this.childSizeProvider}
             freezeDimensions={BoolCast(this.props.Document.childFreezeDimensions, this.props.childFreezeDimensions)}
@@ -1614,7 +1610,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const isDocInView = (doc: Doc, rect: { left: number, top: number, width: number, height: number }) => intersectRect(docDims(doc), rect);
 
         const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) };
-        let snappableDocs = activeDocs.filter(doc => !StrListCast(doc._layerTags).includes(StyleLayers.Background) && doc.z === undefined && isDocInView(doc, selRect));  // first see if there are any foreground docs to snap to
+        let snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect));  // first see if there are any foreground docs to snap to
         !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect))); // if not, see if there are background docs to snap to
         !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z !== undefined && isDocInView(doc, otherBounds))); // if not, then why not snap to floating docs
 
@@ -1739,7 +1735,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             onContextMenu={this.onContextMenu}
             style={{
                 pointerEvents: this.props.Document.type === DocumentType.MARKER ? "none" :  // bcz: ugh.. this is here to prevent markers, which render as freeform views, from grabbing events -- need a better approach.
-                    this.backgroundEvents ? "all" : this.props.pointerEvents?.() as any,
+                    this.props.pointerEvents?.() as any,
                 transform: `scale(${this.contentScaling || 1})`,
                 width: `${100 / (this.contentScaling || 1)}%`,
                 height: this.isAnnotationOverlay && this.Document.scrollHeight ? NumCast(this.Document.scrollHeight) : `${100 / (this.contentScaling || 1)}%`// : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
@@ -1767,7 +1763,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     </svg>
                 </div>}
 
-            {this.props.Document._isGroup && SnappingManager.GetIsDragging() && (this.ChildDrag || this.props.layerProvider?.(this.props.Document) === false) ?
+            {this.props.Document._isGroup && SnappingManager.GetIsDragging() && this.ChildDrag ?
                 <div className="collectionFreeForm-groupDropper" ref={this.createGroupEventsTarget} style={{
                     width: this.ChildDrag ? "10000" : "100%",
                     height: this.ChildDrag ? "10000" : "100%",
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 5f303b428..1c4d47d57 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -28,7 +28,6 @@ import { CollectionView } from "../CollectionView";
 import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu";
 import "./MarqueeView.scss";
 import React = require("react");
-import { StyleLayers } from "../../StyleProvider";
 import { TreeView } from "../TreeView";
 import { VideoBox } from "../../nodes/VideoBox";
 import { ImageField, WebField } from "../../../../fields/URLField";
@@ -348,7 +347,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
         this.hideMarquee();
     }
 
-    getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, layers: string[], makeGroup: Opt<boolean>) => {
+    getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, makeGroup: Opt<boolean>) => {
         const newCollection = creator ? creator(selected, { title: "nested stack", }) : ((doc: Doc) => {
             Doc.GetProto(doc).data = new List<Doc>(selected);
             Doc.GetProto(doc).title = makeGroup ? "grouping" : "nested freeform";
@@ -357,7 +356,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             return doc;
         })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
         newCollection.system = undefined;
-        newCollection._layerTags = new List<string>(layers);
         newCollection._width = this.Bounds.width;
         newCollection._height = this.Bounds.height;
         newCollection._isGroup = makeGroup;
@@ -437,7 +435,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             }));
             this.props.removeDocument?.(selected);
         }
-        const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === "t" ? Docs.Create.StackingDocument : undefined, [], group);
+        const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === "t" ? Docs.Create.StackingDocument : undefined, group);
         this.props.addDocument?.(newCollection);
         this.props.selectDocuments([newCollection]);
         MarqueeOptionsMenu.Instance.fadeOut(true);
@@ -531,7 +529,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
 
     @action
     background = (e: KeyboardEvent | React.PointerEvent | undefined) => {
-        const newCollection = this.getCollection([], undefined, [StyleLayers.Background], undefined);
+        const newCollection = this.getCollection([], undefined, undefined);
         this.props.addDocument?.(newCollection);
         MarqueeOptionsMenu.Instance.fadeOut(true);
         this.hideMarquee();
@@ -617,7 +615,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
                 (this.touchesLine(bounds) || this.boundingShape(bounds)) && selection.push(doc);
             }
         };
-        this.props.activeDocuments().filter(doc => this.props.layerProvider?.(doc) !== false && !doc.z).map(selectFunc);
+        this.props.activeDocuments().filter(doc => !doc.z && !doc._lockedPosition).map(selectFunc);
         if (!selection.length && selectBackgrounds) this.props.activeDocuments().filter(doc => doc.z === undefined).map(selectFunc);
         if (!selection.length) this.props.activeDocuments().filter(doc => doc.z !== undefined).map(selectFunc);
         return selection;
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index c615bfb8e..bec582dcd 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -155,7 +155,6 @@ export class CollectionLinearView extends CollectionSubView() {
                 renderDepth={this.props.renderDepth + 1}
                 focus={emptyFunction}
                 styleProvider={this.props.styleProvider}
-                layerProvider={this.props.layerProvider}
                 docViewPath={returnEmptyDoclist}
                 whenChildContentsActiveChanged={emptyFunction}
                 bringToFront={emptyFunction}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 6929a1cd8..92f9b2f49 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -219,7 +219,6 @@ export class CollectionMulticolumnView extends CollectionSubView() {
             Document={layout}
             DataDoc={layout.resolvedDataDoc as Doc}
             styleProvider={this.props.styleProvider}
-            layerProvider={this.props.layerProvider}
             docViewPath={this.props.docViewPath}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 7e2b83230..4c4054b09 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -218,7 +218,6 @@ export class CollectionMultirowView extends CollectionSubView() {
             Document={layout}
             DataDoc={layout.resolvedDataDoc as Doc}
             styleProvider={this.props.styleProvider}
-            layerProvider={this.props.layerProvider}
             docViewPath={this.props.docViewPath}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index a93762ea4..b731479a5 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -417,7 +417,6 @@ export class CollectionSchemaView extends CollectionSubView() {
                     docRangeFilters={this.childDocRangeFilters}
                     searchFilterDocs={this.searchFilterDocs}
                     styleProvider={DefaultStyleProvider}
-                    layerProvider={undefined}
                     docViewPath={returnEmptyDoclist}
                     ContainingCollectionDoc={this.props.CollectionView?.props.Document}
                     ContainingCollectionView={this.props.CollectionView}
diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx
index 605481ddf..bea5b3be6 100644
--- a/src/client/views/collections/collectionSchema/SchemaTable.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx
@@ -573,7 +573,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         Document={this._showDoc}
                         DataDoc={this._showDataDoc}
                         styleProvider={DefaultStyleProvider}
-                        layerProvider={undefined}
                         docViewPath={returnEmptyDoclist}
                         freezeDimensions={true}
                         focus={DocUtils.DefaultFocus}
diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx
index c8be9069c..4b33ef8ae 100644
--- a/src/client/views/linking/LinkPopup.tsx
+++ b/src/client/views/linking/LinkPopup.tsx
@@ -67,7 +67,7 @@ export class LinkPopup extends React.Component<LinkPopupProps> {
                     <input defaultValue={""} autoComplete="off" type="text" placeholder="Search for Document..." id="search-input"
                         className="linkPopup-searchBox searchBox-input" /> */}
 
-                    <SearchBox 
+                    <SearchBox
                         Document={CurrentUserUtils.MySearchPanelDoc}
                         DataDoc={CurrentUserUtils.MySearchPanelDoc}
                         linkFrom={linkDoc}
@@ -83,7 +83,6 @@ export class LinkPopup extends React.Component<LinkPopupProps> {
                         pinToPres={emptyFunction}
                         rootSelected={returnTrue}
                         styleProvider={DefaultStyleProvider}
-                        layerProvider={undefined}
                         removeDocument={undefined}
                         ScreenToLocalTransform={Transform.Identity}
                         PanelWidth={this.getPWidth}
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index e28e5b453..d97cb6f84 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -654,7 +654,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             className="audiobox-container"
             onContextMenu={this.specificContextMenu}
             onClick={!this.path && !this._recorder ? this.recordAudioAnnotation : undefined}
-            style={{ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined }}
+            style={{ pointerEvents: this.layoutDoc._lockedPosition ? "none" : undefined }}
         >
             {!this.path ? this.recordingControls : this.playbackControls}
         </div>;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index edadd59c0..5a0ab9110 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -21,7 +21,6 @@ import React = require("react");
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
     sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined;
-    layerProvider: ((doc: Doc, assign?: boolean) => boolean) | undefined;
     renderCutoffProvider: (doc: Doc) => boolean;
     zIndex?: number;
     highlight?: boolean;
@@ -159,7 +158,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             ...this.props,
             CollectionFreeFormDocumentView: this.returnThis,
             styleProvider: this.styleProvider,
-            layerProvider: this.props.layerProvider,
             ScreenToLocalTransform: this.screenToLocalTransform,
             PanelWidth: this.panelWidth,
             PanelHeight: this.panelHeight,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f30d093a1..c999b3224 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -37,7 +37,7 @@ import { DocComponent } from "../DocComponent";
 import { EditableView } from '../EditableView';
 import { InkingStroke } from "../InkingStroke";
 import { LightboxView } from "../LightboxView";
-import { StyleLayers, StyleProp } from "../StyleProvider";
+import { StyleProp } from "../StyleProvider";
 import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
 import { DocumentContentsView } from "./DocumentContentsView";
 import { DocumentLinksButton } from './DocumentLinksButton';
@@ -123,7 +123,6 @@ export interface DocumentViewSharedProps {
     PanelHeight: () => number;
     docViewPath: () => DocumentView[];
     dataTransition?: string; // specifies animation transition - used by collectionPile and potentially other layout engines when changing the size of documents so that the change won't be abrupt
-    layerProvider: undefined | ((doc: Doc, assign?: boolean) => boolean);
     styleProvider: Opt<StyleProviderFunc>;
     focus: DocFocusFunc;
     fitWidth?: (doc: Doc) => boolean;
@@ -474,7 +473,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
             let stopPropagate = true;
             let preventDefault = true;
-            !StrListCast(this.props.Document._layerTags).includes(StyleLayers.Background) && (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc);
+            (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc);
             if (this._doubleTap && (this.props.Document.type !== DocumentType.FONTICON || this.onDoubleClickHandler)) {// && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
                 if (this._timeout) {
                     clearTimeout(this._timeout);
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 78adf63cb..a47e17dfc 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -423,7 +423,6 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     treeViewHideHeaderFields={false}
                     dontRegisterView={true}
                     styleProvider={this.FilterStyleProvider}
-                    layerProvider={this.props.layerProvider}
                     docViewPath={this.props.docViewPath}
                     scriptContext={this.props.scriptContext}
                     moveDocument={returnFalse}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index e7c43e5cd..3b04aa807 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -379,7 +379,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             style={{
                 width: this.props.PanelWidth() ? undefined : `100%`,
                 height: this.props.PanelWidth() ? undefined : `100%`,
-                pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined,
+                pointerEvents: this.layoutDoc._lockedPosition ? "none" : undefined,
                 borderRadius
             }} >
             <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 881cbf2bb..80def3025 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -60,7 +60,6 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             docRangeFilters: returnEmptyFilter,
             searchFilterDocs: returnEmptyDoclist,
             styleProvider: DefaultStyleProvider,
-            layerProvider: undefined,
             docViewPath: returnEmptyDoclist,
             ContainingCollectionView: undefined,
             ContainingCollectionDoc: undefined,
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 437d29f39..7fd289a97 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -89,7 +89,6 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
     openLinkTargetOnRight = (e: React.MouseEvent) => {
         const alias = Doc.MakeAlias(Cast(this.layoutDoc[this.fieldKey], Doc, null));
         alias._isLinkButton = undefined;
-        alias._layerTags = undefined;
         alias.layoutKey = "layout";
         this.props.addDocTab(alias, "add:right");
     }
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 375434933..ba515fb89 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -179,7 +179,6 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
                             moveDocument={returnFalse}
                             rootSelected={returnFalse}
                             styleProvider={this.props.docProps?.styleProvider}
-                            layerProvider={this.props.docProps?.layerProvider}
                             docViewPath={returnEmptyDoclist}
                             ScreenToLocalTransform={Transform.Identity}
                             isDocumentActive={returnFalse}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 3b4c94562..c350e3139 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -809,7 +809,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         const borderRadius = borderRad?.includes("px") ? `${Number(borderRad.split("px")[0]) / this.scaling()}px` : borderRad;
         return (<div className="videoBox" onContextMenu={this.specificContextMenu} ref={this._mainCont}
             style={{
-                pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined,
+                pointerEvents: this.layoutDoc._lockedPosition ? "none" : undefined,
                 borderRadius,
                 overflow: this.props.docViewPath?.().slice(-1)[0].fitWidth ? "auto" : undefined
             }} onWheel={e => { e.stopPropagation(); e.preventDefault(); }}>
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 20e01be05..445df8ddd 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -74,7 +74,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     @computed get allAnnotations() { return DocListCast(this.dataDoc[this.annotationKey]); }
     @computed get inlineTextAnnotations() { return this.allAnnotations.filter(a => a.textInlineAnnotations); }
     @computed get webField() { return Cast(this.dataDoc[this.props.fieldKey], WebField)?.url; }
-    @computed get webThumb() { return this.props.thumbShown?.() && ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumbScrollTop === this.layoutDoc._scrollTop ? this.layoutDoc.thumb : undefined))?.url }
+    @computed get webThumb() { return this.props.thumbShown?.() && ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumbScrollTop === this.layoutDoc._scrollTop ? this.layoutDoc.thumb : undefined))?.url; }
 
     constructor(props: any) {
         super(props);
@@ -134,7 +134,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                         returnedfilename => setTimeout(action(() => {
                             this.lockout = false;
                             this.layoutDoc.thumb = new ImageField(returnedfilename);
-                            this.layoutDoc.thumbScrollTop = scrollTop
+                            this.layoutDoc.thumbScrollTop = scrollTop;
                         }), 500));
                 })
                 .catch(function (error: any) {
@@ -717,7 +717,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     pointerEvents = () => !this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" : SnappingManager.GetIsDragging() ? undefined : "none";
     annotationPointerEvents = () => this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none";
     render() {
-        const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : this.props.pointerEvents?.() as any;
+        const pointerEvents = this.layoutDoc._lockedPosition ? "none" : this.props.pointerEvents?.() as any;
         const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
         const scale = previewScale * (this.props.scaling?.() || 1);
         const renderAnnotations = (docFilters?: () => string[]) =>
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 364be461f..1d8e3a2cf 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -182,7 +182,6 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
                     removeDocument={this.removeDoc}
                     isDocumentActive={returnFalse}
                     isContentActive={this._textBox.props.isContentActive}
-                    layerProvider={this._textBox.props.layerProvider}
                     styleProvider={this._textBox.props.styleProvider}
                     docViewPath={this._textBox.props.docViewPath}
                     ScreenToLocalTransform={this.getDocTransform}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 29117794e..f2a222cee 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1630,7 +1630,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         const active = this.props.isContentActive();
         const scale = (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
         const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
-        const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
+        const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || !this.layoutDoc._lockedPosition);
         if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide);
         const minimal = this.props.ignoreAutoHeight;
         const paddingX = NumCast(this.layoutDoc._xMargin, this.props.xPadding || 0);
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 820d7ef96..64f5a296f 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -700,7 +700,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.rootDoc, this.fieldKey, doc);
     getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
     panelHeight = () => this.props.PanelHeight() - 40;
-    isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) &&
+    isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && !this.layoutDoc._lockedPosition) &&
         (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
 
     /**
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index f4dc9b615..ef918d991 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -80,7 +80,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     Document={this.targetDoc}
                     DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
                     styleProvider={this.styleProvider}
-                    layerProvider={this.props.layerProvider}
                     docViewPath={returnEmptyDoclist}
                     rootSelected={returnTrue}
                     addDocument={returnFalse}
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index fb2e33e2a..5bdce273d 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -26,7 +26,7 @@ export
             {DocListCast(this.props.anno.textInlineAnnotations).map(a =>
                 <RegionAnnotation pointerEvents={this.props.pointerEvents} {...this.props} document={a} key={a[Id]} />
             )}
-        </div>
+        </div>;
     }
 }
 
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 2905e96d9..152b7bbcb 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -127,7 +127,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
     static foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) {
         let newarray: Doc[] = [];
         var depth = 0;
-        let visited: Doc[] = [];
+        const visited: Doc[] = [];
         while (docs.length > 0) {
             newarray = [];
             docs.filter(d => d && !visited.includes(d)).forEach(d => {
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 9de8d0831..194b3ba27 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1026,7 +1026,7 @@ export namespace Doc {
         if (status === DocBrushStatus.unbrushed) {
             const lastBrushed = Array.from(brushManager.BrushedDoc.keys()).lastElement();
             if (lastBrushed) {
-                for (var link of LinkManager.Instance.getAllDirectLinks(lastBrushed)) {
+                for (const link of LinkManager.Instance.getAllDirectLinks(lastBrushed)) {
                     const a1 = Cast(link.anchor1, Doc, null);
                     const a2 = Cast(link.anchor2, Doc, null);
                     if (Doc.AreProtosEqual(a1, doc) || Doc.AreProtosEqual(a2, doc) ||
diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx
index 88221732e..418464f0e 100644
--- a/src/mobile/AudioUpload.tsx
+++ b/src/mobile/AudioUpload.tsx
@@ -96,7 +96,6 @@ export class AudioUpload extends React.Component {
                         isDocumentActive={returnTrue}
                         isContentActive={emptyFunction}
                         focus={emptyFunction}
-                        layerProvider={undefined}
                         styleProvider={() => "rgba(0,0,0,0)"}
                         docViewPath={returnEmptyDoclist}
                         whenChildContentsActiveChanged={emptyFunction}
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index cfcc48608..78ec706d7 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -214,7 +214,6 @@ export class MobileInterface extends React.Component {
                     isContentActive={emptyFunction}
                     focus={DocUtils.DefaultFocus}
                     styleProvider={this.whitebackground}
-                    layerProvider={undefined}
                     docViewPath={returnEmptyDoclist}
                     whenChildContentsActiveChanged={emptyFunction}
                     bringToFront={emptyFunction}
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index bdea57cb2..fd000a83c 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -195,7 +195,7 @@ function proxyServe(req: any, requrl: string, response: any) {
                 console.log("EROR?: ", e);
             }
         } else req.pipe(request(requrl)).pipe(response);
-    }
+    };
     retrieveHTTPBody = () => {
         req.headers.cookie = "";
         req.pipe(request(requrl))
-- 
cgit v1.2.3-70-g09d2


From ee1fa0ad22f1643888e4c467c6f8df837cc69178 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 17 May 2022 10:18:45 -0400
Subject: fixed pointerevents on treview open icon.  added browse mode for
 freeformcollections

---
 src/client/util/DragManager.ts                     | 24 ++++++++++++----------
 src/client/views/collections/TabDocView.tsx        |  2 +-
 src/client/views/collections/TreeView.tsx          | 13 ++++++++----
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 23 ++++++++++++++++-----
 .../CollectionMulticolumnView.tsx                  |  2 +-
 .../CollectionMultirowView.tsx                     |  2 +-
 6 files changed, 43 insertions(+), 23 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 037da132b..5a00e0c04 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -456,17 +456,19 @@ export namespace DragManager {
                 dragData.userDropAction = e.ctrlKey && e.altKey ? "copy" : e.ctrlKey ? "alias" : dragData.defaultDropAction;
             }
             if (((e.target as any)?.className === "lm_tabs" || e?.shiftKey) && dragData.draggedDocuments.length === 1) {
-                if (!startWindowDragTimer) startWindowDragTimer = setTimeout(async () => {
-                    startWindowDragTimer = undefined;
-                    dragData.dropAction = dragData.userDropAction || "same";
-                    AbortDrag();
-                    await finishDrag?.(new DragCompleteEvent(true, dragData));
-                    DragManager.StartWindowDrag?.(e, dragData.droppedDocuments, (aborted) => {
-                        if (!aborted && (dragData.dropAction === "move" || dragData.dropAction === "same")) {
-                            dragData.removeDocument?.(dragData.draggedDocuments[0]);
-                        }
-                    });
-                }, 500);
+                if (!startWindowDragTimer) {
+                    startWindowDragTimer = setTimeout(async () => {
+                        startWindowDragTimer = undefined;
+                        dragData.dropAction = dragData.userDropAction || "same";
+                        AbortDrag();
+                        await finishDrag?.(new DragCompleteEvent(true, dragData));
+                        DragManager.StartWindowDrag?.(e, dragData.droppedDocuments, (aborted) => {
+                            if (!aborted && (dragData.dropAction === "move" || dragData.dropAction === "same")) {
+                                dragData.removeDocument?.(dragData.draggedDocuments[0]);
+                            }
+                        });
+                    }, 500);
+                }
             } else {
                 clearTimeout(startWindowDragTimer);
                 startWindowDragTimer = undefined;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 1310a582c..cebc3f779 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -85,7 +85,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             titleEle.value = doc.title;
             titleEle.onkeydown = (e: KeyboardEvent) => {
                 e.stopPropagation();
-            }
+            };
             titleEle.onchange = undoBatch(action((e: any) => {
                 titleEle.size = e.currentTarget.value.length + 3;
                 Doc.GetProto(doc).title = e.currentTarget.value;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index d608f800c..c004b4d49 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -494,10 +494,15 @@ export class TreeView extends React.Component<TreeViewProps> {
         return <div className={`bullet${this.props.treeView.outlineMode ? "-outline" : ""}`} key={"bullet"}
             title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
             onClick={this.bulletClick}
-            style={this.props.treeView.outlineMode ? { opacity: this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Opacity) } : {
-                color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"),
-                opacity: checked === "unchecked" || typeof iconType !== "string" ? undefined : 0.4
-            }}>
+            style={this.props.treeView.outlineMode ?
+                {
+                    opacity: this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Opacity)
+                } :
+                {
+                    pointerEvents: this.props.isContentActive() ? "all" : undefined,
+                    opacity: checked === "unchecked" || typeof iconType !== "string" ? undefined : 0.4,
+                    color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"),
+                }}>
             {this.props.treeView.outlineMode ?
                 !(this.doc.text as RichTextField)?.Text ? (null) :
                     <FontAwesomeIcon size="sm" icon={[this.childDocs?.length && !this.treeViewOpen ? "fas" : "far", "circle"]} /> :
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a60253914..68a51ef69 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -53,6 +53,7 @@ import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCurso
 import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
+import { ScriptingGlobals } from "../../../util/ScriptingGlobals";
 
 export const panZoomSchema = createSchema({
     _panX: "number",
@@ -154,7 +155,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action setKeyFrameEditing = (set: boolean) => this._keyframeEditing = set;
     getKeyFrameEditing = () => this._keyframeEditing;
-    onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick);
+    onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick, ScriptCast(this.layoutDoc.onBrowseClick));
     onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
     elementFunc = () => this._layoutElements;
     shrinkWrap = () => {
@@ -621,7 +622,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     }
 
     onClick = (e: React.MouseEvent) => {
-        if ((Math.abs(e.pageX - this._downX) < 3 && Math.abs(e.pageY - this._downY) < 3)) {
+
+        if (this.layoutDoc.onBrowseClick) {
+            this.zoomSmoothlyAboutPt(this.getTransform().transformPoint(e.clientX, e.clientY), 1);
+            e.stopPropagation();
+            e.preventDefault();
+        }
+        else if ((Math.abs(e.pageX - this._downX) < 3 && Math.abs(e.pageY - this._downY) < 3)) {
             if (e.shiftKey) {
                 if (Date.now() - this._lastTap < 300) { // reset zoom of freeform view to 1-to-1 on a shift + double click 
                     this.zoomSmoothlyAboutPt(this.getTransform().transformPoint(e.clientX, e.clientY), 1);
@@ -1127,7 +1134,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const screen = { left: cx - pw / 2, right: cx + pw / 2, top: cy - ph / 2, bot: cy + ph / 2 };
 
         if (scale) {
-            const maxZoom = 2; // sets the limit for how far we will zoom. this is useful for preventing small text boxes from filling the screen. So probably needs to be more sophisticated to consider more about the target and context
+            const maxZoom = 5; // sets the limit for how far we will zoom. this is useful for preventing small text boxes from filling the screen. So probably needs to be more sophisticated to consider more about the target and context
             return {
                 panX: (bounds.left + bounds.right) / 2,
                 panY: (bounds.top + bounds.bot) / 2,
@@ -1549,7 +1556,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
         const viewctrls = ContextMenu.Instance.findByDescription("UI Controls...");
         const viewCtrlItems = viewctrls && "subitems" in viewctrls ? viewctrls.subitems : [];
-
+        viewCtrlItems.push({ description: (this.layoutDoc.onChildClick ? "Leave" : "Enter") + " Browse Mode", event: () => this.layoutDoc.onBrowseClick = this.layoutDoc.onBrowseClick ? undefined : ScriptField.MakeScript("CollectionBrowseClick(documentView)", { documentView: "any" }), icon: "compress-arrows-alt" });
         !Doc.UserDoc().noviceMode ? viewCtrlItems.push({ description: (Doc.UserDoc().showSnapLines ? "Hide" : "Show") + " Snap Lines", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" }) : null;
         !Doc.UserDoc().noviceMode ? viewCtrlItems.push({ description: (this.Document._useClusters ? "Hide" : "Show") + " Clusters", event: () => this.updateClusters(!this.Document._useClusters), icon: "braille" }) : null;
         !viewctrls && ContextMenu.Instance.addItem({ description: "UI Controls...", subitems: viewCtrlItems, icon: "eye" });
@@ -1973,4 +1980,10 @@ class CollectionFreeFormBackgroundGrid extends React.Component<CollectionFreeFor
                 }
             }} />;
     }
-}
\ No newline at end of file
+}
+
+export function CollectionBrowseClick(dv: DocumentView) {
+    dv.props.focus(dv.props.Document, { willZoom: true });
+    Doc.linkFollowHighlight(dv?.props.Document, false);
+}
+ScriptingGlobals.add(CollectionBrowseClick);
\ No newline at end of file
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index c18b4cec7..b6b59a2d6 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -212,7 +212,7 @@ export class CollectionMulticolumnView extends CollectionSubView() {
                         dropInd = Math.ceil(index / 2 + (de.x - brect.x > brect.width / 2 ? 0 : -1));
                     }
                 }
-            })
+            });
             if (super.onInternalDrop(e, de)) {
                 de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
                     d._dimUnit = "*";
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 95456cf46..4074f8d69 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -212,7 +212,7 @@ export class CollectionMultirowView extends CollectionSubView() {
                         dropInd = Math.ceil(index / 2 + (de.y - brect.y > brect.height / 2 ? 0 : -1));
                     }
                 }
-            })
+            });
             if (super.onInternalDrop(e, de)) {
                 de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
                     d._dimUnit = "*";
-- 
cgit v1.2.3-70-g09d2


From 6df80c76b4046ef1ac9e98e52f766dfaf540ead2 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 20 May 2022 12:51:51 -0400
Subject: removed enumerables field stuff which was hacky and never used. 
 cleaned up some of currentUserUtils initialiazation.  fixed treeView sorting
 for 'none" which fixes problem with slide template.

---
 src/client/documents/Documents.ts                  |  24 --
 src/client/util/CurrentUserUtils.ts                | 242 +++++----------------
 .../views/collections/CollectionStackingView.tsx   |   1 -
 src/client/views/collections/TreeView.tsx          |   2 +-
 src/client/views/nodes/ComparisonBox.tsx           |   2 +-
 .../views/nodes/formattedText/DashFieldView.tsx    |  14 --
 6 files changed, 57 insertions(+), 228 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2dd8de089..4be9674f7 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1406,30 +1406,6 @@ export namespace DocUtils {
         return undefined;
     }
 
-    export async function addFieldEnumerations(doc: Opt<Doc>, enumeratedFieldKey: string, enumerations: { title: string, _backgroundColor?: string, color?: string }[]) {
-        let optionsCollection = await DocServer.GetRefField(enumeratedFieldKey);
-        if (!(optionsCollection instanceof Doc)) {
-            optionsCollection = Docs.Create.StackingDocument([], { title: `${enumeratedFieldKey} field set`, system: true }, enumeratedFieldKey);
-            Doc.AddDocToList((Doc.UserDoc().fieldTypes as Doc), "data", optionsCollection as Doc);
-        }
-        const options = optionsCollection as Doc;
-        const targetDoc = doc && Doc.GetProto(Cast(doc.rootDocument, Doc, null) || doc);
-        const docFind = `options.data?.find(doc => doc.title === (this.rootDocument||this)["${enumeratedFieldKey}"])?`;
-        targetDoc && (targetDoc.backgroundColor = ComputedField.MakeFunction(docFind + `._backgroundColor || "white"`, undefined, { options }));
-        targetDoc && (targetDoc.color = ComputedField.MakeFunction(docFind + `.color || "black"`, undefined, { options }));
-        targetDoc && (targetDoc.borderRounding = ComputedField.MakeFunction(docFind + `.borderRounding`, undefined, { options }));
-        enumerations.map(enumeration => {
-            const found = DocListCast(options.data).find(d => d.title === enumeration.title);
-            if (found) {
-                found._backgroundColor = enumeration._backgroundColor || found._backgroundColor;
-                found._color = enumeration.color || found._color;
-            } else {
-                Doc.AddDocToList(options, "data", Docs.Create.TextDocument(enumeration.title, { ...enumeration, system: true }));
-            }
-        });
-        return optionsCollection;
-    }
-
     // /**
     //  * 
     //  * @param dms Degree Minute Second format exif gps data
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 8fed6e940..e0580d3c4 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -75,201 +75,68 @@ export class CurrentUserUtils {
     @observable public static searchPanelWidth: number = 0;
 
     // sets up the default User Templates - slideView,  headerView
-    static setupUserTemplateButtons(doc: Doc) {
-        // Prototype for mobile button (not sure if 'Advanced Item Prototypes' is ideal location)
-        if (doc["template-mobile-button"] === undefined) {
-            const queryTemplate = this.mobileButton({
-                title: "NEW MOBILE BUTTON",
-                onClick: undefined,
-            },
-                [this.createToolButton({
-                    ignoreClick: true,
-                    icon: "mobile",
-                    btnType: ButtonType.ToolButton,
-                    backgroundColor: "transparent"
-                }),
-                this.mobileTextContainer({},
-                    [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]);
-            doc["template-mobile-button"] = CurrentUserUtils.createToolButton({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(queryTemplate) as any as Doc, title: "mobile button", icon: "mobile", btnType: ButtonType.ToolButton,
-            });
-        }
-
-        if (doc["template-button-slides"] === undefined) {
-            const slideTemplate = Docs.Create.MultirowDocument(
-                [
-                    Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }),
-                    Docs.Create.TextDocument("", { title: "text", _height: 100, system: true, _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize) })
-                ],
-                { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true }
-            );
-            slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
-            doc["template-button-slides"] = CurrentUserUtils.createToolButton({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(slideTemplate) as any as Doc, title: "presentation slide", icon: "address-card",
-                btnType: ButtonType.ToolButton
-            });
-        }
-
-        if (doc["template-button-link"] === undefined) {  // set _backgroundColor to transparent to prevent link dot from obscuring document it's attached to.
-            const linkTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _autoHeight: true, system: true }, "header")); // text needs to be a space to allow templateText to be created
-            linkTemplate.system = true;
-            Doc.GetProto(linkTemplate).layout =
-                "<div>" +
-                "    <FormattedTextBox {...props} dontSelectOnLoad={'true'} height='{this._headerHeight||75}px' ignoreAutoHeight={'true'} background='{this._headerColor||`lightGray`}' fieldKey={'header'}/>" +
-                "    <FormattedTextBox {...props} position='absolute' top='{(this._headerHeight||75)*scale}px' height='calc({100/scale}% - {this._headerHeight||75}px)' fieldKey={'text'}/>" +
-                "</div>";
-            (linkTemplate.proto as Doc).isTemplateDoc = makeTemplate(linkTemplate.proto as Doc, true, "linkView");
-
-            const rtf2 = {
-                doc: {
-                    type: "doc", content: [
-                        {
-                            type: "paragraph",
-                            content: [{
-                                type: "dashField",
-                                attrs: {
-                                    fieldKey: "src",
-                                    hideKey: false
-                                }
-                            }]
-                        },
-                        { type: "paragraph" },
-                        {
-                            type: "paragraph",
-                            content: [{
-                                type: "dashField",
-                                attrs: {
-                                    fieldKey: "dst",
-                                    hideKey: false
-                                }
-                            }]
-                        }]
+    static setupExperimentalTemplateButtons(doc: Doc) {
+        if (doc["template-experimental-buttons"] === undefined) {
+            const requiredTypeNameFields = [
+                {
+                    type: "slide", icon: "address-card", template: Docs.Create.MultirowDocument(
+                        [
+                            Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }),
+                            Docs.Create.TextDocument("", { title: "text", _height: 100, system: true, _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize) })
+                        ],
+                        { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true }
+                    )
                 },
-                selection: { type: "text", anchor: 1, head: 1 },
-                storedMarks: []
-            };
-            linkTemplate.header = new RichTextField(JSON.stringify(rtf2), "");
-
-            doc["template-button-link"] = CurrentUserUtils.createToolButton({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, title: "link view", icon: "window-maximize", system: true,
-                btnType: ButtonType.ToolButton
+                {
+                    type: "mobile", icon: "mobile", template: this.mobileButton({ title: "NEW MOBILE BUTTON", onClick: undefined, },
+                        [this.createToolButton({ ignoreClick: true, icon: "mobile", btnType: ButtonType.ToolButton, backgroundColor: "transparent" }),
+                        this.mobileTextContainer({},
+                            [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])
+                        ]
+                    )
+                },
+            ];
+            const requiredTypes = requiredTypeNameFields.map(({ type, icon, template }) => {
+                if (doc[`template-button-${type}`] === undefined) {
+                    template.isTemplateDoc = makeTemplate(template);
+                    doc[`template-button-${type}`] = CurrentUserUtils.createToolButton({
+                        onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
+                        dragFactory: new PrefetchProxy(template) as any as Doc,
+                        title: type,
+                        icon,
+                        btnType: ButtonType.ToolButton,
+                    });
+                }
+                return doc[`template-button-${type}`] as Doc;
             });
-        }
 
-        // if (doc["template-button-switch"] === undefined) {
-        //     const { FreeformDocument, MulticolumnDocument, TextDocument } = Docs.Create;
-
-        //     const yes = FreeformDocument([], { title: "yes", _height: 35, _width: 50, _dimUnit: DimUnit.Pixel, _dimMagnitude: 40, system: true });
-        //     const name = TextDocument("name", { title: "name", _height: 35, _width: 70, _dimMagnitude: 1, system: true });
-        //     const no = FreeformDocument([], { title: "no", _height: 100, _width: 100, system: true });
-        //     const labelTemplate = {
-        //         doc: {
-        //             type: "doc", content: [{
-        //                 type: "paragraph",
-        //                 content: [{ type: "dashField", attrs: { fieldKey: "PARAMS", hideKey: true } }]
-        //             }]
-        //         },
-        //         selection: { type: "text", anchor: 1, head: 1 },
-        //         storedMarks: []
-        //     };
-        //     Doc.GetProto(name).text = new RichTextField(JSON.stringify(labelTemplate), "PARAMS");
-        //     Doc.GetProto(yes).backgroundColor = ComputedField.MakeFunction("self[this.PARAMS] ? 'green':'red'");
-        //     // Doc.GetProto(no).backgroundColor = ComputedField.MakeFunction("!self[this.PARAMS] ? 'red':'white'");
-        //     // Doc.GetProto(yes).onClick = ScriptField.MakeScript("self[this.PARAMS] = true");
-        //     Doc.GetProto(yes).onClick = ScriptField.MakeScript("self[this.PARAMS] = !self[this.PARAMS]");
-        //     // Doc.GetProto(no).onClick = ScriptField.MakeScript("self[this.PARAMS] = false");
-        //     const box = MulticolumnDocument([/*no, */ yes, name], { title: "value", _width: 120, _height: 35, system: true });
-        //     box.isTemplateDoc = makeTemplate(box, true, "switch");
-
-        //     doc["template-button-switch"] = CurrentUserUtils.createToolButton({
-        //         onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-        //         dragFactory: new PrefetchProxy(box) as any as Doc, title: "data switch", icon: "toggle-on", system: true,
-        //         btnType: ButtonType.ToolButton
-        //     });
-        // }
-
-        const requiredTypes = [
-            doc["template-button-slides"] as Doc,
-            doc["template-mobile-button"] as Doc,
-            doc["template-button-link"] as Doc,
-            //doc["template-button-switch"] as Doc]
-        ];
-        if (doc["template-buttons"] === undefined) {
-            doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, {
-                title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", _chromeHidden: true,
+            doc["template-experimental-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, {
+                title: "Experimental Tools", _xMargin: 0, _showTitle: "title", _chromeHidden: true,
                 hidden: ComputedField.MakeFunction("IsNoviceMode()") as any,
                 _stayInCollection: true, _hideContextMenu: true, _forceActive: true,
                 _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
             }));
-        } else {
-            const curButnTypes = Cast(doc["template-buttons"], Doc, null);
-            DocListCastAsync(curButnTypes.data).then(async curBtns => {
-                curBtns && await Promise.all(curBtns);
-                requiredTypes.map(btype => Doc.AddDocToList(curButnTypes, "data", btype));
-            });
         }
-        return doc["template-buttons"] as Doc;
+        return doc["template-experimental-buttons"] as Doc;
     }
 
     // setup the different note type skins
     static setupNoteTemplates(doc: Doc) {
-        if (doc["template-note-Note"] === undefined) {
-            const noteView = Docs.Create.TextDocument("", {
-                title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true, icon: "sticky-note",
-                _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
-            });
-            noteView.isTemplateDoc = makeTemplate(noteView, true, "Note");
-            doc["template-note-Note"] = new PrefetchProxy(noteView);
-        }
-        if (doc["template-note-Idea"] === undefined) {
-            const noteView = Docs.Create.TextDocument("", {
-                title: "text", backgroundColor: "pink", system: true, icon: "lightbulb",
-                _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
-            });
-            noteView.isTemplateDoc = makeTemplate(noteView, true, "Idea");
-            doc["template-note-Idea"] = new PrefetchProxy(noteView);
-        }
-        if (doc["template-note-Topic"] === undefined) {
-            const noteView = Docs.Create.TextDocument("", {
-                title: "text", backgroundColor: "lightblue", system: true, icon: "book-open",
-                _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
-            });
-            noteView.isTemplateDoc = makeTemplate(noteView, true, "Topic");
-            doc["template-note-Topic"] = new PrefetchProxy(noteView);
-        }
-        // if (doc["template-note-Todo"] === undefined) {
-        //     const noteView = Docs.Create.TextDocument("", {
-        //         title: "text", backgroundColor: "orange", _autoHeight: false, _height: 100, _showCaption: "caption",
-        //         layout: FormattedTextBox.LayoutString("Todo"), caption: RichTextField.DashField("taskStatus"), system: true,
-        //         _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
-        //     });
-        //     noteView.isTemplateDoc = makeTemplate(noteView, true, "Todo");
-        //     doc["template-note-Todo"] = new PrefetchProxy(noteView);
-        // }
-        // const taskStatusValues = [
-        //     { title: "todo", _backgroundColor: "blue", color: "white", system: true },
-        //     { title: "in progress", _backgroundColor: "yellow", color: "black", system: true },
-        //     { title: "completed", _backgroundColor: "green", color: "white", system: true }
-        // ];
-        // if (doc.fieldTypes === undefined) {
-        //     doc.fieldTypes = Docs.Create.TreeDocument([], { title: "field enumerations", system: true });
-        //     DocUtils.addFieldEnumerations(Doc.GetProto(doc["template-note-Todo"] as any as Doc), "taskStatus", taskStatusValues);
-        // }
-
         if (doc["template-notes"] === undefined) {
-            doc["template-notes"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-note-Note"] as any as Doc, doc["template-note-Idea"] as any as Doc, doc["template-note-Topic"] as any as Doc], // doc["template-note-Todo"] as any as Doc],
-                { title: "Note Layouts", _height: 75, system: true }));
-        } else {
-            const curNoteTypes = Cast(doc["template-notes"], Doc, null);
-            const requiredTypes = [doc["template-note-Note"] as any as Doc, doc["template-note-Idea"] as any as Doc, doc["template-note-Topic"] as any as Doc];//, doc["template-note-Todo"] as any as Doc];
-            DocListCastAsync(curNoteTypes.data).then(async curNotes => {
-                curNotes && await Promise.all(curNotes);
-                requiredTypes.map(ntype => Doc.AddDocToList(curNoteTypes, "data", ntype));
-            });
+            const requiredTypeNameFields = [
+                { type: "Note", backgroundColor: "yellow", icon: "sticky-note" },
+                { type: "Idea", backgroundColor: "pink", icon: "lightbulb" },
+                { type: "Topic", backgroundColor: "lightblue", icon: "book-open" }];
+            const requiredTypes = requiredTypeNameFields.map(({ type, backgroundColor, icon }) =>
+                doc[`template-note-${type}`] as Doc ??
+                (() => {
+                    const noteView = Docs.Create.TextDocument("", { title: "text", backgroundColor, system: true, icon });
+                    noteView.isTemplateDoc = makeTemplate(noteView, true, type);
+                    return doc[`template-note-${type}`] = new PrefetchProxy(noteView);
+                })());
+
+            doc["template-notes"] = new PrefetchProxy(Docs.Create.TreeDocument(requiredTypes, { title: "Note Layouts", _height: 75, system: true }));
         }
 
         return doc["template-notes"] as Doc;
@@ -277,11 +144,12 @@ export class CurrentUserUtils {
 
     // creates Note templates, and initial "user" templates
     static setupDocTemplates(doc: Doc) {
-        const noteTemplates = CurrentUserUtils.setupNoteTemplates(doc);
-        const userTemplateBtns = CurrentUserUtils.setupUserTemplateButtons(doc);
-        const clickTemplates = CurrentUserUtils.setupClickEditorTemplates(doc);
         if (doc.templateDocs === undefined) {
-            doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([noteTemplates, userTemplateBtns, clickTemplates], {
+            doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([
+                CurrentUserUtils.setupNoteTemplates(doc),
+                CurrentUserUtils.setupExperimentalTemplateButtons(doc),
+                CurrentUserUtils.setupClickEditorTemplates(doc)
+            ], {
                 title: "template layouts", _xMargin: 0, system: true,
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name })
             }));
@@ -717,7 +585,7 @@ export class CurrentUserUtils {
     static async setupToolsBtnPanel(doc: Doc) {
         // setup a masonry view of all he creators
         const creatorBtns = await CurrentUserUtils.setupCreatorButtons(doc);
-        const templateBtns = CurrentUserUtils.setupUserTemplateButtons(doc);
+        const templateBtns = CurrentUserUtils.setupExperimentalTemplateButtons(doc);
 
         doc["tabs-button-tools"] = undefined;
 
@@ -1260,7 +1128,7 @@ export class CurrentUserUtils {
         doc.noviceMode = doc.noviceMode === undefined ? "true" : doc.noviceMode;
         doc.title = Doc.CurrentUserEmail;
         doc._raiseWhenDragged = true;
-        doc._showLabel = false;
+        doc._showLabel = true;
         doc._showMenuLabel = true;
         doc.textAlign = StrCast(doc.textAlign, "left");
         doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)");
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 4338dedcc..4630b3bf2 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -482,7 +482,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
         if (value && this.columnHeaders) {
             const schemaHdrField = new SchemaHeaderField(value);
             this.columnHeaders.push(schemaHdrField);
-            DocUtils.addFieldEnumerations(undefined, this.pivotField, [{ title: value, _backgroundColor: "schemaHdrField.color" }]);
             return true;
         }
         return false;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index c004b4d49..65f8fe248 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -895,7 +895,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result);
         }
 
-        const docs = TreeView.sortDocs(childDocs, StrCast(containerCollection.treeViewSortCriterion));
+        const docs = TreeView.sortDocs(childDocs, StrCast(containerCollection.treeViewSortCriterion, TreeSort.None));
         const rowWidth = () => panelWidth() - treeBulletWidth();
         const treeViewRefs = new Map<Doc, TreeView | undefined>();
         return docs.filter(child => child instanceof Doc).map((child, i) => {
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 49cd39f43..5ea6d567a 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -76,7 +76,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
         const clearButton = (which: string) => {
             return <div className={`clear-button ${which}`}
                 onPointerDown={e => e.stopPropagation()} // prevent triggering slider movement in registerSliding 
-                onClick={e => this.clearDoc(e, `compareBox-${which}`)}>
+                onClick={e => this.clearDoc(e, which)}>
                 <FontAwesomeIcon className={`clear-button ${which}`} icon={"times"} size="sm" />
             </div>;
         };
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 34908e54b..1a8352b72 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -58,7 +58,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
     _textBoxDoc: Doc;
     _fieldKey: string;
     _fieldStringRef = React.createRef<HTMLSpanElement>();
-    @observable _showEnumerables: boolean = false;
     @observable _dashDoc: Doc | undefined;
 
     constructor(props: IDashFieldViewInternal) {
@@ -110,7 +109,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
                         r?.addEventListener("keydown", e => this.fieldSpanKeyDown(e, r));
                         r?.addEventListener("blur", e => r && this.updateText(r.textContent!, false));
                         r?.addEventListener("pointerdown", action((e) => {
-                            this._showEnumerables = true;
                             e.stopPropagation();
                         }));
                     }} >
@@ -124,7 +122,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
     @action
     fieldSpanKeyDown = (e: KeyboardEvent, span: HTMLSpanElement) => {
         if (e.key === "Enter") {  // handle the enter key by "submitting" the current text to Dash's database. 
-            e.ctrlKey && DocUtils.addFieldEnumerations(this._textBoxDoc, this._fieldKey, [{ title: span.textContent! }]);
             this.updateText(span.textContent!, true);
             e.preventDefault();// prevent default to avoid a newline from being generated and wiping out this field view
         }
@@ -142,7 +139,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
 
     @action
     updateText = (nodeText: string, forceMatch: boolean) => {
-        this._showEnumerables = false;
         if (nodeText) {
             const newText = nodeText.startsWith(":=") || nodeText.startsWith("=:=") ? ":=-computed-" : nodeText;
 
@@ -154,7 +150,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
                 (options instanceof Doc) && DocListCast(options.data).forEach(opt => (forceMatch ? StrCast(opt.title).startsWith(newText) : StrCast(opt.title) === newText) && (modText = StrCast(opt.title)));
                 if (modText) {
                     //  elementfieldSpan.innerHTML = this._dashDoc![this._fieldKey as string] = modText;
-                    DocUtils.addFieldEnumerations(this._textBoxDoc, this._fieldKey, []);
                     Doc.SetInPlace(this._dashDoc!, this._fieldKey, modText, true);
                 } // if the text starts with a ':=' then treat it as an expression by making a computed field from its value storing it in the key
                 else if (nodeText.startsWith(":=")) {
@@ -178,13 +173,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
         }
     }
 
-    // display a collection of all the enumerable values for this field
-    onPointerDownEnumerables = async (e: any) => {
-        e.stopPropagation();
-        const collview = await DocUtils.addFieldEnumerations(this._textBoxDoc, this._fieldKey, [{ title: this._fieldKey }]);
-        collview instanceof Doc && this.props.tbox.props.addDocTab(collview, "add:right");
-    }
-
 
     // clicking on the label creates a pivot view collection of all documents
     // in the same collection.  The pivot field is the fieldKey of this label
@@ -220,8 +208,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
 
             {this.props.fieldKey.startsWith("#") ? (null) : this.fieldValueContent}
 
-            {!this._showEnumerables ? (null) : <div className="dashFieldView-enumerables" onPointerDown={this.onPointerDownEnumerables} />}
-
         </div >;
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 3fe0e0e02a6c9bd717b3df9b000c13d1131f6eb4 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 23 May 2022 12:28:31 -0400
Subject: cleaning up singleLine text box api and TreeView types

---
 src/client/util/CurrentUserUtils.ts                |  7 +--
 src/client/views/MainView.tsx                      |  5 +-
 .../views/collections/CollectionTreeView.tsx       | 29 ++++++----
 src/client/views/collections/TreeView.tsx          | 35 ++++++------
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 34 ++++++++++--
 .../collections/collectionFreeForm/MarqueeView.tsx | 13 +++--
 src/client/views/nodes/DocumentView.tsx            |  2 +
 src/client/views/nodes/FieldView.tsx               |  3 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  7 +--
 .../formattedText/ProsemirrorExampleTransfer.ts    | 62 ++++++----------------
 10 files changed, 101 insertions(+), 96 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 85769d915..1ebb5365a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -16,6 +16,7 @@ import { Docs, DocumentOptions, DocUtils } from "../documents/Documents";
 import { DocumentType } from "../documents/DocumentTypes";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { CollectionFreeFormView } from "../views/collections/collectionFreeForm";
+import { TreeViewType } from "../views/collections/CollectionTreeView";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
 import { TreeView } from "../views/collections/TreeView";
 import { Colors } from "../views/global/globalEnums";
@@ -215,7 +216,7 @@ export class CurrentUserUtils {
         if (doc.emptySlide === undefined) {
             doc.emptySlide = Docs.Create.TreeDocument([], {
                 ...standardOps(), title: ComputedField.MakeFunction('self.text?.Text') as any, _viewType: CollectionViewType.Tree, treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true, "dragFactory-count": undefined,
-                allowOverlayDrop: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "white"
+                allowOverlayDrop: true, treeViewType: TreeViewType.outline, _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "white"
             });
         }
         if (doc.emptyHeader === undefined) {
@@ -563,7 +564,7 @@ export class CurrentUserUtils {
                 title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true, freezeChildren: "remove|add",
                 treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newDashboardButton,
-                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true,
+                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, system: true,
                 explainer: "This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files."
             }));
             const toggleDarkTheme = ScriptField.MakeScript(`this.colorScheme = this.colorScheme ? undefined : "${ColorScheme.Dark}"`);
@@ -616,7 +617,7 @@ export class CurrentUserUtils {
                 title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100,
                 treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
-                isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
+                isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true,
                 _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true,
                 explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
             }));
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6a2df3b51..09a57843c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -8,11 +8,9 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import * as ReactDOM from 'react-dom';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
-import { List } from '../../fields/List';
 import { PrefetchProxy } from '../../fields/Proxy';
 import { ScriptField } from '../../fields/ScriptField';
 import { PromiseValue, StrCast } from '../../fields/Types';
-import { TraceMobx } from '../../fields/util';
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
@@ -34,6 +32,7 @@ import { CollectionDockingView } from './collections/CollectionDockingView';
 import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu';
 import { CollectionLinearView } from './collections/collectionLinear';
 import { CollectionMenu } from './collections/CollectionMenu';
+import { TreeViewType } from './collections/CollectionTreeView';
 import { CollectionViewType } from './collections/CollectionView';
 import "./collections/TreeView.scss";
 import { ComponentDecorations } from './ComponentDecorations';
@@ -263,7 +262,7 @@ export class MainView extends React.Component {
                 title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100,
                 treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
-                isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
+                isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true,
                 _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true,
                 explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
             }));
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 5e89016db..99ffb9bb0 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -27,6 +27,7 @@ import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import { TreeView } from "./TreeView";
 import React = require("react");
+import { FieldViewProps } from "../nodes/FieldView";
 const _global = (window /* browser */ || global /* node */) as any;
 
 export type collectionTreeViewProps = {
@@ -39,6 +40,12 @@ export type collectionTreeViewProps = {
     onChildClick?: () => ScriptField;
 };
 
+export enum TreeViewType {
+    outline = "outline",
+    fileSystem = "fileSystem",
+    default = "default"
+}
+
 @observer
 export class CollectionTreeView extends CollectionSubView<Partial<collectionTreeViewProps>>() {
     private _treedropDisposer?: DragManager.DragDropDisposer;
@@ -54,8 +61,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     @computed get dataDoc() { return this.props.DataDoc || this.doc; }
     @computed get treeViewtruncateTitleWidth() { return NumCast(this.doc.treeViewTruncateTitleWidth, this.panelWidth()); }
     @computed get treeChildren() { TraceMobx(); return this.props.childDocuments || this.childDocs; }
-    @computed get outlineMode() { return this.doc.treeViewType === "outline"; }
-    @computed get fileSysMode() { return this.doc.treeViewType === "fileSystem"; }
+    @computed get outlineMode() { return this.doc.treeViewType === TreeViewType.outline }
+    @computed get fileSysMode() { return this.doc.treeViewType === TreeViewType.fileSystem; }
     @computed get dashboardMode() { return this.doc === Doc.UserDoc().myDashboards; }
 
     @observable _explainerHeight = 0; // height of the description of the tree view
@@ -180,13 +187,20 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             height={"auto"}
             GetValue={() => StrCast(this.dataDoc.title)}
             SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
-                if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(this.treeChildren);
+                if (enter && this.props.Document.treeViewType === TreeViewType.outline) this.makeTextCollection(this.treeChildren);
                 this.dataDoc.title = value;
                 return true;
             })} />;
     }
 
 
+    onKey = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
+        if (this.outlineMode && e.key === "Enter") {
+            e.stopPropagation();
+            this.makeTextCollection(this.treeChildren);
+            return true;
+        }
+    }
     get documentTitle() {
         return <FormattedTextBox
             {...this.props}
@@ -199,6 +213,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             PanelWidth={this.documentTitleWidth}
             PanelHeight={this.documentTitleHeight}
             scaling={returnOne}
+            onKey={this.onKey}
             docFilters={returnEmptyFilter}
             docRangeFilters={returnEmptyFilter}
             searchFilterDocs={returnEmptyDoclist}
@@ -257,13 +272,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         return this.dataDoc === null ? (null) :
             <div className="collectionTreeView-titleBar" key={this.doc[Id]}
                 style={!this.outlineMode ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}}
-                ref={r => this._titleRef = r}
-                onKeyDown={e => {
-                    if (this.outlineMode) {
-                        e.stopPropagation();
-                        e.key === "Enter" && this.makeTextCollection(this.treeChildren);
-                    }
-                }}>
+                ref={r => this._titleRef = r}>
                 {this.outlineMode ? this.documentTitle : this.editableTitle}
             </div>;
     }
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 65f8fe248..70ad23f41 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -26,11 +26,12 @@ import { DocumentView, DocumentViewInternal, DocumentViewProps, StyleProviderFun
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
 import { StyleProp } from '../StyleProvider';
-import { CollectionTreeView } from './CollectionTreeView';
+import { CollectionTreeView, TreeViewType } from './CollectionTreeView';
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TreeView.scss";
 import React = require("react");
 import { KeyValueBox } from '../nodes/KeyValueBox';
+import { FieldViewProps } from '../nodes/FieldView';
 
 export interface TreeViewProps {
     treeView: CollectionTreeView;
@@ -241,7 +242,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             layout: CollectionView.LayoutString("data"),
             title: "-title-",
             treeViewExpandedViewLock: true, treeViewExpandedView: "data",
-            _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: "outline",
+            _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: TreeViewType.outline,
             x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _width: 1000, _height: 10
         });
         Doc.GetProto(bullet).title = ComputedField.MakeFunction('self.text?.Text');
@@ -604,24 +605,29 @@ export class TreeView extends React.Component<TreeViewProps> {
         if (property.startsWith(StyleProp.Decorations)) return (null);
         return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
     }
-    onKeyDown = (e: React.KeyboardEvent) => {
+    onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
         if (this.doc.treeViewHideHeader || (this.doc.treeViewHideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode) {
             switch (e.key) {
                 case "Tab":
-                    e.stopPropagation();
-                    e.preventDefault();
+                    e.stopPropagation?.();
+                    e.preventDefault?.();
                     setTimeout(() => RichTextMenu.Instance.TextView?.EditorView?.focus(), 150);
-                    return UndoManager.RunInBatch(() => e.shiftKey ? this.props.outdentDocument?.(true) : this.props.indentDocument?.(true), "tab");
+                    UndoManager.RunInBatch(() => e.shiftKey ? this.props.outdentDocument?.(true) : this.props.indentDocument?.(true), "tab");
+                    return true;
                 case "Backspace":
-                    e.stopPropagation();
-                    e.preventDefault();
-                    return !(this.doc.text as RichTextField)?.Text && this.props.removeDoc?.(this.doc);
+                    if (!(this.doc.text as RichTextField)?.Text && this.props.removeDoc?.(this.doc)) {
+                        e.stopPropagation?.();
+                        e.preventDefault?.();
+                        return true;
+                    }
+                    break;
                 case "Enter":
-                    e.stopPropagation();
-                    e.preventDefault();
+                    e.stopPropagation?.();
+                    e.preventDefault?.();
                     return UndoManager.RunInBatch(this.makeTextCollection, "bullet");
             }
         }
+        return false;
     }
     titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth()));
 
@@ -758,6 +764,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             hideResizeHandles={this.props.treeView.outlineMode}
             focus={this.refocus}
             ContentScaling={returnOne}
+            onKey={this.onKeyDown}
             hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
             dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
             ScreenToLocalTransform={this.docTransform}
@@ -800,7 +807,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get renderBorder() {
         const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
         const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string, label: string } };
-        return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`} style={{ borderColor: sortings[sorting]?.color }}>
+        return <div className={`treeView-border${this.props.treeView.outlineMode ? TreeViewType.outline : ""}`} style={{ borderColor: sortings[sorting]?.color }}>
             {!this.treeViewOpen ? (null) : this.renderContent}
         </div>;
     }
@@ -821,9 +828,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
             <div className={`treeView-container${this.props.isContentActive() ? "-active" : ""}`}
                 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}>
+                onDrop={this.onTreeDrop}>
                 <li className="collection-child">
                     {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader ? // should test for prop 'treeViewRenderDocWithBulletAsHeader"
                         this.renderEmbeddedDocument(false, returnFalse) :
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index df09569ef..3b32cf57d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,18 +1,18 @@
 import { Bezier } from "bezier-js";
-import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { computedFn } from "mobx-utils";
 import { DateField } from "../../../../fields/DateField";
-import { Doc, HeightSym, Opt, StrListCast, WidthSym } from "../../../../fields/Doc";
+import { DataSym, Doc, HeightSym, Opt, StrListCast, WidthSym } from "../../../../fields/Doc";
 import { Id } from "../../../../fields/FieldSymbols";
 import { InkData, InkField, InkTool, PointData, Segment } from "../../../../fields/InkField";
 import { List } from "../../../../fields/List";
 import { ObjectField } from "../../../../fields/ObjectField";
 import { RichTextField } from "../../../../fields/RichTextField";
-import { ImageField } from "../../../../fields/URLField";
 import { createSchema, listSpec } from "../../../../fields/Schema";
 import { ScriptField } from "../../../../fields/ScriptField";
 import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
+import { ImageField } from "../../../../fields/URLField";
 import { TraceMobx } from "../../../../fields/util";
 import { GestureUtils } from "../../../../pen-gestures/GestureUtils";
 import { aggregateBounds, emptyFunction, intersectRect, returnFalse, setupMoveUpEvents, Utils } from "../../../../Utils";
@@ -26,6 +26,7 @@ import { DragManager, dropActionType } from "../../../util/DragManager";
 import { HistoryUtil } from "../../../util/History";
 import { InteractionUtils } from "../../../util/InteractionUtils";
 import { LinkManager } from "../../../util/LinkManager";
+import { ScriptingGlobals } from "../../../util/ScriptingGlobals";
 import { SearchUtil } from "../../../util/SearchUtil";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { ColorScheme } from "../../../util/SettingsManager";
@@ -47,13 +48,14 @@ import { CreateImage } from "../../nodes/WebBoxRenderer";
 import { StyleProp } from "../../StyleProvider";
 import { CollectionDockingView } from "../CollectionDockingView";
 import { CollectionSubView } from "../CollectionSubView";
+import { TreeViewType } from "../CollectionTreeView";
 import { CollectionViewType } from "../CollectionView";
 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 { ScriptingGlobals } from "../../../util/ScriptingGlobals";
+import { FieldView, FieldViewProps } from "../../nodes/FieldView";
 
 export const panZoomSchema = createSchema({
     _panX: "number",
@@ -957,7 +959,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
-        if (this.layoutDoc._Transform || (this.layoutDoc._fitWidth && this.layoutDoc.nativeHeight) || CurrentUserUtils.OverlayDocs.includes(this.props.Document) || this.props.Document.treeViewOutlineMode === "outline") return;
+        if (this.layoutDoc._Transform || (this.layoutDoc._fitWidth && this.layoutDoc.nativeHeight) || CurrentUserUtils.OverlayDocs.includes(this.props.Document) || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
         if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) { // things that can scroll vertically should do that instead of zooming
             e.stopPropagation();
         }
@@ -1160,6 +1162,27 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     isContentActive = () => this.props.isSelected() || this.props.isContentActive();
 
+    @undoBatch
+    @action
+    onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
+        const docView = fieldProps.DocumentView?.();
+        if (docView && docView.rootDoc._singleLine && ["Tab", "Enter"].includes(e.key)) {
+            e.stopPropagation?.();
+            const below = !e.altKey && e.key !== "Tab";
+            const layoutKey = StrCast(docView.LayoutFieldKey);
+            const newDoc = Doc.MakeCopy(docView.rootDoc, true);
+            const dataField = docView.rootDoc[Doc.LayoutFieldKey(newDoc)];
+            newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
+            if (below) newDoc.y = NumCast(docView.rootDoc.y) + NumCast(docView.rootDoc._height) + 10;
+            else newDoc.x = NumCast(docView.rootDoc.x) + NumCast(docView.rootDoc._width) + 10;
+            if (layoutKey !== "layout" && docView.rootDoc[layoutKey] instanceof Doc) {
+                newDoc[layoutKey] = docView.rootDoc[layoutKey];
+            }
+            Doc.GetProto(newDoc).text = undefined;
+            FormattedTextBox.SelectOnLoad = newDoc[Id];
+            return this.addDocument?.(newDoc);
+        }
+    }
     pointerEvents = () => {
         const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine);
         const pointerEvents = this.props.isContentActive() === false ? "none" :
@@ -1185,6 +1208,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             LayoutTemplateString={childLayout.z ? undefined : this.props.childLayoutString}
             rootSelected={childData ? this.rootSelected : returnFalse}
             onClick={this.onChildClickHandler}
+            onKey={this.onKeyDown}
             onDoubleClick={this.onChildDoubleClickHandler}
             onBrowseClick={this.onBrowseClickHandler}
             ScreenToLocalTransform={childLayout.z ? this.getContainerTransform : this.getTransform}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 1c4d47d57..29bdae170 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,14 +1,15 @@
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
-import { AclAugment, AclAdmin, AclEdit, DataSym, Doc, Opt } from "../../../../fields/Doc";
+import { AclAdmin, AclAugment, AclEdit, DataSym, Doc, Opt } from "../../../../fields/Doc";
 import { Id } from "../../../../fields/FieldSymbols";
 import { InkData, InkField, InkTool } from "../../../../fields/InkField";
 import { List } from "../../../../fields/List";
 import { RichTextField } from "../../../../fields/RichTextField";
 import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
 import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types";
+import { ImageField } from "../../../../fields/URLField";
 import { GetEffectiveAcl } from "../../../../fields/util";
-import { Utils, intersectRect, returnFalse } from "../../../../Utils";
+import { intersectRect, returnFalse, Utils } from "../../../../Utils";
 import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
 import { Docs, DocumentOptions, DocUtils } from "../../../documents/Documents";
 import { DocumentType } from "../../../documents/DocumentTypes";
@@ -21,17 +22,15 @@ import { ContextMenu } from "../../ContextMenu";
 import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
 import { PresBox } from "../../nodes/trails/PresBox";
 import { PresMovement } from "../../nodes/trails/PresEnums";
+import { VideoBox } from "../../nodes/VideoBox";
+import { pasteImageBitmap } from "../../nodes/WebBoxRenderer";
 import { PreviewCursor } from "../../PreviewCursor";
 import { CollectionDockingView } from "../CollectionDockingView";
 import { SubCollectionViewProps } from "../CollectionSubView";
-import { CollectionView } from "../CollectionView";
+import { TreeView } from "../TreeView";
 import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu";
 import "./MarqueeView.scss";
 import React = require("react");
-import { TreeView } from "../TreeView";
-import { VideoBox } from "../../nodes/VideoBox";
-import { ImageField, WebField } from "../../../../fields/URLField";
-import { pasteImageBitmap } from "../../nodes/WebBoxRenderer";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f5ad47ca7..f7312e59c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -50,6 +50,7 @@ import { ScriptingBox } from "./ScriptingBox";
 import { PresBox } from './trails/PresBox';
 import React = require("react");
 import { DocServer } from "../../DocServer";
+import { FieldViewProps } from "./FieldView";
 const { Howl } = require('howler');
 
 interface Window {
@@ -178,6 +179,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
     onPointerDown?: () => ScriptField;
     onPointerUp?: () => ScriptField;
     onBrowseClick?: () => (ScriptField | undefined);
+    onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => (boolean | undefined);
 }
 
 // these props are only available in DocumentViewIntenral
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 94937430e..79c1f1c40 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -5,7 +5,7 @@ import { DateField } from "../../../fields/DateField";
 import { Doc, Field, FieldResult, Opt } from "../../../fields/Doc";
 import { List } from "../../../fields/List";
 import { WebField } from "../../../fields/URLField";
-import { DocumentViewSharedProps } from "./DocumentView";
+import { DocumentView, DocumentViewSharedProps } from "./DocumentView";
 import { ScriptField } from "../../../fields/ScriptField";
 
 //
@@ -25,6 +25,7 @@ export interface FieldViewProps extends DocumentViewSharedProps {
     scaling?: () => number;
     setHeight?: (height: number) => void;
     onBrowseClick?: () => (ScriptField | undefined);
+    onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => (boolean | undefined);
 
     // properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React)
     pointerEvents?: () => Opt<string>;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 164bcb9b0..0e29461a6 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -17,6 +17,7 @@ import { InkTool } from '../../../../fields/InkField';
 import { PrefetchProxy } from '../../../../fields/Proxy';
 import { RichTextField } from "../../../../fields/RichTextField";
 import { RichTextUtils } from '../../../../fields/RichTextUtils';
+import { ComputedField } from '../../../../fields/ScriptField';
 import { Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
 import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, OmitKeys, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils';
@@ -62,7 +63,6 @@ import { schema } from "./schema_rts";
 import { SummaryView } from "./SummaryView";
 import applyDevTools = require("prosemirror-dev-tools");
 import React = require("react");
-import { ComputedField } from '../../../../fields/ScriptField';
 const translateGoogleApi = require("translate-google-api");
 
 export interface FormattedTextBoxProps {
@@ -1471,11 +1471,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             }, "titler");
         }
     }
+
     onKeyDown = (e: React.KeyboardEvent) => {
-        // single line text boxes need to pass through tab/enter/backspace so that their containers can respond (eg, an outline container)
-        if (this.rootDoc._singleLine && ((e.key === "Backspace" && !this.dataDoc[this.fieldKey]?.Text) || ["Tab", "Enter"].includes(e.key))) {
-            return;
-        }
         if (e.altKey) {
             e.preventDefault();
             return;
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index c76eda859..0dd0a8411 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -1,20 +1,15 @@
-import { chainCommands, exitCode, joinDown, joinUp, lift, deleteSelection, joinBackward, selectNodeBackward, setBlockType, splitBlockKeepMarks, toggleMark, wrapIn, newlineInCode } from "prosemirror-commands";
-import { liftTarget } from "prosemirror-transform";
+import { chainCommands, deleteSelection, exitCode, joinBackward, joinDown, joinUp, lift, newlineInCode, selectNodeBackward, setBlockType, splitBlockKeepMarks, toggleMark, wrapIn } from "prosemirror-commands";
 import { redo, undo } from "prosemirror-history";
 import { Schema } from "prosemirror-model";
-import { liftListItem, sinkListItem } from "./prosemirrorPatches.js";
-import { splitListItem, wrapInList, } from "prosemirror-schema-list";
-import { EditorState, Transaction, TextSelection } from "prosemirror-state";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { NumCast, BoolCast, Cast, StrCast } from "../../../../fields/Types";
-import { Doc, DataSym, DocListCast, AclAugment, AclSelfEdit } from "../../../../fields/Doc";
-import { FormattedTextBox } from "./FormattedTextBox";
-import { Id } from "../../../../fields/FieldSymbols";
-import { Docs } from "../../../documents/Documents";
-import { Utils } from "../../../../Utils";
-import { listSpec } from "../../../../fields/Schema";
-import { List } from "../../../../fields/List";
+import { splitListItem, wrapInList } from "prosemirror-schema-list";
+import { EditorState, TextSelection, Transaction } from "prosemirror-state";
+import { liftTarget } from "prosemirror-transform";
+import { AclAugment, AclSelfEdit, Doc } from "../../../../fields/Doc";
 import { GetEffectiveAcl } from "../../../../fields/util";
+import { Utils } from "../../../../Utils";
+import { Docs } from "../../../documents/Documents";
+import { SelectionManager } from "../../../util/SelectionManager";
+import { liftListItem, sinkListItem } from "./prosemirrorPatches.js";
 
 const mac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
 
@@ -48,29 +43,6 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
         keys[key] = cmd;
     }
 
-    /// bcz; Argh!!  replace with an onEnter func that conditionally handles Enter 
-    const addTextBox = (below: boolean, force?: boolean) => {
-        if (props.Document.treeViewType === "outline") return true;  // bcz: Arghh .. need to determine if this is an treeViewOutlineBox in which case Enter's are ignored..
-        const layoutDoc = props.Document;
-        const originalDoc = layoutDoc.rootDocument || layoutDoc;
-        if (force || props.Document._singleLine) {
-            const layoutKey = StrCast(originalDoc.layoutKey);
-            const newDoc = Doc.MakeCopy(originalDoc, true);
-            const dataField = originalDoc[Doc.LayoutFieldKey(newDoc)];
-            newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
-            if (below) newDoc.y = NumCast(originalDoc.y) + NumCast(originalDoc._height) + 10;
-            else newDoc.x = NumCast(originalDoc.x) + NumCast(originalDoc._width) + 10;
-            if (layoutKey !== "layout" && originalDoc[layoutKey] instanceof Doc) {
-                newDoc[layoutKey] = originalDoc[layoutKey];
-            }
-            Doc.GetProto(newDoc).text = undefined;
-            FormattedTextBox.SelectOnLoad = newDoc[Id];
-            props.addDocument(newDoc);
-            return true;
-        }
-        return false;
-    };
-
     const canEdit = (state: any) => {
         switch (GetEffectiveAcl(props.Document)) {
             case AclAugment: return false;
@@ -109,11 +81,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
     bind("Ctrl-i", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state as any, dispatch as any));
 
     bind("Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
-        /// bcz; Argh!!  replace layotuTEmpalteString with a onTab prop conditionally handles Tab);
-        if (props.Document._singleLine) {
-            if (!props.LayoutTemplateString) return addTextBox(false, true);
-            return true;
-        }
+        if (props.onKey?.({ key: "Tab" }, props)) return true;
         if (!canEdit(state)) return true;
         const ref = state.selection;
         const range = ref.$from.blockRange(ref.$to);
@@ -138,8 +106,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
     });
 
     bind("Shift-Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
-        /// bcz; Argh!!  replace with a onShiftTab prop conditionally handles Tab);
-        if (props.Document._singleLine) return true;
+        if (props.onKey?.({ key: "Tab", shiftKey: true })) return true; // single line docs don't process tabs so that their containers can decide what to do.  This should be a prop
         if (!canEdit(state)) return true;
         const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
 
@@ -188,13 +155,14 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
     };
 
     //Command to create a text document to the right of the selected textbox
-    bind("Alt-Enter", () => addTextBox(false, true));
+    bind("Alt-Enter", () => true);
 
     //Command to create a text document to the bottom of the selected textbox
-    bind("Ctrl-Enter", () => addTextBox(true, true));
+    bind("Ctrl-Enter", () => true);
 
     // backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward);
     bind("Backspace", (state: EditorState<S>, dispatch: (tx: Transaction<Schema<any, any>>) => void) => {
+        if (props.onKey?.(event, props)) return true;
         if (!canEdit(state)) return true;
 
         if (!deleteSelection(state, (tx: Transaction<S>) => {
@@ -216,8 +184,8 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
     //newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock
     //command to break line
     bind("Enter", (state: EditorState<S>, dispatch: (tx: Transaction<Schema<any, any>>) => void) => {
-        if (addTextBox(true, false)) return true;
 
+        if (props.onKey?.(event, props)) return true;
         if (!canEdit(state)) return true;
 
         const trange = state.selection.$from.blockRange(state.selection.$to);
-- 
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

