From f4446ed5f08a483abaeab3551b6e62d0a41915c8 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 14 Apr 2022 10:11:43 -0400
Subject: fixed pushpin behavior when there are multiple links to the pushpin
 (they all toggle).   changed lightboxview to allow stepping into links when
 doc has no contents.

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

(limited to 'src/client/views/LightboxView.tsx')

diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index ec3bf6c18..b39b5020c 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -36,7 +36,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
     @observable private static _tourMap: Opt<Doc[]> = [];   // list of all tours available from the current target
     private static _savedState: Opt<{ panX: Opt<number>, panY: Opt<number>, scale: Opt<number>, scrollTop: Opt<number> }>;
     private static _history: Opt<{ doc: Doc, target?: Doc }[]> = [];
-    private static _future: Opt<Doc[]> = [];
+    @observable private static _future: Opt<Doc[]> = [];
     private static _docView: Opt<DocumentView>;
     static path: { doc: Opt<Doc>, target: Opt<Doc>, history: Opt<{ doc: Doc, target?: Doc }[]>, future: Opt<Doc[]>, saved: Opt<{ panX: Opt<number>, panY: Opt<number>, scale: Opt<number>, scrollTop: Opt<number> }> }[] = [];
     @action public static SetLightboxDoc(doc: Opt<Doc>, target?: Doc, future?: Doc[], layoutTemplate?: Doc) {
@@ -195,7 +195,9 @@ export class LightboxView extends React.Component<LightboxViewProps> {
             const coll = LightboxView._docTarget;
             if (coll) {
                 const fieldKey = Doc.LayoutFieldKey(coll);
-                LightboxView.SetLightboxDoc(coll, undefined, [...DocListCast(coll[fieldKey]), ...DocListCast(coll[fieldKey + "-annotations"])]);
+                const contents = [...DocListCast(coll[fieldKey]), ...DocListCast(coll[fieldKey + "-annotations"])];
+                const links = DocListCast(coll.links).map(link => LinkManager.getOppositeAnchor(link, coll)).filter(doc => doc).map(doc => doc!);
+                LightboxView.SetLightboxDoc(coll, undefined, contents.length ? contents : links);
                 TabDocView.PinDoc(coll, { hidePresBox: true });
             }
         }
-- 
cgit v1.2.3-70-g09d2


From 74ef5f7a8c60dc68a1262077f7502d0535377b88 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 14 Apr 2022 11:49:28 -0400
Subject: fixed following links to documents in iconified collections/text to
 deiconify.  fixed ctrl-x to cut (not iconify).  changed lightboxview to add
 to future docs when stepping into.  added placeholder for indicating how many
 documents are left in lightbox future

---
 src/client/util/DocumentManager.ts                        | 14 +++++++++++++-
 src/client/views/DocumentDecorations.tsx                  |  8 ++++----
 src/client/views/GlobalKeyHandler.ts                      |  2 +-
 src/client/views/LightboxView.tsx                         | 11 ++++-------
 src/client/views/nodes/DocumentView.tsx                   | 15 +++++++++------
 src/client/views/nodes/formattedText/FormattedTextBox.tsx |  4 ++--
 6 files changed, 33 insertions(+), 21 deletions(-)

(limited to 'src/client/views/LightboxView.tsx')

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index fb50ecb4a..607a3d6bf 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -197,7 +197,14 @@ export class DocumentManager {
             (wasHidden && annoContainerView);// if we have an annotation container and the target was hidden, then try again because we just un-hid the document above
         const focusView = !docView && targetDoc.type === DocumentType.MARKER && annoContainerView ? annoContainerView : docView;
         if (!docView && annoContainerView) {
-            annoContainerView.focus(targetDoc);  // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
+            if (annoContainerView.props.Document.layoutKey === "layout_icon") {
+                annoContainerView.iconify(() => this.jumpToDocument(
+                    targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc,
+                    finished, originalTarget, noSelect, presZoom));
+                return;
+            } else {
+                annoContainerView.focus(targetDoc);  // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
+            }
         }
         if (focusView) {
             !noSelect && Doc.linkFollowHighlight(focusView.rootDoc); //TODO:glr make this a setting in PresBox
@@ -217,6 +224,11 @@ export class DocumentManager {
                     targetDocContextView.props.focus(targetDocContextView.rootDoc, {
                         willZoom, afterFocus: async () => {
                             targetDocContext._viewTransition = undefined;
+                            if (targetDocContext.layoutKey === "layout_icon") {
+                                targetDocContextView.iconify(() => this.jumpToDocument(
+                                    targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc,
+                                    finished, originalTarget, noSelect, presZoom));
+                            }
                             return ViewAdjustment.doNothing;
                         }
                     });
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index a8d91e0a2..78a8a4c7e 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -145,11 +145,11 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
     }
 
     _iconifyTimeout: NodeJS.Timeout | undefined;
-    onCloseClick = () => {
+    onCloseClick = (force = false) => {
         if (this.canDelete) {
             const views = SelectionManager.Views().slice().filter(v => v);
-            const icons = this._iconifyTimeout ? views : views.filter(view => view.rootDoc.layoutKey === "layout_icon");
-            const others = this._iconifyTimeout ? [] : views.filter(view => view.rootDoc.layoutKey !== "layout_icon");
+            const icons = this._iconifyTimeout || force ? views : views.filter(view => view.rootDoc.layoutKey === "layout_icon");
+            const others = this._iconifyTimeout || force ? [] : views.filter(view => view.rootDoc.layoutKey !== "layout_icon");
             icons.forEach(iconView => iconView.props.removeDocument?.(iconView.props.Document));
             others.forEach(dv => dv.iconify());
             others.length && (this._iconifyTimeout = setTimeout(() => {
@@ -519,7 +519,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
                     left: bounds.x - this._resizeBorderWidth / 2,
                     top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
                 }}>
-                    {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, this.onCloseClick, "Close")}
+                    {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, e => this.onCloseClick(), "Close")}
                     {titleArea}
                     {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
                     {hideResizers ? (null) :
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 91e0503b3..e3031d2c5 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -275,7 +275,7 @@ export class KeyManager {
                     const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
                     const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":");
                     SelectionManager.Views().length && navigator.clipboard.writeText(text);
-                    DocumentDecorations.Instance.onCloseClick();
+                    DocumentDecorations.Instance.onCloseClick(true);
                     stopPropagation = false;
                     preventDefault = false;
                 }
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index b39b5020c..59ed0dc92 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -63,7 +63,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
             }
         }
         if (future) {
-            this._future = future.slice().sort((a, b) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow)).sort((a, b) => DocListCast(a.links).length - DocListCast(b.links).length);
+            this._future = [...(this._future ?? []), ...(this.LightboxDoc ? [this.LightboxDoc] : []), ...future.slice().sort((a, b) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow)).sort((a, b) => DocListCast(a.links).length - DocListCast(b.links).length),];
         }
         this._doc = doc;
         this._layoutTemplate = layoutTemplate;
@@ -118,7 +118,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
     addDocTab = LightboxView.AddDocTab;
     @action public static Next() {
         const doc = LightboxView._doc!;
-        const target = LightboxView._docTarget = LightboxView._future?.pop();
+        const target = LightboxView._docTarget = this._future?.pop();
         const targetDocView = target && DocumentManager.Instance.getLightboxDocumentView(target);
         if (targetDocView && target) {
             const l = DocUtils.MakeLinkToActiveAudio(() => targetDocView.ComponentView?.getAnchor?.() || target).lastElement();
@@ -163,11 +163,8 @@ export class LightboxView extends React.Component<LightboxViewProps> {
         const docView = DocumentManager.Instance.getLightboxDocumentView(target || doc);
         if (docView) {
             LightboxView._docTarget = target;
-            const focusSpeed = 1000;
-            doc._viewTransition = `transform ${focusSpeed}ms`;
             if (!target) docView.ComponentView?.shrinkWrap?.();
             else docView.focus(target, { willZoom: true, scale: 0.9 });
-            setTimeout(() => doc._viewTransition = undefined, focusSpeed);
         }
         else {
             LightboxView.SetLightboxDoc(doc, target);
@@ -232,7 +229,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                             const doc = LightboxView._doc;
                             const targetView = target && DocumentManager.Instance.getLightboxDocumentView(target);
                             if (doc === r.props.Document && (!target || target === doc)) r.ComponentView?.shrinkWrap?.();
-                            else target && targetView?.focus(target, { willZoom: true, scale: 0.9, instant: true });
+                            //else target && targetView?.focus(target, { willZoom: true, scale: 0.9, instant: true }); // bcz: why was this here?  it breaks smooth navigation in lightbox using 'next' button
                         }));
                     })}
                         Document={LightboxView.LightboxDoc}
@@ -272,7 +269,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                     () => LightboxView.LightboxDoc && LightboxView._future?.length ? "" : "none", e => {
                         e.stopPropagation();
                         LightboxView.Next();
-                    })}
+                    }, this.future()?.length.toString())}
                 <LightboxTourBtn navBtn={this.navBtn} future={this.future} stepInto={this.stepInto} tourMap={this.tourMap} />
                 <div className="lightboxView-tabBtn" title={"open in tab"}
                     onClick={e => {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0e22b1b3f..4380cb0bc 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -452,7 +452,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         });
         // after  a timeout, the right _componentView should have been created, so call it to update its view spec values
         setTimeout(() => this._componentView?.setViewSpec?.(anchor, LinkDocPreview.LinkInfo ? true : false));
-        const focusSpeed = this._componentView?.scrollFocus?.(anchor, !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here
+        const focusSpeed = this._componentView?.scrollFocus?.(anchor, !options?.instant || !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here
         const endFocus = focusSpeed === undefined ? options?.afterFocus : async (moved: boolean) => options?.afterFocus ? options?.afterFocus(true) : ViewAdjustment.doNothing;
         this.props.focus(options?.docTransform ? anchor : this.rootDoc, {
             ...options, afterFocus: (didFocus: boolean) =>
@@ -1243,15 +1243,15 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         return { left, top, right, bottom, center: this.ComponentView?.getCenter?.(xf) };
     }
 
-    public iconify() {
+    public iconify(finished?: () => void) {
         this.ComponentView?.updateIcon?.();
         const layoutKey = Cast(this.Document.layoutKey, "string", null);
         if (layoutKey !== "layout_icon") {
-            this.switchViews(true, "icon");
+            this.switchViews(true, "icon", finished);
             if (layoutKey && layoutKey !== "layout" && layoutKey !== "layout_icon") this.Document.deiconifyLayout = layoutKey.replace("layout_", "");
         } else {
             const deiconifyLayout = Cast(this.Document.deiconifyLayout, "string", null);
-            this.switchViews(deiconifyLayout ? true : false, deiconifyLayout);
+            this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finished);
             this.Document.deiconifyLayout = undefined;
             this.props.bringToFront(this.rootDoc);
         }
@@ -1262,12 +1262,15 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         Doc.setNativeView(this.props.Document);
         custom && DocUtils.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
     }
-    switchViews = action((custom: boolean, view: string) => {
+    switchViews = action((custom: boolean, view: string, finished?: () => void) => {
         this.docView && (this.docView._animateScalingTo = 0.1);  // shrink doc
         setTimeout(action(() => {
             this.setCustomView(custom, view);
             this.docView && (this.docView._animateScalingTo = 1); // expand it
-            setTimeout(action(() => this.docView && (this.docView._animateScalingTo = 0)), this.docView!._animateScaleTime - 10);
+            setTimeout(action(() => {
+                this.docView && (this.docView._animateScalingTo = 0);
+                finished?.();
+            }), this.docView!._animateScaleTime - 10);
         }), this.docView!._animateScaleTime - 10);
     });
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index b6713d878..ac291801b 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -758,7 +758,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             const splitter = state.schema.marks.splitter.create({ id: Utils.GenerateGuid() });
             let tr = state.tr.addMark(sel.from, sel.to, splitter);
             if (sel.from !== sel.to) {
-                const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: "#" + this._editorView?.state.doc.textBetween(sel.from, sel.to), unrendered: true });
+                const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: "#" + this._editorView?.state.doc.textBetween(sel.from, sel.to), annotationOn: this.dataDoc, unrendered: true });
                 const href = targetHref ?? Doc.localServerPath(anchor);
                 if (anchor !== anchorDoc) this.addDocument(anchor);
                 tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => {
@@ -859,7 +859,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             ({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => {
                 autoHeight && this.props.setHeight?.(marginsHeight + Math.max(sidebarHeight, textHeight));
             }, { fireImmediately: true });
-        this._disposers.links = reaction(() => DocListCast(this.Document.links), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks
+        this._disposers.links = reaction(() => DocListCast(this.dataDoc.links), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks
             newLinks => {
                 this._cachedLinks.forEach(l => !newLinks.includes(l) && this.RemoveLinkFromDoc(l));
                 this._cachedLinks = newLinks;
-- 
cgit v1.2.3-70-g09d2

