From b8d4b08716791246847d2a647a9df1f37508b87f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 8 Nov 2022 14:43:47 -0500
Subject: making pasting form pdf work again with backlinks. text fixes for
 equationViews and dashField views -- trying to get docref linkAnchor to work.

---
 .../views/nodes/formattedText/FormattedTextBox.tsx | 87 ++++++++--------------
 1 file changed, 32 insertions(+), 55 deletions(-)

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

diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 63435eea8..fc8d2b7dd 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1,7 +1,7 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { isEqual } from 'lodash';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx';
 import { observer } from 'mobx-react';
 import { baseKeymap, selectAll } from 'prosemirror-commands';
 import { history } from 'prosemirror-history';
@@ -87,7 +87,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
     private _ref: React.RefObject<HTMLDivElement> = React.createRef();
     private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _editorView: Opt<EditorView>;
-    private _applyingChange: string = '';
+    public _applyingChange: string = '';
     private _searchIndex = 0;
     private _lastTimedMark: Mark | undefined = undefined;
     private _cachedLinks: Doc[] = [];
@@ -499,12 +499,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             const end = this._editorView.state.doc.nodeSize - 2;
             this._editorView.dispatch(this._editorView.state.tr.removeMark(0, end, mark).removeMark(0, end, activeMark));
         }
-        if (FormattedTextBox.PasteOnLoad) {
-            const pdfDocId = FormattedTextBox.PasteOnLoad.clipboardData?.getData('dash/pdfOrigin');
-            const pdfRegionId = FormattedTextBox.PasteOnLoad.clipboardData?.getData('dash/pdfRegion');
-            FormattedTextBox.PasteOnLoad = undefined;
-            setTimeout(() => pdfDocId && pdfRegionId && this.addPdfReference(pdfDocId, pdfRegionId, undefined), 10);
-        }
     };
     adoptAnnotation = (start: number, end: number, mark: Mark) => {
         const view = this._editorView!;
@@ -1235,61 +1229,38 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
     };
 
     handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => {
-        const cbe = event as ClipboardEvent;
-        const pdfDocId = cbe.clipboardData?.getData('dash/pdfOrigin');
-        const pdfRegionId = cbe.clipboardData?.getData('dash/pdfRegion');
-        return pdfDocId && pdfRegionId && this.addPdfReference(pdfDocId, pdfRegionId, slice) ? true : false;
+        const pdfAnchorId = (event as ClipboardEvent).clipboardData?.getData('dash/pdfAnchor');
+        return pdfAnchorId && this.addPdfReference(pdfAnchorId) ? true : false;
     };
 
-    addPdfReference = (pdfDocId: string, pdfRegionId: string, slice?: Slice) => {
+    addPdfReference = (pdfAnchorId: string) => {
         const view = this._editorView!;
-        if (pdfDocId && pdfRegionId) {
-            DocServer.GetRefField(pdfDocId).then(pdfDoc => {
-                DocServer.GetRefField(pdfRegionId).then(pdfRegion => {
-                    if (pdfDoc instanceof Doc && pdfRegion instanceof Doc) {
-                        setTimeout(async () => {
-                            const targetField = Doc.LayoutFieldKey(pdfDoc);
-                            const targetAnnotations = await DocListCastAsync(pdfDoc[DataSym][targetField + '-annotations']); // bcz: better to have the PDF's view handle updating its own annotations
-                            if (targetAnnotations) targetAnnotations.push(pdfRegion);
-                            else Doc.AddDocToList(pdfDoc[DataSym], targetField + '-annotations', pdfRegion);
-                        });
-
-                        const link = DocUtils.MakeLink({ doc: this.rootDoc }, { doc: pdfRegion }, 'PDF pasted');
-                        if (link) {
-                            const linkId = link[Id];
-                            const quote = view.state.schema.nodes.blockquote.create({ content: addMarkToFrag(slice?.content || view.state.doc.content, (node: Node) => addLinkMark(node, StrCast(pdfDoc.title), linkId)) });
-                            const newSlice = new Slice(Fragment.from(quote), slice?.openStart || 0, slice?.openEnd || 0);
-                            if (slice) {
-                                view.dispatch(view.state.tr.replaceSelection(newSlice).scrollIntoView().setMeta('paste', true).setMeta('uiEvent', 'paste'));
-                            } else {
-                                selectAll(view.state, (tx: Transaction) => view.dispatch(tx.replaceSelection(newSlice).scrollIntoView()));
-                            }
-                        }
+        if (pdfAnchorId) {
+            DocServer.GetRefField(pdfAnchorId).then(pdfAnchor => {
+                if (pdfAnchor instanceof Doc) {
+                    const dashField = view.state.schema.nodes.paragraph.create({}, [
+                        view.state.schema.nodes.dashField.create({ fieldKey: 'text', docid: pdfAnchor[Id], hideKey: true, editable: false }, undefined, [
+                            view.state.schema.marks.linkAnchor.create({
+                                allAnchors: [{ href: `/doc/${this.rootDoc[Id]}`, title: this.rootDoc.title, anchorId: `${this.rootDoc[Id]}` }],
+                                location: 'add:right',
+                                title: `from: ${DocCast(pdfAnchor.context).title}`,
+                                noPreview: true,
+                                docref: false,
+                            }),
+                            view.state.schema.marks.pFontSize.create({ fontSize: '8px' }),
+                            view.state.schema.marks.em.create({}),
+                        ]),
+                    ]);
+
+                    const link = DocUtils.MakeLink({ doc: pdfAnchor }, { doc: this.rootDoc }, 'PDF pasted');
+                    if (link) {
+                        view.dispatch(view.state.tr.replaceSelectionWith(dashField, false).scrollIntoView().setMeta('paste', true).setMeta('uiEvent', 'paste'));
                     }
-                });
+                }
             });
             return true;
         }
         return false;
-
-        function addMarkToFrag(frag: Fragment, marker: (node: Node) => Node) {
-            const nodes: Node[] = [];
-            frag.forEach(node => nodes.push(marker(node)));
-            return Fragment.fromArray(nodes);
-        }
-
-        function addLinkMark(node: Node, title: string, linkId: string) {
-            if (!node.isText) {
-                const content = addMarkToFrag(node.content, (node: Node) => addLinkMark(node, title, linkId));
-                return node.copy(content);
-            }
-            const marks = [...node.marks];
-            const linkIndex = marks.findIndex(mark => mark.type.name === 'link');
-            const allLinks = [{ href: Doc.globalServerPath(linkId), title, linkId }];
-            const link = view.state.schema.mark(view.state.schema.marks.linkAnchor, { allLinks, location: 'add:right', title, docref: true });
-            marks.splice(linkIndex === -1 ? 0 : linkIndex, 1, link);
-            return node.mark(marks);
-        }
     };
 
     isActiveTab(el: Element | null | undefined) {
@@ -1417,6 +1388,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                 ...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontSize) })] : []),
                 ...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []),
             ];
+            if (FormattedTextBox.PasteOnLoad) {
+                const pdfAnchorId = FormattedTextBox.PasteOnLoad.clipboardData?.getData('dash/pdfAnchor');
+                FormattedTextBox.PasteOnLoad = undefined;
+                pdfAnchorId && this.addPdfReference(pdfAnchorId);
+            }
         }
         FormattedTextBox.DontSelectInitialText = false;
     }
@@ -1530,6 +1506,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         //applyDevTools.applyDevTools(this._editorView);
         FormattedTextBox.Focused = this;
         this.ProseRef?.children[0] === e.nativeEvent.target && this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props);
+        this.startUndoTypingBatch();
     };
     @observable public static Focused: FormattedTextBox | undefined;
 
-- 
cgit v1.2.3-70-g09d2

