mirror of
https://github.com/calli-eve/eve-pi.git
synced 2026-02-11 18:28:49 +01:00
some users have so many characters that we cant keep them in localSotrage. use db
This commit is contained in:
@@ -18,6 +18,7 @@ import { useSearchParams } from "next/navigation";
|
|||||||
import { EvePraisalResult, fetchAllPrices } from "@/eve-praisal";
|
import { EvePraisalResult, fetchAllPrices } from "@/eve-praisal";
|
||||||
import { getPlanet, getPlanetUniverse, getPlanets } from "@/planets";
|
import { getPlanet, getPlanetUniverse, getPlanets } from "@/planets";
|
||||||
import { PlanetConfig } from "@/types";
|
import { PlanetConfig } from "@/types";
|
||||||
|
import { saveCharacters as saveCharactersDB, loadCharacters } from "@/storage";
|
||||||
|
|
||||||
// Add batch processing utility
|
// Add batch processing utility
|
||||||
const processInBatches = async <T, R>(
|
const processInBatches = async <T, R>(
|
||||||
@@ -108,13 +109,8 @@ const Home = () => {
|
|||||||
return Promise.resolve(characters);
|
return Promise.resolve(characters);
|
||||||
};
|
};
|
||||||
|
|
||||||
const initializeCharacters = useCallback((): AccessToken[] => {
|
const initializeCharacters = useCallback(async (): Promise<AccessToken[]> => {
|
||||||
const localStorageCharacters = localStorage.getItem("characters");
|
return await loadCharacters();
|
||||||
if (localStorageCharacters) {
|
|
||||||
const characterArray: AccessToken[] = JSON.parse(localStorageCharacters);
|
|
||||||
return characterArray.filter((c) => c.access_token && c.character);
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initializeCharacterPlanets = (
|
const initializeCharacterPlanets = (
|
||||||
@@ -139,9 +135,8 @@ const Home = () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const saveCharacters = (characters: AccessToken[]): AccessToken[] => {
|
const saveCharacters = async (characters: AccessToken[]): Promise<AccessToken[]> => {
|
||||||
localStorage.setItem("characters", JSON.stringify(characters));
|
return await saveCharactersDB(characters);
|
||||||
return characters;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const restoreCharacters = (characters: AccessToken[]) => {
|
const restoreCharacters = (characters: AccessToken[]) => {
|
||||||
@@ -279,8 +274,8 @@ const Home = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const ESI_CACHE_TIME_MS = 3000000;
|
const ESI_CACHE_TIME_MS = 3000000;
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(async () => {
|
||||||
const characters = initializeCharacters();
|
const characters = await initializeCharacters();
|
||||||
refreshSession(characters)
|
refreshSession(characters)
|
||||||
.then(saveCharacters)
|
.then(saveCharacters)
|
||||||
.then(initializeCharacterPlanets)
|
.then(initializeCharacterPlanets)
|
||||||
|
|||||||
107
src/storage.ts
Normal file
107
src/storage.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { AccessToken } from "./types";
|
||||||
|
|
||||||
|
const DB_NAME = "eve-pi-db";
|
||||||
|
const DB_VERSION = 1;
|
||||||
|
const STORE_NAME = "characters";
|
||||||
|
|
||||||
|
// Initialize IndexedDB
|
||||||
|
const initDB = (): Promise<IDBDatabase> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
||||||
|
|
||||||
|
request.onerror = () => reject(request.error);
|
||||||
|
request.onsuccess = () => resolve(request.result);
|
||||||
|
|
||||||
|
request.onupgradeneeded = (event) => {
|
||||||
|
const db = (event.target as IDBOpenDBRequest).result;
|
||||||
|
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
||||||
|
db.createObjectStore(STORE_NAME);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save characters to IndexedDB
|
||||||
|
export const saveCharacters = async (
|
||||||
|
characters: AccessToken[]
|
||||||
|
): Promise<AccessToken[]> => {
|
||||||
|
try {
|
||||||
|
const db = await initDB();
|
||||||
|
const transaction = db.transaction([STORE_NAME], "readwrite");
|
||||||
|
const store = transaction.objectStore(STORE_NAME);
|
||||||
|
|
||||||
|
store.put(characters, "characters");
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
transaction.oncomplete = () => {
|
||||||
|
db.close();
|
||||||
|
resolve(characters);
|
||||||
|
};
|
||||||
|
transaction.onerror = () => {
|
||||||
|
db.close();
|
||||||
|
reject(transaction.error);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to save to IndexedDB:", error);
|
||||||
|
// Fallback: save minimal data to localStorage
|
||||||
|
try {
|
||||||
|
const minimalCharacters = characters.map((c) => ({
|
||||||
|
...c,
|
||||||
|
planets: [], // Strip planet data to reduce size
|
||||||
|
}));
|
||||||
|
localStorage.setItem("characters", JSON.stringify(minimalCharacters));
|
||||||
|
console.warn("Saved minimal character data to localStorage fallback");
|
||||||
|
} catch (storageError) {
|
||||||
|
console.error("Failed to save to localStorage fallback:", storageError);
|
||||||
|
}
|
||||||
|
return characters;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load characters from IndexedDB
|
||||||
|
export const loadCharacters = async (): Promise<AccessToken[]> => {
|
||||||
|
try {
|
||||||
|
const db = await initDB();
|
||||||
|
const transaction = db.transaction([STORE_NAME], "readonly");
|
||||||
|
const store = transaction.objectStore(STORE_NAME);
|
||||||
|
const request = store.get("characters");
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request.onsuccess = () => {
|
||||||
|
db.close();
|
||||||
|
const characters = request.result as AccessToken[] | undefined;
|
||||||
|
if (characters && characters.length > 0) {
|
||||||
|
resolve(characters);
|
||||||
|
} else {
|
||||||
|
// Try localStorage migration
|
||||||
|
resolve(migrateFromLocalStorage());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
request.onerror = () => {
|
||||||
|
db.close();
|
||||||
|
reject(request.error);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to load from IndexedDB:", error);
|
||||||
|
// Fallback to localStorage
|
||||||
|
return migrateFromLocalStorage();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Migrate data from localStorage to IndexedDB
|
||||||
|
const migrateFromLocalStorage = (): AccessToken[] => {
|
||||||
|
try {
|
||||||
|
const localStorageCharacters = localStorage.getItem("characters");
|
||||||
|
if (localStorageCharacters) {
|
||||||
|
const characterArray: AccessToken[] = JSON.parse(localStorageCharacters);
|
||||||
|
const filtered = characterArray.filter((c) => c.access_token && c.character);
|
||||||
|
// Don't delete from localStorage yet - keep as backup
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to migrate from localStorage:", error);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user