generate real fractional index after z-index actions

mrazator/test-fractional-index-and-granular-history
Ryan Di 1 year ago
parent d1a9c593cc
commit 093e684d9e

@ -43,6 +43,7 @@ import {
measureBaseline, measureBaseline,
} from "../element/textElement"; } from "../element/textElement";
import { normalizeLink } from "./url"; import { normalizeLink } from "./url";
import { normalizeFractionalIndicies } from "../fractionalIndex";
type RestoredAppState = Omit< type RestoredAppState = Omit<
AppState, AppState,
@ -460,7 +461,7 @@ export const restoreElements = (
} }
} }
return restoredElements; return normalizeFractionalIndicies(restoredElements) as ExcalidrawElement[];
}; };
const coalesceAppStateValue = < const coalesceAppStateValue = <

@ -1,6 +1,6 @@
import { mutateElement } from "./element/mutateElement"; import { mutateElement } from "./element/mutateElement";
import { ExcalidrawElement } from "./element/types"; import { ExcalidrawElement } from "./element/types";
import { generateKeyBetween } from "fractional-indexing"; import { generateKeyBetween, generateNKeysBetween } from "fractional-indexing";
type FractionalIndex = ExcalidrawElement["fractionalIndex"]; type FractionalIndex = ExcalidrawElement["fractionalIndex"];
@ -28,6 +28,80 @@ const isValidFractionalIndex = (
return false; return false;
}; };
const getContiguousMovedIndices = (
elements: readonly ExcalidrawElement[],
movedElementsMap: Record<string, ExcalidrawElement>,
) => {
const result: number[][] = [];
const contiguous: number[] = [];
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
if (movedElementsMap[element.id]) {
if (contiguous.length) {
if (contiguous[contiguous.length - 1] + 1 === i) {
contiguous.push(i);
} else {
result.push(contiguous.slice());
contiguous.length = 0;
contiguous.push(i);
}
} else {
contiguous.push(i);
}
}
}
if (contiguous.length > 0) {
result.push(contiguous.slice());
}
return result;
};
export const fixFractionalIndices = (
elements: readonly ExcalidrawElement[],
movedElementsMap: Record<string, ExcalidrawElement>,
) => {
const fixedElements = elements.slice();
const contiguousMovedIndices = getContiguousMovedIndices(
fixedElements,
movedElementsMap,
);
for (const movedIndices of contiguousMovedIndices) {
try {
const predecessor =
fixedElements[movedIndices[0] - 1]?.fractionalIndex || null;
const successor =
fixedElements[movedIndices[movedIndices.length - 1] + 1]
?.fractionalIndex || null;
const newKeys = generateNKeysBetween(
predecessor,
successor,
movedIndices.length,
);
for (let i = 0; i < movedIndices.length; i++) {
const element = fixedElements[movedIndices[i]];
mutateElement(
element,
{
fractionalIndex: newKeys[i],
},
false,
);
}
} catch (e) {
console.error("error generating fractional indices", e);
}
}
return fixedElements;
};
const generateFractionalIndex = ( const generateFractionalIndex = (
index: FractionalIndex, index: FractionalIndex,
predecessor: FractionalIndex, predecessor: FractionalIndex,

@ -328,7 +328,9 @@ class Scene {
if (element.frameId) { if (element.frameId) {
this.insertElementAtIndex(element, this.getElementIndex(element.frameId)); this.insertElementAtIndex(element, this.getElementIndex(element.frameId));
} else { } else {
this.replaceAllElements([...this.elements, element]); this.replaceAllElements(
normalizeFractionalIndicies([...this.elements, element]),
);
} }
}; };

@ -1,6 +1,7 @@
import { bumpVersion } from "./element/mutateElement"; import { bumpVersion } from "./element/mutateElement";
import { isFrameLikeElement } from "./element/typeChecks"; import { isFrameLikeElement } from "./element/typeChecks";
import { ExcalidrawElement, ExcalidrawFrameLikeElement } from "./element/types"; import { ExcalidrawElement, ExcalidrawFrameLikeElement } from "./element/types";
import { fixFractionalIndices } from "./fractionalIndex";
import { getElementsInGroup } from "./groups"; import { getElementsInGroup } from "./groups";
import { getSelectedElements } from "./scene"; import { getSelectedElements } from "./scene";
import Scene from "./scene/Scene"; import Scene from "./scene/Scene";
@ -312,12 +313,7 @@ const shiftElementsByOne = (
]; ];
}); });
return elements.map((element) => { return fixFractionalIndices(elements, targetElementsMap);
if (targetElementsMap[element.id]) {
return bumpVersion(element);
}
return element;
});
}; };
const shiftElementsToEnd = ( const shiftElementsToEnd = (
@ -390,19 +386,22 @@ const shiftElementsToEnd = (
const leadingElements = elements.slice(0, leadingIndex); const leadingElements = elements.slice(0, leadingIndex);
const trailingElements = elements.slice(trailingIndex + 1); const trailingElements = elements.slice(trailingIndex + 1);
return direction === "left" return fixFractionalIndices(
? [ direction === "left"
...leadingElements, ? [
...targetElements, ...leadingElements,
...displacedElements, ...targetElements,
...trailingElements, ...displacedElements,
] ...trailingElements,
: [ ]
...leadingElements, : [
...displacedElements, ...leadingElements,
...targetElements, ...displacedElements,
...trailingElements, ...targetElements,
]; ...trailingElements,
],
targetElementsMap,
);
}; };
function shiftElementsAccountingForFrames( function shiftElementsAccountingForFrames(

Loading…
Cancel
Save