Spaces:
Runtime error
Runtime error
Persist gallery images in IndexedDB across page reloads
Browse files- index.html +58 -0
index.html
CHANGED
|
@@ -448,6 +448,50 @@ if (hostname.endsWith(".hf.space") || hostname.includes(".dev.")) {
|
|
| 448 |
window.parent.postMessage(ZEROGPU_HEADERS_MSG, origin);
|
| 449 |
}
|
| 450 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 451 |
// State
|
| 452 |
const gallery = [];
|
| 453 |
let client = null;
|
|
@@ -475,6 +519,18 @@ const errorToast = document.getElementById("error-toast");
|
|
| 475 |
|
| 476 |
// ---- Init ----
|
| 477 |
async function init() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 478 |
try {
|
| 479 |
client = await Client.connect(window.location.origin);
|
| 480 |
generateBtn.disabled = false;
|
|
@@ -515,6 +571,7 @@ async function generate() {
|
|
| 515 |
placeholderItem.height = data.height;
|
| 516 |
placeholderItem.pending = false;
|
| 517 |
replacePlaceholder(placeholderItem);
|
|
|
|
| 518 |
|
| 519 |
if (randomSeedEl.checked) {
|
| 520 |
seedInputEl.value = data.seed;
|
|
@@ -610,6 +667,7 @@ function clearGallery() {
|
|
| 610 |
gallery.length = 0;
|
| 611 |
galleryEl.innerHTML = "";
|
| 612 |
updateGalleryHeader();
|
|
|
|
| 613 |
}
|
| 614 |
|
| 615 |
// ---- Lightbox ----
|
|
|
|
| 448 |
window.parent.postMessage(ZEROGPU_HEADERS_MSG, origin);
|
| 449 |
}
|
| 450 |
|
| 451 |
+
// ---- IndexedDB persistence ----
|
| 452 |
+
const DB_NAME = "z-image-studio";
|
| 453 |
+
const DB_STORE = "images";
|
| 454 |
+
|
| 455 |
+
function openDB() {
|
| 456 |
+
return new Promise((resolve, reject) => {
|
| 457 |
+
const req = indexedDB.open(DB_NAME, 1);
|
| 458 |
+
req.onupgradeneeded = () => req.result.createObjectStore(DB_STORE, { keyPath: "id" });
|
| 459 |
+
req.onsuccess = () => resolve(req.result);
|
| 460 |
+
req.onerror = () => reject(req.error);
|
| 461 |
+
});
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
async function saveItem(item) {
|
| 465 |
+
const db = await openDB();
|
| 466 |
+
const tx = db.transaction(DB_STORE, "readwrite");
|
| 467 |
+
tx.objectStore(DB_STORE).put({ id: item.id, b64: item.b64, prompt: item.prompt, seed: item.seed, width: item.width, height: item.height });
|
| 468 |
+
db.close();
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
async function loadAll() {
|
| 472 |
+
const db = await openDB();
|
| 473 |
+
return new Promise((resolve) => {
|
| 474 |
+
const tx = db.transaction(DB_STORE, "readonly");
|
| 475 |
+
const req = tx.objectStore(DB_STORE).getAll();
|
| 476 |
+
req.onsuccess = () => { db.close(); resolve(req.result); };
|
| 477 |
+
req.onerror = () => { db.close(); resolve([]); };
|
| 478 |
+
});
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
async function clearDB() {
|
| 482 |
+
const db = await openDB();
|
| 483 |
+
const tx = db.transaction(DB_STORE, "readwrite");
|
| 484 |
+
tx.objectStore(DB_STORE).clear();
|
| 485 |
+
db.close();
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
async function deleteItem(id) {
|
| 489 |
+
const db = await openDB();
|
| 490 |
+
const tx = db.transaction(DB_STORE, "readwrite");
|
| 491 |
+
tx.objectStore(DB_STORE).delete(id);
|
| 492 |
+
db.close();
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
// State
|
| 496 |
const gallery = [];
|
| 497 |
let client = null;
|
|
|
|
| 519 |
|
| 520 |
// ---- Init ----
|
| 521 |
async function init() {
|
| 522 |
+
// Restore persisted images
|
| 523 |
+
try {
|
| 524 |
+
const saved = await loadAll();
|
| 525 |
+
saved.sort((a, b) => b.id - a.id); // newest first
|
| 526 |
+
for (const item of saved) {
|
| 527 |
+
gallery.push(item);
|
| 528 |
+
renderGalleryItem(item);
|
| 529 |
+
}
|
| 530 |
+
updateGalleryHeader();
|
| 531 |
+
} catch (_) {}
|
| 532 |
+
|
| 533 |
+
// Connect to backend
|
| 534 |
try {
|
| 535 |
client = await Client.connect(window.location.origin);
|
| 536 |
generateBtn.disabled = false;
|
|
|
|
| 571 |
placeholderItem.height = data.height;
|
| 572 |
placeholderItem.pending = false;
|
| 573 |
replacePlaceholder(placeholderItem);
|
| 574 |
+
saveItem(placeholderItem);
|
| 575 |
|
| 576 |
if (randomSeedEl.checked) {
|
| 577 |
seedInputEl.value = data.seed;
|
|
|
|
| 667 |
gallery.length = 0;
|
| 668 |
galleryEl.innerHTML = "";
|
| 669 |
updateGalleryHeader();
|
| 670 |
+
clearDB();
|
| 671 |
}
|
| 672 |
|
| 673 |
// ---- Lightbox ----
|