diff --git a/server/queue_manager.py b/server/queue_manager.py index 7a11459..b9a3344 100644 --- a/server/queue_manager.py +++ b/server/queue_manager.py @@ -153,11 +153,36 @@ class PersistentQueueManager: async def _api_get_pqueue(self, request: web.Request) -> web.Response: from server import PromptServer running, queued = PromptServer.instance.prompt_queue.get_current_queue_volatile() + # Compute per-prompt progress (0..1) using global progress registry when available + progress_map = {} + try: + from comfy_execution.progress import get_progress_state + reg = get_progress_state() + if reg is not None and getattr(reg, 'nodes', None) and reg.prompt_id: + total_max = 0.0 + total_val = 0.0 + for st in reg.nodes.values(): + try: + mv = float(st.get('max', 1.0) or 1.0) + vv = float(st.get('value', 0.0) or 0.0) + except Exception: + mv = 1.0 + vv = 0.0 + if mv <= 0: + mv = 1.0 + total_max += mv + total_val += max(0.0, min(vv, mv)) + frac = (total_val / total_max) if total_max > 0 else 0.0 + progress_map[reg.prompt_id] = max(0.0, min(1.0, frac)) + except Exception: + pass + return web.json_response({ "paused": self.paused, "db_pending": self.db.get_pending_jobs(), "queue_running": running, "queue_pending": queued, + "running_progress": progress_map, }) async def _api_get_history(self, request: web.Request) -> web.Response: diff --git a/web/css/queue_style.css b/web/css/queue_style.css index 406cb0f..77a5d06 100644 --- a/web/css/queue_style.css +++ b/web/css/queue_style.css @@ -6,6 +6,7 @@ .pqueue-card>.p-card-body{padding:.25rem .5rem} .pqueue-list{list-style:none;margin:0;padding:0} .pqueue-item{display:flex;align-items:center;justify-content:space-between;border-bottom:1px dashed var(--border-color);padding:.35rem .25rem;border-radius:4px} +.pqueue-left{display:flex;flex-direction:column;gap:.25rem;flex:1} .pqueue-item:hover{background:rgba(0,0,0,0.04)} .dark-theme .pqueue-item:hover{background:rgba(255,255,255,0.06)} .pqueue-item:last-child{border-bottom:none} @@ -15,4 +16,6 @@ .pqueue-status-error{color:var(--red-500)} .pqueue-empty{opacity:.7;font-size:.9rem;padding:.25rem 0} .pqueue-thumbs-grid{display:grid;grid-template-columns:repeat(2, 96px);gap:6px} -.pqueue-thumb{width:96px;height:96px;object-fit:cover;border-radius:4px;cursor:pointer} \ No newline at end of file +.pqueue-thumb{width:96px;height:96px;object-fit:cover;border-radius:4px;cursor:pointer} +.pqueue-progress-wrap{width:100%;height:8px;background:#1f2a1f;border-radius:4px;overflow:hidden;margin-top:6px} +.pqueue-progress-bar{height:100%;width:0;background:#22c55e;transition:width .3s ease} \ No newline at end of file diff --git a/web/pqueue.js b/web/pqueue.js index e42cda4..048aa46 100644 --- a/web/pqueue.js +++ b/web/pqueue.js @@ -18,6 +18,7 @@ queue_pending: [], db_pending: [], history: [], + running_progress: {}, container: null, listPending: null, selectedPending: new Set(), @@ -70,11 +71,23 @@ const runningList = el('ul', { class: 'pqueue-list' }); if (!state.queue_running.length) runningList.appendChild(el('li', { class: 'pqueue-empty', text: 'No running job' })); state.queue_running.forEach(item => { - const li = el('li', { class: 'pqueue-item' }, [ + const pid = item[1]; + const leftCol = el('div', { class: 'pqueue-left' }, [ el('div', { class: 'pqueue-meta' }, [ el('i', { class: 'pi pi-spin pi-spinner' }), - el('span', { text: item[1] }) + el('span', { text: pid }) ]), + (() => { + const wrap = el('div', { class: 'pqueue-progress-wrap' }); + const bar = el('div', { class: 'pqueue-progress-bar' }); + const frac = Math.max(0, Math.min(1, Number(state.running_progress && state.running_progress[pid]) || 0)); + bar.style.width = `${(frac * 100).toFixed(2)}%`; + wrap.appendChild(bar); + return wrap; + })() + ]); + const li = el('li', { class: 'pqueue-item' }, [ + leftCol, el('div', { class: 'pqueue-actions' }, []) ]); runningList.appendChild(li); @@ -268,6 +281,7 @@ state.queue_running = q.queue_running || []; state.queue_pending = q.queue_pending || []; state.db_pending = q.db_pending || []; + state.running_progress = q.running_progress || {}; const h = await API.getHistory(50); state.history = h.history || []; render();