fix: use idb for elements and app state
This commit is contained in:
@@ -9,6 +9,11 @@ import type { AppState } from "@excalidraw/excalidraw/types";
|
||||
|
||||
import { STORAGE_KEYS } from "../app_constants";
|
||||
|
||||
import {
|
||||
AppStateIndexedDBAdapter,
|
||||
ElementsIndexedDBAdapter,
|
||||
} from "./LocalData";
|
||||
|
||||
export const saveUsernameToLocalStorage = (username: string) => {
|
||||
try {
|
||||
localStorage.setItem(
|
||||
@@ -74,28 +79,146 @@ export const importFromLocalStorage = () => {
|
||||
return { elements, appState };
|
||||
};
|
||||
|
||||
export const getElementsStorageSize = () => {
|
||||
export const importFromIndexedDB = async () => {
|
||||
let savedElements = null;
|
||||
let savedState = null;
|
||||
|
||||
try {
|
||||
const elements = localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_ELEMENTS);
|
||||
const elementsSize = elements?.length || 0;
|
||||
return elementsSize;
|
||||
savedElements = await ElementsIndexedDBAdapter.load();
|
||||
savedState = await AppStateIndexedDBAdapter.load();
|
||||
} catch (error: any) {
|
||||
// unable to access IndexedDB
|
||||
console.error(error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
let elements: ExcalidrawElement[] = [];
|
||||
if (savedElements) {
|
||||
try {
|
||||
elements = clearElementsForLocalStorage(savedElements);
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
let appState = null;
|
||||
if (savedState) {
|
||||
try {
|
||||
appState = {
|
||||
...getDefaultAppState(),
|
||||
...clearAppStateForLocalStorage(savedState),
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
return { elements, appState };
|
||||
};
|
||||
|
||||
export const migrateFromLocalStorageToIndexedDB = async () => {
|
||||
try {
|
||||
// check if we have data in localStorage
|
||||
const savedElements = localStorage.getItem(
|
||||
STORAGE_KEYS.LOCAL_STORAGE_ELEMENTS,
|
||||
);
|
||||
const savedState = localStorage.getItem(
|
||||
STORAGE_KEYS.LOCAL_STORAGE_APP_STATE,
|
||||
);
|
||||
|
||||
if (savedElements || savedState) {
|
||||
// parse and migrate elements
|
||||
if (savedElements) {
|
||||
try {
|
||||
const elements = JSON.parse(savedElements);
|
||||
await ElementsIndexedDBAdapter.save(elements);
|
||||
} catch (error) {
|
||||
console.error("Failed to migrate elements:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// parse and migrate app state
|
||||
if (savedState) {
|
||||
try {
|
||||
const appState = JSON.parse(savedState);
|
||||
await AppStateIndexedDBAdapter.save(appState);
|
||||
} catch (error) {
|
||||
console.error("Failed to migrate app state:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// clear localStorage after successful migration
|
||||
localStorage.removeItem(STORAGE_KEYS.LOCAL_STORAGE_ELEMENTS);
|
||||
localStorage.removeItem(STORAGE_KEYS.LOCAL_STORAGE_APP_STATE);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Migration failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
export const getTotalStorageSize = () => {
|
||||
/**
|
||||
* Get the size of elements stored in IndexedDB (with localStorage fallback)
|
||||
* @returns Promise<number> - Size in bytes
|
||||
*/
|
||||
export const getElementsStorageSize = async () => {
|
||||
try {
|
||||
const appState = localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_APP_STATE);
|
||||
const elements = await ElementsIndexedDBAdapter.load();
|
||||
if (elements) {
|
||||
// calculate size by stringifying the data
|
||||
const elementsString = JSON.stringify(elements);
|
||||
return elementsString.length;
|
||||
}
|
||||
return 0;
|
||||
} catch (error: any) {
|
||||
console.error("Failed to get elements size from IndexedDB:", error);
|
||||
// fallback to localStorage
|
||||
try {
|
||||
const elements = localStorage.getItem(
|
||||
STORAGE_KEYS.LOCAL_STORAGE_ELEMENTS,
|
||||
);
|
||||
return elements?.length || 0;
|
||||
} catch (localStorageError: any) {
|
||||
console.error(
|
||||
"Failed to get elements size from localStorage:",
|
||||
localStorageError,
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the total size of all data stored in IndexedDB and localStorage
|
||||
* @returns Promise<number> - Size in bytes
|
||||
*/
|
||||
export const getTotalStorageSize = async () => {
|
||||
try {
|
||||
const appState = await AppStateIndexedDBAdapter.load();
|
||||
const collab = localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_COLLAB);
|
||||
|
||||
const appStateSize = appState?.length || 0;
|
||||
const appStateSize = appState ? JSON.stringify(appState).length : 0;
|
||||
const collabSize = collab?.length || 0;
|
||||
|
||||
return appStateSize + collabSize + getElementsStorageSize();
|
||||
const elementsSize = await getElementsStorageSize();
|
||||
return appStateSize + collabSize + elementsSize;
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
return 0;
|
||||
console.error("Failed to get total storage size from IndexedDB:", error);
|
||||
// fallback to localStorage
|
||||
try {
|
||||
const appState = localStorage.getItem(
|
||||
STORAGE_KEYS.LOCAL_STORAGE_APP_STATE,
|
||||
);
|
||||
const collab = localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_COLLAB);
|
||||
|
||||
const appStateSize = appState?.length || 0;
|
||||
const collabSize = collab?.length || 0;
|
||||
|
||||
const elementsSize = await getElementsStorageSize();
|
||||
return appStateSize + collabSize + elementsSize;
|
||||
} catch (localStorageError: any) {
|
||||
console.error(
|
||||
"Failed to get total storage size from localStorage:",
|
||||
localStorageError,
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user