Visualizer work
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

118 lines
4.1 KiB

// In src/db.js, replace the entire file content with this:
let db;
// Initializes the IndexedDB database.
// Opens or creates the 'visualizerDB' database.
export function initDB(callback) {
const request = indexedDB.open("visualizerDB", 1);
request.onupgradeneeded = function (event) {
const db = event.target.result;
if (!db.objectStoreNames.contains("files")) {
db.createObjectStore("files");
// Creates an object store named 'files' if it doesn't exist.
}
};
request.onsuccess = function (event) {
db = event.target.result;
console.log("Database initialized");
// Assigns the opened database to the 'db' variable.
if (callback) callback();
};
request.onerror = function (event) {
console.error("IndexedDB error:", event.target.errorCode);
// Even if DB fails, call the callback so the app doesn't hang
// Logs any errors during database operations.
// Calls the callback even if there's an error to prevent the app from hanging.
if (callback) callback();
};
}
// Saves a file (Blob) along with its metadata into the IndexedDB.
export function saveFileWithMetadata(key, file) {
if (!db) return;
const transaction = db.transaction(["files"], "readwrite");
const store = transaction.objectStore("files");
// Creates a read-write transaction and gets the 'files' object store.
// Store an object containing the blob and its metadata
const dataToStore = {
filename: file.name,
size: file.size,
type: file.type,
blob: file
// Prepares the data object to be stored, including filename, size, type, and the file itself (as a Blob).
};
const request = store.put(dataToStore, key);
request.onsuccess = () => console.log(`File '${file.name}' saved to DB with metadata.`);
// Gracefully handle errors, especially quota limits
transaction.onerror = (event) => {
if (event.target.error.name === 'QuotaExceededError') {
alert("Could not cache file: Browser storage quota exceeded. The app will still work for this session.");
} else {
// Handles potential errors during the save operation, such as QuotaExceededError.
console.error(`Error saving file '${key}':`, event.target.error);
}
};
}
// Loads a file from IndexedDB, performing checks for filename and size to ensure data integrity.
export function loadFreshFileFromDB(key, expectedFilename) {
return new Promise((resolve) => {
if (!db || !expectedFilename) {
resolve(null);
return;
}
const transaction = db.transaction(["files"], "readonly");
// Creates a read-only transaction.
const store = transaction.objectStore("files");
const request = store.get(key);
request.onsuccess = function () {
const cachedData = request.result;
if (!cachedData) {
console.log(`Cache miss for key '${key}': No data found.`);
// If no data is found for the key, resolve with null.
resolve(null);
return;
}
// 1. Versioning Check: Do the filenames match?
if (cachedData.filename !== expectedFilename) {
// Checks if the cached filename matches the expected filename.
console.warn(`Cache miss for key '${key}': Stale data found (Filename mismatch).`);
resolve(null);
return;
}
// 2. Integrity Check: Do the sizes match?
// Checks if the cached file size matches the stored size metadata.
if (cachedData.blob.size !== cachedData.size) {
console.error(`Cache miss for key '${key}': Corrupted data found (Size mismatch).`);
resolve(null);
return;
}
// All checks passed!
// If all checks pass, resolve with the cached Blob.
console.log(`Cache hit for '${expectedFilename}'`);
resolve(cachedData.blob);
};
request.onerror = (event) => {
console.error(`Error loading file '${key}' from DB:`, event.target.error);
// Logs any errors during the load operation.
resolve(null);
};
});
}