Use IndexedDB for storage to avoid the 5MB limit of localStorage.

This commit is contained in:
NilsUeter
2025-03-18 17:25:25 +01:00
parent 8caa054e1d
commit 1d45b814e6
2 changed files with 116 additions and 2 deletions
+2 -2
View File
@@ -3,7 +3,7 @@ import factionBackground from "../assets/factionBackground.png";
import adeptusAstartesIcon from "../assets/adeptusAstartesIcon.png";
import { Arrow, wavyLine } from "../assets/icons";
import { Weapons, hasDifferentProfiles } from "./Weapons";
import { useLocalStorage } from "../helpers/useLocalStorage";
import { useIndexedDB } from "../helpers/useIndexedDB"; // New hook for IndexedDB
import { ImgEditor } from "./ImgEditor";
export const Roster = ({ roster, onePerPage, colorUserChoice }) => {
@@ -91,7 +91,7 @@ const Unit = ({
modelList,
cost,
} = unit;
const [image, setImage] = useLocalStorage("image" + name);
const [image, setImage] = useIndexedDB("image" + name); // Use IndexedDB hook
const hasImage = image && image !== "undefined";
const [bgRemoved, setBgRemoved] = useState(false);
+114
View File
@@ -0,0 +1,114 @@
import { useState, useEffect } from "react";
const DB_NAME = "fancyscribe";
const STORE_NAME = "images";
const openDB = () => {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains(STORE_NAME)) {
db.createObjectStore(STORE_NAME);
}
};
request.onsuccess = () => {
resolve(request.result);
};
request.onerror = () => {
reject(request.error);
};
});
};
const getItem = (db, key) => {
return new Promise((resolve, reject) => {
const transaction = db.transaction([STORE_NAME], "readonly");
const store = transaction.objectStore(STORE_NAME);
const request = store.get(key);
request.onsuccess = () => {
resolve(request.result);
};
request.onerror = () => {
reject(request.error);
};
});
};
const setItem = (db, key, value) => {
return new Promise((resolve, reject) => {
const transaction = db.transaction([STORE_NAME], "readwrite");
const store = transaction.objectStore(STORE_NAME);
const request = store.put(value, key);
request.onsuccess = () => {
resolve();
};
request.onerror = () => {
reject(request.error);
};
});
};
export const useIndexedDB = (key) => {
const [value, setValue] = useState(null);
useEffect(() => {
let db;
let isMounted = true;
const fetchData = () => {
openDB()
.then((database) => {
db = database;
return getItem(db, key);
})
.then((storedValue) => {
if (isMounted) {
setValue(storedValue);
}
})
.catch((error) => {
console.error("Failed to open DB or get item", error);
});
};
fetchData();
const handleStorageChange = (event) => {
if (event?.detail?.key === key) {
fetchData();
}
};
window.addEventListener("storage", handleStorageChange);
return () => {
isMounted = false;
window.removeEventListener("storage", handleStorageChange);
if (db) {
db.close();
}
};
}, [key]);
const setStoredValue = (newValue) => {
openDB()
.then((db) => setItem(db, key, newValue))
.then(() => {
setValue(newValue);
window.dispatchEvent(new CustomEvent("storage", { detail: { key } }));
})
.catch((error) => {
console.error("Failed to set item", error);
});
};
return [value, setStoredValue];
};