From 09e6a1f83de643437d03deac57e1cdebc68d6140 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 4 Feb 2021 16:18:35 -0500 Subject: fixed marquee annotations for web/pdf when scrolled --- src/client/views/nodes/VideoBox.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/nodes/VideoBox.tsx') diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 8a1cefbd9..760620b19 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -574,6 +574,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent Date: Tue, 9 Feb 2021 12:16:25 -0500 Subject: started to cleanup LinkDocPreview, LinkMenu. --- src/client/util/LinkManager.ts | 1 - src/client/views/DocumentDecorations.scss | 2 +- src/client/views/MainView.tsx | 2 +- src/client/views/linking/LinkMenu.scss | 40 ++------ src/client/views/linking/LinkMenu.tsx | 76 +++++--------- src/client/views/linking/LinkMenuGroup.tsx | 10 +- src/client/views/linking/LinkMenuItem.tsx | 112 +++++++-------------- src/client/views/nodes/AudioBox.tsx | 4 +- src/client/views/nodes/DocumentLinksButton.tsx | 10 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 4 +- src/client/views/nodes/LinkDocPreview.tsx | 30 ++---- src/client/views/nodes/VideoBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- .../formattedText/FormattedTextBoxComment.tsx | 10 +- .../views/nodes/formattedText/RichTextMenu.tsx | 2 +- .../views/nodes/formattedText/TooltipTextMenu.scss | 2 +- 17 files changed, 105 insertions(+), 210 deletions(-) (limited to 'src/client/views/nodes/VideoBox.tsx') 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, 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} {LinkDescriptionPopup.descriptionPopup ? : null} - {DocumentLinksButton.EditLink ? : (null)} + {DocumentLinksButton.LinkEditorDocView ? : (null)} {LinkDocPreview.LinkInfo ? : (null)} 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 { - - @observable private _editingLink?: Doc; - @observable private _linkMenuRef = React.createRef(); private _editorRef = React.createRef(); + @observable _editingLink?: Doc; + @observable _linkMenuRef = React.createRef(); - //@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>): Array => { @@ -66,32 +45,23 @@ export class LinkMenu extends React.Component { 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 : [

No links have been created yet. Drag the linking button onto another document to create a link.

]; } - @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 = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); - return
- {!this._editingLink ? -
- {this.renderAllGroups(groups)} -
: + return
+ {this._editingLink ?
- this._editingLink = undefined)} /> -
- } - + this._editingLink = undefined)} /> +
: +
+ {this.renderAllGroups(LinkManager.Instance.getRelatedGroupedLinks(sourceDoc))} +
}
; } } \ 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 { - - private _drag = React.createRef(); private _menuRef = React.createRef(); render() { @@ -31,7 +28,6 @@ export class LinkMenuGroup extends React.Component { if (destination && this.props.sourceDoc) { return { return (
-
-

{this.props.groupType}:

+

{this.props.groupType}:

-
{groupItems}
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; } @@ -69,9 +69,6 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume @observer export class LinkMenuItem extends React.Component { private _drag = React.createRef(); - private _downX = 0; - private _downY = 0; - private _eleClone: any; _editRef = React.createRef(); _buttonRef = React.createRef(); @@ -81,84 +78,45 @@ export class LinkMenuItem extends React.Component { 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 {
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}>
@@ -205,26 +163,26 @@ export class LinkMenuItem extends React.Component {
{this.props.linkDoc.hidden ? "Show Anchor" : "Hide Anchor"}
}> -
+
e.stopPropagation()}>
{!this.props.linkDoc.linkDisplay ? "Show link" : "Hide link"}
}> -
+
e.stopPropagation()}>
{!this.props.linkDoc.linkAutoMove ? "Auto move dot" : "Freeze dot position"}
}> -
+
e.stopPropagation()}>
Edit Link
}> -
+
e.stopPropagation()}>
Delete Link
}> -
+
e.stopPropagation()}>
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 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 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 { private _linkButton = React.createRef(); - @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; public static invisibleWebRef = React.createRef(); + @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 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 : - !DocumentLinksButton.EditLink && !this.props.InMenu ? + !DocumentLinksButton.LinkEditorDocView && !this.props.InMenu ?
{title}
}> {this.linkButtonInner}
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 { - 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 ); return
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 { - 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; @observable _toolTipText = ""; @@ -30,28 +33,13 @@ export class LinkDocPreview extends React.Component { _editRef = React.createRef(); @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 { 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 { 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 !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 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 { // 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; -- cgit v1.2.3-70-g09d2 From 5fd9ffcc2bb62faa664f33a817ae1fd51c36ef98 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 9 Feb 2021 19:11:28 -0500 Subject: overhaul of linkdocpreview. delegated linkpreviewing from formattedTextBoxComments to LinkDocPreview --- src/client/util/LinkManager.ts | 1 - src/client/views/MainView.tsx | 3 +- src/client/views/linking/LinkMenu.tsx | 3 +- src/client/views/linking/LinkMenuItem.tsx | 3 +- src/client/views/nodes/AudioBox.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 3 +- src/client/views/nodes/LinkDocPreview.scss | 69 ++++++ src/client/views/nodes/LinkDocPreview.tsx | 232 ++++++++++++------- src/client/views/nodes/VideoBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 13 +- .../formattedText/FormattedTextBoxComment.scss | 76 +----- .../formattedText/FormattedTextBoxComment.tsx | 255 ++++----------------- 13 files changed, 283 insertions(+), 385 deletions(-) create mode 100644 src/client/views/nodes/LinkDocPreview.scss (limited to 'src/client/views/nodes/VideoBox.tsx') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index ecf245d03..c32a78ef3 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, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { - 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 const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2 diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d53e66c47..d09b0269f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -626,8 +626,7 @@ export class MainView extends React.Component { {LinkDescriptionPopup.descriptionPopup ? : null} {DocumentLinksButton.LinkEditorDocView ? : (null)} - {LinkDocPreview.LinkInfo ? : (null)} + {LinkDocPreview.LinkInfo ? : (null)} {this.mainContent} diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 8cd069210..c7888c5ee 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -30,8 +30,7 @@ export class LinkMenu extends React.Component { onPointerDown = (e: PointerEvent) => { LinkDocPreview.Clear(); - if (this._linkMenuRef && this._editorRef && - !this._linkMenuRef.current?.contains(e.target as any) && + if (!this._linkMenuRef.current?.contains(e.target as any) && !this._editorRef.current?.contains(e.target as any)) { DocumentLinksButton.ClearLinkEditor(); } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index e9866f6e3..2bc2bc6a4 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -143,7 +143,8 @@ export class LinkMenuItem extends React.Component { docprops: this.props.docView.props, linkSrc: this.props.sourceDoc, linkDoc: this.props.linkDoc, - Location: [e.clientX, e.clientY + 20] + showHeader: false, + location: [e.clientX, e.clientY + 20] })} onPointerDown={this.onLinkButtonDown}> diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index fbe289f64..e24a671d0 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -107,7 +107,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent AudioBox._scrubTime, (time) => this.layoutDoc.playOnSelect && this.playFromTime(AudioBox._scrubTime)); this._disposers.triggerAudio = reaction( - () => !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerAudio, null) : undefined, + () => !LinkDocPreview.LinkInfo && 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 this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? Cast(this.Document._audioStop, "number", null) : undefined, + () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo ? 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/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f56246e9a..8afa53eac 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -377,7 +377,7 @@ export class DocumentViewInternal extends DocComponent { - this._componentView?.scrollFocus?.(doc, !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc); // bcz: smooth parameter should really be passed into focus() instead of inferred here + this._componentView?.scrollFocus?.(doc, !LinkDocPreview.LinkInfo); // 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 673c936ce..7a4209563 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -140,7 +140,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent { +export class LinkDocPreview extends React.Component { @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 }>; + @action public static SetLinkInfo(info?: LinkDocPreviewProps) { LinkDocPreview.LinkInfo != info && (LinkDocPreview.LinkInfo = info); } + + _infoRef = React.createRef(); + @observable public static LinkInfo: Opt; @observable _targetDoc: Opt; + @observable _linkDoc: Opt; + @observable _linkSrc: Opt; @observable _toolTipText = ""; - _linkTarget: Opt; - _editRef = React.createRef(); + @observable _hrefInd = 0; + @observable _linkTarget: Opt; - @action - componentWillUnmount() { LinkDocPreview.LinkInfo = undefined; } + @action componentDidUpdate(props: any) { + if (props.linkSrc !== this.props.linkSrc || + props.linkDoc !== this.props.linkDoc || + props.hrefs !== this.props.hrefs) { + this._linkTarget = this.props.linkDoc; + this._linkSrc = this.props.linkSrc; + this._linkDoc = this.props.linkDoc; + this._toolTipText = ""; + this.updatePreview(); + } + } + @action componentDidMount() { + this._linkTarget = this.props.linkDoc; + this._linkSrc = this.props.linkSrc; + this._linkDoc = this.props.linkDoc; + this._toolTipText = ""; + this.updatePreview(); + document.addEventListener("pointerdown", this.onPointerDown); + } + + componentWillUnmount() { + LinkDocPreview.SetLinkInfo(undefined); + document.removeEventListener("pointerdown", this.onPointerDown); + } + + onPointerDown = (e: PointerEvent) => { + !this._infoRef.current?.contains(e.target as any) && LinkDocPreview.Clear(); + } - componentDidUpdate() { this.updatePreview(); } - componentDidMount() { this.updatePreview(); } - async updatePreview() { + updatePreview() { const linkDoc = this.props.linkDoc; const linkSrc = this.props.linkSrc; - 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)))); + if (this.props.hrefs?.length) { + const href = this.props.hrefs[this._hrefInd]; + if (href.indexOf(Utils.prepend("/doc/")) !== 0) { + if (href.startsWith("https://en.wikipedia.org/wiki/")) { + wiki().page(href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500)))); + } else { + runInAction(() => this._toolTipText = "external => " + href); + } } else { - runInAction(() => this._toolTipText = "external => " + this.props.href); + const anchorDoc = href.replace(Utils.prepend("/doc/"), "").split("?")[0]; + anchorDoc && DocServer.GetRefField(anchorDoc).then(action(async anchor => { + if (anchor instanceof Doc) { + this._linkDoc = DocListCast(anchor.links)[0]; + this._linkSrc = anchor; + const targetanchor = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); + runInAction(async () => { + this._linkTarget = targetanchor; + const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget; + this._toolTipText = ""; + runInAction(() => this._targetDoc = target); + }); + } + })); } - } else if (linkDoc && linkSrc) { + } else if (linkDoc) { const anchor1 = linkDoc.anchor1 as Doc; const anchor2 = linkDoc.anchor2 as Doc; - this._linkTarget = Doc.AreProtosEqual(anchor1, linkSrc) || Doc.AreProtosEqual(anchor1.annotationOn as Doc, linkSrc) ? anchor2 : anchor1; - const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget; - runInAction(() => { + runInAction(async () => { + this._linkTarget = Doc.AreProtosEqual(anchor1, linkSrc) || Doc.AreProtosEqual(anchor1.annotationOn as Doc, linkSrc) ? anchor2 : anchor1; + const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget; this._toolTipText = ""; - this._targetDoc = target; + runInAction(() => this._targetDoc = target); }); } } - pointerDown = (e: React.PointerEvent) => { - if (this.props.linkDoc && this.props.linkSrc) { - LinkManager.FollowLink(this.props.linkDoc, this.props.linkSrc, this.props.docprops, false); + deleteLink = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => this._linkDoc ? LinkManager.Instance.deleteLink(this._linkDoc) : null)); + } + nextHref = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => { + this._hrefInd = (this._hrefInd + 1) % (this.props.hrefs?.length || 1); + this.updatePreview(); + })); + } + + followLink = (e: React.PointerEvent) => { + if (this._linkDoc && this._linkSrc) { + LinkManager.FollowLink(this._linkDoc, this._linkSrc, this.props.docprops, false); } else if (this.props.href) { this.props.docprops?.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, useCors: true }), "add:right"); } } width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225)); height = () => Math.min(225, NumCast(this._targetDoc?.[HeightSym](), 225)); - @computed get targetDocView() { - return !this._targetDoc ? -
-
- {this._toolTipText} + @computed get previewHeader() { + return !this._linkDoc || !this._targetDoc || !this._linkSrc ? (null) : +
+
+ {StrCast(this._targetDoc.title).length > 16 ? StrCast(this._targetDoc.title).substr(0, 16) + "..." : this._targetDoc.title} +

{StrCast(this._linkDoc.description)}

+
+
+ {(this.props.hrefs?.length || 0) <= 1 ? (null) : + Next Link
} placement="top"> +
+ +
+ } + + Delete Link
} placement="top"> +
+ +
+ +
+
; + } + + @computed get docPreview() { + return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? (null) : +
+ {!this.props.showHeader ? (null) : this.previewHeader} +
+ {this._toolTipText ? this._toolTipText : + { + const targetanchor = LinkManager.getOppositeAnchor(this._linkDoc!, this._linkSrc!); + targetanchor && this._targetDoc !== targetanchor && r?.focus(targetanchor); + }} + Document={this._targetDoc} + moveDocument={returnFalse} + rootSelected={returnFalse} + styleProvider={this.props.docprops?.styleProvider} + layerProvider={this.props.docprops?.layerProvider} + docViewPath={emptyPath} + ScreenToLocalTransform={Transform.Identity} + parentActive={returnFalse} + addDocument={returnFalse} + removeDocument={returnFalse} + addDocTab={returnFalse} + pinToPres={returnFalse} + dontRegisterView={true} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + ContainingCollectionDoc={undefined} + ContainingCollectionView={undefined} + renderDepth={-1} + PanelWidth={this.width} + PanelHeight={this.height} + focus={emptyFunction} + whenActiveChanged={returnFalse} + bringToFront={returnFalse} + NativeWidth={Doc.NativeWidth(this._targetDoc) ? () => Doc.NativeWidth(this._targetDoc) : undefined} + NativeHeight={Doc.NativeHeight(this._targetDoc) ? () => Doc.NativeHeight(this._targetDoc) : undefined} + />}
-
- : - this._linkTarget !== this._targetDoc && this._linkTarget && r?.focus(this._linkTarget)} - Document={this._targetDoc} - moveDocument={returnFalse} - rootSelected={returnFalse} - ScreenToLocalTransform={Transform.Identity} - parentActive={returnFalse} - addDocument={returnFalse} - removeDocument={returnFalse} - addDocTab={returnFalse} - pinToPres={returnFalse} - dontRegisterView={true} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={undefined} - ContainingCollectionView={undefined} - renderDepth={-1} - PanelWidth={this.width} - PanelHeight={this.height} - focus={emptyFunction} - whenActiveChanged={returnFalse} - bringToFront={returnFalse} - styleProvider={this.props.docprops?.styleProvider} - layerProvider={this.props.docprops?.layerProvider} - docViewPath={emptyPath} - />; +
; } render() { - return
- {this.targetDocView} + return
+ {this.docPreview}
; } } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index c21701f32..324861573 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -211,7 +211,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined, + () => !LinkDocPreview.LinkInfo && 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 this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo && !FormattedTextBoxComment.linkDoc ? NumCast(this.Document._triggerVideoStop, null) : undefined, + () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo ? 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 0374b1426..bf868634b 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.LinkInfo && !FormattedTextBoxComment.linkDoc) { + if (!LinkDocPreview.LinkInfo) { scrollPos && smoothScroll(500, scrollRef, scrollPos); } else { scrollRef.scrollTo({ top: scrollPos }); @@ -1338,7 +1338,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp onPointerUp = (e: React.PointerEvent): void => { if (!this._downEvent) return; this._downEvent = false; - if (!(e.nativeEvent as any).formattedHandled) { + if (!(e.nativeEvent as any).formattedHandled && this.active(true)) { const editor = this._editorView!; FormattedTextBoxComment.textBox = this; const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY }); @@ -1366,13 +1366,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp e.preventDefault(); } FormattedTextBoxComment.Hide(); - if (FormattedTextBoxComment.linkDoc) { - if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) { - this.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "add" : "add:right"); - } else { - LinkManager.FollowLink(FormattedTextBoxComment.linkDoc, this.props.Document, this.props, false); - } - } (e.nativeEvent as any).formattedHandled = true; @@ -1601,7 +1594,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.LinkInfo && !FormattedTextBoxComment.linkDoc && this._scrollRef.current) { + if (!LinkDocPreview.LinkInfo && 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.scss b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss index 81afba4d7..3251319b9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss @@ -1,6 +1,8 @@ .FormattedTextBox-tooltip { position: absolute; - pointer-events: none; + pointer-events: all; + height: 100%; + overflow: hidden; z-index: 20; background: white; border: 1px solid silver; @@ -9,67 +11,9 @@ -webkit-transform: translateX(-50%); transform: translateX(-50%); box-shadow: 3px 3px 1.5px grey; - - .FormattedTextBoxComment { - background-color: white; - border: 8px solid white; - //width: 200px; - - //display: flex; - .FormattedTextBoxComment-info { - - margin-bottom: 37px; - - .FormattedTextBoxComment-title { - padding-right: 4px; - float: left; - - .FormattedTextBoxComment-description { - text-decoration: none; - font-style: italic; - color: rgb(95, 97, 102); - font-size: 10px; - } - } - - .FormattedTextBoxComment-button { - display: inline; - padding-left: 6px; - padding-right: 6px; - padding-top: 2.5px; - padding-bottom: 2.5px; - width: 17px; - height: 17px; - margin: 0; - margin-right: 3px; - border-radius: 50%; - pointer-events: auto; - background-color: rgb(0, 0, 0); - color: rgb(255, 255, 255); - transition: transform 0.2s; - text-align: center; - position: relative; - font-size: 12px; - - &:hover { - background-color: rgb(77, 77, 77); - cursor: pointer; - } - } - } - - .FormattedTextBoxComment-preview-wrapper { - //width: 170px; - height: 170px; - overflow: hidden; - //padding-top: 5px; - margin-top: 10px; - margin-bottom: 8px; - align-content: center; - justify-content: center; - background-color: rgb(160, 160, 160); - } - } + max-width: 400; + max-height: 235; + height:max-content; } .FormattedTextBox-tooltip:before { @@ -96,12 +40,4 @@ border: 5px solid transparent; border-bottom-width: 0; border-top-color: white; -} - -.FormattedTextBoxComment-buttons { - display: none; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); } \ No newline at end of file diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index d1bb2ad84..827bb2591 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -1,28 +1,17 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Tooltip } from "@material-ui/core"; import { action, observable } from "mobx"; import { Mark, ResolvedPos } from "prosemirror-model"; import { EditorState, Plugin } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import * as ReactDOM from 'react-dom'; -import wiki from "wikijs"; -import { Doc, DocCastAsync, DocListCast, Opt } from "../../../../fields/Doc"; -import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types"; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, Utils, emptyPath } from "../../../../Utils"; +import { Doc, DocListCast, Opt } from "../../../../fields/Doc"; +import { Utils } from "../../../../Utils"; import { DocServer } from "../../../DocServer"; import { Docs } from "../../../documents/Documents"; -import { DocumentType } from "../../../documents/DocumentTypes"; -import { LinkManager } from "../../../util/LinkManager"; -import { Transform } from "../../../util/Transform"; -import { undoBatch } from "../../../util/UndoManager"; -import { DocumentLinksButton } from "../DocumentLinksButton"; -import { DocumentView } from "../DocumentView"; import { LinkDocPreview } from "../LinkDocPreview"; import { FormattedTextBox } from "./FormattedTextBox"; import './FormattedTextBoxComment.scss'; import { schema } from "./schema_rts"; import React = require("react"); -import { DefaultStyleProvider } from "../../StyleProvider"; export let formattedTextBoxCommentPlugin = new Plugin({ view(editorView) { return new FormattedTextBoxComment(editorView); } @@ -64,67 +53,24 @@ export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (mark export class FormattedTextBoxComment { static tooltip: HTMLElement; static tooltipText: HTMLElement; - static tooltipInput: HTMLInputElement; static start: number; static end: number; static mark: Mark; static textBox: FormattedTextBox | undefined; - static linkDoc: Doc | undefined; - - static _deleteRef: Opt; - static _followRef: Opt; - static _nextRef: Opt; - - static _lastState?: EditorState; - static _lastView?: EditorView; - - @observable static _hrefInd = 0; - static _hrefs: string[] | undefined = []; constructor(view: any) { if (!FormattedTextBoxComment.tooltip) { const root = document.getElementById("root"); - FormattedTextBoxComment.tooltipInput = document.createElement("input"); - FormattedTextBoxComment.tooltipInput.type = "checkbox"; FormattedTextBoxComment.tooltip = document.createElement("div"); FormattedTextBoxComment.tooltipText = document.createElement("div"); - //FormattedTextBoxComment.tooltipText.style.width = "100%"; - FormattedTextBoxComment.tooltipText.style.height = "100%"; + FormattedTextBoxComment.tooltipText.style.height = "max-content"; FormattedTextBoxComment.tooltipText.style.textOverflow = "ellipsis"; FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText); FormattedTextBoxComment.tooltip.className = "FormattedTextBox-tooltip"; - FormattedTextBoxComment.tooltip.style.pointerEvents = "all"; - FormattedTextBoxComment.tooltip.style.maxWidth = "400px"; - FormattedTextBoxComment.tooltip.style.maxHeight = "235px"; - //FormattedTextBoxComment.tooltip.style.width = "100%"; - FormattedTextBoxComment.tooltip.style.height = "100%"; - FormattedTextBoxComment.tooltip.style.overflow = "hidden"; FormattedTextBoxComment.tooltip.style.display = "none"; - // FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipInput); - FormattedTextBoxComment.tooltip.onpointerdown = async (e: PointerEvent) => { - const keep = e.target && (e.target as any).type === "checkbox" ? true : false; + FormattedTextBoxComment.tooltip.onpointerdown = (e: PointerEvent) => { const textBox = FormattedTextBoxComment.textBox; - const linkDoc = FormattedTextBoxComment.linkDoc; - if (linkDoc && !keep && textBox) { - if (linkDoc.author) { - if (FormattedTextBoxComment._deleteRef?.contains(e.target as any)) { - this.deleteLink(); - } else if (FormattedTextBoxComment._nextRef?.contains(e.target as any)) { - FormattedTextBoxComment.showPreview(FormattedTextBoxComment._lastView!, FormattedTextBoxComment._lastState, FormattedTextBoxComment._hrefs?.[(++FormattedTextBoxComment._hrefInd) % FormattedTextBoxComment._hrefs?.length]); - } else { - FormattedTextBoxComment.linkDoc = undefined; - if (linkDoc.type !== DocumentType.LINK) { - textBox.props.addDocTab(linkDoc, e.ctrlKey ? "add" : "add:right"); - } else { - const target = LinkManager.getOppositeAnchor(linkDoc, textBox.dataDoc); - target && LinkManager.FollowLink(linkDoc, textBox.dataDoc, textBox.props, e.altKey); - } - } - } - } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) { - textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400, useCors: true }), "add:right"); - } - keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation( + false && FormattedTextBoxComment.start !== undefined && textBox?.adoptAnnotation( FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark); e.stopPropagation(); e.preventDefault(); @@ -132,21 +78,9 @@ export class FormattedTextBoxComment { root?.appendChild(FormattedTextBoxComment.tooltip); } } - - @undoBatch - deleteLink = action(() => { - FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null; - FormattedTextBoxComment.Hide(); - }); - public static Hide() { FormattedTextBoxComment.textBox = undefined; - FormattedTextBoxComment.linkDoc = undefined; FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none"); - try { - ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText); - FormattedTextBoxComment.tooltip.removeChild(FormattedTextBoxComment.tooltipText); - } catch (e) { } } public static SetState(textBox: any, start: number, end: number, mark: Mark) { FormattedTextBoxComment.textBox = textBox; @@ -170,180 +104,71 @@ 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); } - static update(view: EditorView, lastState?: EditorState, forceUrl: string = "") { - // Don't do anything if the document/selection didn't change - if (!forceUrl && lastState?.doc.eq(view.state.doc) && lastState?.selection.eq(view.state.selection)) { - return; + static update(view: EditorView, lastState?: EditorState, hrefs: string = "") { + if (FormattedTextBoxComment.textBox && (hrefs || !lastState?.doc.eq(view.state.doc) || !lastState?.selection.eq(view.state.selection))) { + FormattedTextBoxComment.setupPreview(view, FormattedTextBoxComment.textBox, hrefs ? hrefs.trim().split(" ") : undefined); } - FormattedTextBoxComment._lastState = lastState; - FormattedTextBoxComment._lastView = view; - FormattedTextBoxComment._hrefs = forceUrl ? forceUrl.trim().split(" ") : undefined; - FormattedTextBoxComment._hrefInd = 0; - FormattedTextBoxComment.linkDoc = undefined; - FormattedTextBoxComment.showPreview(view, lastState, FormattedTextBoxComment._hrefs?.[FormattedTextBoxComment._hrefInd]); } - static showPreview(view: EditorView, lastState?: EditorState, forceUrl: string = "") { + static setupPreview(view: EditorView, textBox: FormattedTextBox, hrefs?: string[]) { const state = view.state; - const textBox = FormattedTextBoxComment.textBox; - if (!textBox || !textBox.props) { - return; - } - let set = "none"; - let nbef = 0; - FormattedTextBoxComment.tooltipInput.style.display = "none"; - FormattedTextBoxComment.tooltip.style.width = ""; - FormattedTextBoxComment.tooltip.style.height = ""; - (FormattedTextBoxComment.tooltipText as any).href = ""; - FormattedTextBoxComment.tooltipText.style.whiteSpace = ""; - FormattedTextBoxComment.tooltipText.style.overflow = ""; // this section checks to see if the insertion point is over text entered by a different user. If so, it sets ths comment text to indicate the user and the modification date + var hide = true; if (state.selection.$from) { - nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark); + const nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark); const naft = findEndOfMark(state.selection.$from, view, findOtherUserMark); - const noselection = view.state.selection.$from === view.state.selection.$to; + const noselection = state.selection.$from === state.selection.$to; let child: any = null; state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node)); const mark = child && findOtherUserMark(child.marks); if (mark && child && (nbef || naft) && (!mark.attrs.opened || noselection)) { - FormattedTextBoxComment.SetState(FormattedTextBoxComment.textBox, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark); + FormattedTextBoxComment.SetState(textBox, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark); } if (mark && child && ((nbef && naft) || !noselection)) { FormattedTextBoxComment.tooltipText.textContent = mark.attrs.userid + " on " + (new Date(mark.attrs.modified * 1000)).toLocaleString(); - set = ""; - FormattedTextBoxComment.tooltipInput.style.display = ""; + FormattedTextBoxComment.showCommentbox("", view, nbef); + hide = false; } } // this checks if the selection is a hyperlink. If so, it displays the target doc's text for internal links, and the url of the target for external links. - if (set === "none" && state.selection.$from) { - nbef = findStartOfMark(state.selection.$from, view, findLinkMark); + if (hide && state.selection.$from) { + const nbef = findStartOfMark(state.selection.$from, view, findLinkMark); const naft = findEndOfMark(state.selection.$from, view, findLinkMark) || nbef; let child: any = null; state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node)); child = child || (nbef && state.selection.$from.nodeBefore); const mark = child ? findLinkMark(child.marks) : undefined; - const href = forceUrl || (!mark?.attrs.docref || naft === nbef) && mark?.attrs.allAnchors.find((item: { href: string }) => item.href)?.href; - if (forceUrl || (href && child && nbef && naft && mark?.attrs.showPreview)) { - try { - ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText); - FormattedTextBoxComment.tooltip.removeChild(FormattedTextBoxComment.tooltipText); - } catch (e) { } - FormattedTextBoxComment.tooltipText = document.createElement("div"); - FormattedTextBoxComment.tooltipText.className = "FormattedTextBoxComment-toolTipText"; - FormattedTextBoxComment.tooltipText.style.width = "100%"; - FormattedTextBoxComment.tooltipText.style.height = "100%"; - FormattedTextBoxComment.tooltipText.style.textOverflow = "ellipsis"; - FormattedTextBoxComment.tooltipText.style.cursor = "pointer"; - FormattedTextBoxComment.tooltipText.textContent = "URL: " + href; - (FormattedTextBoxComment.tooltipText as any).href = href; - FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText); - - if (href.startsWith("https://en.wikipedia.org/wiki/")) { - wiki().page(href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(summary => FormattedTextBoxComment.tooltipText.textContent = summary.substring(0, 500))); - } else { - FormattedTextBoxComment.tooltipText.style.whiteSpace = "pre"; - FormattedTextBoxComment.tooltipText.style.overflow = "hidden"; - } - if (href.indexOf(Utils.prepend("/doc/")) === 0) { - const anchorDoc = href.replace(Utils.prepend("/doc/"), "").split("?")[0]; - FormattedTextBoxComment.tooltipText.textContent = "target not found..."; - (FormattedTextBoxComment.tooltipText as any).href = ""; - anchorDoc && DocServer.GetRefField(anchorDoc).then(async anchor => { - if (anchor instanceof Doc) { - const linkDoc = DocListCast(anchor.links)[0]; - (FormattedTextBoxComment.tooltipText as any).href = href; - FormattedTextBoxComment.linkDoc = linkDoc; - const targetanchor = LinkManager.getOppositeAnchor(linkDoc, anchor); - const target = targetanchor?.annotationOn ? await DocCastAsync(targetanchor.annotationOn) : targetanchor; - if (target?.author) { - FormattedTextBoxComment.showCommentbox("", view, nbef); - - const title = StrCast(target.title).length > 16 ? StrCast(target.title).substr(0, 16) + "..." : target.title; - - const docPreview =
-
-
- {title} - {FormattedTextBoxComment.linkDoc.description === "" ? (null) : -

{StrCast(FormattedTextBoxComment.linkDoc.description)}

} -
-
- {(FormattedTextBoxComment._hrefs?.length || 0) <= 1 ? (null) :
Next Link
} placement="top"> -
this._nextRef = r}> - -
-
} - -
Delete Link
} placement="top"> -
this._deleteRef = r}> - -
-
- -
Follow Link
} placement="top"> -
this._followRef = r}> - -
-
-
-
-
- targetanchor && target !== targetanchor && r?.focus(targetanchor)} - Document={target} - moveDocument={returnFalse} - rootSelected={returnFalse} - styleProvider={DefaultStyleProvider} - layerProvider={undefined} - docViewPath={emptyPath} - ScreenToLocalTransform={Transform.Identity} - parentActive={returnFalse} - addDocument={returnFalse} - removeDocument={returnFalse} - addDocTab={returnFalse} - pinToPres={returnFalse} - dontRegisterView={true} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={undefined} - ContainingCollectionView={undefined} - renderDepth={-1} - PanelWidth={() => 175} //Math.min(350, NumCast(target._width, 350))} - PanelHeight={() => 175} //Math.min(250, NumCast(target._height, 250))} - focus={emptyFunction} - whenActiveChanged={returnFalse} - bringToFront={returnFalse} - NativeWidth={Doc.NativeWidth(target) ? (() => Doc.NativeWidth(target)) : undefined} - NativeHeight={Doc.NativeHeight(target) ? (() => Doc.NativeHeight(target)) : undefined} - /> -
-
; - - FormattedTextBoxComment.showCommentbox("", view, nbef); - - ReactDOM.render(docPreview, FormattedTextBoxComment.tooltipText); - - //FormattedTextBoxComment.tooltip.style.width = "100%"; - FormattedTextBoxComment.tooltip.style.height = "100%"; - } - } + const href = (!mark?.attrs.docref || naft === nbef) && mark?.attrs.allAnchors.find((item: { href: string }) => item.href)?.href; + if ((href && child && nbef && naft && mark?.attrs.showPreview)) { + const anchorDoc = href.indexOf(Utils.prepend("/doc/")) === 0 ? href.replace(Utils.prepend("/doc/"), "").split("?")[0] : undefined; + if (anchorDoc) { + DocServer.GetRefField(anchorDoc).then(async anchor => + anchor instanceof Doc && textBox && LinkDocPreview.SetLinkInfo({ + docprops: textBox.props.docViewPath.lastElement().props, + linkSrc: textBox.props.Document, + linkDoc: DocListCast(anchor.links)[0], + location: ((pos) => [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - nbef)), + hrefs, + showHeader: true + }) + ); + } else if (hrefs?.length) { + LinkDocPreview.SetLinkInfo({ + docprops: textBox.props.docViewPath.lastElement().props, + linkSrc: textBox.props.Document, + linkDoc: undefined, + location: ((pos) => [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - nbef)), + hrefs, + showHeader: true }); } - set = ""; } } - FormattedTextBoxComment.showCommentbox(set, view, nbef); + if (hide) FormattedTextBoxComment.Hide(); } destroy() { } -- cgit v1.2.3-70-g09d2 From 861363c59997db5cde1b96786b156b64630465d7 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 10 Feb 2021 10:35:34 -0500 Subject: fixed some z-index issues with lightbox and typing new notes + videobox zooming zindex --- src/client/views/LightboxView.scss | 2 +- src/client/views/PreviewCursor.scss | 1 + src/client/views/collections/CollectionMenu.scss | 6 +++--- src/client/views/nodes/VideoBox.scss | 5 +++++ src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/nodes/WebBox.scss | 2 +- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 3 ++- src/client/views/search/SearchBox.scss | 2 +- 8 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src/client/views/nodes/VideoBox.tsx') diff --git a/src/client/views/LightboxView.scss b/src/client/views/LightboxView.scss index 9847966bf..35f11b699 100644 --- a/src/client/views/LightboxView.scss +++ b/src/client/views/LightboxView.scss @@ -4,7 +4,7 @@ width: 100%; height: 100%; background: #000000bb; - z-index: 10000; + z-index: 1000; .lightboxView-contents { position: absolute; } diff --git a/src/client/views/PreviewCursor.scss b/src/client/views/PreviewCursor.scss index d384fd284..de9bd69c4 100644 --- a/src/client/views/PreviewCursor.scss +++ b/src/client/views/PreviewCursor.scss @@ -7,4 +7,5 @@ left:0; pointer-events: none; opacity: 1; + z-index: 1001; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 180eaba4e..47adb6a1c 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -6,7 +6,7 @@ display: inline-flex; width: 100%; opacity: 0.9; - z-index: 9001; + z-index: 901; transition: top .5s; background: #323232; color: white; @@ -30,7 +30,7 @@ height: 32px; border-bottom: .5px solid rgb(180, 180, 180); overflow: visible; - z-index: 9001; + z-index: 901; border: unset; .collectionViewBaseChrome { @@ -325,7 +325,7 @@ .webBox-urlEditor { position: relative; opacity: 0.9; - z-index: 9001; + z-index: 901; transition: top .5s; .urlEditor { diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index b9123587b..dd8d77603 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -13,6 +13,11 @@ .collectionStackedTimeline { background: beige; } + .videoBox-stackPanel { + z-index: -1; + width: 100%; + position: absolute; + } } .videoBox-content-YouTube, .videoBox-content-YouTube-fullScreen, diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 324861573..a821eb7c2 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -489,7 +489,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent this.player!.currentTime = this.layoutDoc._currentTimecode = time; timelineHeight = () => this.props.PanelHeight() * (100 - this.heightPercent) / 100; @computed get renderTimeline() { - return
+ return
Date: Wed, 10 Feb 2021 18:31:40 -0500 Subject: fixed creating videoBox anchor to reference the whole doc when the timecode is 0. fixed following links to a document that has a colleciton context to open the context properly. --- src/client/util/DocumentManager.ts | 12 ++++-------- src/client/util/LinkManager.ts | 12 ++++++------ src/client/views/nodes/VideoBox.tsx | 3 ++- src/fields/documentSchemas.ts | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) (limited to 'src/client/views/nodes/VideoBox.tsx') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 811d04eb3..d7335c8c6 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -149,14 +149,10 @@ export class DocumentManager { const focusAndFinish = () => { finished?.(); return false; }; const highlight = () => { const finalDocView = getFirstDocView(targetDoc); - if (finalDocView) { - const parent = targetDoc?.annotationOn as Doc; - if (parent) finalDocView.layoutDoc.scrollToAnchorID = targetDoc?.[Id]; - Doc.linkFollowHighlight(finalDocView.rootDoc); - } + finalDocView && Doc.linkFollowHighlight(finalDocView.rootDoc); }; const docView = getFirstDocView(targetDoc, originatingDoc); - let annotatedDoc = await Cast(targetDoc.annotationOn, Doc); + let annotatedDoc = Cast(targetDoc.annotationOn, Doc, null); if (annotatedDoc && annotatedDoc !== originatingDoc?.context && !targetDoc?.isPushpin) { const first = getFirstDocView(annotatedDoc); if (first) { @@ -184,8 +180,8 @@ export class DocumentManager { highlight(); } else { const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; - const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc)) ? docContext : undefined; - const targetDocContext = annotatedDoc || contextDoc; + const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined; + const targetDocContext = contextDoc || annotatedDoc; if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default createViewFunc(Doc.BrushDoc(targetDoc), finished); // bcz: should we use this?: Doc.MakeAlias(targetDoc))); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index a684a202d..7ad37f059 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -102,7 +102,7 @@ export class LinkManager { // follows a link - if the target is on screen, it highlights/pans to it. // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place // depending on the followLinkLocation property of the source (or the link itself as a fallback); - public static FollowLink = async (linkDoc: Opt, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean) => { + public static FollowLink = (linkDoc: Opt, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean) => { const batch = UndoManager.StartBatch("follow link click"); // open up target if it's not already in view ... const createViewFunc = (doc: Doc, followLoc: string, finished: Opt<() => void>) => { @@ -126,9 +126,9 @@ export class LinkManager { docViewProps.focus(sourceDoc, BoolCast(sourceDoc.followLinkZoom, true), 1, targetFocusAfterDocFocus); } }; - await LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined); + LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined); } - public static async traverseLink(link: Opt, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { + public static traverseLink(link: Opt, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { 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 const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2 @@ -150,9 +150,9 @@ export class LinkManager { runInAction(() => LightboxView.LightboxDoc = (target.annotationOn as Doc) ?? target); finished?.(); } else { - const containerDoc = (await Cast(target.annotationOn, Doc)) || target; - containerDoc._currentTimecode = targetTimecode; - const targetContext = await target?.context as Doc; + const containerDoc = Cast(target.annotationOn, Doc, null) || target; + targetTimecode !== undefined && (containerDoc._currentTimecode = targetTimecode); + const targetContext = Cast(containerDoc?.context, Doc, null); const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, doc, finished); } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index a821eb7c2..c0247c226 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -70,7 +70,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent { - return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey + "-timeline", "videoStart", "videoEnd", Cast(this.layoutDoc._currentTimecode, "number", null)) || this.rootDoc; + const timecode = Cast(this.layoutDoc._currentTimecode, "number", null); + return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey + "-timeline", "videoStart", "videoEnd", timecode ? timecode : undefined) || this.rootDoc; } choosePath(url: string) { diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index f35c85110..056243953 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -114,7 +114,7 @@ export const collectionSchema = createSchema({ childLayoutTemplate: Doc, // layout template to use to render children of a collecion childLayoutString: "string", //layout string to use to render children of a collection childClickedOpenTemplateView: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to read this value and apply template) - dontRegisterChildViews: "boolean", // whether views made of this document are registered so that they can be found when drawing links scrollToAnchorID: "string", // id of anchor being traversed. allows this doc to scroll/highlight/etc its link anchor. scrollToAnchorID should be set to undefined by this doc after it sets up its scroll,etc. + dontRegisterChildViews: "boolean", // whether views made of this document are registered so that they can be found when drawing links onChildClick: ScriptField, // script to run for each child when its clicked onChildDoubleClick: ScriptField, // script to run for each child when its clicked onCheckedClick: ScriptField, // script to run when a checkbox is clicked next to a child in a tree view -- cgit v1.2.3-70-g09d2