mirror of https://github.com/vladmandic/automatic
improve ui connection monitor
Signed-off-by: Vladimir Mandic <mandic00@live.com>pull/4663/head
parent
8ea9d428d5
commit
2d9c3275f1
|
|
@ -1,12 +1,12 @@
|
|||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2026-02-21
|
||||
## Update for 2026-02-22
|
||||
|
||||
### Highlights for 2026-02-21
|
||||
### Highlights for 2026-02-22
|
||||
|
||||
TBD
|
||||
|
||||
### Details for 2026-02-21
|
||||
### Details for 2026-02-22
|
||||
|
||||
- **Models**
|
||||
- [FireRed Image Edit](https://huggingface.co/FireRedTeam/FireRed-Image-Edit-1.0)
|
||||
|
|
@ -88,6 +88,7 @@ TBD
|
|||
- gallery over remote/unsecure connections
|
||||
- ltx2-i2v
|
||||
- handle missing preview image
|
||||
- ui connection monitor
|
||||
|
||||
## Update for 2026-02-04
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ async function logMonitor() {
|
|||
for (const line of lines) addLogLine(line);
|
||||
if (!logConnected) {
|
||||
logConnected = true;
|
||||
monitorConnection();
|
||||
xhrPost(`${window.api}/log`, { debug: 'connected' });
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ class ConnectionMonitorState {
|
|||
static version = '';
|
||||
static commit = '';
|
||||
static branch = '';
|
||||
static model = '';
|
||||
static startup = '';
|
||||
static online = false;
|
||||
|
||||
static getModel() {
|
||||
|
|
@ -11,66 +13,85 @@ class ConnectionMonitorState {
|
|||
}
|
||||
|
||||
static trimModelName(name) {
|
||||
// remove trailing [hash], split on / or \, return last segment, trim
|
||||
return name.replace(/\s*\[.*\]\s*$/, '').split(/[\\/]/).pop().trim() || 'unknown model';
|
||||
}
|
||||
|
||||
static setData({ online, updated, commit, branch }) {
|
||||
static setData({ online, data }) {
|
||||
this.online = online;
|
||||
this.version = updated;
|
||||
this.commit = commit;
|
||||
this.branch = branch;
|
||||
if (data?.version) this.version = data.version;
|
||||
if (data?.commit) this.commit = data.commit;
|
||||
if (data?.branch) this.branch = data.branch;
|
||||
if (data?.model) this.model = this.trimModelName(data.model);
|
||||
}
|
||||
|
||||
static setElement(el) {
|
||||
this.element = el;
|
||||
}
|
||||
|
||||
static toHTML(modelOverride) {
|
||||
static toHTML() {
|
||||
if (!this.model) this.model = this.getModel();
|
||||
return `
|
||||
Version: <b>${this.version}</b><br>
|
||||
Commit: <b>${this.commit}</b><br>
|
||||
Branch: <b>${this.branch}</b><br>
|
||||
Status: ${this.online ? '<b style="color:lime">online</b>' : '<b style="color:darkred">offline</b>'}<br>
|
||||
Model: <b>${modelOverride ? this.trimModelName(modelOverride) : this.getModel()}</b><br>
|
||||
Since: ${new Date().toLocaleString()}<br>
|
||||
Model: <b>${this.model}</b><br>
|
||||
Since: ${this.startup.toLocaleString()}<br>
|
||||
`;
|
||||
}
|
||||
|
||||
static updateState(incomingModel) {
|
||||
this.element.dataset.hint = this.toHTML(incomingModel);
|
||||
static updateState() {
|
||||
if (!this.element) {
|
||||
const el = document.getElementById('logo_nav');
|
||||
if (el) this.element = el;
|
||||
else return;
|
||||
}
|
||||
this.element.dataset.hint = this.toHTML();
|
||||
this.element.style.backgroundColor = this.online ? 'var(--sd-main-accent-color)' : 'var(--color-error)';
|
||||
}
|
||||
}
|
||||
|
||||
let monitorAutoUpdating = false;
|
||||
|
||||
async function updateIndicator(online, data, msg) {
|
||||
const el = document.getElementById('logo_nav');
|
||||
if (!el || !data) return;
|
||||
ConnectionMonitorState.setElement(el);
|
||||
if (!monitorAutoUpdating) {
|
||||
monitorOption('sd_model_checkpoint', (newVal) => { ConnectionMonitorState.updateState(newVal); }); // Runs before opt actually changes
|
||||
monitorAutoUpdating = true;
|
||||
}
|
||||
ConnectionMonitorState.setData({ online, ...data });
|
||||
async function updateIndicator(online, data = {}, msg = undefined) {
|
||||
ConnectionMonitorState.setData({ online, data });
|
||||
ConnectionMonitorState.updateState();
|
||||
if (online) {
|
||||
log('monitorConnection: online', data);
|
||||
} else {
|
||||
log('monitorConnection: offline', msg);
|
||||
if (msg) log('monitorConnection:', { online, data, msg });
|
||||
}
|
||||
|
||||
async function wsMonitorLoop(url) {
|
||||
try {
|
||||
const ws = new WebSocket(`${url}/queue/join`);
|
||||
ws.onopen = () => {};
|
||||
ws.onmessage = (evt) => updateIndicator(true);
|
||||
ws.onclose = () => setTimeout(() => wsMonitorLoop(url), 10000);
|
||||
ws.onerror = (e) => {
|
||||
updateIndicator(false, {}, e.message);
|
||||
setTimeout(() => monitorConnection(url), 10000); // eslint-disable-line no-use-before-define
|
||||
};
|
||||
} catch (e) {
|
||||
updateIndicator(false, {}, e.message);
|
||||
setTimeout(() => monitorConnection(url), 10000); // eslint-disable-line no-use-before-define
|
||||
}
|
||||
}
|
||||
|
||||
let monitorActive = false;
|
||||
|
||||
async function monitorConnection() {
|
||||
if (!monitorActive) { // start monitor loop only once on startup
|
||||
monitorActive = true;
|
||||
monitorOption('sd_model_checkpoint', (newVal) => { // runs before opt actually changes
|
||||
ConnectionMonitorState.model = newVal;
|
||||
ConnectionMonitorState.updateState();
|
||||
});
|
||||
}
|
||||
ConnectionMonitorState.startup = new Date();
|
||||
|
||||
let data = {};
|
||||
try {
|
||||
const res = await authFetch(`${window.api}/version`);
|
||||
const data = await res.json();
|
||||
const url = res.url.split('/sdapi')[0].replace('http', 'ws'); // update global url as ws need fqdn
|
||||
const ws = new WebSocket(`${url}/queue/join`);
|
||||
ws.onopen = () => updateIndicator(true, data, '');
|
||||
ws.onclose = () => updateIndicator(false, data, '');
|
||||
ws.onerror = (e) => updateIndicator(false, data, e.message);
|
||||
ws.onmessage = (evt) => log('monitorConnection: message', evt.data);
|
||||
} catch { /**/ }
|
||||
data = await res.json();
|
||||
log('monitorConnection:', { data });
|
||||
ConnectionMonitorState.startup = new Date();
|
||||
updateIndicator(true, data);
|
||||
const url = res.url.split('/sdapi')[0].replace('https:', 'wss:').replace('http:', 'ws:'); // update global url as ws need fqdn
|
||||
wsMonitorLoop(url);
|
||||
} catch {
|
||||
monitorConnection(false, data);
|
||||
setTimeout(monitorConnection, 10000);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,22 +30,21 @@ async function initStartup() {
|
|||
if (window.setupLogger) await setupLogger();
|
||||
|
||||
// all items here are non-blocking async calls
|
||||
await initModels();
|
||||
await getUIDefaults();
|
||||
await initPromptChecker();
|
||||
await initContextMenu();
|
||||
await initDragDrop();
|
||||
await initAccordions();
|
||||
await initSettings();
|
||||
await initImageViewer();
|
||||
await initiGenerationParams();
|
||||
await initChangelog();
|
||||
await setupControlUI();
|
||||
initModels();
|
||||
getUIDefaults();
|
||||
initPromptChecker();
|
||||
initContextMenu();
|
||||
initDragDrop();
|
||||
initAccordions();
|
||||
initSettings();
|
||||
initImageViewer();
|
||||
initiGenerationParams();
|
||||
initChangelog();
|
||||
setupControlUI();
|
||||
|
||||
// reconnect server session
|
||||
await reconnectUI();
|
||||
await waitForOpts();
|
||||
|
||||
await initGallery();
|
||||
|
||||
log('mountURL', window.opts.subpath);
|
||||
|
|
@ -60,6 +59,7 @@ async function initStartup() {
|
|||
|
||||
// optinally wait for modern ui
|
||||
if (window.waitForUiReady) await waitForUiReady();
|
||||
monitorConnection();
|
||||
removeSplash();
|
||||
|
||||
// post startup tasks that may take longer but are not critical
|
||||
|
|
|
|||
|
|
@ -630,5 +630,4 @@ async function reconnectUI() {
|
|||
const sd_model_observer = new MutationObserver(sd_model_callback);
|
||||
sd_model_observer.observe(sd_model, { attributes: true, childList: true, subtree: true });
|
||||
log('reconnectUI');
|
||||
monitorConnection();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue