From 09e6a1f83de643437d03deac57e1cdebc68d6140 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 4 Feb 2021 16:18:35 -0500
Subject: fixed marquee annotations for web/pdf when scrolled

---
 src/client/views/nodes/VideoBox.tsx | 1 +
 1 file changed, 1 insertion(+)

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

diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 8a1cefbd9..760620b19 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -574,6 +574,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
                 {this.renderTimeline}
                 {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
                     <MarqueeAnnotator
+                        scrollTop={0}
                         rootDoc={this.rootDoc}
                         down={this._marqueeing}
                         scaling={this.marqueeFitScaling}
-- 
cgit v1.2.3-70-g09d2


From 81bd2378ffa753e851390c2616e66a71d23c9989 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 9 Feb 2021 12:16:25 -0500
Subject: started to cleanup LinkDocPreview, LinkMenu.

---
 src/client/util/LinkManager.ts                     |   1 -
 src/client/views/DocumentDecorations.scss          |   2 +-
 src/client/views/MainView.tsx                      |   2 +-
 src/client/views/linking/LinkMenu.scss             |  40 ++------
 src/client/views/linking/LinkMenu.tsx              |  76 +++++---------
 src/client/views/linking/LinkMenuGroup.tsx         |  10 +-
 src/client/views/linking/LinkMenuItem.tsx          | 112 +++++++--------------
 src/client/views/nodes/AudioBox.tsx                |   4 +-
 src/client/views/nodes/DocumentLinksButton.tsx     |  10 +-
 src/client/views/nodes/DocumentView.tsx            |   2 +-
 src/client/views/nodes/LinkAnchorBox.tsx           |   4 +-
 src/client/views/nodes/LinkDocPreview.tsx          |  30 ++----
 src/client/views/nodes/VideoBox.tsx                |   4 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   4 +-
 .../formattedText/FormattedTextBoxComment.tsx      |  10 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     |   2 +-
 .../views/nodes/formattedText/TooltipTextMenu.scss |   2 +-
 17 files changed, 105 insertions(+), 210 deletions(-)

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

diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index afc0e76be..ecf245d03 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -129,7 +129,6 @@ export class LinkManager {
         await LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined);
     }
     public static async traverseLink(link: Opt<Doc>, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) {
-        LinkDocPreview.TargetDoc = undefined;
         FormattedTextBoxComment.linkDoc = undefined;
         const linkDocs = link ? [link] : DocListCast(doc.links);
         const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 461ea0fef..de8a3c909 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -4,7 +4,7 @@ $linkGap : 3px;
 
 .documentDecorations {
     position: absolute;
-    z-index: 20000;
+    z-index: 2000;
 }
 
 .documentDecorations-container {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index bc3d05005..d53e66c47 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -625,7 +625,7 @@ export class MainView extends React.Component {
             {this.search}
             <CollectionMenu />
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
-            {DocumentLinksButton.EditLink ? <LinkMenu docView={DocumentLinksButton.EditLink} docprops={DocumentLinksButton.EditLink.props} changeFlyout={emptyFunction} /> : (null)}
+            {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} docprops={LinkDocPreview.LinkInfo.docprops}
                 linkDoc={LinkDocPreview.LinkInfo.linkDoc} linkSrc={LinkDocPreview.LinkInfo.linkSrc} href={LinkDocPreview.LinkInfo.href} /> : (null)}
             <GestureOverlay >
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index ebf8878cb..a90bf8b0a 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -4,29 +4,23 @@
     width: auto;
     height: auto;
     position: absolute;
-    z-index: 20001;
-
-    .linkMenu-list {
+    z-index: 2001;
 
+    .linkMenu-list,
+    .linkMenu-listEditor
+     {
         display: inline-block;
-
+        position: relative;
         border: 1px solid black;
-
         box-shadow: 3px 3px 1.5px grey;
+        background: white;
 
+        min-width: 170px;
         max-height: 170px;
         overflow-y: scroll;
-        position: relative;
         z-index: 10;
-        background: white;
-        min-width: 170px;
-        //border-radius: 5px;
-        //padding-top: 6.5px;
-        //padding-bottom: 6.5px;
-        //padding-left: 6.5px;
-        //padding-right: 2px;
-        //width: calc(auto + 50px);
-
+     }
+     .linkMenu-list {
         white-space: nowrap;
         overflow-x: hidden;
         width: 240px;
@@ -40,22 +34,6 @@
             scrollbar-color: rgb(201, 239, 252);
         }
     }
-
-    .linkMenu-listEditor {
-
-        display: inline-block;
-
-        border: 1px solid black;
-
-        box-shadow: 3px 3px 1.5px grey;
-
-        max-height: 170px;
-        overflow-y: scroll;
-        position: relative;
-        z-index: 10;
-        background: white;
-        min-width: 170px;
-    }
 }
 
 .linkMenu-group {
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index b32022024..8cd069210 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -13,49 +13,28 @@ import React = require("react");
 interface Props {
     docView: DocumentView;
     changeFlyout: () => void;
-    docprops: DocumentViewSharedProps;
 }
 
 @observer
 export class LinkMenu extends React.Component<Props> {
-
-    @observable private _editingLink?: Doc;
-    @observable private _linkMenuRef = React.createRef<HTMLDivElement>();
     private _editorRef = React.createRef<HTMLDivElement>();
+    @observable _editingLink?: Doc;
+    @observable _linkMenuRef = React.createRef<HTMLDivElement>();
 
-    //@observable private _numLinks: number = 0;
-
-    // @computed get overflow() {
-    //     if (this._numLinks) {
-    //         return "scroll";
-    //     }
-    //     return "auto";
-    // }
-
-    @action
-    onClick = (e: PointerEvent) => {
-
-        LinkDocPreview.LinkInfo = undefined;
-
-
-        if (this._linkMenuRef && !this._linkMenuRef.current?.contains(e.target as any)) {
-            if (this._editorRef && !this._editorRef.current?.contains(e.target as any)) {
-                DocumentLinksButton.EditLink = undefined;
-            }
-        }
-    }
-    @action
-    componentDidMount() {
-        this._editingLink = undefined;
-        document.addEventListener("pointerdown", this.onClick);
+    @computed get position() {
+        return ((dv) => ({ x: dv?.left || 0, y: dv?.top || 0, r: dv?.right || 0, b: dv?.bottom || 0 }))(this.props.docView.getBounds());
     }
 
-    componentWillUnmount() {
-        document.removeEventListener("pointerdown", this.onClick);
-    }
+    componentDidMount() { document.addEventListener("pointerdown", this.onPointerDown); }
+    componentWillUnmount() { document.removeEventListener("pointerdown", this.onPointerDown); }
 
-    clearAllLinks = () => {
-        LinkManager.Instance.deleteAllLinksOnAnchor(this.props.docView.props.Document);
+    onPointerDown = (e: PointerEvent) => {
+        LinkDocPreview.Clear();
+        if (this._linkMenuRef && this._editorRef &&
+            !this._linkMenuRef.current?.contains(e.target as any) &&
+            !this._editorRef.current?.contains(e.target as any)) {
+            DocumentLinksButton.ClearLinkEditor();
+        }
     }
 
     renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => {
@@ -66,32 +45,23 @@ export class LinkMenu extends React.Component<Props> {
                 sourceDoc={this.props.docView.props.Document}
                 group={group[1]}
                 groupType={group[0]}
-                showEditor={action(linkDoc => this._editingLink = linkDoc)}
-                docprops={this.props.docprops} />);
+                showEditor={action(linkDoc => this._editingLink = linkDoc)} />);
 
         return linkItems.length ? linkItems : [<p key="">No links have been created yet. Drag the linking button onto another document to create a link.</p>];
     }
 
-    @computed
-    get position() {
-        const docView = this.props.docView.getBounds();
-        return { x: docView?.left || 0, y: docView?.top || 0, r: docView?.right || 0, b: docView?.bottom || 0 };
-    }
-
     render() {
         const sourceDoc = this.props.docView.props.Document;
-        const groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc);
-        return <div className="linkMenu" style={{ left: this.position.x, top: this.props.docView.topMost ? undefined : this.position.b + 15, bottom: this.props.docView.topMost ? 20 : undefined }} ref={this._linkMenuRef} >
-            {!this._editingLink ?
-                <div className="linkMenu-list" >
-                    {this.renderAllGroups(groups)}
-                </div> :
+        return <div className="linkMenu" ref={this._linkMenuRef}
+            style={{ left: this.position.x, top: this.props.docView.topMost ? undefined : this.position.b + 15, bottom: this.props.docView.topMost ? 20 : undefined }}
+        >
+            {this._editingLink ?
                 <div className="linkMenu-listEditor">
-                    <LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink}
-                        showLinks={action(() => this._editingLink = undefined)} />
-                </div>
-            }
-
+                    <LinkEditor sourceDoc={sourceDoc} linkDoc={this._editingLink} showLinks={action(() => this._editingLink = undefined)} />
+                </div> :
+                <div className="linkMenu-list" >
+                    {this.renderAllGroups(LinkManager.Instance.getRelatedGroupedLinks(sourceDoc))}
+                </div>}
         </div>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 7db908393..74af78234 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -3,7 +3,7 @@ import { Doc } from "../../../fields/Doc";
 import { Id } from "../../../fields/FieldSymbols";
 import { Cast } from "../../../fields/Types";
 import { LinkManager } from "../../util/LinkManager";
-import { DocumentView, DocumentViewSharedProps } from "../nodes/DocumentView";
+import { DocumentView } from "../nodes/DocumentView";
 import './LinkMenu.scss';
 import { LinkMenuItem } from "./LinkMenuItem";
 import React = require("react");
@@ -13,14 +13,11 @@ interface LinkMenuGroupProps {
     group: Doc[];
     groupType: string;
     showEditor: (linkDoc: Doc) => void;
-    docprops: DocumentViewSharedProps;
     docView: DocumentView;
 }
 
 @observer
 export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
-
-    private _drag = React.createRef<HTMLDivElement>();
     private _menuRef = React.createRef<HTMLDivElement>();
 
     render() {
@@ -31,7 +28,6 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
             if (destination && this.props.sourceDoc) {
                 return <LinkMenuItem key={linkDoc[Id]}
                     groupType={this.props.groupType}
-                    docprops={this.props.docprops}
                     docView={this.props.docView}
                     linkDoc={linkDoc}
                     sourceDoc={this.props.sourceDoc}
@@ -43,11 +39,9 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
 
         return (
             <div className="linkMenu-group" ref={this._menuRef}>
-
                 <div className="linkMenu-group-name">
-                    <p ref={this._drag} className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p>
+                    <p className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p>
                 </div>
-
                 <div className="linkMenu-group-wrapper">
                     {groupItems}
                 </div>
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index e9a0486d1..e9866f6e3 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -6,7 +6,7 @@ import { observer } from "mobx-react";
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { Cast, StrCast } from '../../../fields/Types';
 import { WebField } from '../../../fields/URLField';
-import { emptyFunction, setupMoveUpEvents } from '../../../Utils';
+import { emptyFunction, setupMoveUpEvents, returnFalse } from '../../../Utils';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager } from '../../util/DragManager';
@@ -18,6 +18,7 @@ import { DocumentView, DocumentViewSharedProps } from '../nodes/DocumentView';
 import { LinkDocPreview } from '../nodes/LinkDocPreview';
 import './LinkMenuItem.scss';
 import React = require("react");
+import { setup } from 'mocha';
 
 
 interface LinkMenuItemProps {
@@ -27,7 +28,6 @@ interface LinkMenuItemProps {
     sourceDoc: Doc;
     destinationDoc: Doc;
     showEditor: (linkDoc: Doc) => void;
-    docprops: DocumentViewSharedProps;
     menuRef: React.Ref<HTMLDivElement>;
 }
 
@@ -69,9 +69,6 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume
 @observer
 export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     private _drag = React.createRef<HTMLDivElement>();
-    private _downX = 0;
-    private _downY = 0;
-    private _eleClone: any;
 
     _editRef = React.createRef<HTMLDivElement>();
     _buttonRef = React.createRef<HTMLDivElement>();
@@ -81,84 +78,45 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
     onEdit = (e: React.PointerEvent): void => {
         LinkManager.currentLink = this.props.linkDoc;
-        setupMoveUpEvents(this, e, this.editMoved, emptyFunction, () => this.props.showEditor(this.props.linkDoc));
-    }
-
-    editMoved = (e: PointerEvent) => {
-        const dragData = new DragManager.DocumentDragData([this.props.linkDoc]);
-        DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y);
-        return true;
+        setupMoveUpEvents(this, e, e => {
+            DragManager.StartDocumentDrag([this._editRef.current!], new DragManager.DocumentDragData([this.props.linkDoc]), e.x, e.y);
+            return true;
+        }, emptyFunction, () => this.props.showEditor(this.props.linkDoc));
     }
 
-    @action
     onLinkButtonDown = (e: React.PointerEvent): void => {
-        this._downX = e.clientX;
-        this._downY = e.clientY;
-        this._eleClone = this._drag.current!.cloneNode(true);
-        e.stopPropagation();
-        document.removeEventListener("pointermove", this.onLinkButtonMoved);
-        document.addEventListener("pointermove", this.onLinkButtonMoved);
-        document.removeEventListener("pointerup", this.onLinkButtonUp);
-        document.addEventListener("pointerup", this.onLinkButtonUp);
-
-        if (this._buttonRef && !!!this._buttonRef.current?.contains(e.target as any)) {
-            LinkDocPreview.LinkInfo = undefined;
-        }
-    }
-
-    onLinkButtonUp = action((e: PointerEvent): void => {
-        document.removeEventListener("pointermove", this.onLinkButtonMoved);
-        document.removeEventListener("pointerup", this.onLinkButtonUp);
-        LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false);
-        LinkDocPreview.LinkInfo = undefined;
-        DocumentLinksButton.EditLink = undefined;
-
-        e.stopPropagation();
-    });
-
-    onLinkButtonMoved = async (e: PointerEvent) => {
-        if (this._drag.current !== null && Math.abs((e.clientX - this._downX) * (e.clientX - this._downX) + (e.clientY - this._downY) * (e.clientY - this._downY)) > 5) {
-            document.removeEventListener("pointermove", this.onLinkButtonMoved);
-            document.removeEventListener("pointerup", this.onLinkButtonUp);
-
-            this._eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`;
-            StartLinkTargetsDrag(this._eleClone, this.props.docView, e.x, e.y, this.props.sourceDoc, [this.props.linkDoc]);
-        }
-        e.stopPropagation();
+        setupMoveUpEvents(this, e,
+            e => {
+                const eleClone: any = this._drag.current!.cloneNode(true);
+                eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`;
+                StartLinkTargetsDrag(eleClone, this.props.docView, e.x, e.y, this.props.sourceDoc, [this.props.linkDoc]);
+                DocumentLinksButton.ClearLinkEditor();
+                return true;
+            },
+            emptyFunction,
+            () => {
+                DocumentLinksButton.ClearLinkEditor();
+                LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false);
+            });
     }
 
-    @undoBatch
-    @action
     deleteLink = (e: React.PointerEvent): void => {
-        this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
-        LinkManager.Instance.deleteLink(this.props.linkDoc);
-        e.stopPropagation();
-
-        runInAction(() => {
-            LinkDocPreview.LinkInfo = undefined;
-            DocumentLinksButton.EditLink = undefined;
-        });
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => {
+            this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+            LinkManager.Instance.deleteLink(this.props.linkDoc);
+        })));
     }
 
-    @undoBatch
-    @action
     autoMove = (e: React.PointerEvent) => {
-        e.stopPropagation();
-        this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove;
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove)));
     }
 
-    @undoBatch
-    @action
     showLink = (e: React.PointerEvent) => {
-        e.stopPropagation();
-        this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay;
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay)));
     }
 
-    @undoBatch
-    @action
     showAnchor = (e: React.PointerEvent) => {
-        e.stopPropagation();
-        this.props.linkDoc.hidden = !this.props.linkDoc.hidden;
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.hidden = !this.props.linkDoc.hidden)));
     }
 
     render() {
@@ -180,13 +138,13 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 <div className={"linkMenu-item-content expand-two"}>
 
                     <div ref={this._drag} className="linkMenu-name" //title="drag to view target. click to customize."
-                        onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)}
-                        onPointerEnter={action(e => this.props.linkDoc && (LinkDocPreview.LinkInfo = {
-                            docprops: this.props.docprops,
+                        onPointerLeave={LinkDocPreview.Clear}
+                        onPointerEnter={e => this.props.linkDoc && LinkDocPreview.SetLinkInfo({
+                            docprops: this.props.docView.props,
                             linkSrc: this.props.sourceDoc,
                             linkDoc: this.props.linkDoc,
                             Location: [e.clientX, e.clientY + 20]
-                        }))}
+                        })}
                         onPointerDown={this.onLinkButtonDown}>
 
                         <div className="linkMenu-text">
@@ -205,26 +163,26 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                         <div className="linkMenu-item-buttons" ref={this._buttonRef} >
 
                             <Tooltip title={<><div className="dash-tooltip">{this.props.linkDoc.hidden ? "Show Anchor" : "Hide Anchor"}</div></>}>
-                                <div className="button" ref={this._editRef} onPointerDown={this.showAnchor}>
+                                <div className="button" ref={this._editRef} onPointerDown={this.showAnchor} onClick={e => e.stopPropagation()}>
                                     <FontAwesomeIcon className="fa-icon" icon={this.props.linkDoc.hidden ? "eye-slash" : "eye"} size="sm" /></div>
                             </Tooltip>
 
                             <Tooltip title={<><div className="dash-tooltip">{!this.props.linkDoc.linkDisplay ? "Show link" : "Hide link"}</div></>}>
-                                <div className="button" ref={this._editRef} onPointerDown={this.showLink}>
+                                <div className="button" ref={this._editRef} onPointerDown={this.showLink} onClick={e => e.stopPropagation()}>
                                     <FontAwesomeIcon className="fa-icon" icon={!this.props.linkDoc.linkDisplay ? "eye-slash" : "eye"} size="sm" /></div>
                             </Tooltip>
 
                             <Tooltip title={<><div className="dash-tooltip">{!this.props.linkDoc.linkAutoMove ? "Auto move dot" : "Freeze dot position"}</div></>}>
-                                <div className="button" ref={this._editRef} onPointerDown={this.autoMove}>
+                                <div className="button" ref={this._editRef} onPointerDown={this.autoMove} onClick={e => e.stopPropagation()}>
                                     <FontAwesomeIcon className="fa-icon" icon={this.props.linkDoc.linkAutoMove ? "play" : "pause"} size="sm" /></div>
                             </Tooltip>
 
                             <Tooltip title={<><div className="dash-tooltip">Edit Link</div></>}>
-                                <div className="button" ref={this._editRef} onPointerDown={this.onEdit}>
+                                <div className="button" ref={this._editRef} onPointerDown={this.onEdit} onClick={e => e.stopPropagation()}>
                                     <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
                             </Tooltip>
                             <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>}>
-                                <div className="button" onPointerDown={this.deleteLink}>
+                                <div className="button" onPointerDown={this.deleteLink} onClick={e => e.stopPropagation()}>
                                     <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
                             </Tooltip>
                         </div>
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 692eaae66..fbe289f64 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -107,7 +107,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
         //this._disposers.scrubbing = reaction(() => AudioBox._scrubTime, (time) => this.layoutDoc.playOnSelect && this.playFromTime(AudioBox._scrubTime));
 
         this._disposers.triggerAudio = reaction(
-            () => !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerAudio, null) : undefined,
+            () => !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerAudio, null) : undefined,
             start => start !== undefined && setTimeout(() => {
                 this.playFrom(start);
                 setTimeout(() => {
@@ -119,7 +119,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
         );
 
         this._disposers.audioStop = reaction(
-            () => this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc ? Cast(this.Document._audioStop, "number", null) : undefined,
+            () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? Cast(this.Document._audioStop, "number", null) : undefined,
             audioStop => audioStop !== undefined && setTimeout(() => {
                 this.Pause();
                 setTimeout(() => this.Document._audioStop = undefined, 10);
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index defa4dbf0..13a6c9df8 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -33,16 +33,16 @@ interface DocumentLinksButtonProps {
 @observer
 export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> {
     private _linkButton = React.createRef<HTMLDivElement>();
-
     @observable public static StartLink: Doc | undefined;
     @observable public static StartLinkView: DocumentView | undefined;
     @observable public static AnnotationId: string | undefined;
     @observable public static AnnotationUri: string | undefined;
-    @observable public static EditLink: DocumentView | undefined;
+    @observable public static LinkEditorDocView: DocumentView | undefined;
 
     @observable public static invisibleWebDoc: Opt<Doc>;
     public static invisibleWebRef = React.createRef<HTMLDivElement>();
 
+    @action public static ClearLinkEditor() { DocumentLinksButton.LinkEditorDocView = undefined; }
     @action @undoBatch
     onLinkButtonMoved = (e: PointerEvent) => {
         if (this.props.InMenu && this.props.StartLink) {
@@ -83,7 +83,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     DocumentLinksButton.StartLinkView = this.props.View;
                 }
             } else if (!this.props.InMenu) {
-                DocumentLinksButton.EditLink = this.props.View;
+                DocumentLinksButton.LinkEditorDocView = this.props.View;
             }
         }));
     }
@@ -103,7 +103,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
             //action(() => Doc.BrushDoc(this.props.View.Document));
         } else if (!this.props.InMenu) {
-            DocumentLinksButton.EditLink = this.props.View;
+            DocumentLinksButton.LinkEditorDocView = this.props.View;
         }
     }
 
@@ -264,7 +264,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     {this.linkButtonInner}
                 </Tooltip>
                 :
-                !DocumentLinksButton.EditLink && !this.props.InMenu ?
+                !DocumentLinksButton.LinkEditorDocView && !this.props.InMenu ?
                     <Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
                         {this.linkButtonInner}
                     </Tooltip>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bfdacdb45..f56246e9a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -377,7 +377,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     }
 
     focus = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => {
-        this._componentView?.scrollFocus?.(doc, !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc); // bcz: smooth parameter should really be passed into focus() instead of inferred here
+        this._componentView?.scrollFocus?.(doc, !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc); // bcz: smooth parameter should really be passed into focus() instead of inferred here
         return this.props.focus(doc, willZoom, scale, afterFocus, dontCenter, focused);
     }
     onClick = action((e: React.MouseEvent | React.PointerEvent) => {
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index ca6c71ea3..673c936ce 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -135,8 +135,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
             </div>
         );
         return <div className={`linkAnchorBox-cont${small ? "-small" : ""}`}
-            onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)}
-            onPointerEnter={action(e => LinkDocPreview.LinkInfo = {
+            onPointerLeave={LinkDocPreview.Clear}
+            onPointerEnter={e => LinkDocPreview.SetLinkInfo({
                 docprops: this.props,
                 linkSrc: linkSource,
                 linkDoc: this.rootDoc,
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 8051568ff..4808feb47 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -22,7 +22,10 @@ interface Props {
 }
 @observer
 export class LinkDocPreview extends React.Component<Props> {
-    static TargetDoc: Doc | undefined;
+    @action public static Clear() { LinkDocPreview.LinkInfo = undefined; }
+    @action public static SetLinkInfo(info: { linkDoc?: Doc; linkSrc: Doc; href?: string; Location: number[], docprops: DocumentViewSharedProps }) {
+        LinkDocPreview.LinkInfo = info;
+    }
     @observable public static LinkInfo: Opt<{ linkDoc?: Doc; linkSrc: Doc; href?: string; Location: number[], docprops: DocumentViewSharedProps }>;
     @observable _targetDoc: Opt<Doc>;
     @observable _toolTipText = "";
@@ -30,28 +33,13 @@ export class LinkDocPreview extends React.Component<Props> {
     _editRef = React.createRef<HTMLDivElement>();
 
     @action
-    onContextMenu = (e: React.MouseEvent) => {
-        DocumentLinksButton.EditLink = undefined;
-        LinkDocPreview.LinkInfo = undefined;
-        e.preventDefault();
-        ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" });
-        ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
-    }
-
-    @action.bound
-    async followDefault() {
-        DocumentLinksButton.EditLink = undefined;
-        LinkDocPreview.LinkInfo = undefined;
-        this._targetDoc && LinkManager.FollowLink(this.props.linkDoc, this._targetDoc, this.props.docprops, false);
-    }
-    componentWillUnmount() { LinkDocPreview.TargetDoc = undefined; }
+    componentWillUnmount() { LinkDocPreview.LinkInfo = undefined; }
 
     componentDidUpdate() { this.updatePreview(); }
     componentDidMount() { this.updatePreview(); }
     async updatePreview() {
         const linkDoc = this.props.linkDoc;
         const linkSrc = this.props.linkSrc;
-        LinkDocPreview.TargetDoc = undefined;
         if (this.props.href) {
             if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) {
                 wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500))));
@@ -65,7 +53,7 @@ export class LinkDocPreview extends React.Component<Props> {
             const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget;
             runInAction(() => {
                 this._toolTipText = "";
-                LinkDocPreview.TargetDoc = this._targetDoc = target;
+                this._targetDoc = target;
             });
         }
     }
@@ -119,9 +107,11 @@ export class LinkDocPreview extends React.Component<Props> {
             style={{
                 position: "absolute", left: this.props.location[0],
                 top: this.props.location[1], width: this.width() + 16, height: this.height() + 16,
-                zIndex: 1000,
+                zIndex: 2004,
+                pointerEvents: "none",
                 backgroundColor: "lightblue",
-                border: "8px solid white", borderRadius: "7px",
+                border: "8px solid white",
+                borderRadius: "7px",
                 boxShadow: "3px 3px 1.5px grey",
                 borderBottom: "8px solid white", borderRight: "8px solid white"
             }}>
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 760620b19..c21701f32 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -211,7 +211,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             },
             { fireImmediately: true });
         this._disposers.triggerVideo = reaction(
-            () => !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined,
+            () => !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined,
             time => time !== undefined && setTimeout(() => {
                 this.player && this.Play();
                 setTimeout(() => this.Document._triggerVideo = undefined, 10);
@@ -219,7 +219,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             { fireImmediately: true }
         );
         this._disposers.triggerStop = reaction(
-            () => this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc ? NumCast(this.Document._triggerVideoStop, null) : undefined,
+            () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? NumCast(this.Document._triggerVideoStop, null) : undefined,
             stop => stop !== undefined && setTimeout(() => {
                 this.player && this.Pause();
                 setTimeout(() => this.Document._triggerVideoStop = undefined, 10);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 2409f36a0..0374b1426 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1215,7 +1215,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     const scrollRef = self._scrollRef.current;
                     if ((docPos.top < viewRect.top || docPos.top > viewRect.bottom) && scrollRef) {
                         const scrollPos = scrollRef.scrollTop + (docPos.top - viewRect.top) * self.props.ScreenToLocalTransform().Scale;
-                        if (!LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc) {
+                        if (!LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc) {
                             scrollPos && smoothScroll(500, scrollRef, scrollPos);
                         } else {
                             scrollRef.scrollTo({ top: scrollPos });
@@ -1601,7 +1601,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         eve.stopPropagation(); // drag n drop of text within text note will generate a new note if not caughst, as will dragging in from outside of Dash.
     }
     onScroll = (ev: React.UIEvent) => {
-        if (!LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc && this._scrollRef.current) {
+        if (!LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this._scrollRef.current) {
             this._ignoreScroll = true;
             this.layoutDoc._scrollTop = this._scrollRef.current.scrollTop;
             this._ignoreScroll = false;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 05f0fefd8..d1bb2ad84 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -136,8 +136,6 @@ export class FormattedTextBoxComment {
     @undoBatch
     deleteLink = action(() => {
         FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null;
-        LinkDocPreview.LinkInfo = undefined;
-        DocumentLinksButton.EditLink = undefined;
         FormattedTextBoxComment.Hide();
     });
 
@@ -158,6 +156,7 @@ export class FormattedTextBoxComment {
         FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "");
     }
 
+    @action
     static showCommentbox(set: string, view: EditorView, nbef: number) {
         const state = view.state;
         if (set !== "none") {
@@ -171,6 +170,13 @@ export class FormattedTextBoxComment {
             const left = Math.max((start.left + end.left) / 2, start.left + 3);
             FormattedTextBoxComment.tooltip.style.left = (left - box.left) + "px";
             FormattedTextBoxComment.tooltip.style.bottom = (box.bottom - start.top) + "px";
+            // const props = FormattedTextBoxComment.textBox?.props.docViewPath.lastElement().props;
+            // props && (LinkDocPreview.SetLinkInfo({
+            //     docprops: props,
+            //     linkSrc: props.Document,
+            //     linkDoc: FormattedTextBoxComment.linkDoc,
+            //     Location: [start.left, start.top + 25]
+            // });
         }
         FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = set);
     }
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index b041c4fc9..5da868281 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -851,7 +851,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
     // TODO: should check for valid URL
     @undoBatch
     makeLinkToURL = (target: string, lcoation: string) => {
-        ((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", "", target);
+        ((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", target, target);
     }
 
     @undoBatch
diff --git a/src/client/views/nodes/formattedText/TooltipTextMenu.scss b/src/client/views/nodes/formattedText/TooltipTextMenu.scss
index e2149e9c1..0e4b752ac 100644
--- a/src/client/views/nodes/formattedText/TooltipTextMenu.scss
+++ b/src/client/views/nodes/formattedText/TooltipTextMenu.scss
@@ -103,7 +103,7 @@
 }
 
 .tooltipMenu, .basic-tools {
-    z-index: 20000;
+    z-index: 3000;
     pointer-events: all;
     padding: 3px;
     padding-bottom: 5px;
-- 
cgit v1.2.3-70-g09d2


From 5fd9ffcc2bb62faa664f33a817ae1fd51c36ef98 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 9 Feb 2021 19:11:28 -0500
Subject: overhaul of linkdocpreview.  delegated linkpreviewing from
 formattedTextBoxComments to LinkDocPreview

---
 src/client/util/LinkManager.ts                     |   1 -
 src/client/views/MainView.tsx                      |   3 +-
 src/client/views/linking/LinkMenu.tsx              |   3 +-
 src/client/views/linking/LinkMenuItem.tsx          |   3 +-
 src/client/views/nodes/AudioBox.tsx                |   4 +-
 src/client/views/nodes/DocumentView.tsx            |   2 +-
 src/client/views/nodes/LinkAnchorBox.tsx           |   3 +-
 src/client/views/nodes/LinkDocPreview.scss         |  69 ++++++
 src/client/views/nodes/LinkDocPreview.tsx          | 232 ++++++++++++-------
 src/client/views/nodes/VideoBox.tsx                |   4 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  13 +-
 .../formattedText/FormattedTextBoxComment.scss     |  76 +-----
 .../formattedText/FormattedTextBoxComment.tsx      | 255 ++++-----------------
 13 files changed, 283 insertions(+), 385 deletions(-)
 create mode 100644 src/client/views/nodes/LinkDocPreview.scss

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

diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index ecf245d03..c32a78ef3 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -129,7 +129,6 @@ export class LinkManager {
         await LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined);
     }
     public static async traverseLink(link: Opt<Doc>, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) {
-        FormattedTextBoxComment.linkDoc = undefined;
         const linkDocs = link ? [link] : DocListCast(doc.links);
         const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1
         const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d53e66c47..d09b0269f 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -626,8 +626,7 @@ export class MainView extends React.Component {
             <CollectionMenu />
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
             {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)}
-            {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} docprops={LinkDocPreview.LinkInfo.docprops}
-                linkDoc={LinkDocPreview.LinkInfo.linkDoc} linkSrc={LinkDocPreview.LinkInfo.linkSrc} href={LinkDocPreview.LinkInfo.href} /> : (null)}
+            {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
             <GestureOverlay >
                 {this.mainContent}
             </GestureOverlay>
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 8cd069210..c7888c5ee 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -30,8 +30,7 @@ export class LinkMenu extends React.Component<Props> {
 
     onPointerDown = (e: PointerEvent) => {
         LinkDocPreview.Clear();
-        if (this._linkMenuRef && this._editorRef &&
-            !this._linkMenuRef.current?.contains(e.target as any) &&
+        if (!this._linkMenuRef.current?.contains(e.target as any) &&
             !this._editorRef.current?.contains(e.target as any)) {
             DocumentLinksButton.ClearLinkEditor();
         }
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index e9866f6e3..2bc2bc6a4 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -143,7 +143,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             docprops: this.props.docView.props,
                             linkSrc: this.props.sourceDoc,
                             linkDoc: this.props.linkDoc,
-                            Location: [e.clientX, e.clientY + 20]
+                            showHeader: false,
+                            location: [e.clientX, e.clientY + 20]
                         })}
                         onPointerDown={this.onLinkButtonDown}>
 
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index fbe289f64..e24a671d0 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -107,7 +107,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
         //this._disposers.scrubbing = reaction(() => AudioBox._scrubTime, (time) => this.layoutDoc.playOnSelect && this.playFromTime(AudioBox._scrubTime));
 
         this._disposers.triggerAudio = reaction(
-            () => !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerAudio, null) : undefined,
+            () => !LinkDocPreview.LinkInfo && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerAudio, null) : undefined,
             start => start !== undefined && setTimeout(() => {
                 this.playFrom(start);
                 setTimeout(() => {
@@ -119,7 +119,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
         );
 
         this._disposers.audioStop = reaction(
-            () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? Cast(this.Document._audioStop, "number", null) : undefined,
+            () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo ? Cast(this.Document._audioStop, "number", null) : undefined,
             audioStop => audioStop !== undefined && setTimeout(() => {
                 this.Pause();
                 setTimeout(() => this.Document._audioStop = undefined, 10);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f56246e9a..8afa53eac 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -377,7 +377,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     }
 
     focus = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => {
-        this._componentView?.scrollFocus?.(doc, !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc); // bcz: smooth parameter should really be passed into focus() instead of inferred here
+        this._componentView?.scrollFocus?.(doc, !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here
         return this.props.focus(doc, willZoom, scale, afterFocus, dontCenter, focused);
     }
     onClick = action((e: React.MouseEvent | React.PointerEvent) => {
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 673c936ce..7a4209563 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -140,7 +140,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
                 docprops: this.props,
                 linkSrc: linkSource,
                 linkDoc: this.rootDoc,
-                Location: [e.clientX, e.clientY + 20]
+                showHeader: true,
+                location: [e.clientX, e.clientY + 20]
             })}
             onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} onContextMenu={this.specificContextMenu}
             ref={this._ref}
diff --git a/src/client/views/nodes/LinkDocPreview.scss b/src/client/views/nodes/LinkDocPreview.scss
new file mode 100644
index 000000000..abbb8cdf0
--- /dev/null
+++ b/src/client/views/nodes/LinkDocPreview.scss
@@ -0,0 +1,69 @@
+ .linkDocPreview {
+    position: absolute;
+    pointer-events: all;
+    background-color: lightblue;
+    border: 8px solid white;
+    border-radius: 7px;
+    box-shadow: 3px 3px 1.5px grey;
+    border-bottom: 8px solid white;
+    border-right: 8px solid white;
+    z-index: 2004;
+    .linkDocPreview-inner {
+        background-color: white;
+        border: 8px solid white;
+        width: 100%;
+        height: 100%;
+        pointer-events: none;
+
+        .linkDocPreview-info {
+            height: 37px;
+            white-space: pre;
+
+            .linkDocPreview-title {
+                padding-right: 4px;
+                float: left;
+                width: calc(100% - 48px);
+                overflow: hidden;
+                text-overflow: ellipsis;
+                height: 25px;
+
+                .linkDocPreview-description {
+                    text-decoration: none;
+                    font-style: italic;
+                    color: rgb(95, 97, 102);
+                    font-size: 10px;
+                }
+            }
+
+            .linkDocPreview-button {
+                display: inline-flex;
+                margin: 0;
+                margin-right: 3px;
+                border-radius: 50%;
+                pointer-events: auto;
+                background-color: black;
+                color: white;
+                transition: transform 0.2s;
+                text-align: center;
+                position: relative;
+                font-size: 12px;
+                width: 20px;
+                height: 20px;
+                align-items: center;
+                justify-content: center;
+
+                &:hover {
+                    background-color: rgb(77, 77, 77);
+                    cursor: pointer;
+                }
+            }
+
+            .linkDocPreview-preview-wrapper {
+                overflow: hidden;
+                align-content: center;
+                justify-content: center;
+                background-color: rgb(160, 160, 160);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 4808feb47..04a407eab 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -1,121 +1,197 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Tooltip } from '@material-ui/core';
 import { action, computed, observable, runInAction } from 'mobx';
 import { observer } from "mobx-react";
 import wiki from "wikijs";
-import { Doc, DocCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
-import { Id } from '../../../fields/FieldSymbols';
-import { Cast, FieldValue, NumCast } from "../../../fields/Types";
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, emptyPath } from "../../../Utils";
+import { Doc, DocCastAsync, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { NumCast, StrCast } from "../../../fields/Types";
+import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, setupMoveUpEvents, Utils } from "../../../Utils";
+import { DocServer } from '../../DocServer';
 import { Docs } from "../../documents/Documents";
 import { LinkManager } from '../../util/LinkManager';
 import { Transform } from "../../util/Transform";
-import { ContextMenu } from '../ContextMenu';
-import { DocumentLinksButton } from './DocumentLinksButton';
-import { DocumentView, StyleProviderFunc, DocumentViewSharedProps } from "./DocumentView";
+import { DocumentView, DocumentViewSharedProps } from "./DocumentView";
+import './LinkDocPreview.scss';
 import React = require("react");
 
-interface Props {
+interface LinkDocPreviewProps {
     linkDoc?: Doc;
     linkSrc?: Doc;
     href?: string;
     docprops: DocumentViewSharedProps;
     location: number[];
+    hrefs?: string[];
+    showHeader?: boolean;
 }
 @observer
-export class LinkDocPreview extends React.Component<Props> {
+export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
     @action public static Clear() { LinkDocPreview.LinkInfo = undefined; }
-    @action public static SetLinkInfo(info: { linkDoc?: Doc; linkSrc: Doc; href?: string; Location: number[], docprops: DocumentViewSharedProps }) {
-        LinkDocPreview.LinkInfo = info;
-    }
-    @observable public static LinkInfo: Opt<{ linkDoc?: Doc; linkSrc: Doc; href?: string; Location: number[], docprops: DocumentViewSharedProps }>;
+    @action public static SetLinkInfo(info?: LinkDocPreviewProps) { LinkDocPreview.LinkInfo != info && (LinkDocPreview.LinkInfo = info); }
+
+    _infoRef = React.createRef<HTMLDivElement>();
+    @observable public static LinkInfo: Opt<LinkDocPreviewProps>;
     @observable _targetDoc: Opt<Doc>;
+    @observable _linkDoc: Opt<Doc>;
+    @observable _linkSrc: Opt<Doc>;
     @observable _toolTipText = "";
-    _linkTarget: Opt<Doc>;
-    _editRef = React.createRef<HTMLDivElement>();
+    @observable _hrefInd = 0;
+    @observable _linkTarget: Opt<Doc>;
 
-    @action
-    componentWillUnmount() { LinkDocPreview.LinkInfo = undefined; }
+    @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;
+        this._linkSrc = this.props.linkSrc;
+        this._linkDoc = this.props.linkDoc;
+        this._toolTipText = "";
+        this.updatePreview();
+        document.addEventListener("pointerdown", this.onPointerDown);
+    }
+
+    componentWillUnmount() {
+        LinkDocPreview.SetLinkInfo(undefined);
+        document.removeEventListener("pointerdown", this.onPointerDown);
+    }
+
+    onPointerDown = (e: PointerEvent) => {
+        !this._infoRef.current?.contains(e.target as any) && LinkDocPreview.Clear();
+    }
 
-    componentDidUpdate() { this.updatePreview(); }
-    componentDidMount() { this.updatePreview(); }
-    async updatePreview() {
+    updatePreview() {
         const linkDoc = this.props.linkDoc;
         const linkSrc = this.props.linkSrc;
-        if (this.props.href) {
-            if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) {
-                wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500))));
+        if (this.props.hrefs?.length) {
+            const href = this.props.hrefs[this._hrefInd];
+            if (href.indexOf(Utils.prepend("/doc/")) !== 0) {
+                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);
+                }
             } else {
-                runInAction(() => this._toolTipText = "external => " + this.props.href);
+                const anchorDoc = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
+                anchorDoc && DocServer.GetRefField(anchorDoc).then(action(async anchor => {
+                    if (anchor instanceof Doc) {
+                        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;
+                            this._toolTipText = "";
+                            runInAction(() => this._targetDoc = target);
+                        });
+                    }
+                }));
             }
-        } else if (linkDoc && linkSrc) {
+        } else if (linkDoc) {
             const anchor1 = linkDoc.anchor1 as Doc;
             const anchor2 = linkDoc.anchor2 as Doc;
-            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(() => {
+            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;
                 this._toolTipText = "";
-                this._targetDoc = target;
+                runInAction(() => this._targetDoc = target);
             });
         }
     }
-    pointerDown = (e: React.PointerEvent) => {
-        if (this.props.linkDoc && this.props.linkSrc) {
-            LinkManager.FollowLink(this.props.linkDoc, this.props.linkSrc, this.props.docprops, false);
+    deleteLink = (e: React.PointerEvent) => {
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => this._linkDoc ? LinkManager.Instance.deleteLink(this._linkDoc) : null));
+    }
+    nextHref = (e: React.PointerEvent) => {
+        setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => {
+            this._hrefInd = (this._hrefInd + 1) % (this.props.hrefs?.length || 1);
+            this.updatePreview();
+        }));
+    }
+
+    followLink = (e: React.PointerEvent) => {
+        if (this._linkDoc && this._linkSrc) {
+            LinkManager.FollowLink(this._linkDoc, this._linkSrc, this.props.docprops, false);
         } else if (this.props.href) {
             this.props.docprops?.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, useCors: true }), "add:right");
         }
     }
     width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225));
     height = () => Math.min(225, NumCast(this._targetDoc?.[HeightSym](), 225));
-    @computed get targetDocView() {
-        return !this._targetDoc ?
-            <div style={{ pointerEvents: "all", maxWidth: 225, maxHeight: 225, width: "100%", height: "100%", overflow: "hidden" }}>
-                <div style={{ width: "100%", height: "100%", textOverflow: "ellipsis", }} onPointerDown={this.pointerDown}>
-                    {this._toolTipText}
+    @computed get previewHeader() {
+        return !this._linkDoc || !this._targetDoc || !this._linkSrc ? (null) :
+            <div className="LinkDocPreview-info" ref={this._infoRef}>
+                <div className="LinkDocPreview-title">
+                    {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>}
+
+                    <Tooltip title={<div className="dash-tooltip">Delete Link</div>} placement="top">
+                        <div className="LinkDocPreview-button" onPointerDown={this.deleteLink}>
+                            <FontAwesomeIcon className="LinkDocPreview-fa-icon" icon="trash" color="white" size="sm" />
+                        </div>
+                    </Tooltip>
+                </div>
+            </div>;
+    }
+
+    @computed get docPreview() {
+        return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? (null) :
+            <div className="LinkDocPreview-inner">
+                {!this.props.showHeader ? (null) : this.previewHeader}
+                <div className="LinkDocPreview-preview-wrapper">
+                    {this._toolTipText ? this._toolTipText :
+                        <DocumentView ref={(r) => {
+                            const targetanchor = LinkManager.getOppositeAnchor(this._linkDoc!, this._linkSrc!);
+                            targetanchor && this._targetDoc !== targetanchor && r?.focus(targetanchor);
+                        }}
+                            Document={this._targetDoc}
+                            moveDocument={returnFalse}
+                            rootSelected={returnFalse}
+                            styleProvider={this.props.docprops?.styleProvider}
+                            layerProvider={this.props.docprops?.layerProvider}
+                            docViewPath={emptyPath}
+                            ScreenToLocalTransform={Transform.Identity}
+                            parentActive={returnFalse}
+                            addDocument={returnFalse}
+                            removeDocument={returnFalse}
+                            addDocTab={returnFalse}
+                            pinToPres={returnFalse}
+                            dontRegisterView={true}
+                            docFilters={returnEmptyFilter}
+                            docRangeFilters={returnEmptyFilter}
+                            searchFilterDocs={returnEmptyDoclist}
+                            ContainingCollectionDoc={undefined}
+                            ContainingCollectionView={undefined}
+                            renderDepth={-1}
+                            PanelWidth={this.width}
+                            PanelHeight={this.height}
+                            focus={emptyFunction}
+                            whenActiveChanged={returnFalse}
+                            bringToFront={returnFalse}
+                            NativeWidth={Doc.NativeWidth(this._targetDoc) ? () => Doc.NativeWidth(this._targetDoc) : undefined}
+                            NativeHeight={Doc.NativeHeight(this._targetDoc) ? () => Doc.NativeHeight(this._targetDoc) : undefined}
+                        />}
                 </div>
-            </div>
-            :
-            <DocumentView ref={r => this._linkTarget !== this._targetDoc && this._linkTarget && r?.focus(this._linkTarget)}
-                Document={this._targetDoc}
-                moveDocument={returnFalse}
-                rootSelected={returnFalse}
-                ScreenToLocalTransform={Transform.Identity}
-                parentActive={returnFalse}
-                addDocument={returnFalse}
-                removeDocument={returnFalse}
-                addDocTab={returnFalse}
-                pinToPres={returnFalse}
-                dontRegisterView={true}
-                docFilters={returnEmptyFilter}
-                docRangeFilters={returnEmptyFilter}
-                searchFilterDocs={returnEmptyDoclist}
-                ContainingCollectionDoc={undefined}
-                ContainingCollectionView={undefined}
-                renderDepth={-1}
-                PanelWidth={this.width}
-                PanelHeight={this.height}
-                focus={emptyFunction}
-                whenActiveChanged={returnFalse}
-                bringToFront={returnFalse}
-                styleProvider={this.props.docprops?.styleProvider}
-                layerProvider={this.props.docprops?.layerProvider}
-                docViewPath={emptyPath}
-            />;
+            </div>;
     }
 
     render() {
-        return <div className="linkDocPreview"
-            style={{
-                position: "absolute", left: this.props.location[0],
-                top: this.props.location[1], width: this.width() + 16, height: this.height() + 16,
-                zIndex: 2004,
-                pointerEvents: "none",
-                backgroundColor: "lightblue",
-                border: "8px solid white",
-                borderRadius: "7px",
-                boxShadow: "3px 3px 1.5px grey",
-                borderBottom: "8px solid white", borderRight: "8px solid white"
-            }}>
-            {this.targetDocView}
+        return <div className="linkDocPreview" onPointerDown={this.followLink}
+            style={{ left: this.props.location[0], top: this.props.location[1], width: this.width() + 16 }}>
+            {this.docPreview}
         </div>;
     }
 }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index c21701f32..324861573 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -211,7 +211,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             },
             { fireImmediately: true });
         this._disposers.triggerVideo = reaction(
-            () => !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined,
+            () => !LinkDocPreview.LinkInfo && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined,
             time => time !== undefined && setTimeout(() => {
                 this.player && this.Play();
                 setTimeout(() => this.Document._triggerVideo = undefined, 10);
@@ -219,7 +219,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             { fireImmediately: true }
         );
         this._disposers.triggerStop = reaction(
-            () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? NumCast(this.Document._triggerVideoStop, null) : undefined,
+            () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo ? NumCast(this.Document._triggerVideoStop, null) : undefined,
             stop => stop !== undefined && setTimeout(() => {
                 this.player && this.Pause();
                 setTimeout(() => this.Document._triggerVideoStop = undefined, 10);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 0374b1426..bf868634b 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1215,7 +1215,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     const scrollRef = self._scrollRef.current;
                     if ((docPos.top < viewRect.top || docPos.top > viewRect.bottom) && scrollRef) {
                         const scrollPos = scrollRef.scrollTop + (docPos.top - viewRect.top) * self.props.ScreenToLocalTransform().Scale;
-                        if (!LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc) {
+                        if (!LinkDocPreview.LinkInfo) {
                             scrollPos && smoothScroll(500, scrollRef, scrollPos);
                         } else {
                             scrollRef.scrollTo({ top: scrollPos });
@@ -1338,7 +1338,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     onPointerUp = (e: React.PointerEvent): void => {
         if (!this._downEvent) return;
         this._downEvent = false;
-        if (!(e.nativeEvent as any).formattedHandled) {
+        if (!(e.nativeEvent as any).formattedHandled && this.active(true)) {
             const editor = this._editorView!;
             FormattedTextBoxComment.textBox = this;
             const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
@@ -1366,13 +1366,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             e.preventDefault();
         }
         FormattedTextBoxComment.Hide();
-        if (FormattedTextBoxComment.linkDoc) {
-            if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) {
-                this.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "add" : "add:right");
-            } else {
-                LinkManager.FollowLink(FormattedTextBoxComment.linkDoc, this.props.Document, this.props, false);
-            }
-        }
 
         (e.nativeEvent as any).formattedHandled = true;
 
@@ -1601,7 +1594,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         eve.stopPropagation(); // drag n drop of text within text note will generate a new note if not caughst, as will dragging in from outside of Dash.
     }
     onScroll = (ev: React.UIEvent) => {
-        if (!LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this._scrollRef.current) {
+        if (!LinkDocPreview.LinkInfo && this._scrollRef.current) {
             this._ignoreScroll = true;
             this.layoutDoc._scrollTop = this._scrollRef.current.scrollTop;
             this._ignoreScroll = false;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
index 81afba4d7..3251319b9 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
@@ -1,6 +1,8 @@
 .FormattedTextBox-tooltip {
     position: absolute;
-    pointer-events: none;
+    pointer-events: all;
+    height: 100%;
+    overflow: hidden;
     z-index: 20;
     background: white;
     border: 1px solid silver;
@@ -9,67 +11,9 @@
     -webkit-transform: translateX(-50%);
     transform: translateX(-50%);
     box-shadow: 3px 3px 1.5px grey;
-
-    .FormattedTextBoxComment {
-        background-color: white;
-        border: 8px solid white;
-        //width: 200px;
-
-        //display: flex;
-        .FormattedTextBoxComment-info {
-
-            margin-bottom: 37px;
-
-            .FormattedTextBoxComment-title {
-                padding-right: 4px;
-                float: left;
-
-                .FormattedTextBoxComment-description {
-                    text-decoration: none;
-                    font-style: italic;
-                    color: rgb(95, 97, 102);
-                    font-size: 10px;
-                }
-            }
-
-            .FormattedTextBoxComment-button {
-                display: inline;
-                padding-left: 6px;
-                padding-right: 6px;
-                padding-top: 2.5px;
-                padding-bottom: 2.5px;
-                width: 17px;
-                height: 17px;
-                margin: 0;
-                margin-right: 3px;
-                border-radius: 50%;
-                pointer-events: auto;
-                background-color: rgb(0, 0, 0);
-                color: rgb(255, 255, 255);
-                transition: transform 0.2s;
-                text-align: center;
-                position: relative;
-                font-size: 12px;
-
-                &:hover {
-                    background-color: rgb(77, 77, 77);
-                    cursor: pointer;
-                }
-            }
-        }
-
-        .FormattedTextBoxComment-preview-wrapper {
-            //width: 170px;
-            height: 170px;
-            overflow: hidden;
-            //padding-top: 5px;
-            margin-top: 10px;
-            margin-bottom: 8px;
-            align-content: center;
-            justify-content: center;
-            background-color: rgb(160, 160, 160);
-        }
-    }
+    max-width: 400;
+    max-height: 235;
+    height:max-content;
 }
 
 .FormattedTextBox-tooltip:before {
@@ -96,12 +40,4 @@
     border: 5px solid transparent;
     border-bottom-width: 0;
     border-top-color: white;
-}
-
-.FormattedTextBoxComment-buttons {
-    display: none;
-    position: absolute;
-    top: 50%;
-    right: 0;
-    transform: translateY(-50%);
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index d1bb2ad84..827bb2591 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -1,28 +1,17 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
 import { action, observable } from "mobx";
 import { Mark, ResolvedPos } from "prosemirror-model";
 import { EditorState, Plugin } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import * as ReactDOM from 'react-dom';
-import wiki from "wikijs";
-import { Doc, DocCastAsync, DocListCast, Opt } from "../../../../fields/Doc";
-import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types";
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, Utils, emptyPath } from "../../../../Utils";
+import { Doc, DocListCast, Opt } from "../../../../fields/Doc";
+import { Utils } from "../../../../Utils";
 import { DocServer } from "../../../DocServer";
 import { Docs } from "../../../documents/Documents";
-import { DocumentType } from "../../../documents/DocumentTypes";
-import { LinkManager } from "../../../util/LinkManager";
-import { Transform } from "../../../util/Transform";
-import { undoBatch } from "../../../util/UndoManager";
-import { DocumentLinksButton } from "../DocumentLinksButton";
-import { DocumentView } from "../DocumentView";
 import { LinkDocPreview } from "../LinkDocPreview";
 import { FormattedTextBox } from "./FormattedTextBox";
 import './FormattedTextBoxComment.scss';
 import { schema } from "./schema_rts";
 import React = require("react");
-import { DefaultStyleProvider } from "../../StyleProvider";
 
 export let formattedTextBoxCommentPlugin = new Plugin({
     view(editorView) { return new FormattedTextBoxComment(editorView); }
@@ -64,67 +53,24 @@ export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (mark
 export class FormattedTextBoxComment {
     static tooltip: HTMLElement;
     static tooltipText: HTMLElement;
-    static tooltipInput: HTMLInputElement;
     static start: number;
     static end: number;
     static mark: Mark;
     static textBox: FormattedTextBox | undefined;
-    static linkDoc: Doc | undefined;
-
-    static _deleteRef: Opt<HTMLDivElement | null>;
-    static _followRef: Opt<HTMLDivElement | null>;
-    static _nextRef: Opt<HTMLDivElement | null>;
-
-    static _lastState?: EditorState;
-    static _lastView?: EditorView;
-
-    @observable static _hrefInd = 0;
-    static _hrefs: string[] | undefined = [];
 
     constructor(view: any) {
         if (!FormattedTextBoxComment.tooltip) {
             const root = document.getElementById("root");
-            FormattedTextBoxComment.tooltipInput = document.createElement("input");
-            FormattedTextBoxComment.tooltipInput.type = "checkbox";
             FormattedTextBoxComment.tooltip = document.createElement("div");
             FormattedTextBoxComment.tooltipText = document.createElement("div");
-            //FormattedTextBoxComment.tooltipText.style.width = "100%";
-            FormattedTextBoxComment.tooltipText.style.height = "100%";
+            FormattedTextBoxComment.tooltipText.style.height = "max-content";
             FormattedTextBoxComment.tooltipText.style.textOverflow = "ellipsis";
             FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText);
             FormattedTextBoxComment.tooltip.className = "FormattedTextBox-tooltip";
-            FormattedTextBoxComment.tooltip.style.pointerEvents = "all";
-            FormattedTextBoxComment.tooltip.style.maxWidth = "400px";
-            FormattedTextBoxComment.tooltip.style.maxHeight = "235px";
-            //FormattedTextBoxComment.tooltip.style.width = "100%";
-            FormattedTextBoxComment.tooltip.style.height = "100%";
-            FormattedTextBoxComment.tooltip.style.overflow = "hidden";
             FormattedTextBoxComment.tooltip.style.display = "none";
-            // FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipInput);
-            FormattedTextBoxComment.tooltip.onpointerdown = async (e: PointerEvent) => {
-                const keep = e.target && (e.target as any).type === "checkbox" ? true : false;
+            FormattedTextBoxComment.tooltip.onpointerdown = (e: PointerEvent) => {
                 const textBox = FormattedTextBoxComment.textBox;
-                const linkDoc = FormattedTextBoxComment.linkDoc;
-                if (linkDoc && !keep && textBox) {
-                    if (linkDoc.author) {
-                        if (FormattedTextBoxComment._deleteRef?.contains(e.target as any)) {
-                            this.deleteLink();
-                        } else if (FormattedTextBoxComment._nextRef?.contains(e.target as any)) {
-                            FormattedTextBoxComment.showPreview(FormattedTextBoxComment._lastView!, FormattedTextBoxComment._lastState, FormattedTextBoxComment._hrefs?.[(++FormattedTextBoxComment._hrefInd) % FormattedTextBoxComment._hrefs?.length]);
-                        } else {
-                            FormattedTextBoxComment.linkDoc = undefined;
-                            if (linkDoc.type !== DocumentType.LINK) {
-                                textBox.props.addDocTab(linkDoc, e.ctrlKey ? "add" : "add:right");
-                            } else {
-                                const target = LinkManager.getOppositeAnchor(linkDoc, textBox.dataDoc);
-                                target && LinkManager.FollowLink(linkDoc, textBox.dataDoc, textBox.props, e.altKey);
-                            }
-                        }
-                    }
-                } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) {
-                    textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400, useCors: true }), "add:right");
-                }
-                keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation(
+                false && FormattedTextBoxComment.start !== undefined && textBox?.adoptAnnotation(
                     FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark);
                 e.stopPropagation();
                 e.preventDefault();
@@ -132,21 +78,9 @@ export class FormattedTextBoxComment {
             root?.appendChild(FormattedTextBoxComment.tooltip);
         }
     }
-
-    @undoBatch
-    deleteLink = action(() => {
-        FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null;
-        FormattedTextBoxComment.Hide();
-    });
-
     public static Hide() {
         FormattedTextBoxComment.textBox = undefined;
-        FormattedTextBoxComment.linkDoc = undefined;
         FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none");
-        try {
-            ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText);
-            FormattedTextBoxComment.tooltip.removeChild(FormattedTextBoxComment.tooltipText);
-        } catch (e) { }
     }
     public static SetState(textBox: any, start: number, end: number, mark: Mark) {
         FormattedTextBoxComment.textBox = textBox;
@@ -170,180 +104,71 @@ export class FormattedTextBoxComment {
             const left = Math.max((start.left + end.left) / 2, start.left + 3);
             FormattedTextBoxComment.tooltip.style.left = (left - box.left) + "px";
             FormattedTextBoxComment.tooltip.style.bottom = (box.bottom - start.top) + "px";
-            // const props = FormattedTextBoxComment.textBox?.props.docViewPath.lastElement().props;
-            // props && (LinkDocPreview.SetLinkInfo({
-            //     docprops: props,
-            //     linkSrc: props.Document,
-            //     linkDoc: FormattedTextBoxComment.linkDoc,
-            //     Location: [start.left, start.top + 25]
-            // });
         }
         FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = set);
     }
 
-    static update(view: EditorView, lastState?: EditorState, forceUrl: string = "") {
-        // Don't do anything if the document/selection didn't change
-        if (!forceUrl && lastState?.doc.eq(view.state.doc) && lastState?.selection.eq(view.state.selection)) {
-            return;
+    static update(view: EditorView, lastState?: EditorState, hrefs: string = "") {
+        if (FormattedTextBoxComment.textBox && (hrefs || !lastState?.doc.eq(view.state.doc) || !lastState?.selection.eq(view.state.selection))) {
+            FormattedTextBoxComment.setupPreview(view, FormattedTextBoxComment.textBox, hrefs ? hrefs.trim().split(" ") : undefined);
         }
-        FormattedTextBoxComment._lastState = lastState;
-        FormattedTextBoxComment._lastView = view;
-        FormattedTextBoxComment._hrefs = forceUrl ? forceUrl.trim().split(" ") : undefined;
-        FormattedTextBoxComment._hrefInd = 0;
-        FormattedTextBoxComment.linkDoc = undefined;
-        FormattedTextBoxComment.showPreview(view, lastState, FormattedTextBoxComment._hrefs?.[FormattedTextBoxComment._hrefInd]);
     }
 
-    static showPreview(view: EditorView, lastState?: EditorState, forceUrl: string = "") {
+    static setupPreview(view: EditorView, textBox: FormattedTextBox, hrefs?: string[]) {
         const state = view.state;
-        const textBox = FormattedTextBoxComment.textBox;
-        if (!textBox || !textBox.props) {
-            return;
-        }
-        let set = "none";
-        let nbef = 0;
-        FormattedTextBoxComment.tooltipInput.style.display = "none";
-        FormattedTextBoxComment.tooltip.style.width = "";
-        FormattedTextBoxComment.tooltip.style.height = "";
-        (FormattedTextBoxComment.tooltipText as any).href = "";
-        FormattedTextBoxComment.tooltipText.style.whiteSpace = "";
-        FormattedTextBoxComment.tooltipText.style.overflow = "";
         // this section checks to see if the insertion point is over text entered by a different user.  If so, it sets ths comment text to indicate the user and the modification date
+        var hide = true;
         if (state.selection.$from) {
-            nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark);
+            const nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark);
             const naft = findEndOfMark(state.selection.$from, view, findOtherUserMark);
-            const noselection = view.state.selection.$from === view.state.selection.$to;
+            const noselection = state.selection.$from === state.selection.$to;
             let child: any = null;
             state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node));
             const mark = child && findOtherUserMark(child.marks);
             if (mark && child && (nbef || naft) && (!mark.attrs.opened || noselection)) {
-                FormattedTextBoxComment.SetState(FormattedTextBoxComment.textBox, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark);
+                FormattedTextBoxComment.SetState(textBox, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark);
             }
             if (mark && child && ((nbef && naft) || !noselection)) {
                 FormattedTextBoxComment.tooltipText.textContent = mark.attrs.userid + " on " + (new Date(mark.attrs.modified * 1000)).toLocaleString();
-                set = "";
-                FormattedTextBoxComment.tooltipInput.style.display = "";
+                FormattedTextBoxComment.showCommentbox("", view, nbef);
+                hide = false;
             }
         }
         // this checks if the selection is a hyperlink.  If so, it displays the target doc's text for internal links, and the url of the target for external links. 
-        if (set === "none" && state.selection.$from) {
-            nbef = findStartOfMark(state.selection.$from, view, findLinkMark);
+        if (hide && state.selection.$from) {
+            const nbef = findStartOfMark(state.selection.$from, view, findLinkMark);
             const naft = findEndOfMark(state.selection.$from, view, findLinkMark) || nbef;
             let child: any = null;
             state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node));
             child = child || (nbef && state.selection.$from.nodeBefore);
             const mark = child ? findLinkMark(child.marks) : undefined;
-            const href = forceUrl || (!mark?.attrs.docref || naft === nbef) && mark?.attrs.allAnchors.find((item: { href: string }) => item.href)?.href;
-            if (forceUrl || (href && child && nbef && naft && mark?.attrs.showPreview)) {
-                try {
-                    ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText);
-                    FormattedTextBoxComment.tooltip.removeChild(FormattedTextBoxComment.tooltipText);
-                } catch (e) { }
-                FormattedTextBoxComment.tooltipText = document.createElement("div");
-                FormattedTextBoxComment.tooltipText.className = "FormattedTextBoxComment-toolTipText";
-                FormattedTextBoxComment.tooltipText.style.width = "100%";
-                FormattedTextBoxComment.tooltipText.style.height = "100%";
-                FormattedTextBoxComment.tooltipText.style.textOverflow = "ellipsis";
-                FormattedTextBoxComment.tooltipText.style.cursor = "pointer";
-                FormattedTextBoxComment.tooltipText.textContent = "URL: " + href;
-                (FormattedTextBoxComment.tooltipText as any).href = href;
-                FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText);
-
-                if (href.startsWith("https://en.wikipedia.org/wiki/")) {
-                    wiki().page(href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(summary => FormattedTextBoxComment.tooltipText.textContent = summary.substring(0, 500)));
-                } else {
-                    FormattedTextBoxComment.tooltipText.style.whiteSpace = "pre";
-                    FormattedTextBoxComment.tooltipText.style.overflow = "hidden";
-                }
-                if (href.indexOf(Utils.prepend("/doc/")) === 0) {
-                    const anchorDoc = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
-                    FormattedTextBoxComment.tooltipText.textContent = "target not found...";
-                    (FormattedTextBoxComment.tooltipText as any).href = "";
-                    anchorDoc && DocServer.GetRefField(anchorDoc).then(async anchor => {
-                        if (anchor instanceof Doc) {
-                            const linkDoc = DocListCast(anchor.links)[0];
-                            (FormattedTextBoxComment.tooltipText as any).href = href;
-                            FormattedTextBoxComment.linkDoc = linkDoc;
-                            const targetanchor = LinkManager.getOppositeAnchor(linkDoc, anchor);
-                            const target = targetanchor?.annotationOn ? await DocCastAsync(targetanchor.annotationOn) : targetanchor;
-                            if (target?.author) {
-                                FormattedTextBoxComment.showCommentbox("", view, nbef);
-
-                                const title = StrCast(target.title).length > 16 ? StrCast(target.title).substr(0, 16) + "..." : target.title;
-
-                                const docPreview = <div className="FormattedTextBoxComment">
-                                    <div className="FormattedTextBoxComment-info">
-                                        <div className="FormattedTextBoxComment-title">
-                                            {title}
-                                            {FormattedTextBoxComment.linkDoc.description === "" ? (null) :
-                                                <p className="FormattedTextBoxComment-description"> {StrCast(FormattedTextBoxComment.linkDoc.description)}</p>}
-                                        </div>
-                                        <div className="wrapper" style={{ float: "right" }}>
-                                            {(FormattedTextBoxComment._hrefs?.length || 0) <= 1 ? (null) : <Tooltip title={<><div className="dash-tooltip">Next Link</div></>} placement="top">
-                                                <div className="FormattedTextBoxComment-button" ref={(r) => this._nextRef = r}>
-                                                    <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="chevron-right" color="white" size="sm" />
-                                                </div>
-                                            </Tooltip>}
-
-                                            <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>} placement="top">
-                                                <div className="FormattedTextBoxComment-button" ref={(r) => this._deleteRef = r}>
-                                                    <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white" size="sm" />
-                                                </div>
-                                            </Tooltip>
-
-                                            <Tooltip title={<><div className="dash-tooltip">Follow Link</div></>} placement="top">
-                                                <div className="FormattedTextBoxComment-button" ref={(r) => this._followRef = r}>
-                                                    <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white" size="sm" />
-                                                </div>
-                                            </Tooltip>
-                                        </div>
-                                    </div>
-                                    <div className="FormattedTextBoxComment-preview-wrapper">
-                                        <DocumentView ref={(r) => targetanchor && target !== targetanchor && r?.focus(targetanchor)}
-                                            Document={target}
-                                            moveDocument={returnFalse}
-                                            rootSelected={returnFalse}
-                                            styleProvider={DefaultStyleProvider}
-                                            layerProvider={undefined}
-                                            docViewPath={emptyPath}
-                                            ScreenToLocalTransform={Transform.Identity}
-                                            parentActive={returnFalse}
-                                            addDocument={returnFalse}
-                                            removeDocument={returnFalse}
-                                            addDocTab={returnFalse}
-                                            pinToPres={returnFalse}
-                                            dontRegisterView={true}
-                                            docFilters={returnEmptyFilter}
-                                            docRangeFilters={returnEmptyFilter}
-                                            searchFilterDocs={returnEmptyDoclist}
-                                            ContainingCollectionDoc={undefined}
-                                            ContainingCollectionView={undefined}
-                                            renderDepth={-1}
-                                            PanelWidth={() => 175} //Math.min(350, NumCast(target._width, 350))}
-                                            PanelHeight={() => 175} //Math.min(250, NumCast(target._height, 250))}
-                                            focus={emptyFunction}
-                                            whenActiveChanged={returnFalse}
-                                            bringToFront={returnFalse}
-                                            NativeWidth={Doc.NativeWidth(target) ? (() => Doc.NativeWidth(target)) : undefined}
-                                            NativeHeight={Doc.NativeHeight(target) ? (() => Doc.NativeHeight(target)) : undefined}
-                                        />
-                                    </div>
-                                </div>;
-
-                                FormattedTextBoxComment.showCommentbox("", view, nbef);
-
-                                ReactDOM.render(docPreview, FormattedTextBoxComment.tooltipText);
-
-                                //FormattedTextBoxComment.tooltip.style.width = "100%";
-                                FormattedTextBoxComment.tooltip.style.height = "100%";
-                            }
-                        }
+            const href = (!mark?.attrs.docref || naft === nbef) && mark?.attrs.allAnchors.find((item: { href: string }) => item.href)?.href;
+            if ((href && child && nbef && naft && mark?.attrs.showPreview)) {
+                const anchorDoc = href.indexOf(Utils.prepend("/doc/")) === 0 ? href.replace(Utils.prepend("/doc/"), "").split("?")[0] : undefined;
+                if (anchorDoc) {
+                    DocServer.GetRefField(anchorDoc).then(async anchor =>
+                        anchor instanceof Doc && textBox && LinkDocPreview.SetLinkInfo({
+                            docprops: textBox.props.docViewPath.lastElement().props,
+                            linkSrc: textBox.props.Document,
+                            linkDoc: DocListCast(anchor.links)[0],
+                            location: ((pos) => [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - nbef)),
+                            hrefs,
+                            showHeader: true
+                        })
+                    );
+                } else if (hrefs?.length) {
+                    LinkDocPreview.SetLinkInfo({
+                        docprops: textBox.props.docViewPath.lastElement().props,
+                        linkSrc: textBox.props.Document,
+                        linkDoc: undefined,
+                        location: ((pos) => [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - nbef)),
+                        hrefs,
+                        showHeader: true
                     });
                 }
-                set = "";
             }
         }
-        FormattedTextBoxComment.showCommentbox(set, view, nbef);
+        if (hide) FormattedTextBoxComment.Hide();
     }
 
     destroy() { }
-- 
cgit v1.2.3-70-g09d2


From 861363c59997db5cde1b96786b156b64630465d7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Feb 2021 10:35:34 -0500
Subject: fixed some z-index issues with lightbox and typing new notes +
 videobox zooming zindex

---
 src/client/views/LightboxView.scss                        | 2 +-
 src/client/views/PreviewCursor.scss                       | 1 +
 src/client/views/collections/CollectionMenu.scss          | 6 +++---
 src/client/views/nodes/VideoBox.scss                      | 5 +++++
 src/client/views/nodes/VideoBox.tsx                       | 2 +-
 src/client/views/nodes/WebBox.scss                        | 2 +-
 src/client/views/nodes/formattedText/FormattedTextBox.tsx | 3 ++-
 src/client/views/search/SearchBox.scss                    | 2 +-
 8 files changed, 15 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/LightboxView.scss b/src/client/views/LightboxView.scss
index 9847966bf..35f11b699 100644
--- a/src/client/views/LightboxView.scss
+++ b/src/client/views/LightboxView.scss
@@ -4,7 +4,7 @@
     width: 100%;
     height: 100%;
     background: #000000bb;
-    z-index: 10000;
+    z-index: 1000;
     .lightboxView-contents {
         position: absolute;
     }
diff --git a/src/client/views/PreviewCursor.scss b/src/client/views/PreviewCursor.scss
index d384fd284..de9bd69c4 100644
--- a/src/client/views/PreviewCursor.scss
+++ b/src/client/views/PreviewCursor.scss
@@ -7,4 +7,5 @@
     left:0;
     pointer-events: none;
     opacity: 1;
+    z-index: 1001;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index 180eaba4e..47adb6a1c 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -6,7 +6,7 @@
     display: inline-flex;
     width: 100%;
     opacity: 0.9;
-    z-index: 9001;
+    z-index: 901;
     transition: top .5s;
     background: #323232;
     color: white;
@@ -30,7 +30,7 @@
         height: 32px;
         border-bottom: .5px solid rgb(180, 180, 180);
         overflow: visible;
-        z-index: 9001;
+        z-index: 901;
         border: unset;
 
         .collectionViewBaseChrome {
@@ -325,7 +325,7 @@
 .webBox-urlEditor {
     position: relative;
     opacity: 0.9;
-    z-index: 9001;
+    z-index: 901;
     transition: top .5s;
 
     .urlEditor {
diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss
index b9123587b..dd8d77603 100644
--- a/src/client/views/nodes/VideoBox.scss
+++ b/src/client/views/nodes/VideoBox.scss
@@ -13,6 +13,11 @@
     .collectionStackedTimeline {
         background: beige;
     }
+    .videoBox-stackPanel {
+        z-index: -1;
+        width: 100%;
+        position: absolute; 
+    }
 }
 
 .videoBox-content-YouTube, .videoBox-content-YouTube-fullScreen,
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 324861573..a821eb7c2 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -489,7 +489,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
     setAnchorTime = (time: number) => this.player!.currentTime = this.layoutDoc._currentTimecode = time;
     timelineHeight = () => this.props.PanelHeight() * (100 - this.heightPercent) / 100;
     @computed get renderTimeline() {
-        return <div style={{ width: "100%", transition: this.transition, height: `${100 - this.heightPercent}%`, position: "absolute" }}>
+        return <div className="videoBox-stackPanel" style={{ transition: this.transition, height: `${100 - this.heightPercent}%` }}>
             <CollectionStackedTimeline ref={this._stackedTimeline} {...this.props}
                 fieldKey={this.annotationKey}
                 renderDepth={this.props.renderDepth + 1}
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index 5a7c1c904..ca6611a6b 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -96,7 +96,7 @@
     }
 
     .webBox-annotationToggle {
-        z-index: 9001;
+        z-index: 901;
         position: absolute;
         top: 2;
         left: 2;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 2434bee40..a91157519 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -66,6 +66,7 @@ import { StyleProp } from '../../StyleProvider';
 import { AnchorMenu } from '../../pdf/AnchorMenu';
 import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
 import { DocumentManager } from '../../../util/DocumentManager';
+import { LightboxView } from '../../LightboxView';
 const translateGoogleApi = require("translate-google-api");
 
 export interface FormattedTextBoxProps {
@@ -1244,7 +1245,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             (this._editorView as any).TextView = this;
         }
 
-        const selectOnLoad = this.rootDoc[Id] === FormattedTextBox.SelectOnLoad;
+        const selectOnLoad = this.rootDoc[Id] === FormattedTextBox.SelectOnLoad && (!LightboxView.LightboxDoc || this.props.docViewPath.includes(LightboxView.LightboxDocView.current!));
         if (selectOnLoad && !this.props.dontRegisterView && !this.props.dontSelectOnLoad && this.isActiveTab(this.ProseRef)) {
             FormattedTextBox.SelectOnLoad = "";
             this.props.select(false);
diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss
index 76f9b66eb..4f5b7e41a 100644
--- a/src/client/views/search/SearchBox.scss
+++ b/src/client/views/search/SearchBox.scss
@@ -13,7 +13,7 @@
     overflow-x: visible;
     background: lightgrey;
     overflow: visible;
-    z-index: 10000;
+    z-index: 1000;
 
     .searchBox-bar {
         height: $searchpanel-height;
-- 
cgit v1.2.3-70-g09d2


From c37675d530f77ad2c077d0155d2ee3e35c55978b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Feb 2021 18:31:40 -0500
Subject: fixed creating videoBox anchor to reference the whole doc when the
 timecode is 0.  fixed following links to a document that has a colleciton
 context to open the context properly.

---
 src/client/util/DocumentManager.ts  | 12 ++++--------
 src/client/util/LinkManager.ts      | 12 ++++++------
 src/client/views/nodes/VideoBox.tsx |  3 ++-
 src/fields/documentSchemas.ts       |  2 +-
 4 files changed, 13 insertions(+), 16 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 811d04eb3..d7335c8c6 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -149,14 +149,10 @@ export class DocumentManager {
         const focusAndFinish = () => { finished?.(); return false; };
         const highlight = () => {
             const finalDocView = getFirstDocView(targetDoc);
-            if (finalDocView) {
-                const parent = targetDoc?.annotationOn as Doc;
-                if (parent) finalDocView.layoutDoc.scrollToAnchorID = targetDoc?.[Id];
-                Doc.linkFollowHighlight(finalDocView.rootDoc);
-            }
+            finalDocView && Doc.linkFollowHighlight(finalDocView.rootDoc);
         };
         const docView = getFirstDocView(targetDoc, originatingDoc);
-        let annotatedDoc = await Cast(targetDoc.annotationOn, Doc);
+        let annotatedDoc = Cast(targetDoc.annotationOn, Doc, null);
         if (annotatedDoc && annotatedDoc !== originatingDoc?.context && !targetDoc?.isPushpin) {
             const first = getFirstDocView(annotatedDoc);
             if (first) {
@@ -184,8 +180,8 @@ export class DocumentManager {
             highlight();
         } else {
             const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined;
-            const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc)) ? docContext : undefined;
-            const targetDocContext = annotatedDoc || contextDoc;
+            const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined;
+            const targetDocContext = contextDoc || annotatedDoc;
 
             if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default
                 createViewFunc(Doc.BrushDoc(targetDoc), finished); // bcz: should we use this?: Doc.MakeAlias(targetDoc)));
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index a684a202d..7ad37f059 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -102,7 +102,7 @@ export class LinkManager {
     // follows a link - if the target is on screen, it highlights/pans to it.
     // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place
     // depending on the followLinkLocation property of the source (or the link itself as a fallback);
-    public static FollowLink = async (linkDoc: Opt<Doc>, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean) => {
+    public static FollowLink = (linkDoc: Opt<Doc>, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean) => {
         const batch = UndoManager.StartBatch("follow link click");
         // open up target if it's not already in view ...
         const createViewFunc = (doc: Doc, followLoc: string, finished: Opt<() => void>) => {
@@ -126,9 +126,9 @@ export class LinkManager {
                 docViewProps.focus(sourceDoc, BoolCast(sourceDoc.followLinkZoom, true), 1, targetFocusAfterDocFocus);
             }
         };
-        await LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined);
+        LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined);
     }
-    public static async traverseLink(link: Opt<Doc>, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) {
+    public static traverseLink(link: Opt<Doc>, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) {
         const linkDocs = link ? [link] : DocListCast(doc.links);
         const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1
         const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2
@@ -150,9 +150,9 @@ export class LinkManager {
                         runInAction(() => LightboxView.LightboxDoc = (target.annotationOn as Doc) ?? target);
                         finished?.();
                     } else {
-                        const containerDoc = (await Cast(target.annotationOn, Doc)) || target;
-                        containerDoc._currentTimecode = targetTimecode;
-                        const targetContext = await target?.context as Doc;
+                        const containerDoc = Cast(target.annotationOn, Doc, null) || target;
+                        targetTimecode !== undefined && (containerDoc._currentTimecode = targetTimecode);
+                        const targetContext = Cast(containerDoc?.context, Doc, null);
                         const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
                         DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, doc, finished);
                     }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index a821eb7c2..c0247c226 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -70,7 +70,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
     }
 
     getAnchor = () => {
-        return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey + "-timeline", "videoStart", "videoEnd", Cast(this.layoutDoc._currentTimecode, "number", null)) || this.rootDoc;
+        const timecode = Cast(this.layoutDoc._currentTimecode, "number", null);
+        return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey + "-timeline", "videoStart", "videoEnd", timecode ? timecode : undefined) || this.rootDoc;
     }
 
     choosePath(url: string) {
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index f35c85110..056243953 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -114,7 +114,7 @@ export const collectionSchema = createSchema({
     childLayoutTemplate: Doc, // layout template to use to render children of a collecion
     childLayoutString: "string", //layout string to use to render children of a collection
     childClickedOpenTemplateView: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to read this value and apply template)
-    dontRegisterChildViews: "boolean", // whether views made of this document are registered so that they can be found when drawing links scrollToAnchorID: "string",   // id of anchor being traversed. allows this doc to scroll/highlight/etc its link anchor. scrollToAnchorID should be set to undefined by this doc after it sets up its scroll,etc.
+    dontRegisterChildViews: "boolean", // whether views made of this document are registered so that they can be found when drawing links 
     onChildClick: ScriptField, // script to run for each child when its clicked
     onChildDoubleClick: ScriptField, // script to run for each child when its clicked
     onCheckedClick: ScriptField, // script to run when a checkbox is clicked next to a child in a tree view
-- 
cgit v1.2.3-70-g09d2

