fix fractional indices on adding new elements

mrazator/test-fractional-index-and-granular-history
Ryan Di 1 year ago
parent 5bc23d6dee
commit 7dfba985f9

@ -268,6 +268,7 @@ import {
muteFSAbortError,
isTestEnv,
easeOut,
arrayToMap,
} from "../utils";
import {
createSrcDoc,
@ -2921,7 +2922,7 @@ class App extends React.Component<AppProps, AppState> {
...newElements,
];
this.scene.replaceAllElements(nextElements);
this.scene.replaceAllElements(nextElements, arrayToMap(newElements));
newElements.forEach((newElement) => {
if (isTextElement(newElement) && isBoundToContainer(newElement)) {
@ -3147,10 +3148,10 @@ class App extends React.Component<AppProps, AppState> {
this.scene.getElementIndex(frameId),
);
} else {
this.scene.replaceAllElements([
...this.scene.getElementsIncludingDeleted(),
...textElements,
]);
this.scene.replaceAllElements(
[...this.scene.getElementsIncludingDeleted(), ...textElements],
arrayToMap(textElements),
);
}
this.setState({
@ -6137,10 +6138,10 @@ class App extends React.Component<AppProps, AppState> {
height,
});
this.scene.replaceAllElements([
...this.scene.getElementsIncludingDeleted(),
element,
]);
this.scene.replaceAllElements(
[...this.scene.getElementsIncludingDeleted(), element],
arrayToMap([element]),
);
return element;
};
@ -6192,10 +6193,10 @@ class App extends React.Component<AppProps, AppState> {
validated: null,
});
this.scene.replaceAllElements([
...this.scene.getElementsIncludingDeleted(),
element,
]);
this.scene.replaceAllElements(
[...this.scene.getElementsIncludingDeleted(), element],
arrayToMap([element]),
);
return element;
};
@ -6473,10 +6474,10 @@ class App extends React.Component<AppProps, AppState> {
? newMagicFrameElement(constructorOpts)
: newFrameElement(constructorOpts);
this.scene.replaceAllElements([
...this.scene.getElementsIncludingDeleted(),
frame,
]);
this.scene.replaceAllElements(
[...this.scene.getElementsIncludingDeleted(), frame],
arrayToMap([frame]),
);
this.setState({
multiElement: null,

@ -30,14 +30,14 @@ const isValidFractionalIndex = (
const getContiguousMovedIndices = (
elements: readonly ExcalidrawElement[],
movedElementsMap: Record<string, ExcalidrawElement>,
movedElementsMap: Map<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 (movedElementsMap.has(element.id)) {
if (contiguous.length) {
if (contiguous[contiguous.length - 1] + 1 === i) {
contiguous.push(i);
@ -59,9 +59,22 @@ const getContiguousMovedIndices = (
return result;
};
export const generateFractionalIndexBetween = (
predecessor: FractionalIndex,
successor: FractionalIndex,
) => {
if (predecessor && successor) {
if (predecessor < successor) {
return generateKeyBetween(predecessor, successor);
}
return null;
}
return generateKeyBetween(predecessor, successor);
};
export const fixFractionalIndices = (
elements: readonly ExcalidrawElement[],
movedElementsMap: Record<string, ExcalidrawElement>,
movedElementsMap: Map<string, ExcalidrawElement>,
) => {
const fixedElements = elements.slice();
const contiguousMovedIndices = getContiguousMovedIndices(
@ -95,7 +108,7 @@ export const fixFractionalIndices = (
);
}
} catch (e) {
console.error("error generating fractional indices", e);
console.error("error fixing fractional indices", e);
}
}
@ -164,6 +177,8 @@ export const normalizeFractionalIndicies = (
let pre = -1;
let suc = 1;
const normalized: ExcalidrawElement[] = [];
for (const element of allElements) {
const predecessor = allElements[pre]?.fractionalIndex || null;
const successor = allElements[suc]?.fractionalIndex || null;
@ -178,20 +193,20 @@ export const normalizeFractionalIndicies = (
successor,
);
mutateElement(
element,
{
normalized.push({
...element,
fractionalIndex: nextFractionalIndex,
},
false,
);
});
} catch (e) {
console.error("normalizing fractional index", e);
normalized.push(element);
}
} else {
normalized.push(element);
}
pre++;
suc++;
}
return allElements;
return normalized;
};

@ -11,7 +11,8 @@ import { getSelectedElements } from "./selection";
import { AppState } from "../types";
import { Assert, SameType } from "../utility-types";
import { randomInteger } from "../random";
import { normalizeFractionalIndicies } from "../fractionalIndex";
import { fixFractionalIndices } from "../fractionalIndex";
import { arrayToMap } from "../utils";
type ElementIdKey = InstanceType<typeof LinearElementEditor>["elementId"];
type ElementKey = ExcalidrawElement | ElementIdKey;
@ -230,9 +231,14 @@ class Scene {
replaceAllElements(
nextElements: readonly ExcalidrawElement[],
mapElementIds = true,
mapOfIndicesToFix?: Map<string, ExcalidrawElement>,
) {
const _nextElements = normalizeFractionalIndicies(nextElements);
let _nextElements;
if (mapOfIndicesToFix) {
_nextElements = fixFractionalIndices(nextElements, mapOfIndicesToFix);
} else {
_nextElements = nextElements;
}
this.elements = _nextElements;
const nextFrameLikes: ExcalidrawFrameLikeElement[] = [];
@ -306,7 +312,7 @@ class Scene {
element,
...this.elements.slice(index),
];
this.replaceAllElements(nextElements);
this.replaceAllElements(nextElements, arrayToMap([element]));
}
insertElementsAtIndex(elements: ExcalidrawElement[], index: number) {
@ -321,14 +327,17 @@ class Scene {
...this.elements.slice(index),
];
this.replaceAllElements(nextElements);
this.replaceAllElements(nextElements, arrayToMap(elements));
}
addNewElement = (element: ExcalidrawElement) => {
if (element.frameId) {
this.insertElementAtIndex(element, this.getElementIndex(element.frameId));
} else {
this.replaceAllElements([...this.elements, element]);
this.replaceAllElements(
[...this.elements, element],
arrayToMap([element]),
);
}
};

@ -235,9 +235,9 @@ const getTargetElementsMap = <T extends ExcalidrawElement>(
) => {
return indices.reduce((acc, index) => {
const element = elements[index];
acc[element.id] = element;
acc.set(element.id, element);
return acc;
}, {} as Record<string, ExcalidrawElement>);
}, new Map<string, ExcalidrawElement>());
};
const shiftElementsByOne = (

Loading…
Cancel
Save