diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/DocumentManager.ts | 2 | ||||
-rw-r--r-- | src/client/util/RichTextRules.ts | 20 | ||||
-rw-r--r-- | src/client/util/RichTextSchema.tsx | 10 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 13 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBoxComment.tsx | 19 |
6 files changed, 41 insertions, 25 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index d491cd1b1..07247b7e9 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -194,6 +194,8 @@ export class DocumentManager { const target = linkFollowDocs[reverse ? 1 : 0]; target.currentTimecode !== undefined && (target.currentTimecode = linkFollowTimecodes[reverse ? 1 : 0]); DocumentManager.Instance.jumpToDocument(linkFollowDocs[reverse ? 1 : 0], zoom, (doc: Doc) => focus(doc, maxLocation), targetContext, linkDoc[Id]); + } else if (link) { + DocumentManager.Instance.jumpToDocument(link, zoom, (doc: Doc) => focus(doc, "onRight"), undefined, undefined); } } diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index 94bfc5ef2..c69112b3b 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -6,8 +6,10 @@ import { NumCast, Cast } from "../../new_fields/Types"; import { Doc } from "../../new_fields/Doc"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; import { TooltipTextMenuManager } from "../util/TooltipTextMenu"; -import { Docs } from "../documents/Documents"; +import { Docs, DocUtils } from "../documents/Documents"; import { Id } from "../../new_fields/FieldSymbols"; +import { DocServer } from "../DocServer"; +import { returnFalse, Utils } from "../../Utils"; export const inpRules = { rules: [ @@ -173,6 +175,22 @@ export const inpRules = { return node ? state.tr.addMark(start, end, schema.marks.user_tag.create({ userid: Doc.CurrentUserEmail, tag: "disagree", modified: Math.round(Date.now() / 1000 / 60) })) : state.tr; }), new InputRule( + new RegExp(/@$/), + (state, match, start, end) => { + if (state.selection.to === state.selection.from) return null; + + const value = state.doc.textBetween(start, end); + if (value) { + DocServer.GetRefField(value).then(docx => { + let doc = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([], { title: value, width: 500, height: 500 }, value); + DocUtils.Publish(doc, value, returnFalse, returnFalse); + }); + const link = state.schema.marks.link.create({ href: Utils.prepend("/doc/" + value), location: "onRight", title: value }); + return state.tr.addMark(start, end, link); + } + return state.tr; + }), + new InputRule( new RegExp(/^\^\^\s$/), (state, match, start, end) => { const node = (state.doc.resolve(start) as any).nodeAfter; diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index fac8f4027..c6314bc30 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -462,7 +462,6 @@ export const marks: { [index: string]: MarkSpec } = { user_mark: { attrs: { userid: { default: "" }, - opened: { default: true }, modified: { default: "when?" }, // 5 second intervals since 1970 }, group: "inline", @@ -472,16 +471,13 @@ export const marks: { [index: string]: MarkSpec } = { const hr = Math.round(min / 60); const day = Math.round(hr / 60 / 24); const remote = node.attrs.userid !== Doc.CurrentUserEmail ? " userMark-remote" : ""; - return node.attrs.opened ? - ['span', { class: "userMark-" + uid + remote + " userMark-min-" + min + " userMark-hr-" + hr + " userMark-day-" + day }, 0] : - ['span', { class: "userMark-" + uid + remote + " userMark-min-" + min + " userMark-hr-" + hr + " userMark-day-" + day }, ['span', 0]]; + return ['span', { class: "userMark-" + uid + remote + " userMark-min-" + min + " userMark-hr-" + hr + " userMark-day-" + day }, 0]; } }, // the id of the user who entered the text user_tag: { attrs: { userid: { default: "" }, - opened: { default: true }, modified: { default: "when?" }, // 5 second intervals since 1970 tag: { default: "" } }, @@ -489,9 +485,7 @@ export const marks: { [index: string]: MarkSpec } = { inclusive: false, toDOM(node: any) { const uid = node.attrs.userid.replace(".", "").replace("@", ""); - return node.attrs.opened ? - ['span', { class: "userTag-" + uid + " userTag-" + node.attrs.tag }, 0] : - ['span', { class: "userTag-" + uid + " userTag-" + node.attrs.tag }, ['span', 0]]; + return ['span', { class: "userTag-" + uid + " userTag-" + node.attrs.tag }, 0]; } }, diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 727d631c4..24cc0b5ea 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -644,7 +644,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu contents={this.Document[showTitle]} display={"block"} height={72} fontSize={12} GetValue={() => StrCast(this.Document[showTitle])} - SetValue={(value: string) => (Doc.GetProto(this.Document)[showTitle] = value) ? true : true} + SetValue={undoBatch((value: string) => (Doc.GetProto(this.Document)[showTitle] = value) ? true : true)} /> </div>); return <> diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 70fa4974d..9318142e2 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -184,7 +184,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this.linkOnDeselect.set(key, value); const id = Utils.GenerateDeterministicGuid(this.dataDoc[Id] + key); - const link = this._editorView.state.schema.marks.link.create({ href: `http://localhost:1050/doc/${id}`, location: "onRight", title: value }); + const link = this._editorView.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + id), location: "onRight", title: value }); const mval = this._editorView.state.schema.marks.metadataVal.create(); const offset = (tx.selection.to === range!.end - 1 ? -1 : 0); tx = tx.addMark(textEndSelection - value.length + offset, textEndSelection, link).addMark(textEndSelection - value.length + offset, textEndSelection, mval); @@ -238,9 +238,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._editorView.dispatch(this._editorView.state.tr.removeMark(0, end, mark).removeMark(0, end, activeMark)); } } - setAnnotation = (start: number, end: number, mark: Mark, opened: boolean, keep: boolean = false) => { + adoptAnnotation = (start: number, end: number, mark: Mark) => { const view = this._editorView!; - const nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: keep ? Doc.CurrentUserEmail : mark.attrs.userid, opened: opened }); + const nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: Doc.CurrentUserEmail }); view.dispatch(view.state.tr.removeMark(start, end, nmark).addMark(start, end, nmark)); } protected createDropTarget = (ele: HTMLDivElement) => { @@ -873,6 +873,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & static _downEvent: any; onPointerDown = (e: React.PointerEvent): void => { + this.doLinkOnDeselect(); FormattedTextBox._downEvent = true; FormattedTextBoxComment.textBox = this; if (this.props.onClick && e.button === 0) { @@ -1053,9 +1054,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._undoTyping.end(); this._undoTyping = undefined; } - this.doLinkOnDeselect(); 6 + this.doLinkOnDeselect(); } + _lastTimedMark: Mark | undefined = undefined; onKeyPress = (e: React.KeyboardEvent) => { if (e.altKey) { e.preventDefault(); @@ -1078,7 +1080,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & if (e.key === "Tab" || e.key === "Enter") { e.preventDefault(); } - const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.round(Date.now() / 1000 / 5) }); + const mark = e.key !== " " && this._lastTimedMark ? this._lastTimedMark! : schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.round(Date.now() / 1000 / 5) }); + this._lastTimedMark = mark; this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})).addStoredMark(mark)); if (!this._undoTyping) { diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index 409229c1a..1755cb99c 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -57,7 +57,6 @@ export class FormattedTextBoxComment { static start: number; static end: number; static mark: Mark; - static opened: boolean; static textBox: FormattedTextBox | undefined; static linkDoc: Doc | undefined; constructor(view: any) { @@ -89,10 +88,8 @@ export class FormattedTextBoxComment { } 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 }), undefined, "onRight"); } - FormattedTextBoxComment.opened = keep || !FormattedTextBoxComment.opened; - textBox && FormattedTextBoxComment.start !== undefined && textBox.setAnnotation( - FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark, - FormattedTextBoxComment.opened, keep); + keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation( + FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark); e.stopPropagation(); e.preventDefault(); }; @@ -104,12 +101,11 @@ export class FormattedTextBoxComment { FormattedTextBoxComment.textBox = undefined; FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none"); } - public static SetState(textBox: any, opened: boolean, start: number, end: number, mark: Mark) { + public static SetState(textBox: any, start: number, end: number, mark: Mark) { FormattedTextBoxComment.textBox = textBox; FormattedTextBoxComment.start = start; FormattedTextBoxComment.end = end; FormattedTextBoxComment.mark = mark; - FormattedTextBoxComment.opened = opened; FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = ""); } @@ -143,7 +139,7 @@ export class FormattedTextBoxComment { 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, mark.attrs.opened, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark); + FormattedTextBoxComment.SetState(FormattedTextBoxComment.textBox, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark); } if (mark && child && ((nbef && naft) || !noselection)) { FormattedTextBoxComment.tooltipText.textContent = mark.attrs.userid + " date=" + (new Date(mark.attrs.modified * 5000)).toDateString(); @@ -160,19 +156,22 @@ export class FormattedTextBoxComment { const mark = child && findLinkMark(child.marks); if (mark && child && nbef && naft) { FormattedTextBoxComment.tooltipText.textContent = "external => " + mark.attrs.href; + (FormattedTextBoxComment.tooltipText as any).href = mark.attrs.href; if (mark.attrs.href.startsWith("https://en.wikipedia.org/wiki/")) { wiki().page(mark.attrs.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"; } - (FormattedTextBoxComment.tooltipText as any).href = mark.attrs.href; if (mark.attrs.href.indexOf(Utils.prepend("/doc/")) === 0) { + FormattedTextBoxComment.tooltipText.textContent = "target not found..."; + (FormattedTextBoxComment.tooltipText as any).href = ""; const docTarget = mark.attrs.href.replace(Utils.prepend("/doc/"), "").split("?")[0]; docTarget && DocServer.GetRefField(docTarget).then(linkDoc => { if (linkDoc instanceof Doc) { + (FormattedTextBoxComment.tooltipText as any).href = mark.attrs.href; FormattedTextBoxComment.linkDoc = linkDoc; - const target = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.props.Document) ? Cast(linkDoc.anchor2, Doc) : Cast(linkDoc.anchor1, Doc)); + const target = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.props.Document) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc); try { ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText); } catch (e) { } |