|
@@ -1,6 +1,9 @@
|
|
|
import { mutateElement } from "./element/mutateElement";
|
|
|
import { ExcalidrawElement } from "./element/types";
|
|
|
-import { generateKeyBetween, generateNKeysBetween } from "fractional-indexing";
|
|
|
+import {
|
|
|
+ generateKeyBetween,
|
|
|
+ generateNJitteredKeysBetween,
|
|
|
+} from "fractional-indexing-jittered";
|
|
|
|
|
|
type FractionalIndex = ExcalidrawElement["fractionalIndex"];
|
|
|
|
|
@@ -10,18 +13,22 @@ const isValidFractionalIndex = (
|
|
|
successor: FractionalIndex,
|
|
|
) => {
|
|
|
if (index) {
|
|
|
- if (!predecessor && !successor) {
|
|
|
- return index.length > 0;
|
|
|
+ if (predecessor && successor) {
|
|
|
+ return predecessor < index && index < successor;
|
|
|
}
|
|
|
|
|
|
- if (!predecessor) {
|
|
|
+ if (successor && !predecessor) {
|
|
|
// first element
|
|
|
- return index < successor!;
|
|
|
+ return index < successor;
|
|
|
}
|
|
|
|
|
|
- if (!successor) {
|
|
|
+ if (predecessor && !successor) {
|
|
|
// last element
|
|
|
- return predecessor! < index;
|
|
|
+ return predecessor < index;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!predecessor && !successor) {
|
|
|
+ return index.length > 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -89,7 +96,7 @@ export const fixFractionalIndices = (
|
|
|
elements[movedIndices[movedIndices.length - 1] + 1]?.fractionalIndex ||
|
|
|
null;
|
|
|
|
|
|
- const newKeys = generateNKeysBetween(
|
|
|
+ const newKeys = generateNJitteredKeysBetween(
|
|
|
predecessor,
|
|
|
successor,
|
|
|
movedIndices.length,
|
|
@@ -114,7 +121,26 @@ export const fixFractionalIndices = (
|
|
|
return elements as ExcalidrawElement[];
|
|
|
};
|
|
|
|
|
|
-const generateFractionalIndex = (
|
|
|
+const compareStrings = (a: string, b: string) => {
|
|
|
+ return a < b ? -1 : 1;
|
|
|
+};
|
|
|
+
|
|
|
+export const orderByFractionalIndex = (allElements: ExcalidrawElement[]) => {
|
|
|
+ return allElements.sort((a, b) => {
|
|
|
+ if (a.fractionalIndex && b.fractionalIndex) {
|
|
|
+ if (a.fractionalIndex < b.fractionalIndex) {
|
|
|
+ return -1;
|
|
|
+ } else if (a.fractionalIndex > b.fractionalIndex) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return compareStrings(a.id, b.id);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const restoreFractionalIndex = (
|
|
|
index: FractionalIndex,
|
|
|
predecessor: FractionalIndex,
|
|
|
successor: FractionalIndex,
|
|
@@ -124,13 +150,13 @@ const generateFractionalIndex = (
|
|
|
return index;
|
|
|
}
|
|
|
|
|
|
- if (!predecessor) {
|
|
|
+ if (successor && !predecessor) {
|
|
|
// first element in the array
|
|
|
// insert before successor
|
|
|
return generateKeyBetween(null, successor);
|
|
|
}
|
|
|
|
|
|
- if (!successor) {
|
|
|
+ if (predecessor && !successor) {
|
|
|
// last element in the array
|
|
|
// insert after predecessor
|
|
|
return generateKeyBetween(predecessor, null);
|
|
@@ -144,25 +170,6 @@ const generateFractionalIndex = (
|
|
|
return generateKeyBetween(null, null);
|
|
|
};
|
|
|
|
|
|
-const compareStrings = (a: string, b: string) => {
|
|
|
- return a < b ? -1 : 1;
|
|
|
-};
|
|
|
-
|
|
|
-export const orderByFractionalIndex = (allElements: ExcalidrawElement[]) => {
|
|
|
- return allElements.sort((a, b) => {
|
|
|
- if (a.fractionalIndex && b.fractionalIndex) {
|
|
|
- if (a.fractionalIndex < b.fractionalIndex) {
|
|
|
- return -1;
|
|
|
- } else if (a.fractionalIndex > b.fractionalIndex) {
|
|
|
- return 1;
|
|
|
- }
|
|
|
- return compareStrings(a.id, b.id);
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
/**
|
|
|
* normalize the fractional indicies of the elements in the given array such that
|
|
|
* every element in the array has a fractional index smaller than its successor's
|
|
@@ -170,7 +177,7 @@ export const orderByFractionalIndex = (allElements: ExcalidrawElement[]) => {
|
|
|
* note that this function is not pure, it mutates elements whose fractional indicies
|
|
|
* need updating
|
|
|
*/
|
|
|
-export const normalizeFractionalIndicies = (
|
|
|
+export const restoreFractionalIndicies = (
|
|
|
allElements: readonly ExcalidrawElement[],
|
|
|
) => {
|
|
|
let pre = -1;
|
|
@@ -186,7 +193,7 @@ export const normalizeFractionalIndicies = (
|
|
|
!isValidFractionalIndex(element.fractionalIndex, predecessor, successor)
|
|
|
) {
|
|
|
try {
|
|
|
- const nextFractionalIndex = generateFractionalIndex(
|
|
|
+ const nextFractionalIndex = restoreFractionalIndex(
|
|
|
element.fractionalIndex,
|
|
|
predecessor,
|
|
|
successor,
|
|
@@ -197,7 +204,6 @@ export const normalizeFractionalIndicies = (
|
|
|
fractionalIndex: nextFractionalIndex,
|
|
|
});
|
|
|
} catch (e) {
|
|
|
- console.error("normalizing fractional index", e);
|
|
|
normalized.push(element);
|
|
|
}
|
|
|
} else {
|
|
@@ -209,3 +215,34 @@ export const normalizeFractionalIndicies = (
|
|
|
|
|
|
return normalized;
|
|
|
};
|
|
|
+
|
|
|
+export const validateFractionalIndicies = (
|
|
|
+ elements: readonly ExcalidrawElement[],
|
|
|
+) => {
|
|
|
+ for (let i = 0; i < elements.length; i++) {
|
|
|
+ const element = elements[i];
|
|
|
+ const successor = elements[i + 1];
|
|
|
+
|
|
|
+ if (successor) {
|
|
|
+ if (element.fractionalIndex && successor.fractionalIndex) {
|
|
|
+ if (element.fractionalIndex >= successor.fractionalIndex) {
|
|
|
+ console.log(
|
|
|
+ "this is the case",
|
|
|
+ element.fractionalIndex,
|
|
|
+ successor.fractionalIndex,
|
|
|
+ );
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.log(
|
|
|
+ "this is the other case",
|
|
|
+ element.fractionalIndex,
|
|
|
+ successor.fractionalIndex,
|
|
|
+ );
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+};
|