Skip to content

Commit 2d9c327

Browse files
committed
improve ui connection monitor
Signed-off-by: Vladimir Mandic <mandic00@live.com>
1 parent 8ea9d42 commit 2d9c327

5 files changed

Lines changed: 74 additions & 54 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Change Log for SD.Next
22

3-
## Update for 2026-02-21
3+
## Update for 2026-02-22
44

5-
### Highlights for 2026-02-21
5+
### Highlights for 2026-02-22
66

77
TBD
88

9-
### Details for 2026-02-21
9+
### Details for 2026-02-22
1010

1111
- **Models**
1212
- [FireRed Image Edit](https://huggingface.co/FireRedTeam/FireRed-Image-Edit-1.0)
@@ -88,6 +88,7 @@ TBD
8888
- gallery over remote/unsecure connections
8989
- ltx2-i2v
9090
- handle missing preview image
91+
- ui connection monitor
9192

9293
## Update for 2026-02-04
9394

javascript/logMonitor.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ async function logMonitor() {
8282
for (const line of lines) addLogLine(line);
8383
if (!logConnected) {
8484
logConnected = true;
85-
monitorConnection();
8685
xhrPost(`${window.api}/log`, { debug: 'connected' });
8786
}
8887
} else {

javascript/monitor.js

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ class ConnectionMonitorState {
33
static version = '';
44
static commit = '';
55
static branch = '';
6+
static model = '';
7+
static startup = '';
68
static online = false;
79

810
static getModel() {
@@ -11,66 +13,85 @@ class ConnectionMonitorState {
1113
}
1214

1315
static trimModelName(name) {
14-
// remove trailing [hash], split on / or \, return last segment, trim
1516
return name.replace(/\s*\[.*\]\s*$/, '').split(/[\\/]/).pop().trim() || 'unknown model';
1617
}
1718

18-
static setData({ online, updated, commit, branch }) {
19+
static setData({ online, data }) {
1920
this.online = online;
20-
this.version = updated;
21-
this.commit = commit;
22-
this.branch = branch;
21+
if (data?.version) this.version = data.version;
22+
if (data?.commit) this.commit = data.commit;
23+
if (data?.branch) this.branch = data.branch;
24+
if (data?.model) this.model = this.trimModelName(data.model);
2325
}
2426

25-
static setElement(el) {
26-
this.element = el;
27-
}
28-
29-
static toHTML(modelOverride) {
27+
static toHTML() {
28+
if (!this.model) this.model = this.getModel();
3029
return `
3130
Version: <b>${this.version}</b><br>
3231
Commit: <b>${this.commit}</b><br>
3332
Branch: <b>${this.branch}</b><br>
3433
Status: ${this.online ? '<b style="color:lime">online</b>' : '<b style="color:darkred">offline</b>'}<br>
35-
Model: <b>${modelOverride ? this.trimModelName(modelOverride) : this.getModel()}</b><br>
36-
Since: ${new Date().toLocaleString()}<br>
34+
Model: <b>${this.model}</b><br>
35+
Since: ${this.startup.toLocaleString()}<br>
3736
`;
3837
}
3938

40-
static updateState(incomingModel) {
41-
this.element.dataset.hint = this.toHTML(incomingModel);
39+
static updateState() {
40+
if (!this.element) {
41+
const el = document.getElementById('logo_nav');
42+
if (el) this.element = el;
43+
else return;
44+
}
45+
this.element.dataset.hint = this.toHTML();
4246
this.element.style.backgroundColor = this.online ? 'var(--sd-main-accent-color)' : 'var(--color-error)';
4347
}
4448
}
4549

46-
let monitorAutoUpdating = false;
47-
48-
async function updateIndicator(online, data, msg) {
49-
const el = document.getElementById('logo_nav');
50-
if (!el || !data) return;
51-
ConnectionMonitorState.setElement(el);
52-
if (!monitorAutoUpdating) {
53-
monitorOption('sd_model_checkpoint', (newVal) => { ConnectionMonitorState.updateState(newVal); }); // Runs before opt actually changes
54-
monitorAutoUpdating = true;
55-
}
56-
ConnectionMonitorState.setData({ online, ...data });
50+
async function updateIndicator(online, data = {}, msg = undefined) {
51+
ConnectionMonitorState.setData({ online, data });
5752
ConnectionMonitorState.updateState();
58-
if (online) {
59-
log('monitorConnection: online', data);
60-
} else {
61-
log('monitorConnection: offline', msg);
53+
if (msg) log('monitorConnection:', { online, data, msg });
54+
}
55+
56+
async function wsMonitorLoop(url) {
57+
try {
58+
const ws = new WebSocket(`${url}/queue/join`);
59+
ws.onopen = () => {};
60+
ws.onmessage = (evt) => updateIndicator(true);
61+
ws.onclose = () => setTimeout(() => wsMonitorLoop(url), 10000);
62+
ws.onerror = (e) => {
63+
updateIndicator(false, {}, e.message);
64+
setTimeout(() => monitorConnection(url), 10000); // eslint-disable-line no-use-before-define
65+
};
66+
} catch (e) {
67+
updateIndicator(false, {}, e.message);
68+
setTimeout(() => monitorConnection(url), 10000); // eslint-disable-line no-use-before-define
6269
}
6370
}
6471

72+
let monitorActive = false;
73+
6574
async function monitorConnection() {
75+
if (!monitorActive) { // start monitor loop only once on startup
76+
monitorActive = true;
77+
monitorOption('sd_model_checkpoint', (newVal) => { // runs before opt actually changes
78+
ConnectionMonitorState.model = newVal;
79+
ConnectionMonitorState.updateState();
80+
});
81+
}
82+
ConnectionMonitorState.startup = new Date();
83+
84+
let data = {};
6685
try {
6786
const res = await authFetch(`${window.api}/version`);
68-
const data = await res.json();
69-
const url = res.url.split('/sdapi')[0].replace('http', 'ws'); // update global url as ws need fqdn
70-
const ws = new WebSocket(`${url}/queue/join`);
71-
ws.onopen = () => updateIndicator(true, data, '');
72-
ws.onclose = () => updateIndicator(false, data, '');
73-
ws.onerror = (e) => updateIndicator(false, data, e.message);
74-
ws.onmessage = (evt) => log('monitorConnection: message', evt.data);
75-
} catch { /**/ }
87+
data = await res.json();
88+
log('monitorConnection:', { data });
89+
ConnectionMonitorState.startup = new Date();
90+
updateIndicator(true, data);
91+
const url = res.url.split('/sdapi')[0].replace('https:', 'wss:').replace('http:', 'ws:'); // update global url as ws need fqdn
92+
wsMonitorLoop(url);
93+
} catch {
94+
monitorConnection(false, data);
95+
setTimeout(monitorConnection, 10000);
96+
}
7697
}

javascript/startup.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,21 @@ async function initStartup() {
3030
if (window.setupLogger) await setupLogger();
3131

3232
// all items here are non-blocking async calls
33-
await initModels();
34-
await getUIDefaults();
35-
await initPromptChecker();
36-
await initContextMenu();
37-
await initDragDrop();
38-
await initAccordions();
39-
await initSettings();
40-
await initImageViewer();
41-
await initiGenerationParams();
42-
await initChangelog();
43-
await setupControlUI();
33+
initModels();
34+
getUIDefaults();
35+
initPromptChecker();
36+
initContextMenu();
37+
initDragDrop();
38+
initAccordions();
39+
initSettings();
40+
initImageViewer();
41+
initiGenerationParams();
42+
initChangelog();
43+
setupControlUI();
4444

4545
// reconnect server session
4646
await reconnectUI();
4747
await waitForOpts();
48-
4948
await initGallery();
5049

5150
log('mountURL', window.opts.subpath);
@@ -60,6 +59,7 @@ async function initStartup() {
6059

6160
// optinally wait for modern ui
6261
if (window.waitForUiReady) await waitForUiReady();
62+
monitorConnection();
6363
removeSplash();
6464

6565
// post startup tasks that may take longer but are not critical

javascript/ui.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,5 +630,4 @@ async function reconnectUI() {
630630
const sd_model_observer = new MutationObserver(sd_model_callback);
631631
sd_model_observer.observe(sd_model, { attributes: true, childList: true, subtree: true });
632632
log('reconnectUI');
633-
monitorConnection();
634633
}

0 commit comments

Comments
 (0)