diff options
-rw-r--r-- | src/client/documents/Documents.ts | 1 | ||||
-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/LinkMenuItem.tsx | 60 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 68 |
6 files changed, 137 insertions, 9 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ae65fde1e..e53c72c1c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -620,7 +620,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 f027a4bf7..379da112f 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 c376b6f86..34025787d 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -309,11 +309,13 @@ export class TooltipTextMenu { handlers: { dragComplete: action(() => { let linkDoc = dragData.linkDocument; + let guid = Utils.GenerateGuid(); let proto = Doc.GetProto(linkDoc); if (proto && docView && docView.props.ContainingCollectionView) { proto.sourceContext = docView.props.ContainingCollectionView.props.Document; } - 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 @@ -395,13 +397,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/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 19a0023e9..0e951fc38 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -12,6 +12,18 @@ import { MainView } from '../MainView'; import { LinkFollowBox } from './LinkFollowBox'; import './LinkMenu.scss'; import React = require("react"); +<<<<<<< HEAD:src/client/views/nodes/LinkMenuItem.tsx +import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; +import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; +import { observable, action } from 'mobx'; +import { LinkManager } from '../../util/LinkManager'; +import { DragLinkAsDocument } from '../../util/DragManager'; +import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { SelectionManager } from '../../util/SelectionManager'; +import { Utils } from '../../../Utils'; +import { Id } from '../../../new_fields/FieldSymbols'; +======= +>>>>>>> ec62b213439ab49134fa2dbbdf38a6d1ef5737cd:src/client/views/linking/LinkMenuItem.tsx library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -28,8 +40,56 @@ interface LinkMenuItemProps { export class LinkMenuItem extends React.Component<LinkMenuItemProps> { private _drag = React.createRef<HTMLDivElement>(); @observable private _showMore: boolean = false; +<<<<<<< HEAD:src/client/views/nodes/LinkMenuItem.tsx + @action toggleShowMore() { this._showMore = !this._showMore; } + + @undoBatch + onFollowLink = async (e: React.PointerEvent): Promise<void> => { + e.stopPropagation(); + e.persist(); + let jumpToDoc = this.props.destinationDoc; + let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc)); + if (pdfDoc) { + jumpToDoc = pdfDoc; + } + let proto = Doc.GetProto(this.props.linkDoc); + let targetContext = await Cast(proto.targetContext, Doc); + let sourceContext = await Cast(proto.sourceContext, Doc); + let guid = StrCast(this.props.linkDoc.guid); + let self = this; + + let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + if (e.ctrlKey) { + dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined); + } + + if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, async document => dockingFunc(document), undefined, targetContext); + } + else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!)); + if (guid) { + console.log('wegotthis', StrCast(self.props.linkDoc.anchor2), jumpToDoc[Id]); + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(this.props.linkDoc.anchor2)); + jumpToDoc.guid = guid; + } else { // retroactively fixing old in-text links by adding guid + console.log('wegotthis', self.props.linkDoc.anchor2, jumpToDoc[Id]); + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(this.props.linkDoc.anchor2)); + let newguid = Utils.GenerateGuid(); + this.props.linkDoc.guid = newguid; + jumpToDoc.guid = newguid; + } + } + else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page))); + } + else { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc); + } +======= @action toggleShowMore() { this._showMore = !this._showMore; +>>>>>>> ec62b213439ab49134fa2dbbdf38a6d1ef5737cd:src/client/views/linking/LinkMenuItem.tsx } onEdit = (e: React.PointerEvent): void => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0ea36cdc2..985075a52 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -135,6 +135,65 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this.props.isOverlay) { DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined); } + + document.addEventListener("paste", this.paste); + + 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) { + tr = editor.state.tr.setSelection(TextSelection.between(editor.state.doc.resolve(ret.start + 2), editor.state.doc.resolve(ret.start + ret.frag.firstChild.nodeSize))); + } else { + tr = editor.state.tr.setSelection(TextSelection.near(editor.state.doc.resolve(ret.start))); + } + 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 = ""; + this.props.Document.linkHref = ""; + } + } + + 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; + } + console.log('href was and is ', href, marks[linkIndex].attrs.href); + } + return undefined; + } + } + ); } public get CurrentDiv(): HTMLDivElement { return this._ref.current!; } @@ -598,6 +657,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let frag = addMarkToFrag(slice.content, (node: Node) => addLinkMark(node, StrCast(doc.title))); slice = new Slice(frag, slice.openStart, slice.openEnd); var tr = view.state.tr.replaceSelection(slice); + view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); } }); @@ -724,6 +784,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; @@ -747,9 +808,14 @@ 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)) { - + // if !guid, then generate guid and apply to full doc + if (!guid) { + console.log('making new guid!'); // hehheehhehehe + linkDoc.guid = Utils.GenerateGuid(); + } DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((jumpToDoc === linkDoc.anchor2 ? linkDoc.anchor2Page : linkDoc.anchor1Page))); return; } |