aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-06-23 13:26:59 -0400
committerbobzel <zzzman@gmail.com>2025-06-23 13:26:59 -0400
commit35bd9e51f7cef551382025a5459d68eddd8f028b (patch)
tree8edab8e8e283d06bdeba632959fd51e1488c4af5 /src/client/views/collections
parente7a96fa043cfc9c3c426e09bbef42c8df88a45f6 (diff)
fixed invalidations to not trigger creating new refs when ref= was assigned to an anonymous function. fixed scribble erase to not delete everything it overlaps, just things it intersects with or contains. fixed ink to have a Math mode and fixed math recognition myscript calls.
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx3
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx10
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx12
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx3
-rw-r--r--src/client/views/collections/TreeView.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx53
-rw-r--r--src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx39
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx5
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx24
-rw-r--r--src/client/views/collections/collectionSchema/SchemaCellField.tsx4
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx9
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx3
13 files changed, 91 insertions, 80 deletions
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 7f639a11e..7a4408931 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -256,9 +256,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const height = () => this.getDocHeight(doc);
let dref: Opt<DocumentView>;
const noteTakingDocTransform = () => this.getDocTransform(doc, dref);
+ const setRef = (r: DocumentView | null) => (dref = r || undefined);
return (
<DocumentView
- ref={r => (dref = r || undefined)}
+ ref={setRef}
Document={doc}
TemplateDataDocument={doc.isTemplateDoc || doc.isTemplateForField ? this._props.TemplateDataDocument : undefined}
pointerEvents={this.blockPointerEventsWhenDragging}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index bdeb7d944..fbdd23315 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,6 +1,6 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import * as CSS from 'csstype';
-import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ClientUtils, DivHeight, returnNone, returnZero, setupMoveUpEvents, smoothScroll } from '../../../ClientUtils';
@@ -391,10 +391,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
});
// This following three functions must be from the view Mehek showed
- columnDividerDown = (e: React.PointerEvent) => {
- runInAction(() => {
- this._cursor = 'grabbing';
- });
+ columnDividerDown = action((e: React.PointerEvent) => {
+ this._cursor = 'grabbing';
const batch = UndoManager.StartBatch('stacking width');
setupMoveUpEvents(
this,
@@ -406,7 +404,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
}),
emptyFunction
);
- };
+ });
@action
onDividerMove = (e: PointerEvent) => {
this.Document._layout_columnWidth = Math.max(10, (this._props.DocumentView?.().screenToViewTransform().transformPoint(e.clientX, 0)[0] ?? 0) - this.xMargin);
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 8c535534a..b5efa7a72 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -304,6 +304,12 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
ContextMenu.Instance.displayMenu(pt[0], pt[1], undefined, true);
};
+ setRef = (r: HTMLDivElement | null) => {
+ if (this._headerRef && this._props.colHeaderRefs.includes(this._headerRef)) this._props.colHeaderRefs.splice(this._props.colStackRefs.indexOf(this._headerRef), 1);
+ r && this._props.colHeaderRefs.push(r);
+ this._headerRef = r;
+ };
+
@computed get innards() {
TraceMobx();
const key = this._props.pivotField;
@@ -315,11 +321,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
<div
key={heading}
className="collectionStackingView-sectionHeader"
- ref={r => {
- if (this._headerRef && this._props.colHeaderRefs.includes(this._headerRef)) this._props.colHeaderRefs.splice(this._props.colStackRefs.indexOf(this._headerRef), 1);
- r && this._props.colHeaderRefs.push(r);
- this._headerRef = r;
- }}
+ ref={this.setRef}
style={{
marginTop: 0,
marginBottom: this._props.gridGap,
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index bee5d016d..4625965b4 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -407,6 +407,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this._props.fieldKey}_annotations`) || false;
moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => this.moveDocument(doc, targetCollection, addDocument) || false;
+ setRef = (r: HTMLDivElement | null) => !this.Document.treeView_HasOverlay && r && this.createTreeDropTarget(r);
@observable _headerHeight = 0;
@computed get content() {
const background = () => this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor) as string;
@@ -428,7 +429,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
<div
className="collectionTreeView-contents"
key="tree"
- ref={r => !this.Document.treeView_HasOverlay && r && this.createTreeDropTarget(r)}
+ ref={this.setRef}
style={{
...(!titleBar ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
color: color(),
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 5b2f1ff81..f84c7d3c0 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1294,6 +1294,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return null;
}
+ const setRef = (r: TreeView | null) => treeViewRefs.set(child, r || undefined);
const dentDoc = (editTitle: boolean, newParent: Doc, addAfter: Doc | undefined, parent: TreeView | CollectionTreeView | undefined) => {
if (parent instanceof TreeView && parent._props.treeView.fileSysMode && !newParent.isFolder) return;
const fieldKey = Doc.LayoutDataKey(newParent);
@@ -1317,7 +1318,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return (
<TreeView
key={child[Id]}
- ref={r => treeViewRefs.set(child, r || undefined)}
+ ref={setRef}
Document={pair.layout}
dataDoc={pair.data}
treeViewParent={treeViewParent}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 32ace463d..6e9e503f4 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -562,7 +562,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const B = this.screenToFreeformContentsXf.transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
const inkDoc = this.createInkDoc(points, B);
if (Doc.ActiveInk === InkInkTool.Highlight) inkDoc.$backgroundColor = 'transparent';
- if (Doc.ActiveInk === InkInkTool.Write) {
+ if ([InkInkTool.Write, InkInkTool.Math].includes(Doc.ActiveInk)) {
this.unprocessedDocs.push(inkDoc);
CollectionFreeFormView.collectionsWithUnprocessedInk.add(this);
}
@@ -2220,18 +2220,41 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
);
};
+ @computed get inkEraser() {
+ return (
+ Doc.ActiveTool === InkTool.Eraser &&
+ Doc.ActiveEraser === InkEraserTool.Radius &&
+ this._showEraserCircle && (
+ <div
+ onPointerMove={this.onCursorMove}
+ style={{
+ position: 'fixed',
+ left: this._eraserX,
+ top: this._eraserY,
+ width: (ActiveEraserWidth() + 5) * 2,
+ height: (ActiveEraserWidth() + 5) * 2,
+ borderRadius: '50%',
+ border: '1px solid gray',
+ transform: 'translate(-50%, -50%)',
+ }}
+ />
+ )
+ );
+ }
+
+ setRef = (r: HTMLDivElement | null) => {
+ this.createDashEventsTarget(r);
+ this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel);
+ r?.addEventListener('mouseleave', this.onMouseLeave);
+ r?.addEventListener('mouseenter', this.onMouseEnter);
+ };
render() {
TraceMobx();
return (
<div
className="collectionfreeformview-container"
id={this._paintedId}
- ref={r => {
- this.createDashEventsTarget(r);
- this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel);
- r?.addEventListener('mouseleave', this.onMouseLeave);
- r?.addEventListener('mouseenter', this.onMouseEnter);
- }}
+ ref={this.setRef}
onWheel={this.onPointerWheel}
onClick={this.onClick}
onPointerDown={this.onPointerDown}
@@ -2246,21 +2269,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
width: `${100 / this.nativeDimScaling}%`,
height: this._props.getScrollHeight?.() ?? `${100 / this.nativeDimScaling}%`,
}}>
- {Doc.ActiveTool === InkTool.Eraser && Doc.ActiveEraser === InkEraserTool.Radius && this._showEraserCircle && (
- <div
- onPointerMove={this.onCursorMove}
- style={{
- position: 'fixed',
- left: this._eraserX,
- top: this._eraserY,
- width: (ActiveEraserWidth() + 5) * 2,
- height: (ActiveEraserWidth() + 5) * 2,
- borderRadius: '50%',
- border: '1px solid gray',
- transform: 'translate(-50%, -50%)',
- }}
- />
- )}
+ {this.inkEraser}
{this.paintFunc ? (
<FormattedTextBox {...this.props} /> // need this so that any live dashfieldviews will update the underlying text that the code eval reads
) : this._lightboxDoc ? (
diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
index 142085e14..c31558dff 100644
--- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
+++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
@@ -150,6 +150,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, this.Document);
}, 'remove doc from face');
+ setRef = (r: HTMLDivElement | null) => this.fixWheelEvents(r, this._props.isContentActive);
render() {
return (
<div className="face-document-item" ref={ele => this.createDropTarget(ele!)}>
@@ -176,7 +177,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
style={{
pointerEvents: this._props.isContentActive() ? undefined : 'none',
}}
- ref={r => this.fixWheelEvents(r, this._props.isContentActive)}>
+ ref={this.setRef}>
{FaceRecognitionHandler.UniqueFaceImages(this.Document).map((doc, i) => {
const [name, type] = ImageCastToNameType(doc?.[Doc.LayoutDataKey(doc)]) ?? ['-missing-', '.png'];
return (
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index ff78b332a..4191aaca8 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -762,29 +762,26 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
}
e.stopPropagation();
};
+ setRef = (r: HTMLDivElement | null) => {
+ r?.addEventListener('dashDragMovePause', this.onDragMovePause as EventListenerOrEventListenerObject);
+ this.MarqueeRef = r;
+ };
render() {
return (
- <>
- <div
- className="marqueeView"
- ref={r => {
- r?.addEventListener('dashDragMovePause', this.onDragMovePause as EventListenerOrEventListenerObject);
- this.MarqueeRef = r;
- }}
- style={{
- overflow: StrCast(this._props.Document._overflow),
- cursor: Doc.ActiveTool === InkTool.Ink || this._visible ? 'crosshair' : 'pointer',
- }}
- onDragOver={e => e.preventDefault()}
- onScroll={e => {
- e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0;
- }}
- onClick={this.onClick}
- onPointerDown={this.onPointerDown}>
- {this._visible ? this.marqueeDiv : null}
- {this.props.children}
- </div>
- </>
+ <div
+ className="marqueeView"
+ ref={this.setRef}
+ style={{
+ overflow: StrCast(this._props.Document._overflow),
+ cursor: Doc.ActiveTool === InkTool.Ink || this._visible ? 'crosshair' : 'pointer',
+ }}
+ onDragOver={e => e.preventDefault()}
+ onScroll={e => (e.currentTarget.scrollTop = (e.currentTarget.scrollLeft = 0))} // prettier-ignore
+ onClick={this.onClick}
+ onPointerDown={this.onPointerDown}>
+ {this._visible ? this.marqueeDiv : null}
+ {this.props.children}
+ </div>
);
}
}
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index d0a1e6f0d..435f618d9 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -158,14 +158,13 @@ export class CollectionLinearView extends CollectionSubView() {
let dref: Opt<HTMLDivElement>;
const docXf = () => this.getTransform(dref);
+ const setRef = (r: HTMLDivElement | null) => (dref = r || undefined);
// const scalable = pair.layout.onClick || pair.layout.onDragStart;
return hidden ? null : (
<div
className={preview ? 'preview' : `collectionLinearView-docBtn`}
key={doc[Id]}
- ref={r => {
- dref = r || undefined;
- }}
+ ref={setRef}
style={{
pointerEvents: 'all',
width: NumCast(doc._width),
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 6442385c0..2576bdf9b 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1043,17 +1043,16 @@ export class CollectionSchemaView extends CollectionSubView() {
if (!this._oldKeysWheel?.scrollTop && e.deltaY <= 0) e.preventDefault();
e.stopPropagation();
};
+ setRef = (r: HTMLDivElement | null) => {
+ this._oldKeysWheel?.removeEventListener('wheel', this.onKeysPassiveWheel);
+ this._oldKeysWheel = r;
+ r?.addEventListener('wheel', this.onKeysPassiveWheel, { passive: false });
+ };
_oldKeysWheel: HTMLDivElement | null = null;
@computed get keysDropdown() {
return (
<div className="schema-key-search">
- <div
- className="schema-key-list"
- ref={r => {
- this._oldKeysWheel?.removeEventListener('wheel', this.onKeysPassiveWheel);
- this._oldKeysWheel = r;
- r?.addEventListener('wheel', this.onKeysPassiveWheel, { passive: false });
- }}>
+ <div className="schema-key-list" ref={this.setRef}>
{this._menuKeys.map(key => (
<div
key={key}
@@ -1294,6 +1293,9 @@ export class CollectionSchemaView extends CollectionSubView() {
screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
previewWidthFunc = () => this.previewWidth;
displayedDocsFunc = () => this.docsWithDrag.docs;
+ setColHdrRef = (r: SchemaColumnHeader | null) => r && this._headerRefs.push(r);
+ setPreviewRef = (r: HTMLDivElement | null) => (this._previewRef = r);
+
render() {
return (
<div
@@ -1331,7 +1333,7 @@ export class CollectionSchemaView extends CollectionSubView() {
{this.columnKeys.map((key, index) => (
<SchemaColumnHeader
//cleanupField={this.cleanupComputedField}
- ref={r => r && this._headerRefs.push(r)}
+ ref={this.setColHdrRef}
keysDropdown={this.keysDropdown}
schemaView={this}
columnWidth={() => CollectionSchemaView._minColWidth} //TODO: update
@@ -1379,11 +1381,7 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
{this.previewWidth > 0 && <div className="schema-preview-divider" style={{ width: CollectionSchemaView._previewDividerWidth }} onPointerDown={this.onDividerDown} />}
{this.previewWidth > 0 && (
- <div
- style={{ width: `${this.previewWidth}px` }}
- ref={ref => {
- this._previewRef = ref;
- }}>
+ <div style={{ width: `${this.previewWidth}px` }} ref={this.setPreviewRef}>
{Array.from(this._selectedDocs).lastElement() && (
<DocumentView
Document={Array.from(this._selectedDocs).lastElement()}
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 9ad94cb31..412daa105 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -341,12 +341,14 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
return <span className="editableView-static">{this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : ''}</span>;
};
+ setRef = (r: HTMLDivElement | null) => (this._inputref = r);
+
renderEditor = () => {
return (
<div
contentEditable
className="schemaField-editing"
- ref={r => (this._inputref = r)}
+ ref={this.setRef}
style={{ minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20 }}
onBlur={() => (this._props.refSelectModeInfo.enabled ? setTimeout(() => this.setIsFocused(true), 1000) : this.finalizeEdit(false, true, false))}
onInput={this.onChange}
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 134f2ed31..64bfab856 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -118,6 +118,10 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
return { color, fieldProps, cursor };
};
+ setRef = (r: EditableView | null) => {
+ this._inputRef = r;
+ this._props.autoFocus && r?.setIsFocused(true);
+ };
@computed get editableView() {
const { color, fieldProps } = this.renderProps(this._props);
@@ -133,10 +137,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
width: '100%',
}}>
<EditableView
- ref={r => {
- this._inputRef = r;
- this._props.autoFocus && r?.setIsFocused(true);
- }}
+ ref={this.setRef}
oneLine={true}
allowCRs={false}
contents={''}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 8b34b4139..02e0d8100 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -185,6 +185,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
return eqSymbol + modField;
};
+ setRef = (r: SchemaCellField | null) => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true);
@computed get defaultCellContent() {
const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props);
@@ -204,7 +205,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
Doc={this._props.Doc}
highlightCells={(text: string) => this._props.highlightCells(this.adjustSelfReference(text))}
getCells={(text: string) => this._props.eqHighlightFunc(this.adjustSelfReference(text))}
- ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
+ ref={this.setRef}
oneLine={this._props.oneLine}
contents={undefined}
fieldContents={fieldProps}