From 76a21badf70c82388872ec5485858ab06e303bca Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 30 May 2025 09:57:46 -0400 Subject: fixed using empty images in templates to support assigning a new image and getting native dimensions right. fixed native dimensions of images within templates to not use native dims of template. fixed undo for text templates that don't have a text box. fixed image dropping on images that are empty (to assign the dropped image). --- src/client/views/nodes/EquationBox.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/EquationBox.tsx') diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 3cacb6692..8e48a0b54 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -6,7 +6,7 @@ import { TraceMobx } from '../../../fields/util'; import { DocUtils } from '../../documents/DocUtils'; import { DocumentType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; -import { undoBatch } from '../../util/UndoManager'; +import { undoBatch, UndoManager } from '../../util/UndoManager'; import { ViewBoxBaseComponent } from '../DocComponent'; import { StyleProp } from '../StyleProp'; import { DocumentView } from './DocumentView'; @@ -21,6 +21,7 @@ export class EquationBox extends ViewBoxBaseComponent() { return FieldView.LayoutString(EquationBox, fieldKey); } _ref: React.RefObject = React.createRef(); + _liveTextUndo: UndoManager.Batch | undefined; // captured undo batch when typing a new text note into a collection constructor(props: FieldViewProps) { super(props); @@ -30,6 +31,8 @@ export class EquationBox extends ViewBoxBaseComponent() { componentDidMount() { this._props.setContentViewBox?.(this); if (DocumentView.SelectOnLoad === this.Document && (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.()))) { + this._liveTextUndo = FormattedTextBox.LiveTextUndo; + FormattedTextBox.LiveTextUndo = undefined; this._props.select(false); this._ref.current?.mathField.focus(); @@ -113,9 +116,7 @@ export class EquationBox extends ViewBoxBaseComponent() { className="equationBox-cont" onKeyDown={e => e.stopPropagation()} onPointerDown={e => !e.ctrlKey && e.stopPropagation()} - onBlur={() => { - FormattedTextBox.LiveTextUndo?.end(); - }} + onBlur={() => this._liveTextUndo?.end()} style={{ transform: `scale(${scale})`, minWidth: `${100 / scale}%`, -- cgit v1.2.3-70-g09d2 From d3e5e09a51c7c95bffabd41b14e660aafcd80015 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 3 Jun 2025 22:32:16 -0400 Subject: fixed equationBox so that it can be used in templates. --- src/client/views/nodes/EquationBox.tsx | 32 ++++++++++++++++------ .../views/nodes/formattedText/EquationEditor.tsx | 4 +++ 2 files changed, 28 insertions(+), 8 deletions(-) (limited to 'src/client/views/nodes/EquationBox.tsx') diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 8e48a0b54..e0ab04692 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -14,6 +14,7 @@ import './EquationBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; import EquationEditor from './formattedText/EquationEditor'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; +import { Doc } from '../../../fields/Doc'; @observer export class EquationBox extends ViewBoxBaseComponent() { @@ -30,14 +31,17 @@ export class EquationBox extends ViewBoxBaseComponent() { componentDidMount() { this._props.setContentViewBox?.(this); - if (DocumentView.SelectOnLoad === this.Document && (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.()))) { + if (DocumentView.SelectOnLoad === this.rootDoc && (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.()))) { this._liveTextUndo = FormattedTextBox.LiveTextUndo; FormattedTextBox.LiveTextUndo = undefined; this._props.select(false); + this.dataDoc[Doc.LayoutDataKey(this.Document)] = FormattedTextBox.SelectOnLoadChar ?? ''; + this._ref.current?.mathField.focus(); - this.dataDoc.text === 'x' && this._ref.current?.mathField.select(); + this.dataDoc[Doc.LayoutDataKey(this.Document)] === 'x' && this._ref.current?.mathField.select(); DocumentView.SetSelectOnLoad(undefined); + FormattedTextBox.SelectOnLoadChar = ''; } reaction( () => this._props.isSelected(), @@ -56,7 +60,7 @@ export class EquationBox extends ViewBoxBaseComponent() { @action keyPressed = (e: KeyboardEvent) => { if (e.key === 'Enter') { - const nextEq = Docs.Create.EquationDocument(e.shiftKey ? StrCast(this.dataDoc.text) : '', { + const nextEq = Docs.Create.EquationDocument(e.shiftKey ? StrCast(this.dataDoc[Doc.LayoutDataKey(this.Document)]) : '', { title: '# math', _width: NumCast(this.layoutDoc._width), _height: NumCast(this.layoutDoc._height), @@ -73,9 +77,10 @@ export class EquationBox extends ViewBoxBaseComponent() { e.stopPropagation(); } if (e.key === 'Tab') { + const target = this.Document.isTemplateDoc ? this.rootDoc : this.Document; const graph = Docs.Create.FunctionPlotDocument([this.Document], { - x: NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc._width), - y: NumCast(this.layoutDoc.y), + x: NumCast(target.x) + NumCast(this.layoutDoc._width), + y: NumCast(target.y), _width: 400, _height: 300, backgroundColor: 'white', @@ -85,11 +90,11 @@ export class EquationBox extends ViewBoxBaseComponent() { link && this._props.addDocument?.(link); e.stopPropagation(); } - if (e.key === 'Backspace' && !this.dataDoc.text) this._props.removeDocument?.(this.Document); + if (e.key === 'Backspace' && !this.dataDoc[Doc.LayoutDataKey(this.Document)]) this._props.removeDocument?.(this.Document); }; @undoBatch onChange = (str: string) => { - this.dataDoc.text = str; + this.dataDoc[Doc.LayoutDataKey(this.Document)] = str; }; updateSize = (mathSpan: HTMLSpanElement) => { @@ -106,6 +111,10 @@ export class EquationBox extends ViewBoxBaseComponent() { this.layoutDoc._width = mathWidth * nScale; this.layoutDoc._height = mathHeight * nScale; + if (this.layoutDoc._nativeWidth) { + this.layoutDoc._nativeWidth = mathWidth; + this.layoutDoc._nativeHeight = mathHeight; + } }; render() { TraceMobx(); @@ -129,7 +138,14 @@ export class EquationBox extends ViewBoxBaseComponent() { paddingTop: NumCast(this.layoutDoc.yMargin), paddingBottom: NumCast(this.layoutDoc.yMargin), }}> - + ); } diff --git a/src/client/views/nodes/formattedText/EquationEditor.tsx b/src/client/views/nodes/formattedText/EquationEditor.tsx index 48efa6e63..23d273523 100644 --- a/src/client/views/nodes/formattedText/EquationEditor.tsx +++ b/src/client/views/nodes/formattedText/EquationEditor.tsx @@ -72,6 +72,10 @@ class EquationEditor extends Component { this.mathField.latex(value || ''); } + componentDidUpdate(prevProps: Readonly): void { + !prevProps.value && this.mathField.latex(this.props.value || ''); + } + render() { return ; } -- cgit v1.2.3-70-g09d2 From 35bd9e51f7cef551382025a5459d68eddd8f028b Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 23 Jun 2025 13:26:59 -0400 Subject: 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. --- src/Utils.ts | 3 + src/client/util/CurrentUserUtils.ts | 4 + src/client/views/EditableView.tsx | 5 +- src/client/views/GestureOverlay.tsx | 4 +- src/client/views/InkTranscription.tsx | 182 +++++++++++---------- src/client/views/InkingStroke.tsx | 2 +- src/client/views/LightboxView.tsx | 3 +- src/client/views/MainView.tsx | 36 ++-- src/client/views/UndoStack.tsx | 3 +- src/client/views/animationtimeline/Timeline.tsx | 3 +- .../views/collections/CollectionNoteTakingView.tsx | 3 +- .../views/collections/CollectionStackingView.tsx | 10 +- .../CollectionStackingViewFieldColumn.tsx | 12 +- .../views/collections/CollectionTreeView.tsx | 3 +- src/client/views/collections/TreeView.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 53 +++--- .../collectionFreeForm/FaceCollectionBox.tsx | 3 +- .../collections/collectionFreeForm/MarqueeView.tsx | 39 ++--- .../collectionLinear/CollectionLinearView.tsx | 5 +- .../collectionSchema/CollectionSchemaView.tsx | 24 ++- .../collectionSchema/SchemaCellField.tsx | 4 +- .../collectionSchema/SchemaColumnHeader.tsx | 9 +- .../collectionSchema/SchemaTableCell.tsx | 3 +- src/client/views/global/globalScripts.ts | 2 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 7 +- .../DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx | 3 +- .../nodes/DataVizBox/components/Histogram.tsx | 11 +- .../nodes/DataVizBox/components/LineChart.tsx | 11 +- .../views/nodes/DataVizBox/components/PieChart.tsx | 15 +- src/client/views/nodes/DiagramBox.tsx | 6 +- src/client/views/nodes/DocumentContentsView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 22 +-- src/client/views/nodes/EquationBox.tsx | 3 +- src/client/views/nodes/FunctionPlotBox.tsx | 3 +- src/client/views/nodes/LabelBox.tsx | 38 +++-- src/client/views/nodes/LinkBox.tsx | 23 +-- src/client/views/nodes/LinkDocPreview.tsx | 9 +- src/client/views/nodes/ScreenshotBox.tsx | 18 +- src/client/views/nodes/calendarBox/CalendarBox.tsx | 35 ++-- .../nodes/chatbot/chatboxcomponents/ChatBox.tsx | 14 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 8 +- src/client/views/nodes/trails/PresBox.tsx | 51 +++--- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 3 +- src/fields/InkField.ts | 1 + 44 files changed, 358 insertions(+), 345 deletions(-) (limited to 'src/client/views/nodes/EquationBox.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 724725c23..e96b8e231 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -202,6 +202,9 @@ export function aggregateBounds(boundsList: { x: number; y: number; width?: numb export function intersectRect(r1: { left: number; top: number; width: number; height: number }, r2: { left: number; top: number; width: number; height: number }) { return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top); } +export function rectContains(r1: { left: number; top: number; width: number; height: number }, r2: { left: number; top: number; width: number; height: number }) { + if (r1.left < r2.left && r1.left + r1.width > r2.left + r2.width && r1.top < r2.top && r1.top + r1.height > r2.top + r2.height) return true; +} export function stringHash(s?: string) { return !s ? undefined : Math.abs(s.split('').reduce((a, b) => (n => n & n)((a << 5) - a + b.charCodeAt(0)), 0)); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 45feb0b2f..9fbc82bef 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -796,6 +796,7 @@ pie title Minerals in my tap water { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: InkInkTool.Pen, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }}, { title: "Highlight",toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", toolType: InkInkTool.Highlight, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }}, { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: InkInkTool.Write, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }}, + { title: "Math", toolTip: "Math", btnType: ButtonType.ToggleButton, icon: "calculator", toolType: InkInkTool.Math, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }}, ]}, { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: InkProperty.StrokeWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}, numBtnMin: 1, linearView_btnWidth:40}, { title: "Color", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: InkProperty.StrokeColor,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}}, @@ -1032,6 +1033,9 @@ pie title Minerals in my tap water doc[`active${InkInkTool.Write}Color`] ?? (doc[`active${InkInkTool.Write}Color`] = "rgb(255, 0, 0)"); doc[`active${InkInkTool.Write}Width`] ?? (doc[`active${InkInkTool.Write}Width`] = 1); doc[`active${InkInkTool.Write}Bezier`] ?? (doc[`active${InkInkTool.Write}Bezier`] = "0"); + doc[`active${InkInkTool.Math}Color`] ?? (doc[`active${InkInkTool.Math}Color`] = "rgb(0, 0, 255)"); + doc[`active${InkInkTool.Math}Width`] ?? (doc[`active${InkInkTool.Math}Width`] = 1); + doc[`active${InkInkTool.Math}Bezier`] ?? (doc[`active${InkInkTool.Math}Bezier`] = "0"); doc[`active${InkInkTool.Highlight}Color`] ?? (doc[`active${InkInkTool.Highlight}Color`] = 'transparent'); doc[`active${InkInkTool.Highlight}Width`] ?? (doc[`active${InkInkTool.Highlight}Width`] = 20); doc[`active${InkInkTool.Highlight}Bezier`] ?? (doc[`active${InkInkTool.Highlight}Bezier`] = "0"); diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index d9447b7ec..deeabaa28 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -236,6 +236,7 @@ export class EditableView extends ObservableReactComponent { return this._editing; }; + setInputRef = (r: HTMLInputElement | HTMLTextAreaElement | null) => (this._inputref = r); renderEditor() { return this._props.autosuggestProps ? ( { ) : this._props.oneLine !== false && this._props.GetValue()?.toString().indexOf('\n') === -1 ? ( { this._inputref = r; }} // prettier-ignore + ref={this.setInputRef} style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minWidth: 20, background: this._props.background }} placeholder={this._props.placeholder} onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)} @@ -270,7 +271,7 @@ export class EditableView extends ObservableReactComponent { ) : (