diff options
| author | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-03-10 11:57:30 -0500 |
|---|---|---|
| committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-03-10 11:57:30 -0500 |
| commit | 89b7b2ae27cbab6a7edd5fa3759949afe2cd2f71 (patch) | |
| tree | e3d034d928a63f478ea705c083a3f74764e38d03 /src/client/views/nodes | |
| parent | e7dd6dbdf8d01cef390ff65c0948e5e70ac232cf (diff) | |
| parent | 80597c4780b1e8833d3742339836815d388356d2 (diff) | |
conflicts
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/DocHolderBox.scss | 15 | ||||
| -rw-r--r-- | src/client/views/nodes/DocHolderBox.tsx | 212 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentContentsView.tsx | 3 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 6 | ||||
| -rw-r--r-- | src/client/views/nodes/FilterBox.tsx | 56 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 190 |
7 files changed, 126 insertions, 358 deletions
diff --git a/src/client/views/nodes/DocHolderBox.scss b/src/client/views/nodes/DocHolderBox.scss deleted file mode 100644 index 6a9ef0b6f..000000000 --- a/src/client/views/nodes/DocHolderBox.scss +++ /dev/null @@ -1,15 +0,0 @@ -.documentBox-container { - width: 100%; - height: 100%; - pointer-events: all; - position: absolute; - .documentBox-lock { - margin: auto; - color: white; - position: absolute; - padding: 3px; - } - .contentFittingDocumentView { - position: absolute; - } -}
\ No newline at end of file diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx deleted file mode 100644 index 765751a65..000000000 --- a/src/client/views/nodes/DocHolderBox.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, IReactionDisposer, reaction } from "mobx"; -import { observer } from "mobx-react"; -import { Doc, Field } from "../../../fields/Doc"; -import { collectionSchema, documentSchema } from "../../../fields/documentSchemas"; -import { listSpec, makeInterface } from "../../../fields/Schema"; -import { ComputedField } from "../../../fields/ScriptField"; -import { Cast, NumCast, StrCast } from "../../../fields/Types"; -import { TraceMobx } from "../../../fields/util"; -import { returnFalse } from "../../../Utils"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { DragManager } from "../../util/DragManager"; -import { undoBatch } from "../../util/UndoManager"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; -import { ViewBoxAnnotatableComponent } from "../DocComponent"; -import { StyleProp } from "../StyleProvider"; -import "./DocHolderBox.scss"; -import { DocumentView } from "./DocumentView"; -import { FieldView, FieldViewProps } from "./FieldView"; -import React = require("react"); - -type DocHolderBoxSchema = makeInterface<[typeof documentSchema, typeof collectionSchema]>; -const DocHolderBoxDocument = makeInterface(documentSchema, collectionSchema); - -@observer -export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, DocHolderBoxSchema>(DocHolderBoxDocument) { - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocHolderBox, fieldKey); } - _prevSelectionDisposer: IReactionDisposer | undefined; - _dropDisposer?: DragManager.DragDropDisposer; - _selections: Doc[] = []; - _contRef = React.createRef<HTMLDivElement>(); - _curSelection = -1; - componentDidMount() { - this._prevSelectionDisposer = reaction(() => this.dataDoc[this.fieldKey], (data) => { - if (data instanceof Doc && !this.isSelectionLocked()) { - this._selections.indexOf(data) !== -1 && this._selections.splice(this._selections.indexOf(data), 1); - this._selections.push(data); - this._curSelection = this._selections.length - 1; - } - }); - } - componentWillUnmount() { - this._prevSelectionDisposer?.(); - } - specificContextMenu = (e: React.MouseEvent): void => { - const funcs: ContextMenuProps[] = []; - funcs.push({ description: (this.isSelectionLocked() ? "Show" : "Lock") + " Selection", event: () => this.toggleLockSelection, icon: "expand-arrows-alt" }); - funcs.push({ description: (this.layoutDoc.excludeCollections ? "Include" : "Exclude") + " Collections", event: () => this.layoutDoc.excludeCollections = !this.layoutDoc.excludeCollections, icon: "expand-arrows-alt" }); - funcs.push({ description: `${this.layoutDoc.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.layoutDoc.forceActive = !this.layoutDoc.forceActive, icon: "project-diagram" }); - funcs.push({ description: `Show ${this.layoutDoc.childLayoutTemplateName !== "keyValue" ? "key values" : "contents"}`, event: () => this.layoutDoc.childLayoutString = this.layoutDoc.childLayoutString ? undefined : "<KeyValueBox {...props} />", icon: "project-diagram" }); - - ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); - } - lockSelection = () => { - this.dataDoc[this.fieldKey] = this.dataDoc[this.fieldKey]; - } - showSelection = () => { - this.dataDoc[this.fieldKey] = ComputedField.MakeFunction(`selectedDocs(self,this.excludeCollections,[_last_])?.[0]`); - } - isSelectionLocked = () => { - const kvpstring = Field.toKeyValueString(this.dataDoc, this.fieldKey); - return !kvpstring || kvpstring.includes("DOC"); - } - toggleLockSelection = () => { - !this.isSelectionLocked() ? this.lockSelection() : this.showSelection(); - return true; - } - prevSelection = () => { - this.lockSelection(); - if (this._curSelection > 0) { - this.dataDoc[this.fieldKey] = this._selections[--this._curSelection]; - return true; - } - } - nextSelection = () => { - if (this._curSelection < this._selections.length - 1 && this._selections.length) { - this.dataDoc[this.fieldKey] = this._selections[++this._curSelection]; - return true; - } - } - onPointerDown = (e: React.PointerEvent) => { - if (this.active() && e.button === 0 && !e.ctrlKey) { - e.stopPropagation(); - } - } - onLockClick = (e: React.MouseEvent) => { - this.toggleLockSelection(); - (e.nativeEvent as any).formattedHandled = true; - e.stopPropagation(); - } - get xPad() { return NumCast(this.rootDoc._xPadding); } - get yPad() { return NumCast(this.rootDoc._yPadding); } - onClick = (e: React.MouseEvent) => { - let hitWidget: boolean | undefined = false; - if (this._contRef.current!.getBoundingClientRect().top + this.yPad > e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); - else if (this._contRef.current!.getBoundingClientRect().bottom - this.yPad < e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); - else { - if (this._contRef.current!.getBoundingClientRect().left + this.xPad > e.clientX) hitWidget = this.prevSelection(); - if (this._contRef.current!.getBoundingClientRect().right - this.xPad < e.clientX) hitWidget = this.nextSelection(); - } - if (hitWidget) { - (e.nativeEvent as any).formattedHandled = true; - e.stopPropagation(); - } - } - pwidth = () => this.props.PanelWidth() - 2 * this.xPad; - pheight = () => this.props.PanelHeight() - 2 * this.yPad; - getTransform = () => this.props.ScreenToLocalTransform().translate(-this.xPad, -this.yPad); - isActive = (outsideReaction: boolean) => this.active(outsideReaction) || this.props.renderDepth <= 1; - layoutTemplateDoc = () => Cast(this.layoutDoc.childLayoutTemplate, Doc, null); - get renderContents() { - const containedDoc = Cast(this.dataDoc[this.fieldKey], Doc, null); - const layoutTemplate = StrCast(this.layoutDoc.childLayoutString); - const contents = !(containedDoc instanceof Doc) || - Cast(containedDoc[Doc.LayoutFieldKey(containedDoc)], listSpec(Doc), null)?.includes(this.rootDoc) - ? (null) : this.layoutDoc.childLayoutString || this.layoutTemplateDoc() ? - <DocumentView - Document={containedDoc} - DataDoc={undefined} - docFilters={this.props.docFilters} - docRangeFilters={this.props.docRangeFilters} - searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={this as any} // bcz: hack! need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked. currently, the up selector allows only a containing collection to be selected - ContainingCollectionDoc={undefined} - styleProvider={this.props.styleProvider} - layerProvider={this.props.layerProvider} - docViewPath={this.props.docViewPath} - LayoutTemplateString={layoutTemplate} - LayoutTemplate={this.layoutTemplateDoc} - rootSelected={this.props.isSelected} - addDocument={this.props.addDocument} - moveDocument={this.props.moveDocument} - removeDocument={this.props.removeDocument} - addDocTab={this.props.addDocTab} - pinToPres={this.props.pinToPres} - ScreenToLocalTransform={this.getTransform} - renderDepth={containedDoc.type !== DocumentType.DOCHOLDER && !this.props.renderDepth ? 0 : this.props.renderDepth + 1} - PanelWidth={this.pwidth} - PanelHeight={this.pheight} - focus={this.props.focus} - parentActive={this.isActive} - dontRegisterView={true} - whenActiveChanged={this.props.whenActiveChanged} - bringToFront={returnFalse} /> : - <DocumentView - Document={containedDoc} - DataDoc={undefined} - docFilters={this.props.docFilters} - docRangeFilters={this.props.docRangeFilters} - searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={this as any} // bcz: hack! need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked. currently, the up selector allows only a containing collection to be selected - ContainingCollectionDoc={undefined} - styleProvider={this.props.styleProvider} - layerProvider={this.props.layerProvider} - docViewPath={this.props.docViewPath} - ignoreAutoHeight={true} - LayoutTemplateString={layoutTemplate} - LayoutTemplate={this.layoutTemplateDoc} - rootSelected={this.props.isSelected} - addDocument={this.props.addDocument} - moveDocument={this.props.moveDocument} - removeDocument={this.props.removeDocument} - addDocTab={this.props.addDocTab} - pinToPres={this.props.pinToPres} - ScreenToLocalTransform={this.getTransform} - renderDepth={containedDoc.type !== DocumentType.DOCHOLDER && !this.props.renderDepth ? 0 : this.props.renderDepth + 1} - PanelWidth={this.pwidth} - PanelHeight={this.pheight} - focus={this.props.focus} - parentActive={this.isActive} - dontRegisterView={true} - whenActiveChanged={this.props.whenActiveChanged} - bringToFront={returnFalse} - />; - return contents; - } - render() { - const containedDoc = Cast(this.dataDoc[this.fieldKey], Doc, null); - TraceMobx(); - return !containedDoc ? (null) : <div className="documentBox-container" ref={this._contRef} - onContextMenu={this.specificContextMenu} - onPointerDown={this.onPointerDown} onClick={this.onClick} - style={{ - background: this.props.styleProvider?.(containedDoc, this.props, StyleProp.BackgroundColor), - border: `#00000021 solid ${this.xPad}px`, - borderTop: `#0000005e solid ${this.yPad}px`, - borderBottom: `#0000005e solid ${this.yPad}px`, - }}> - {this.renderContents} - <div className="documentBox-lock" onClick={this.onLockClick} ref={this.createDropTarget} - style={{ marginTop: - this.yPad, background: "black" }}> - <FontAwesomeIcon icon={this.isSelectionLocked() ? "lock" : "unlock"} size="sm" /> - </div> - </div >; - } - - @undoBatch - @action - drop = (e: Event, de: DragManager.DropEvent) => { - const docDragData = de.complete.docDragData; - if (docDragData?.draggedDocuments[0].type === DocumentType.FONTICON) { - const doc = Cast(docDragData.draggedDocuments[0].dragFactory, Doc, null); - this.layoutDoc.childLayoutTemplate = doc; - } - } - protected createDropTarget = (ele: HTMLDivElement) => { - this._dropDisposer?.(); - ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.rootDoc)); - } - -} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 32542d056..2f7923574 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -16,7 +16,6 @@ import { FunctionPlotBox } from "./FunctionPlotBox"; import { SliderBox } from "./SliderBox"; import { LinkBox } from "./LinkBox"; import { ScriptingBox } from "./ScriptingBox"; -import { DocHolderBox } from "./DocHolderBox"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import { FontIconBox } from "./FontIconBox"; @@ -225,7 +224,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, LabelBox, EquationBox, SliderBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, SearchBox, FilterBox, FunctionPlotBox, - ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, DocHolderBox, LinkBox, ScriptingBox, + ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, LinkBox, ScriptingBox, ScreenshotBox, HTMLtag, ComparisonBox }} bindings={bindings} diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 085ffae26..d62061aea 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -280,7 +280,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp TraceMobx(); const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link"; - const buttonTitle = "Tap to view links"; + const buttonTitle = "Tap to view links; double tap to open link collection"; const title = this.props.InMenu ? menuTitle : buttonTitle; return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? (null) : diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 83022a759..ebc65002f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -286,7 +286,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } handle1PointerMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => { - if ((e as any).formattedHandled) { e.stopPropagation; return; } if (e.cancelBubble && this.active) { this.removeMoveListeners(); } @@ -475,7 +474,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } else clickFunc(); } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself this.props.addDocTab(DocUtils.makeCustomViewClicked(Doc.MakeAlias(this.props.Document), undefined, "onClick"), "add:right"); - } else if (this.allLinks && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey && !(e.nativeEvent as any).formattedHandled) { + } else if (this.allLinks && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { this.allLinks.length && LinkManager.FollowLink(undefined, this.props.Document, this.props, e.altKey); } else { if ((this.layoutDoc.onDragStart || this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part @@ -517,13 +516,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps 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 => { - if ((e as any).formattedHandled) { e.stopPropagation(); return; } if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) return; if (e.cancelBubble && this.active) { document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView) diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index a4ae0b5a3..0f8dcad9d 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -1,8 +1,8 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, runInAction } from "mobx"; +import { computed, observable, action, trace, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { DataSym, Doc, DocListCast, DocListCastAsync, Field, Opt } from "../../../fields/Doc"; +import { DataSym, Doc, DocListCast, Field, Opt, DocListCastAsync } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { List } from "../../../fields/List"; import { RichTextField } from "../../../fields/RichTextField"; @@ -19,8 +19,6 @@ import { SearchBox } from "../search/SearchBox"; import { FieldView, FieldViewProps } from './FieldView'; import './FilterBox.scss'; import { Scripting } from "../../util/Scripting"; -import { values } from "lodash"; -import { tokenToString } from "typescript"; import { SelectionManager } from "../../util/SelectionManager"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; @@ -59,10 +57,20 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc return FilterBox._filterScope === "Current Collection" ? SelectionManager.Views()[0].Document || CollectionDockingView.Instance.props.Document : CollectionDockingView.Instance.props.Document; } + @observable _loaded = false; + componentDidMount() { + reaction(() => DocListCastAsync(CollectionDockingView.Instance.props.Document.data), + async (activeTabsAsync) => { + const activeTabs = await activeTabsAsync; + activeTabs && (await SearchBox.foreachRecursiveDocAsync(activeTabs, emptyFunction)); + runInAction(() => this._loaded = true); + }, { fireImmediately: true }); + } @computed get allDocs() { + trace(); const allDocs = new Set<Doc>(); const targetDoc = FilterBox._filterScope === "Current Collection" ? SelectionManager.Views()[0].Document || CollectionDockingView.Instance.props.Document : CollectionDockingView.Instance.props.Document; - if (targetDoc) { + if (this._loaded && targetDoc) { const activeTabs = DocListCast(targetDoc.data); SearchBox.foreachRecursiveDoc(activeTabs, (doc: Doc) => allDocs.add(doc)); setTimeout(() => targetDoc.allDocuments = new List<Doc>(Array.from(allDocs))); @@ -71,6 +79,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc } @computed get _allFacets() { + trace(); const noviceReqFields = ["author", "tags", "text", "type"]; const noviceLayoutFields: string[] = [];//["_curPage"]; const noviceFields = [...noviceReqFields, ...noviceLayoutFields]; @@ -200,12 +209,12 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`; newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" }); } else if (facetHeader !== "tags" && nonNumbers / facetValues.strings.length < .1) { - newFacet = Docs.Create.SliderDocument({ title: facetHeader, _overflow: "visible", _height: 40, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", treeViewOpen: true }); + newFacet = Docs.Create.SliderDocument({ title: facetHeader, _overflow: "visible", _fitWidth: true, _height: 40, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", treeViewOpen: true }); const newFacetField = Doc.LayoutFieldKey(newFacet); const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox - const extendedMinVal = minVal - Math.min(1, Math.abs(maxVal - minVal) * .05); - const extendedMaxVal = maxVal + Math.min(1, Math.abs(maxVal - minVal) * .05); + const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * .1)); + const extendedMaxVal = maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * .05)); newFacet[newFacetField + "-min"] = ranged === undefined ? extendedMinVal : ranged[0]; newFacet[newFacetField + "-max"] = ranged === undefined ? extendedMaxVal : ranged[1]; Doc.GetProto(newFacet)[newFacetField + "-minThumb"] = extendedMinVal; @@ -218,8 +227,8 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc newFacet.title = facetHeader; newFacet.treeViewOpen = true; newFacet.type = DocumentType.COL; - const capturedVariables = { layoutDoc: targetDoc, system: true, _stayInCollection: true, _hideContextMenu: true, dataDoc: (targetDoc.data as any)[0][DataSym] }; - newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, "${facetHeader}")`, {}, capturedVariables); + newFacet.target = targetDoc; + newFacet.data = ComputedField.MakeFunction(`readFacetData(self.target, "${facetHeader}")`); } newFacet && Doc.AddDocToList(this.dataDoc, this.props.fieldKey, newFacet); } @@ -345,6 +354,26 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc value={null} closeMenuOnSelect={false} /> + {/* @computed get flyoutpanel() { + return <div className="filterBox-flyout" style={{ width: `100%`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}> + {this._allFacets.map(facet => <label className="filterBox-flyout-facet" key={`${facet}`} onClick={e => this.facetClick(facet)}> + <input type="checkbox" onChange={emptyFunction} checked={DocListCast(this.props.Document[this.props.fieldKey]).some(d => d.title === facet)} /> + <span className="checkmark" /> + {facet} + </label>)} + </div>; + } + render() { + const facetCollection = this.props.Document; + + return this.props.dontRegisterView ? (null) : <div className="filterBox-treeView" style={{ width: "100%" }}> + <div className="filterBox-addFacet" style={{ width: "100%" }} onPointerDown={e => e.stopPropagation()}> + <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyoutpanel}> + <div className="filterBox-addFacetButton"> + <FontAwesomeIcon icon={"edit"} size={"lg"} /> + <span className="filterBox-span">Choose Facets</span> + </div> + </Flyout> */} </div> <div className="filterBox-tree" key="tree"> @@ -451,7 +480,7 @@ Scripting.addGlobal(function determineCheckedState(layoutDoc: Doc, facetHeader: } return undefined; }); -Scripting.addGlobal(function readFacetData(layoutDoc: Doc, facetHeader: string) { +Scripting.addGlobal(function readFacetData(targetDoc: Doc, facetHeader: string) { const allCollectionDocs = DocListCast(CollectionDockingView.Instance?.props.Document.allDocuments); const set = new Set<string>(); if (facetHeader === "tags") allCollectionDocs.forEach(child => Field.toString(child[facetHeader] as Field).split(":").forEach(key => set.add(key))); @@ -464,7 +493,10 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, facetHeader: string) const doc = new Doc(); doc.system = true; doc.title = facetValue.toString(); - doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(layoutDoc, facetHeader, facetValue)", {}, { layoutDoc, facetHeader, facetValue }); + doc.target = targetDoc; + doc.facetHeader = facetHeader; + doc.facetValue = facetValue; + doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(self.target, self.facetHeader, self.facetValue)"); return doc; }); return new List<Doc>(facetValueDocSet); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 0f669a544..ad11d55bf 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -15,7 +15,7 @@ import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, Wid import { documentSchema } from '../../../../fields/documentSchemas'; import applyDevTools = require("prosemirror-dev-tools"); import { removeMarkWithAttrs } from "./prosemirrorPatches"; -import { Id, Copy } from '../../../../fields/FieldSymbols'; +import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { RichTextField } from "../../../../fields/RichTextField"; @@ -90,11 +90,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp public static get DefaultLayout() { return Cast(Doc.UserDoc().defaultTextLayout, Doc, null) || StrCast(Doc.UserDoc().defaultTextLayout, null); } - public static CanAnnotate = true; public static Instance: FormattedTextBox; - public ProseRef?: HTMLDivElement; - public get EditorView() { return this._editorView; } - public get SidebarKey() { return this.fieldKey + "-sidebar"; } + public static LiveTextUndo: UndoManager.Batch | undefined; + static _highlights: string[] = ["Audio Tags", "Text from Others", "Todo Items", "Important Items", "Disagree Items", "Ignore Items"]; + static _highlightStyleSheet: any = addStyleSheet(); + static _bulletStyleSheet: any = addStyleSheet(); + static _userStyleSheet: any = addStyleSheet(); + static _canAnnotate = true; + static _hadSelection: boolean = false; private _ref: React.RefObject<HTMLDivElement> = React.createRef(); private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef(); private _editorView: Opt<EditorView>; @@ -111,6 +114,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp private _focusSpeed: Opt<number>; private _keymap: any = undefined; private _rules: RichTextRules | undefined; + private _forceUncollapse = true; // if the cursor doesn't move between clicks, then the selection will disappear for some reason. This flags the 2nd click as happening on a selection which allows bullet points to toggle + private _forceDownNode: Node | undefined; + private _downEvent: any; + private _downX = 0; + private _downY = 0; + private _break = false; + public ProseRef?: HTMLDivElement; + public get EditorView() { return this._editorView; } + public get SidebarKey() { return this.fieldKey + "-sidebar"; } @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); } @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); } @@ -121,10 +133,26 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get titleHeight() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin) || 0; } @computed get _recording() { return this.dataDoc?.audioState === "recording"; } set _recording(value) { this.dataDoc.audioState = value ? "recording" : undefined; } + @computed get config() { + this._keymap = buildKeymap(schema, this.props); + this._rules = new RichTextRules(this.props.Document, this); + return { + schema, + plugins: [ + inputRules(this._rules.inpRules), + this.richTextMenuPlugin(), + history(), + keymap(this._keymap), + keymap(baseKeymap), + new Plugin({ props: { attributes: { class: "ProseMirror-example-setup-style" } } }), + new Plugin({ view(editorView) { return new FormattedTextBoxComment(editorView); } }) + ] + }; + } public static FocusedBox: FormattedTextBox | undefined; - public static SelectOnLoad = ""; public static PasteOnLoad: ClipboardEvent | undefined; + public static SelectOnLoad = ""; public static SelectOnLoadChar = ""; public static IsFragment(html: string) { return html.indexOf("data-pm-slice") !== -1; } public static GetHref(html: string): string { @@ -205,9 +233,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.rootDoc, this.getAnchor, targetCreator), e.pageX, e.pageY); }); - const coordsT = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); - this.props.isSelected(true) && AnchorMenu.Instance.jumpTo(Math.min(coordsT.left, coordsB.left), Math.max(coordsT.bottom, coordsB.bottom)); + this.props.isSelected(true) && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom); } dispatchTransaction = (tx: Transaction) => { @@ -315,7 +342,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } // needs a better API for taking in a set of words with target documents instead of just one target - public hyperlinkTerms = (terms: string[], target: Doc) => { + hyperlinkTerms = (terms: string[], target: Doc) => { if (this._editorView && (this._editorView as any).docView && terms.some(t => t)) { const res1 = terms.filter(t => t).map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term)); let tr = this._editorView.state.tr; @@ -335,7 +362,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._editorView.dispatch(tr); } } - public highlightSearchTerms = (terms: string[], backward: boolean) => { + highlightSearchTerms = (terms: string[], backward: boolean) => { if (this._editorView && (this._editorView as any).docView && terms.some(t => t)) { const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight); const activeMark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight, { selected: true }); @@ -364,7 +391,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } } - public unhighlightSearchTerms = () => { + unhighlightSearchTerms = () => { if (window.screen.width < 600) null; else if (this._editorView && (this._editorView as any).docView) { const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight); @@ -407,18 +434,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp // embed document when dragg marked as embed } else if (de.embedKey) { const target = dragData.droppedDocuments[0]; - // const link = DocUtils.MakeLink({ doc: this.dataDoc, ctx: this.props.ContainingCollectionDoc }, { doc: target }, "Embedded Doc:" + target.title); - // if (link) { target._fitToBox = true; const node = schema.nodes.dashDoc.create({ width: target[WidthSym](), height: target[HeightSym](), - title: "dashDoc", docid: target[Id], + title: "dashDoc", + docid: target[Id], float: "right" }); const view = this._editorView!; view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node)); e.stopPropagation(); - // } } // otherwise, fall through to outer collection to handle drop } } @@ -467,7 +492,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return ret; } - static _highlights: string[] = ["Audio Tags", "Text from Others", "Todo Items", "Important Items", "Disagree Items", "Ignore Items"]; updateHighlights = () => { clearStyleSheetRules(FormattedTextBox._userStyleSheet); if (FormattedTextBox._highlights.indexOf("Audio Tags") === -1) { @@ -551,9 +575,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp }, icon: "expand-arrows-alt" })); - const uicontrols: ContextMenuProps[] = []; - uicontrols.push({ description: `${FormattedTextBox.CanAnnotate ? "Hide" : "Show"} Annotation Bar`, event: () => FormattedTextBox.CanAnnotate = !FormattedTextBox.CanAnnotate, icon: "expand-arrows-alt" }); + uicontrols.push({ description: `${FormattedTextBox._canAnnotate ? "Hide" : "Show"} Annotation Bar`, event: () => FormattedTextBox._canAnnotate = !FormattedTextBox._canAnnotate, icon: "expand-arrows-alt" }); uicontrols.push({ description: !this.Document._noSidebar ? "Hide Sidebar Handle" : "Show Sidebar Handle", event: () => this.layoutDoc._noSidebar = !this.layoutDoc._noSidebar, icon: "expand-arrows-alt" }); uicontrols.push({ description: `${this.layoutDoc._showAudio ? "Hide" : "Show"} Dictation Icon`, event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" }); uicontrols.push({ description: "Show Highlights...", noexpand: true, subitems: highlighting, icon: "hand-point-right" }); @@ -612,10 +635,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (results && [DictationManager.Controls.Infringed].includes(results)) { DictationManager.Controls.stop(); } - //this._editorView!.focus(); }); } - stopDictation = (abort: boolean) => { DictationManager.Controls.stop(!abort); }; + stopDictation = (abort: boolean) => DictationManager.Controls.stop(!abort); setDictationContent = (value: string) => { if (this._editorView) { @@ -643,26 +665,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } } - @computed get config() { - this._keymap = buildKeymap(schema, this.props); - this._rules = new RichTextRules(this.props.Document, this); - return { - schema, - plugins: [ - inputRules(this._rules.inpRules), - this.richTextMenuPlugin(), - history(), - keymap(this._keymap), - keymap(baseKeymap), - new Plugin({ - props: { - attributes: { class: "ProseMirror-example-setup-style" } - } - }), new Plugin({ view(editorView) { return new FormattedTextBoxComment(editorView); } }) - ] - }; - } - makeLinkAnchor(anchorDoc?: Doc, location?: string, targetHref?: string, title?: string) { const state = this._editorView?.state; if (state) { @@ -692,10 +694,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return anchorDoc ?? this.rootDoc; } - IsActive = () => { - return this.active();//this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; - } - scrollFocus = (doc: Doc, smooth: boolean) => { const anchorId = doc[Id]; const findAnchorFrag = (frag: Fragment, editor: EditorView) => { @@ -753,7 +751,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp componentDidMount() { this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. - this.props.contentsActive?.(this.IsActive); + this.props.contentsActive?.(this.active); this._cachedLinks = DocListCast(this.Document.links); this._disposers.autoHeight = reaction(() => ({ scrollHeight: this.scrollHeight, autoHeight: this.autoHeight, width: NumCast(this.layoutDoc._width) }), ({ width, autoHeight, scrollHeight }) => width && autoHeight && this.resetNativeHeight(scrollHeight) @@ -771,7 +769,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp instance => { if (instance) { this.pullFromGoogleDoc(this.checkState); - this.dataDoc[GoogleRef] && this.dataDoc.unchanged && runInAction(() => instance.isAnimatingFetch = true); + this.dataDoc[GoogleRef] && this.dataDoc.googleDocUnchanged && runInAction(() => instance.isAnimatingFetch = true); } } ); @@ -801,8 +799,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp () => { if (!DocumentButtonBar.hasPulledHack) { DocumentButtonBar.hasPulledHack = true; - const unchanged = this.dataDoc.unchanged; - this.pullFromGoogleDoc(unchanged ? this.checkState : this.updateState); + this.pullFromGoogleDoc(this.dataDoc.googleDocUnchanged ? this.checkState : this.updateState); } } ); @@ -877,19 +874,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const response = await GoogleApiClientUtils.Docs.write({ reference, content, mode }); response && (this.dataDoc[GoogleRef] = response.documentId); const pushSuccess = response !== undefined && !("errors" in response); - dataDoc.unchanged = pushSuccess; + dataDoc.googleDocUnchanged = pushSuccess; DocumentButtonBar.Instance.startPushOutcome(pushSuccess); } }; const undo = () => { - if (!exportState) { - return; - } - const content: GoogleApiClientUtils.Docs.Content = { - text: exportState.text, - requests: [] - }; - if (reference && content) { + if (exportState && reference) { + const content: GoogleApiClientUtils.Docs.Content = { + text: exportState.text, + requests: [] + }; GoogleApiClientUtils.Docs.write({ reference, content, mode }); } }; @@ -922,7 +916,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp }, 0); dataDoc.title = exportState.title; this.dataDoc["title-custom"] = true; - dataDoc.unchanged = true; + dataDoc.googleDocUnchanged = true; } else { delete dataDoc[GoogleRef]; } @@ -934,7 +928,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const equalContent = isEqual(this._editorView.state.doc, exportState.state.doc); const equalTitles = dataDoc.title === exportState.title; const unchanged = equalContent && equalTitles; - dataDoc.unchanged = unchanged; + dataDoc.googleDocUnchanged = unchanged; DocumentButtonBar.Instance.setPullState(unchanged); } } @@ -1094,7 +1088,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp selectAll(this._editorView!.state, this._editorView?.dispatch); this.startUndoTypingBatch(); } - } selectOnLoad && this._editorView!.focus(); // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. @@ -1112,11 +1105,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none"); } - _downEvent: any; - _downX = 0; - _downY = 0; - _break = false; - _collapsed = false; onPointerDown = (e: React.PointerEvent): void => { if ((e.target as any).tagName === "AUDIOTAG") { e.preventDefault(); @@ -1164,9 +1152,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp document.removeEventListener("pointerup", this.onSelectEnd); document.removeEventListener("pointermove", this.onSelectMove); } - onPointerUp = (e: React.PointerEvent): void => { - if (!this._editorView?.state.selection.empty && FormattedTextBox.CanAnnotate) this.setupAnchorMenu(); + if (!this._editorView?.state.selection.empty && FormattedTextBox._canAnnotate) this.setupAnchorMenu(); if (!this._downEvent) return; this._downEvent = false; if (!(e.nativeEvent as any).formattedHandled && this.active(true)) { @@ -1183,13 +1170,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp e.stopPropagation(); } } - @action onDoubleClick = (e: React.MouseEvent): void => { FormattedTextBoxComment.textBox = this; if (e.button === 0 && this.props.isSelected(true) && !e.altKey && !e.ctrlKey && !e.metaKey) { if (e.clientX < this.ProseRef!.getBoundingClientRect().right) { // stop propagation if not in sidebar - e.stopPropagation(); // if the text box is selected, then it consumes all down events + e.stopPropagation(); // if the text box is selected, then it consumes all click events } } if (e.button === 2 || (e.button === 0 && e.ctrlKey)) { @@ -1203,7 +1189,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp e.stopPropagation(); } } - @action onFocused = (e: React.FocusEvent): void => { FormattedTextBox.FocusedBox = this; @@ -1230,17 +1215,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } } onPointerWheel = (e: React.WheelEvent): void => { - // if a text note is not selected and scrollable, this prevents us from being able to scroll and zoom out at the same time + // if a text note is selected and scrollable, stop event to prevent, say, outer collection from zooming. if ((this.props.rootSelected(true) || this.props.isSelected(true)) || e.currentTarget.scrollHeight > e.currentTarget.clientHeight) { e.stopPropagation(); } } - - static _highlightStyleSheet: any = addStyleSheet(); - static _bulletStyleSheet: any = addStyleSheet(); - static _userStyleSheet: any = addStyleSheet(); - _forceUncollapse = true; // if the cursor doesn't move between clicks, then the selection will disappear for some reason. This flags the 2nd click as happening on a selection which allows bullet points to toggle - _forceDownNode: Node | undefined; onClick = (e: React.MouseEvent): void => { if (Math.abs(e.clientX - this._downX) > 4 || Math.abs(e.clientY - this._downY) > 4) { this._forceDownNode = undefined; @@ -1276,7 +1255,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._forceUncollapse = !(this._editorView!.root as any).getSelection().isCollapsed; this._forceDownNode = (this._editorView!.state.selection as NodeSelection)?.node; } - // 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, collapse: boolean, highlightOnly: boolean, downNode: Node | undefined = undefined, selectOrderedList: boolean = false) { this._forceUncollapse = false; @@ -1302,8 +1280,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (selectOrderedList || (!collapse && listNode.attrs.visibility)) { this._editorView.dispatch(this._editorView.state.tr.setSelection(new NodeSelection(selectOrderedList ? $olistPos! : listPos!))); } else if (!listNode.attrs.visibility || downNode === listNode) { - this._editorView.dispatch(this._editorView.state.tr.setNodeMarkup(clickPos.pos, listNode.type, { ...listNode.attrs, visibility: !listNode.attrs.visibility })); - this._editorView.dispatch(this._editorView.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, clickPos.pos))); + const tr = this._editorView.state.tr.setNodeMarkup(clickPos.pos, listNode.type, { ...listNode.attrs, visibility: !listNode.attrs.visibility }); + this._editorView.dispatch(tr.setSelection(TextSelection.create(tr.doc, clickPos.pos))); } } addStyleSheetRule(FormattedTextBox._bulletStyleSheet, olistNode.attrs.mapStyle + olistNode.attrs.bulletStyle + ":hover:before", { background: "lightgray" }); @@ -1321,30 +1299,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp view.root.removeEventListener("mouseup", originalUpHandler); view.mouseDown.up = (e: MouseEvent) => { !(e as any).formattedHandled && originalUpHandler(e); - // e.stopPropagation(); (e as any).formattedHandled = true; }; view.root.addEventListener("mouseup", view.mouseDown.up); } } - - public startUndoTypingBatch() { + startUndoTypingBatch() { !this._undoTyping && (this._undoTyping = UndoManager.StartBatch("undoTyping")); } - public endUndoTypingBatch() { const wasUndoing = this._undoTyping; this._undoTyping?.end(); this._undoTyping = undefined; return wasUndoing; } - public static LiveTextUndo: UndoManager.Batch | undefined; - public static HadSelection: boolean = false; onBlur = (e: any) => { if (RichTextMenu.Instance?.view === this._editorView && !this.props.isSelected(true)) { RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined); } - FormattedTextBox.HadSelection = window.getSelection()?.toString() !== ""; + FormattedTextBox._hadSelection = window.getSelection()?.toString() !== ""; this.endUndoTypingBatch(); FormattedTextBox.LiveTextUndo?.end(); @@ -1363,7 +1336,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._lastText = curText; } } - onKeyDown = (e: React.KeyboardEvent) => { // single line text boxes need to pass through tab/enter/backspace so that their containers can respond (eg, an outline container) if (this.rootDoc._singleLine && ((e.key === "Backspace" && !this.dataDoc[this.fieldKey]?.Text) || ["Tab", "Enter"].includes(e.key))) { @@ -1385,36 +1357,33 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._rules!.EnteringStyle = false; } e.stopPropagation(); - if (e.key === "Escape") { - this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); - (document.activeElement as any).blur?.(); - SelectionManager.DeselectAll(); - RichTextMenu.Instance.updateMenu(undefined, undefined, undefined); - } else { - if (e.key === "Tab" || e.key === "Enter") { - if (e.key === "Enter") this.insertTime(); - e.preventDefault(); - } - if (e.key === " " || this._lastTimedMark?.attrs.userid !== Doc.CurrentUserEmail) { - const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }); - this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})).addStoredMark(mark)); - } - this.startUndoTypingBatch(); + switch (e.key) { + case "Escape": + this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); + (document.activeElement as any).blur?.(); + SelectionManager.DeselectAll(); + RichTextMenu.Instance.updateMenu(undefined, undefined, undefined); + return; + case "Enter": this.insertTime(); + case "Tab": e.preventDefault(); break; + default: if (this._lastTimedMark?.attrs.userid === Doc.CurrentUserEmail) break; + case " ": + this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})) + .addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))); } + this.startUndoTypingBatch(); } - - ondrop = (eve: React.DragEvent) => { + ondrop = (e: React.DragEvent) => { this._editorView!.dispatch(updateBullets(this._editorView!.state.tr, this._editorView!.state.schema)); - eve.stopPropagation(); // drag n drop of text within text note will generate a new note if not caughst, as will dragging in from outside of Dash. + e.stopPropagation(); // drag n drop of text within text note will generate a new note if not caughst, as will dragging in from outside of Dash. } - onScroll = (ev: React.UIEvent) => { + onScroll = (e: React.UIEvent) => { if (!LinkDocPreview.LinkInfo && this._scrollRef.current) { this._ignoreScroll = true; this.layoutDoc._scrollTop = this._scrollRef.current.scrollTop; this._ignoreScroll = false; } } - tryUpdateScrollHeight() { const proseHeight = this.ProseRef?.scrollHeight || 0; const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); @@ -1425,7 +1394,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } else setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... } } - fitToBox = () => this.props.Document._fitToBox; sidebarContentScaling = () => (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.SidebarKey); @@ -1442,7 +1410,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } @computed get sidebarHandle() { const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length; - return <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} + return (!annotated && !this.active()) ? (null) : <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} style={{ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`, background: this.props.styleProvider?.(this.props.Document, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : "")) @@ -1489,7 +1457,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const scale = this.props.hideOnLeave ? 1 : (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; const interactive = (Doc.GetSelectedTool() === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false); - if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(() => FormattedTextBoxComment.Hide()); + if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide); const minimal = this.props.ignoreAutoHeight; const margins = NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0); const selPad = Math.min(margins, 10); |
