1
0
mirror of https://github.com/excalidraw/excalidraw.git synced 2024-11-10 11:35:52 +01:00

fix: elements in non-existing frame getting removed (#6708)

Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
Ryan Di 2023-06-23 06:10:08 +08:00 committed by GitHub
parent 8dfa2a98bb
commit b7350f9707
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 3 deletions

@ -370,6 +370,24 @@ const repairBoundElement = (
}
};
/**
* Remove an element's frameId if its containing frame is non-existent
*
* NOTE mutates elements.
*/
const repairFrameMembership = (
element: Mutable<ExcalidrawElement>,
elementsMap: Map<string, Mutable<ExcalidrawElement>>,
) => {
if (element.frameId) {
const containingFrame = elementsMap.get(element.frameId);
if (!containingFrame) {
element.frameId = null;
}
}
};
export const restoreElements = (
elements: ImportedDataState["elements"],
/** NOTE doesn't serve for reconciliation */
@ -410,6 +428,10 @@ export const restoreElements = (
// repair binding. Mutates elements.
const restoredElementsMap = arrayToMap(restoredElements);
for (const element of restoredElements) {
if (element.frameId) {
repairFrameMembership(element, restoredElementsMap);
}
if (isTextElement(element) && element.containerId) {
repairBoundElement(element, restoredElementsMap);
} else if (element.boundElements) {

@ -304,7 +304,7 @@ export const groupsAreCompletelyOutOfFrame = (
/**
* Returns a map of frameId to frame elements. Includes empty frames.
*/
export const groupByFrames = (elements: ExcalidrawElementsIncludingDeleted) => {
export const groupByFrames = (elements: readonly ExcalidrawElement[]) => {
const frameElementsMap = new Map<
ExcalidrawElement["id"],
ExcalidrawElement[]
@ -591,6 +591,7 @@ export const updateFrameMembershipOfSelectedElements = (
elementsToFilter.forEach((element) => {
if (
element.frameId &&
!isFrameElement(element) &&
!isElementInFrame(element, allElements, appState)
) {
@ -598,7 +599,9 @@ export const updateFrameMembershipOfSelectedElements = (
}
});
return removeElementsFromFrame(allElements, [...elementsToRemove], appState);
return elementsToRemove.size > 0
? removeElementsFromFrame(allElements, [...elementsToRemove], appState)
: allElements;
};
/**

@ -376,9 +376,22 @@ function shift(
) => ExcalidrawElement[] | readonly ExcalidrawElement[],
elementsToBeMoved?: readonly ExcalidrawElement[],
) {
let rootElements = elements.filter((element) => isRootElement(element));
const elementsMap = arrayToMap(elements);
const frameElementsMap = groupByFrames(elements);
// in case root is non-existent, we promote children elements to root
let rootElements = elements.filter(
(element) =>
isRootElement(element) ||
(element.frameId && !elementsMap.has(element.frameId)),
);
// and remove non-existet root
for (const frameId of frameElementsMap.keys()) {
if (!elementsMap.has(frameId)) {
frameElementsMap.delete(frameId);
}
}
// shift the root elements first
rootElements = shiftFunction(
rootElements,