diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 3 | ||||
-rw-r--r-- | src/client/goldenLayout.js | 2 | ||||
-rw-r--r-- | src/client/util/RichTextSchema.tsx | 1 | ||||
-rw-r--r-- | src/client/util/TooltipTextMenu.tsx | 14 | ||||
-rw-r--r-- | src/client/views/linking/LinkFollowBox.tsx | 12 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 66 |
7 files changed, 89 insertions, 13 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2fa0d2dcb..b2a320517 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -638,7 +638,7 @@ export namespace DocUtils { }); } export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", sourceContext?: Doc, id?: string, anchored1?: boolean) { - if (LinkManager.Instance.doesLinkExist(source, target)) return undefined; + // if (LinkManager.Instance.doesLinkExist(source, target)) return undefined; let sv = DocumentManager.Instance.getDocumentView(source); if (sv && sv.props.ContainingCollectionDoc === target) return; if (target === CurrentUserUtils.UserDocument) return undefined; @@ -651,7 +651,6 @@ export namespace DocUtils { linkDocProto.sourceContext = sourceContext; linkDocProto.title = title === "" ? source.title + " to " + target.title : title; linkDocProto.linkDescription = description; - linkDocProto.type = DocumentType.LINK; linkDocProto.anchor1 = source; linkDocProto.anchor1Page = source.curPage; diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js index ad78139c1..29b750720 100644 --- a/src/client/goldenLayout.js +++ b/src/client/goldenLayout.js @@ -377,7 +377,7 @@ this._nOriginalY = coordinates.y; this._oDocument.on('mousemove touchmove', this._fMove); - this._oDocument.one('mouseup touchend', this._fUp); + this._oDocument.on('mouseup touchend', this._fUp); this._timeout = setTimeout(lm.utils.fnBind(this._startDrag, this), this._nDelay); } diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index ba4b92a25..ea31671ac 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -253,6 +253,7 @@ export const marks: { [index: string]: MarkSpec } = { href: {}, location: { default: null }, title: { default: null }, + guid: { default: null }, docref: { default: false } }, inclusive: false, diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index b6de048e4..a2653855c 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -303,11 +303,13 @@ export class TooltipTextMenu { handlers: { dragComplete: action(() => { let linkDoc = dragData.linkDocument; + let guid = Utils.GenerateGuid(); let proto = Doc.GetProto(linkDoc); if (proto && docView) { proto.sourceContext = docView.props.ContainingCollectionDoc; } - linkDoc instanceof Doc && this.makeLink(Utils.prepend("/doc/" + linkDoc[Id]), ctrlKey ? "onRight" : "inTab"); + linkDoc.guid = guid; + linkDoc instanceof Doc && this.makeLink(Utils.prepend("/doc/" + linkDoc[Id]), ctrlKey ? "onRight" : "inTab", guid); }), }, hideSource: false @@ -389,13 +391,13 @@ export class TooltipTextMenu { } } - makeLinkWithState = (state: EditorState, target: string, location: string) => { - let link = state.schema.mark(state.schema.marks.link, { href: target, location: location }); - } + // makeLinkWithState = (state: EditorState, target: string, location: string) => { + // let link = state.schema.mark(state.schema.marks.link, { href: target, location: location }); + // } - makeLink = (target: string, location: string) => { + makeLink = (target: string, location: string, guid?: string) => { let node = this.view.state.selection.$from.nodeAfter; - let link = this.view.state.schema.mark(this.view.state.schema.marks.link, { href: target, location: location }); + let link = this.view.state.schema.mark(this.view.state.schema.marks.link, { href: target, location: location, guid: guid }); this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link)); this.view.dispatch(this.view.state.tr.addMark(this.view.state.selection.from, this.view.state.selection.to, link)); node = this.view.state.selection.$from.nodeAfter; diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 81b0249dd..1280ae28b 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -18,6 +18,7 @@ import { DocServer } from "../../DocServer"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { docs_v1 } from "googleapis"; +import { Utils } from "../../../Utils"; enum FollowModes { OPENTAB = "Open in Tab", @@ -242,6 +243,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { let proto = Doc.GetProto(LinkFollowBox.linkDoc); let targetContext = await Cast(proto.targetContext, Doc); let sourceContext = await Cast(proto.sourceContext, Doc); + let guid = StrCast(LinkFollowBox.linkDoc.guid); const shouldZoom = options ? options.shouldZoom : false; let dockingFunc = (document: Doc) => { (this._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; @@ -251,6 +253,16 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { } else if (LinkFollowBox.destinationDoc === LinkFollowBox.linkDoc.anchor1 && sourceContext) { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!)); + if (LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc) { + if (guid) { + LinkFollowBox.destinationDoc.guid = guid; + } else { + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.linkDoc[Id])); + let newguid = Utils.GenerateGuid(); + LinkFollowBox.linkDoc.guid = newguid; + LinkFollowBox.destinationDoc.guid = newguid; + } + } } else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, undefined, undefined, diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 82fe3df23..835554ac0 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -28,9 +28,7 @@ interface LinkMenuItemProps { export class LinkMenuItem extends React.Component<LinkMenuItemProps> { private _drag = React.createRef<HTMLDivElement>(); @observable private _showMore: boolean = false; - @action toggleShowMore() { - this._showMore = !this._showMore; - } + @action toggleShowMore() { this._showMore = !this._showMore; } onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index eb4718581..53f28ac00 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -138,6 +138,69 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this.props.isOverlay) { DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined); } + + this.props.Document.guid = undefined; + this.props.Document.linkHref = undefined; + + reaction( + () => StrCast(this.props.Document.guid), + async (guid) => { + let start = -1; + let href = this.props.Document.linkHref; + + if (this._editorView && guid) { + let editor = this._editorView; + let ret = findLinkFrag(editor.state.doc.content, editor); + + if (ret.frag.size > 2) { + let tr; + if (ret.frag.firstChild) { + let between = TextSelection.between(editor.state.doc.resolve(ret.start + 2), editor.state.doc.resolve(ret.start + ret.frag.firstChild.nodeSize)); + tr = editor.state.tr.setSelection(between); + } else { + let near = TextSelection.near(editor.state.doc.resolve(ret.start)); + tr = editor.state.tr.setSelection(near); + } + + editor.focus(); + editor.dispatch(tr.scrollIntoView()); + editor.dispatch(tr.scrollIntoView()); // bcz: sometimes selection doesn't fully scroll into view on smaller text boxes <5 lines visibility -- hopefully avoidable by ppl just not using small boxes...? + + this.props.Document.guid = undefined; + this.props.Document.linkHref = undefined; + } + } + + function findLinkFrag(frag: Fragment, editor: EditorView) { + const nodes: Node[] = []; + frag.forEach((node, index) => { + let examinedNode = findLinkNode(node, editor); + if (examinedNode && examinedNode.textContent !== "") { + nodes.push(examinedNode); + start += index; + } + }); + return { frag: Fragment.fromArray(nodes), start: start }; + } + function findLinkNode(node: Node, editor: EditorView) { + if (!node.isText) { + const content = findLinkFrag(node.content, editor); + return node.copy(content.frag); + } + const marks = [...node.marks]; + const linkIndex = marks.findIndex(mark => mark.type.name === "link"); + if (linkIndex !== -1) { + if (guid === marks[linkIndex].attrs.guid) { + return node; + } else if (href && href === marks[linkIndex].attrs.href) { // retroactively fixing old in-text links by adding guid + marks[linkIndex].attrs.guid = guid; + return node; + } + } + return undefined; + } + } + ); } public get CurrentDiv(): HTMLDivElement { return this._ref.current!; } @@ -760,6 +823,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let ctrlKey = e.ctrlKey; if (e.button === 0 && ((!this.props.isSelected() && !e.ctrlKey) || (this.props.isSelected() && e.ctrlKey)) && !e.metaKey && e.target) { let href = (e.target as any).href; + let guid = (e.target as any).guid; let location: string; if ((e.target as any).attributes.location) { location = (e.target as any).attributes.location.value; @@ -783,9 +847,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let proto = Doc.GetProto(linkDoc); let targetContext = await Cast(proto.targetContext, Doc); let jumpToDoc = await Cast(linkDoc.anchor2, Doc); + if (jumpToDoc) { if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((jumpToDoc === linkDoc.anchor2 ? linkDoc.anchor2Page : linkDoc.anchor1Page))); return; } |