Fix broken history when eleemnt in update scene are optional
This commit is contained in:
parent
f0458cc216
commit
60512f13d5
@ -3907,6 +3907,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
const { elements, appState, collaborators, captureUpdate } = sceneData;
|
const { elements, appState, collaborators, captureUpdate } = sceneData;
|
||||||
|
|
||||||
if (captureUpdate) {
|
if (captureUpdate) {
|
||||||
|
const nextElements = elements ? elements : undefined;
|
||||||
const observedAppState = appState
|
const observedAppState = appState
|
||||||
? getObservedAppState({
|
? getObservedAppState({
|
||||||
...this.store.snapshot.appState,
|
...this.store.snapshot.appState,
|
||||||
@ -3916,7 +3917,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
this.store.scheduleMicroAction({
|
this.store.scheduleMicroAction({
|
||||||
action: captureUpdate,
|
action: captureUpdate,
|
||||||
elements: elements ?? [],
|
elements: nextElements,
|
||||||
appState: observedAppState,
|
appState: observedAppState,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -14820,6 +14820,158 @@ exports[`history > singleplayer undo/redo > should not end up with history entry
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`history > singleplayer undo/redo > should not modify anything on unrelated appstate change > [end of test] appState 1`] = `
|
||||||
|
{
|
||||||
|
"activeEmbeddable": null,
|
||||||
|
"activeLockedId": null,
|
||||||
|
"activeTool": {
|
||||||
|
"customType": null,
|
||||||
|
"fromSelection": false,
|
||||||
|
"lastActiveTool": null,
|
||||||
|
"locked": false,
|
||||||
|
"type": "selection",
|
||||||
|
},
|
||||||
|
"collaborators": Map {},
|
||||||
|
"contextMenu": null,
|
||||||
|
"croppingElementId": null,
|
||||||
|
"currentChartType": "bar",
|
||||||
|
"currentHoveredFontFamily": null,
|
||||||
|
"currentItemArrowType": "round",
|
||||||
|
"currentItemBackgroundColor": "transparent",
|
||||||
|
"currentItemEndArrowhead": "arrow",
|
||||||
|
"currentItemFillStyle": "solid",
|
||||||
|
"currentItemFontFamily": 5,
|
||||||
|
"currentItemFontSize": 20,
|
||||||
|
"currentItemOpacity": 100,
|
||||||
|
"currentItemRoughness": 1,
|
||||||
|
"currentItemRoundness": "sharp",
|
||||||
|
"currentItemStartArrowhead": null,
|
||||||
|
"currentItemStrokeColor": "#1e1e1e",
|
||||||
|
"currentItemStrokeStyle": "solid",
|
||||||
|
"currentItemStrokeWidth": 2,
|
||||||
|
"currentItemTextAlign": "left",
|
||||||
|
"cursorButton": "up",
|
||||||
|
"defaultSidebarDockedPreference": false,
|
||||||
|
"editingFrame": null,
|
||||||
|
"editingGroupId": null,
|
||||||
|
"editingLinearElement": null,
|
||||||
|
"editingTextElement": null,
|
||||||
|
"elementsToHighlight": null,
|
||||||
|
"errorMessage": null,
|
||||||
|
"exportBackground": true,
|
||||||
|
"exportEmbedScene": false,
|
||||||
|
"exportScale": 1,
|
||||||
|
"exportWithDarkMode": false,
|
||||||
|
"fileHandle": null,
|
||||||
|
"followedBy": Set {},
|
||||||
|
"frameRendering": {
|
||||||
|
"clip": true,
|
||||||
|
"enabled": true,
|
||||||
|
"name": true,
|
||||||
|
"outline": true,
|
||||||
|
},
|
||||||
|
"frameToHighlight": null,
|
||||||
|
"gridModeEnabled": false,
|
||||||
|
"gridSize": 20,
|
||||||
|
"gridStep": 5,
|
||||||
|
"height": 0,
|
||||||
|
"hoveredElementIds": {},
|
||||||
|
"isBindingEnabled": true,
|
||||||
|
"isCropping": false,
|
||||||
|
"isLoading": false,
|
||||||
|
"isResizing": false,
|
||||||
|
"isRotating": false,
|
||||||
|
"lastPointerDownWith": "mouse",
|
||||||
|
"lockedMultiSelections": {},
|
||||||
|
"multiElement": null,
|
||||||
|
"newElement": null,
|
||||||
|
"objectsSnapModeEnabled": false,
|
||||||
|
"offsetLeft": 0,
|
||||||
|
"offsetTop": 0,
|
||||||
|
"openDialog": null,
|
||||||
|
"openMenu": null,
|
||||||
|
"openPopup": null,
|
||||||
|
"openSidebar": null,
|
||||||
|
"originSnapOffset": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
"pasteDialog": {
|
||||||
|
"data": null,
|
||||||
|
"shown": false,
|
||||||
|
},
|
||||||
|
"penDetected": false,
|
||||||
|
"penMode": false,
|
||||||
|
"previousSelectedElementIds": {},
|
||||||
|
"resizingElement": null,
|
||||||
|
"scrollX": 0,
|
||||||
|
"scrollY": 0,
|
||||||
|
"searchMatches": null,
|
||||||
|
"selectedElementIds": {},
|
||||||
|
"selectedElementsAreBeingDragged": false,
|
||||||
|
"selectedGroupIds": {},
|
||||||
|
"selectionElement": null,
|
||||||
|
"shouldCacheIgnoreZoom": false,
|
||||||
|
"showHyperlinkPopup": false,
|
||||||
|
"showWelcomeScreen": false,
|
||||||
|
"snapLines": [],
|
||||||
|
"startBoundElement": null,
|
||||||
|
"stats": {
|
||||||
|
"open": false,
|
||||||
|
"panels": 3,
|
||||||
|
},
|
||||||
|
"suggestedBindings": [],
|
||||||
|
"theme": "light",
|
||||||
|
"toast": null,
|
||||||
|
"userToFollow": null,
|
||||||
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"viewModeEnabled": true,
|
||||||
|
"width": 0,
|
||||||
|
"zenModeEnabled": false,
|
||||||
|
"zoom": {
|
||||||
|
"value": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`history > singleplayer undo/redo > should not modify anything on unrelated appstate change > [end of test] element 0 1`] = `
|
||||||
|
{
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"boundElements": [],
|
||||||
|
"customData": undefined,
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"frameId": null,
|
||||||
|
"groupIds": [],
|
||||||
|
"height": 100,
|
||||||
|
"id": "id0",
|
||||||
|
"index": "a0",
|
||||||
|
"isDeleted": false,
|
||||||
|
"link": null,
|
||||||
|
"locked": false,
|
||||||
|
"opacity": 100,
|
||||||
|
"roughness": 1,
|
||||||
|
"roundness": null,
|
||||||
|
"strokeColor": "#1e1e1e",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"type": "rectangle",
|
||||||
|
"updated": 1,
|
||||||
|
"version": 2,
|
||||||
|
"width": 100,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`history > singleplayer undo/redo > should not modify anything on unrelated appstate change > [end of test] number of elements 1`] = `1`;
|
||||||
|
|
||||||
|
exports[`history > singleplayer undo/redo > should not modify anything on unrelated appstate change > [end of test] number of renders 1`] = `4`;
|
||||||
|
|
||||||
|
exports[`history > singleplayer undo/redo > should not modify anything on unrelated appstate change > [end of test] redo stack 1`] = `[]`;
|
||||||
|
|
||||||
|
exports[`history > singleplayer undo/redo > should not modify anything on unrelated appstate change > [end of test] undo stack 1`] = `[]`;
|
||||||
|
|
||||||
exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] appState 1`] = `
|
exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] appState 1`] = `
|
||||||
{
|
{
|
||||||
"activeEmbeddable": null,
|
"activeEmbeddable": null,
|
||||||
|
@ -243,6 +243,37 @@ describe("history", () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not modify anything on unrelated appstate change", async () => {
|
||||||
|
const rect = API.createElement({ type: "rectangle" });
|
||||||
|
await render(
|
||||||
|
<Excalidraw
|
||||||
|
handleKeyboardGlobally={true}
|
||||||
|
initialData={{
|
||||||
|
elements: [rect],
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
API.updateScene({
|
||||||
|
appState: {
|
||||||
|
viewModeEnabled: true,
|
||||||
|
},
|
||||||
|
captureUpdate: CaptureUpdateAction.NEVER,
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(h.state.viewModeEnabled).toBe(true);
|
||||||
|
expect(API.getUndoStack().length).toBe(0);
|
||||||
|
expect(API.getRedoStack().length).toBe(0);
|
||||||
|
expect(h.elements).toEqual([
|
||||||
|
expect.objectContaining({ id: rect.id, isDeleted: false }),
|
||||||
|
]);
|
||||||
|
expect(h.store.snapshot.elements.get(rect.id)).toEqual(
|
||||||
|
expect.objectContaining({ id: rect.id, isDeleted: false }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should not clear the redo stack on standalone appstate change", async () => {
|
it("should not clear the redo stack on standalone appstate change", async () => {
|
||||||
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user