From d3361f910ba123f5df53aed9bdd746ec3fb9d904 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Fri, 14 Jul 2023 17:13:24 +0530 Subject: [PATCH] remove convertToExcalidrawElements call from restore --- src/data/blob.ts | 5 +- src/data/restore.ts | 56 +++++------- src/data/transform.ts | 99 ++++++++++++++++++++- src/data/types.ts | 103 +--------------------- src/excalidraw-app/data/index.ts | 1 - src/excalidraw-app/index.tsx | 7 +- src/packages/excalidraw/example/App.tsx | 4 +- src/tests/packages/utils.unmocked.test.ts | 4 +- 8 files changed, 128 insertions(+), 151 deletions(-) diff --git a/src/data/blob.ts b/src/data/blob.ts index 4a9e1ac26c..08c394ac74 100644 --- a/src/data/blob.ts +++ b/src/data/blob.ts @@ -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( diff --git a/src/data/restore.ts b/src/data/restore.ts index c90279ffa8..2c3fc8bb6d 100644 --- a/src/data/restore.ts +++ b/src/data/restore.ts @@ -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(); - 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; diff --git a/src/data/transform.ts b/src/data/transform.ts index beb5000ca3..547222d749 100644 --- a/src/data/transform.ts +++ b/src/data/transform.ts @@ -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; + 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) + ) & + MarkOptional; + 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) + ) & + MarkOptional; +} & Partial; + +export type ValidContainer = + | { + type: Exclude; + id?: ExcalidrawGenericElement["id"]; + label?: { + text: string; + fontSize?: number; + fontFamily?: FontFamilyValues; + textAlign?: TextAlign; + verticalAlign?: VerticalAlign; + } & MarkOptional; + } & 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`); diff --git a/src/data/types.ts b/src/data/types.ts index ff61e242e8..69112b6b6c 100644 --- a/src/data/types.ts +++ b/src/data/types.ts @@ -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; - 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) - ) & - MarkOptional; - 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) - ) & - MarkOptional; -} & Partial; - -export type ValidContainer = - | { - type: Exclude; - id?: ExcalidrawGenericElement["id"]; - label?: { - text: string; - fontSize?: number; - fontFamily?: FontFamilyValues; - textAlign?: TextAlign; - verticalAlign?: VerticalAlign; - } & MarkOptional; - } & ElementConstructorOpts; - export interface ImportedDataState { type?: string; version?: number; diff --git a/src/excalidraw-app/data/index.ts b/src/excalidraw-app/data/index.ts index a40f8a3e2b..c85eb27c04 100644 --- a/src/excalidraw-app/data/index.ts +++ b/src/excalidraw-app/data/index.ts @@ -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"; diff --git a/src/excalidraw-app/index.tsx b/src/excalidraw-app/index.tsx index d078e5c7ca..dab0eda038 100644 --- a/src/excalidraw-app/index.tsx +++ b/src/excalidraw-app/index.tsx @@ -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)) { diff --git a/src/packages/excalidraw/example/App.tsx b/src/packages/excalidraw/example/App.tsx index 0d85a1aa05..72cf08a25f 100644 --- a/src/packages/excalidraw/example/App.tsx +++ b/src/packages/excalidraw/example/App.tsx @@ -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: { diff --git a/src/tests/packages/utils.unmocked.test.ts b/src/tests/packages/utils.unmocked.test.ts index 3b1c1d9c0a..e8cb14930a 100644 --- a/src/tests/packages/utils.unmocked.test.ts +++ b/src/tests/packages/utils.unmocked.test.ts @@ -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), ); }); });