Skip to content

Commit af996e5

Browse files
authored
Bug fix: Prevent tree from wrongly updating the selection (#571)
1 parent f725e75 commit af996e5

File tree

2 files changed

+78
-32
lines changed

2 files changed

+78
-32
lines changed

packages/base/src/commands.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,11 @@ export async function executeOperator(
240240
}
241241
sharedModel.transact(() => {
242242
transaction(sharedModel);
243-
});
244-
setTimeout(() => {
245243
current.context.model.syncSelected(
246244
{ [objectModel.name]: { type: 'shape' } },
247245
uuid()
248246
);
249-
}, 0); // doing the selection at the next tick
247+
});
250248
}
251249

252250
const OPERATORS = {
@@ -1248,12 +1246,10 @@ namespace Private {
12481246
objectModel.shapeMetadata = objMeta;
12491247
}
12501248
sharedModel.addObject(objectModel);
1251-
setTimeout(() => {
1252-
jcadModel.syncSelected(
1253-
{ [objectModel.name]: { type: 'shape' } },
1254-
uuid()
1255-
);
1256-
}, 0); // doing the selection at the next tick
1249+
jcadModel.syncSelected(
1250+
{ [objectModel.name]: { type: 'shape' } },
1251+
uuid()
1252+
);
12571253
} else {
12581254
showErrorMessage(
12591255
'The object already exists',

packages/base/src/panelview/objecttree.tsx

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -174,13 +174,27 @@ class ObjectTreeReact extends React.Component<IProps, IStates> {
174174
this._onClientSharedOptionsChanged
175175
);
176176

177-
this.setState(old => ({
178-
...old,
179-
filePath: document.context.localPath,
180-
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
181-
options: this.props.cpModel.sharedModel?.options,
182-
clientId: document.context.model.getClientId()
183-
}));
177+
const currentSelection = this._getCurrentSelection();
178+
179+
if (!currentSelection) {
180+
this.setState(old => ({
181+
...old,
182+
filePath: document.context.localPath,
183+
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
184+
options: this.props.cpModel.sharedModel?.options,
185+
clientId: document.context.model.getClientId()
186+
}));
187+
} else {
188+
this.setState(old => ({
189+
...old,
190+
selectedNodes: currentSelection.newSelectedNodes,
191+
openNodes: currentSelection.newOpenNodes,
192+
filePath: document.context.localPath,
193+
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
194+
options: this.props.cpModel.sharedModel?.options,
195+
clientId: document.context.model.getClientId()
196+
}));
197+
}
184198
} else {
185199
this.setState({
186200
filePath: undefined,
@@ -257,11 +271,23 @@ class ObjectTreeReact extends React.Component<IProps, IStates> {
257271
change: IJcadObjectDocChange
258272
): void => {
259273
if (change.objectChange) {
260-
this.setState(old => ({
261-
...old,
262-
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
263-
options: this.props.cpModel.sharedModel?.options
264-
}));
274+
const currentSelection = this._getCurrentSelection();
275+
276+
if (!currentSelection) {
277+
this.setState(old => ({
278+
...old,
279+
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
280+
options: this.props.cpModel.sharedModel?.options
281+
}));
282+
} else {
283+
this.setState(old => ({
284+
...old,
285+
selectedNodes: currentSelection.newSelectedNodes,
286+
openNodes: currentSelection.newOpenNodes,
287+
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
288+
options: this.props.cpModel.sharedModel?.options
289+
}));
290+
}
265291
}
266292
};
267293

@@ -284,35 +310,59 @@ class ObjectTreeReact extends React.Component<IProps, IStates> {
284310
sender: IJupyterCadModel,
285311
clients: Map<number, IJupyterCadClientState>
286312
): void => {
313+
const currentSelection = this._getCurrentSelection(clients);
314+
315+
if (!currentSelection) {
316+
return;
317+
}
318+
319+
const { newSelectedNodes, newOpenNodes } = currentSelection;
320+
const { selectedNodes, openNodes } = this.state;
321+
if (
322+
JSON.stringify(selectedNodes) !== JSON.stringify(newSelectedNodes) ||
323+
JSON.stringify(openNodes) !== JSON.stringify(newOpenNodes)
324+
) {
325+
this.setState(old => ({
326+
...old,
327+
openNodes: newOpenNodes,
328+
selectedNodes: newSelectedNodes
329+
}));
330+
}
331+
};
332+
333+
private _getCurrentSelection(
334+
clients?: Map<number, IJupyterCadClientState>
335+
):
336+
| { newSelectedNodes: string[]; newOpenNodes: (string | number)[] }
337+
| undefined {
287338
const localState = this.props.cpModel.jcadModel?.localState;
288339

289340
if (!localState) {
290341
return;
291342
}
292343

293-
let selectedNodes: string[] = [];
294-
if (localState.remoteUser) {
344+
let newSelectedNodes: string[] = [];
345+
if (clients && localState.remoteUser) {
295346
// We are in following mode.
296347
// Sync selections from a remote user
297348
const remoteState = clients.get(localState.remoteUser);
298349

299350
if (remoteState?.selected?.value) {
300-
selectedNodes = this._selectedNodes(remoteState.selected.value);
351+
newSelectedNodes = this._selectedNodes(remoteState.selected.value);
301352
}
302353
} else if (localState.selected?.value) {
303-
selectedNodes = this._selectedNodes(localState.selected.value);
354+
newSelectedNodes = this._selectedNodes(localState.selected.value);
304355
}
305356

306-
const openNodes = [...this.state.openNodes];
307-
308-
for (const selectedNode of selectedNodes) {
309-
if (selectedNode && openNodes.indexOf(selectedNode) === -1) {
310-
openNodes.push(selectedNode);
357+
const newOpenNodes = [...this.state.openNodes];
358+
for (const selectedNode of newSelectedNodes) {
359+
if (selectedNode && newOpenNodes.indexOf(selectedNode) === -1) {
360+
newOpenNodes.push(selectedNode);
311361
}
312362
}
313363

314-
this.setState(old => ({ ...old, openNodes, selectedNodes }));
315-
};
364+
return { newSelectedNodes, newOpenNodes };
365+
}
316366

317367
private _onClientSharedOptionsChanged = (
318368
sender: IJupyterCadDoc,

0 commit comments

Comments
 (0)