From 43f134d9f9f48db33c140fe9f06461381ccce456 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:38:04 -0800 Subject: [PATCH 1/4] Keep error handling within GalleryFile --- javascript/gallery.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/javascript/gallery.js b/javascript/gallery.js index efa7aa4c3..a818af54f 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -26,6 +26,17 @@ const el = { const SUPPORTED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'tiff', 'jp2', 'jxl', 'gif', 'mp4', 'mkv', 'avi', 'mjpeg', 'mpg', 'avr']; +async function getHash(str) { + let hex = ''; + const strBuf = new TextEncoder().encode(str); + let hashBuf; + if (crypto?.subtle?.digest) hashBuf = await crypto.subtle.digest('SHA-256', strBuf); + else hashBuf = hash(strBuf).buffer; // from sha256.js + const view = new DataView(hashBuf); + for (let i = 0; i < hashBuf.byteLength; i += 4) hex += (`00000000${view.getUint32(i).toString(16)}`).slice(-8); + return hex; +} + function getVisibleGalleryFiles() { if (!el.files) return []; return Array.from(el.files.children).filter((node) => node.name && node.offsetParent); @@ -449,7 +460,12 @@ class GalleryFile extends HTMLElement { } } - this.hash = await getHash(`${this.src}/${this.size}/${this.mtime}`); // eslint-disable-line + this.hash = await getHash(`${this.src}/${this.size}/${this.mtime}`) + .catch((err) => { + error('getHash:', err); + galleryProgressBar.error('File hash error'); + return null; + }); const cachedData = (this.hash && opts.browser_cache) ? await idbGet(this.hash).catch(() => undefined) : undefined; const img = document.createElement('img'); img.className = 'gallery-file'; @@ -659,23 +675,6 @@ async function addSeparators() { const gallerySendImage = (_images) => [currentImage]; // invoked by gradio button -async function getHash(str) { - try { - let hex = ''; - const strBuf = new TextEncoder().encode(str); - let hashBuf; - if (crypto?.subtle?.digest) hashBuf = await crypto.subtle.digest('SHA-256', strBuf); - else hashBuf = await hash(strBuf).buffer; // from sha256.js - const view = new DataView(hashBuf); - for (let i = 0; i < hashBuf.byteLength; i += 4) hex += (`00000000${view.getUint32(i).toString(16)}`).slice(-8); - return hex; - } catch (err) { - error('getHash:', err); - galleryProgressBar.error('File hash error'); - return undefined; - } -} - /** * Helper function to update status with sort mode * @param {...string|[string, string]} messages - Each can be either a string to use as-is, or an array of a string label and value From 792d2a4d99ed2f34370b673b5d0d23cbc620ec1b Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:24:17 -0800 Subject: [PATCH 2/4] Add fallback counter --- javascript/gallery.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/javascript/gallery.js b/javascript/gallery.js index a818af54f..70969e0f7 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -8,7 +8,6 @@ let outstanding = 0; let lastSort = 0; let lastSortName = 'None'; let gallerySelection = { files: [], index: -1 }; -const galleryHashes = new Set(); let maintenanceController = new AbortController(); const folderStylesheet = new CSSStyleSheet(); const fileStylesheet = new CSSStyleSheet(); @@ -111,7 +110,8 @@ async function awaitForOutstanding(num, signal) { * @param {AbortSignal} signal - AbortController signal */ async function awaitForGallery(expectedSize, signal) { - while (galleryHashes.size < expectedSize && !signal.aborted) await new Promise((resolve) => { setTimeout(resolve, 500); }); // longer interval because it's a low priority check + // eslint-disable-next-line no-use-before-define + while (Math.max(galleryHashes.size, galleryHashes.fallback) < expectedSize && !signal.aborted) await new Promise((resolve) => { setTimeout(resolve, 500); }); // longer interval because it's a low priority check signal.throwIfAborted(); } @@ -185,6 +185,26 @@ function updateGalleryStyles() { // Classes +class HashSet extends Set { + constructor(val) { + super(val); + // Using a variable to store a counter has sometimes been unreliable in the past + this.fallback = 0; + } + + add(value) { + ++this.fallback; + super.add(value); + } + + clear() { + this.fallback = 0; + super.clear(); + } +} + +const galleryHashes = new HashSet(); + class SimpleProgressBar { #container = document.createElement('div'); #progress = document.createElement('div'); From 254198360f2228209cb10d8ef2574e695bcca574 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:26:08 -0800 Subject: [PATCH 3/4] Only add to cache if hash is available --- javascript/gallery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/gallery.js b/javascript/gallery.js index 70969e0f7..722a2909b 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -520,7 +520,7 @@ class GalleryFile extends HTMLElement { this.height = json.height; this.size = json.size; this.mtime = new Date(json.mtime); - if (opts.browser_cache) { + if (opts.browser_cache && this.hash) { await idbAdd({ hash: this.hash, folder: this.fullFolder, From dd776936d655be77f5d091dcadafe2b23ed93a52 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:53:53 -0800 Subject: [PATCH 4/4] Remove previous error handler - New fallback seems to be more stable than previous tries. --- javascript/gallery.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/javascript/gallery.js b/javascript/gallery.js index 722a2909b..bfa42c357 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -188,7 +188,6 @@ function updateGalleryStyles() { class HashSet extends Set { constructor(val) { super(val); - // Using a variable to store a counter has sometimes been unreliable in the past this.fallback = 0; } @@ -214,7 +213,6 @@ class SimpleProgressBar { #hideTimeout = null; #interval = null; #max = 0; - #errorState = false; /** @type {Set} */ #monitoredSet; @@ -231,7 +229,6 @@ class SimpleProgressBar { } start(total) { - if (this.#errorState) return; this.clear(); this.#max = total; this.#interval = setInterval(() => { @@ -248,7 +245,6 @@ class SimpleProgressBar { clear() { this.#stop(); - this.#errorState = false; clearTimeout(this.#hideTimeout); this.#hideTimeout = null; this.#container.style.display = 'none'; @@ -257,20 +253,6 @@ class SimpleProgressBar { this.#text.textContent = ''; } - error(message) { - if (!this.#errorState) { - this.#errorState = true; - this.#stop(); - this.#container.style.display = 'block'; - this.#visible = true; - clearTimeout(this.#hideTimeout); - this.#text.textContent = message; - this.#hideTimeout = setTimeout(() => { - this.clear(); - }, 2000); - } - } - #update(loaded, max) { if (this.#hideTimeout) { this.#hideTimeout = null; @@ -483,7 +465,6 @@ class GalleryFile extends HTMLElement { this.hash = await getHash(`${this.src}/${this.size}/${this.mtime}`) .catch((err) => { error('getHash:', err); - galleryProgressBar.error('File hash error'); return null; }); const cachedData = (this.hash && opts.browser_cache) ? await idbGet(this.hash).catch(() => undefined) : undefined;