From 0c0911eddcde66ae296e54d42f1e67fcca8f2a43 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Fri, 6 Feb 2026 00:43:03 -0800 Subject: [PATCH 1/4] Adjust click handlers for `GalleryFolder` --- javascript/gallery.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/gallery.js b/javascript/gallery.js index f72ddc29f..f5ce1c51c 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -339,8 +339,8 @@ class GalleryFolder extends HTMLElement { this.div.className = 'gallery-folder'; this.div.innerHTML = ` ${this.label}`; this.div.title = this.name; // Show full path on hover - this.div.addEventListener('click', () => { this.updateSelected(); }); // Ensures 'this' isn't the div in the called method - this.div.addEventListener('click', fetchFilesWS); // eslint-disable-line no-use-before-define + this.addEventListener('click', this.updateSelected); + this.addEventListener('click', fetchFilesWS); // eslint-disable-line no-use-before-define this.shadow.appendChild(this.div); GalleryFolder.folders.add(this); } @@ -1150,7 +1150,7 @@ async function fetchFilesWS(evt) { // fetch file-by-file list over websockets let wsConnected = false; try { ws = new WebSocket(`${url}/sdapi/v1/browser/files`); - wsConnected = await wsConnect(ws); // Warning. This changes "evt". + wsConnected = await wsConnect(ws); } catch (err) { log('gallery: ws connect error', err); return; From 171ead0fa26f1b59bbb0fa6849b944c6e51aec28 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Fri, 6 Feb 2026 00:43:58 -0800 Subject: [PATCH 2/4] Auto-select current folder after refresh --- javascript/gallery.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/javascript/gallery.js b/javascript/gallery.js index f5ce1c51c..625224609 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -343,6 +343,9 @@ class GalleryFolder extends HTMLElement { this.addEventListener('click', fetchFilesWS); // eslint-disable-line no-use-before-define this.shadow.appendChild(this.div); GalleryFolder.folders.add(this); + if (this.name === currentGalleryFolder) { + this.updateSelected(); + } } async disconnectedCallback() { From f84cb6ac64aa3dad5f19189b1c189e13730ea4ae Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Fri, 6 Feb 2026 00:44:48 -0800 Subject: [PATCH 3/4] Track active gallery element --- javascript/gallery.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/javascript/gallery.js b/javascript/gallery.js index 625224609..b61663c62 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -315,6 +315,8 @@ class SimpleFunctionQueue { class GalleryFolder extends HTMLElement { static folders = new Set(); + /** @type {GalleryFolder | null} */ + static #active = null; constructor(folder) { super(); @@ -352,10 +354,18 @@ class GalleryFolder extends HTMLElement { await Promise.resolve(); // Wait for other microtasks (such as element moving) if (this.isConnected) return; GalleryFolder.folders.delete(this); + if (GalleryFolder.#active === this) { + GalleryFolder.#active = null; + } + } + + static getActive() { + return GalleryFolder.#active; } updateSelected() { this.div.classList.add('gallery-folder-selected'); + GalleryFolder.#active = this; for (const folder of GalleryFolder.folders) { if (folder !== this) { folder.div.classList.remove('gallery-folder-selected'); From ade7c2e5f9564795e3cc466a3a23d6cee1825ffe Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Fri, 6 Feb 2026 00:50:04 -0800 Subject: [PATCH 4/4] Add auto-update setting and functionality --- javascript/gallery.js | 37 +++++++++++++++++++++++++++++++++++++ modules/shared.py | 1 + 2 files changed, 38 insertions(+) diff --git a/javascript/gallery.js b/javascript/gallery.js index b61663c62..78dda3bf2 100644 --- a/javascript/gallery.js +++ b/javascript/gallery.js @@ -1271,6 +1271,43 @@ async function galleryClearInit() { }, 1000); } +async function initGalleryAutoRefresh() { + const isModern = opts.theme_type?.toLowerCase() === 'modern'; + let galleryTab = isModern ? document.getElementById('gallery_tabitem') : document.getElementById('tab_gallery'); + let timeout = 0; + while (!galleryTab && timeout++ < 60) { + await new Promise((resolve) => { setTimeout(resolve, 1000); }); + galleryTab = isModern ? document.getElementById('gallery_tabitem') : document.getElementById('tab_gallery'); + } + if (!galleryTab) { + throw new Error('Timed out waiting for gallery tab element'); + } + const displayNoneRegEx = /display:\s*none/; + async function galleryAutoRefresh(mutations) { + if (!opts.browser_gallery_autoupdate) return; + for (const mutation of mutations) { + switch (mutation.attributeName) { + case 'class': + if (mutation.oldValue.includes('hidden') && !mutation.target.classList.contains('hidden')) { + await updateFolders(); + GalleryFolder.getActive()?.click(); + } + break; + case 'style': + if (displayNoneRegEx.test(mutation.oldValue) && !displayNoneRegEx.test(mutation.target.style.display)) { + await updateFolders(); + GalleryFolder.getActive()?.click(); + } + break; + default: + break; + } + } + } + const galleryVisObserver = new MutationObserver(galleryAutoRefresh); + galleryVisObserver.observe(galleryTab, { attributeFilter: ['class', 'style'], attributeOldValue: true }); +} + async function blockQueueUntilReady() { // Add block to maintenanceQueue until cache is ready maintenanceQueue.enqueue({ diff --git a/modules/shared.py b/modules/shared.py index b3dec7abf..a29874001 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -535,6 +535,7 @@ options_templates.update(options_section(('saving-images', "Image Options"), { "image_sep_browser": OptionInfo("