From 3573a81d334cf8cc13d19b04c6f2094c24c43932 Mon Sep 17 00:00:00 2001
From: Aubrey Li <Aubrey-Li>
Date: Thu, 3 Mar 2022 18:12:13 -0500
Subject: edit: lightbox opens tab in the same stack

---
 src/client/views/collections/TabDocView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 7e57d0e89..c11b6c7b3 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -300,7 +300,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
             case "lightbox": {
                 // TabDocView.PinDoc(doc, { hidePresBox: true });
-                return LightboxView.AddDocTab(doc, location);
+                return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
             }
             case "inPlace":
             case "add":
-- 
cgit v1.2.3-70-g09d2


From 58114c03252463b7386d16fc2aef61c361038bfa Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 2 Jun 2022 15:44:23 -0400
Subject: fixed previously introduced bug where pin doc added pres to first tab
 collection.  Highlight pres targets when following.  fixed videoBox to play
 regions properly.  adjusted labelBox for stackedTimeline views.  fixed
 stacked timelines to not stop keyboard events which was preventing text notes
 from being created on video boxes.

---
 src/Utils.ts                                         |  2 +-
 .../views/collections/CollectionStackedTimeline.tsx  |  9 +++++++--
 src/client/views/collections/TabDocView.tsx          |  4 +---
 src/client/views/nodes/LabelBox.tsx                  | 20 +++++++++++---------
 src/client/views/nodes/VideoBox.tsx                  |  2 ++
 src/client/views/nodes/trails/PresBox.tsx            |  1 +
 src/fields/Doc.ts                                    |  4 ++--
 src/fields/List.ts                                   |  1 +
 8 files changed, 26 insertions(+), 17 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index dbae0aa8c..e6aa0ad8b 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -209,7 +209,7 @@ export namespace Utils {
         if (scrollTop + contextHgt < Math.min(scrollHeight, targetY + minSpacing + targetHgt)) {
             return Math.ceil(targetY + minSpacing + targetHgt - contextHgt);
         }
-        if (scrollTop > Math.max(0, targetY - minSpacing - targetHgt)) {
+        if (scrollTop >= Math.max(0, targetY - minSpacing - targetHgt)) {
             return Math.max(0, Math.floor(targetY - minSpacing - targetHgt));
         }
     }
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 02b2248fb..5a1cc4ded 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -22,6 +22,7 @@ import {
     returnOne, returnTrue, setupMoveUpEvents, smoothScrollHorizontal, StopEvent
 } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
+import { DocumentType } from "../../documents/DocumentTypes";
 import { DocumentManager } from "../../util/DocumentManager";
 import { DragManager } from "../../util/DragManager";
 import { LinkManager } from "../../util/LinkManager";
@@ -182,7 +183,6 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
         ) {
             // if shift pressed scrub 1 second otherwise 1/10th
             const jump = e.shiftKey ? 1 : 0.1;
-            e.stopPropagation();
             switch (e.key) {
                 case " ":
                     if (!CollectionStackedTimeline.SelectingRegion) {
@@ -202,18 +202,22 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
                         this._markerEnd = undefined;
                         CollectionStackedTimeline.SelectingRegion = undefined;
                     }
+                    e.stopPropagation();
                     break;
                 case "Escape":
                     // abandons current trim
                     this._trimStart = this.clipStart;
                     this._trimStart = this.clipEnd;
                     this._trimming = TrimScope.None;
+                    e.stopPropagation();
                     break;
                 case "ArrowLeft":
                     this.props.setTime(Math.min(Math.max(this.clipStart, this.currentTime - jump), this.clipEnd));
+                    e.stopPropagation();
                     break;
                 case "ArrowRight":
                     this.props.setTime(Math.min(Math.max(this.clipStart, this.currentTime + jump), this.clipEnd));
+                    e.stopPropagation();
                     break;
             }
         }
@@ -788,6 +792,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
 
     // updates marker document title to reflect correct timecodes
     computeTitle = () => {
+        if (this.props.mark.type !== DocumentType.LABEL) return undefined;
         const start = Math.max(NumCast(this.props.mark[this.props.startTag]), this.props.trimStart) - this.props.trimStart;
         const end = Math.min(NumCast(this.props.mark[this.props.endTag]), this.props.trimEnd) - this.props.trimStart;
         return `#${formatTime(start)}-${formatTime(end)}`;
@@ -921,7 +926,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
                     DataDoc={undefined}
                     renderDepth={this.props.renderDepth + 1}
                     LayoutTemplate={undefined}
-                    LayoutTemplateString={LabelBox.LayoutStringWithTitle(LabelBox, "data", this.computeTitle())}
+                    LayoutTemplateString={LabelBox.LayoutStringWithTitle("data", this.computeTitle())}
                     isDocumentActive={this.props.isDocumentActive}
                     PanelWidth={width}
                     PanelHeight={height}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 2b78b20ea..be68e1001 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -236,9 +236,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
             const dview = CollectionDockingView.Instance.props.Document;
             const fieldKey = CollectionDockingView.Instance.props.fieldKey;
-            const sublists = DocListCast(dview[fieldKey]);
-            const tabs = Cast(sublists[0], Doc, null);
-            const tabdocs = await DocListCastAsync(tabs?.data);
+            const tabdocs = await DocListCastAsync(dview[fieldKey]);
             runInAction(() => {
                 if (!pinProps?.hidePresBox && !tabdocs?.includes(curPres)) {
                     tabdocs?.push(curPres);  // bcz: Argh! this is annoying.  if multiple documents are pinned, this will get called multiple times before the presentation view is drawn.  Thus it won't be in the tabdocs list and it will get created multple times.  so need to explicilty add the presbox to the list of open tabs
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index d0d61fd79..b0b050cea 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -23,8 +23,8 @@ export interface LabelBoxProps {
 @observer
 export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxProps)>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LabelBox, fieldKey); }
-    public static LayoutStringWithTitle(fieldType: { name: string }, fieldStr: string, label: string) {
-        return `<${fieldType.name} fieldKey={'${fieldStr}'} label={'${label}'} {...props} />`;  //e.g., "<ImageBox {...props} fieldKey={"data} />"
+    public static LayoutStringWithTitle(fieldStr: string, label?: string) {
+        return !label ? LabelBox.LayoutString(fieldStr) : `<LabelBox fieldKey={'${fieldStr}'} label={'${label}'} {...props} />`;  //e.g., "<ImageBox {...props} fieldKey={"data} />"
     }
     private dropDisposer?: DragManager.DragDropDisposer;
     private _timeout: any;
@@ -79,17 +79,18 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
     @computed get hoverColor() { return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : "unset"; }
 
     fitTextToBox = (r: any): any => {
+        const singleLine = BoolCast(this.rootDoc._singleLine, true);
         const params = {
             rotateText: null,
             fontSizeFactor: 1,
-            minimumFontSize: NumCast(this.rootDoc._minFontSize, 2),
+            minimumFontSize: NumCast(this.rootDoc._minFontSize, 8),
             maximumFontSize: NumCast(this.rootDoc._maxFontSize, 1000),
             limitingDimension: "both",
             horizontalAlign: "center",
             verticalAlign: "center",
             textAlign: "center",
-            singleLine: BoolCast(this.rootDoc._singleLine),
-            whiteSpace: this.rootDoc._singleLine ? "nowrap" : "pre-wrap"
+            singleLine,
+            whiteSpace: singleLine ? "nowrap" : "pre-wrap"
         };
         this._timeout = undefined;
         if (!r) return params;
@@ -99,15 +100,16 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
         parentStyle.display = "";
         parentStyle.alignItems = "";
         r.setAttribute("style", "");
-        r.style.width = this.rootDoc._singleLine ? "" : "100%";
+        r.style.width = singleLine ? "" : "100%";
 
         r.style.textOverflow = "ellipsis";
         r.style.overflow = "hidden";
         BigText(r, params);
+        return params;
     }
     // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")")
     render() {
-        this.fitTextToBox(null);// this causes mobx to trigger re-render when data changes
+        const boxParams = this.fitTextToBox(null);// this causes mobx to trigger re-render when data changes
         const params = Cast(this.paramsDoc["onClick-paramFieldKeys"], listSpec("string"), []);
         const missingParams = params?.filter(p => !this.paramsDoc[p]);
         params?.map(p => DocListCast(this.paramsDoc[p])); // bcz: really hacky form of prefetching ...
@@ -130,9 +132,9 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
                     paddingBottom: NumCast(this.rootDoc._yPadding),
                     width: this.props.PanelWidth(),
                     height: this.props.PanelHeight(),
-                    whiteSpace: this.rootDoc._singleLine ? "pre" : "pre-wrap"
+                    whiteSpace: boxParams.singleLine ? "pre" : "pre-wrap"
                 }} >
-                    <span style={{ width: this.layoutDoc._singleLine ? "" : "100%" }} ref={action((r: any) => this.fitTextToBox(r))}>
+                    <span style={{ width: boxParams.singleLine ? "" : "100%" }} ref={action((r: any) => this.fitTextToBox(r))}>
                         {label.startsWith("#") ? (null) : label.replace(/([^a-zA-Z])/g, "$1\u200b")}
                     </span>
                 </div>
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index c350e3139..ac848fc2a 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -147,6 +147,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
 
     // plays video
     @action public Play = (update: boolean = true) => {
+        if (this._playRegionTimer) return;
         this._playing = true;
         const eleTime = this.player?.currentTime || 0;
         if (this.timeline) {
@@ -558,6 +559,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                         // removes from currently playing if playback has reached end of range marker
                         else this.removeCurrentlyPlaying();
                         this.Pause();
+                        this._playRegionTimer = undefined;
                     }, playRegionDuration * 1000);
             } else {
                 this.Pause();
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 9641b403f..077db9077 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -297,6 +297,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 this.startTempMedia(targetDoc, activeItem);
             }
             if (targetDoc) {
+                Doc.linkFollowHighlight((targetDoc.annotationOn instanceof Doc) ? [targetDoc, targetDoc.annotationOn] : targetDoc);
                 targetDoc && runInAction(() => {
                     if (activeItem.presMovement === PresMovement.Jump) targetDoc.focusSpeed = 0;
                     else targetDoc.focusSpeed = activeItem.presTransition ? activeItem.presTransition : 500;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index b0a45091e..6abc27b23 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1073,9 +1073,9 @@ export namespace Doc {
     }
 
     let _lastDate = 0;
-    export function linkFollowHighlight(destDoc: Doc, dataAndDisplayDocs = true) {
+    export function linkFollowHighlight(destDoc: Doc | Doc[], dataAndDisplayDocs = true) {
         linkFollowUnhighlight();
-        Doc.HighlightDoc(destDoc, dataAndDisplayDocs);
+        (destDoc instanceof Doc ? [destDoc] : destDoc).forEach(doc => Doc.HighlightDoc(doc, dataAndDisplayDocs));
         document.removeEventListener("pointerdown", linkFollowUnhighlight);
         document.addEventListener("pointerdown", linkFollowUnhighlight);
         const lastDate = _lastDate = Date.now();
diff --git a/src/fields/List.ts b/src/fields/List.ts
index 60bf442d4..b15548327 100644
--- a/src/fields/List.ts
+++ b/src/fields/List.ts
@@ -32,6 +32,7 @@ const listHandlers: any = {
     },
     push: action(function (this: any, ...items: any[]) {
         items = items.map(toObjectField);
+
         const list = this[Self];
         const length = list.__fields.length;
         for (let i = 0; i < items.length; i++) {
-- 
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/TabDocView.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 84e843ccb21dcb95dff11e34b749f4587fc0fd86 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 4 Jun 2022 23:21:17 -0400
Subject: fixed mini-pres view css, fixed interaction with mini-pres by fixing
 overlayView panelWidth/height, fixed tabMap to get updated properly to allow
 CloseSplit to work, etc.

---
 src/client/views/OverlayView.tsx            | 12 +++---
 src/client/views/StyleProvider.tsx          |  2 +-
 src/client/views/collections/TabDocView.tsx |  2 +-
 src/client/views/nodes/trails/PresBox.scss  |  7 +--
 src/client/views/nodes/trails/PresBox.tsx   | 67 ++++++++++++++++++++---------
 5 files changed, 58 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index ebad2981d..18b87e3d5 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -2,10 +2,10 @@ import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import * as React from "react";
 import ReactLoading from 'react-loading';
-import { Doc } from "../../fields/Doc";
+import { Doc, HeightSym, WidthSym } from "../../fields/Doc";
 import { Id } from "../../fields/FieldSymbols";
 import { Cast, NumCast } from "../../fields/Types";
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue, setupMoveUpEvents, Utils } from "../../Utils";
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from "../../Utils";
 import { DocUtils } from "../documents/Documents";
 import { CurrentUserUtils } from "../util/CurrentUserUtils";
 import { DragManager } from "../util/DragManager";
@@ -186,12 +186,12 @@ export class OverlayView extends React.Component {
                     bringToFront={emptyFunction}
                     addDocument={undefined}
                     removeDocument={undefined}
-                    PanelWidth={returnOne}
-                    PanelHeight={returnOne}
+                    PanelWidth={d[WidthSym]}
+                    PanelHeight={d[HeightSym]}
                     ScreenToLocalTransform={Transform.Identity}
                     renderDepth={1}
-                    isDocumentActive={returnTrue}
-                    isContentActive={emptyFunction}
+                    isDocumentActive={returnFalse}
+                    isContentActive={returnTrue}
                     whenChildContentsActiveChanged={emptyFunction}
                     focus={DocUtils.DefaultFocus}
                     styleProvider={DefaultStyleProvider}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 553f84a67..35415ae4e 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -136,7 +136,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                         StrCast(props?.Document.backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : "")));
             switch (doc?.type) {
                 case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break;
-                case DocumentType.PRES: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
+                case DocumentType.PRES: docColor = docColor || (darkScheme() ? "transparent" : "transparent"); break;
                 case DocumentType.FONTICON: docColor = docColor || Colors.DARK_GRAY; break;
                 case DocumentType.RTF: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
                 case DocumentType.FILTER: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : "rgba(105, 105, 105, 0.432)"); break;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index d64cb2fd7..ad01be3a3 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -76,7 +76,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             tab._disposers = {} as { [name: string]: IReactionDisposer };
             tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true);
             tab.DashDoc = doc;
-            CollectionDockingView.Instance.tabMap.add(tab);
             const iconType: IconProp = Doc.toIcon(doc);
             // setup the title element and set its size according to the # of chars in the title.  Show the full title when clicked.
             const titleEle = tab.titleElement[0];
@@ -186,6 +185,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab");
                 });
         }
+        CollectionDockingView.Instance.tabMap.add(tab);
     }
 
     /**
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index 06932d145..a0a2dd4f8 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -1078,11 +1078,13 @@
 .miniPres {
     cursor: grab;
     position: absolute;
-    right: 10;
-    top: 10;
+    top: 0;
+    left: 0;
     opacity: 0.1;
     transition: all 0.4s;
     color: $white;
+    width: 100%;
+    height: 100%;
 }
 
 .miniPres:hover {
@@ -1101,7 +1103,6 @@
     align-items: center;
     display: flex;
     position: absolute;
-    right: 10px;
     transition: all 0.2s;
 
     .presPanel-button-text {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 0af7715fe..914d6ab15 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -12,7 +12,7 @@ import { PrefetchProxy } from "../../../../fields/Proxy";
 import { listSpec } from "../../../../fields/Schema";
 import { ScriptField } from "../../../../fields/ScriptField";
 import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types";
-import { emptyFunction, returnFalse, returnOne, returnTrue } from '../../../../Utils';
+import { emptyFunction, returnFalse, returnOne, returnTrue, setupMoveUpEvents } from '../../../../Utils';
 import { Docs } from "../../../documents/Documents";
 import { DocumentType } from "../../../documents/DocumentTypes";
 import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
@@ -604,27 +604,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
      * The method called to open the presentation as a minimized view
      */
     @action
-    updateMinimize = () => {
-        const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc);
+    updateMinimize = async () => {
         if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
-            console.log("case 1");
             this.layoutDoc.presStatus = PresStatus.Edit;
             Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
             CollectionDockingView.AddSplit(this.rootDoc, "right");
-        } else if ((true || this.layoutDoc.context) && docView) {
-            console.log("case 2");
+        } else {
             this.layoutDoc.presStatus = PresStatus.Edit;
             clearTimeout(this._presTimer);
             const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
             this.rootDoc.x = pt[0] + (this.props.PanelWidth() - 250);
             this.rootDoc.y = pt[1] + 10;
-            this.rootDoc._height = 35;
-            this.rootDoc._width = 250;
-            docView.props.removeDocument?.(this.layoutDoc);
+            this.rootDoc._height = 30;
+            this.rootDoc._width = 248;
+            this.props.removeDocument?.(this.layoutDoc);
             Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
-        } else {
-            console.log("case 3");
-            // TODO glr: fix this case
         }
     }
 
@@ -2424,6 +2418,31 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         else this.pauseAutoPres();
     }
 
+    @action
+    prevClicked = (e: PointerEvent) => {
+        this.back();
+        if (this._presTimer) {
+            clearTimeout(this._presTimer);
+            this.layoutDoc.presStatus = PresStatus.Manual;
+        }
+    }
+
+    @action
+    nextClicked = (e: PointerEvent) => {
+        this.next();
+        if (this._presTimer) {
+            clearTimeout(this._presTimer);
+            this.layoutDoc.presStatus = PresStatus.Manual;
+        }
+    }
+    @undoBatch
+    @action
+    exitClicked = (e: PointerEvent) => {
+        this.updateMinimize();
+        this.layoutDoc.presStatus = PresStatus.Edit;
+        clearTimeout(this._presTimer);
+    }
+
     @action
     startMarqueeCreateSlide = () => {
         PresBox.startMarquee = true;
@@ -2465,28 +2484,34 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return CurrentUserUtils.OverlayDocs.includes(this.rootDoc) ?
             <div className="miniPres">
                 <div className="presPanelOverlay" style={{ display: "inline-flex", height: 30, background: '#323232', top: 0, zIndex: 3000000, boxShadow: presKeyEvents ? '0 0 0px 3px ' + Colors.MEDIUM_BLUE : undefined }}>
-                    <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
+                    <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : undefined }}
+                        onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.layoutDoc.presLoop = !this.layoutDoc.presLoop, false, false)}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
                     <div className="presPanel-divider"></div>
-                    <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div>
-                    <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
-                    <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }} onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
+                    <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }}
+                        onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.prevClicked, false, false)}><FontAwesomeIcon icon={"arrow-left"} /></div>
+                    <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button"
+                        onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.startOrPause, false, false)}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
+                    <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }}
+                        onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.nextClicked, false, false)}><FontAwesomeIcon icon={"arrow-right"} /></div>
                     <div className="presPanel-divider"></div>
-                    <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }} onClick={() => this.gotoDocument(0, this.activeItem)}><b>1</b></div></Tooltip>
+                    <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }}
+                        onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.gotoDocument(0, this.activeItem), false, false)}><b>1</b></div></Tooltip>
                     <div className="presPanel-button-text">
                         Slide {this.itemIndex + 1} / {this.childDocs.length}
                         {this.playButtonFrames}
                     </div>
-                    <div className="presPanel-divider"></div>
-                    <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.updateMinimize(); this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); }))}>EXIT</div>
+                    <div className="presPanel-divider" />
+                    <div className="presPanel-button-text" onPointerDown={e =>
+                        setupMoveUpEvents(this, e, returnFalse, returnFalse, this.exitClicked, false, false)}>EXIT</div>
                 </div>
-            </div>
+            </div >
             :
             <div className="presBox-cont" style={{ minWidth: CurrentUserUtils.OverlayDocs.includes(this.layoutDoc) ? 240 : undefined }} >
                 {this.topPanel}
                 {this.toolbar}
                 {this.newDocumentToolbarDropdown}
                 <div className="presBox-listCont">
-                    <div className="Slide" style={{ height: `calc(100% - 100px)` }}>
+                    <div className="Slide" style={{ height: `calc(100% - 30px)` }}>
                         {mode !== CollectionViewType.Invalid ?
                             <CollectionView {...this.props}
                                 ContainingCollectionDoc={this.props.Document}
-- 
cgit v1.2.3-70-g09d2


From acf19e54a43d5b05c58ef3c80d27086dd64f8e8e Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Sun, 5 Jun 2022 16:38:46 +0100
Subject: updated and refactored pinWithView

Changed MarqueeView pinWithView so that it just calls TabDocView.PinDoc
---
 .vscode/settings.json                              |   2 +-
 src/client/views/collections/TabDocView.tsx        |  11 +-
 .../collections/collectionFreeForm/MarqueeView.tsx | 122 +++++----------------
 src/client/views/nodes/trails/PresBox.tsx          |  13 ++-
 4 files changed, 50 insertions(+), 98 deletions(-)

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

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 27acfd1a2..a6e6ad360 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -6,7 +6,7 @@
         "**/CVS": true,
         "**/.DS_Store": true,
     },
-    "editor.formatOnSave": true,
+    "editor.formatOnSave": false,
     "editor.detectIndentation": false,
     "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
     "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true,
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index ad01be3a3..0cd3fb5a7 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -193,10 +193,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
      **/
     @action
     public static async PinDoc(doc: Doc, pinProps?: PinProps) {
-        if (pinProps?.unpin) console.log('TODO: Remove UNPIN from this location');
         //add this new doc to props.Document
+
+        // all docs will be added to the ActivePresentation as stored on CurrentUserUtils
         const curPres = CurrentUserUtils.ActivePresentation;
         if (curPres) {
+            // Edge Case 1: Cannot pin document to itself
             if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; }
             const batch = UndoManager.StartBatch("pinning doc");
             const pinDoc = Doc.MakeAlias(doc);
@@ -239,6 +241,13 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             const dview = CollectionDockingView.Instance.props.Document;
             const fieldKey = CollectionDockingView.Instance.props.fieldKey;
             const tabdocs = await DocListCastAsync(dview[fieldKey]);
+			if (pinProps?.pinWithView) {
+				const viewProps = pinProps.pinWithView;
+				pinDoc.presPinView = true;
+            	pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
+            	pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
+            	pinDoc.presPinViewScale = viewProps.scale;
+			}
             runInAction(() => {
                 if (!pinProps?.hidePresBox && !tabdocs?.includes(curPres)) {
                     tabdocs?.push(curPres);  // bcz: Argh! this is annoying.  if multiple documents are pinned, this will get called multiple times before the presentation view is drawn.  Thus it won't be in the tabdocs list and it will get created multple times.  so need to explicilty add the presbox to the list of open tabs
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 8ca7e160e..362117b19 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -20,7 +20,7 @@ import { Transform } from "../../../util/Transform";
 import { undoBatch, UndoManager } from "../../../util/UndoManager";
 import { ContextMenu } from "../../ContextMenu";
 import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
-import { PresBox } from "../../nodes/trails/PresBox";
+import { PinViewProps, PresBox } from "../../nodes/trails/PresBox";
 import { PresMovement } from "../../nodes/trails/PresEnums";
 import { VideoBox } from "../../nodes/VideoBox";
 import { pasteImageBitmap } from "../../nodes/WebBoxRenderer";
@@ -31,6 +31,7 @@ import { TreeView } from "../TreeView";
 import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu";
 import "./MarqueeView.scss";
 import React = require("react");
+import { TabDocView } from "../TabDocView";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -44,6 +45,14 @@ interface MarqueeViewProps {
     ungroup?: () => void;
     setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void;
 }
+
+export interface MarqueeViewBounds {
+	left: number;
+	top: number;
+	width: number;
+	height: number;
+}
+
 @observer
 export class MarqueeView extends React.Component<SubCollectionViewProps & MarqueeViewProps>
 {
@@ -60,7 +69,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
     @computed get Bounds() {
         const topLeft = this.Transform.transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY);
         const size = this.Transform.transformDirection(this._lastX - this._downX, this._lastY - this._downY);
-        return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) };
+		const bounds:MarqueeViewBounds = { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }
+        return bounds;
     }
     get inkDoc() { return this.props.Document; }
     get ink() { return Cast(this.props.Document.ink, InkField); }
@@ -263,7 +273,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             document.removeEventListener("wheel", hideMarquee);
         };
         if (PresBox.startMarquee) {
-            this.pinMarqueeView();
+            this.pinWithView();
             PresBox.startMarquee = false;
         }
         if (!this._commandExecuted && (Math.abs(this.Bounds.height * this.Bounds.width) > 100) && !PresBox.startMarquee) {
@@ -385,98 +395,24 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
         this.hideMarquee();
     }
 
+	/**
+	 * This triggers the TabDocView.PinDoc method which is the universal method
+	 * used to pin documents to the currently active presentation trail. 
+	 * 
+	 * This one is unique in that it includes the bounds associated with marquee view. 
+	 */
     @undoBatch
     @action
-    pinMarqueeView = async () => {
-        const doc = this.props.Document;
-        const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
-        if (curPres) {
-            console.log(curPres);
-            if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; }
-            const pinDoc = Doc.MakeAlias(doc);
-            pinDoc.presentationTargetDoc = doc;
-            pinDoc.presMovement = PresMovement.Zoom;
-            pinDoc.groupWithUp = false;
-            pinDoc.context = curPres;
-            pinDoc.title = doc.title + " - Slide";// these should potentially all be props passed down by the CollectionTreeView to the TreeView elements.  That way the PresBox could configure all of its children at render time
-            pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
-            pinDoc.treeViewHeaderWidth = "100%"; // forces the header to grow to be the same size as its largest sibling.
-            pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
-            pinDoc.treeViewFieldKey = "data"; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
-            pinDoc.treeViewExpandedView = "data";// in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
-            pinDoc.treeViewGrowsHorizontally = true;// the document expands horizontally when displayed as a tree view header  
-            pinDoc.treeViewHideHeaderIfTemplate = true;  // this will force the document to render itself as the tree view header
-
-            const presArray = PresBox.Instance?.sortArray();
-            const size = PresBox.Instance?._selectedArray.size;
-            const presSelected = presArray && size ? presArray[size - 1] : undefined;
-            Doc.AddDocToList(curPres, "data", pinDoc, presSelected);
-            if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
-            const dview = CollectionDockingView.Instance.props.Document;
-            const fieldKey = CollectionDockingView.Instance.props.fieldKey;
-            const tabdocs = await DocListCastAsync(dview[fieldKey]);
-            if (!tabdocs?.includes(curPres)) {
-                tabdocs?.push(curPres);  // bcz: Argh! this is annoying.  if multiple documents are pinned, this will get called multiple times before the presentation view is drawn.  Thus it won't be in the tabdocs list and it will get created multple times.  so need to explicilty add the presbox to the list of open tabs
-                CollectionDockingView.AddSplit(curPres, "right");
-            }
-            PresBox.Instance?._selectedArray.clear();
-            pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Updates selected array
-            const index = PresBox.Instance?.childDocs.indexOf(pinDoc);
-            index && (curPres._itemIndex = index);
-            const scale = Math.min(this.props.PanelWidth() / this.Bounds.width, this.props.PanelHeight() / this.Bounds.height);
-            pinDoc.presPinView = true;
-            pinDoc.presPinViewX = this.Bounds.left + this.Bounds.width / 2;
-            pinDoc.presPinViewY = this.Bounds.top + this.Bounds.height / 2;
-            pinDoc.presPinViewScale = scale;
-        }
-        this.hideMarquee();
-    }
-
-    @undoBatch
-    @action
-    pinWithView = async (e: KeyboardEvent | React.PointerEvent | undefined) => {
-        const doc = this.props.Document;
-        const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
-        if (curPres) {
-            if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; }
-            const pinDoc = Doc.MakeAlias(doc);
-            pinDoc.presentationTargetDoc = doc;
-            pinDoc.presMovement = PresMovement.Zoom;
-            pinDoc.groupWithUp = false;
-            pinDoc.context = curPres;
-            pinDoc.title = doc.title + " - Slide";
-            pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
-            pinDoc.treeViewHeaderWidth = "100%"; // forces the header to grow to be the same size as its largest sibling.
-            pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
-            pinDoc.treeViewFieldKey = "data"; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
-            pinDoc.treeViewExpandedView = "data";// in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
-            pinDoc.treeViewGrowsHorizontally = true;// the document expands horizontally when displayed as a tree view header  
-            pinDoc.treeViewHideHeaderIfTemplate = true;  // this will force the document to render itself as the tree view header
-
-            const presArray = PresBox.Instance?.sortArray();
-            const size = PresBox.Instance?._selectedArray.size;
-            const presSelected = presArray && size ? presArray[size - 1] : undefined;
-            Doc.AddDocToList(curPres, "data", pinDoc, presSelected);
-            if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; const dview = CollectionDockingView.Instance.props.Document;
-            const fieldKey = CollectionDockingView.Instance.props.fieldKey;
-            const tabdocs = await DocListCastAsync(dview[fieldKey]);
-            if (!tabdocs?.includes(curPres)) {
-                tabdocs?.push(curPres);  // bcz: Argh! this is annoying.  if multiple documents are pinned, this will get called multiple times before the presentation view is drawn.  Thus it won't be in the tabdocs list and it will get created multple times.  so need to explicilty add the presbox to the list of open tabs
-                CollectionDockingView.AddSplit(curPres, "right");
-            }
-            PresBox.Instance?._selectedArray.clear();
-            pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Updates selected array
-            const index = PresBox.Instance?.childDocs.indexOf(pinDoc);
-            index && (curPres._itemIndex = index);
-            if (e instanceof KeyboardEvent ? e.key === "c" : true) {
-                const scale = Math.min(this.props.PanelWidth() / this.Bounds.width, this.props.PanelHeight() / this.Bounds.height);
-                pinDoc.presPinView = true;
-                pinDoc.presPinViewX = this.Bounds.left + this.Bounds.width / 2;
-                pinDoc.presPinViewY = this.Bounds.top + this.Bounds.height / 2;
-                pinDoc.presPinViewScale = scale;
-            }
-        }
-        MarqueeOptionsMenu.Instance.fadeOut(true);
+    pinWithView = async () => {
+		console.log("pinWithView");
+        const scale = Math.min(this.props.PanelWidth() / this.Bounds.width, this.props.PanelHeight() / this.Bounds.height);
+		const doc = this.props.Document;
+		const viewOptions:PinViewProps = {
+			bounds: this.Bounds,
+			scale: scale
+		};
+		TabDocView.PinDoc(doc, {pinWithView: viewOptions});
+		MarqueeOptionsMenu.Instance.fadeOut(true);
         this.hideMarquee();
     }
 
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index ab5382581..3a29d9adf 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -30,14 +30,21 @@ import { CollectionFreeFormDocumentView } from "../CollectionFreeFormDocumentVie
 import { FieldView, FieldViewProps } from '../FieldView';
 import "./PresBox.scss";
 import { PresEffect, PresMovement, PresStatus } from "./PresEnums";
+import { MarqueeViewBounds } from "../../collections/collectionFreeForm";
 
-export class PinProps {
+export interface PinProps {
     audioRange?: boolean;
-    unpin?: boolean;
     setPosition?: boolean;
     hidePresBox?: boolean;
+    pinWithView?: PinViewProps;
 }
 
+export interface PinViewProps {
+  bounds: MarqueeViewBounds;
+  scale: number;
+}
+
+
 @observer
 export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
@@ -2543,7 +2550,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
 // this func communicates with PresBoxElement to send information of the doc
 ScriptingGlobals.add(function lookupPresBoxField(presBoxDoc: Doc, field: string, presEleDoc: Doc) {
     if (field === 'indexInPres') return DocListCast(presBoxDoc._viewType === CollectionViewType.Tree ? presBoxDoc.presentationLinearizedDocuments : presBoxDoc[StrCast(presBoxDoc.presentationFieldKey)]).indexOf(presEleDoc);
-    if (field === 'presCollapsedHeight') return [CollectionViewType.Tree || CollectionViewType.Stacking].includes(presBoxDoc._viewType as any) ? 35 : 31;
+    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;
-- 
cgit v1.2.3-70-g09d2


From d939e83f1279cb010b3573f0ac02ba4dc7c3cb37 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Sun, 5 Jun 2022 17:11:22 +0100
Subject: updates and attempts at debugging

---
 src/client/views/collections/TabDocView.tsx | 15 ++++++++-------
 src/client/views/nodes/trails/PresBox.tsx   |  5 +++++
 2 files changed, 13 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 0cd3fb5a7..004032282 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -220,6 +220,14 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             const size: number = PresBox.Instance?._selectedArray.size;
             const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
             const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
+			// If pinWithView option set then update scale and x / y props of slide
+			if (pinProps?.pinWithView) {
+				const viewProps = pinProps.pinWithView;
+				pinDoc.presPinView = true;
+            	pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
+            	pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
+            	pinDoc.presPinViewScale = viewProps.scale;
+			}
             Doc.AddDocToList(curPres, "data", pinDoc, presSelected);
             if (!pinProps?.audioRange && duration !== undefined) {
                 pinDoc.mediaStart = "manual";
@@ -241,13 +249,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             const dview = CollectionDockingView.Instance.props.Document;
             const fieldKey = CollectionDockingView.Instance.props.fieldKey;
             const tabdocs = await DocListCastAsync(dview[fieldKey]);
-			if (pinProps?.pinWithView) {
-				const viewProps = pinProps.pinWithView;
-				pinDoc.presPinView = true;
-            	pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
-            	pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
-            	pinDoc.presPinViewScale = viewProps.scale;
-			}
             runInAction(() => {
                 if (!pinProps?.hidePresBox && !tabdocs?.includes(curPres)) {
                     tabdocs?.push(curPres);  // bcz: Argh! this is annoying.  if multiple documents are pinned, this will get called multiple times before the presentation view is drawn.  Thus it won't be in the tabdocs list and it will get created multple times.  so need to explicilty add the presbox to the list of open tabs
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 3a29d9adf..ca71c76a9 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -335,7 +335,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     navigateToView = (targetDoc: Doc, activeItem: Doc) => {
         clearTimeout(this._navTimer);
         const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document;
+        if (bestTarget) console.log(bestTarget.title, bestTarget.type);
+        else console.log("no best target");
         bestTarget && runInAction(() => {
+            console.log(bestTarget.title, bestTarget.type);
             if (bestTarget.type === DocumentType.PDF || bestTarget.type === DocumentType.WEB || bestTarget.type === DocumentType.RTF || bestTarget._viewType === CollectionViewType.Stacking) {
                 bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
                 bestTarget._scrollTop = activeItem.presPinViewScroll;
@@ -417,6 +420,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         // 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.
         if (activeItem.presPinView) {
+            console.log(targetDoc.title);
+            console.log("presPinView in PresBox.tsx:420");
             // if targetDoc is not displayed but one of its aliases is, then we need to modify that alias, not the original target
             this.navigateToView(targetDoc, activeItem);
         }
-- 
cgit v1.2.3-70-g09d2


From 0371242941dfdd1d689d0097140b203bb0b24dea Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 5 Jun 2022 20:16:02 -0400
Subject: fixed presentations to allow pinning a clip of audio.  fixed
 TabDocViews to be added properly to DocumentManager.  fixed presentations to
 allow groupWithUp to work in tree/stacking view modes.  f

---
 src/client/views/collections/TabDocView.tsx | 3 +++
 src/client/views/nodes/AudioBox.tsx         | 1 -
 src/client/views/nodes/trails/PresBox.tsx   | 4 ++--
 3 files changed, 5 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index ad01be3a3..dab3d490d 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -265,6 +265,9 @@ export class TabDocView extends React.Component<TabDocViewProps> {
         //     ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""),
         //     { fireImmediately: true });
     }
+    componentDidUpdate() {
+        this._view && DocumentManager.Instance.AddView(this._view);
+    }
 
     componentWillUnmount() {
         this._tabReaction?.();
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index d97cb6f84..85dfd1e9a 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -611,7 +611,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                 renderDepth={this.props.renderDepth + 1}
                 startTag={"_timecodeToShow" /* audioStart */}
                 endTag={"_timecodeToHide" /* audioEnd */}
-                focus={DocUtils.DefaultFocus}
                 bringToFront={emptyFunction}
                 CollectionView={undefined}
                 playFrom={this.playFrom}
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 18344a11d..e32f2826f 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -319,7 +319,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             }
             if (!group) this._selectedArray.clear();
             this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //Update selected array
-            if ([CollectionViewType.Stacking, CollectionViewType.Tree].includes(this.layoutDoc._viewType as any) && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
+            this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
             this.onHideDocument(); //Handles hide after/before
         }
     });
@@ -357,7 +357,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     navigateToElement = async (curDoc: Doc) => {
         const activeItem: Doc = this.activeItem;
         const targetDoc: Doc = this.targetDoc;
-        const srcContext = Cast(targetDoc.context, Doc, null);
+        const srcContext = Cast(targetDoc.context, Doc, null) ?? Cast(Cast(targetDoc.annotationOn, Doc, null)?.context, Doc, null);
         const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
         const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined;
         const includesDoc: boolean = DocListCast(presCollection?.data).includes(targetDoc);
-- 
cgit v1.2.3-70-g09d2


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

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

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

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


From 5157f0c500b01a635c373cc661a2588ef7506d79 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Jun 2022 12:44:36 -0400
Subject: added context menu back to tab's via the doc icon.  made docicon
 draggable and clickable. removed collectiondockingviewmenu.

---
 src/client/goldenLayout.js                         |  5 ++-
 .../views/collections/CollectionDockingView.tsx    |  3 +-
 .../collections/CollectionDockingViewMenu.scss     | 34 ---------------
 .../collections/CollectionDockingViewMenu.tsx      | 48 --------------------
 src/client/views/collections/TabDocView.tsx        | 51 +++++++++++-----------
 5 files changed, 31 insertions(+), 110 deletions(-)
 delete mode 100644 src/client/views/collections/CollectionDockingViewMenu.scss
 delete mode 100644 src/client/views/collections/CollectionDockingViewMenu.tsx

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

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index 4735f216f..012ee163c 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -458,8 +458,9 @@
                 if (this._bDragging === true) {
                     this._bDragging = false;
                     this.emit('dragStop', oEvent, this._nOriginalX + this._nX);
-                } else if (oEvent.target) { // make title receive pointer events to allow setting insertion position or selecting texst range
-                    if (oEvent.target.className.includes("lm_title_wrap")) {
+                } else  { // make title receive pointer events to allow setting insertion position or selecting texst range
+                    const classname = typeof oEvent.target?.className === "string" ? oEvent.target.className : "";
+                    if (classname.includes("lm_title_wrap")) {
                         oEvent.target.children[0].style.pointerEvents = "all";
                         oEvent.target.children[0].focus();
                     }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 745565ff5..476ffaf81 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -362,7 +362,8 @@ export class CollectionDockingView extends CollectionSubView() {
             const htmlTarget = e.target as HTMLElement;
             window.addEventListener("mouseup", this.onPointerUp);
             if (!htmlTarget.closest("*.lm_content") && (htmlTarget.closest("*.lm_tab") || htmlTarget.closest("*.lm_stack"))) {
-                if (!htmlTarget.className.includes("lm_close") && !htmlTarget.className.includes("lm_maximise")) {
+                const className = typeof htmlTarget.className === "string" ? htmlTarget.className : "";
+                if (!className.includes("lm_close") && !className.includes("lm_maximise")) {
                     this._flush = UndoManager.StartBatch("golden layout edit");
                 }
             }
diff --git a/src/client/views/collections/CollectionDockingViewMenu.scss b/src/client/views/collections/CollectionDockingViewMenu.scss
deleted file mode 100644
index 4157f0f7e..000000000
--- a/src/client/views/collections/CollectionDockingViewMenu.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-
-.dockingViewButtonSelector {
-    div {
-        overflow: visible !important;
-    }
-
-    display: inline-block;
-    width:100%;
-    height:100%;
-}
-.dockingViewButtonSelector-flyout {
-    position: relative;
-    z-index: 9999;
-    background-color: #eeeeee;
-    box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
-    color: black;
-
-    padding: 10px;
-    border-radius: 3px;
-    display: inline-block;
-    height: 100%;
-    width: 100%;
-    border-radius: 3px;
-
-    hr {
-        height: 1px;
-        margin: 0px;
-        background-color: gray;
-        border-top: 0px;
-        border-bottom: 0px;
-        border-right: 0px;
-        border-left: 0px;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionDockingViewMenu.tsx b/src/client/views/collections/CollectionDockingViewMenu.tsx
deleted file mode 100644
index 1cab293a8..000000000
--- a/src/client/views/collections/CollectionDockingViewMenu.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
-import { action, computed, observable } from "mobx";
-import { observer } from "mobx-react";
-import * as React from "react";
-import { DocumentButtonBar } from "../DocumentButtonBar";
-import { DocumentView } from "../nodes/DocumentView";
-const higflyout = require("@hig/flyout");
-export const { anchorPoints } = higflyout;
-export const Flyout = higflyout.default;
-
-@observer
-export class CollectionDockingViewMenu extends React.Component<{ views: () => DocumentView[], Stack: any }> {
-    customStylesheet(styles: any) {
-        return {
-            ...styles,
-            panel: {
-                ...styles.panel,
-                minWidth: "100px"
-            },
-        };
-    }
-    _ref = React.createRef<HTMLDivElement>();
-
-    @computed get flyout() {
-        return (
-            <div className="dockingViewButtonSelector-flyout" title=" " ref={this._ref}>
-                <DocumentButtonBar views={this.props.views} stack={this.props.Stack} />
-            </div>
-        );
-    }
-
-    @observable _tooltipOpen: boolean = false;
-    render() {
-        return <Tooltip open={this._tooltipOpen} onClose={action(() => this._tooltipOpen = false)} title={<><div className="dash-tooltip">Tap for toolbar, drag to create alias in another pane</div></>} placement="bottom">
-            <span className="dockingViewButtonSelector"
-                onPointerEnter={action(() => !this._ref.current?.getBoundingClientRect().width && (this._tooltipOpen = true))}
-                onPointerDown={action(e => {
-                    this.props.views()[0]?.select(false);
-                    this._tooltipOpen = false;
-                })} >
-                <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyout} stylesheet={this.customStylesheet}>
-                    <FontAwesomeIcon icon={"arrows-alt"} size={"sm"} />
-                </Flyout>
-            </span>
-        </Tooltip >;
-    }
-}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 75a8207dd..91c6975ea 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -4,15 +4,15 @@ import { Tooltip } from '@material-ui/core';
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
 import { clamp } from 'lodash';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
 import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
-import { DataSym, Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { FieldId } from "../../../fields/RefField";
 import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils";
+import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { DocUtils } from '../../documents/Documents';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -27,10 +27,10 @@ import { Colors, Shadows } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
 import { MainView } from '../MainView';
 import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
+import { DashFieldView } from '../nodes/formattedText/DashFieldView';
 import { PinProps, PresBox, PresMovement } from '../nodes/trails';
 import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
 import { CollectionDockingView } from './CollectionDockingView';
-import { CollectionDockingViewMenu } from './CollectionDockingViewMenu';
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TabDocView.scss";
@@ -92,14 +92,28 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 Doc.GetProto(doc).title = e.currentTarget.value;
             }));
 
-            const dragBtnDown = (e: React.PointerEvent) => {
-                setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction);
-            };
-
-
             if (tab.element[0].children[1].children.length === 1) {
-                iconWrap.className = "lm_iconWrap";
-                iconWrap.id = "lm_iconWrap";
+                iconWrap.className = "lm_iconWrap lm_moreInfo";
+                const dragBtnDown = (e: React.PointerEvent) => {
+                    setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, action(e => {
+                        if (this.view) {
+                            SelectionManager.SelectView(this.view, false);
+                            let child = this.view.ContentDiv!.children[0];
+                            while (child.children.length) {
+                                const next = Array.from(child.children).find(c => c.className?.toString().includes("SVGAnimatedString") || typeof (c.className) === "string");
+                                if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
+                                if (next?.className?.toString().includes(DashFieldView.name)) break;
+                                if (next) child = next;
+                                else break;
+                            }
+                            simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+                        }
+                        else { this._activated = true;
+                              setTimeout(() =>this.view && SelectionManager.SelectView(this.view, false));
+                        }
+                    }));
+                };
+
                 closeWrap.className = "lm_iconWrap";
                 closeWrap.id = "lm_closeWrap";
                 closeWrap.onclick = (e: MouseEvent) => {
@@ -111,6 +125,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 const closeIcon = <FontAwesomeIcon icon={"times"} />;
                 ReactDOM.render(docIcon, iconWrap);
                 ReactDOM.render(closeIcon, closeWrap);
+                tab.reactComponents = [iconWrap, closeWrap];
                 // tab.element[0].append(closeWrap);
                 tab.element[0].prepend(iconWrap);
                 tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
@@ -122,7 +137,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                         titleEle.style.backgroundColor = "transparent";
                         iconWrap.style.color = textColor;
                         closeWrap.style.color = textColor;
-                        moreInfoDrag.style.backgroundColor = textColor;
                         tab.element[0].style.background = !layer ? color : "dimgrey";
                     }, { fireImmediately: true });
             }
@@ -155,19 +169,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     // toggle.style.textTransform = selected ? "uppercase" : "";
                 }));
 
-            //attach the selection doc buttons menu to the drag handle
-            const stack: HTMLDivElement = tab.contentItem.parent;
-            const header: HTMLDivElement = tab;
-            stack.onscroll = action((e: any) => {
-                console.log('scrolling...');
-            });
-            const moreInfoDrag = document.createElement("div");
-            moreInfoDrag.className = "lm_iconWrap";
-            tab._disposers.buttonDisposer = reaction(() => this.view, view =>
-                view && [ReactDOM.render(<span><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, moreInfoDrag), tab._disposers.buttonDisposer?.()],
-                { fireImmediately: true });
-            // tab.reactComponents = [moreInfoDrag];
-            // tab.element[0].children[3].before(moreInfoDrag);
 
             // highlight the tab when the tab document is brushed in any part of the UI
             tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => {
-- 
cgit v1.2.3-70-g09d2


From 94975954fbd1ce9b68f6545b16a4eabe4b41cca0 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Jun 2022 14:30:18 -0400
Subject: fixed bug with adding to pres when in miniview mode.

---
 .../views/collections/CollectionDockingView.tsx    | 69 ++++++++++------------
 src/client/views/collections/TabDocView.tsx        |  3 +
 src/client/views/nodes/trails/PresBox.tsx          |  4 +-
 3 files changed, 37 insertions(+), 39 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 476ffaf81..a790a0475 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -172,12 +172,6 @@ export class CollectionDockingView extends CollectionSubView() {
     @undoBatch
     @action
     public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) {
-        if (document.type === DocumentType.PRES) {
-            const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []);
-            if (docs.includes(document)) {
-                docs.splice(docs.indexOf(document), 1);
-            }
-        }
         if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document);
 
         const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document);
@@ -186,6 +180,7 @@ export class CollectionDockingView extends CollectionSubView() {
             return true;
         }
         const instance = CollectionDockingView.Instance;
+        const glayRoot = instance._goldenLayout.root;
         if (!instance) return false;
         const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
 
@@ -194,29 +189,29 @@ export class CollectionDockingView extends CollectionSubView() {
             stack.setActiveContentItem(stack.contentItems[stack.contentItems.length - 1]);
         } else {
             const newItemStackConfig = { type: 'stack', content: [docContentConfig] };
-            const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
-            if (instance._goldenLayout.root.contentItems.length === 0) { // if no rows / columns
-                instance._goldenLayout.root.addChild(newContentItem);
-            } else if (instance._goldenLayout.root.contentItems[0].isStack) {
-                instance._goldenLayout.root.contentItems[0].addChild(docContentConfig);
+            const newContentItem = glayRoot.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
+            if (glayRoot.contentItems.length === 0) { // if no rows / columns
+                glayRoot.addChild(newContentItem);
+            } else if (glayRoot.contentItems[0].isStack) {
+                glayRoot.contentItems[0].addChild(docContentConfig);
             } else if (
-                instance._goldenLayout.root.contentItems.length === 1 &&
-                instance._goldenLayout.root.contentItems[0].contentItems.length === 1 &&
-                instance._goldenLayout.root.contentItems[0].contentItems[0].contentItems.length === 0) {
-                instance._goldenLayout.root.contentItems[0].contentItems[0].addChild(docContentConfig);
+                glayRoot.contentItems.length === 1 &&
+                glayRoot.contentItems[0].contentItems.length === 1 &&
+                glayRoot.contentItems[0].contentItems[0].contentItems.length === 0) {
+                glayRoot.contentItems[0].contentItems[0].addChild(docContentConfig);
             }
             else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row
                 switch (pullSide) {
                     default:
-                    case "right": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break;
-                    case "left": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break;
+                    case "right": glayRoot.contentItems[0].addChild(newContentItem); break;
+                    case "left": glayRoot.contentItems[0].addChild(newContentItem, 0); break;
                     case "top":
                     case "bottom":
                         // if not going in a row layout, must add already existing content into column
-                        const rowlayout = instance._goldenLayout.root.contentItems[0];
+                        const rowlayout = glayRoot.contentItems[0];
                         const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout);
 
-                        CollectionDockingView.Instance._goldenLayout.saveScrollTops(rowlayout.element);
+                        instance._goldenLayout.saveScrollTops(rowlayout.element);
                         rowlayout.parent.replaceChild(rowlayout, newColumn);
                         if (pullSide === "top") {
                             newColumn.addChild(rowlayout, undefined, true);
@@ -225,23 +220,23 @@ export class CollectionDockingView extends CollectionSubView() {
                             newColumn.addChild(newContentItem, undefined, true);
                             newColumn.addChild(rowlayout, 0, true);
                         }
-                        CollectionDockingView.Instance._goldenLayout.restoreScrollTops(rowlayout.element);
+                        instance._goldenLayout.restoreScrollTops(rowlayout.element);
 
                         rowlayout.config.height = 50;
                         newContentItem.config.height = 50;
                 }
             } else {// if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
                 switch (pullSide) {
-                    case "top": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break;
-                    case "bottom": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break;
+                    case "top": glayRoot.contentItems[0].addChild(newContentItem, 0); break;
+                    case "bottom": glayRoot.contentItems[0].addChild(newContentItem); break;
                     case "left":
                     case "right":
                     default:
                         // if not going in a row layout, must add already existing content into column
-                        const collayout = instance._goldenLayout.root.contentItems[0];
+                        const collayout = glayRoot.contentItems[0];
                         const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
 
-                        CollectionDockingView.Instance._goldenLayout.saveScrollTops(collayout.element);
+                        instance._goldenLayout.saveScrollTops(collayout.element);
                         collayout.parent.replaceChild(collayout, newRow);
                         if (pullSide === "left") {
                             newRow.addChild(collayout, undefined, true);
@@ -250,7 +245,7 @@ export class CollectionDockingView extends CollectionSubView() {
                             newRow.addChild(newContentItem, undefined, true);
                             newRow.addChild(collayout, 0, true);
                         }
-                        CollectionDockingView.Instance._goldenLayout.restoreScrollTops(collayout.element);
+                        instance._goldenLayout.restoreScrollTops(collayout.element);
 
                         collayout.config.width = 50;
                         newContentItem.config.width = 50;
@@ -289,19 +284,19 @@ export class CollectionDockingView extends CollectionSubView() {
                         this._goldenLayout.unbind('stackCreated', this.stackCreated);
                     } catch (e) { }
                 }
+                this.tabMap.clear();
+                this._goldenLayout.destroy();
             }
-            this.tabMap.clear();
-            this._goldenLayout?.destroy();
-            this._goldenLayout = new GoldenLayout(JSON.parse(config));
-            this._goldenLayout.on('tabCreated', this.tabCreated);
-            this._goldenLayout.on('tabDestroyed', this.tabDestroyed);
-            this._goldenLayout.on('stackCreated', this.stackCreated);
-            this._goldenLayout.registerComponent('DocumentFrameRenderer', TabDocView);
-            this._goldenLayout.container = this._containerRef.current;
-            this._goldenLayout.init();
-            this._goldenLayout.root.layoutManager.on('itemDropped', this.tabItemDropped);
-            this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart);
-            this._goldenLayout.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
+            const glay = this._goldenLayout = new GoldenLayout(JSON.parse(config));
+            glay.on('tabCreated', this.tabCreated);
+            glay.on('tabDestroyed', this.tabDestroyed);
+            glay.on('stackCreated', this.stackCreated);
+            glay.registerComponent('DocumentFrameRenderer', TabDocView);
+            glay.container = this._containerRef.current;
+            glay.init();
+            glay.root.layoutManager.on('itemDropped', this.tabItemDropped);
+            glay.root.layoutManager.on('dragStart', this.tabDragStart);
+            glay.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
         }
     }
 
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 91c6975ea..34fe572e3 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -35,6 +35,7 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TabDocView.scss";
 import React = require("react");
+import { listSpec } from '../../../fields/Schema';
 const _global = (window /* browser */ || global /* node */) as any;
 
 interface TabDocViewProps {
@@ -246,6 +247,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             }
             if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
             if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
+                const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []);
+                if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
                 CollectionDockingView.AddSplit(curPres, "right");
                 setTimeout(() => DocumentManager.Instance.jumpToDocument(doc, false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
             }
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 1a4be8e0c..591480023 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -403,11 +403,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             // openInTab(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 ? [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 ? [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.
-- 
cgit v1.2.3-70-g09d2

