remove convertToExcalidrawElements call from restore

This commit is contained in:
Aakansha Doshi 2023-07-14 17:13:24 +05:30
parent 2ff0528a4f
commit d3361f910b
8 changed files with 128 additions and 151 deletions

View file

@ -13,7 +13,6 @@ import { FileSystemHandle, nativeFileSystemSupported } from "./filesystem";
import { isValidExcalidrawData, isValidLibrary } from "./json";
import { restore, restoreLibraryItems } from "./restore";
import { ImportedLibraryData } from "./types";
import { convertToExcalidrawElements } from "../data/transform";
const parseFileContents = async (blob: Blob | File) => {
let contents: string;
@ -135,9 +134,7 @@ export const loadSceneOrLibraryFromBlob = async (
try {
const data = JSON.parse(contents);
if (isValidExcalidrawData(data)) {
const excaldrawElements = convertToExcalidrawElements(
data.elements || [],
);
const excaldrawElements = data.elements || [];
return {
type: MIME_TYPES.excalidraw,
data: restore(

View file

@ -41,10 +41,7 @@ import {
getDefaultLineHeight,
measureBaseline,
} from "../element/textElement";
import {
ExcalidrawProgrammaticAPI,
convertToExcalidrawElements,
} from "../data/transform";
import { normalizeLink } from "./url";
type RestoredAppState = Omit<
@ -394,44 +391,37 @@ const repairFrameMembership = (
};
export const restoreElements = (
elements: ExcalidrawProgrammaticAPI["elements"],
elements: ImportedDataState["elements"],
/** NOTE doesn't serve for reconciliation */
localElements: readonly ExcalidrawElement[] | null | undefined,
opts?: { refreshDimensions?: boolean; repairBindings?: boolean } | undefined,
): ExcalidrawElement[] => {
// used to detect duplicate top-level element ids
const existingIds = new Set<string>();
const excalidrawElements = convertToExcalidrawElements(elements);
const localElementsMap = localElements ? arrayToMap(localElements) : null;
const restoredElements = (excalidrawElements || []).reduce(
(elements, element) => {
// filtering out selection, which is legacy, no longer kept in elements,
// and causing issues if retained
if (element.type !== "selection" && !isInvisiblySmallElement(element)) {
let migratedElement: ExcalidrawElement | null = restoreElement(
element,
opts?.refreshDimensions,
);
if (migratedElement) {
const localElement = localElementsMap?.get(element.id);
if (localElement && localElement.version > migratedElement.version) {
migratedElement = bumpVersion(
migratedElement,
localElement.version,
);
}
if (existingIds.has(migratedElement.id)) {
migratedElement = { ...migratedElement, id: randomId() };
}
existingIds.add(migratedElement.id);
elements.push(migratedElement);
const restoredElements = (elements || []).reduce((elements, element) => {
// filtering out selection, which is legacy, no longer kept in elements,
// and causing issues if retained
if (element.type !== "selection" && !isInvisiblySmallElement(element)) {
let migratedElement: ExcalidrawElement | null = restoreElement(
element,
opts?.refreshDimensions,
);
if (migratedElement) {
const localElement = localElementsMap?.get(element.id);
if (localElement && localElement.version > migratedElement.version) {
migratedElement = bumpVersion(migratedElement, localElement.version);
}
if (existingIds.has(migratedElement.id)) {
migratedElement = { ...migratedElement, id: randomId() };
}
existingIds.add(migratedElement.id);
elements.push(migratedElement);
}
return elements;
},
[] as ExcalidrawElement[],
);
}
return elements;
}, [] as ExcalidrawElement[]);
if (!opts?.repairBindings) {
return restoredElements;

View file

@ -24,16 +24,109 @@ import {
import {
ExcalidrawBindableElement,
ExcalidrawElement,
ExcalidrawFrameElement,
ExcalidrawFreeDrawElement,
ExcalidrawGenericElement,
ExcalidrawImageElement,
ExcalidrawLinearElement,
ExcalidrawSelectionElement,
ExcalidrawTextElement,
FontFamilyValues,
TextAlign,
VerticalAlign,
} from "../element/types";
import { MarkOptional } from "../utility-types";
import { getFontString } from "../utils";
import { ValidContainer, ValidLinearElement } from "./types";
export type ValidLinearElement = {
type: "arrow" | "line";
x: number;
y: number;
label?: {
text: string;
fontSize?: number;
fontFamily?: FontFamilyValues;
textAlign?: TextAlign;
verticalAlign?: VerticalAlign;
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
end?:
| (
| (
| {
type: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text" | "frame"
>;
id?: ExcalidrawGenericElement["id"];
}
| {
id: ExcalidrawGenericElement["id"];
type?: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text" | "frame"
>;
}
)
| ((
| {
type: "text";
text: string;
}
| {
type?: "text";
id: ExcalidrawTextElement["id"];
text: string;
}
) &
Partial<ExcalidrawTextElement>)
) &
MarkOptional<ElementConstructorOpts, "x" | "y">;
start?:
| (
| (
| {
type: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text" | "frame"
>;
id?: ExcalidrawGenericElement["id"];
}
| {
id: ExcalidrawGenericElement["id"];
type?: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text" | "frame"
>;
}
)
| ((
| {
type: "text";
text: string;
}
| {
type?: "text";
id: ExcalidrawTextElement["id"];
text: string;
}
) &
Partial<ExcalidrawTextElement>)
) &
MarkOptional<ElementConstructorOpts, "x" | "y">;
} & Partial<ExcalidrawLinearElement>;
export type ValidContainer =
| {
type: Exclude<ExcalidrawGenericElement["type"], "selection">;
id?: ExcalidrawGenericElement["id"];
label?: {
text: string;
fontSize?: number;
fontFamily?: FontFamilyValues;
textAlign?: TextAlign;
verticalAlign?: VerticalAlign;
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
} & ElementConstructorOpts;
export interface ExcalidrawProgrammaticAPI {
elements?:
@ -168,7 +261,7 @@ const bindLinearElementToElement = (
.get()
.find((ele) => ele?.id === start.id) as Exclude<
ExcalidrawBindableElement,
ExcalidrawImageElement
ExcalidrawImageElement | ExcalidrawFrameElement
>;
if (!existingElement) {
console.error(`No element for start binding with id ${start.id} found`);
@ -235,7 +328,7 @@ const bindLinearElementToElement = (
.get()
.find((ele) => ele?.id === end.id) as Exclude<
ExcalidrawBindableElement,
ExcalidrawImageElement
ExcalidrawImageElement | ExcalidrawFrameElement
>;
if (!existingElement) {
console.error(`No element for end binding with id ${end.id} found`);

View file

@ -1,13 +1,4 @@
import {
ExcalidrawBindableElement,
ExcalidrawElement,
ExcalidrawGenericElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
FontFamilyValues,
TextAlign,
VerticalAlign,
} from "../element/types";
import { ExcalidrawElement } from "../element/types";
import {
AppState,
BinaryFiles,
@ -16,8 +7,6 @@ import {
} from "../types";
import type { cleanAppStateForExport } from "../appState";
import { VERSIONS } from "../constants";
import { MarkOptional } from "../utility-types";
import { ElementConstructorOpts } from "../element/newElement";
export interface ExportedDataState {
type: string;
@ -40,96 +29,6 @@ export type LegacyAppState = {
isSidebarDocked: [boolean, "defaultSidebarDockedPreference"];
};
export type ValidLinearElement = {
type: "arrow" | "line";
x: number;
y: number;
label?: {
text: string;
fontSize?: number;
fontFamily?: FontFamilyValues;
textAlign?: TextAlign;
verticalAlign?: VerticalAlign;
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
end?:
| (
| (
| {
type: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text"
>;
id?: ExcalidrawGenericElement["id"];
}
| {
id: ExcalidrawGenericElement["id"];
type?: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text"
>;
}
)
| ((
| {
type: "text";
text: string;
}
| {
type?: "text";
id: ExcalidrawTextElement["id"];
text: string;
}
) &
Partial<ExcalidrawTextElement>)
) &
MarkOptional<ElementConstructorOpts, "x" | "y">;
start?:
| (
| (
| {
type: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text"
>;
id?: ExcalidrawGenericElement["id"];
}
| {
id: ExcalidrawGenericElement["id"];
type?: Exclude<
ExcalidrawBindableElement["type"],
"image" | "selection" | "text"
>;
}
)
| ((
| {
type: "text";
text: string;
}
| {
type?: "text";
id: ExcalidrawTextElement["id"];
text: string;
}
) &
Partial<ExcalidrawTextElement>)
) &
MarkOptional<ElementConstructorOpts, "x" | "y">;
} & Partial<ExcalidrawLinearElement>;
export type ValidContainer =
| {
type: Exclude<ExcalidrawGenericElement["type"], "selection">;
id?: ExcalidrawGenericElement["id"];
label?: {
text: string;
fontSize?: number;
fontFamily?: FontFamilyValues;
textAlign?: TextAlign;
verticalAlign?: VerticalAlign;
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
} & ElementConstructorOpts;
export interface ImportedDataState {
type?: string;
version?: number;

View file

@ -7,7 +7,6 @@ import {
import { serializeAsJSON } from "../../data/json";
import { restore } from "../../data/restore";
import { ImportedDataState } from "../../data/types";
import { convertToExcalidrawElements } from "../../data/transform";
import { isInvisiblySmallElement } from "../../element/sizeHelpers";
import { isInitializedImageElement } from "../../element/typeChecks";
import { ExcalidrawElement, FileId } from "../../element/types";

View file

@ -91,7 +91,6 @@ import { appJotaiStore } from "./app-jotai";
import "./index.scss";
import { ResolutionType } from "../utility-types";
import { convertToExcalidrawElements } from "../data/transform";
import { ShareableLinkDialog } from "../components/ShareableLinkDialog";
import { openConfirmModal } from "../components/OverwriteConfirm/OverwriteConfirmState";
import { OverwriteConfirmDialog } from "../components/OverwriteConfirm/OverwriteConfirm";
@ -229,7 +228,7 @@ const initializeScene = async (opts: {
isLoading: false,
},
elements: reconcileElements(
convertToExcalidrawElements(scene?.elements || []),
scene?.elements || [],
excalidrawAPI.getSceneElementsIncludingDeleted(),
excalidrawAPI.getAppState(),
),
@ -310,7 +309,7 @@ const ExcalidrawWrapper = () => {
if (data.scene.elements) {
collabAPI
.fetchImageFilesFromFirebase({
elements: convertToExcalidrawElements(data.scene.elements),
elements: data.scene.elements,
forceFetchFiles: true,
})
.then(({ loadedFiles, erroredFiles }) => {
@ -323,7 +322,7 @@ const ExcalidrawWrapper = () => {
});
}
} else {
const sceneElements = convertToExcalidrawElements(data.scene.elements);
const sceneElements = data.scene.elements;
const fileIds =
sceneElements?.reduce((acc, element) => {
if (isInitializedImageElement(element)) {

View file

@ -189,7 +189,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
const updateScene = () => {
const sceneData = {
elements: restoreElements(
[
convertToExcalidrawElements([
{
type: "rectangle",
id: "rect-1",
@ -222,7 +222,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
y: 100,
text: "HELLO WORLD!",
},
],
]),
null,
),
appState: {

View file

@ -32,7 +32,7 @@ describe("embedding scene data", () => {
const importedData: ImportedDataState = JSON.parse(parsedString);
expect(sourceElements.map((x) => x.id)).toEqual(
convertToExcalidrawElements(importedData.elements)?.map((el) => el.id),
importedData.elements?.map((el) => el.id),
);
});
});
@ -61,7 +61,7 @@ describe("embedding scene data", () => {
const importedData: ImportedDataState = JSON.parse(parsedString);
expect(sourceElements.map((x) => x.id)).toEqual(
convertToExcalidrawElements(importedData.elements)?.map((el) => el.id),
importedData.elements?.map((el) => el.id),
);
});
});