Stable Diffusion: clickable pod-status dot in the chat bar (copy of the settings indicator; click toggles warmup/shutdown)

738ff23c09bfe7e2cb9c40337737de38d1c2cf96

permissionBRICK <40219477+permissionBRICK@users.noreply.github.com>

2 files changed, +45 -2Ignore whitespace
public/scripts/extensions/stable-diffusion/index.js+35 -2
@@ -1461,6 +1461,7 @@ const RUNPOD_PING_MS = 60000;
14611461
1462let runpodStatusTimer = null;1462let runpodStatusTimer = null;
1463let runpodPingTimer = null;1463let runpodPingTimer = null;
1464let runpodLastPhase = 'red';
14641465
1465function getRunpodLazyUrl() {1466function getRunpodLazyUrl() {
1466 return String(extension_settings.sd.runpod_lazy_url ?? '').trim().replace(/\/$/, '');1467 return String(extension_settings.sd.runpod_lazy_url ?? '').trim().replace(/\/$/, '');
@@ -1477,8 +1478,12 @@ function renderRunpodStatus(status) {
1477 return;1478 return;
1478 }1479 }
1479 const phase = status?.state ?? 'red';1480 const phase = status?.state ?? 'red';
1480 dot.classList.remove('sd_runpod_red', 'sd_runpod_orange', 'sd_runpod_green');1481 runpodLastPhase = phase;
1481 dot.classList.add(`sd_runpod_${['red', 'orange', 'green'].includes(phase) ? phase : 'red'}`);1482 const phaseClass = `sd_runpod_${['red', 'orange', 'green'].includes(phase) ? phase : 'red'}`;
1483 for (const el of [dot, document.getElementById('sd_runpod_bar_dot')].filter(Boolean)) {
1484 el.classList.remove('sd_runpod_red', 'sd_runpod_orange', 'sd_runpod_green');
1485 el.classList.add(phaseClass);
1486 }
1482 const openLink = document.getElementById('sd_runpod_open');1487 const openLink = document.getElementById('sd_runpod_open');
1483 if (openLink) {1488 if (openLink) {
1484 const showLink = phase === 'green' && status?.url;1489 const showLink = phase === 'green' && status?.url;
@@ -1497,9 +1502,32 @@ function renderRunpodStatus(status) {
1497 } else {1502 } else {
1498 text.textContent = 'off';1503 text.textContent = 'off';
1499 }1504 }
1505 const barDot = document.getElementById('sd_runpod_bar_dot');
1506 if (barDot) {
1507 barDot.title = `RunPod pod: ${text.textContent} — click to ${phase === 'red' ? 'warm up' : 'shut down'}`;
1508 }
1500 return phase;1509 return phase;
1501}1510}
15021511
1512/** Adds the clickable pod-status dot to the chat bar (next to other extension icons). */
1513function ensureRunpodBarDot() {
1514 if (document.getElementById('sd_runpod_bar_dot')) {
1515 return;
1516 }
1517 const anchor = document.getElementById('leftSendForm');
1518 if (!anchor) {
1519 return;
1520 }
1521 const dot = document.createElement('div');
1522 dot.id = 'sd_runpod_bar_dot';
1523 dot.classList.add('sd_runpod_bar_dot', 'sd_runpod_red', 'interactable');
1524 dot.title = 'RunPod pod';
1525 dot.tabIndex = 0;
1526 dot.addEventListener('click', () => runpodControl(runpodLastPhase === 'red' ? 'warmup' : 'shutdown'));
1527 anchor.appendChild(dot);
1528 dot.style.display = getRunpodLazyUrl() ? '' : 'none';
1529}
1530
1503async function pollRunpodStatus() {1531async function pollRunpodStatus() {
1504 const url = getRunpodLazyUrl();1532 const url = getRunpodLazyUrl();
1505 if (!url) {1533 if (!url) {
@@ -1547,6 +1575,11 @@ function runpodKeepalive() {
1547function setupRunpodLoops() {1575function setupRunpodLoops() {
1548 clearTimeout(runpodStatusTimer);1576 clearTimeout(runpodStatusTimer);
1549 clearInterval(runpodPingTimer);1577 clearInterval(runpodPingTimer);
1578 ensureRunpodBarDot();
1579 const barDot = document.getElementById('sd_runpod_bar_dot');
1580 if (barDot) {
1581 barDot.style.display = getRunpodLazyUrl() ? '' : 'none';
1582 }
1550 if (!getRunpodLazyUrl()) {1583 if (!getRunpodLazyUrl()) {
1551 renderRunpodStatus(null);1584 renderRunpodStatus(null);
1552 return;1585 return;
public/scripts/extensions/stable-diffusion/style.css+10 -0
@@ -127,3 +127,13 @@
127.sd_runpod_dot.sd_runpod_red { background: #d9534f; }127.sd_runpod_dot.sd_runpod_red { background: #d9534f; }
128.sd_runpod_dot.sd_runpod_orange { background: #f0ad4e; }128.sd_runpod_dot.sd_runpod_orange { background: #f0ad4e; }
129.sd_runpod_dot.sd_runpod_green { background: #5cb85c; }129.sd_runpod_dot.sd_runpod_green { background: #5cb85c; }
130
131#sd_runpod_bar_dot {
132 width: 14px;
133 height: 14px;
134 border-radius: 50%;
135 align-self: center;
136 cursor: pointer;
137 margin: 0 4px;
138 flex-shrink: 0;
139}