fix: stale appState.pendingImageElement (#5322)

* fix: stale `appState.pendingImageElement`

* unrelated fix for devTools race conditions

* snap fix
This commit is contained in:
David Luzar 2022-06-19 14:13:43 +02:00 committed by GitHub
parent fd48c2cf79
commit 4712393b62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 107 additions and 103 deletions

View file

@ -309,7 +309,7 @@ class App extends React.Component<AppProps, AppState> {
UIOptions: DEFAULT_UI_OPTIONS,
};
private scene: Scene;
public scene: Scene;
private resizeObserver: ResizeObserver | undefined;
private nearestScrollableContainer: HTMLElement | Document | undefined;
public library: AppClassProperties["library"];
@ -1141,8 +1141,7 @@ class App extends React.Component<AppProps, AppState> {
if (isImageElement(element)) {
if (
// not placed on canvas yet (but in elements array)
this.state.pendingImageElement &&
element.id === this.state.pendingImageElement.id
this.state.pendingImageElementId === element.id
) {
return false;
}
@ -3002,19 +3001,24 @@ class App extends React.Component<AppProps, AppState> {
// reset image preview on pointerdown
setCursor(this.canvas, CURSOR_TYPE.CROSSHAIR);
if (!this.state.pendingImageElement) {
// retrieve the latest element as the state may be stale
const pendingImageElement =
this.state.pendingImageElementId &&
this.scene.getElement(this.state.pendingImageElementId);
if (!pendingImageElement) {
return;
}
this.setState({
draggingElement: this.state.pendingImageElement,
editingElement: this.state.pendingImageElement,
pendingImageElement: null,
draggingElement: pendingImageElement,
editingElement: pendingImageElement,
pendingImageElementId: null,
multiElement: null,
});
const { x, y } = viewportCoordsToSceneCoords(event, this.state);
mutateElement(this.state.pendingImageElement, {
mutateElement(pendingImageElement, {
x,
y,
});
@ -4330,8 +4334,8 @@ class App extends React.Component<AppProps, AppState> {
pointerDownState.eventListeners.onKeyUp!,
);
if (this.state.pendingImageElement) {
this.setState({ pendingImageElement: null });
if (this.state.pendingImageElementId) {
this.setState({ pendingImageElementId: null });
}
if (draggingElement?.type === "freedraw") {
@ -4819,7 +4823,7 @@ class App extends React.Component<AppProps, AppState> {
await cachedImageData.image;
}
if (
this.state.pendingImageElement?.id !== imageElement.id &&
this.state.pendingImageElementId !== imageElement.id &&
this.state.draggingElement?.id !== imageElement.id
) {
this.initializeImageDimensions(imageElement, true);
@ -4901,7 +4905,7 @@ class App extends React.Component<AppProps, AppState> {
previewDataURL = canvas.toDataURL(MIME_TYPES.svg) as DataURL;
}
if (this.state.pendingImageElement) {
if (this.state.pendingImageElementId) {
setCursor(this.canvas, `url(${previewDataURL}) 4 4, auto`);
}
};
@ -4942,7 +4946,7 @@ class App extends React.Component<AppProps, AppState> {
} else {
this.setState(
{
pendingImageElement: imageElement,
pendingImageElementId: imageElement.id,
},
() => {
this.insertImageElement(
@ -4961,7 +4965,7 @@ class App extends React.Component<AppProps, AppState> {
}
this.setState(
{
pendingImageElement: null,
pendingImageElementId: null,
editingElement: null,
activeTool: updateActiveTool(this.state, { type: "selection" }),
},
@ -5881,10 +5885,10 @@ if (
elements: {
configurable: true,
get() {
return this.app.scene.getElementsIncludingDeleted();
return this.app?.scene.getElementsIncludingDeleted();
},
set(elements: ExcalidrawElement[]) {
return this.app.scene.replaceAllElements(elements);
return this.app?.scene.replaceAllElements(elements);
},
},
});

View file

@ -45,7 +45,7 @@ const getHints = ({ appState, elements, isMobile }: HintViewerProps) => {
return t("hints.text");
}
if (appState.activeTool.type === "image" && appState.pendingImageElement) {
if (appState.activeTool.type === "image" && appState.pendingImageElementId) {
return t("hints.placeImage");
}