From 7fedb7f75829269e46da5eaeb3b58166f9ab2126 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Feb 2021 00:48:40 -0500
Subject: fixes for removing individual overlapping textanchors in a textBox.
 Hopefully near final cleanup of linkDocPreview and FormattedTextComment

---
 src/client/views/nodes/LinkDocPreview.tsx | 100 ++++++++++++------------------
 1 file changed, 40 insertions(+), 60 deletions(-)

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

diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 463719824..576d1d15b 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -13,11 +13,12 @@ import { Transform } from "../../util/Transform";
 import { DocumentView, DocumentViewSharedProps } from "./DocumentView";
 import './LinkDocPreview.scss';
 import React = require("react");
+import { undoBatch } from '../../util/UndoManager';
 
 interface LinkDocPreviewProps {
     linkDoc?: Doc;
     linkSrc?: Doc;
-    docprops: DocumentViewSharedProps;
+    docProps: DocumentViewSharedProps;
     location: number[];
     hrefs?: string[];
     showHeader?: boolean;
@@ -34,25 +35,24 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
     @observable _linkSrc: Opt<Doc>;
     @observable _toolTipText = "";
     @observable _hrefInd = 0;
-    @observable _linkTarget: Opt<Doc>;
 
-    @action componentDidUpdate(props: any) {
-        if (props.linkSrc !== this.props.linkSrc ||
-            props.linkDoc !== this.props.linkDoc ||
-            props.hrefs !== this.props.hrefs) {
-            this._linkTarget = this.props.linkDoc;
-            this._linkSrc = this.props.linkSrc;
-            this._linkDoc = this.props.linkDoc;
-            this._toolTipText = "";
-            this.updatePreview();
-        }
-    }
-    @action componentDidMount() {
-        this._linkTarget = this.props.linkDoc;
+    @action init() {
+        var linkTarget = this.props.linkDoc;
         this._linkSrc = this.props.linkSrc;
         this._linkDoc = this.props.linkDoc;
+        const anchor1 = this._linkDoc?.anchor1 as Doc;
+        const anchor2 = this._linkDoc?.anchor2 as Doc;
+        if (anchor1 && anchor2) {
+            linkTarget = Doc.AreProtosEqual(anchor1, this._linkSrc) || Doc.AreProtosEqual(anchor1?.annotationOn as Doc, this._linkSrc) ? anchor2 : anchor1;
+        }
+        this._targetDoc = linkTarget?.annotationOn as Doc ?? linkTarget;
         this._toolTipText = "";
-        this.updatePreview();
+    }
+    componentDidUpdate(props: any) {
+        if (props.linkSrc !== this.props.linkSrc || props.linkDoc !== this.props.linkDoc || props.hrefs !== this.props.hrefs) this.init();
+    }
+    componentDidMount() {
+        this.init();
         document.addEventListener("pointerdown", this.onPointerDown);
     }
 
@@ -62,66 +62,46 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
     }
 
     onPointerDown = (e: PointerEvent) => {
-        !this._infoRef.current?.contains(e.target as any) && LinkDocPreview.Clear();
+        !this._infoRef.current?.contains(e.target as any) && LinkDocPreview.Clear(); // close preview when not clicking anywhere other than the info bar of the preview
     }
 
-    updatePreview() {
-        const linkDoc = this.props.linkDoc;
-        const linkSrc = this.props.linkSrc;
+    @computed get href() {
         if (this.props.hrefs?.length) {
             const href = this.props.hrefs[this._hrefInd];
-            if (href.indexOf(Utils.prepend("/doc/")) !== 0) {
+            if (href.indexOf(Utils.prepend("/doc/")) !== 0) {  // link to a web page URL -- try to show a preview
                 if (href.startsWith("https://en.wikipedia.org/wiki/")) {
                     wiki().page(href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500))));
                 } else {
-                    runInAction(() => this._toolTipText = "external => " + href);
+                    setTimeout(action(() => this._toolTipText = "url => " + href));
                 }
-            } else {
+            } else { // hyperlink to a document .. decode doc id and retrieve from the server. this will trigger vals() being invalidated
                 const anchorDoc = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
-                anchorDoc && DocServer.GetRefField(anchorDoc).then(action(async anchor => {
+                anchorDoc && DocServer.GetRefField(anchorDoc).then(action(anchor => {
                     if (anchor instanceof Doc && DocListCast(anchor.links).length) {
                         this._linkDoc = DocListCast(anchor.links)[0];
                         this._linkSrc = anchor;
-                        const targetanchor = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc);
-                        runInAction(async () => {
-                            this._linkTarget = targetanchor;
-                            const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget;
-                            runInAction(() => {
-                                this._toolTipText = "";
-                                this._targetDoc = target;
-                            });
-                        });
+                        const linkTarget = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc);
+                        this._targetDoc = linkTarget?.annotationOn as Doc ?? linkTarget;
+                        this._toolTipText = "";
                     }
                 }));
             }
-        } else if (linkDoc) {
-            const anchor1 = linkDoc.anchor1 as Doc;
-            const anchor2 = linkDoc.anchor2 as Doc;
-            runInAction(async () => {
-                this._linkTarget = Doc.AreProtosEqual(anchor1, linkSrc) || Doc.AreProtosEqual(anchor1.annotationOn as Doc, linkSrc) ? anchor2 : anchor1;
-                const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget;
-                runInAction(() => {
-                    this._toolTipText = "";
-                    this._targetDoc = target;
-                });
-            });
+            return href;
         }
+        return undefined;
     }
     deleteLink = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => this._linkDoc ? LinkManager.Instance.deleteLink(this._linkDoc) : null));
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(() => this._linkDoc && LinkManager.Instance.deleteLink(this._linkDoc)));
     }
     nextHref = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => {
-            this._hrefInd = (this._hrefInd + 1) % (this.props.hrefs?.length || 1);
-            this.updatePreview();
-        }));
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => this._hrefInd = (this._hrefInd + 1) % (this.props.hrefs?.length || 1)));
     }
 
     followLink = (e: React.PointerEvent) => {
         if (this._linkDoc && this._linkSrc) {
-            LinkManager.FollowLink(this._linkDoc, this._linkSrc, this.props.docprops, false);
+            LinkManager.FollowLink(this._linkDoc, this._linkSrc, this.props.docProps, false);
         } else if (this.props.hrefs?.length) {
-            this.props.docprops?.addDocTab(Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _width: 200, _height: 400, useCors: true }), "add:right");
+            this.props.docProps?.addDocTab(Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _width: 200, _height: 400, useCors: true }), "add:right");
         }
     }
     width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225));
@@ -133,13 +113,12 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
                     {StrCast(this._targetDoc.title).length > 16 ? StrCast(this._targetDoc.title).substr(0, 16) + "..." : this._targetDoc.title}
                     <p className="linkDocPreview-description"> {StrCast(this._linkDoc.description)}</p>
                 </div>
-                <div className="wrapper" style={{ float: "right" }}>
-                    {(this.props.hrefs?.length || 0) <= 1 ? (null) :
-                        <Tooltip title={<div className="dash-tooltip">Next Link</div>} placement="top">
-                            <div className="linkDocPreview-button" onPointerDown={this.nextHref}>
-                                <FontAwesomeIcon className="linkDocPreview-fa-icon" icon="chevron-right" color="white" size="sm" />
-                            </div>
-                        </Tooltip>}
+                <div className="linkDocPreview-buttonBar" >
+                    <Tooltip title={<div className="dash-tooltip">Next Link</div>} placement="top">
+                        <div className="linkDocPreview-button" style={{ background: (this.props.hrefs?.length || 0) <= 1 ? "gray" : "green" }} onPointerDown={this.nextHref}>
+                            <FontAwesomeIcon className="linkDocPreview-fa-icon" icon="chevron-right" color="white" size="sm" />
+                        </div>
+                    </Tooltip>
 
                     <Tooltip title={<div className="dash-tooltip">Delete Link</div>} placement="top">
                         <div className="linkDocPreview-button" onPointerDown={this.deleteLink}>
@@ -151,6 +130,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
     }
 
     @computed get docPreview() {
+        const href = this.href; // needs to be here to trigger lookup of web pages and docs on server
         return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? (null) :
             <div className="linkDocPreview-inner">
                 {!this.props.showHeader ? (null) : this.previewHeader}
@@ -163,8 +143,8 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
                             Document={this._targetDoc!}
                             moveDocument={returnFalse}
                             rootSelected={returnFalse}
-                            styleProvider={this.props.docprops?.styleProvider}
-                            layerProvider={this.props.docprops?.layerProvider}
+                            styleProvider={this.props.docProps?.styleProvider}
+                            layerProvider={this.props.docProps?.layerProvider}
                             docViewPath={emptyPath}
                             ScreenToLocalTransform={Transform.Identity}
                             parentActive={returnFalse}
-- 
cgit v1.2.3-70-g09d2

