diff options
author | Safae Merigh <safae_merigh@brown.edu> | 2020-05-27 23:41:18 +0000 |
---|---|---|
committer | Safae Merigh <safae_merigh@brown.edu> | 2020-05-27 23:41:18 +0000 |
commit | b8aa8800236972ed9325d5eede4fdc37a8e561c0 (patch) | |
tree | 00d0470ba2bbc6533dd2a977d2b8059f119ecde0 /src | |
parent | 9bd24940bda0544e65ff53ed7da02314ee6d31b6 (diff) |
isolated files. Only DashDocView left.
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/formattedText/RichTextSchema.tsx | 439 |
1 files changed, 88 insertions, 351 deletions
diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx index 91280dea4..f6bc858da 100644 --- a/src/client/views/nodes/formattedText/RichTextSchema.tsx +++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx @@ -26,163 +26,69 @@ import { DocumentManager } from "../../../util/DocumentManager"; import { Transform } from "../../../util/Transform"; import React = require("react"); -import { schema } from "./schema_rts"; -export class OrderedListView { - update(node: any) { - return false; // if attr's of an ordered_list (e.g., bulletStyle) change, return false forces the dom node to be recreated which is necessary for the bullet labels to update - } -} - -export class ImageResizeView { - _handle: HTMLElement; - _img: HTMLElement; - _outer: HTMLElement; - constructor(node: any, view: any, getPos: any, addDocTab: any) { - //moved - this._handle = document.createElement("span"); - this._img = document.createElement("img"); - this._outer = document.createElement("span"); - this._outer.style.position = "relative"; - this._outer.style.width = node.attrs.width; - this._outer.style.height = node.attrs.height; - this._outer.style.display = "inline-block"; - this._outer.style.overflow = "hidden"; - (this._outer.style as any).float = node.attrs.float; - //moved - this._img.setAttribute("src", node.attrs.src); - this._img.style.width = "100%"; - this._handle.style.position = "absolute"; - this._handle.style.width = "20px"; - this._handle.style.height = "20px"; - this._handle.style.backgroundColor = "blue"; - this._handle.style.borderRadius = "15px"; - this._handle.style.display = "none"; - this._handle.style.bottom = "-10px"; - this._handle.style.right = "-10px"; - const self = this; - //moved - this._img.onclick = function (e: any) { - e.stopPropagation(); - e.preventDefault(); - if (view.state.selection.node && view.state.selection.node.type !== view.state.schema.nodes.image) { - view.dispatch(view.state.tr.setSelection(new NodeSelection(view.state.doc.resolve(view.state.selection.from - 2)))); - } - }; - //moved - this._img.onpointerdown = function (e: any) { - if (e.ctrlKey) { - e.preventDefault(); - e.stopPropagation(); - DocServer.GetRefField(node.attrs.docid).then(async linkDoc => - (linkDoc instanceof Doc) && - DocumentManager.Instance.FollowLink(linkDoc, view.state.schema.Document, - document => addDocTab(document, node.attrs.location ? node.attrs.location : "inTab"), false)); - } - }; - //moved - this._handle.onpointerdown = function (e: any) { - e.preventDefault(); - e.stopPropagation(); - const wid = Number(getComputedStyle(self._img).width.replace(/px/, "")); - const hgt = Number(getComputedStyle(self._img).height.replace(/px/, "")); - const startX = e.pageX; - const startWidth = parseFloat(node.attrs.width); - const onpointermove = (e: any) => { - const currentX = e.pageX; - const diffInPx = currentX - startX; - self._outer.style.width = `${startWidth + diffInPx}`; - self._outer.style.height = `${(startWidth + diffInPx) * hgt / wid}`; - }; - - const onpointerup = () => { - document.removeEventListener("pointermove", onpointermove); - document.removeEventListener("pointerup", onpointerup); - const pos = view.state.selection.from; - view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: self._outer.style.width, height: self._outer.style.height })); - view.dispatch(view.state.tr.setSelection(new NodeSelection(view.state.doc.resolve(pos)))); - }; - - document.addEventListener("pointermove", onpointermove); - document.addEventListener("pointerup", onpointerup); - }; - //Moved - this._outer.appendChild(this._img); - this._outer.appendChild(this._handle); - (this as any).dom = this._outer; - } - - selectNode() { - this._img.classList.add("ProseMirror-selectednode"); - - this._handle.style.display = ""; - } - - deselectNode() { - this._img.classList.remove("ProseMirror-selectednode"); - this._handle.style.display = "none"; - } -} - -export class DashDocCommentView { - _collapsed: HTMLElement; - _view: any; - constructor(node: any, view: any, getPos: any) { - //moved - this._collapsed = document.createElement("span"); - this._collapsed.className = "formattedTextBox-inlineComment"; - this._collapsed.id = "DashDocCommentView-" + node.attrs.docid; - this._view = view; - //moved - const targetNode = () => { // search forward in the prosemirror doc for the attached dashDocNode that is the target of the comment anchor - for (let i = getPos() + 1; i < view.state.doc.content.size; i++) { - const m = view.state.doc.nodeAt(i); - if (m && m.type === view.state.schema.nodes.dashDoc && m.attrs.docid === node.attrs.docid) { - return { node: m, pos: i, hidden: m.attrs.hidden } as { node: any, pos: number, hidden: boolean }; - } - } - const dashDoc = view.state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: node.attrs.docid, float: "right" }); - view.dispatch(view.state.tr.insert(getPos() + 1, dashDoc)); - setTimeout(() => { try { view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos() + 2))); } catch (e) { } }, 0); - return undefined; - }; - //moved - this._collapsed.onpointerdown = (e: any) => { - e.stopPropagation(); - }; - //moved - this._collapsed.onpointerup = (e: any) => { - const target = targetNode(); - if (target) { - const expand = target.hidden; - const tr = view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true }); - view.dispatch(tr.setSelection(TextSelection.create(tr.doc, getPos() + (expand ? 2 : 1)))); // update the attrs - setTimeout(() => { - expand && DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); - try { view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos() + (expand ? 2 : 1)))); } catch (e) { } - }, 0); - } - e.stopPropagation(); - }; - //moved - this._collapsed.onpointerenter = (e: any) => { - DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); - e.preventDefault(); - e.stopPropagation(); - }; - //moved - this._collapsed.onpointerleave = (e: any) => { - DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); - e.preventDefault(); - e.stopPropagation(); - }; - - (this as any).dom = this._collapsed; - } - //moved - selectNode() { } -} +// export class DashDocCommentView { +// _collapsed: HTMLElement; +// _view: any; +// constructor(node: any, view: any, getPos: any) { + +// console.log("DashDocCommentView constructor"); + +// //moved +// this._collapsed = document.createElement("span"); +// this._collapsed.className = "formattedTextBox-inlineComment"; +// this._collapsed.id = "DashDocCommentView-" + node.attrs.docid; +// this._view = view; +// //moved +// const targetNode = () => { // search forward in the prosemirror doc for the attached dashDocNode that is the target of the comment anchor +// for (let i = getPos() + 1; i < view.state.doc.content.size; i++) { +// const m = view.state.doc.nodeAt(i); +// if (m && m.type === view.state.schema.nodes.dashDoc && m.attrs.docid === node.attrs.docid) { +// return { node: m, pos: i, hidden: m.attrs.hidden } as { node: any, pos: number, hidden: boolean }; +// } +// } +// const dashDoc = view.state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: node.attrs.docid, float: "right" }); +// view.dispatch(view.state.tr.insert(getPos() + 1, dashDoc)); +// setTimeout(() => { try { view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos() + 2))); } catch (e) { } }, 0); +// return undefined; +// }; +// //moved +// this._collapsed.onpointerdown = (e: any) => { +// e.stopPropagation(); +// }; +// //moved +// this._collapsed.onpointerup = (e: any) => { +// const target = targetNode(); +// if (target) { +// const expand = target.hidden; +// const tr = view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true }); +// view.dispatch(tr.setSelection(TextSelection.create(tr.doc, getPos() + (expand ? 2 : 1)))); // update the attrs +// setTimeout(() => { +// expand && DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); +// try { view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos() + (expand ? 2 : 1)))); } catch (e) { } +// }, 0); +// } +// e.stopPropagation(); +// }; +// //moved +// this._collapsed.onpointerenter = (e: any) => { +// DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); +// e.preventDefault(); +// e.stopPropagation(); +// }; +// //moved +// this._collapsed.onpointerleave = (e: any) => { +// DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); +// e.preventDefault(); +// e.stopPropagation(); +// }; + +// (this as any).dom = this._collapsed; +// } +// //moved +// selectNode() { } +// } export class DashDocView { _dashSpan: HTMLDivElement; @@ -192,16 +98,22 @@ export class DashDocView { _renderDisposer: IReactionDisposer | undefined; _textBox: FormattedTextBox; + //moved getDocTransform = () => { const { scale, translateX, translateY } = Utils.GetScreenTransform(this._outer); return new Transform(-translateX, -translateY, 1).scale(1 / this.contentScaling() / scale); } + + //moved contentScaling = () => NumCast(this._dashDoc!._nativeWidth) > 0 ? this._dashDoc![WidthSym]() / NumCast(this._dashDoc!._nativeWidth) : 1; + //moved outerFocus = (target: Doc) => this._textBox.props.focus(this._textBox.props.Document); // ideally, this would scroll to show the focus target constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) { + //moved this._textBox = tbox; + this._dashSpan = document.createElement("div"); this._outer = document.createElement("span"); this._outer.style.position = "relative"; @@ -218,28 +130,42 @@ export class DashDocView { this._dashSpan.style.position = "absolute"; this._dashSpan.style.display = "inline-block"; this._dashSpan.style.whiteSpace = "normal"; + this._dashSpan.onpointerleave = () => { + + console.log("DashDocView_dashSpan.onpointerleave"); // SMM + console.log("DashDocCommentView-id=", node.attrs.docid); // SMM + const ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); if (ele) { (ele as HTMLDivElement).style.backgroundColor = ""; } }; + this._dashSpan.onpointerenter = () => { + console.log("DashDocView_dashSpan.onpointerenter"); // SMM + console.log("DashDocCommentView-id=", node.attrs.docid); // SMM + const ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); if (ele) { (ele as HTMLDivElement).style.backgroundColor = "orange"; } }; + const removeDoc = () => { + console.log("DashDocView.removeDoc"); // SMM const pos = getPos(); const ns = new NodeSelection(view.state.doc.resolve(pos)); view.dispatch(view.state.tr.setSelection(ns).deleteSelection()); return true; }; - const alias = node.attrs.alias; + const alias = node.attrs.alias; + const self = this; const docid = node.attrs.docid || tbox.props.Document[Id];// tbox.props.DataDoc?.[Id] || tbox.dataDoc?.[Id]; + DocServer.GetRefField(docid + alias).then(async dashDoc => { + if (!(dashDoc instanceof Doc)) { alias && DocServer.GetRefField(docid).then(async dashDocBase => { if (dashDocBase instanceof Doc) { @@ -253,7 +179,8 @@ export class DashDocView { self.doRender(dashDoc, removeDoc, node, view, getPos); } }); - const self = this; + + this._dashSpan.onkeydown = function (e: any) { e.stopPropagation(); if (e.key === "Tab" || e.key === "Enter") { @@ -281,6 +208,7 @@ export class DashDocView { this._dashSpan.style.height = this._outer.style.height = Math.max(20, dim[1]) + "px"; this._outer.style.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeWorkspace, Doc, null).darkScheme ? "dimGray" : "lightGray")); }, { fireImmediately: true }); + const doReactRender = (finalLayout: Doc, resolvedDataDoc: Doc) => { ReactDOM.unmountComponentAtNode(this._dashSpan); @@ -310,6 +238,7 @@ export class DashDocView { ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc} ContentScaling={this.contentScaling} />, this._dashSpan); + if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") { try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" })); @@ -318,6 +247,7 @@ export class DashDocView { } } }; + this._renderDisposer?.(); this._renderDisposer = reaction(() => { // if (!Doc.AreProtosEqual(finalLayout, dashDoc)) { @@ -337,202 +267,9 @@ export class DashDocView { { fireImmediately: true }); } } + destroy() { ReactDOM.unmountComponentAtNode(this._dashSpan); this._reactionDisposer?.(); } } - -export class FootnoteView { - innerView: any; - outerView: any; - node: any; - dom: any; - getPos: any; - - constructor(node: any, view: any, getPos: any) { - // We'll need these later - this.node = node; - this.outerView = view; - this.getPos = getPos; - - // The node's representation in the editor (empty, for now) - this.dom = document.createElement("footnote"); - this.dom.addEventListener("pointerup", this.toggle, true); - // These are used when the footnote is selected - this.innerView = null; - } - selectNode() { - const attrs = { ...this.node.attrs }; - attrs.visibility = true; - this.dom.classList.add("ProseMirror-selectednode"); - if (!this.innerView) this.open(); - } - - deselectNode() { - const attrs = { ...this.node.attrs }; - attrs.visibility = false; - this.dom.classList.remove("ProseMirror-selectednode"); - if (this.innerView) this.close(); - } - open() { - // Append a tooltip to the outer node - const tooltip = this.dom.appendChild(document.createElement("div")); - tooltip.className = "footnote-tooltip"; - // And put a sub-ProseMirror into that - this.innerView = new EditorView(tooltip, { - // You can use any node as an editor document - state: EditorState.create({ - doc: this.node, - plugins: [keymap(baseKeymap), - keymap({ - "Mod-z": () => undo(this.outerView.state, this.outerView.dispatch), - "Mod-y": () => redo(this.outerView.state, this.outerView.dispatch), - "Mod-b": toggleMark(schema.marks.strong) - }), - // new Plugin({ - // view(newView) { - // // TODO -- make this work with RichTextMenu - // // return FormattedTextBox.getToolTip(newView); - // } - // }) - ], - - }), - // This is the magic part - dispatchTransaction: this.dispatchInner.bind(this), - handleDOMEvents: { - pointerdown: ((view: any, e: PointerEvent) => { - // Kludge to prevent issues due to the fact that the whole - // footnote is node-selected (and thus DOM-selected) when - // the parent editor is focused. - e.stopPropagation(); - document.addEventListener("pointerup", this.ignore, true); - if (this.outerView.hasFocus()) this.innerView.focus(); - }) as any - } - - }); - setTimeout(() => this.innerView && this.innerView.docView.setSelection(0, 0, this.innerView.root, true), 0); - } - - ignore = (e: PointerEvent) => { - e.stopPropagation(); - document.removeEventListener("pointerup", this.ignore, true); - } - - toggle = () => { - if (this.innerView) this.close(); - else { - this.open(); - } - } - close() { - this.innerView && this.innerView.destroy(); - this.innerView = null; - this.dom.textContent = ""; - } - - dispatchInner(tr: any) { - const { state, transactions } = this.innerView.state.applyTransaction(tr); - this.innerView.updateState(state); - - if (!tr.getMeta("fromOutside")) { - const outerTr = this.outerView.state.tr, offsetMap = StepMap.offset(this.getPos() + 1); - for (const transaction of transactions) { - const steps = transaction.steps; - for (const step of steps) { - outerTr.step(step.map(offsetMap)); - } - } - if (outerTr.docChanged) this.outerView.dispatch(outerTr); - } - } - update(node: any) { - if (!node.sameMarkup(this.node)) return false; - this.node = node; - if (this.innerView) { - const state = this.innerView.state; - const start = node.content.findDiffStart(state.doc.content); - if (start !== null) { - let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content); - const overlap = start - Math.min(endA, endB); - if (overlap > 0) { endA += overlap; endB += overlap; } - this.innerView.dispatch( - state.tr - .replace(start, endB, node.slice(start, endA)) - .setMeta("fromOutside", true)); - } - } - return true; - } - - destroy() { - if (this.innerView) this.close(); - } - - stopEvent(event: any) { - return this.innerView && this.innerView.dom.contains(event.target); - } - - ignoreMutation() { return true; } -} - -export class SummaryView { - _collapsed: HTMLElement; - _view: any; - constructor(node: any, view: any, getPos: any) { - this._collapsed = document.createElement("span"); - this._collapsed.className = this.className(node.attrs.visibility); - this._view = view; - const js = node.toJSON; - node.toJSON = function () { - return js.apply(this, arguments); - }; - - this._collapsed.onpointerdown = (e: any) => { - const visible = !node.attrs.visibility; - const attrs = { ...node.attrs, visibility: visible }; - let textSelection = TextSelection.create(view.state.doc, getPos() + 1); - if (!visible) { // update summarized text and save in attrs - textSelection = this.updateSummarizedText(getPos() + 1); - attrs.text = textSelection.content(); - attrs.textslice = attrs.text.toJSON(); - } - view.dispatch(view.state.tr. - setSelection(textSelection). // select the current summarized text (or where it will be if its collapsed) - replaceSelection(!visible ? new Slice(Fragment.fromArray([]), 0, 0) : node.attrs.text). // collapse/expand it - setNodeMarkup(getPos(), undefined, attrs)); // update the attrs - e.preventDefault(); - e.stopPropagation(); - this._collapsed.className = this.className(visible); - }; - (this as any).dom = this._collapsed; - } - selectNode() { } - - deselectNode() { } - - className = (visible: boolean) => "formattedTextBox-summarizer" + (visible ? "" : "-collapsed"); - - updateSummarizedText(start?: any) { - const mtype = this._view.state.schema.marks.summarize; - const mtypeInc = this._view.state.schema.marks.summarizeInclusive; - let endPos = start; - - const visited = new Set(); - for (let i: number = start + 1; i < this._view.state.doc.nodeSize - 1; i++) { - let skip = false; - this._view.state.doc.nodesBetween(start, i, (node: Node, pos: number, parent: Node, index: number) => { - if (node.isLeaf && !visited.has(node) && !skip) { - if (node.marks.find((m: any) => m.type === mtype || m.type === mtypeInc)) { - visited.add(node); - endPos = i + node.nodeSize - 1; - } - else skip = true; - } - }); - } - return TextSelection.create(this._view.state.doc, start, endPos); - } -}
\ No newline at end of file |