From 5ed063e0e39cc1dbdffc21b162d1acff0db65ba1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 2 Oct 2020 21:35:45 -0400 Subject: cleaned up CollectionLinkView and fixed an issue with link lines flopping around --- .../CollectionFreeFormLinkView.tsx | 145 +++++++++------------ 1 file changed, 64 insertions(+), 81 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 9dcfde7f9..3e9c0b485 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -22,74 +22,63 @@ export class CollectionFreeFormLinkView extends React.Component (Date.now() < this._start++ + 1000) && (this._timeout = setTimeout(this.timeout, 25))); + componentWillUnmount() { this._anchorDisposer?.(); } + @action timeout = action(() => (Date.now() < this._start++ + 1000) && (this._timeout = setTimeout(this.timeout, 25))); componentDidMount() { - this._anchorDisposer = reaction(() => [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform(), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document)], + this._anchorDisposer = reaction(() => [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform()], action(() => { this._start = Date.now(); this._timeout && clearTimeout(this._timeout); this._timeout = setTimeout(this.timeout, 25); - if (SnappingManager.GetIsDragging() || !this.props.A.ContentDiv || !this.props.B.ContentDiv) return; - 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(() => (!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. - const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; - const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; - const adiv = (acont.length ? acont[0] : this.props.A.ContentDiv); - const bdiv = (bcont.length ? bcont[0] : this.props.B.ContentDiv); - const a = adiv.getBoundingClientRect(); - const b = bdiv.getBoundingClientRect(); - const abounds = adiv.parentElement!.getBoundingClientRect(); - const bbounds = bdiv.parentElement!.getBoundingClientRect(); - const apt = Utils.closestPtBetweenRectangles(abounds.left, abounds.top, abounds.width, abounds.height, - bbounds.left, bbounds.top, bbounds.width, bbounds.height, - a.left + a.width / 2, a.top + a.height / 2); - const bpt = Utils.closestPtBetweenRectangles(bbounds.left, bbounds.top, bbounds.width, bbounds.height, - abounds.left, abounds.top, abounds.width, abounds.height, - apt.point.x, apt.point.y); - const afield = this.props.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, - // 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 linkId = this.props.LinkDocs[0][Id]; // this link's Id - const AanchorId = (this.props.LinkDocs[0][afield] as Doc)[Id]; // anchor a's id - const BanchorId = (this.props.LinkDocs[0][bfield] as Doc)[Id]; // anchor b's id - const linkEles = Array.from(window.document.getElementsByClassName(linkId)); - const targetAhyperlink = linkEles.find((ele: any) => ele.dataset.targetids?.includes(AanchorId)); - const targetBhyperlink = linkEles.find((ele: any) => ele.dataset.targetids?.includes(BanchorId)); - if (!targetBhyperlink) { - this.props.A.rootDoc[afield + "_x"] = (apt.point.x - abounds.left) / abounds.width * 100; - this.props.A.rootDoc[afield + "_y"] = (apt.point.y - abounds.top) / abounds.height * 100; - } else { - setTimeout(() => { - (this.props.A.rootDoc[(this.props.A.props as any).fieldKey] as Doc); - const m = targetBhyperlink.getBoundingClientRect(); - const mp = this.props.A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); - this.props.A.rootDoc[afield + "_x"] = Math.min(1, mp[0] / this.props.A.props.PanelWidth()) * 100; - this.props.A.rootDoc[afield + "_y"] = Math.min(1, mp[1] / this.props.A.props.PanelHeight()) * 100; - }, 0); - } - if (!targetAhyperlink) { - this.props.A.rootDoc[bfield + "_x"] = (bpt.point.x - bbounds.left) / bbounds.width * 100; - this.props.A.rootDoc[bfield + "_y"] = (bpt.point.y - bbounds.top) / bbounds.height * 100; - } else { - setTimeout(() => { - (this.props.B.rootDoc[(this.props.B.props as any).fieldKey] as Doc); - const m = targetAhyperlink.getBoundingClientRect(); - const mp = this.props.B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); - this.props.B.rootDoc[bfield + "_x"] = Math.min(1, mp[0] / this.props.B.props.PanelWidth()) * 100; - this.props.B.rootDoc[bfield + "_y"] = Math.min(1, mp[1] / this.props.B.props.PanelHeight()) * 100; - }, 0); - } + setTimeout(this.placeAnchors); }) , { fireImmediately: true }); } + placeAnchors = () => { + const { A, B, LinkDocs } = this.props; + const linkDoc = LinkDocs[0]; + if (SnappingManager.GetIsDragging() || !A.ContentDiv || !B.ContentDiv) return; + 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. + 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 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, + // 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])); + if (!targetBhyperlink) { + A.rootDoc[afield + "_x"] = (apt.point.x - aleft) / awidth * 100; + A.rootDoc[afield + "_y"] = (apt.point.y - atop) / aheight * 100; + } else { + const m = targetBhyperlink.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; + } + if (!targetAhyperlink) { + B.rootDoc[bfield + "_x"] = (bpt.point.x - bleft) / bwidth * 100; + B.rootDoc[bfield + "_y"] = (bpt.point.y - btop) / bheight * 100; + } else { + const m = targetAhyperlink.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; + } + } pointerDown = (e: React.PointerEvent) => { @@ -138,14 +127,12 @@ export class CollectionFreeFormLinkView extends React.Component Date: Fri, 2 Oct 2020 21:40:38 -0400 Subject: from last --- .../views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 3e9c0b485..f051d5f8d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -102,7 +102,7 @@ export class CollectionFreeFormLinkView extends React.Component Date: Sun, 11 Oct 2020 01:33:28 -0400 Subject: prevented documents that are unshared (ie private to soeone else) from showing up as an empty key value in stacking and other views. tried to fix an exception when showing links (that wasn't repeatable, so dion't know if fix works). --- src/client/views/collections/CollectionSubView.tsx | 2 +- .../CollectionFreeFormLinkView.tsx | 28 ++++++++++++---------- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index fa80c8062..493018093 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -134,7 +134,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: rawdocs = rootDoc && !this.props.annotationsKey ? [Doc.GetProto(rootDoc)] : []; } - const docs = rawdocs.filter(d => !(d instanceof Promise)).map(d => d as Doc); + const docs = rawdocs.filter(d => !(d instanceof Promise) && Object.keys(d).length).map(d => d as Doc); const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField); const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index f051d5f8d..4cf257640 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -100,13 +100,15 @@ export class CollectionFreeFormLinkView extends React.Component width !== undefined && setTimeout(() => this.tryUpdateHeight(), 0) ); this._disposers.height = reaction( - () => NumCast(this.layoutDoc._height), + () => Cast(this.layoutDoc._height, "number", null), action(height => { if (height !== undefined && height <= 20 && height < NumCast(this.layoutDoc._delayAutoHeight, 20)) { this.layoutDoc._delayAutoHeight = height; -- cgit v1.2.3-70-g09d2