Skip to content

Commit 0e66223

Browse files
shuejaTinbite-A
authored andcommitted
Upgrade mobx-react to 9.2.0 with necessary architectural changes (SleipnirGroup#1249)
1 parent fe0f136 commit 0e66223

File tree

5 files changed

+68
-49
lines changed

5 files changed

+68
-49
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"hotkeys-js": "^3.13.9",
4242
"mathjs": "^13.2.3",
4343
"mobx": "^6.13.5",
44-
"mobx-react": "^7.6.0",
44+
"mobx-react": "^9.2.0",
4545
"mobx-state-tree": "^6.0.1",
4646
"mobx-utils": "^6.1.0",
4747
"mst-middlewares": "^6.1.0",

pnpm-lock.yaml

Lines changed: 23 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/field/svg/OverlayWaypoint.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,31 +44,33 @@ class OverlayWaypoint extends Component<Props, State> {
4444
robotConfig,
4545
strokeColor,
4646
strokeWidthPx,
47-
dashed
47+
dashed,
48+
index
4849
}: {
4950
robotConfig: IRobotConfigStore;
5051
strokeColor: string;
5152
strokeWidthPx: number;
5253
dashed: boolean;
54+
index: number;
5355
}) => (
5456
<g>
5557
<defs>
5658
<path
57-
id={this.appendIndexID("bumpers")}
59+
id={this.appendIndexID("bumpers", index)}
5860
d={
5961
dashed
6062
? robotConfig.dashedBumperSVGElement()
6163
: robotConfig.bumperSVGElement()
6264
}
6365
></path>
64-
<clipPath id={this.appendIndexID("clip")}>
65-
<use xlinkHref={`#${this.appendIndexID("bumpers")}`} />
66+
<clipPath id={this.appendIndexID("clip", index)}>
67+
<use xlinkHref={`#${this.appendIndexID("bumpers", index)}`} />
6668
</clipPath>
6769
</defs>
6870

6971
<use
70-
xlinkHref={`#${this.appendIndexID("bumpers")}`}
71-
clipPath={`url(#${this.appendIndexID("clip")})`}
72+
xlinkHref={`#${this.appendIndexID("bumpers", index)}`}
73+
clipPath={`url(#${this.appendIndexID("clip", index)})`}
7274
stroke={strokeColor}
7375
strokeWidth={strokeWidthPx * uiState.fieldScalingFactor}
7476
strokeLinecap="square"
@@ -166,8 +168,8 @@ class OverlayWaypoint extends Component<Props, State> {
166168
}
167169
}
168170

169-
appendIndexID(id: string): string {
170-
return `${id}${this.props.index}`;
171+
appendIndexID(id: string, index: number): string {
172+
return `${id}${index}`;
171173
}
172174

173175
getBoxColor() {
@@ -208,21 +210,22 @@ class OverlayWaypoint extends Component<Props, State> {
208210
transform={`translate(${waypoint.x.value}, ${waypoint.y.value}) rotate(${
209211
(waypoint.heading.value * 180) / Math.PI
210212
})`}
211-
id={this.appendIndexID("waypointGroup")}
213+
id={this.appendIndexID("waypointGroup", this.props.index)}
212214
>
213215
{this.props.waypoint.type === 0 && (
214216
<this.BumperBox
215217
robotConfig={robotConfig}
216218
strokeColor={boxColorStr}
217219
strokeWidthPx={6}
218220
dashed={this.props.waypoint.type !== 0}
221+
index={this.props.index}
219222
></this.BumperBox>
220223
)}
221224

222225
{/* Heading drag point */}
223226
<polygon
224227
transform={`translate(${robotConfig.bumper.length / 2},0)`}
225-
id={this.appendIndexID("rotateTarget")}
228+
id={this.appendIndexID("rotateTarget", this.props.index)}
226229
fill={boxColorStr}
227230
strokeWidth={outlineWidth}
228231
stroke="black"
@@ -254,7 +257,7 @@ class OverlayWaypoint extends Component<Props, State> {
254257
robotConfig.bumper.length
255258
)
256259
}
257-
id={this.appendIndexID("dragTarget")}
260+
id={this.appendIndexID("dragTarget", this.props.index)}
258261
fill={
259262
type == 2 || type == 3
260263
? "transparent"
@@ -295,7 +298,7 @@ class OverlayWaypoint extends Component<Props, State> {
295298
onClick={() => this.selectWaypoint()}
296299
></circle>
297300
<path
298-
id={this.appendIndexID("dragTarget")}
301+
id={this.appendIndexID("dragTarget", this.props.index)}
299302
fill={this.getDragTargetColor()}
300303
transform={`matrix(${sx}, 0, 0, ${sy}, ${cx - sx * cx}, ${
301304
cy - sy * cy

src/components/input/ExpressionInput.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { IExpressionStore, math } from "../../document/ExpressionStore";
66
import styles from "./InputList.module.css";
77
import { IReactionDisposer, reaction } from "mobx";
88

9-
type Props = {
9+
export type ExpressionInputProps = {
1010
/** The text to show before the number */
1111
title: string | (() => React.ReactNode);
1212
/** Whether the input should be editable, or else italic and grayed out */
@@ -28,20 +28,20 @@ type State = {
2828
matchesProp: boolean;
2929
resetCounter: number;
3030
};
31-
32-
class Input extends Component<Props, State> {
31+
class Input extends Component<ExpressionInputProps, State> {
3332
inputElemRef: React.RefObject<HTMLInputElement>;
3433
unsubscriber: IReactionDisposer | undefined;
35-
constructor(props: Props) {
34+
number: IExpressionStore;
35+
constructor(props: ExpressionInputProps) {
3636
super(props);
37+
this.number = this.props.number;
3738
this.state = {
3839
matchesProp: true,
39-
editedValue: this.props.number.expr.toString(),
40+
editedValue: this.number.expr.toString(),
4041
resetCounter: 0
4142
};
4243
this.inputElemRef = React.createRef<HTMLInputElement>();
4344
}
44-
4545
// Increment the reset counter state to trigger a re-render that fully recreates the input.
4646
// This clears the input's own undo history.
4747
// Should be used when submitting a new value.
@@ -53,20 +53,20 @@ class Input extends Component<Props, State> {
5353

5454
// Return the string of the expression prop.
5555
getExprStr(): string {
56-
return this.props.number.expr.toString();
56+
return this.number.expr.toString();
5757
}
5858

5959
// If the internal state is marked as matching the prop, use the prop's validity
6060
// Otherwise, validate the internal state.
6161
getValid(): boolean {
6262
try {
6363
if (!this.state.matchesProp) {
64-
const newNode = this.props.number.validate(
64+
const newNode = this.number.validate(
6565
math.parse(this.state.editedValue)
6666
);
6767
return newNode !== undefined;
6868
} else {
69-
return this.props.number.valid;
69+
return this.number.valid;
7070
}
7171
} catch {
7272
return false;
@@ -103,7 +103,7 @@ class Input extends Component<Props, State> {
103103
this.unsubscriber?.();
104104
}
105105
render() {
106-
if (!isAlive(this.props.number)) {
106+
if (!isAlive(this.number)) {
107107
return <></>;
108108
}
109109
const showNumberWhenDisabled = this.props.showNumberWhenDisabled ?? true;
@@ -147,14 +147,11 @@ class Input extends Component<Props, State> {
147147
// The below is needed to make inputs on CommandDraggables work
148148
onClick={(e) => e.stopPropagation()}
149149
onBlur={(_e) => {
150-
const newNode = this.props.number.validate(
150+
const newNode = this.number.validate(
151151
math.parse(this.state.editedValue)
152152
);
153-
if (
154-
newNode !== undefined &&
155-
!newNode.equals(this.props.number.expr)
156-
) {
157-
this.props.number.set(newNode);
153+
if (newNode !== undefined && !newNode.equals(this.number.expr)) {
154+
this.number.set(newNode);
158155
} else {
159156
this.revert();
160157
}
@@ -180,4 +177,9 @@ class Input extends Component<Props, State> {
180177
);
181178
}
182179
}
183-
export default observer(Input);
180+
const ObservedInput = observer(Input);
181+
// Recreate the input element entirely when the store changes.
182+
function ExpressionInput(props: ExpressionInputProps) {
183+
return <ObservedInput {...props} key={props.number.uuid}></ObservedInput>;
184+
}
185+
export default ExpressionInput;

src/document/ExpressionStore.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ type Evaluator = (arg: MathNode) => Evaluated;
191191
export const ExpressionStore = types
192192
.model("ExpressionStore", {
193193
expr: types.frozen<MathNode>(),
194-
dimension: types.frozen<DimensionName>()
194+
dimension: types.frozen<DimensionName>(),
195+
uuid: types.identifier
195196
})
196197
.volatile((self) => ({
197198
tempDisableRecalc: false,
@@ -626,29 +627,33 @@ export const Variables = types
626627
if (dimension === "Number") {
627628
store = ExpressionStore.create({
628629
expr: new ConstantNode(expr),
629-
dimension
630+
dimension,
631+
uuid: crypto.randomUUID()
630632
});
631633
} else {
632634
store = ExpressionStore.create({
633635
expr: addUnitToExpression(
634636
new math.ConstantNode(expr),
635637
Dimensions[dimension]?.unit.toString()
636638
),
637-
dimension
639+
dimension,
640+
uuid: crypto.randomUUID()
638641
});
639642
}
640643
} else if (isExpr(expr)) {
641644
// deserialize Expr
642645
store = ExpressionStore.create({
643646
expr: math.parse(expr.exp),
644-
dimension
647+
dimension,
648+
uuid: crypto.randomUUID()
645649
});
646650
store.deserialize(expr);
647651
} else {
648652
// handle string exprs
649653
store = ExpressionStore.create({
650654
expr: math.parse(expr),
651-
dimension
655+
dimension,
656+
uuid: crypto.randomUUID()
652657
});
653658
}
654659

0 commit comments

Comments
 (0)