From b8fd7bee09ad06ca6ae8fb9e607bf54ca42d0fad Mon Sep 17 00:00:00 2001 From: kimdahey Date: Wed, 27 Nov 2019 16:45:57 -0500 Subject: committing:w --- src/client/views/nodes/FormattedTextBox.scss | 45 +++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 77cdd3d42..ab4a08d62 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -50,6 +50,7 @@ width: 100%; height: 100%; } + .formattedTextBox-sidebar-handle { position: absolute; top: calc(50% - 17.5px); @@ -58,19 +59,23 @@ background: lightgray; border-radius: 20px; } -.formattedTextBox-cont > .formattedTextBox-sidebar-handle { + +.formattedTextBox-cont>.formattedTextBox-sidebar-handle { right: 0; left: unset; } -.formattedTextBox-sidebar, .formattedTextBox-sidebar-inking { - border-left: dashed 1px black; - height: 100%; + +.formattedTextBox-sidebar, +.formattedTextBox-sidebar-inking { + border-left: dashed 1px black; + height: 100%; display: inline-block; position: absolute; right: 0; - > .formattedTextBox-sidebar-handle { - right:unset; - left:-5; + + >.formattedTextBox-sidebar-handle { + right: unset; + left: -5; } } @@ -222,7 +227,7 @@ footnote::after { } ; - font-size: 24; + font-size: 18; ul, ol { @@ -238,7 +243,7 @@ footnote::after { } ; - font-size: 18; + font-size: 14; ul, ol { @@ -254,7 +259,7 @@ footnote::after { } ; - font-size: 14; + font-size: 12; ul, ol { @@ -360,70 +365,70 @@ footnote::after { } .decimal1:before { - content: counter(deci1) ") "; + content: counter(deci1) ". "; counter-increment: deci1; display: inline-block; min-width: 30; } .decimal2:before { - content: counter(deci1) "."counter(deci2) ") "; + content: counter(deci1) "."counter(deci2) ". "; counter-increment: deci2; display: inline-block; min-width: 35 } .decimal3:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) ") "; + content: counter(deci1) "."counter(deci2) "."counter(deci3) ". "; counter-increment: deci3; display: inline-block; min-width: 35 } .decimal4:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) ") "; + content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) ". "; counter-increment: deci4; display: inline-block; min-width: 40 } .decimal5:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) ") "; + content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) ". "; counter-increment: deci5; display: inline-block; min-width: 40 } .decimal6:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) ") "; + content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) ". "; counter-increment: deci6; display: inline-block; min-width: 45 } .decimal7:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) "."counter(deci7) ") "; + content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) "."counter(deci7) ". "; counter-increment: deci7; display: inline-block; min-width: 50 } .upper-alpha:before { - content: counter(deci1) "."counter(ualph, upper-alpha) ") "; + content: counter(deci1) "."counter(ualph, upper-alpha) ". "; counter-increment: ualph; display: inline-block; min-width: 35 } .lower-roman:before { - content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) ") "; + content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) ". "; counter-increment: lroman; display: inline-block; min-width: 50 } .lower-alpha:before { - content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) "."counter(lalpha, lower-alpha) ") "; + content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) "."counter(lalpha, lower-alpha) ". "; counter-increment: lalpha; display: inline-block; min-width: 35 -- cgit v1.2.3-70-g09d2 From cb8d81b4a0963004ecc60122783716ce8a587d0b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 27 Nov 2019 18:39:20 -0500 Subject: a couple of fixes for bulleted text list interactions. --- src/client/views/nodes/FormattedTextBox.scss | 241 +++------------------------ src/client/views/nodes/FormattedTextBox.tsx | 27 +-- 2 files changed, 42 insertions(+), 226 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index ab4a08d62..984d51791 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -31,8 +31,8 @@ flex-direction: row; .formattedTextBox-dictation { - height: 20px; - width: 20px; + height: 12px; + width: 10px; top: 0px; left: 0px; position: absolute; @@ -219,218 +219,27 @@ footnote::after { padding-left: 0px; } - .decimal1-ol { - counter-reset: deci1; - - p { - display: inline - } - - ; - font-size: 18; - - ul, - ol { - padding-left: 30px; - } - } - - .decimal2-ol { - counter-reset: deci2; - - p { - display: inline - } - - ; - font-size: 14; - - ul, - ol { - padding-left: 30px; - } - } - - .decimal3-ol { - counter-reset: deci3; - - p { - display: inline - } - - ; - font-size: 12; - - ul, - ol { - padding-left: 30px; - } - } - - .decimal4-ol { - counter-reset: deci4; - - p { - display: inline - } - - ; - font-size: 10; - - ul, - ol { - padding-left: 30px; - } - } - - .decimal5-ol { - counter-reset: deci5; - - p { - display: inline - } - - ; - font-size: 10; - - ul, - ol { - padding-left: 30px; - } - } - - .decimal6-ol { - counter-reset: deci6; - - p { - display: inline - } - - ; - font-size: 10; - - ul, - ol { - padding-left: 30px; - } - } - - .decimal7-ol { - counter-reset: deci7; - - p { - display: inline - } - - ; - font-size: 10; - - ul, - ol { - padding-left: 30px; - } - } - - .upper-alpha-ol { - counter-reset: ualph; - - p { - display: inline - } - - ; - font-size: 18; - } - - .lower-roman-ol { - counter-reset: lroman; - - p { - display: inline - } - - ; - font-size: 14; - } - - .lower-alpha-ol { - counter-reset: lalpha; - - p { - display: inline - } - - ; - font-size: 10; - } - - .decimal1:before { - content: counter(deci1) ". "; - counter-increment: deci1; - display: inline-block; - min-width: 30; - } - - .decimal2:before { - content: counter(deci1) "."counter(deci2) ". "; - counter-increment: deci2; - display: inline-block; - min-width: 35 - } - - .decimal3:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) ". "; - counter-increment: deci3; - display: inline-block; - min-width: 35 - } - - .decimal4:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) ". "; - counter-increment: deci4; - display: inline-block; - min-width: 40 - } - - .decimal5:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) ". "; - counter-increment: deci5; - display: inline-block; - min-width: 40 - } - - .decimal6:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) ". "; - counter-increment: deci6; - display: inline-block; - min-width: 45 - } - - .decimal7:before { - content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) "."counter(deci7) ". "; - counter-increment: deci7; - display: inline-block; - min-width: 50 - } - - .upper-alpha:before { - content: counter(deci1) "."counter(ualph, upper-alpha) ". "; - counter-increment: ualph; - display: inline-block; - min-width: 35 - } - - .lower-roman:before { - content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) ". "; - counter-increment: lroman; - display: inline-block; - min-width: 50 - } - - .lower-alpha:before { - content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) "."counter(lalpha, lower-alpha) ". "; - counter-increment: lalpha; - display: inline-block; - min-width: 35 - } + .decimal1-ol { counter-reset: deci1; p { display: inline }; ul, ol { padding-left: 30px; } } + .decimal2-ol { counter-reset: deci2; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } + .decimal3-ol { counter-reset: deci3; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } + .decimal4-ol { counter-reset: deci4; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } + .decimal5-ol { counter-reset: deci5; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } + .decimal6-ol { counter-reset: deci6; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } + .decimal7-ol { counter-reset: deci7; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } + + .upper-alpha-ol { counter-reset: ualph; p { display: inline}; font-size: smaller; } + .lower-roman-ol { counter-reset: lroman; p { display: inline}; font-size: smaller; } + .lower-alpha-ol { counter-reset: lalpha; p { display: inline}; font-size: smaller; } + + .decimal1:before { counter-increment: deci1; display: inline-block; content: counter(deci1) ". "; } + .decimal2:before { counter-increment: deci2; display: inline-block; content: counter(deci1) "."counter(deci2) ". "; } + .decimal3:before { counter-increment: deci3; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) ". "; } + .decimal4:before { counter-increment: deci4; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) ". "; } + .decimal5:before { counter-increment: deci5; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) ". "; } + .decimal6:before { counter-increment: deci5; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) ". "; } + .decimal7:before { counter-increment: deci5; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) "."counter(deci7) ". "; } + + .upper-alpha:before { counter-increment: ualph; display: inline-block; content: counter(deci1) "."counter(ualph, upper-alpha) ". "; } + .lower-roman:before { counter-increment: lroman; display: inline-block; content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) ". "; } + .lower-alpha:before { counter-increment: lalpha; display: inline-block; content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) "."counter(lalpha, lower-alpha) ". "; } } \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index bad912944..876f390d9 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -919,24 +919,30 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } // this hackiness handles clicking on the list item bullets to do expand/collapse. the bullets are ::before pseudo elements so there's no real way to hit test against them. - hitBulletTargets(x: number, y: number, offsetX: number, select: boolean = false) { + hitBulletTargets(x: number, y: number, offsetX: number, select: boolean, highlightOnly = false) { clearStyleSheetRules(FormattedTextBox._bulletStyleSheet); if (this.props.isSelected(true) && offsetX < 40) { let pos = this._editorView!.posAtCoords({ left: x, top: y }); if (pos && pos.pos > 0) { let node = this._editorView!.state.doc.nodeAt(pos.pos); - let node2 = node && node.type === schema.nodes.paragraph ? this._editorView!.state.doc.nodeAt(pos.pos - 1) : undefined; - if (node === this._nodeClicked && node2 && (node2.type === schema.nodes.ordered_list || node2.type === schema.nodes.list_item)) { + let node2 = node?.type === schema.nodes.paragraph ? this._editorView!.state.doc.nodeAt(pos.pos - 1) : undefined; + if ((node === this._nodeClicked || highlightOnly) && (node2?.type === schema.nodes.ordered_list || node2?.type === schema.nodes.list_item)) { let hit = this._editorView!.domAtPos(pos.pos).node as any; // let beforeEle = document.querySelector("." + hit.className) as Element; let before = hit ? window.getComputedStyle(hit, ':before') : undefined; let beforeWidth = before ? Number(before.getPropertyValue('width').replace("px", "")) : undefined; - if (beforeWidth && offsetX < beforeWidth) { + if (beforeWidth && offsetX < beforeWidth * .9) { let ol = this._editorView!.state.doc.nodeAt(pos.pos - 2) ? this._editorView!.state.doc.nodeAt(pos.pos - 2) : undefined; - if (ol && ol.type === schema.nodes.ordered_list && select) { - this._editorView!.dispatch(this._editorView!.state.tr.setSelection(new NodeSelection(this._editorView!.state.doc.resolve(pos.pos - 2)))); - addStyleSheetRule(FormattedTextBox._bulletStyleSheet, hit.className + ":before", { background: "gray" }); + if (ol?.type === schema.nodes.ordered_list && select) { + if (!highlightOnly) { + this._editorView!.dispatch(this._editorView!.state.tr.setSelection(new NodeSelection(this._editorView!.state.doc.resolve(pos.pos - 2)))); + } + addStyleSheetRule(FormattedTextBox._bulletStyleSheet, hit.className + ":before", { background: "lightgray" }); } else { - this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(pos.pos - 1, node2.type, { ...node2.attrs, visibility: !node2.attrs.visibility })); + if (highlightOnly) { + addStyleSheetRule(FormattedTextBox._bulletStyleSheet, hit.className + ":before", { background: "lightgray" }); + } else { + this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(pos.pos - 1, node2.type, { ...node2.attrs, visibility: !node2.attrs.visibility })); + } } } } @@ -1045,6 +1051,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & onKeyDown={this.onKeyPress} onFocus={this.onFocused} onClick={this.onClick} + onPointerMove={e => this.hitBulletTargets(e.clientX, e.clientY, e.nativeEvent.offsetX, e.shiftKey, true)} onBlur={this.onBlur} onPointerUp={this.onPointerUp} onPointerDown={this.onPointerDown} @@ -1062,10 +1069,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
this.props.PanelHeight()} + PanelHeight={this.props.PanelHeight} PanelWidth={() => this.sidebarWidth} annotationsKey={this.annotationsKey} - isAnnotationOverlay={true} + isAnnotationOverlay={false} focus={this.props.focus} isSelected={this.props.isSelected} select={emptyFunction} -- cgit v1.2.3-70-g09d2 From 1280c005829cf49fd106fd872afcf4ed6593a2f6 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 2 Dec 2019 13:21:59 -0500 Subject: fixed inline text comments to highlight and hide/show. --- src/client/util/RichTextRules.ts | 12 +++--- src/client/util/RichTextSchema.tsx | 64 ++++++++++++++++++++++++++-- src/client/views/nodes/FormattedTextBox.scss | 12 ++++++ src/client/views/nodes/FormattedTextBox.tsx | 5 ++- 4 files changed, 81 insertions(+), 12 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index ebb9bda8a..f4c44e5ce 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -147,16 +147,14 @@ export const inpRules = { new InputRule( new RegExp(/##\s$/), (state, match, start, end) => { + let target = Docs.Create.TextDocument({ width: 75, height: 35, autoHeight: true, fontSize: 9, title: "inline comment" }); let node = (state.doc.resolve(start) as any).nodeAfter; + let newNode = schema.nodes.dashComment.create({ docid: target[Id] }); + let dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); let sm = state.storedMarks || undefined; - let target = Docs.Create.TextDocument({ width: 75, height: 35, autoHeight: true, fontSize: 9, title: "inline comment" }); - let replaced = node ? state.tr.insertText("←", start).replaceRangeWith(start + 1, end + 1, schema.nodes.dashDoc.create({ - width: 75, height: 35, - title: "dashDoc", docid: target[Id], - float: "right" - })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : + let replaced = node ? state.tr.insert(start, newNode).replaceRangeWith(start + 1, end + 1, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; - return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 1))); + return replaced;//.setSelection(new NodeSelection(replaced.doc.resolve(end))); }), new InputRule( new RegExp(/\(\(/), diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 506c9767f..522232e9f 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -107,6 +107,18 @@ export const nodes: { [index: string]: NodeSpec } = { group: "inline" }, + dashComment: { + attrs: { + docid: { default: "" }, + }, + inline: true, + group: "inline", + toDOM(node) { + const attrs = { style: `width: 40px` }; + return ["span", { ...node.attrs, ...attrs }, "←"]; + }, + }, + star: { inline: true, attrs: { @@ -171,7 +183,8 @@ export const nodes: { [index: string]: NodeSpec } = { title: { default: null }, float: { default: "right" }, location: { default: "onRight" }, - docid: { default: "" } + hidden: { default: false }, + docid: { default: "" }, }, group: "inline", draggable: true, @@ -648,6 +661,38 @@ export class ImageResizeView { } } + +export class DashDocCommentView { + _collapsed: HTMLElement; + _view: any; + constructor(node: any, view: any, getPos: any) { + this._collapsed = document.createElement("span"); + this._collapsed.className = "formattedTextBox-inlineComment"; + this._collapsed.id = "DashDocCommentView-" + node.attrs.docid; + this._view = view; + this._collapsed.onpointerdown = (e: any) => { + let node = view.state.doc.nodeAt(getPos() + 1); + view.dispatch(view.state.tr. + setNodeMarkup(getPos() + 1, undefined, { ...node.attrs, hidden: node.attrs.hidden ? false : true })); // update the attrs + setTimeout(() => node.attrs.hidden && DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)), 100); + } + this._collapsed.onpointerenter = (e: any) => { + let node = view.state.doc.nodeAt(getPos() + 1); + DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); + e.preventDefault(); + e.stopPropagation(); + }; + this._collapsed.onpointerleave = (e: any) => { + let node = view.state.doc.nodeAt(getPos() + 1); + DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); + e.preventDefault(); + e.stopPropagation(); + }; + (this as any).dom = this._collapsed; + } + selectNode() { } +} + export class DashDocView { _dashSpan: HTMLDivElement; _outer: HTMLElement; @@ -667,20 +712,33 @@ export class DashDocView { 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.display = node.attrs.hidden ? "none" : "inline-block"; + // this._outer.style.overflow = "hidden"; // bcz: not sure if this is needed. if it's used, then the doc doesn't highlight when you hover over a docComment (this._outer.style as any).float = node.attrs.float; this._dashSpan.style.width = node.attrs.width; this._dashSpan.style.height = node.attrs.height; this._dashSpan.style.position = "absolute"; this._dashSpan.style.display = "inline-block"; + this._dashSpan.style.borderWidth = "4"; let removeDoc = () => { let pos = getPos(); let ns = new NodeSelection(view.state.doc.resolve(pos)); view.dispatch(view.state.tr.setSelection(ns).deleteSelection()); return true; }; + this._dashSpan.onpointerleave = () => { + let ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); + if (ele) { + (ele as HTMLDivElement).style.backgroundColor = ""; + } + } + this._dashSpan.onpointerenter = () => { + let ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); + if (ele) { + (ele as HTMLDivElement).style.backgroundColor = "orange"; + } + } DocServer.GetRefField(node.attrs.docid).then(async dashDoc => { if (dashDoc instanceof Doc) { self._dashDoc = dashDoc; diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 984d51791..4f72bb679 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -189,6 +189,17 @@ footnote::after { width: 0; } + +.formattedTextBox-inlineComment { + position: relative; + width: 40px; + height: 20px; +} + +.formattedTextBox-inlineComment::after { + content: "←"; +} + .formattedTextBox-summarizer { opacity: 0.5; position: relative; @@ -198,6 +209,7 @@ footnote::after { .formattedTextBox-summarizer::after { content: "←"; + font-weight: bold; } .formattedTextBox-summarizer-collapsed { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index c8a629984..a5530f32d 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -27,7 +27,7 @@ import { DictationManager } from '../../util/DictationManager'; import { DragManager } from "../../util/DragManager"; import buildKeymap from "../../util/ProsemirrorExampleTransfer"; import { inpRules } from "../../util/RichTextRules"; -import { FootnoteView, ImageResizeView, DashDocView, OrderedListView, schema, SummarizedView } from "../../util/RichTextSchema"; +import { DashDocCommentView, FootnoteView, ImageResizeView, DashDocView, OrderedListView, schema, SummarizedView } from "../../util/RichTextSchema"; import { SelectionManager } from "../../util/SelectionManager"; import { TooltipLinkingMenu } from "../../util/TooltipLinkingMenu"; import { TooltipTextMenu } from "../../util/TooltipTextMenu"; @@ -787,6 +787,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & }, dispatchTransaction: this.dispatchTransaction, nodeViews: { + dashComment(node, view, getPos) { return new DashDocCommentView(node, view, getPos); }, dashDoc(node, view, getPos) { return new DashDocView(node, view, getPos, self); }, image(node, view, getPos) { return new ImageResizeView(node, view, getPos, self.props.addDocTab); }, star(node, view, getPos) { return new SummarizedView(node, view, getPos); }, @@ -1081,7 +1082,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & whenActiveChanged={this.whenActiveChanged} removeDocument={this.removeDocument} moveDocument={this.moveDocument} - addDocument={(doc:Doc) => { doc.hideSidebar = true; return this.addDocument(doc); }} + addDocument={(doc: Doc) => { doc.hideSidebar = true; return this.addDocument(doc); }} CollectionView={undefined} ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth), 0)} ruleProvider={undefined} -- cgit v1.2.3-70-g09d2 From 59ab8a05866bbf065aa5078029a7bef1ebb708df Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 2 Dec 2019 13:43:08 -0500 Subject: small highlighting fixes to inline text comments. --- src/client/views/nodes/FormattedTextBox.scss | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 4f72bb679..c06f38a6c 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -194,10 +194,12 @@ footnote::after { position: relative; width: 40px; height: 20px; -} - -.formattedTextBox-inlineComment::after { - content: "←"; + &::after { + content: "→"; + } + &:hover { + background: orange; + } } .formattedTextBox-summarizer { @@ -205,11 +207,9 @@ footnote::after { position: relative; width: 40px; height: 20px; -} - -.formattedTextBox-summarizer::after { - content: "←"; - font-weight: bold; + &::after { + content: "←"; + } } .formattedTextBox-summarizer-collapsed { @@ -217,10 +217,9 @@ footnote::after { position: relative; width: 40px; height: 20px; -} - -.formattedTextBox-summarizer-collapsed::after { - content: "..."; + &::after { + content: "..."; + } } .ProseMirror { -- cgit v1.2.3-70-g09d2 From 97a4a9b1cfddc8b147ff61be13624704949c97f7 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 4 Dec 2019 12:50:38 -0500 Subject: tweaks to textbox sidebar. update to passport and npm --- package.json | 4 ++-- src/client/views/nodes/FormattedTextBox.scss | 1 + src/client/views/nodes/FormattedTextBox.tsx | 3 ++- src/server/Initialization.ts | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/package.json b/package.json index 574c7e7fa..32344aad4 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@types/mongoose": "^5.5.8", "@types/node": "^10.12.30", "@types/nodemailer": "^4.6.6", - "@types/passport": "^1.0.0", + "@types/passport": "^1.0.2", "@types/passport-google-oauth20": "^2.0.2", "@types/passport-local": "^1.0.33", "@types/pdfjs-dist": "^2.0.0", @@ -171,7 +171,7 @@ "nodemailer": "^5.1.1", "nodemon": "^1.18.10", "normalize.css": "^8.0.1", - "npm": "^6.12.0", + "npm": "^6.13.2", "p-limit": "^2.2.0", "passport": "^0.4.0", "passport-google-oauth20": "^2.0.0", diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index c06f38a6c..f3a14169a 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -58,6 +58,7 @@ height: 35px; background: lightgray; border-radius: 20px; + cursor:grabbing; } .formattedTextBox-cont>.formattedTextBox-sidebar-handle { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index fcd8b6202..481ae441e 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -197,6 +197,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & const tsel = this._editorView.state.selection.$from; tsel.marks().filter(m => m.type === this._editorView!.state.schema.marks.user_mark).map(m => AudioBox.SetScrubTime(Math.max(0, m.attrs.modified * 5000 - 1000))); this._applyingChange = true; + this.extensionDoc && !this.extensionDoc.lastModified && (this.extensionDoc.backgroundColor = "lightGray"); this.extensionDoc && (this.extensionDoc.lastModified = new DateField(new Date(Date.now()))); this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()), state.doc.textBetween(0, state.doc.content.size, "\n\n")); this._applyingChange = false; @@ -1131,7 +1132,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.stopPropagation(); }} > + style={{ color: this._recording ? "red" : "blue", opacity: this._recording ? 1 : 0.5, display: this.props.isSelected() ? "" : "none" }} icon={"microphone"} size="sm" />
); diff --git a/src/server/Initialization.ts b/src/server/Initialization.ts index 6fe67f2c7..ff2b64317 100644 --- a/src/server/Initialization.ts +++ b/src/server/Initialization.ts @@ -40,7 +40,7 @@ export default async function InitializeServer(options: InitializationOptions) { app.use("*", ({ user, originalUrl }, res, next) => { if (user && !originalUrl.includes("Heartbeat")) { - const userEmail = user.email; + const userEmail = (user as any).email; if (userEmail) { timeMap[userEmail] = Date.now(); } -- cgit v1.2.3-70-g09d2 From fef12d4ca96d35c230a3a5e7c053b9b90eb38243 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 6 Dec 2019 15:00:33 -0500 Subject: more fixes for inline comments. --- src/client/util/RichTextRules.ts | 2 +- src/client/util/RichTextSchema.tsx | 25 ++++++++++++++++++------- src/client/views/nodes/FormattedTextBox.scss | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 9 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index 4e3192dd4..cd4bfdc63 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -174,7 +174,7 @@ export const inpRules = { const newNode = schema.nodes.dashComment.create({ docid: target[Id] }); const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); const sm = state.storedMarks || undefined; - const replaced = node ? state.tr.insert(start, newNode).replaceRangeWith(start + 1, end + 1, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : + const replaced = node ? state.tr.insert(start, newNode).replaceRangeWith(start + 1, end + 1, dashDoc).insertText(" ", start + 2).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced;//.setSelection(new NodeSelection(replaced.doc.resolve(end))); }), diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 5fcf15cb7..8c74c3f68 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -672,23 +672,34 @@ export class DashDocCommentView { this._collapsed.className = "formattedTextBox-inlineComment"; this._collapsed.id = "DashDocCommentView-" + node.attrs.docid; this._view = view; - const targetNode = () => { - for (let i = getPos() + 1; i < view.state.doc.nodeSize; i++) { + 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 } as { node: any, pos: number }; + 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; }; this._collapsed.onpointerdown = (e: any) => { + e.stopPropagation(); + }; + this._collapsed.onpointerup = (e: any) => { const target = targetNode(); if (target) { - view.dispatch(view.state.tr. - setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true })); // update the attrs - setTimeout(() => node.attrs.hidden && DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)), 100); + let expand = target.hidden; + let 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(); + } this._collapsed.onpointerenter = (e: any) => { DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); e.preventDefault(); diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index f3a14169a..baf758c0e 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -195,7 +195,7 @@ footnote::after { position: relative; width: 40px; height: 20px; - &::after { + &::before { content: "→"; } &:hover { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index e7c59ccb4..3302d2e54 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -913,6 +913,20 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & static _userStyleSheet: any = addStyleSheet(); onClick = (e: React.MouseEvent): void => { + if ((this._editorView!.root as any).getSelection().isCollapsed) { // this is a hack to allow the cursor to be placed at the end of a document when the document ends in an inline dash comment. Apparently Chrome on Windows has a bug/feature which breaks this when clicking after the end of the text. + let pcords = this._editorView!.posAtCoords({ left: e.clientX, top: e.clientY }); + let node = pcords && this._editorView!.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text) + if (pcords && node?.type === this._editorView!.state.schema.nodes.dashComment) { + this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pcords.pos + 2))); + e.preventDefault(); + } + if (!node && this._proseRef) { + let lastNode = this._proseRef.children[this._proseRef.children.length - 1].children[this._proseRef.children[this._proseRef.children.length - 1].children.length - 1]; // get the last prosemirror div + if (e.clientY > lastNode.getBoundingClientRect().bottom) { // if we clicked below the last prosemirror div, then set the selection to be the end of the document + this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, this._editorView!.state.doc.content.size))); + } + } + } if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); return; } (e.nativeEvent as any).formattedHandled = true; // if (e.button === 0 && ((!this.props.isSelected(true) && !e.ctrlKey) || (this.props.isSelected(true) && e.ctrlKey)) && !e.metaKey && e.target) { -- cgit v1.2.3-70-g09d2 From 78a65a6d871ce89f3dfed76035e379df631757a8 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 9 Dec 2019 15:55:17 -0500 Subject: fixed up bulleted list formatting. disabled auto-flyout of sidebar. --- src/client/util/RichTextSchema.tsx | 12 ++---- src/client/views/MainView.tsx | 14 +++--- src/client/views/nodes/FormattedTextBox.scss | 64 +++++++++++++++++----------- src/client/views/nodes/FormattedTextBox.tsx | 57 ++++++++++++++----------- 4 files changed, 80 insertions(+), 67 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 2102ea85b..9e95314a9 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -249,16 +249,13 @@ export const nodes: { [index: string]: NodeSpec } = { bulletStyle: { default: 0 }, mapStyle: { default: "decimal" }, setFontSize: { default: undefined }, - setFontFamily: { default: undefined }, + setFontFamily: { default: "inherit" }, inheritedFontSize: { default: undefined }, visibility: { default: true } }, toDOM(node: Node) { - const bs = node.attrs.bulletStyle; if (node.attrs.mapStyle === "bullet") return ['ul', 0]; - const decMap = bs ? "decimal" + bs : ""; - const multiMap = bs === 1 ? "decimal1" : bs === 2 ? "upper-alpha" : bs === 3 ? "lower-roman" : bs === 4 ? "lower-alpha" : ""; - const map = node.attrs.mapStyle === "decimal" ? decMap : multiMap; + const map = node.attrs.bulletStyle ? node.attrs.mapStyle + node.attrs.bulletStyle : ""; const fsize = node.attrs.setFontSize ? node.attrs.setFontSize : node.attrs.inheritedFontSize; const ffam = node.attrs.setFontFamily; return node.attrs.visibility ? ['ol', { class: `${map}-ol`, style: `list-style: none; font-size: ${fsize}; font-family: ${ffam}` }, 0] : @@ -285,10 +282,7 @@ export const nodes: { [index: string]: NodeSpec } = { ...listItem, content: 'paragraph block*', toDOM(node: any) { - const bs = node.attrs.bulletStyle; - const decMap = bs ? "decimal" + bs : ""; - const multiMap = bs === 1 ? "decimal1" : bs === 2 ? "upper-alpha" : bs === 3 ? "lower-roman" : bs === 4 ? "lower-alpha" : ""; - const map = node.attrs.mapStyle === "decimal" ? decMap : node.attrs.mapStyle === "multi" ? multiMap : ""; + const map = node.attrs.bulletStyle ? node.attrs.mapStyle + node.attrs.bulletStyle : ""; return node.attrs.visibility ? ["li", { class: `${map}` }, 0] : ["li", { class: `${map}` }, "..."]; //return ["li", { class: `${map}` }, 0]; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index bcdc3a453..01cd7957c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -315,11 +315,11 @@ export class MainView extends React.Component { @action pointerOverDragger = () => { - if (this.flyoutWidth === 0) { - this.flyoutWidth = 250; - this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; - this._flyoutTranslate = false; - } + // if (this.flyoutWidth === 0) { + // this.flyoutWidth = 250; + // this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; + // this._flyoutTranslate = false; + // } } @action @@ -338,7 +338,7 @@ export class MainView extends React.Component { @action onPointerUp = (e: PointerEvent) => { if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4) { - this.flyoutWidth = this.flyoutWidth < 5 ? 250 : 0; + this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0; this.flyoutWidth && (this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30); } document.removeEventListener("pointermove", this.onPointerMove); @@ -429,7 +429,7 @@ export class MainView extends React.Component { style={{ backgroundColor: `${StrCast(sidebar.backgroundColor, "lightGray")}` }} > diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index baf758c0e..8256cffac 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -225,33 +225,47 @@ footnote::after { .ProseMirror { touch-action: none; + span { + font-family: inherit; + } + ol, ul { + counter-reset: deci1 0 multi1 0; + padding-left: 1em; + font-family: inherit; + } ol { - counter-reset: deci1 0; - padding-left: 0px; + margin-left: 1em; + font-family: inherit; } - - .decimal1-ol { counter-reset: deci1; p { display: inline }; ul, ol { padding-left: 30px; } } - .decimal2-ol { counter-reset: deci2; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } - .decimal3-ol { counter-reset: deci3; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } - .decimal4-ol { counter-reset: deci4; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } - .decimal5-ol { counter-reset: deci5; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } - .decimal6-ol { counter-reset: deci6; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } - .decimal7-ol { counter-reset: deci7; p { display: inline }; font-size: smaller; ul, ol { padding-left: 30px; } } - - .upper-alpha-ol { counter-reset: ualph; p { display: inline}; font-size: smaller; } - .lower-roman-ol { counter-reset: lroman; p { display: inline}; font-size: smaller; } - .lower-alpha-ol { counter-reset: lalpha; p { display: inline}; font-size: smaller; } - - .decimal1:before { counter-increment: deci1; display: inline-block; content: counter(deci1) ". "; } - .decimal2:before { counter-increment: deci2; display: inline-block; content: counter(deci1) "."counter(deci2) ". "; } - .decimal3:before { counter-increment: deci3; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) ". "; } - .decimal4:before { counter-increment: deci4; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) ". "; } - .decimal5:before { counter-increment: deci5; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) ". "; } - .decimal6:before { counter-increment: deci5; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) ". "; } - .decimal7:before { counter-increment: deci5; display: inline-block; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) "."counter(deci7) ". "; } + p { + display: inline; + font-family: inherit; + } + + .decimal1-ol { counter-reset: deci1; margin-left: 0; } + .decimal2-ol { counter-reset: deci2; font-size: smaller; padding-left: 1em;} + .decimal3-ol { counter-reset: deci3; font-size: smaller; padding-left: 2em;} + .decimal4-ol { counter-reset: deci4; font-size: smaller; padding-left: 3em;} + .decimal5-ol { counter-reset: deci5; font-size: smaller; } + .decimal6-ol { counter-reset: deci6; font-size: smaller; } + .decimal7-ol { counter-reset: deci7; font-size: smaller; } + + .multi1-ol { counter-reset: multi1; margin-left: 0; padding-left: 1.2em } + .multi2-ol { counter-reset: multi2; font-size: smaller; padding-left: 1.4em;} + .multi3-ol { counter-reset: multi3; font-size: smaller; padding-left: 2em;} + .multi4-ol { counter-reset: multi4; font-size: smaller; padding-left: 3.4em;} + + .decimal1:before { transition: 0.5s;counter-increment: deci1; display: inline-block; margin-left: -1em; width: 1em; content: counter(deci1) ". "; } + .decimal2:before { transition: 0.5s;counter-increment: deci2; display: inline-block; margin-left: -2.1em; width: 2.1em; content: counter(deci1) "."counter(deci2) ". "; } + .decimal3:before { transition: 0.5s;counter-increment: deci3; display: inline-block; margin-left: -2.85em;width: 2.85em; content: counter(deci1) "."counter(deci2) "."counter(deci3) ". "; } + .decimal4:before { transition: 0.5s;counter-increment: deci4; display: inline-block; margin-left: -3.85em;width: 3.85em; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) ". "; } + .decimal5:before { transition: 0.5s;counter-increment: deci5; display: inline-block; margin-left: -2em; width: 5em; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) ". "; } + .decimal6:before { transition: 0.5s;counter-increment: deci6; display: inline-block; margin-left: -2em; width: 6em; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) ". "; } + .decimal7:before { transition: 0.5s;counter-increment: deci7; display: inline-block; margin-left: -2em; width: 7em; content: counter(deci1) "."counter(deci2) "."counter(deci3) "."counter(deci4) "."counter(deci5) "."counter(deci6) "."counter(deci7) ". "; } - .upper-alpha:before { counter-increment: ualph; display: inline-block; content: counter(deci1) "."counter(ualph, upper-alpha) ". "; } - .lower-roman:before { counter-increment: lroman; display: inline-block; content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) ". "; } - .lower-alpha:before { counter-increment: lalpha; display: inline-block; content: counter(deci1) "."counter(ualph, upper-alpha) "."counter(lroman, lower-roman) "."counter(lalpha, lower-alpha) ". "; } + .multi1:before { transition: 0.5s;counter-increment: multi1; display: inline-block; margin-left: -1em; width: 1.2em; content: counter(multi1, upper-alpha) ". "; } + .multi2:before { transition: 0.5s;counter-increment: multi2; display: inline-block; margin-left: -2em; width: 2em; content: counter(multi1, upper-alpha) "."counter(multi2, decimal) ". "; } + .multi3:before { transition: 0.5s;counter-increment: multi3; display: inline-block; margin-left: -2.85em; width:2.85em; content: counter(multi1, upper-alpha) "."counter(multi2, decimal) "."counter(multi3, lower-alpha) ". "; } + .multi4:before { transition: 0.5s;counter-increment: multi4; display: inline-block; margin-left: -4.2em; width: 4.2em; content: counter(multi1, upper-alpha) "."counter(multi2, decimal) "."counter(multi3, lower-alpha) "."counter(multi4, lower-roman) ". "; } } \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 3ed010e8f..3197ce79f 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -962,37 +962,42 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & // } // } - this.hitBulletTargets(e.clientX, e.clientY, e.nativeEvent.offsetX, e.shiftKey); + this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, false) if (this._recording) setTimeout(() => { this.stopDictation(true); setTimeout(() => this.recordDictation(), 500); }, 500); } // this hackiness handles clicking on the list item bullets to do expand/collapse. the bullets are ::before pseudo elements so there's no real way to hit test against them. - hitBulletTargets(x: number, y: number, offsetX: number, select: boolean, highlightOnly = false) { + hitBulletTargets(x: number, y: number, select: boolean, highlightOnly: boolean) { clearStyleSheetRules(FormattedTextBox._bulletStyleSheet); - if (this.props.isSelected(true) && offsetX < 40) { - const pos = this._editorView!.posAtCoords({ left: x, top: y }); - if (pos && pos.pos > 0) { - const node = this._editorView!.state.doc.nodeAt(pos.pos); - const node2 = node?.type === schema.nodes.paragraph ? this._editorView!.state.doc.nodeAt(pos.pos - 1) : undefined; - if ((node === this._nodeClicked || highlightOnly) && (node2?.type === schema.nodes.ordered_list || node2?.type === schema.nodes.list_item)) { - const hit = this._editorView!.domAtPos(pos.pos).node as any; // let beforeEle = document.querySelector("." + hit.className) as Element; - const before = hit ? window.getComputedStyle(hit, ':before') : undefined; - const beforeWidth = before ? Number(before.getPropertyValue('width').replace("px", "")) : undefined; - if (beforeWidth && offsetX < beforeWidth * .9) { - const ol = this._editorView!.state.doc.nodeAt(pos.pos - 2) ? this._editorView!.state.doc.nodeAt(pos.pos - 2) : undefined; - if (ol?.type === schema.nodes.ordered_list && select) { - if (!highlightOnly) { - this._editorView!.dispatch(this._editorView!.state.tr.setSelection(new NodeSelection(this._editorView!.state.doc.resolve(pos.pos - 2)))); - } - addStyleSheetRule(FormattedTextBox._bulletStyleSheet, hit.className + ":before", { background: "lightgray" }); - } else { - if (highlightOnly) { - addStyleSheetRule(FormattedTextBox._bulletStyleSheet, hit.className + ":before", { background: "lightgray" }); - } else { - this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(pos.pos - 1, node2.type, { ...node2.attrs, visibility: !node2.attrs.visibility })); - } - } + const pos = this._editorView!.posAtCoords({ left: x, top: y }); + if (pos && this.props.isSelected(true)) { + // let beforeEle = document.querySelector("." + hit.className) as Element; // const before = hit ? window.getComputedStyle(hit, ':before') : undefined; + //const node = this._editorView!.state.doc.nodeAt(pos.pos); + let $pos = this._editorView!.state.doc.resolve(pos.pos); + let list_node = $pos.node().type === schema.nodes.list_item ? $pos.node() : undefined; + if ($pos.node().type === schema.nodes.ordered_list) { + for (let off = 1; off < 100; off++) { + const pos = this._editorView!.posAtCoords({ left: x + off, top: y }); + const node = pos && this._editorView!.state.doc.nodeAt(pos.pos); + if (node?.type === schema.nodes.list_item) { + list_node = node; + break; + } + } + } + if (list_node && this._editorView!.state.doc.nodeAt(pos.inside)!.attrs.bulletStyle === list_node.attrs.bulletStyle) { + if (select) { + let $olist_pos = this._editorView!.state.doc.resolve($pos.pos - $pos.parentOffset - 1); + if (!highlightOnly) { + this._editorView!.dispatch(this._editorView!.state.tr.setSelection(new NodeSelection($olist_pos))); + } + addStyleSheetRule(FormattedTextBox._bulletStyleSheet, list_node.attrs.mapStyle + list_node.attrs.bulletStyle + ":hover:before", { background: "lightgray" }); + } else if (Math.abs(pos.pos - pos.inside) < 2) { + if (!highlightOnly) { + this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(pos.inside, list_node.type, { ...list_node.attrs, visibility: !list_node.attrs.visibility })); + this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pos.inside))); } + addStyleSheetRule(FormattedTextBox._bulletStyleSheet, list_node.attrs.mapStyle + list_node.attrs.bulletStyle + ":hover:before", { background: "lightgray" }); } } } @@ -1113,7 +1118,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & onKeyDown={this.onKeyPress} onFocus={this.onFocused} onClick={this.onClick} - onPointerMove={e => this.hitBulletTargets(e.clientX, e.clientY, e.nativeEvent.offsetX, e.shiftKey, true)} + onPointerMove={e => this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, true)} onBlur={this.onBlur} onPointerUp={this.onPointerUp} onPointerDown={this.onPointerDown} -- cgit v1.2.3-70-g09d2 From c9c91b0e74934e36514916786da8822b1f3c05f3 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 9 Dec 2019 16:03:26 -0500 Subject: from last --- src/client/views/GlobalKeyHandler.ts | 2 +- src/client/views/nodes/FormattedTextBox.scss | 30 ++++++++++++---------------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index edc7df12a..bce33531d 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -108,7 +108,7 @@ export default class KeyManager { let preventDefault = false; switch (keyname) { - case " ": + case "~": DictationManager.Controls.listen({ useOverlay: true, tryExecute: true }); stopPropagation = true; preventDefault = true; diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 8256cffac..ed320bdcd 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -238,23 +238,19 @@ footnote::after { margin-left: 1em; font-family: inherit; } - p { - display: inline; - font-family: inherit; - } - - .decimal1-ol { counter-reset: deci1; margin-left: 0; } - .decimal2-ol { counter-reset: deci2; font-size: smaller; padding-left: 1em;} - .decimal3-ol { counter-reset: deci3; font-size: smaller; padding-left: 2em;} - .decimal4-ol { counter-reset: deci4; font-size: smaller; padding-left: 3em;} - .decimal5-ol { counter-reset: deci5; font-size: smaller; } - .decimal6-ol { counter-reset: deci6; font-size: smaller; } - .decimal7-ol { counter-reset: deci7; font-size: smaller; } - - .multi1-ol { counter-reset: multi1; margin-left: 0; padding-left: 1.2em } - .multi2-ol { counter-reset: multi2; font-size: smaller; padding-left: 1.4em;} - .multi3-ol { counter-reset: multi3; font-size: smaller; padding-left: 2em;} - .multi4-ol { counter-reset: multi4; font-size: smaller; padding-left: 3.4em;} + + .decimal1-ol { counter-reset: deci1; p {display: inline; font-family: inherit} margin-left: 0; } + .decimal2-ol { counter-reset: deci2; p {display: inline; font-family: inherit} font-size: smaller; padding-left: 1em;} + .decimal3-ol { counter-reset: deci3; p {display: inline; font-family: inherit} font-size: smaller; padding-left: 2em;} + .decimal4-ol { counter-reset: deci4; p {display: inline; font-family: inherit} font-size: smaller; padding-left: 3em;} + .decimal5-ol { counter-reset: deci5; p {display: inline; font-family: inherit} font-size: smaller; } + .decimal6-ol { counter-reset: deci6; p {display: inline; font-family: inherit} font-size: smaller; } + .decimal7-ol { counter-reset: deci7; p {display: inline; font-family: inherit} font-size: smaller; } + + .multi1-ol { counter-reset: multi1; p {display: inline; font-family: inherit} margin-left: 0; padding-left: 1.2em } + .multi2-ol { counter-reset: multi2; p {display: inline; font-family: inherit} font-size: smaller; padding-left: 1.4em;} + .multi3-ol { counter-reset: multi3; p {display: inline; font-family: inherit} font-size: smaller; padding-left: 2em;} + .multi4-ol { counter-reset: multi4; p {display: inline; font-family: inherit} font-size: smaller; padding-left: 3.4em;} .decimal1:before { transition: 0.5s;counter-increment: deci1; display: inline-block; margin-left: -1em; width: 1em; content: counter(deci1) ". "; } .decimal2:before { transition: 0.5s;counter-increment: deci2; display: inline-block; margin-left: -2.1em; width: 2.1em; content: counter(deci1) "."counter(deci2) ". "; } -- cgit v1.2.3-70-g09d2 From 218a04638200b27b6b9132ca9086bb4d76740acf Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 20 Dec 2019 15:22:23 -0500 Subject: minor cleanup --- src/client/util/DocumentManager.ts | 2 +- src/client/util/RichTextSchema.tsx | 5 +++-- src/client/util/SelectionManager.ts | 3 --- src/client/views/collections/collectionFreeForm/MarqueeView.scss | 3 +-- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.scss | 1 - src/new_fields/Doc.ts | 1 + 7 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 60c251f0e..a318dede8 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -140,7 +140,7 @@ export class DocumentManager { if (first) annotatedDoc = first.props.Document; } if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? - docView.props.focus(annotatedDoc || docView.props.Document, false); + docView.props.focus(docView.props.Document, false); highlight(); } else { const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index bede23cb2..622e71812 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -16,7 +16,7 @@ import { DocumentManager } from "./DocumentManager"; import ParagraphNodeSpec from "./ParagraphNodeSpec"; import { Transform } from "./Transform"; import React = require("react"); -import { BoolCast, NumCast } from "../../new_fields/Types"; +import { BoolCast, NumCast, Cast } from "../../new_fields/Types"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], @@ -702,6 +702,7 @@ export class DashDocView { return new Transform(-translateX, -translateY, 1).scale(1 / this.contentScaling() / scale); } contentScaling = () => NumCast(this._dashDoc!.nativeWidth) > 0 && !this._dashDoc!.ignoreAspect ? this._dashDoc![WidthSym]() / NumCast(this._dashDoc!.nativeWidth) : 1; + 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) { this._textBox = tbox; this._dashSpan = document.createElement("div"); @@ -765,7 +766,7 @@ export class DashDocView { renderDepth={1} PanelWidth={self._dashDoc[WidthSym]} PanelHeight={self._dashDoc[HeightSym]} - focus={self._textBox.props.focus} + focus={self.outerFocus} backgroundColor={returnEmptyString} parentActive={returnFalse} whenActiveChanged={returnFalse} diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 932387085..4612f10f4 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -3,7 +3,6 @@ import { Doc } from "../../new_fields/Doc"; import { DocumentView } from "../views/nodes/DocumentView"; import { computedFn } from "mobx-utils"; import { List } from "../../new_fields/List"; -import { Scripting } from "./Scripting"; export namespace SelectionManager { @@ -84,5 +83,3 @@ export namespace SelectionManager { } } -Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); }); - diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss index d14495626..18d6da0da 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss @@ -5,10 +5,9 @@ left:0; width:100%; height:100%; -} -.marqueeView { overflow: hidden; pointer-events: inherit; + border-radius: inherit; } .marqueeView:focus-within { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index dc68ae81c..523edb918 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -520,7 +520,7 @@ export class MarqueeView extends React.Component e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} style={{ borderRadius: "inherit" }} onClick={this.onClick} onPointerDown={this.onPointerDown}> + return
e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}> {this._visible ? this.marqueeDiv : null} {this.props.children}
; diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index ed320bdcd..a344a50b3 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -25,7 +25,6 @@ color: initial; height: 100%; pointer-events: all; - overflow-y: auto; max-height: 100%; display: flex; flex-direction: row; diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index a969a8359..8e0b28606 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -756,6 +756,7 @@ Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }) Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); }); Scripting.addGlobal(function undo() { return UndoManager.Undo(); }); Scripting.addGlobal(function redo() { return UndoManager.Redo(); }); +Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); }); Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) { const docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCUMENT && d.type !== DocumentType.KVP && (!excludeCollections || !Cast(d.data, listSpec(Doc), null))); return docs.length ? new List(docs) : prevValue; -- cgit v1.2.3-70-g09d2 From d16636a8246dadb486476fe98da63fc0db4d36dc Mon Sep 17 00:00:00 2001 From: Stanley Yip Date: Tue, 7 Jan 2020 14:49:27 -0500 Subject: resizing works, the math is just wrong looool --- src/client/util/InteractionUtils.ts | 2 +- src/client/views/Touchable.tsx | 21 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 44 ++++- src/client/views/nodes/DocumentView.tsx | 191 +++++++++++++++++---- src/client/views/nodes/FormattedTextBox.scss | 20 ++- 5 files changed, 220 insertions(+), 58 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/util/InteractionUtils.ts b/src/client/util/InteractionUtils.ts index 7c386abc2..2d3671041 100644 --- a/src/client/util/InteractionUtils.ts +++ b/src/client/util/InteractionUtils.ts @@ -8,7 +8,7 @@ export namespace InteractionUtils { const REACT_POINTER_PEN_BUTTON = 0; const ERASER_BUTTON = 5; - export function GetMyTargetTouches(e: TouchEvent, prevPoints: Map): React.Touch[] { + export function GetMyTargetTouches(e: TouchEvent | React.TouchEvent, prevPoints: Map): React.Touch[] { let myTouches = new Array(); for (let i = 0; i < e.targetTouches.length; i++) { let pt = e.targetTouches.item(i); diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx index a647dec04..7b0581376 100644 --- a/src/client/views/Touchable.tsx +++ b/src/client/views/Touchable.tsx @@ -26,7 +26,6 @@ export abstract class Touchable extends React.Component { } if (this.prevPoints.size) { - console.log(e.targetTouches.length); switch (this.prevPoints.size) { case 1: this.handle1PointerDown(e); @@ -35,11 +34,6 @@ export abstract class Touchable extends React.Component { this.handle2PointersDown(e); break; } - - document.removeEventListener("touchmove", this.onTouch); - document.addEventListener("touchmove", this.onTouch); - document.removeEventListener("touchend", this.onTouchEnd); - document.addEventListener("touchend", this.onTouchEnd); } } @@ -110,6 +104,17 @@ export abstract class Touchable extends React.Component { e.preventDefault(); } - handle1PointerDown = (e: React.TouchEvent): any => { }; - handle2PointersDown = (e: React.TouchEvent): any => { }; + handle1PointerDown = (e: React.TouchEvent): any => { + document.removeEventListener("touchmove", this.onTouch); + document.addEventListener("touchmove", this.onTouch); + document.removeEventListener("touchend", this.onTouchEnd); + document.addEventListener("touchend", this.onTouchEnd); + } + + handle2PointersDown = (e: React.TouchEvent): any => { + document.removeEventListener("touchmove", this.onTouch); + document.addEventListener("touchmove", this.onTouch); + document.removeEventListener("touchend", this.onTouchEnd); + document.addEventListener("touchend", this.onTouchEnd); + } } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7b507f739..75690ab2c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -326,9 +326,30 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action handle1PointerDown = (e: React.TouchEvent) => { + if (e.nativeEvent.cancelBubble) return; let pt = e.targetTouches.item(0); if (pt) { this._hitCluster = this.props.Document.useCluster ? this.pickCluster(this.getTransform().transformPoint(pt.clientX, pt.clientY)) !== -1 : false; + if (!e.shiftKey && !e.altKey && !e.ctrlKey && this.props.active(true)) { + document.removeEventListener("touchmove", this.onTouch); + document.addEventListener("touchmove", this.onTouch); + document.removeEventListener("touchend", this.onTouchEnd); + document.addEventListener("touchend", this.onTouchEnd); + if (InkingControl.Instance.selectedTool === InkTool.Highlighter || InkingControl.Instance.selectedTool === InkTool.Pen) { + e.stopPropagation(); + e.preventDefault(); + let point = this.getTransform().transformPoint(pt.pageX, pt.pageY); + this._points.push({ X: point[0], Y: point[1] }); + } + else if (InkingControl.Instance.selectedTool === InkTool.None) { + this._lastX = pt.pageX; + this._lastY = pt.pageY; + } + else { + e.stopPropagation(); + e.preventDefault(); + } + } } } @@ -544,14 +565,21 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } handle2PointersDown = (e: React.TouchEvent) => { - let pt1: React.Touch | null = e.targetTouches.item(0); - let pt2: React.Touch | null = e.targetTouches.item(1); - if (!pt1 || !pt2) return; - - let centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; - let centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; - this._lastX = centerX; - this._lastY = centerY; + if (!e.nativeEvent.cancelBubble && this.props.active(true)) { + let pt1: React.Touch | null = e.targetTouches.item(0); + let pt2: React.Touch | null = e.targetTouches.item(1); + if (!pt1 || !pt2) return; + + let centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2; + let centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2; + this._lastX = centerX; + this._lastY = centerY; + document.removeEventListener("touchmove", this.onTouch); + document.addEventListener("touchmove", this.onTouch); + document.removeEventListener("touchend", this.onTouchEnd); + document.addEventListener("touchend", this.onTouchEnd); + e.stopPropagation(); + } } cleanUpInteractions = () => { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index dfeadb8c0..1780d9789 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -4,7 +4,7 @@ import { action, computed, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import * as rp from "request-promise"; import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc"; -import { Document } from '../../../new_fields/documentSchemas'; +import { Document, PositionDocument } from '../../../new_fields/documentSchemas'; import { Id } from '../../../new_fields/FieldSymbols'; import { listSpec } from "../../../new_fields/Schema"; import { ScriptField } from '../../../new_fields/ScriptField'; @@ -193,28 +193,165 @@ export class DocumentView extends DocComponent(Docu } } + handle1PointerDown = (e: React.TouchEvent) => { + if (!e.nativeEvent.cancelBubble) { + let touch = InteractionUtils.GetMyTargetTouches(e, this.prevPoints)[0]; + this._downX = touch.clientX; + this._downY = touch.clientY; + this._hitTemplateDrag = false; + for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) { + if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") { + this._hitTemplateDrag = true; + } + } + if ((this.active || this.Document.onDragStart || this.Document.onClick) && !e.ctrlKey && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); + document.removeEventListener("touchmove", this.onTouch); + document.addEventListener("touchmove", this.onTouch); + document.removeEventListener("touchend", this.onTouchEnd); + document.addEventListener("touchend", this.onTouchEnd); + if ((e.nativeEvent as any).formattedHandled) e.stopPropagation(); + console.log("down") + } + } + + handle1PointerMove = (e: TouchEvent) => { + if ((e as any).formattedHandled) { e.stopPropagation; return; } + if (e.cancelBubble && this.active) { + document.removeEventListener("touchmove", this.onTouch); + } + else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.Document.onDragStart || this.Document.onClick) && !this.Document.lockedPosition && !this.Document.inOverlay) { + let touch = InteractionUtils.GetMyTargetTouches(e, this.prevPoints)[0]; + if (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3) { + if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick)) { + document.removeEventListener("touchmove", this.onTouch); + document.removeEventListener("touchend", this.onTouchEnd); + this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); + } + } + e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers + e.preventDefault(); + + } + } + + handle2PointersDown = (e: React.TouchEvent) => { + if (!e.nativeEvent.cancelBubble && !this.isSelected()) { + e.stopPropagation(); + e.preventDefault(); + + document.removeEventListener("touchmove", this.onTouch); + document.addEventListener("touchmove", this.onTouch); + document.removeEventListener("touchend", this.onTouchEnd); + document.addEventListener("touchend", this.onTouchEnd); + } + } + + @action + handle2PointersMove = (e: TouchEvent) => { + let myTouches = InteractionUtils.GetMyTargetTouches(e, this.prevPoints); + let pt1 = myTouches[0]; + let pt2 = myTouches[1]; + let oldPoint1 = this.prevPoints.get(pt1.identifier); + let oldPoint2 = this.prevPoints.get(pt2.identifier); + let pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!); + if (pinching !== 0 && oldPoint1 && oldPoint2) { + // let dX = (Math.min(pt1.clientX, pt2.clientX) - Math.min(oldPoint1.clientX, oldPoint2.clientX)); + // let dY = (Math.min(pt1.clientY, pt2.clientY) - Math.min(oldPoint1.clientY, oldPoint2.clientY)); + // let dX = Math.sign(Math.abs(pt1.clientX - oldPoint1.clientX) - Math.abs(pt2.clientX - oldPoint2.clientX)); + // let dY = Math.sign(Math.abs(pt1.clientY - oldPoint1.clientY) - Math.abs(pt2.clientY - oldPoint2.clientY)); + // let dW = -dX; + // let dH = -dY; + let dW = (Math.abs(pt1.clientX - pt2.clientX) - Math.abs(oldPoint1.clientX - oldPoint2.clientX)); + let dH = (Math.abs(pt1.clientY - pt2.clientY) - Math.abs(oldPoint1.clientY - oldPoint2.clientY)); + let dX = -1 * Math.sign(dW); + let dY = -1 * Math.sign(dH); + + if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { + let doc = PositionDocument(this.props.Document); + let layoutDoc = PositionDocument(Doc.Layout(this.props.Document)); + let nwidth = layoutDoc.nativeWidth || 0; + let nheight = layoutDoc.nativeHeight || 0; + let width = (layoutDoc.width || 0); + let height = (layoutDoc.height || (nheight / nwidth * width)); + let scale = this.props.ScreenToLocalTransform().Scale * this.props.ContentScaling(); + let actualdW = Math.max(width + (dW * scale), 20); + let actualdH = Math.max(height + (dH * scale), 20); + doc.x = (doc.x || 0) + dX * (actualdW - width); + doc.y = (doc.y || 0) + dY * (actualdH - height); + let fixedAspect = e.ctrlKey || (!layoutDoc.ignoreAspect && nwidth && nheight); + if (fixedAspect && e.ctrlKey && layoutDoc.ignoreAspect) { + layoutDoc.ignoreAspect = false; + layoutDoc.nativeWidth = nwidth = layoutDoc.width || 0; + layoutDoc.nativeHeight = nheight = layoutDoc.height || 0; + } + if (fixedAspect && (!nwidth || !nheight)) { + layoutDoc.nativeWidth = nwidth = layoutDoc.width || 0; + layoutDoc.nativeHeight = nheight = layoutDoc.height || 0; + } + if (nwidth > 0 && nheight > 0 && !layoutDoc.ignoreAspect) { + if (Math.abs(dW) > Math.abs(dH)) { + if (!fixedAspect) { + layoutDoc.nativeWidth = actualdW / (layoutDoc.width || 1) * (layoutDoc.nativeWidth || 0); + } + layoutDoc.width = actualdW; + if (fixedAspect && !layoutDoc.fitWidth) layoutDoc.height = nheight / nwidth * layoutDoc.width; + else layoutDoc.height = actualdH; + } + else { + if (!fixedAspect) { + layoutDoc.nativeHeight = actualdH / (layoutDoc.height || 1) * (doc.nativeHeight || 0); + } + layoutDoc.height = actualdH; + if (fixedAspect && !layoutDoc.fitWidth) layoutDoc.width = nwidth / nheight * layoutDoc.height; + else layoutDoc.width = actualdW; + } + } else { + dW && (layoutDoc.width = actualdW); + dH && (layoutDoc.height = actualdH); + dH && layoutDoc.autoHeight && (layoutDoc.autoHeight = false); + } + } + // let newWidth = Math.max(Math.abs(oldPoint1!.clientX - oldPoint2!.clientX), Math.abs(pt1.clientX - pt2.clientX)) + // this.props.Document.width = newWidth; + e.stopPropagation(); + e.preventDefault(); + } + } + onPointerDown = (e: React.PointerEvent): void => { - if ((e.nativeEvent.cancelBubble && (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) - // return if we're inking, and not selecting a button document - || (InkingControl.Instance.selectedTool !== InkTool.None && !this.Document.onClick) - // return if using pen or eraser - || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || InteractionUtils.IsType(e, InteractionUtils.ERASERTYPE)) return; - this._downX = e.clientX; - this._downY = e.clientY; - this._hitTemplateDrag = false; - // this whole section needs to move somewhere else. We're trying to initiate a special "template" drag where - // this document is the template and we apply it to whatever we drop it on. - for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) { - if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") { - this._hitTemplateDrag = true; + // console.log(e.button) + // console.log(e.nativeEvent) + // continue if the event hasn't been canceled AND we are using a moues or this is has an onClick or onDragStart function (meaning it is a button document) + if (!InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE)) { + e.stopPropagation(); + return; + } + if ((!e.nativeEvent.cancelBubble || this.Document.onClick || this.Document.onDragStart)) { + // if ((e.nativeEvent.cancelBubble && (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) + // // return if we're inking, and not selecting a button document + // || (InkingControl.Instance.selectedTool !== InkTool.None && !this.Document.onClick) + // // return if using pen or eraser + // || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || InteractionUtils.IsType(e, InteractionUtils.ERASERTYPE)) { + // return; + // } + + this._downX = e.clientX; + this._downY = e.clientY; + this._hitTemplateDrag = false; + // this whole section needs to move somewhere else. We're trying to initiate a special "template" drag where + // this document is the template and we apply it to whatever we drop it on. + for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) { + if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") { + this._hitTemplateDrag = true; + } } + if ((this.active || this.Document.onDragStart || this.Document.onClick) && !e.ctrlKey && (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointerup", this.onPointerUp); + if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); } } - if ((this.active || this.Document.onDragStart || this.Document.onClick) && !e.ctrlKey && (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointerup", this.onPointerUp); - if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); } } onPointerMove = (e: PointerEvent): void => { @@ -649,20 +786,6 @@ export class DocumentView extends DocComponent(Docu return (this.Document.isBackground && !this.isSelected()) || (this.Document.type === DocumentType.INK && InkingControl.Instance.selectedTool !== InkTool.None); } - @action - handle2PointersMove = (e: TouchEvent) => { - let myTouches = InteractionUtils.GetMyTargetTouches(e, this.prevPoints); - let pt1 = myTouches[0]; - let pt2 = myTouches[1]; - let oldPoint1 = this.prevPoints.get(pt1.identifier); - let oldPoint2 = this.prevPoints.get(pt2.identifier); - let pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!); - if (pinching !== 0) { - let newWidth = Math.max(Math.abs(oldPoint1!.clientX - oldPoint2!.clientX), Math.abs(pt1.clientX - pt2.clientX)) - this.props.Document.width = newWidth; - } - } - render() { if (!this.props.Document) return (null); const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined; diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 77cdd3d42..2e5848db4 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -11,6 +11,7 @@ } .formattedTextBox-cont { + touch-action: none; cursor: text; background: inherit; padding: 0; @@ -50,6 +51,7 @@ width: 100%; height: 100%; } + .formattedTextBox-sidebar-handle { position: absolute; top: calc(50% - 17.5px); @@ -58,19 +60,23 @@ background: lightgray; border-radius: 20px; } -.formattedTextBox-cont > .formattedTextBox-sidebar-handle { + +.formattedTextBox-cont>.formattedTextBox-sidebar-handle { right: 0; left: unset; } -.formattedTextBox-sidebar, .formattedTextBox-sidebar-inking { - border-left: dashed 1px black; - height: 100%; + +.formattedTextBox-sidebar, +.formattedTextBox-sidebar-inking { + border-left: dashed 1px black; + height: 100%; display: inline-block; position: absolute; right: 0; - > .formattedTextBox-sidebar-handle { - right:unset; - left:-5; + + >.formattedTextBox-sidebar-handle { + right: unset; + left: -5; } } -- cgit v1.2.3-70-g09d2