From c660a8b1846db1bc05cf8f496f77e706fe469711 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 13 Jul 2022 10:48:25 -0400 Subject: fixed linkdoc preview not going away when clicking outside of it. --- src/client/views/nodes/LinkDocPreview.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index c2fb5d4ec..d8b943ae4 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -3,20 +3,20 @@ import { Tooltip } from '@material-ui/core'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import wiki from 'wikijs'; -import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocCastAsync } from '../../../fields/Doc'; -import { NumCast, StrCast, Cast } from '../../../fields/Types'; -import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, setupMoveUpEvents, Utils } from '../../../Utils'; +import { Doc, DocCastAsync, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; +import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs, DocUtils } from '../../documents/Documents'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { DragManager } from '../../util/DragManager'; +import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { DocumentView, DocumentViewSharedProps } from './DocumentView'; import './LinkDocPreview.scss'; import React = require('react'); -import { DocumentType } from '../../documents/DocumentTypes'; -import { DragManager } from '../../util/DragManager'; -import { LinkFollower } from '../../util/LinkFollower'; interface LinkDocPreviewProps { linkDoc?: Doc; @@ -65,12 +65,12 @@ export class LinkDocPreview extends React.Component { } componentDidMount() { this.init(); - document.addEventListener('pointerdown', this.onPointerDown); + document.addEventListener('pointerdown', this.onPointerDown, true); } componentWillUnmount() { LinkDocPreview.SetLinkInfo(undefined); - document.removeEventListener('pointerdown', this.onPointerDown); + document.removeEventListener('pointerdown', this.onPointerDown, true); } onPointerDown = (e: PointerEvent) => { -- cgit v1.2.3-70-g09d2 From 5f8248acbc5b83a4e1571779913f9ed5700382de Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 26 Jul 2022 15:54:23 -0400 Subject: fixed clicking linkDocPreview to follow links. switched target drag behavior from title to preview --- src/client/views/MainView.tsx | 2 +- src/client/views/nodes/LinkDocPreview.scss | 18 +++++++---- src/client/views/nodes/LinkDocPreview.tsx | 52 +++++++++++++++++++++--------- 3 files changed, 49 insertions(+), 23 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4dc8a2e4a..e96f65548 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -205,7 +205,7 @@ export class MainView extends React.Component { componentWillUnMount() { window.removeEventListener('keyup', KeyManager.Instance.unhandle); window.removeEventListener('keydown', KeyManager.Instance.handle); - window.removeEventListener('pointerdown', this.globalPointerDown); + window.removeEventListener('pointerdown', this.globalPointerDown, true); window.removeEventListener('paste', KeyManager.Instance.paste as any); document.removeEventListener('linkAnnotationToDash', Hypothesis.linkListener); } diff --git a/src/client/views/nodes/LinkDocPreview.scss b/src/client/views/nodes/LinkDocPreview.scss index 3febbcecb..c68e55f73 100644 --- a/src/client/views/nodes/LinkDocPreview.scss +++ b/src/client/views/nodes/LinkDocPreview.scss @@ -8,6 +8,7 @@ border-bottom: 8px solid white; border-right: 8px solid white; z-index: 2004; + cursor: pointer; .linkDocPreview-inner { background-color: white; @@ -63,13 +64,16 @@ cursor: pointer; } } + } - .linkDocPreview-preview-wrapper { - overflow: hidden; - align-content: center; - justify-content: center; - background-color: rgb(160, 160, 160); - } + .linkDocPreview-preview-wrapper { + overflow: hidden; + align-content: center; + justify-content: center; + pointer-events: all; + background-color: rgb(160, 160, 160); + overflow: auto; + cursor: grab; } } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index d8b943ae4..a12564839 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -5,7 +5,7 @@ import { observer } from 'mobx-react'; import wiki from 'wikijs'; import { Doc, DocCastAsync, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -36,6 +36,7 @@ export class LinkDocPreview extends React.Component { } _infoRef = React.createRef(); + _linkDocRef = React.createRef(); @observable public static LinkInfo: Opt; @observable _targetDoc: Opt; @observable _linkDoc: Opt; @@ -74,7 +75,7 @@ export class LinkDocPreview extends React.Component { } onPointerDown = (e: PointerEvent) => { - !this._infoRef.current?.contains(e.target as any) && LinkDocPreview.Clear(); // close preview when not clicking anywhere other than the info bar of the preview + !this._linkDocRef.current?.contains(e.target as any) && LinkDocPreview.Clear(); // close preview when not clicking anywhere other than the info bar of the preview }; @computed get href() { @@ -143,7 +144,7 @@ export class LinkDocPreview extends React.Component { ); }; - followLink = (e: React.PointerEvent) => { + followLink = () => { if (this._linkDoc && this._linkSrc) { LinkDocPreview.Clear(); LinkFollower.FollowLink(this._linkDoc, this._linkSrc, this.props.docProps, false); @@ -151,6 +152,9 @@ export class LinkDocPreview extends React.Component { this.props.docProps?.addDocTab(Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, useCors: true }), 'add:right'); } }; + + followLinkPointerDown = (e: React.PointerEvent) => setupMoveUpEvents(this, e, returnFalse, emptyFunction, this.followLink); + width = () => { if (!this._targetDoc) return 225; if (this._targetDoc[WidthSym]() < this._targetDoc?.[HeightSym]()) { @@ -167,15 +171,8 @@ export class LinkDocPreview extends React.Component { }; @computed get previewHeader() { return !this._linkDoc || !this._targetDoc || !this._linkSrc ? null : ( -
-
{ - DragManager.StartDocumentDrag([this._infoRef.current!], new DragManager.DocumentDragData([this._targetDoc!]), e.pageX, e.pageY); - e.stopPropagation(); - LinkDocPreview.Clear(); - }}> +
+
{StrCast(this._targetDoc.title).length > 16 ? StrCast(this._targetDoc.title).substr(0, 16) + '...' : StrCast(this._targetDoc.title)}

{StrCast(this._linkDoc.description)}

@@ -201,7 +198,27 @@ export class LinkDocPreview extends React.Component { return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? null : (
{!this.props.showHeader ? null : this.previewHeader} -
+
+ setupMoveUpEvents( + this, + e, + (e, down, delta) => { + if (Math.abs(e.clientX - down[0]) + Math.abs(e.clientY - down[1]) > 100) { + DragManager.StartDocumentDrag([this._infoRef.current!], new DragManager.DocumentDragData([this._targetDoc!]), e.pageX, e.pageY); + LinkDocPreview.Clear(); + return true; + } + return false; + }, + emptyFunction, + this.followLink, + true + ) + } + ref={this._infoRef} + style={{ maxHeight: this._toolTipText ? '100%' : undefined }}> {this._toolTipText ? ( this._toolTipText ) : ( @@ -217,7 +234,7 @@ export class LinkDocPreview extends React.Component { docViewPath={returnEmptyDoclist} ScreenToLocalTransform={Transform.Identity} isDocumentActive={returnFalse} - isContentActive={emptyFunction} + isContentActive={returnFalse} addDocument={returnFalse} removeDocument={returnFalse} addDocTab={returnFalse} @@ -232,6 +249,7 @@ export class LinkDocPreview extends React.Component { suppressSetHeight={true} PanelWidth={this.width} PanelHeight={this.height} + pointerEvents={returnNone} focus={DocUtils.DefaultFocus} whenChildContentsActiveChanged={returnFalse} ignoreAutoHeight={true} // need to ignore autoHeight otherwise autoHeight text boxes will expand beyond the preview panel size. @@ -248,7 +266,11 @@ export class LinkDocPreview extends React.Component { render() { const borders = 16; // 8px border on each side return ( -
+
{this.docPreview}
); -- cgit v1.2.3-70-g09d2 From 26670c8b9eb6e2fd981c3a0997bff5556b60504b Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 8 Aug 2022 09:34:51 -0400 Subject: made props.showTitle = '' override doc.showTitle. fixed de-autoLinking when text box is empty --- src/client/views/StyleProvider.tsx | 1 + src/client/views/nodes/LinkDocPreview.tsx | 3 ++- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index a83163eb0..3bd4f5152 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -124,6 +124,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt { isDocumentActive={returnFalse} isContentActive={returnFalse} addDocument={returnFalse} + showTitle={returnEmptyString} removeDocument={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index add83f4e0..a018f51c2 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -382,9 +382,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { + const newAutoLinks = new Set(); + const oldAutoLinks = DocListCast(this.props.Document.links).filter(link => link.linkRelationship === LinkManager.AutoKeywords); if (this._editorView?.state.doc.textContent) { - const newAutoLinks = new Set(); - const oldAutoLinks = DocListCast(this.props.Document.links).filter(link => link.linkRelationship === LinkManager.AutoKeywords); const f = this._editorView.state.selection.from; const t = this._editorView.state.selection.to; var tr = this._editorView.state.tr as any; @@ -393,8 +393,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (tr = this.hyperlinkTerm(tr, term, newAutoLinks))); tr = tr.setSelection(new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t))); this._editorView?.dispatch(tr); - oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.anchor2 !== this.rootDoc).forEach(LinkManager.Instance.deleteLink); } + oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.anchor2 !== this.rootDoc).forEach(LinkManager.Instance.deleteLink); }; updateTitle = () => { -- cgit v1.2.3-70-g09d2 From 2a1d6793d33d9c72295d23965aefd23f2004bbcb Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 8 Aug 2022 11:48:27 -0400 Subject: cleaning up link ui. linkPreviews (not from linkMenu) have an edit button. link lines work when in lightboxview. --- .../CollectionFreeFormLinkView.tsx | 5 +- .../CollectionFreeFormLinksView.tsx | 5 +- src/client/views/linking/LinkEditor.scss | 65 +++++----- src/client/views/linking/LinkEditor.tsx | 141 ++++++++++++--------- src/client/views/linking/LinkMenuItem.tsx | 89 +------------ src/client/views/nodes/DocumentLinksButton.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 16 ++- src/client/views/nodes/LinkAnchorBox.tsx | 2 +- src/client/views/nodes/LinkDocPreview.tsx | 18 ++- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- 10 files changed, 149 insertions(+), 198 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index d979ef961..bf9de6760 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -195,7 +195,10 @@ export class CollectionFreeFormLinkView extends React.Component> { @computed get uniqueConnections() { - return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews)).map(c => ); + return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews)) + .filter(c => !LightboxView.LightboxDoc || (LightboxView.IsLightboxDocView(c.a.docViewPath) && LightboxView.IsLightboxDocView(c.b.docViewPath))) + .map(c => ); } render() { diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss index 1d6496d3c..b0ee4e46d 100644 --- a/src/client/views/linking/LinkEditor.scss +++ b/src/client/views/linking/LinkEditor.scss @@ -1,10 +1,11 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables'; .linkEditor { width: 100%; height: auto; font-size: 13px; // TODO user-select: none; + max-width: 280px; } .linkEditor-button-back { @@ -20,19 +21,20 @@ } .linkEditor-info { - //border-bottom: 0.5px solid $light-gray; - //padding-bottom: 1px; - padding: 12px; + padding-top: 12px; padding-left: 5px; + padding-bottom: 3px; //margin-bottom: 6px; display: flex; justify-content: space-between; color: black; .linkEditor-linkedTo { - width: calc(100% - 26px); - padding-left: 5px; - padding-right: 5px; + width: calc(100% - 46px); + overflow: hidden; + position: relative; + text-overflow: ellipsis; + white-space: pre; .linkEditor-downArrow { &:hover { @@ -77,11 +79,14 @@ width: 20px; } } +.linkEditor-deleteBtn { + padding-left: 3px; +} .linkEditor-description { padding-left: 26px; - padding-right: 6.5px; padding-bottom: 3.5px; + display: flex; .linkEditor-description-label { text-decoration-color: black; @@ -96,7 +101,6 @@ //border: 1px solid grey; //border-radius: 4px; padding-left: 2px; - padding-right: 2px; //margin-right: 4px; color: black; text-decoration-color: grey; @@ -104,17 +108,13 @@ .linkEditor-description-add-button { display: inline; - /* float: right; */ border-radius: 7px; font-size: 9px; background: black; - /* padding: 3px; */ - padding-top: 4px; - padding-left: 7px; - padding-bottom: 4px; - padding-right: 8px; height: 80%; color: white; + padding: 3px; + margin-left: 3px; &:hover { cursor: pointer; @@ -146,6 +146,7 @@ padding-left: 26px; padding-right: 6.5px; padding-bottom: 15px; + display: flex; &:hover { cursor: pointer; @@ -153,12 +154,11 @@ .linkEditor-followingDropdown-label { color: black; + padding-right: 3px; } .linkEditor-followingDropdown-dropdown { - .linkEditor-followingDropdown-header { - border: 1px solid grey; border-radius: 4px; //background-color: rgb(236, 236, 236); @@ -195,27 +195,25 @@ background-color: rgb(187, 220, 231); } } - } } - - } - - - - - .linkEditor-button, .linkEditor-addbutton { - width: 18px; - height: 18px; - padding: 0; - // font-size: 12px; - border-radius: 10px; - - + width: 15%; + border-radius: 7px; + font-size: 9px; + background: black; + padding: 3px; + height: 80%; + color: white; + text-align: center; + margin: auto; + margin-left: 3px; + > svg { + margin: auto; + } &:disabled { background-color: gray; } @@ -270,7 +268,6 @@ } } - .linkEditor-dropdown { width: 100%; position: relative; @@ -334,4 +331,4 @@ .linkEditor-button { margin-left: 3px; } -} \ No newline at end of file +} diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index ba301962b..d23d38854 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -9,11 +9,12 @@ import { undoBatch } from '../../util/UndoManager'; import './LinkEditor.scss'; import { LinkRelationshipSearch } from './LinkRelationshipSearch'; import React = require('react'); +import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; interface LinkEditorProps { sourceDoc: Doc; linkDoc: Doc; - showLinks: () => void; + showLinks?: () => void; hideback?: boolean; } @observer @@ -22,13 +23,6 @@ export class LinkEditor extends React.Component { @observable relationship = StrCast(LinkManager.currentLink?.linkRelationship); @observable zoomFollow = StrCast(this.props.sourceDoc.followLinkZoom); @observable openDropdown: boolean = false; - @observable showInfo: boolean = false; - @computed get infoIcon() { - if (this.showInfo) { - return 'chevron-up'; - } - return 'chevron-down'; - } @observable private buttonColor: string = ''; @observable private relationshipButtonColor: string = ''; @observable private relationshipSearchVisibility: string = 'none'; @@ -36,12 +30,6 @@ export class LinkEditor extends React.Component { //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION"; - @undoBatch - deleteLink = (): void => { - LinkManager.Instance.deleteLink(this.props.linkDoc); - this.props.showLinks(); - }; - @undoBatch setRelationshipValue = action((value: string) => { if (LinkManager.currentLink) { @@ -173,7 +161,7 @@ export class LinkEditor extends React.Component { //NOTE: confusingly, the classnames for the following relationship JSX elements are the same as the for the description elements for shared CSS return (
-
Link Relationship:
+
Relationship:
{ get editDescription() { return (
-
Link Description:
+
Description:
@@ -284,68 +272,99 @@ export class LinkEditor extends React.Component { ); } - @action - changeInfo = () => { - this.showInfo = !this.showInfo; + autoMove = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove)))); + }; + + showAnchor = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.hidden = !this.props.linkDoc.hidden)))); + }; + + showLink = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay)))); + }; + + deleteLink = (e: React.PointerEvent): void => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => LinkManager.Instance.deleteLink(this.props.linkDoc)))); }; render() { const destination = LinkManager.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); return !destination ? null : ( -
e.stopPropagation()}> +
e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
- -
Return to link menu
- - } - placement="top"> - -
+ {!this.props.showLinks ? null : ( + Return to link menu
} placement="top"> + + + )}

Editing Link to: {StrCast(destination.proto?.title, StrCast(destination.title, 'untitled'))}

- -
Show more link information
- - } - placement="top"> -
- + Delete Link
}> +
e.stopPropagation()}> +
- {this.showInfo ? ( -
-
- {this.props.linkDoc.author ? ( -
- {' '} - Author: {StrCast(this.props.linkDoc.author)} -
- ) : null} -
-
- {this.props.linkDoc.creationDate ? ( -
- {' '} - Creation Date: - {DateCast(this.props.linkDoc.creationDate).toString()} -
- ) : null} -
-
- ) : null} +
+ {this.props.linkDoc.author ? ( + <> + {' '} + Author: {StrCast(this.props.linkDoc.author)} + + ) : null} + {this.props.linkDoc.creationDate ? ( + <> + {' '} + Creation Date: + {DateCast(this.props.linkDoc.creationDate).toString()} + + ) : null} +
{this.editDescription} {this.editRelationship} {this.editZoomFollow} +
+ Show Anchor: + {this.props.linkDoc.hidden ? 'Show Link Anchor' : 'Hide Link Anchor'}
}> +
e.stopPropagation()}> + +
+ +
+
+ Show Link Line: + {this.props.linkDoc.linkDisplay ? 'Hide Link Line' : 'Show Link Line'}
}> +
e.stopPropagation()}> + +
+ +
+
+ Freeze Anchor: + {this.props.linkDoc.linkAutoMove ? 'Click to freeze link anchor position' : 'Click to auto move link anchor'}
}> +
e.stopPropagation()}> + +
+ +
{this.followingDropdown}
); diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index ed856a4ab..60428fc98 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -125,33 +125,6 @@ export class LinkMenuItem extends React.Component { ); }; - deleteLink = (e: React.PointerEvent): void => { - 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); - }) - ) - ); - }; - - autoMove = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove)))); - }; - - showLink = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay)))); - }; - - showAnchor = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.hidden = !this.props.linkDoc.hidden)))); - }; - render() { const destinationIcon = Doc.toIcon(this.props.destinationDoc) as any as IconProp; @@ -183,7 +156,7 @@ export class LinkMenuItem extends React.Component { linkSrc: this.props.sourceDoc, linkDoc: this.props.linkDoc, showHeader: false, - location: [e.clientX, e.clientY + 20], + location: [this._drag.current?.getBoundingClientRect().right ?? 100, this._drag.current?.getBoundingClientRect().top ?? e.clientY], }) } onPointerDown={this.onLinkButtonDown}> @@ -206,69 +179,11 @@ export class LinkMenuItem extends React.Component {
- -
{this.props.linkDoc.hidden ? 'Show Link Anchor' : 'Hide Link Anchor'}
- - }> -
e.stopPropagation()}> - -
-
- - -
{this.props.linkDoc.linkDisplay ? 'Hide Link Line' : 'Show Link Line'}
- - }> -
e.stopPropagation()}> - -
-
- - -
{this.props.linkDoc.linkAutoMove ? 'Click to freeze link anchor position' : 'Click to auto move link anchor'}
- - }> -
e.stopPropagation()}> - -
-
- - -
Edit Link
- - }> + Edit Link
}>
e.stopPropagation()}>
- -
Delete Link
- - }> -
e.stopPropagation()}> - -
-
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 5939d1680..a37de7f69 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -307,7 +307,7 @@ export class DocumentLinksButton extends React.Component {(this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) || (!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 1ee1aec5a..2524d66dd 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1070,7 +1070,7 @@ export class DocumentViewInternal extends DocComponent )} {audioView} @@ -1298,6 +1298,7 @@ export class DocumentViewInternal extends DocComponent this._isHovering; @observable _isHovering = false; @observable _: string = ''; + _hoverTimeout: any = undefined; @computed get renderDoc() { TraceMobx(); const thumb = ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb))?.url?.href.replace('.png', '_m.png'); @@ -1308,8 +1309,17 @@ export class DocumentViewInternal extends DocComponent (this._isHovering = true))} - onPointerLeave={action(() => (this._isHovering = false))} + onPointerEnter={action(() => { + clearTimeout(this._hoverTimeout); + this._isHovering = true; + })} + onPointerLeave={action(() => { + clearTimeout(this._hoverTimeout); + this._hoverTimeout = setTimeout( + action(() => (this._isHovering = false)), + 500 + ); + })} style={{ background: isButton || thumb ? undefined : this.backgroundColor, opacity: this.opacity, diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 85a8622ec..5102eae51 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -136,7 +136,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { return (
LinkDocPreview.SetLinkInfo({ docProps: this.props, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 85b1f8d9e..93ca22d5d 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -17,6 +17,7 @@ import { undoBatch } from '../../util/UndoManager'; import { DocumentView, DocumentViewSharedProps } from './DocumentView'; import './LinkDocPreview.scss'; import React = require('react'); +import { LinkEditor } from '../linking/LinkEditor'; interface LinkDocPreviewProps { linkDoc?: Doc; @@ -118,13 +119,15 @@ export class LinkDocPreview extends React.Component { } return undefined; } - deleteLink = (e: React.PointerEvent) => { + @observable _showEditor = false; + editLink = (e: React.PointerEvent): void => { + LinkManager.currentLink = this.props.linkDoc; setupMoveUpEvents( this, e, returnFalse, emptyFunction, - undoBatch(() => this._linkDoc && LinkManager.Instance.deleteLink(this._linkDoc)) + action(() => (this._showEditor = !this._showEditor)) ); }; nextHref = (e: React.PointerEvent) => { @@ -183,9 +186,9 @@ export class LinkDocPreview extends React.Component {
- Delete Link
} placement="top"> -
- + Edit Link
} placement="top"> +
+
@@ -271,8 +274,9 @@ export class LinkDocPreview extends React.Component { className="linkDocPreview" ref={this._linkDocRef} onPointerDown={this.followLinkPointerDown} - style={{ left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> - {this.docPreview} + style={{ left: this.props.location[0], top: this.props.location[1], width: this._showEditor ? 'auto' : this.width() + borders, height: this._showEditor ? 'max-content' : this.height() + borders + (this.props.showHeader ? 37 : 0) }}> + {this._showEditor ? null : this.docPreview} + {!this._showEditor || !this._linkSrc || !this._linkDoc ? null : (this._showEditor = !this._showEditor))} />}
); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index a018f51c2..40b0d285c 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -24,7 +24,7 @@ import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils'; import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; -import { DocumentType } from '../../../documents/DocumentTypes'; +import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { DictationManager } from '../../../util/DictationManager'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; @@ -1751,7 +1751,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const ComponentTag = tag === 'freeform' ? CollectionFreeFormView : tag === 'tree' ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView; + const ComponentTag = tag === CollectionViewType.Freeform ? CollectionFreeFormView : tag === CollectionViewType.Tree ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView; return ComponentTag === CollectionStackingView ? (