diff options
author | bobzel <zzzman@gmail.com> | 2021-02-09 03:03:48 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2021-02-09 03:03:48 -0500 |
commit | 0f03183b9a2374ed3198d2b9ec8348fa819b11b4 (patch) | |
tree | c0acfb9869f3ea768f2574f3eda1592fa3a30ad4 /src | |
parent | 0e5891eab7f53697b764b7e9da5163db0351a0a2 (diff) |
fixed drawing link lines between everything except textanchor - to - textanchor.
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 2 | ||||
-rw-r--r-- | src/client/util/DocumentManager.ts | 75 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 45 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx | 29 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 9 | ||||
-rw-r--r-- | src/client/views/nodes/LinkAnchorBox.tsx | 2 | ||||
-rw-r--r-- | src/fields/Doc.ts | 7 |
7 files changed, 79 insertions, 90 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7d6db06d5..de4a8f43c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -789,7 +789,7 @@ export namespace Docs { } export function TextanchorDocument(options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.TEXTANCHOR), document, { targetDropAction: "move", ...options }); + return InstanceFromProto(Prototypes.get(DocumentType.TEXTANCHOR), undefined, { targetDropAction: "move", ...options }); } export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) { diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index f5f6b6f67..2a48f74b2 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,14 +1,13 @@ import { action, observable, runInAction } from 'mobx'; import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; -import { Cast, NumCast } from '../../fields/Types'; +import { Cast, NumCast, StrCast } from '../../fields/Types'; import { returnFalse } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; import { LightboxView } from '../views/LightboxView'; import { DocumentView } from '../views/nodes/DocumentView'; -import { LinkManager } from './LinkManager'; import { Scripting } from './Scripting'; export type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void; @@ -16,32 +15,28 @@ export type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: ( export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) - @observable - public DocumentViews: DocumentView[] = []; - @observable LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = []; + @observable public DocumentViews: DocumentView[] = []; + @observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = []; - // singleton instance private static _instance: DocumentManager; - - // create one and only one instance of NodeManager - public static get Instance(): DocumentManager { - return this._instance || (this._instance = new this()); - } + public static get Instance(): DocumentManager { return this._instance || (this._instance = new this()); } //private constructor so no other class can create a nodemanager - private constructor() { - } + private constructor() { } @action public AddView = (view: DocumentView) => { - const linksList = DocListCast(view.props.Document.links); - linksList.forEach(link => { - const linkToDoc = link && LinkManager.getOppositeAnchor(link, view.props.Document); - linkToDoc && DocumentManager.Instance.DocumentViews.filter(dv => Doc.AreProtosEqual(dv.props.Document, linkToDoc)).forEach(dv => { - if (dv.props.Document.type !== DocumentType.LINK || dv.props.LayoutTemplateString !== view.props.LayoutTemplateString) { - this.LinkedDocumentViews.push({ a: dv, b: view, l: link }); - } - }); + DocListCast(view.rootDoc.links).forEach(link => { + const whichOtherAnchor = view.props.LayoutTemplateString?.includes("anchor2") ? "anchor1" : "anchor2"; + const otherDoc = link && (link[whichOtherAnchor] as Doc); + const otherDocAnno = otherDoc?.type === DocumentType.TEXTANCHOR ? otherDoc.annotationOn as Doc : undefined; + otherDoc && DocumentManager.Instance.DocumentViews. + filter(dv => Doc.AreProtosEqual(dv.rootDoc, otherDoc) || Doc.AreProtosEqual(dv.rootDoc, otherDocAnno)). + forEach(otherView => { + if (otherView.rootDoc.type !== DocumentType.LINK || otherView.props.LayoutTemplateString !== view.props.LayoutTemplateString) { + this.LinkedDocumentViews.push({ a: whichOtherAnchor === "anchor1" ? otherView : view, b: whichOtherAnchor === "anchor1" ? view : otherView, l: link }); + } + }); }); this.DocumentViews.push(view); } @@ -56,13 +51,13 @@ export class DocumentManager { public getDocumentViewsById(id: string) { const toReturn: DocumentView[] = []; DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id) { + if (view.rootDoc[Id] === id) { toReturn.push(view); } }); if (toReturn.length === 0) { DocumentManager.Instance.DocumentViews.map(view => { - const doc = view.props.Document.proto; + const doc = view.rootDoc.proto; if (doc && doc[Id] && doc[Id] === id) { toReturn.push(view); } @@ -82,14 +77,14 @@ export class DocumentManager { for (const pass of passes) { DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { + if (view.rootDoc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; return; } }); if (!toReturn) { DocumentManager.Instance.DocumentViews.map(view => { - const doc = view.props.Document.proto; + const doc = view.rootDoc.proto; if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; } @@ -107,7 +102,7 @@ export class DocumentManager { } public getFirstDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => { - const views = this.getDocumentViews(toFind).filter(view => view.props.Document !== originatingDoc); + const views = this.getDocumentViews(toFind).filter(view => view.rootDoc !== originatingDoc); return views?.find(view => view.ContentDiv?.getBoundingClientRect().width && view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse) || (views.length ? views[0] : undefined); } public getDocumentViews(toFind: Doc): DocumentView[] { @@ -117,11 +112,11 @@ export class DocumentManager { // heuristic to return the "best" documents first: // choose an exact match over an alias match // choose documents that have a PanelWidth() over those that don't (the treeview documents have no panelWidth) - docViews.map(view => view.docViewPath.includes(LightboxView.LightboxDocView.current!) && view.props.Document === toFind && toReturn.push(view)); - docViews.map(view => view.props.PanelWidth() > 1 && view.props.Document === toFind && toReturn.push(view)); - docViews.map(view => view.props.PanelWidth() <= 1 && view.props.Document === toFind && toReturn.push(view)); - docViews.map(view => view.props.PanelWidth() > 1 && view.props.Document !== toFind && Doc.AreProtosEqual(view.props.Document, toFind) && toReturn.push(view)); - docViews.map(view => view.props.PanelWidth() <= 1 && view.props.Document !== toFind && Doc.AreProtosEqual(view.props.Document, toFind) && toReturn.push(view)); + docViews.map(view => view.docViewPath.includes(LightboxView.LightboxDocView.current!) && view.rootDoc === toFind && toReturn.push(view)); + docViews.map(view => view.props.PanelWidth() > 1 && view.rootDoc === toFind && toReturn.push(view)); + docViews.map(view => view.props.PanelWidth() <= 1 && view.rootDoc === toFind && toReturn.push(view)); + docViews.map(view => view.props.PanelWidth() > 1 && view.rootDoc !== toFind && Doc.AreProtosEqual(view.rootDoc, toFind) && toReturn.push(view)); + docViews.map(view => view.props.PanelWidth() <= 1 && view.rootDoc !== toFind && Doc.AreProtosEqual(view.rootDoc, toFind) && toReturn.push(view)); return toReturn; } @@ -151,7 +146,7 @@ export class DocumentManager { if (finalDocView) { const parent = targetDoc?.annotationOn as Doc; if (parent) finalDocView.layoutDoc.scrollToAnchorID = targetDoc?.[Id]; - Doc.linkFollowHighlight(finalDocView.props.Document); + Doc.linkFollowHighlight(finalDocView.rootDoc); } }; const docView = getFirstDocView(targetDoc, originatingDoc); @@ -159,16 +154,16 @@ export class DocumentManager { if (annotatedDoc && annotatedDoc !== originatingDoc?.context && !targetDoc?.isPushpin) { const first = getFirstDocView(annotatedDoc); if (first) { - annotatedDoc = first.props.Document; + annotatedDoc = first.rootDoc; first.focus(targetDoc, false); } } if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? const sameContext = annotatedDoc && annotatedDoc === originatingDoc?.context; if (originatingDoc?.isPushpin) { - docView.props.focus(docView.props.Document, willZoom, undefined, (didFocus: boolean) => { - if (!didFocus || docView.props.Document.hidden) { - docView.props.Document.hidden = !docView.props.Document.hidden; + docView.props.focus(docView.rootDoc, willZoom, undefined, (didFocus: boolean) => { + if (!didFocus || docView.rootDoc.hidden) { + docView.rootDoc.hidden = !docView.rootDoc.hidden; } return focusAndFinish(); }, sameContext, false);// don't want to focus the container if the source and target are in the same container, so pass 'sameContext' for dontCenter parameter @@ -176,9 +171,9 @@ export class DocumentManager { } else { docView.select(false); - docView.props.Document.hidden && (docView.props.Document.hidden = undefined); + docView.rootDoc.hidden && (docView.rootDoc.hidden = undefined); // @ts-ignore - docView.props.focus(docView.props.Document, willZoom, undefined, focusAndFinish, sameContext, false); + docView.props.focus(docView.rootDoc, willZoom, undefined, focusAndFinish, sameContext, false); } highlight(); } else { @@ -193,7 +188,7 @@ export class DocumentManager { const targetDocContextView = getFirstDocView(targetDocContext); if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. targetDocContext._viewTransition = "transform 500ms"; - targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom); + targetDocContextView.props.focus(targetDocContextView.rootDoc, willZoom); // now find the target document within the context if (targetDoc._timecodeToShow) { // if the target has a timecode, it should show up once the (presumed) video context scrubs to the display timecode; @@ -207,7 +202,7 @@ export class DocumentManager { highlight(); } else if (delay > 1500) { // we didn't find the target, so it must have moved out of the context. Go back to just creating it. - if (closeContextIfNotFound) targetDocContextView.props.removeDocument?.(targetDocContextView.props.Document); + if (closeContextIfNotFound) targetDocContextView.props.removeDocument?.(targetDocContextView.rootDoc); if (targetDoc.layout) { // there will no layout for a TEXTANCHOR type document Doc.SetInPlace(targetDoc, "annotationOn", undefined, false); createViewFunc(Doc.BrushDoc(targetDoc), finished); // create a new view of the target diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index ae5688b48..51cb9387a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -41,44 +41,41 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. if (!linkDoc.linkAutoMove) return; - const acont = A.props.Document.type === DocumentType.LINK ? A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; - const bcont = B.props.Document.type === DocumentType.LINK ? B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; - const adiv = (acont.length ? acont[0] : A.ContentDiv); - const bdiv = (bcont.length ? bcont[0] : B.ContentDiv); + const acont = A.rootDoc.type === DocumentType.LINK ? A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; + const bcont = B.rootDoc.type === DocumentType.LINK ? B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; + const adiv = acont.length ? acont[0] : A.ContentDiv; + const bdiv = bcont.length ? bcont[0] : B.ContentDiv; const a = adiv.getBoundingClientRect(); const b = bdiv.getBoundingClientRect(); const { left: aleft, top: atop, width: awidth, height: aheight } = adiv.parentElement!.getBoundingClientRect(); const { left: bleft, top: btop, width: bwidth, height: bheight } = bdiv.parentElement!.getBoundingClientRect(); const apt = Utils.closestPtBetweenRectangles(aleft, atop, awidth, aheight, bleft, btop, bwidth, bheight, a.left + a.width / 2, a.top + a.height / 2); const bpt = Utils.closestPtBetweenRectangles(bleft, btop, bwidth, bheight, aleft, atop, awidth, aheight, apt.point.x, apt.point.y); - const afield = A.props.LayoutTemplateString?.indexOf("anchor1") === -1 ? "anchor2" : "anchor1"; - const bfield = afield === "anchor1" ? "anchor2" : "anchor1"; // really hacky stuff to make the LinkAnchorBox display where we want it to: - // if there's an element in the DOM with a classname containing the link's id and a data-targetids attribute containing the other end of the link, + // if there's an element in the DOM with a classname containing a link anchor's id, // then that DOM element is a hyperlink source for the current anchor and we want to place our link box at it's top right // otherwise, we just use the computed nearest point on the document boundary to the target Document - const linkEles = Array.from(window.document.getElementsByClassName(linkDoc[Id])); - const targetAhyperlink = linkEles.find((ele: any) => ele.dataset.targetids?.includes((linkDoc[afield] as Doc)[Id])); - const targetBhyperlink = linkEles.find((ele: any) => ele.dataset.targetids?.includes((linkDoc[bfield] as Doc)[Id])); + const targetAhyperlink = Array.from(window.document.getElementsByClassName((linkDoc.anchor1 as Doc)[Id])).lastElement(); + const targetBhyperlink = Array.from(window.document.getElementsByClassName((linkDoc.anchor2 as Doc)[Id])).lastElement(); if ((!targetAhyperlink && !a.width) || (!targetBhyperlink && !b.width)) return; - if (!targetBhyperlink) { - A.rootDoc[afield + "_x"] = (apt.point.x - aleft) / awidth * 100; - A.rootDoc[afield + "_y"] = (apt.point.y - atop) / aheight * 100; + if (!targetAhyperlink) { + linkDoc.anchor1_x = (apt.point.x - aleft) / awidth * 100; + linkDoc.anchor1_y = (apt.point.y - atop) / aheight * 100; } else { - const m = targetBhyperlink.getBoundingClientRect(); + const m = targetAhyperlink.getBoundingClientRect(); const mp = A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); - A.rootDoc[afield + "_x"] = Math.min(1, mp[0] / A.props.PanelWidth()) * 100; - A.rootDoc[afield + "_y"] = Math.min(1, mp[1] / A.props.PanelHeight()) * 100; + linkDoc.anchor1_x = Math.min(1, mp[0] / A.props.PanelWidth()) * 100; + linkDoc.anchor1_y = Math.min(1, mp[1] / A.props.PanelHeight()) * 100; } - if (!targetAhyperlink) { - B.rootDoc[bfield + "_x"] = (bpt.point.x - bleft) / bwidth * 100; - B.rootDoc[bfield + "_y"] = (bpt.point.y - btop) / bheight * 100; + if (!targetBhyperlink) { + linkDoc.anchor2_x = (bpt.point.x - bleft) / bwidth * 100; + linkDoc.anchor2_y = (bpt.point.y - btop) / bheight * 100; } else { - const m = targetAhyperlink.getBoundingClientRect(); + const m = targetBhyperlink.getBoundingClientRect(); const mp = B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); - B.rootDoc[bfield + "_x"] = Math.min(1, mp[0] / B.props.PanelWidth()) * 100; - B.rootDoc[bfield + "_y"] = Math.min(1, mp[1] / B.props.PanelHeight()) * 100; + linkDoc.anchor2_x = Math.min(1, mp[0] / B.props.PanelWidth()) * 100; + linkDoc.anchor2_y = Math.min(1, mp[1] / B.props.PanelHeight()) * 100; } } @@ -162,8 +159,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo const ptlen = Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1])) / 2; const pt1norm = clipped ? [0, 0] : [pt1vec[0] / pt1len * ptlen, pt1vec[1] / pt1len * ptlen]; const pt2norm = clipped ? [0, 0] : [pt2vec[0] / pt2len * ptlen, pt2vec[1] / pt2len * ptlen]; - const aActive = A.isSelected() || Doc.IsBrushed(A.props.Document); - const bActive = B.isSelected() || Doc.IsBrushed(B.props.Document); + const aActive = A.isSelected() || Doc.IsBrushed(A.rootDoc); + const bActive = B.isSelected() || Doc.IsBrushed(B.rootDoc); const textX = (Math.min(pt1[0], pt2[0]) + Math.max(pt1[0], pt2[0])) / 2 + NumCast(LinkDocs[0].linkOffsetX); const textY = (pt1[1] + pt2[1]) / 2 + NumCast(LinkDocs[0].linkOffsetY); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 4dab8f15b..5e0b31754 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -3,32 +3,27 @@ import { observer } from "mobx-react"; import { Doc } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; import { Utils } from "../../../../Utils"; -import { DocumentType } from "../../../documents/DocumentTypes"; import { DocumentManager } from "../../../util/DocumentManager"; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); +import { DocumentType } from "../../../documents/DocumentTypes"; @observer export class CollectionFreeFormLinksView extends React.Component { @computed get uniqueConnections() { - const connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { - if (!drawnPairs.reduce((found, drawnPair) => { - const match1 = (connection.a === drawnPair.a && connection.b === drawnPair.b); - const match2 = (connection.a === drawnPair.b && connection.b === drawnPair.a); - const match = match1 || match2; - if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) { - drawnPair.l.push(connection.l); - } - return match || found; - }, false)) { - drawnPairs.push({ a: connection.a, b: connection.b, l: [connection.l] }); - } - return drawnPairs; - }, [] as { a: DocumentView, b: DocumentView, l: Doc[] }[]); - return connections.filter(c => c.a.props.Document.type === DocumentType.LINK) - .map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />); + const connections = DocumentManager.Instance.LinkedDocumentViews + .filter(c => c.a.props.Document.type === DocumentType.LINK || c.b.props.Document.type === DocumentType.LINK) + .reduce((drawnPairs, connection) => { + const matchingPairs = drawnPairs.filter(pair => connection.a === pair.a && connection.b === pair.b); + matchingPairs.forEach(drawnPair => drawnPair.l.add(connection.l)); + if (!matchingPairs.length) drawnPairs.push({ a: connection.a, b: connection.b, l: new Set<Doc>([connection.l]) }); + return drawnPairs; + }, [] as { a: DocumentView, b: DocumentView, l: Set<Doc> }[]); + const set = new Map<Doc, { a: DocumentView, b: DocumentView, l: Doc[] }>(); + connections.map(c => !set.has(Array.from(c.l)[0]) && set.set(Array.from(c.l)[0], { a: c.a, b: c.b, l: Array.from(c.l) })); + return Array.from(set.values()).map(c => <CollectionFreeFormLinkView key={c.l[0][Id]} A={c.a} B={c.b} LinkDocs={c.l} />); } render() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 463e59bd1..bfdacdb45 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -759,18 +759,19 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps if (this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return null; if (this.layoutDoc.presBox || this.rootDoc.type === DocumentType.LINK || this.props.dontRegisterView) return (null); - const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters(), []).filter(d => !d.hidden); - return filtered.map((d, i) => + // need to use allLinks for RTF since embedded linked text anchors are not rendered with DocumentViews. All other documents render their anchors with nested DocumentViews so we just need to render the directLinks here + const filtered = DocUtils.FilterDocs(this.rootDoc.type === DocumentType.RTF ? this.allLinks : this.directLinks, this.props.docFilters(), []).filter(d => !d.hidden); + return filtered.map((link, i) => <div className="documentView-anchorCont" key={i + 1}> <DocumentView {...this.props} - Document={d} + Document={link} PanelWidth={this.anchorPanelWidth} PanelHeight={this.anchorPanelHeight} dontRegisterView={false} styleProvider={this.anchorStyleProvider} removeDocument={this.hideLinkAnchor} LayoutTemplate={undefined} - LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(d, this.props.Document)}`)} /> + LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(link, this.rootDoc)}`)} /> </div >); } diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index d86dfd7b1..ca6c71ea3 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -134,7 +134,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch </div>} </div> ); - return <div className={`linkAnchorBox-cont${small ? "-small" : ""} ${this.rootDoc[Id]}`} + return <div className={`linkAnchorBox-cont${small ? "-small" : ""}`} onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)} onPointerEnter={action(e => LinkDocPreview.LinkInfo = { docprops: this.props, diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index e1ab1d3d3..56b2db48e 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -958,9 +958,10 @@ export namespace Doc { return doc; } - - export function LinkOtherAnchor(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? Cast(linkDoc.anchor2, Doc) as Doc : Cast(linkDoc.anchor1, Doc) as Doc; } - export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? "1" : "2"; } + export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) { + return Doc.AreProtosEqual(anchorDoc, (linkDoc.anchor1 as Doc).annotationOn as Doc) || + Doc.AreProtosEqual(anchorDoc, linkDoc.anchor1 as Doc) ? "1" : "2"; + } export function linkFollowUnhighlight() { Doc.UnhighlightAll(); |