class ConnectionMonitorState {
static element;
static version = '';
static commit = '';
static branch = '';
static model = '';
static startup = '';
static online = false;
static getModel() {
const cp = opts?.sd_model_checkpoint || '';
return cp ? this.trimModelName(cp) : 'unknown model';
}
static trimModelName(name) {
return name.replace(/\s*\[.*\]\s*$/, '').split(/[\\/]/).pop().trim() || 'unknown model';
}
static setData({ online, data }) {
this.online = online;
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 toHTML() {
if (!this.model) this.model = this.getModel();
return `
Version: ${this.version}
Commit: ${this.commit}
Branch: ${this.branch}
Status: ${this.online ? 'online' : 'offline'}
Model: ${this.model}
Since: ${this.startup.toLocaleString()}
`;
}
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)';
}
}
async function updateIndicator(online, data = {}, msg = undefined) {
ConnectionMonitorState.setData({ online, data });
ConnectionMonitorState.updateState();
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`);
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);
}
}