diff options
-rw-r--r-- | src/client/util/DragManager.ts | 1 | ||||
-rw-r--r-- | src/client/views/DocumentButtonBar.tsx | 9 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentContentsView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 7 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 29 |
5 files changed, 42 insertions, 8 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 63a11c85a..8d3f6751e 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -148,6 +148,7 @@ export namespace DragManager { linkSourceDocument: Doc; dontClearTextBox?: boolean; linkDocument?: Doc; + linkDropCallback?: (data: LinkDragData) => void; } export class ColumnDragData { constructor(colKey: SchemaHeaderField) { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index b0c701b65..b95cc6627 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -4,12 +4,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../new_fields/Doc"; -import { Id } from '../../new_fields/FieldSymbols'; import { RichTextField } from '../../new_fields/RichTextField'; import { NumCast, StrCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; -import RichTextMenu from '../util/RichTextMenu'; import { UndoManager } from "../util/UndoManager"; import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView'; import { ParentDocSelector } from './collections/ParentDocumentSelector'; @@ -121,10 +119,9 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop if (this.view0 && linkDoc) { Doc.GetProto(linkDoc).linkRelationship = "hyperlink"; - - const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-"; - const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : ""; - const text = RichTextMenu.Instance.MakeLinkToSelection(linkDoc[Id], anchor2Title, e.ctrlKey ? "onRight" : "inTab", anchor2Id); + dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData); + runInAction(() => this.view0!._link = linkDoc); + setTimeout(action(() => this.view0!._link = undefined), 0); } linkDrag?.end(); }, diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index c250da874..da035a6ce 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -58,7 +58,9 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & { select: (ctrl: boolean) => void, layoutKey: string, forceLayout?: string, - forceFieldKey?: string + forceFieldKey?: string, + hideOnLeave?:boolean, + makeLink?: () => Opt<Doc>; }> { @computed get layout(): string { TraceMobx(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7770a5caf..d8bbd88ce 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -40,7 +40,6 @@ import { ScriptBox } from '../ScriptBox'; import { ScriptingRepl } from '../ScriptingRepl'; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; -import { FormattedTextBox } from './FormattedTextBox'; import React = require("react"); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { SchemaHeaderField } from '../../../new_fields/SchemaHeaderField'; @@ -967,6 +966,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu Document={this.props.Document} DataDoc={this.props.DataDoc} LayoutDoc={this.props.LayoutDoc} + makeLink={this.makeLink} fitToBox={this.props.fitToBox} LibraryPath={this.props.LibraryPath} addDocument={this.props.addDocument} @@ -1002,6 +1002,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu const ept = Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? linkDoc.anchor1_timecode : linkDoc.anchor2_timecode; return anchor.type === DocumentType.AUDIO && NumCast(ept) ? false : true; } +c + @observable _link:Opt<Doc>; + makeLink = () => { + return this._link; + } @computed get innards() { TraceMobx(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index bc43beab9..241345f3e 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -54,6 +54,7 @@ library.add(faSmile, faTextHeight, faUpload); export interface FormattedTextBoxProps { hideOnLeave?: boolean; + makeLink?: () => Opt<Doc>; } const richTextSchema = createSchema({ @@ -91,6 +92,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & private _pullReactionDisposer: Opt<IReactionDisposer>; private _pushReactionDisposer: Opt<IReactionDisposer>; private _buttonBarReactionDisposer: Opt<IReactionDisposer>; + private _linkMakerDisposer: Opt<IReactionDisposer>; private _scrollDisposer: Opt<IReactionDisposer>; private dropDisposer?: DragManager.DragDropDisposer; @@ -282,8 +284,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.stopPropagation(); // } } // otherwise, fall through to outer collection to handle drop + } else if (de.complete.linkDragData) { + de.complete.linkDragData.linkDropCallback = this.linkDrop; } } + linkDrop = (data: DragManager.LinkDragData) => { + const linkDoc = data.linkDocument!; + const anchor1Title = linkDoc.anchor1 instanceof Doc ? StrCast(linkDoc.anchor1.title) : "-untitled-"; + const anchor1Id = linkDoc.anchor1 instanceof Doc ? linkDoc.anchor1[Id] : ""; + this.makeLinkToSelection(linkDoc[Id], anchor1Title, "onRight", anchor1Id) + } getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null { let offset = 0; @@ -513,6 +523,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & }; } + makeLinkToSelection(linkDocId: string, title: string, location: string, targetDocId: string) { + if (this._editorView) { + const link = this._editorView.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId }); + this._editorView.dispatch(this._editorView.state.tr.removeMark(this._editorView.state.selection.from, this._editorView.state.selection.to, this._editorView.state.schema.marks.link). + addMark(this._editorView.state.selection.from, this._editorView.state.selection.to, link)); + } + } componentDidMount() { this._buttonBarReactionDisposer = reaction( () => DocumentButtonBar.Instance, @@ -523,6 +540,17 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } } ); + this._linkMakerDisposer = reaction( + () => this.props.makeLink?.(), + (linkDoc: Opt<Doc>) => { + if (linkDoc) { + const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-"; + const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : ""; + this.makeLinkToSelection(linkDoc[Id], anchor2Title, "onRight", anchor2Id); + } + }, + { fireImmediately: true } + ); this._reactionDisposer = reaction( () => { @@ -858,6 +886,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._searchReactionDisposer?.(); this._recordReactionDisposer?.(); this._buttonBarReactionDisposer?.(); + this._linkMakerDisposer?.(); this._editorView?.destroy(); } |