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

---
 .../formattedText/FormattedTextBoxComment.tsx      | 255 ++++-----------------
 1 file changed, 40 insertions(+), 215 deletions(-)

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

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

