diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/LinkManager.ts | 1 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.scss | 2 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenu.scss | 40 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenu.tsx | 76 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenuGroup.tsx | 10 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 112 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 10 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/LinkAnchorBox.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/LinkDocPreview.tsx | 30 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx | 10 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/RichTextMenu.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/TooltipTextMenu.scss | 2 |
17 files changed, 105 insertions, 210 deletions
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index afc0e76be..ecf245d03 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -129,7 +129,6 @@ export class LinkManager { await LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined); } public static async traverseLink(link: Opt<Doc>, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { - LinkDocPreview.TargetDoc = undefined; FormattedTextBoxComment.linkDoc = undefined; const linkDocs = link ? [link] : DocListCast(doc.links); const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1 diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 461ea0fef..de8a3c909 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -4,7 +4,7 @@ $linkGap : 3px; .documentDecorations { position: absolute; - z-index: 20000; + z-index: 2000; } .documentDecorations-container { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index bc3d05005..d53e66c47 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -625,7 +625,7 @@ export class MainView extends React.Component { {this.search} <CollectionMenu /> {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null} - {DocumentLinksButton.EditLink ? <LinkMenu docView={DocumentLinksButton.EditLink} docprops={DocumentLinksButton.EditLink.props} changeFlyout={emptyFunction} /> : (null)} + {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)} {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} docprops={LinkDocPreview.LinkInfo.docprops} linkDoc={LinkDocPreview.LinkInfo.linkDoc} linkSrc={LinkDocPreview.LinkInfo.linkSrc} href={LinkDocPreview.LinkInfo.href} /> : (null)} <GestureOverlay > diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index ebf8878cb..a90bf8b0a 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -4,29 +4,23 @@ width: auto; height: auto; position: absolute; - z-index: 20001; - - .linkMenu-list { + z-index: 2001; + .linkMenu-list, + .linkMenu-listEditor + { display: inline-block; - + position: relative; border: 1px solid black; - box-shadow: 3px 3px 1.5px grey; + background: white; + min-width: 170px; max-height: 170px; overflow-y: scroll; - position: relative; z-index: 10; - background: white; - min-width: 170px; - //border-radius: 5px; - //padding-top: 6.5px; - //padding-bottom: 6.5px; - //padding-left: 6.5px; - //padding-right: 2px; - //width: calc(auto + 50px); - + } + .linkMenu-list { white-space: nowrap; overflow-x: hidden; width: 240px; @@ -40,22 +34,6 @@ scrollbar-color: rgb(201, 239, 252); } } - - .linkMenu-listEditor { - - display: inline-block; - - border: 1px solid black; - - box-shadow: 3px 3px 1.5px grey; - - max-height: 170px; - overflow-y: scroll; - position: relative; - z-index: 10; - background: white; - min-width: 170px; - } } .linkMenu-group { diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index b32022024..8cd069210 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -13,49 +13,28 @@ import React = require("react"); interface Props { docView: DocumentView; changeFlyout: () => void; - docprops: DocumentViewSharedProps; } @observer export class LinkMenu extends React.Component<Props> { - - @observable private _editingLink?: Doc; - @observable private _linkMenuRef = React.createRef<HTMLDivElement>(); private _editorRef = React.createRef<HTMLDivElement>(); + @observable _editingLink?: Doc; + @observable _linkMenuRef = React.createRef<HTMLDivElement>(); - //@observable private _numLinks: number = 0; - - // @computed get overflow() { - // if (this._numLinks) { - // return "scroll"; - // } - // return "auto"; - // } - - @action - onClick = (e: PointerEvent) => { - - LinkDocPreview.LinkInfo = undefined; - - - if (this._linkMenuRef && !this._linkMenuRef.current?.contains(e.target as any)) { - if (this._editorRef && !this._editorRef.current?.contains(e.target as any)) { - DocumentLinksButton.EditLink = undefined; - } - } - } - @action - componentDidMount() { - this._editingLink = undefined; - document.addEventListener("pointerdown", this.onClick); + @computed get position() { + return ((dv) => ({ x: dv?.left || 0, y: dv?.top || 0, r: dv?.right || 0, b: dv?.bottom || 0 }))(this.props.docView.getBounds()); } - componentWillUnmount() { - document.removeEventListener("pointerdown", this.onClick); - } + componentDidMount() { document.addEventListener("pointerdown", this.onPointerDown); } + componentWillUnmount() { document.removeEventListener("pointerdown", this.onPointerDown); } - clearAllLinks = () => { - LinkManager.Instance.deleteAllLinksOnAnchor(this.props.docView.props.Document); + onPointerDown = (e: PointerEvent) => { + LinkDocPreview.Clear(); + if (this._linkMenuRef && this._editorRef && + !this._linkMenuRef.current?.contains(e.target as any) && + !this._editorRef.current?.contains(e.target as any)) { + DocumentLinksButton.ClearLinkEditor(); + } } renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => { @@ -66,32 +45,23 @@ export class LinkMenu extends React.Component<Props> { sourceDoc={this.props.docView.props.Document} group={group[1]} groupType={group[0]} - showEditor={action(linkDoc => this._editingLink = linkDoc)} - docprops={this.props.docprops} />); + showEditor={action(linkDoc => this._editingLink = linkDoc)} />); return linkItems.length ? linkItems : [<p key="">No links have been created yet. Drag the linking button onto another document to create a link.</p>]; } - @computed - get position() { - const docView = this.props.docView.getBounds(); - return { x: docView?.left || 0, y: docView?.top || 0, r: docView?.right || 0, b: docView?.bottom || 0 }; - } - render() { const sourceDoc = this.props.docView.props.Document; - const groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); - return <div className="linkMenu" style={{ left: this.position.x, top: this.props.docView.topMost ? undefined : this.position.b + 15, bottom: this.props.docView.topMost ? 20 : undefined }} ref={this._linkMenuRef} > - {!this._editingLink ? - <div className="linkMenu-list" > - {this.renderAllGroups(groups)} - </div> : + return <div className="linkMenu" ref={this._linkMenuRef} + style={{ left: this.position.x, top: this.props.docView.topMost ? undefined : this.position.b + 15, bottom: this.props.docView.topMost ? 20 : undefined }} + > + {this._editingLink ? <div className="linkMenu-listEditor"> - <LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink} - showLinks={action(() => this._editingLink = undefined)} /> - </div> - } - + <LinkEditor sourceDoc={sourceDoc} linkDoc={this._editingLink} showLinks={action(() => this._editingLink = undefined)} /> + </div> : + <div className="linkMenu-list" > + {this.renderAllGroups(LinkManager.Instance.getRelatedGroupedLinks(sourceDoc))} + </div>} </div>; } }
\ No newline at end of file diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 7db908393..74af78234 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -3,7 +3,7 @@ import { Doc } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { Cast } from "../../../fields/Types"; import { LinkManager } from "../../util/LinkManager"; -import { DocumentView, DocumentViewSharedProps } from "../nodes/DocumentView"; +import { DocumentView } from "../nodes/DocumentView"; import './LinkMenu.scss'; import { LinkMenuItem } from "./LinkMenuItem"; import React = require("react"); @@ -13,14 +13,11 @@ interface LinkMenuGroupProps { group: Doc[]; groupType: string; showEditor: (linkDoc: Doc) => void; - docprops: DocumentViewSharedProps; docView: DocumentView; } @observer export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { - - private _drag = React.createRef<HTMLDivElement>(); private _menuRef = React.createRef<HTMLDivElement>(); render() { @@ -31,7 +28,6 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { if (destination && this.props.sourceDoc) { return <LinkMenuItem key={linkDoc[Id]} groupType={this.props.groupType} - docprops={this.props.docprops} docView={this.props.docView} linkDoc={linkDoc} sourceDoc={this.props.sourceDoc} @@ -43,11 +39,9 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { return ( <div className="linkMenu-group" ref={this._menuRef}> - <div className="linkMenu-group-name"> - <p ref={this._drag} className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p> + <p className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p> </div> - <div className="linkMenu-group-wrapper"> {groupItems} </div> diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index e9a0486d1..e9866f6e3 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -6,7 +6,7 @@ import { observer } from "mobx-react"; import { Doc, DocListCast } from '../../../fields/Doc'; import { Cast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; -import { emptyFunction, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, setupMoveUpEvents, returnFalse } from '../../../Utils'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; @@ -18,6 +18,7 @@ import { DocumentView, DocumentViewSharedProps } from '../nodes/DocumentView'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; import './LinkMenuItem.scss'; import React = require("react"); +import { setup } from 'mocha'; interface LinkMenuItemProps { @@ -27,7 +28,6 @@ interface LinkMenuItemProps { sourceDoc: Doc; destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; - docprops: DocumentViewSharedProps; menuRef: React.Ref<HTMLDivElement>; } @@ -69,9 +69,6 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume @observer export class LinkMenuItem extends React.Component<LinkMenuItemProps> { private _drag = React.createRef<HTMLDivElement>(); - private _downX = 0; - private _downY = 0; - private _eleClone: any; _editRef = React.createRef<HTMLDivElement>(); _buttonRef = React.createRef<HTMLDivElement>(); @@ -81,84 +78,45 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { onEdit = (e: React.PointerEvent): void => { LinkManager.currentLink = this.props.linkDoc; - setupMoveUpEvents(this, e, this.editMoved, emptyFunction, () => this.props.showEditor(this.props.linkDoc)); - } - - editMoved = (e: PointerEvent) => { - const dragData = new DragManager.DocumentDragData([this.props.linkDoc]); - DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y); - return true; + setupMoveUpEvents(this, e, e => { + DragManager.StartDocumentDrag([this._editRef.current!], new DragManager.DocumentDragData([this.props.linkDoc]), e.x, e.y); + return true; + }, emptyFunction, () => this.props.showEditor(this.props.linkDoc)); } - @action onLinkButtonDown = (e: React.PointerEvent): void => { - this._downX = e.clientX; - this._downY = e.clientY; - this._eleClone = this._drag.current!.cloneNode(true); - e.stopPropagation(); - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.addEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); - document.addEventListener("pointerup", this.onLinkButtonUp); - - if (this._buttonRef && !!!this._buttonRef.current?.contains(e.target as any)) { - LinkDocPreview.LinkInfo = undefined; - } - } - - onLinkButtonUp = action((e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); - LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false); - LinkDocPreview.LinkInfo = undefined; - DocumentLinksButton.EditLink = undefined; - - e.stopPropagation(); - }); - - onLinkButtonMoved = async (e: PointerEvent) => { - if (this._drag.current !== null && Math.abs((e.clientX - this._downX) * (e.clientX - this._downX) + (e.clientY - this._downY) * (e.clientY - this._downY)) > 5) { - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); - - this._eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`; - StartLinkTargetsDrag(this._eleClone, this.props.docView, e.x, e.y, this.props.sourceDoc, [this.props.linkDoc]); - } - e.stopPropagation(); + setupMoveUpEvents(this, e, + e => { + const eleClone: any = this._drag.current!.cloneNode(true); + eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`; + StartLinkTargetsDrag(eleClone, this.props.docView, e.x, e.y, this.props.sourceDoc, [this.props.linkDoc]); + DocumentLinksButton.ClearLinkEditor(); + return true; + }, + emptyFunction, + () => { + DocumentLinksButton.ClearLinkEditor(); + LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false); + }); } - @undoBatch - @action deleteLink = (e: React.PointerEvent): void => { - this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); - LinkManager.Instance.deleteLink(this.props.linkDoc); - e.stopPropagation(); - - runInAction(() => { - LinkDocPreview.LinkInfo = undefined; - DocumentLinksButton.EditLink = undefined; - }); + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => { + this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); + LinkManager.Instance.deleteLink(this.props.linkDoc); + }))); } - @undoBatch - @action autoMove = (e: React.PointerEvent) => { - e.stopPropagation(); - this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove; + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove))); } - @undoBatch - @action showLink = (e: React.PointerEvent) => { - e.stopPropagation(); - this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay; + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay))); } - @undoBatch - @action showAnchor = (e: React.PointerEvent) => { - e.stopPropagation(); - this.props.linkDoc.hidden = !this.props.linkDoc.hidden; + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.hidden = !this.props.linkDoc.hidden))); } render() { @@ -180,13 +138,13 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { <div className={"linkMenu-item-content expand-two"}> <div ref={this._drag} className="linkMenu-name" //title="drag to view target. click to customize." - onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)} - onPointerEnter={action(e => this.props.linkDoc && (LinkDocPreview.LinkInfo = { - docprops: this.props.docprops, + onPointerLeave={LinkDocPreview.Clear} + onPointerEnter={e => this.props.linkDoc && LinkDocPreview.SetLinkInfo({ + docprops: this.props.docView.props, linkSrc: this.props.sourceDoc, linkDoc: this.props.linkDoc, Location: [e.clientX, e.clientY + 20] - }))} + })} onPointerDown={this.onLinkButtonDown}> <div className="linkMenu-text"> @@ -205,26 +163,26 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { <div className="linkMenu-item-buttons" ref={this._buttonRef} > <Tooltip title={<><div className="dash-tooltip">{this.props.linkDoc.hidden ? "Show Anchor" : "Hide Anchor"}</div></>}> - <div className="button" ref={this._editRef} onPointerDown={this.showAnchor}> + <div className="button" ref={this._editRef} onPointerDown={this.showAnchor} onClick={e => e.stopPropagation()}> <FontAwesomeIcon className="fa-icon" icon={this.props.linkDoc.hidden ? "eye-slash" : "eye"} size="sm" /></div> </Tooltip> <Tooltip title={<><div className="dash-tooltip">{!this.props.linkDoc.linkDisplay ? "Show link" : "Hide link"}</div></>}> - <div className="button" ref={this._editRef} onPointerDown={this.showLink}> + <div className="button" ref={this._editRef} onPointerDown={this.showLink} onClick={e => e.stopPropagation()}> <FontAwesomeIcon className="fa-icon" icon={!this.props.linkDoc.linkDisplay ? "eye-slash" : "eye"} size="sm" /></div> </Tooltip> <Tooltip title={<><div className="dash-tooltip">{!this.props.linkDoc.linkAutoMove ? "Auto move dot" : "Freeze dot position"}</div></>}> - <div className="button" ref={this._editRef} onPointerDown={this.autoMove}> + <div className="button" ref={this._editRef} onPointerDown={this.autoMove} onClick={e => e.stopPropagation()}> <FontAwesomeIcon className="fa-icon" icon={this.props.linkDoc.linkAutoMove ? "play" : "pause"} size="sm" /></div> </Tooltip> <Tooltip title={<><div className="dash-tooltip">Edit Link</div></>}> - <div className="button" ref={this._editRef} onPointerDown={this.onEdit}> + <div className="button" ref={this._editRef} onPointerDown={this.onEdit} onClick={e => e.stopPropagation()}> <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div> </Tooltip> <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>}> - <div className="button" onPointerDown={this.deleteLink}> + <div className="button" onPointerDown={this.deleteLink} onClick={e => e.stopPropagation()}> <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div> </Tooltip> </div> diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 692eaae66..fbe289f64 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -107,7 +107,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD //this._disposers.scrubbing = reaction(() => AudioBox._scrubTime, (time) => this.layoutDoc.playOnSelect && this.playFromTime(AudioBox._scrubTime)); this._disposers.triggerAudio = reaction( - () => !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerAudio, null) : undefined, + () => !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerAudio, null) : undefined, start => start !== undefined && setTimeout(() => { this.playFrom(start); setTimeout(() => { @@ -119,7 +119,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD ); this._disposers.audioStop = reaction( - () => this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc ? Cast(this.Document._audioStop, "number", null) : undefined, + () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? Cast(this.Document._audioStop, "number", null) : undefined, audioStop => audioStop !== undefined && setTimeout(() => { this.Pause(); setTimeout(() => this.Document._audioStop = undefined, 10); diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index defa4dbf0..13a6c9df8 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -33,16 +33,16 @@ interface DocumentLinksButtonProps { @observer export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> { private _linkButton = React.createRef<HTMLDivElement>(); - @observable public static StartLink: Doc | undefined; @observable public static StartLinkView: DocumentView | undefined; @observable public static AnnotationId: string | undefined; @observable public static AnnotationUri: string | undefined; - @observable public static EditLink: DocumentView | undefined; + @observable public static LinkEditorDocView: DocumentView | undefined; @observable public static invisibleWebDoc: Opt<Doc>; public static invisibleWebRef = React.createRef<HTMLDivElement>(); + @action public static ClearLinkEditor() { DocumentLinksButton.LinkEditorDocView = undefined; } @action @undoBatch onLinkButtonMoved = (e: PointerEvent) => { if (this.props.InMenu && this.props.StartLink) { @@ -83,7 +83,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp DocumentLinksButton.StartLinkView = this.props.View; } } else if (!this.props.InMenu) { - DocumentLinksButton.EditLink = this.props.View; + DocumentLinksButton.LinkEditorDocView = this.props.View; } })); } @@ -103,7 +103,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp //action(() => Doc.BrushDoc(this.props.View.Document)); } else if (!this.props.InMenu) { - DocumentLinksButton.EditLink = this.props.View; + DocumentLinksButton.LinkEditorDocView = this.props.View; } } @@ -264,7 +264,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp {this.linkButtonInner} </Tooltip> : - !DocumentLinksButton.EditLink && !this.props.InMenu ? + !DocumentLinksButton.LinkEditorDocView && !this.props.InMenu ? <Tooltip title={<><div className="dash-tooltip">{title}</div></>}> {this.linkButtonInner} </Tooltip> diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bfdacdb45..f56246e9a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -377,7 +377,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } focus = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => { - this._componentView?.scrollFocus?.(doc, !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc); // bcz: smooth parameter should really be passed into focus() instead of inferred here + this._componentView?.scrollFocus?.(doc, !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc); // bcz: smooth parameter should really be passed into focus() instead of inferred here return this.props.focus(doc, willZoom, scale, afterFocus, dontCenter, focused); } onClick = action((e: React.MouseEvent | React.PointerEvent) => { diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index ca6c71ea3..673c936ce 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -135,8 +135,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch </div> ); return <div className={`linkAnchorBox-cont${small ? "-small" : ""}`} - onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)} - onPointerEnter={action(e => LinkDocPreview.LinkInfo = { + onPointerLeave={LinkDocPreview.Clear} + onPointerEnter={e => LinkDocPreview.SetLinkInfo({ docprops: this.props, linkSrc: linkSource, linkDoc: this.rootDoc, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 8051568ff..4808feb47 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -22,7 +22,10 @@ interface Props { } @observer export class LinkDocPreview extends React.Component<Props> { - static TargetDoc: Doc | undefined; + @action public static Clear() { LinkDocPreview.LinkInfo = undefined; } + @action public static SetLinkInfo(info: { linkDoc?: Doc; linkSrc: Doc; href?: string; Location: number[], docprops: DocumentViewSharedProps }) { + LinkDocPreview.LinkInfo = info; + } @observable public static LinkInfo: Opt<{ linkDoc?: Doc; linkSrc: Doc; href?: string; Location: number[], docprops: DocumentViewSharedProps }>; @observable _targetDoc: Opt<Doc>; @observable _toolTipText = ""; @@ -30,28 +33,13 @@ export class LinkDocPreview extends React.Component<Props> { _editRef = React.createRef<HTMLDivElement>(); @action - onContextMenu = (e: React.MouseEvent) => { - DocumentLinksButton.EditLink = undefined; - LinkDocPreview.LinkInfo = undefined; - e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" }); - ContextMenu.Instance.displayMenu(e.clientX, e.clientY); - } - - @action.bound - async followDefault() { - DocumentLinksButton.EditLink = undefined; - LinkDocPreview.LinkInfo = undefined; - this._targetDoc && LinkManager.FollowLink(this.props.linkDoc, this._targetDoc, this.props.docprops, false); - } - componentWillUnmount() { LinkDocPreview.TargetDoc = undefined; } + componentWillUnmount() { LinkDocPreview.LinkInfo = undefined; } componentDidUpdate() { this.updatePreview(); } componentDidMount() { this.updatePreview(); } async updatePreview() { const linkDoc = this.props.linkDoc; const linkSrc = this.props.linkSrc; - LinkDocPreview.TargetDoc = undefined; if (this.props.href) { if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) { wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500)))); @@ -65,7 +53,7 @@ export class LinkDocPreview extends React.Component<Props> { const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget; runInAction(() => { this._toolTipText = ""; - LinkDocPreview.TargetDoc = this._targetDoc = target; + this._targetDoc = target; }); } } @@ -119,9 +107,11 @@ export class LinkDocPreview extends React.Component<Props> { style={{ position: "absolute", left: this.props.location[0], top: this.props.location[1], width: this.width() + 16, height: this.height() + 16, - zIndex: 1000, + zIndex: 2004, + pointerEvents: "none", backgroundColor: "lightblue", - border: "8px solid white", borderRadius: "7px", + border: "8px solid white", + borderRadius: "7px", boxShadow: "3px 3px 1.5px grey", borderBottom: "8px solid white", borderRight: "8px solid white" }}> diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 760620b19..c21701f32 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -211,7 +211,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD }, { fireImmediately: true }); this._disposers.triggerVideo = reaction( - () => !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined, + () => !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined, time => time !== undefined && setTimeout(() => { this.player && this.Play(); setTimeout(() => this.Document._triggerVideo = undefined, 10); @@ -219,7 +219,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD { fireImmediately: true } ); this._disposers.triggerStop = reaction( - () => this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc ? NumCast(this.Document._triggerVideoStop, null) : undefined, + () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? NumCast(this.Document._triggerVideoStop, null) : undefined, stop => stop !== undefined && setTimeout(() => { this.player && this.Pause(); setTimeout(() => this.Document._triggerVideoStop = undefined, 10); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 2409f36a0..0374b1426 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1215,7 +1215,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const scrollRef = self._scrollRef.current; if ((docPos.top < viewRect.top || docPos.top > viewRect.bottom) && scrollRef) { const scrollPos = scrollRef.scrollTop + (docPos.top - viewRect.top) * self.props.ScreenToLocalTransform().Scale; - if (!LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc) { + if (!LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc) { scrollPos && smoothScroll(500, scrollRef, scrollPos); } else { scrollRef.scrollTo({ top: scrollPos }); @@ -1601,7 +1601,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp eve.stopPropagation(); // drag n drop of text within text note will generate a new note if not caughst, as will dragging in from outside of Dash. } onScroll = (ev: React.UIEvent) => { - if (!LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc && this._scrollRef.current) { + if (!LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this._scrollRef.current) { this._ignoreScroll = true; this.layoutDoc._scrollTop = this._scrollRef.current.scrollTop; this._ignoreScroll = false; diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 05f0fefd8..d1bb2ad84 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -136,8 +136,6 @@ export class FormattedTextBoxComment { @undoBatch deleteLink = action(() => { FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null; - LinkDocPreview.LinkInfo = undefined; - DocumentLinksButton.EditLink = undefined; FormattedTextBoxComment.Hide(); }); @@ -158,6 +156,7 @@ export class FormattedTextBoxComment { FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = ""); } + @action static showCommentbox(set: string, view: EditorView, nbef: number) { const state = view.state; if (set !== "none") { @@ -171,6 +170,13 @@ 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); } diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index b041c4fc9..5da868281 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -851,7 +851,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { // TODO: should check for valid URL @undoBatch makeLinkToURL = (target: string, lcoation: string) => { - ((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", "", target); + ((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", target, target); } @undoBatch diff --git a/src/client/views/nodes/formattedText/TooltipTextMenu.scss b/src/client/views/nodes/formattedText/TooltipTextMenu.scss index e2149e9c1..0e4b752ac 100644 --- a/src/client/views/nodes/formattedText/TooltipTextMenu.scss +++ b/src/client/views/nodes/formattedText/TooltipTextMenu.scss @@ -103,7 +103,7 @@ } .tooltipMenu, .basic-tools { - z-index: 20000; + z-index: 3000; pointer-events: all; padding: 3px; padding-bottom: 5px; |