diff options
Diffstat (limited to 'src/client/views/nodes/LinkDocPreview.tsx')
-rw-r--r-- | src/client/views/nodes/LinkDocPreview.tsx | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index b2fdd93fc..1eab06381 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -4,7 +4,7 @@ import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import wiki from 'wikijs'; import { Doc, DocCastAsync, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; -import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs, DocUtils } from '../../documents/Documents'; @@ -17,7 +17,8 @@ import { Transform } from '../../util/Transform'; import { DocumentView, DocumentViewSharedProps, OpenWhere } from './DocumentView'; import './LinkDocPreview.scss'; import React = require('react'); -import { SelectionManager } from '../../util/SelectionManager'; +import { SearchUtil } from '../../util/SearchUtil'; +import { SearchBox } from '../search/SearchBox'; interface LinkDocPreviewProps { linkDoc?: Doc; @@ -37,6 +38,8 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { LinkDocPreview.LinkInfo !== info && (LinkDocPreview.LinkInfo = info); } + static _instance: Opt<LinkDocPreview>; + _infoRef = React.createRef<HTMLDivElement>(); _linkDocRef = React.createRef<HTMLDivElement>(); @observable public static LinkInfo: Opt<LinkDocPreviewProps>; @@ -47,6 +50,11 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { @observable _toolTipText = ''; @observable _hrefInd = 0; + constructor(props: any) { + super(props); + LinkDocPreview._instance = this; + } + @action init() { var linkTarget = this.props.linkDoc; this._linkSrc = this.props.linkSrc; @@ -63,6 +71,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { this._markerTargetDoc = this._targetDoc = linkTarget; } this._toolTipText = ''; + this.updateHref(); } componentDidUpdate(props: any) { if (props.linkSrc !== this.props.linkSrc || props.linkDoc !== this.props.linkDoc || props.hrefs !== this.props.hrefs) this.init(); @@ -72,6 +81,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { document.addEventListener('pointerdown', this.onPointerDown, true); } + @action componentWillUnmount() { LinkDocPreview.SetLinkInfo(undefined); document.removeEventListener('pointerdown', this.onPointerDown, true); @@ -81,7 +91,8 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { !this._linkDocRef.current?.contains(e.target as any) && LinkDocPreview.Clear(); // close preview when not clicking anywhere other than the info bar of the preview }; - @computed get href() { + @action + updateHref() { if (this.props.hrefs?.length) { const href = this.props.hrefs[this._hrefInd]; if (href.indexOf(Doc.localServerPath()) !== 0) { @@ -91,33 +102,33 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { .page(href.replace('https://en.wikipedia.org/wiki/', '')) .then(page => page.summary().then(action(summary => (this._toolTipText = summary.substring(0, 500))))); } else { - setTimeout(action(() => (this._toolTipText = 'url => ' + href))); + this._toolTipText = 'url => ' + href; } } else { // hyperlink to a document .. decode doc id and retrieve from the server. this will trigger vals() being invalidated - const anchorDoc = href.replace(Doc.localServerPath(), '').split('?')[0]; - anchorDoc && - DocServer.GetRefField(anchorDoc).then( - action(anchor => { - if (anchor instanceof Doc && DocListCast(anchor.links).length) { - this._linkDoc = this._linkDoc ?? DocListCast(anchor.links)[0]; - const automaticLink = this._linkDoc.linkRelationship === LinkManager.AutoKeywords; - if (automaticLink) { - // automatic links specify the target in the link info, not the source - const linkTarget = anchor; - this._linkSrc = LinkManager.getOppositeAnchor(this._linkDoc, linkTarget); - this._markerTargetDoc = this._targetDoc = linkTarget; - } else { - this._linkSrc = anchor; - const linkTarget = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); - this._markerTargetDoc = linkTarget; - this._targetDoc = /*linkTarget?.type === DocumentType.MARKER &&*/ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget; - } - this._toolTipText = ''; - if (LinkDocPreview.LinkInfo?.noPreview) this.followLink(); + const anchorDocId = href.replace(Doc.localServerPath(), '').split('?')[0]; + const anchorDoc = anchorDocId ? PromiseValue(DocCast(DocServer.GetCachedRefField(anchorDocId) ?? DocServer.GetRefField(anchorDocId))) : undefined; + anchorDoc?.then?.( + action(anchor => { + if (anchor instanceof Doc && DocListCast(anchor.links).length) { + this._linkDoc = this._linkDoc ?? DocListCast(anchor.links)[0]; + const automaticLink = this._linkDoc.linkRelationship === LinkManager.AutoKeywords; + if (automaticLink) { + // automatic links specify the target in the link info, not the source + const linkTarget = anchor; + this._linkSrc = LinkManager.getOppositeAnchor(this._linkDoc, linkTarget); + this._markerTargetDoc = this._targetDoc = linkTarget; + } else { + this._linkSrc = anchor; + const linkTarget = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); + this._markerTargetDoc = linkTarget; + this._targetDoc = /*linkTarget?.type === DocumentType.MARKER &&*/ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget; } - }) - ); + this._toolTipText = 'link to ' + this._targetDoc?.title; + if (LinkDocPreview.LinkInfo?.noPreview || this._linkSrc?.followLinkToggle || this._markerTargetDoc?.type === DocumentType.PRES) this.followLink(); + } + }) + ); } return href; } @@ -159,11 +170,14 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { }; followLink = () => { + LinkDocPreview.Clear(); if (this._linkDoc && this._linkSrc) { - LinkDocPreview.Clear(); LinkFollower.FollowLink(this._linkDoc, this._linkSrc, this.props.docProps, false); } else if (this.props.hrefs?.length) { - this.props.docProps?.addDocTab(Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, useCors: true }), OpenWhere.addRight); + const webDoc = + Array.from(SearchBox.staticSearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ?? + Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, useCors: true }); + this.props.docProps?.addDocTab(webDoc, OpenWhere.lightbox); } }; @@ -209,7 +223,6 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { } @computed get docPreview() { - const href = this.href; // needs to be here to trigger lookup of web pages and docs on server return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? null : ( <div className="linkDocPreview-inner"> {!this.props.showHeader ? null : this.previewHeader} @@ -286,7 +299,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { className="linkDocPreview" ref={this._linkDocRef} onPointerDown={this.followLinkPointerDown} - style={{ left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> + style={{ display: !this._toolTipText ? 'none' : undefined, left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> {this.docPreview} </div> ); |