From dbf41b6eaaebe16567289ba4814316b2c79e0b65 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 10 Oct 2019 10:50:53 -0400 Subject: richtexteditor menuicon styling --- src/client/views/nodes/FormattedTextBox.scss | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 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 29e8b14a8..f92ccf9f5 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -46,17 +46,17 @@ height: 100%; } -.menuicon { - display: inline-block; - border-right: 1px solid rgba(0, 0, 0, 0.2); - color: #888; - line-height: 1; - padding: 0 7px; - margin: 1px; - cursor: pointer; - text-align: center; - min-width: 1.4em; -} +// .menuicon { +// display: inline-block; +// border-right: 1px solid rgba(0, 0, 0, 0.2); +// color: #888; +// line-height: 1; +// padding: 0 7px; +// margin: 1px; +// cursor: pointer; +// text-align: center; +// min-width: 1.4em; +// } .strong, .heading { -- cgit v1.2.3-70-g09d2 From c9fbdb9cfd5fcf35f7a599706cb41d4e7e586e19 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 14 Nov 2019 16:23:57 -0500 Subject: added optional sidebar for text notes --- src/client/views/DocumentDecorations.tsx | 11 +----- src/client/views/nodes/FormattedTextBox.scss | 12 +++++++ src/client/views/nodes/FormattedTextBox.tsx | 39 +++++++++++++++++++--- src/client/views/nodes/FormattedTextBoxComment.tsx | 5 ++- 4 files changed, 49 insertions(+), 18 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 55c211d1d..49921170f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -157,22 +157,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> this.onBackgroundUp(e); } - @observable _forceUpdate = 0; - _lastBox = { x: 0, y: 0, r: 0, b: 0 }; @computed get Bounds(): { x: number, y: number, b: number, r: number } { - let x = this._forceUpdate; - this._lastBox = SelectionManager.SelectedDocuments().reduce((bounds, documentView) => { + return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => { if (documentView.props.renderDepth === 0 || Doc.AreProtosEqual(documentView.props.Document, CurrentUserUtils.UserDocument)) { return bounds; } let transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse(); - if (transform.TranslateX === 0 && transform.TranslateY === 0) { - setTimeout(action(() => this._forceUpdate++), 0); // bcz: fix CollectionStackingView's getTransform() somehow...without this, resizing things in the library view, for instance, show the wrong bounds - return this._lastBox; - } - var [sptX, sptY] = transform.transformPoint(0, 0); let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight()); if (documentView.props.Document.type === DocumentType.LINK) { @@ -187,7 +179,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) }; }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); - return this._lastBox; } onBackgroundDown = (e: React.PointerEvent): void => { diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index a4acd3b82..98b57bd84 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -36,6 +36,18 @@ } } +.collectionfreeformview-container { + position: relative; +} +.formattedTextBox-outer { + position: relative; + overflow: auto; + display: inline-block; + padding: 10px 10px; + width: 100%; + height: 100%; +} + .formattedTextBox-inner-rounded { height: 70%; width: 85%; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 6d60e8f77..b7df3fb0e 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -18,7 +18,7 @@ import { RichTextField } from "../../../new_fields/RichTextField"; import { RichTextUtils } from '../../../new_fields/RichTextUtils'; import { createSchema, makeInterface } from "../../../new_fields/Schema"; import { Cast, DateCast, NumCast, StrCast } from "../../../new_fields/Types"; -import { numberRange, Utils, addStyleSheet, addStyleSheetRule, clearStyleSheetRules } from '../../../Utils'; +import { numberRange, Utils, addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, returnOne } from '../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../apis/google_docs/GoogleApiClientUtils'; import { DocServer } from "../../DocServer"; import { Docs, DocUtils } from '../../documents/Documents'; @@ -33,7 +33,7 @@ import { SelectionManager } from "../../util/SelectionManager"; import { TooltipLinkingMenu } from "../../util/TooltipLinkingMenu"; import { TooltipTextMenu } from "../../util/TooltipTextMenu"; import { undoBatch, UndoManager } from "../../util/UndoManager"; -import { DocExtendableComponent } from "../DocComponent"; +import { DocAnnotatableComponent } from "../DocComponent"; import { DocumentButtonBar } from '../DocumentButtonBar'; import { DocumentDecorations } from '../DocumentDecorations'; import { InkingControl } from "../InkingControl"; @@ -46,6 +46,7 @@ import { ContextMenu } from '../ContextMenu'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { documentSchema } from '../../../new_fields/documentSchemas'; import { AudioBox } from './AudioBox'; +import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -70,7 +71,7 @@ const RichTextDocument = makeInterface(richTextSchema, documentSchema); type PullHandler = (exportState: Opt, dataDoc: Doc) => void; @observer -export class FormattedTextBox extends DocExtendableComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) { +export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); } public static blankState = () => EditorState.create(FormattedTextBox.Instance.config); public static Instance: FormattedTextBox; @@ -359,6 +360,7 @@ export class FormattedTextBox extends DocExtendableComponent<(FieldViewProps & F specificContextMenu = (e: React.MouseEvent): void => { let funcs: ContextMenuProps[] = []; + funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.props.Document.sidebarWidthPercent = StrCast(this.props.Document.sidebarWidthPercent, "0%") === "0%" ? "25%" : "0%"; }, icon: "expand-arrows-alt" }); funcs.push({ description: "Record Bullet", event: () => { e.stopPropagation(); this.recordBullet(); }, icon: "expand-arrows-alt" }); ["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option => funcs.push({ @@ -1010,6 +1012,9 @@ export class FormattedTextBox extends DocExtendableComponent<(FieldViewProps & F } } + @computed get sidebarWidthPercent() { return StrCast(this.props.Document.sidebarWidth, "0%"); } + @computed get sidebarWidth() { return Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth(); } + @computed get annotationsKey() { return "annotations"; } render() { trace(); let rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; @@ -1042,8 +1047,32 @@ export class FormattedTextBox extends DocExtendableComponent<(FieldViewProps & F onPointerEnter={action(() => this._entered = true)} onPointerLeave={action(() => this._entered = false)} > -
- +
+
+
+ {this.sidebarWidthPercent === "0%" ? (null) :
+ this.props.PanelHeight()} + PanelWidth={() => this.sidebarWidth} + annotationsKey={this.annotationsKey} + isAnnotationOverlay={true} + focus={this.props.focus} + isSelected={this.props.isSelected} + select={emptyFunction} + active={this.active} + ContentScaling={returnOne} + whenActiveChanged={this.whenActiveChanged} + removeDocument={this.removeDocument} + moveDocument={this.moveDocument} + addDocument={this.addDocument} + CollectionView={undefined} + ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth), 0)} + ruleProvider={undefined} + renderDepth={this.props.renderDepth + 1} + ContainingCollectionDoc={this.props.ContainingCollectionDoc} + chromeCollapsed={true}> + +
}
{ this._recording ? this.stopDictation(true) : this.recordDictation(); diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index 04958525c..c076fd34a 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -87,7 +87,7 @@ export class FormattedTextBoxComment { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, (doc: Doc, maxLocation: string) => textBox.props.addDocTab(doc, undefined, e.ctrlKey ? "inTab" : "onRight")); } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) { - textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { width: 200, height: 400 }), undefined, "onRight"); + textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, width: 200, height: 400 }), undefined, "onRight"); } FormattedTextBoxComment.opened = keep || !FormattedTextBoxComment.opened; textBox && FormattedTextBoxComment.start !== undefined && textBox.setAnnotation( @@ -97,7 +97,6 @@ export class FormattedTextBoxComment { }; root && root.appendChild(FormattedTextBoxComment.tooltip); } - //this.update(view, undefined); } public static Hide() { @@ -223,5 +222,5 @@ export class FormattedTextBoxComment { FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = set); } - destroy() { }//FormattedTextBoxComment.tooltip.style.display = "none"; } + destroy() { } } -- cgit v1.2.3-70-g09d2 From ed918920a83a2aea5adc8c2d6dc00f6bcc62514c Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 16 Nov 2019 16:32:26 -0500 Subject: nvm text documents are no lnger buggy --- src/client/views/nodes/FormattedTextBox.scss | 285 +++++++++++++++++++++++---- 1 file changed, 246 insertions(+), 39 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 b497b12b4..b9f1e9940 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -27,6 +27,7 @@ pointer-events: all; overflow-y: auto; max-height: 100%; + .formattedTextBox-dictation { height: 20px; width: 20px; @@ -39,6 +40,7 @@ .collectionfreeformview-container { position: relative; } + .formattedTextBox-outer { position: relative; overflow: auto; @@ -57,8 +59,8 @@ left: 10%; } -.formattedTextBox-inner-rounded , -.formattedTextBox-inner { +.formattedTextBox-inner-rounded, +.formattedTextBox-inner { padding: 10px 10px; height: 100%; } @@ -85,19 +87,20 @@ } .userMarkOpen { - background: rgba(255, 255, 0, 0.267); + background: rgba(255, 255, 0, 0.267); display: inline; } + .userMark { - background: rgba(255, 255, 0, 0.267); + background: rgba(255, 255, 0, 0.267); font-size: 2px; display: inline-grid; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - width:10px; - min-height:10px; - text-align:center; + width: 10px; + min-height: 10px; + text-align: center; align-content: center; } @@ -105,8 +108,9 @@ footnote { display: inline-block; position: relative; cursor: pointer; + div { - padding : 0 !important; + padding: 0 !important; } } @@ -119,7 +123,7 @@ footnote::after { .ProseMirror { counter-reset: prosemirror-footnote; - } +} .footnote-tooltip { cursor: auto; @@ -138,6 +142,7 @@ footnote::after { .prosemirror-attribution { font-size: 8px; } + .footnote-tooltip::before { border: 5px solid silver; border-top-width: 0px; @@ -152,45 +157,247 @@ footnote::after { } .formattedTextBox-summarizer { - opacity :0.5; + opacity: 0.5; position: relative; - width:40px; - height:20px; + width: 40px; + height: 20px; } -.formattedTextBox-summarizer::after{ - content: "←" ; + +.formattedTextBox-summarizer::after { + content: "←"; } .formattedTextBox-summarizer-collapsed { - opacity :0.5; + opacity: 0.5; position: relative; - width:40px; - height:20px; + width: 40px; + height: 20px; } + .formattedTextBox-summarizer-collapsed::after { content: "..."; } .ProseMirror { -ol { counter-reset: deci1 0; padding-left: 0px; } -.decimal1-ol {counter-reset: deci1; p { display: inline }; font-size: 24 ; ul, ol { padding-left:30px; } } -.decimal2-ol {counter-reset: deci2; p { display: inline }; font-size: 18 ; ul, ol { padding-left:30px; } } -.decimal3-ol {counter-reset: deci3; p { display: inline }; font-size: 14 ; 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} -} + touch-action: none; + + ol { + counter-reset: deci1 0; + padding-left: 0px; + } + + .decimal1-ol { + counter-reset: deci1; + + p { + display: inline + } + + ; + font-size: 24; + + ul, + ol { + padding-left: 30px; + } + } + + .decimal2-ol { + counter-reset: deci2; + + p { + display: inline + } + + ; + font-size: 18; + + ul, + ol { + padding-left: 30px; + } + } + + .decimal3-ol { + counter-reset: deci3; + + p { + display: inline + } + + ; + font-size: 14; + + 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 + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 28763de7e4d90a4ecd9bfd640d1de85338a98f79 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 19 Nov 2019 13:36:51 -0500 Subject: fixed inking on text sidebar --- src/client/views/nodes/FormattedTextBox.scss | 9 +++++++++ src/client/views/nodes/FormattedTextBox.tsx | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) (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 b9f1e9940..f7b6e92d9 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -49,6 +49,15 @@ width: 100%; height: 100%; } +.formattedTextBox-sidebar,.formattedTextBox-sidebar-inking { + border-left: solid 1px black; + height: 100%; + display: inline-block; +} + +.formattedTextBox-sidebar-inking { + pointer-events: all; +} .formattedTextBox-inner-rounded { height: 70%; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 4ecdc95ac..31919f192 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -46,6 +46,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { documentSchema } from '../../../new_fields/documentSchemas'; import { AudioBox } from './AudioBox'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; +import { InkTool } from '../../../new_fields/InkField'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -1049,7 +1050,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
- {this.sidebarWidthPercent === "0%" ? (null) :
+ {this.sidebarWidthPercent === "0%" ? (null) :
this.props.PanelHeight()} PanelWidth={() => this.sidebarWidth} -- cgit v1.2.3-70-g09d2 From 667d196a2cbc8e237de5be9a6f7ec4ecca9d2bb5 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 19 Nov 2019 16:05:42 -0500 Subject: tried to simplify button bar menu --- src/client/views/DocumentButtonBar.tsx | 104 +++------------------ src/client/views/InkSelectDecorations.tsx | 16 ++-- src/client/views/TemplateMenu.tsx | 49 +++++++++- .../views/collections/CollectionStaffView.tsx | 14 ++- src/client/views/collections/CollectionView.tsx | 4 +- .../views/collections/ParentDocumentSelector.scss | 6 ++ .../views/collections/ParentDocumentSelector.tsx | 29 ++++-- .../collectionFreeForm/MarqueeOptionsMenu.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.scss | 1 - src/client/views/pdf/PDFViewer.tsx | 2 +- 11 files changed, 104 insertions(+), 127 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 1412316f9..c7ee413c9 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -8,13 +8,12 @@ import { RichTextField } from '../../new_fields/RichTextField'; import { NumCast, StrCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; -import { DragLinksAsDocuments, DragManager } from "../util/DragManager"; +import { DragManager } from "../util/DragManager"; import { LinkManager } from '../util/LinkManager'; import { UndoManager } from "../util/UndoManager"; import './DocumentButtonBar.scss'; import './collections/ParentDocumentSelector.scss'; import { LinkMenu } from "./linking/LinkMenu"; -import { MetadataEntryMenu } from './MetadataEntryMenu'; import { FormattedTextBox, GoogleRef } from "./nodes/FormattedTextBox"; import { TemplateMenu } from "./TemplateMenu"; import { Template, Templates } from "./Templates"; @@ -43,7 +42,6 @@ const fetch: IconProp = "sync-alt"; @observer export class DocumentButtonBar extends React.Component<{ views: DocumentView[], stack?: any }, {}> { private _linkButton = React.createRef(); - private _linkerButton = React.createRef(); private _aliasButton = React.createRef(); private _tooltipoff = React.createRef(); private _textDoc?: Doc; @@ -109,14 +107,6 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], document.addEventListener("pointerup", this.onLinkerButtonUp); } - onAliasButtonDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - document.removeEventListener("pointermove", this.onAliasButtonMoved); - document.addEventListener("pointermove", this.onAliasButtonMoved); - document.removeEventListener("pointerup", this.onAliasButtonUp); - document.addEventListener("pointerup", this.onAliasButtonUp); - } onLinkerButtonUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onLinkerButtonMoved); @@ -124,22 +114,17 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], e.stopPropagation(); } - onAliasButtonUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onAliasButtonMoved); - document.removeEventListener("pointerup", this.onAliasButtonUp); - e.stopPropagation(); - } @action onLinkerButtonMoved = (e: PointerEvent): void => { - if (this._linkerButton.current !== null) { + if (this._linkButton.current !== null) { document.removeEventListener("pointermove", this.onLinkerButtonMoved); - document.removeEventListener("pointerup", this.onLinkerButtonUp); + document.removeEventListener("pointerup", this.onLinkButtonUp); let docView = this.props.views[0]; let container = docView.props.ContainingCollectionDoc ? docView.props.ContainingCollectionDoc.proto : undefined; let dragData = new DragManager.LinkDragData(docView.props.Document, container ? [container] : []); let linkDrag = UndoManager.StartBatch("Drag Link"); - DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, { + DragManager.StartLinkDrag(this._linkButton.current, dragData, e.pageX, e.pageY, { handlers: { dragComplete: () => { let tooltipmenu = FormattedTextBox.ToolTipTextMenu; @@ -163,62 +148,22 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], e.stopPropagation(); } - @action - onAliasButtonMoved = (e: PointerEvent): void => { - if (this._aliasButton.current !== null) { - document.removeEventListener("pointermove", this.onAliasButtonMoved); - document.removeEventListener("pointerup", this.onAliasButtonUp); - - let dragDocView = this.props.views[0]; - let dragData = new DragManager.DocumentDragData([dragDocView.props.Document]); - const [left, top] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).inverse().transformPoint(0, 0); - dragData.offset = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.clientX - left, e.clientY - top); - dragData.embedDoc = true; - dragData.dropAction = "alias"; - DragManager.StartDocumentDrag([dragDocView.ContentDiv!], dragData, e.x, e.y, { - offsetX: dragData.offset[0], - offsetY: dragData.offset[1], - handlers: { - dragComplete: action(emptyFunction), - }, - hideSource: false - }); - } - e.stopPropagation(); - } onLinkButtonDown = (e: React.PointerEvent): void => { e.stopPropagation(); e.preventDefault(); - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.addEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointermove", this.onLinkerButtonMoved); + document.addEventListener("pointermove", this.onLinkerButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); document.addEventListener("pointerup", this.onLinkButtonUp); } onLinkButtonUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointermove", this.onLinkerButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); e.stopPropagation(); } - onLinkButtonMoved = async (e: PointerEvent) => { - if (this._linkButton.current !== null && (e.movementX > 1 || e.movementY > 1)) { - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); - DragLinksAsDocuments(this._linkButton.current, e.x, e.y, this.props.views[0].props.Document); - } - e.stopPropagation(); - } - - aliasDragger = () => { - return (
-
- -
-
); - } - private get targetDoc() { return this.props.views[0].props.Document; } @@ -317,30 +262,18 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], } } - get metadataMenu() { - return ( -
- this.props.views.map(dv => dv.props.Document)} suggestWithFunction />}>{/* tfs: @bcz This might need to be the data document? */} -
-
-
- ); - } - render() { let linkButton = null; if (this.props.views.length > 0) { let selFirst = this.props.views[0]; let linkCount = LinkManager.Instance.getAllRelatedLinks(selFirst.props.Document).length; - linkButton = (}> -
{linkCount}
-
); + linkButton = }> +
+ {linkCount ? linkCount : } +
+
; } let templates: Map = new Map(); @@ -349,21 +282,14 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], return (
-
{linkButton}
-
-
-
- -
+
{linkButton}
- {this.metadataMenu} - {this.aliasDragger()} {this.considerGoogleDocsPush()} {this.considerGoogleDocsPull()} - { + { where === "onRight" ? CollectionDockingView.AddRightSplit(doc, data) : this.props.stack ? CollectionDockingView.Instance.AddTab(this.props.stack, doc, data) : this.props.views[0].props.addDocTab(doc, data, "onRight"); return true; }} /> diff --git a/src/client/views/InkSelectDecorations.tsx b/src/client/views/InkSelectDecorations.tsx index 95ccc1777..d40df9b75 100644 --- a/src/client/views/InkSelectDecorations.tsx +++ b/src/client/views/InkSelectDecorations.tsx @@ -3,7 +3,7 @@ import { Touchable } from "./Touchable"; import { PointData } from "../../new_fields/InkField"; import { observer } from "mobx-react"; import { computed, observable, action, runInAction } from "mobx"; -import "./InkSelectDecorations.scss" +import "./InkSelectDecorations.scss"; @observer export default class InkSelectDecorations extends Touchable { @@ -46,14 +46,10 @@ export default class InkSelectDecorations extends Touchable { render() { let bounds = this.Bounds; - return ( -
- -
- ) + return
; } } \ No newline at end of file diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 96265385e..1df5f49c4 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -10,6 +10,7 @@ import { Template, Templates } from "./Templates"; import React = require("react"); import { Doc } from "../../new_fields/Doc"; import { StrCast } from "../../new_fields/Types"; +import { emptyFunction } from "../../Utils"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -46,10 +47,13 @@ export interface TemplateMenuProps { templates: Map; } + @observer export class TemplateMenu extends React.Component { @observable private _hidden: boolean = true; - dragRef = React.createRef(); + private _downx = 0; + private _downy = 0; + private _dragRef = React.createRef(); toggleCustom = (e: React.ChangeEvent): void => { this.props.docs.map(dv => dv.setCustomView(e.target.checked)); @@ -122,6 +126,43 @@ export class TemplateMenu extends React.Component { layout.chromeStatus = (layout.chromeStatus !== "disabled" ? "disabled" : "enabled"); }); } + onAliasButtonUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onAliasButtonMoved); + document.removeEventListener("pointerup", this.onAliasButtonUp); + e.stopPropagation(); + } + + onAliasButtonDown = (e: React.PointerEvent): void => { + this._downx = e.clientX; + this._downy = e.clientY; + e.stopPropagation(); + e.preventDefault(); + document.removeEventListener("pointermove", this.onAliasButtonMoved); + document.addEventListener("pointermove", this.onAliasButtonMoved); + document.removeEventListener("pointerup", this.onAliasButtonUp); + document.addEventListener("pointerup", this.onAliasButtonUp); + } + onAliasButtonMoved = (e: PointerEvent): void => { + if (this._dragRef.current !== null && (Math.abs(e.clientX - this._downx) > 4 || Math.abs(e.clientY - this._downy) > 4)) { + document.removeEventListener("pointermove", this.onAliasButtonMoved); + document.removeEventListener("pointerup", this.onAliasButtonUp); + + let dragDocView = this.props.docs[0]; + let dragData = new DragManager.DocumentDragData([dragDocView.props.Document]); + const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); + dragData.embedDoc = true; + dragData.dropAction = "alias"; + DragManager.StartDocumentDrag([dragDocView.ContentDiv!], dragData, left, top, { + offsetX: dragData.offset[0], + offsetY: dragData.offset[1], + handlers: { + dragComplete: action(emptyFunction), + }, + hideSource: false + }); + } + e.stopPropagation(); + } render() { let layout = Doc.Layout(this.props.docs[0].Document); @@ -132,9 +173,9 @@ export class TemplateMenu extends React.Component { templateMenu.push(); templateMenu.push(); return ( -
-
this.toggleTemplateActivity()}>+
-
    +
    +
    this.toggleTemplateActivity()}>+
    +
      {templateMenu} {}
    diff --git a/src/client/views/collections/CollectionStaffView.tsx b/src/client/views/collections/CollectionStaffView.tsx index eea05ea61..40e860b12 100644 --- a/src/client/views/collections/CollectionStaffView.tsx +++ b/src/client/views/collections/CollectionStaffView.tsx @@ -1,6 +1,6 @@ import { CollectionSubView } from "./CollectionSubView"; import { Transform } from "../../util/Transform"; -import React = require("react") +import React = require("react"); import { computed, action, IReactionDisposer, reaction, runInAction, observable } from "mobx"; import { Doc, HeightSym } from "../../../new_fields/Doc"; import { NumCast } from "../../../new_fields/Types"; @@ -36,7 +36,7 @@ export class CollectionStaffView extends CollectionSubView(doc => doc) { for (let i = 0; i < this._staves; i++) { let rows = []; for (let j = 0; j < 5; j++) { - rows.push(
    ) + rows.push(
    ); } staves.push(
    {rows} @@ -51,11 +51,9 @@ export class CollectionStaffView extends CollectionSubView(doc => doc) { } render() { - return ( -
    - {this.staves} - {this.addStaffButton} -
    - ) + return
    + {this.staves} + {this.addStaffButton} +
    ; } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 8f1278670..347fa7d0d 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -168,7 +168,7 @@ export class CollectionView extends Touchable { case CollectionViewType.Schema: return (); case CollectionViewType.Docking: return (); case CollectionViewType.Tree: return (); - case CollectionViewType.Staff: return () + case CollectionViewType.Staff: return (); case CollectionViewType.Linear: { return (); } case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } @@ -229,7 +229,7 @@ export class CollectionView extends Touchable { let more = ContextMenu.Instance.findByDescription("More..."); let moreItems = more && "subitems" in more ? more.subitems : []; moreItems.push({ description: "Export Image Hierarchy", icon: "columns", event: () => ImageUtils.ExportHierarchyToFileSystem(this.props.Document) }); - !more && ContextMenu.Instance.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }) + !more && ContextMenu.Instance.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); } } diff --git a/src/client/views/collections/ParentDocumentSelector.scss b/src/client/views/collections/ParentDocumentSelector.scss index c186d15f8..aa25a900c 100644 --- a/src/client/views/collections/ParentDocumentSelector.scss +++ b/src/client/views/collections/ParentDocumentSelector.scss @@ -23,6 +23,12 @@ .parentDocumentSelector-button { pointer-events: all; } +.parentDocumentSelector-metadata { + pointer-events: auto; + padding-right: 5px; + width: 25px; + display: inline-block; +} .buttonSelector { position: absolute; display: inline-block; diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 8b6fa330c..ba83630a4 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -13,10 +13,14 @@ import { DocumentManager } from "../../util/DocumentManager"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faEdit } from "@fortawesome/free-solid-svg-icons"; import { library } from "@fortawesome/fontawesome-svg-core"; +import { MetadataEntryMenu } from "../MetadataEntryMenu"; +const higflyout = require("@hig/flyout"); +export const { anchorPoints } = higflyout; +export const Flyout = higflyout.default; library.add(faEdit); -type SelectorProps = { Document: Doc, Stack?: any, addDocTab(doc: Doc, dataDoc: Doc | undefined, location: string): void }; +type SelectorProps = { Document: Doc, Views: DocumentView[], Stack?: any, addDocTab(doc: Doc, dataDoc: Doc | undefined, location: string): void }; @observer export class SelectorContextMenu extends React.Component { @observable private _docs: { col: Doc, target: Doc }[] = []; @@ -53,16 +57,23 @@ export class SelectorContextMenu extends React.Component { this.props.addDocTab(col, undefined, "inTab"); // bcz: dataDoc? }; } + get metadataMenu() { + return
    + this.props.Views.map(dv => dv.props.Document)} suggestWithFunction />}>{/* tfs: @bcz This might need to be the data document? */} +
    +
    +
    ; + } render() { - return ( - <> -

    Contexts:

    - {this._docs.map(doc =>

    {doc.col.title}

    )} - {this._otherDocs.length ?
    : null} - {this._otherDocs.map(doc =>

    {doc.col.title}

    )} - - ); + return
    +
    Metadata: {this.metadataMenu}
    +

    Contexts:

    + {this._docs.map(doc =>

    {doc.col.title}

    )} + {this._otherDocs.length ?
    : null} + {this._otherDocs.map(doc =>

    {doc.col.title}

    )} +
    ; } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx index 91fcad4be..28ddc19d7 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx @@ -1,4 +1,4 @@ -import React = require("react") +import React = require("react"); import AntimodeMenu from "../../AntimodeMenu"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -40,7 +40,7 @@ export default class MarqueeOptionsMenu extends AntimodeMenu { onPointerDown={this.delete}> , - ] + ]; return this.getElement(buttons); } } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 865ec8d9b..411d6bdea 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -537,7 +537,7 @@ export class DocumentView extends DocComponent(Docu return (showTitle ? 25 : 0) + 1; } - @computed get finalLayoutKey() { return this.props.layoutKey || "layout" } + @computed get finalLayoutKey() { return this.props.layoutKey || "layout"; } childScaling = () => (this.layoutDoc.fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); @computed get contents() { trace(); diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index f7b6e92d9..269a3ca68 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -45,7 +45,6 @@ position: relative; overflow: auto; display: inline-block; - padding: 10px 10px; width: 100%; height: 100%; } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index ec8d8be11..77790a708 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -654,7 +654,7 @@ export class PDFViewer extends DocAnnotatableComponent -
    +
    ; } @computed get pdfViewerDiv() { return
    ; -- cgit v1.2.3-70-g09d2 From 7ef52a87d1731770c6e1a8cd1aef31cb384fff05 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 21 Nov 2019 16:27:56 -0500 Subject: made textbox sidebar toggle a widget. fixed isAnimating stuff. made TraceMobx to simplify tracing --- .../collectionFreeForm/CollectionFreeFormView.tsx | 16 +++--- .../views/nodes/CollectionFreeFormDocumentView.tsx | 13 ++--- src/client/views/nodes/DocumentView.tsx | 7 ++- src/client/views/nodes/FormattedTextBox.scss | 24 +++++++- src/client/views/nodes/FormattedTextBox.tsx | 66 +++++++++++++--------- src/client/views/nodes/ImageBox.tsx | 3 +- src/client/views/pdf/PDFViewer.tsx | 5 +- src/new_fields/documentSchemas.ts | 2 +- src/new_fields/util.ts | 6 +- 9 files changed, 89 insertions(+), 53 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.scss') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8325ffe99..b2344771d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -40,6 +40,7 @@ import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import { computedFn, keepAlive } from "mobx-utils"; +import { TraceMobx } from "../../../../new_fields/util"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -621,12 +622,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } getCalculatedPositions(params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): { x?: number, y?: number, z?: number, width?: number, height?: number, transition?: string, state?: any } { - const script = this.Document.arrangeScript; - const result = script && script.script.run(params, console.log); - const layoutDoc = Doc.Layout(params.doc); - if (result && result.success) { + const result = this.Document.arrangeScript?.script.run(params, console.log); + if (result?.success) { return { ...result, transition: "transform 1s" }; } + const layoutDoc = Doc.Layout(params.doc); return { x: Cast(params.doc.x, "number"), y: Cast(params.doc.y, "number"), z: Cast(params.doc.z, "number"), width: Cast(layoutDoc.width, "number"), height: Cast(layoutDoc.height, "number") }; } @@ -653,7 +653,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } } - childDataProvider = computedFn(function childDataProvider(doc: Doc) { return (this as any)._layoutPoolData.get(doc[Id]); }); + childDataProvider = computedFn(function childDataProvider(doc: Doc) { return (this as any)._layoutPoolData.get(doc[Id]); }.bind(this)); doPivotLayout(poolData: ObservableMap) { return computePivotLayout(poolData, this.props.Document, this.childDocs, @@ -667,9 +667,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let elements = initResult && initResult.success ? this.viewDefsToJSX(initResult.result.views) : []; this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map((pair, i) => { + const data = poolData.get(pair.layout[Id]); const pos = this.getCalculatedPositions({ doc: pair.layout, index: i, collection: this.Document, docs: layoutDocs, state }); state = pos.state === undefined ? state : pos.state; - let data = this._layoutPoolData.get(pair.layout[Id]); if (!data || pos.x !== data.x || pos.y !== data.y || pos.z !== data.z || pos.width !== data.width || pos.height !== data.height || pos.transition !== data.transition) { runInAction(() => poolData.set(pair.layout[Id], pos)); } @@ -695,7 +695,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } componentDidMount() { - this._layoutComputeReaction = reaction(() => { trace(); return this.doLayoutComputation }, + this._layoutComputeReaction = reaction(() => { TraceMobx(); return this.doLayoutComputation }, action((computation: { elements: ViewDefResult[] }) => computation && (this._layoutElements = computation.elements)), { fireImmediately: true, name: "doLayout" }); } @@ -845,7 +845,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return eles; } render() { - trace(); + TraceMobx(); // update the actual dimensions of the collection so that they can inquired (e.g., by a minimap) // this.Document.fitX = this.contentBounds && this.contentBounds.x; // this.Document.fitY = this.contentBounds && this.contentBounds.y; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 0badbd3fe..c85b59488 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -10,6 +10,7 @@ import "./CollectionFreeFormDocumentView.scss"; import { DocumentView, DocumentViewProps } from "./DocumentView"; import React = require("react"); import { PositionDocument } from "../../../new_fields/documentSchemas"; +import { TraceMobx } from "../../../new_fields/util"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { dataProvider?: (doc: Doc) => { x: number, y: number, width: number, height: number, z: number, transition?: string } | undefined; @@ -56,11 +57,9 @@ export class CollectionFreeFormDocumentView extends DocComponent [this.props.Document.animateToPos, this.props.Document.isAnimating], - () => { - const target = this.props.Document.animateToPos ? Array.from(Cast(this.props.Document.animateToPos, listSpec("number"))!) : undefined; - this._animPos = !target ? undefined : target[2] ? [NumCast(this.layoutDoc.x), NumCast(this.layoutDoc.y)] : this.props.ScreenToLocalTransform().transformPoint(target[0], target[1]); - }, { fireImmediately: true }); + this._disposer = reaction(() => this.props.Document.animateToPos ? Array.from(Cast(this.props.Document.animateToPos, listSpec("number"))!) : undefined, + target => this._animPos = !target ? undefined : target[2] ? [NumCast(this.layoutDoc.x), NumCast(this.layoutDoc.y)] : this.props.ScreenToLocalTransform().transformPoint(target[0], target[1]), + { fireImmediately: true }); } contentScaling = () => this.nativeWidth > 0 && !this.props.Document.ignoreAspect ? this.width / this.nativeWidth : 1; @@ -88,7 +87,7 @@ export class CollectionFreeFormDocumentView extends DocComponent this.dataProvider ? this.dataProvider.height : this.panelHeight(); render() { - trace(); + TraceMobx(); return
    (Docu @computed get finalLayoutKey() { return this.props.layoutKey || "layout"; } childScaling = () => (this.layoutDoc.fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); @computed get contents() { - trace(); + TraceMobx(); return ((Docu } @computed get innards() { - trace(); + TraceMobx(); const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined; const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.getLayoutPropStr("showTitle"); const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.getLayoutPropStr("showCaption"); @@ -669,7 +670,7 @@ export class DocumentView extends DocComponent(Docu onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} onPointerEnter={e => Doc.BrushDoc(this.props.Document)} onPointerLeave={e => Doc.UnBrushDoc(this.props.Document)} style={{ - transition: this.Document.isAnimating !== undefined ? ".5s linear" : StrCast(this.Document.transition), + transition: this.Document.isAnimating ? ".5s linear" : StrCast(this.Document.transition), pointerEvents: this.ignorePointerEvents ? "none" : "all", color: StrCast(this.Document.color), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 269a3ca68..77cdd3d42 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -27,6 +27,8 @@ pointer-events: all; overflow-y: auto; max-height: 100%; + display: flex; + flex-direction: row; .formattedTextBox-dictation { height: 20px; @@ -48,10 +50,28 @@ width: 100%; height: 100%; } -.formattedTextBox-sidebar,.formattedTextBox-sidebar-inking { - border-left: solid 1px black; +.formattedTextBox-sidebar-handle { + position: absolute; + top: calc(50% - 17.5px); + width: 10px; + height: 35px; + background: lightgray; + border-radius: 20px; +} +.formattedTextBox-cont > .formattedTextBox-sidebar-handle { + right: 0; + left: unset; +} +.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-inking { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 5201f9bdc..86a32eb22 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -47,6 +47,7 @@ import { documentSchema } from '../../../new_fields/documentSchemas'; import { AudioBox } from './AudioBox'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { InkTool } from '../../../new_fields/InkField'; +import { TraceMobx } from '../../../new_fields/util'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -358,9 +359,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } } + toggleSidebar = () => this.props.Document.sidebarWidthPercent = StrCast(this.props.Document.sidebarWidthPercent, "0%") === "0%" ? "25%" : "0%"; + specificContextMenu = (e: React.MouseEvent): void => { let funcs: ContextMenuProps[] = []; - funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.props.Document.sidebarWidthPercent = StrCast(this.props.Document.sidebarWidthPercent, "0%") === "0%" ? "25%" : "0%"; }, icon: "expand-arrows-alt" }); + funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.toggleSidebar() }, icon: "expand-arrows-alt" }); funcs.push({ description: "Record Bullet", event: () => { e.stopPropagation(); this.recordBullet(); }, icon: "expand-arrows-alt" }); ["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option => funcs.push({ @@ -997,13 +1000,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & if (!this._undoTyping) { this._undoTyping = UndoManager.StartBatch("undoTyping"); } - if (this._recording) { this.stopDictation(true); setTimeout(() => this.recordDictation(), 250); } + if (this._recording) { + this.stopDictation(true); + setTimeout(() => this.recordDictation(), 250); + } } @action tryUpdateHeight() { - let scrollHeight = this._ref.current ? this._ref.current.scrollHeight : 0; - if (!this.layoutDoc.isAnimating && this.layoutDoc.autoHeight && scrollHeight !== 0 && + const scrollHeight = this._ref.current?.scrollHeight; + if (!this.layoutDoc.animateToPos && this.layoutDoc.autoHeight && scrollHeight && getComputedStyle(this._ref.current!.parentElement!).top === "0px") { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation let nh = this.Document.isTemplateField ? 0 : NumCast(this.dataDoc.nativeHeight, 0); let dh = NumCast(this.layoutDoc.height, 0); @@ -1016,7 +1022,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & @computed get sidebarWidth() { return Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth(); } @computed get annotationsKey() { return "annotations"; } render() { - trace(); + TraceMobx(); let rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; let interactive = InkingControl.Instance.selectedTool || this.layoutDoc.isBackground; if (this.props.isSelected()) { @@ -1050,29 +1056,33 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
    - {this.sidebarWidthPercent === "0%" ? (null) :
    - this.props.PanelHeight()} - PanelWidth={() => this.sidebarWidth} - annotationsKey={this.annotationsKey} - isAnnotationOverlay={true} - focus={this.props.focus} - isSelected={this.props.isSelected} - select={emptyFunction} - active={this.annotationsActive} - ContentScaling={returnOne} - whenActiveChanged={this.whenActiveChanged} - removeDocument={this.removeDocument} - moveDocument={this.moveDocument} - addDocument={this.addDocument} - CollectionView={undefined} - ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth), 0)} - ruleProvider={undefined} - renderDepth={this.props.renderDepth + 1} - ContainingCollectionDoc={this.props.ContainingCollectionDoc} - chromeCollapsed={true}> - -
    } + {this.sidebarWidthPercent === "0%" ? +
    e.stopPropagation()} onClick={e => this.toggleSidebar()} /> : +
    + this.props.PanelHeight()} + PanelWidth={() => this.sidebarWidth} + annotationsKey={this.annotationsKey} + isAnnotationOverlay={true} + focus={this.props.focus} + isSelected={this.props.isSelected} + select={emptyFunction} + active={this.annotationsActive} + ContentScaling={returnOne} + whenActiveChanged={this.whenActiveChanged} + removeDocument={this.removeDocument} + moveDocument={this.moveDocument} + addDocument={this.addDocument} + CollectionView={undefined} + ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth), 0)} + ruleProvider={undefined} + renderDepth={this.props.renderDepth + 1} + ContainingCollectionDoc={this.props.ContainingCollectionDoc} + chromeCollapsed={true}> + +
    e.stopPropagation()} onClick={e => this.toggleSidebar()} /> +
    }
    { this._recording ? this.stopDictation(true) : this.recordDictation(); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 5d40e274f..d102c9600 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -27,6 +27,7 @@ import React = require("react"); import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { documentSchema } from '../../../new_fields/documentSchemas'; import { Id } from '../../../new_fields/FieldSymbols'; +import { TraceMobx } from '../../../new_fields/util'; var requestImageSize = require('../../util/request-image-size'); var path = require('path'); const { Howl } = require('howler'); @@ -268,7 +269,7 @@ export class ImageBox extends DocAnnotatableComponent {this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map((anno, index) => )} @@ -674,7 +675,7 @@ export class PDFViewer extends DocAnnotatableComponent this._zoomed; @computed get contentScaling() { return this.props.ContentScaling() } render() { - trace(); + TraceMobx(); return !this.extensionDoc ? (null) :
    Date: Wed, 27 Nov 2019 16:45:57 -0500 Subject: committing:w --- src/client/views/nodes/FormattedTextBox.scss | 45 +++++++++++++++------------- src/client/views/nodes/FormattedTextBox.tsx | 2 +- 2 files changed, 26 insertions(+), 21 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 diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 657b4b406..bad912944 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -1091,7 +1091,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.stopPropagation(); }} > + style={{ color: this._recording ? "red" : "blue", opacity: this._recording ? 1 : 0.5 }} icon={"microphone"} size="sm" />
    ); -- 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