From 4750c9afe93d89d3a78d49931ab0b3fec7800dcf Mon Sep 17 00:00:00 2001 From: Simon Cordt Date: Wed, 24 Sep 2025 01:45:41 +0200 Subject: [PATCH] Feat: Display thumbnails of outputs in history --- web/pqueue.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/web/pqueue.js b/web/pqueue.js index ecf55d7..22dc382 100644 --- a/web/pqueue.js +++ b/web/pqueue.js @@ -119,6 +119,7 @@ if (!state.history.length) historyList.appendChild(el('li', { class: 'pqueue-empty', text: 'No history' })); state.history.forEach(row => { const ok = (row.status||'success') === 'success'; + const thumbs = buildResultThumbs(row); const li = el('li', { class: 'pqueue-item' }, [ el('div', { class: 'pqueue-meta' }, [ el('i', { class: `pi ${ok ? 'pi-check-circle pqueue-status-success' : 'pi-times-circle pqueue-status-error'}` }), @@ -126,7 +127,8 @@ ]), el('div', { class: 'pqueue-actions' }, [ el('span', { class: 'p-tag', text: ok ? 'success' : 'error' }) - ]) + ]), + thumbs ]); historyList.appendChild(li); }); @@ -209,6 +211,34 @@ }); } + function buildResultThumbs(row) { + try { + const wrap = el('div', { class: 'flex gap-1 flex-wrap' }); + let outputs = row.outputs || {}; + if (typeof outputs === 'string') { + try { outputs = JSON.parse(outputs); } catch(e) { outputs = {}; } + } + const images = []; + Object.values(outputs).forEach(v => { + if (v && typeof v === 'object') { + const imgs = (v.images) || (v.ui && v.ui.images) || []; + if (Array.isArray(imgs)) imgs.forEach(i => images.push(i)); + } else if (Array.isArray(v)) { + v.forEach(i => { if (i && (i.filename || i.name)) images.push(i); }); + } + }); + images.slice(0, 4).forEach(i => { + const filename = i.filename || i.name || ''; + const type = i.type || 'output'; + const subfolder = i.subfolder || ''; + const url = `/view?filename=${encodeURIComponent(filename)}&type=${encodeURIComponent(type)}${subfolder?`&subfolder=${encodeURIComponent(subfolder)}`:''}&preview=webp;50`; + const img = el('img', { src: url, style: 'width:48px;height:48px;object-fit:cover;border-radius:4px;border:1px solid var(--border-color)' }); + wrap.appendChild(img); + }); + return wrap; + } catch(e) { return el('span', {}); } + } + async function refresh() { const q = await API.getQueue(); state.paused = !!q.paused;