From 48cfffbd44d71a615b332409dbd65a68f766d442 Mon Sep 17 00:00:00 2001 From: Crystian Date: Sun, 22 Sep 2024 00:52:35 +0200 Subject: [PATCH] starting with horizontal... finally2 --- web/monitor.d.ts | 1 + web/monitor.js | 446 +++++++++++++++++++++++++- web/monitor.ts | 727 +++++++++++++++++++++++-------------------- web/monitorUI.d.ts | 20 ++ web/monitorUI.js | 242 +++++++++++++- web/monitorUI.ts | 426 ++++++++++++------------- web/progressBar.js | 3 - web/progressBar.ts | 4 +- web/progressBarUI.js | 2 - web/progressBarUI.ts | 3 - web/types.d.ts | 7 +- 11 files changed, 1311 insertions(+), 570 deletions(-) diff --git a/web/monitor.d.ts b/web/monitor.d.ts index e69de29..cb0ff5c 100644 --- a/web/monitor.d.ts +++ b/web/monitor.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/web/monitor.js b/web/monitor.js index 3918c74..c27a23b 100644 --- a/web/monitor.js +++ b/web/monitor.js @@ -1 +1,445 @@ -"use strict"; +import { app, api } from './comfy/index.js'; +import { commonPrefix } from './common.js'; +import { MonitorUI } from './monitorUI.js'; +import { Colors } from './styles.js'; +import { convertNumberToPascalCase } from './utils.js'; +class CrystoolsMonitor { + constructor() { + Object.defineProperty(this, "idExtensionName", { + enumerable: true, + configurable: true, + writable: true, + value: 'Crystools.monitor' + }); + Object.defineProperty(this, "menuPrefix", { + enumerable: true, + configurable: true, + writable: true, + value: commonPrefix + }); + Object.defineProperty(this, "monitorUI", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "settingsRate", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "monitorCPUElement", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "monitorRAMElement", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "monitorHDDElement", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "settingsHDD", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "monitorGPUSettings", { + enumerable: true, + configurable: true, + writable: true, + value: [] + }); + Object.defineProperty(this, "monitorVRAMSettings", { + enumerable: true, + configurable: true, + writable: true, + value: [] + }); + Object.defineProperty(this, "monitorTemperatureSettings", { + enumerable: true, + configurable: true, + writable: true, + value: [] + }); + Object.defineProperty(this, "createSettingsRate", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + this.settingsRate = { + id: 'Crystools.RefreshRate', + name: 'Refresh per second', + category: ['Crystools', this.menuPrefix + ' Refresh Rate'], + tooltip: 'This is the time (in seconds) between each update of the monitors, 0 means no refresh', + type: 'slider', + attrs: { + min: 0, + max: 2, + step: 0.25, + }, + defaultValue: .5, + onChange: async (value) => { + let valueNumber; + try { + valueNumber = parseFloat(value); + if (isNaN(valueNumber)) { + throw new Error('invalid value'); + } + } + catch (error) { + console.error(error); + return; + } + try { + await this.updateServer({ rate: valueNumber }); + } + catch (error) { + console.error(error); + return; + } + if (valueNumber === 0) { + this.monitorUI.updateAllMonitors({ + cpu_utilization: 0, + device: 'cpu', + gpus: [ + { + gpu_utilization: 0, + gpu_temperature: 0, + vram_total: 0, + vram_used: 0, + vram_used_percent: 0, + }, + ], + hdd_total: 0, + hdd_used: 0, + hdd_used_percent: 0, + ram_total: 0, + ram_used: 0, + ram_used_percent: 0, + }); + } + this.monitorUI?.updateAllAnimationDuration(valueNumber); + }, + }; + } + }); + Object.defineProperty(this, "createSettingsCPU", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + this.monitorCPUElement = { + id: 'Crystools.ShowCpu', + name: 'CPU Usage', + category: ['Crystools', this.menuPrefix + ' Hardware', 'Cpu'], + type: 'boolean', + label: 'CPU', + symbol: '%', + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.CPU, + onChange: async (value) => { + this.monitorUI?.updateWidget(this.monitorCPUElement); + await this.updateServer({ switchCPU: value }); + }, + }; + } + }); + Object.defineProperty(this, "createSettingsRAM", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + this.monitorRAMElement = { + id: 'Crystools.ShowRam', + name: 'RAM Used', + category: ['Crystools', this.menuPrefix + ' Hardware', 'Ram'], + type: 'boolean', + label: 'RAM', + symbol: '%', + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.RAM, + onChange: async (value) => { + this.monitorUI?.updateWidget(this.monitorRAMElement); + await this.updateServer({ switchRAM: value }); + }, + }; + } + }); + Object.defineProperty(this, "createSettingsGPUUsage", { + enumerable: true, + configurable: true, + writable: true, + value: (name, index, moreThanOneGPU) => { + if (name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + let label = 'GPU '; + label += moreThanOneGPU ? index : ''; + const monitorGPUNElement = { + id: 'Crystools.ShowGpuUsage' + convertNumberToPascalCase(index), + name: ' Usage', + category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'Usage'], + type: 'boolean', + label, + symbol: '%', + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.GPU, + onChange: async (value) => { + this.monitorUI?.updateWidget(monitorGPUNElement); + void await this.updateServerGPU(index, { utilization: value }); + }, + }; + this.monitorGPUSettings[index] = monitorGPUNElement; + app.ui.settings.addSetting(this.monitorGPUSettings[index]); + } + }); + Object.defineProperty(this, "createSettingsGPUVRAM", { + enumerable: true, + configurable: true, + writable: true, + value: (name, index, moreThanOneGPU) => { + if (name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + let label = 'VRAM'; + label += moreThanOneGPU ? index : ''; + const monitorVRAMNElement = { + id: 'Crystools.ShowGpuVram' + convertNumberToPascalCase(index), + name: 'VRAM', + category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'VRAM'], + type: 'boolean', + label: label, + symbol: '%', + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.VRAM, + onChange: async (value) => { + this.monitorUI?.updateWidget(monitorVRAMNElement); + void await this.updateServerGPU(index, { vram: value }); + }, + }; + this.monitorVRAMSettings[index] = monitorVRAMNElement; + app.ui.settings.addSetting(this.monitorVRAMSettings[index]); + } + }); + Object.defineProperty(this, "createSettingsGPUTemp", { + enumerable: true, + configurable: true, + writable: true, + value: (name, index, moreThanOneGPU) => { + if (name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + let label = 'Temp '; + label += moreThanOneGPU ? index : ''; + const monitorTemperatureNElement = { + id: 'Crystools.ShowGpuTemperature' + convertNumberToPascalCase(index), + name: 'Temperature', + category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'Temperature'], + type: 'boolean', + label: label, + symbol: '°', + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.TEMP_START, + cssColorFinal: Colors.TEMP_END, + onChange: async (value) => { + this.monitorUI?.updateWidget(monitorTemperatureNElement); + void await this.updateServerGPU(index, { temperature: value }); + }, + }; + this.monitorTemperatureSettings[index] = monitorTemperatureNElement; + app.ui.settings.addSetting(this.monitorTemperatureSettings[index]); + } + }); + Object.defineProperty(this, "createSettingsHDD", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + this.monitorHDDElement = { + id: 'Crystools.ShowHdd', + name: 'Show HDD Used', + category: ['Crystools', this.menuPrefix + ' Show Hard Disk', 'Show'], + type: 'boolean', + label: 'HDD', + symbol: '%', + defaultValue: false, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.DISK, + onChange: async (value) => { + this.monitorUI?.updateWidget(this.monitorHDDElement); + await this.updateServer({ switchHDD: value }); + }, + }; + this.settingsHDD = { + id: 'Crystools.WhichHdd', + name: 'Partition to show', + category: ['Crystools', this.menuPrefix + ' Show Hard Disk', 'Which'], + type: 'combo', + defaultValue: '/', + data: [], + options: (value) => { + const which = app.ui.settings.getSettingValue(this.settingsHDD.id, this.settingsHDD.defaultValue); + return this.settingsHDD.data.map((m) => ({ + value: m, + text: m, + selected: !value ? m === which : m === value, + })); + }, + onChange: async (value) => { + await this.updateServer({ whichHDD: value }); + }, + }; + } + }); + Object.defineProperty(this, "createSettings", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + app.ui.settings.addSetting(this.settingsRate); + app.ui.settings.addSetting(this.monitorRAMElement); + app.ui.settings.addSetting(this.monitorCPUElement); + void this.getHDDsFromServer().then((data) => { + this.settingsHDD.data = data; + app.ui.settings.addSetting(this.settingsHDD); + }); + app.ui.settings.addSetting(this.monitorHDDElement); + void this.getGPUsFromServer().then((gpus) => { + let moreThanOneGPU = false; + if (gpus.length > 1) { + moreThanOneGPU = true; + } + gpus?.forEach(({ name, index }) => { + this.createSettingsGPUTemp(name, index, moreThanOneGPU); + this.createSettingsGPUVRAM(name, index, moreThanOneGPU); + this.createSettingsGPUUsage(name, index, moreThanOneGPU); + }); + }); + } + }); + Object.defineProperty(this, "updateServer", { + enumerable: true, + configurable: true, + writable: true, + value: async (data) => { + const resp = await api.fetchApi('/crystools/monitor', { + method: 'PATCH', + body: JSON.stringify(data), + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.text(); + } + throw new Error(resp.statusText); + } + }); + Object.defineProperty(this, "updateServerGPU", { + enumerable: true, + configurable: true, + writable: true, + value: async (index, data) => { + const resp = await api.fetchApi(`/crystools/monitor/GPU/${index}`, { + method: 'PATCH', + body: JSON.stringify(data), + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.text(); + } + throw new Error(resp.statusText); + } + }); + Object.defineProperty(this, "getHDDsFromServer", { + enumerable: true, + configurable: true, + writable: true, + value: async () => { + return this.getDataFromServer('HDD'); + } + }); + Object.defineProperty(this, "getGPUsFromServer", { + enumerable: true, + configurable: true, + writable: true, + value: async () => { + return this.getDataFromServer('GPU'); + } + }); + Object.defineProperty(this, "getDataFromServer", { + enumerable: true, + configurable: true, + writable: true, + value: async (what) => { + const resp = await api.fetchApi(`/crystools/monitor/${what}`, { + method: 'GET', + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.json(); + } + throw new Error(resp.statusText); + } + }); + Object.defineProperty(this, "registerListeners", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + api.addEventListener('crystools.monitor', (event) => { + if (event?.detail === undefined) { + return; + } + this.monitorUI.updateAllMonitors(event.detail); + }, false); + } + }); + this.createSettingsRate(); + this.createSettingsCPU(); + this.createSettingsRAM(); + this.createSettingsHDD(); + this.createSettings(); + } + setup() { + const currentRate = parseFloat(app.ui.settings.getSettingValue(this.settingsRate.id, this.settingsRate.defaultValue)); + this.monitorUI = new MonitorUI(this.monitorCPUElement, this.monitorRAMElement, this.monitorHDDElement, this.monitorGPUSettings, this.monitorVRAMSettings, this.monitorTemperatureSettings, currentRate); + this.registerListeners(); + } +} +const crystoolsMonitor = new CrystoolsMonitor(); +app.registerExtension({ + name: crystoolsMonitor.idExtensionName, + setup: crystoolsMonitor.setup.bind(crystoolsMonitor), +}); diff --git a/web/monitor.ts b/web/monitor.ts index 5ce2825..ce141e1 100644 --- a/web/monitor.ts +++ b/web/monitor.ts @@ -1,341 +1,386 @@ -// import { app, api } from './comfy/index.js'; -// import { commonPrefix } from './common.js'; -// import { MonitorUI } from './monitorUI.js'; -// import { Colors } from './styles.js'; -// import { convertNumberToPascalCase } from './utils.js'; -// -// class CrystoolsMonitor { -// idExtensionName = 'Crystools.monitor'; -// menuPrefix = commonPrefix; -// -// monitorUI: MonitorUI; -// -// monitorGPUSettings: TMonitorSettings[] = []; -// monitorVRAMSettings: TMonitorSettings[] = []; -// monitorTemperatureSettings: TMonitorSettings[] = []; -// -// settingsRate = { -// id: 'Crystools.RefreshRate', -// name: 'Refresh per second', -// category: ['Crystools', this.menuPrefix + ' Refresh Rate'], -// tooltip: 'This is the time (in seconds) between each update of the monitors, 0 means no refresh', -// type: 'slider', -// attrs: { -// min: 0, -// max: 2, -// step: 0.25, -// }, -// defaultValue: .5, -// onChange: async(value: string): Promise => { -// let valueNumber: number; -// -// try { -// valueNumber = parseFloat(value); -// if (isNaN(valueNumber)) { -// throw new Error('invalid value'); -// } -// } catch (error) { -// console.error(error); -// return; -// } -// try { -// await this.updateServer({rate: valueNumber}); -// } catch (error) { -// console.error(error); -// return; -// } -// -// if (valueNumber === 0) { -// this.monitorUI.updateAllMonitors({ -// cpu_utilization: 0, -// device: 'cpu', -// -// gpus: [ -// { -// gpu_utilization: 0, -// gpu_temperature: 0, -// vram_total: 0, -// vram_used: 0, -// vram_used_percent: 0, -// }, -// ], -// hdd_total: 0, -// hdd_used: 0, -// hdd_used_percent: 0, -// ram_total: 0, -// ram_used: 0, -// ram_used_percent: 0, -// }); -// } -// -// this.monitorUI?.updateAllAnimationDuration(valueNumber); -// }, -// }; -// -// -// // CPU Variables -// monitorCPUElement: TMonitorSettings = { -// id: 'Crystools.ShowCpu', -// name: 'CPU Usage', -// category: ['Crystools', this.menuPrefix + ' Hardware', 'Cpu'], -// type: 'boolean', -// label: 'CPU', -// symbol: '%', -// defaultValue: true, -// htmlMonitorRef: undefined, -// htmlMonitorSliderRef: undefined, -// htmlMonitorLabelRef: undefined, -// cssColor: Colors.CPU, -// onChange: async(value: boolean) => { -// this.monitorUI?.updateWidget(this.monitorCPUElement); -// await this.updateServer({switchCPU: value}); -// }, -// }; -// -// // RAM Variables -// monitorRAMElement: TMonitorSettings = { -// id: 'Crystools.ShowRam', -// name: 'RAM Used', -// category: ['Crystools', this.menuPrefix + ' Hardware', 'Ram'], -// type: 'boolean', -// label: 'RAM', -// symbol: '%', -// defaultValue: true, -// htmlMonitorRef: undefined, -// htmlMonitorSliderRef: undefined, -// htmlMonitorLabelRef: undefined, -// cssColor: Colors.RAM, -// onChange: async(value: boolean) => { -// this.monitorUI?.updateWidget(this.monitorRAMElement); -// await this.updateServer({switchRAM: value}); -// }, -// }; -// -// // HDD Variables -// monitorHDDElement: TMonitorSettings = { -// id: 'Crystools.ShowHdd', -// name: 'Show HDD Used', -// category: ['Crystools', this.menuPrefix + ' Show Hard Disk', 'Show'], -// type: 'boolean', -// label: 'HDD', -// symbol: '%', -// // tooltip: 'See Partition to show (HDD)', -// defaultValue: false, -// htmlMonitorRef: undefined, -// htmlMonitorSliderRef: undefined, -// htmlMonitorLabelRef: undefined, -// cssColor: Colors.DISK, -// onChange: async(value: boolean) => { -// this.monitorUI?.updateWidget(this.monitorHDDElement); -// await this.updateServer({switchHDD: value}); -// }, -// }; -// -// settingsHDD = { -// id: 'Crystools.WhichHdd', -// name: 'Partition to show', -// category: ['Crystools', this.menuPrefix + ' Show Hard Disk', 'Which'], -// type: 'combo', -// defaultValue: '/', -// data: [], -// // @ts-ignore bad definition from comfyUI: `options?: undefined;`?? -// options: (value: string): any => { -// const which = app.ui.settings.getSettingValue(this.settingsHDD.id, this.settingsHDD.defaultValue); -// return this.settingsHDD.data.map((m) => ({ -// value: m, -// text: m, -// selected: !value ? m === which : m === value, -// })); -// }, -// onChange: async(value: string): Promise => { -// await this.updateServer({whichHDD: value}); -// }, -// }; -// -// constructor() { -// this.createSettings(); -// } -// -// createSettings = (): void => { -// app.ui.settings.addSetting(this.settingsRate); -// app.ui.settings.addSetting(this.monitorRAMElement); -// app.ui.settings.addSetting(this.monitorCPUElement); -// -// void this.getHDDsFromServer().then((data: string[]): void => { -// // @ts-ignore -// this.settingsHDD.data = data; -// app.ui.settings.addSetting(this.settingsHDD); -// }); -// app.ui.settings.addSetting(this.monitorHDDElement); -// -// void this.getGPUsFromServer().then((gpus: TGpuName[]): void => { -// let moreThanOneGPU = false; -// if (gpus.length > 1) { -// moreThanOneGPU = true; -// } -// -// gpus?.forEach(({name, index}) => { -// -// if (name === undefined || index === undefined) { -// console.warn('getGPUsFromServer: name or index undefined', name, index); -// return; -// } -// -// let label = 'GPU'; -// let labelVRAM = 'VRAM'; -// let labelTemperature = 'Temp'; -// if (moreThanOneGPU) { -// label = 'GPU ' + index; -// labelVRAM = 'VRAM' + index; -// labelTemperature = 'Temp ' + index; -// } -// -// // GPU Utilization Variables -// const monitorGPUNElement: TMonitorSettings = { -// id: 'Crystools.ShowGpuUsage' + convertNumberToPascalCase(index), -// name: ' Usage', -// category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'Usage'], -// type: 'boolean', -// label, -// symbol: '%', -// title: `${index}: ${name}`, -// defaultValue: true, -// htmlMonitorRef: undefined, -// htmlMonitorSliderRef: undefined, -// htmlMonitorLabelRef: undefined, -// cssColor: Colors.GPU, -// onChange: async(value: boolean) => { -// this.monitorUI?.updateWidget(monitorGPUNElement); -// void await this.updateServerGPU(index, {utilization: value}); -// }, -// }; -// -// // GPU VRAM Variables -// const monitorVRAMNElement: TMonitorSettings = { -// id: 'Crystools.ShowGpuVram' + convertNumberToPascalCase(index), -// name: 'VRAM', -// category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'VRAM'], -// type: 'boolean', -// label: labelVRAM, -// symbol: '%', -// title: `${index}: ${name}`, -// defaultValue: true, -// htmlMonitorRef: undefined, -// htmlMonitorSliderRef: undefined, -// htmlMonitorLabelRef: undefined, -// cssColor: Colors.VRAM, -// onChange: async(value: boolean) => { -// this.monitorUI?.updateWidget(monitorVRAMNElement); -// void await this.updateServerGPU(index, {vram: value}); -// }, -// }; -// -// // GPU Temperature Variables -// const monitorTemperatureNElement: TMonitorSettings = { -// id: 'Crystools.ShowGpuTemperature' + convertNumberToPascalCase(index), -// name: 'Temperature', -// category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'Temperature'], -// type: 'boolean', -// label: labelTemperature, -// symbol: '°', -// title: `${index}: ${name}`, -// defaultValue: true, -// htmlMonitorRef: undefined, -// htmlMonitorSliderRef: undefined, -// htmlMonitorLabelRef: undefined, -// cssColor: Colors.TEMP_START, -// cssColorFinal: Colors.TEMP_END, -// onChange: async(value: boolean) => { -// this.monitorUI?.updateWidget(monitorTemperatureNElement); -// void await this.updateServerGPU(index, {temperature: value}); -// }, -// }; -// -// this.monitorGPUSettings[index] = monitorGPUNElement; -// this.monitorVRAMSettings[index] = monitorVRAMNElement; -// this.monitorTemperatureSettings[index] = monitorTemperatureNElement; -// // @ts-ignore -// app.ui.settings.addSetting(this.monitorTemperatureSettings[index]); -// // @ts-ignore -// app.ui.settings.addSetting(this.monitorVRAMSettings[index]); -// // @ts-ignore -// app.ui.settings.addSetting(this.monitorGPUSettings[index]); -// }); -// }); -// }; -// -// updateServer = async(data: TStatsSettings): Promise => { -// const resp = await api.fetchApi('/crystools/monitor', { -// method: 'PATCH', -// body: JSON.stringify(data), -// cache: 'no-store', -// }); -// if (resp.status === 200) { -// return await resp.text(); -// } -// throw new Error(resp.statusText); -// }; -// -// updateServerGPU = async(index: number, data: TGpuSettings): Promise => { -// const resp = await api.fetchApi(`/crystools/monitor/GPU/${index}`, { -// method: 'PATCH', -// body: JSON.stringify(data), -// cache: 'no-store', -// }); -// if (resp.status === 200) { -// return await resp.text(); -// } -// throw new Error(resp.statusText); -// }; -// -// getHDDsFromServer = async(): Promise => { -// return this.getDataFromServer('HDD'); -// }; -// -// getGPUsFromServer = async(): Promise => { -// return this.getDataFromServer('GPU'); -// }; -// -// getDataFromServer = async (what: string): Promise => { -// const resp = await api.fetchApi(`/crystools/monitor/${what}`, { -// method: 'GET', -// cache: 'no-store', -// }); -// if (resp.status === 200) { -// return await resp.json(); -// } -// throw new Error(resp.statusText); -// }; -// -// setup(): void { -// const currentRate = -// parseFloat(app.ui.settings.getSettingValue(this.settingsRate.id, this.settingsRate.defaultValue)); -// -// this.monitorUI = new MonitorUI( -// this.monitorCPUElement, -// this.monitorRAMElement, -// this.monitorHDDElement, -// this.monitorGPUSettings, -// this.monitorVRAMSettings, -// this.monitorTemperatureSettings, -// currentRate, -// ); -// -// this.registerListeners(); -// } -// -// registerListeners = (): void => { -// api.addEventListener('crystools.monitor', (event: CustomEvent) => { -// if (event?.detail === undefined) { -// return; -// } -// this.monitorUI.updateAllMonitors(event.detail); -// }, false); -// }; -// } -// -// const crystoolsMonitor = new CrystoolsMonitor(); -// app.registerExtension({ -// name: crystoolsMonitor.idExtensionName, -// setup: crystoolsMonitor.setup.bind(crystoolsMonitor), -// }); +import { app, api } from './comfy/index.js'; +import { commonPrefix } from './common.js'; +import { MonitorUI } from './monitorUI.js'; +import { Colors } from './styles.js'; +import { convertNumberToPascalCase } from './utils.js'; + +class CrystoolsMonitor { + idExtensionName = 'Crystools.monitor'; + menuPrefix = commonPrefix; + + monitorUI: MonitorUI; + + settingsRate: TMonitorSettings; + monitorCPUElement: TMonitorSettings; + monitorRAMElement: TMonitorSettings; + monitorHDDElement: TMonitorSettings; + settingsHDD: TMonitorSettings; + monitorGPUSettings: TMonitorSettings[] = []; + monitorVRAMSettings: TMonitorSettings[] = []; + monitorTemperatureSettings: TMonitorSettings[] = []; + + + constructor() { + this.createSettingsRate(); + this.createSettingsCPU(); + this.createSettingsRAM(); + this.createSettingsHDD(); + this.createSettings(); + } + + createSettingsRate = (): void => { + this.settingsRate = { + id: 'Crystools.RefreshRate', + name: 'Refresh per second', + category: ['Crystools', this.menuPrefix + ' Refresh Rate'], + tooltip: 'This is the time (in seconds) between each update of the monitors, 0 means no refresh', + type: 'slider', + attrs: { + min: 0, + max: 2, + step: 0.25, + }, + defaultValue: .5, + // @ts-ignore + onChange: async(value: string): Promise => { + let valueNumber: number; + + try { + valueNumber = parseFloat(value); + if (isNaN(valueNumber)) { + throw new Error('invalid value'); + } + } catch (error) { + console.error(error); + return; + } + try { + await this.updateServer({rate: valueNumber}); + } catch (error) { + console.error(error); + return; + } + + if (valueNumber === 0) { + this.monitorUI.updateAllMonitors({ + cpu_utilization: 0, + device: 'cpu', + + gpus: [ + { + gpu_utilization: 0, + gpu_temperature: 0, + vram_total: 0, + vram_used: 0, + vram_used_percent: 0, + }, + ], + hdd_total: 0, + hdd_used: 0, + hdd_used_percent: 0, + ram_total: 0, + ram_used: 0, + ram_used_percent: 0, + }); + } + + this.monitorUI?.updateAllAnimationDuration(valueNumber); + }, + }; + }; + + createSettingsCPU = (): void => { + // CPU Variables + this.monitorCPUElement = { + id: 'Crystools.ShowCpu', + name: 'CPU Usage', + category: ['Crystools', this.menuPrefix + ' Hardware', 'Cpu'], + type: 'boolean', + label: 'CPU', + symbol: '%', + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.CPU, + // @ts-ignore + onChange: async(value: boolean): Promise => { + this.monitorUI?.updateWidget(this.monitorCPUElement); + await this.updateServer({switchCPU: value}); + }, + }; + }; + + createSettingsRAM = (): void => { + // RAM Variables + this.monitorRAMElement = { + id: 'Crystools.ShowRam', + name: 'RAM Used', + category: ['Crystools', this.menuPrefix + ' Hardware', 'Ram'], + type: 'boolean', + label: 'RAM', + symbol: '%', + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.RAM, + // @ts-ignore + onChange: async(value: boolean): Promise => { + this.monitorUI?.updateWidget(this.monitorRAMElement); + await this.updateServer({switchRAM: value}); + }, + }; + }; + + createSettingsGPUUsage = (name: string, index: number, moreThanOneGPU: boolean): void => { + if (name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + + let label = 'GPU '; + label += moreThanOneGPU ? index : ''; + + const monitorGPUNElement: TMonitorSettings = { + id: 'Crystools.ShowGpuUsage' + convertNumberToPascalCase(index), + name: ' Usage', + category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'Usage'], + type: 'boolean', + label, + symbol: '%', + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.GPU, + // @ts-ignore + onChange: async(value: boolean): Promise => { + this.monitorUI?.updateWidget(monitorGPUNElement); + void await this.updateServerGPU(index, {utilization: value}); + }, + }; + + this.monitorGPUSettings[index] = monitorGPUNElement; + app.ui.settings.addSetting(this.monitorGPUSettings[index]); + }; + + createSettingsGPUVRAM = (name: string, index: number, moreThanOneGPU: boolean): void => { + if (name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + + let label = 'VRAM'; + label += moreThanOneGPU ? index : ''; + + // GPU VRAM Variables + const monitorVRAMNElement: TMonitorSettings = { + id: 'Crystools.ShowGpuVram' + convertNumberToPascalCase(index), + name: 'VRAM', + category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'VRAM'], + type: 'boolean', + label: label, + symbol: '%', + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.VRAM, + // @ts-ignore + onChange: async(value: boolean): Promise => { + this.monitorUI?.updateWidget(monitorVRAMNElement); + void await this.updateServerGPU(index, {vram: value}); + }, + }; + + this.monitorVRAMSettings[index] = monitorVRAMNElement; + app.ui.settings.addSetting(this.monitorVRAMSettings[index]); + }; + + createSettingsGPUTemp = (name: string, index: number, moreThanOneGPU: boolean): void => { + if (name === undefined || index === undefined) { + console.warn('getGPUsFromServer: name or index undefined', name, index); + return; + } + + let label = 'Temp '; + label += moreThanOneGPU ? index : ''; + + // GPU Temperature Variables + const monitorTemperatureNElement: TMonitorSettings = { + id: 'Crystools.ShowGpuTemperature' + convertNumberToPascalCase(index), + name: 'Temperature', + category: ['Crystools', `${this.menuPrefix} Show GPU [${index}] ${name}`, 'Temperature'], + type: 'boolean', + label: label, + symbol: '°', + title: `${index}: ${name}`, + defaultValue: true, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.TEMP_START, + cssColorFinal: Colors.TEMP_END, + // @ts-ignore + onChange: async(value: boolean): Promise => { + this.monitorUI?.updateWidget(monitorTemperatureNElement); + void await this.updateServerGPU(index, {temperature: value}); + }, + }; + + this.monitorTemperatureSettings[index] = monitorTemperatureNElement; + app.ui.settings.addSetting(this.monitorTemperatureSettings[index]); + }; + + createSettingsHDD = (): void => { + // HDD Variables + this.monitorHDDElement = { + id: 'Crystools.ShowHdd', + name: 'Show HDD Used', + category: ['Crystools', this.menuPrefix + ' Show Hard Disk', 'Show'], + type: 'boolean', + label: 'HDD', + symbol: '%', + // tooltip: 'See Partition to show (HDD)', + defaultValue: false, + htmlMonitorRef: undefined, + htmlMonitorSliderRef: undefined, + htmlMonitorLabelRef: undefined, + cssColor: Colors.DISK, + // @ts-ignore + onChange: async(value: boolean): Promise => { + this.monitorUI?.updateWidget(this.monitorHDDElement); + await this.updateServer({switchHDD: value}); + }, + }; + + this.settingsHDD = { + id: 'Crystools.WhichHdd', + name: 'Partition to show', + category: ['Crystools', this.menuPrefix + ' Show Hard Disk', 'Which'], + type: 'combo', + defaultValue: '/', + data: [], + // @ts-ignore bad definition from comfyUI: `options?: undefined;`?? + options: (value: string): any => { + const which = app.ui.settings.getSettingValue(this.settingsHDD.id, this.settingsHDD.defaultValue); + return this.settingsHDD.data.map((m: any) => ({ + value: m, + text: m, + selected: !value ? m === which : m === value, + })); + }, + // @ts-ignore + onChange: async(value: string): Promise => { + await this.updateServer({whichHDD: value}); + }, + }; + }; + + + createSettings = (): void => { + app.ui.settings.addSetting(this.settingsRate); + app.ui.settings.addSetting(this.monitorRAMElement); + app.ui.settings.addSetting(this.monitorCPUElement); + + void this.getHDDsFromServer().then((data: string[]): void => { + // @ts-ignore + this.settingsHDD.data = data; + app.ui.settings.addSetting(this.settingsHDD); + }); + app.ui.settings.addSetting(this.monitorHDDElement); + + void this.getGPUsFromServer().then((gpus: TGpuName[]): void => { + let moreThanOneGPU = false; + if (gpus.length > 1) { + moreThanOneGPU = true; + } + + gpus?.forEach(({name, index}) => { + + this.createSettingsGPUTemp(name, index, moreThanOneGPU); + this.createSettingsGPUVRAM(name, index, moreThanOneGPU); + this.createSettingsGPUUsage(name, index, moreThanOneGPU); + + }); + }); + }; + + updateServer = async(data: TStatsSettings): Promise => { + const resp = await api.fetchApi('/crystools/monitor', { + method: 'PATCH', + body: JSON.stringify(data), + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.text(); + } + throw new Error(resp.statusText); + }; + + updateServerGPU = async(index: number, data: TGpuSettings): Promise => { + const resp = await api.fetchApi(`/crystools/monitor/GPU/${index}`, { + method: 'PATCH', + body: JSON.stringify(data), + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.text(); + } + throw new Error(resp.statusText); + }; + + getHDDsFromServer = async(): Promise => { + return this.getDataFromServer('HDD'); + }; + + getGPUsFromServer = async(): Promise => { + return this.getDataFromServer('GPU'); + }; + + getDataFromServer = async (what: string): Promise => { + const resp = await api.fetchApi(`/crystools/monitor/${what}`, { + method: 'GET', + cache: 'no-store', + }); + if (resp.status === 200) { + return await resp.json(); + } + throw new Error(resp.statusText); + }; + + setup(): void { + const currentRate = + parseFloat(app.ui.settings.getSettingValue(this.settingsRate.id, this.settingsRate.defaultValue)); + + this.monitorUI = new MonitorUI( + this.monitorCPUElement, + this.monitorRAMElement, + this.monitorHDDElement, + this.monitorGPUSettings, + this.monitorVRAMSettings, + this.monitorTemperatureSettings, + currentRate, + ); + + this.registerListeners(); + } + + registerListeners = (): void => { + api.addEventListener('crystools.monitor', (event: CustomEvent) => { + if (event?.detail === undefined) { + return; + } + this.monitorUI.updateAllMonitors(event.detail); + }, false); + }; +} + +const crystoolsMonitor = new CrystoolsMonitor(); +app.registerExtension({ + name: crystoolsMonitor.idExtensionName, + setup: crystoolsMonitor.setup.bind(crystoolsMonitor), +}); diff --git a/web/monitorUI.d.ts b/web/monitorUI.d.ts index e69de29..124ae33 100644 --- a/web/monitorUI.d.ts +++ b/web/monitorUI.d.ts @@ -0,0 +1,20 @@ +import { ProgressBarUIBase } from './progressBarUI.js'; +export declare class MonitorUI extends ProgressBarUIBase { + private monitorCPUElement; + private monitorRAMElement; + private monitorHDDElement; + private monitorGPUSettings; + private monitorVRAMSettings; + private monitorTemperatureSettings; + private currentRate; + constructor(monitorCPUElement: TMonitorSettings, monitorRAMElement: TMonitorSettings, monitorHDDElement: TMonitorSettings, monitorGPUSettings: TMonitorSettings[], monitorVRAMSettings: TMonitorSettings[], monitorTemperatureSettings: TMonitorSettings[], currentRate: number); + refreshDisplay: () => void; + createDOM: () => void; + updateAllWidget: () => void; + updateWidget: (monitorSettings: TMonitorSettings) => void; + updateAllMonitors: (data: TStatsData) => void; + updateMonitor: (monitorSettings: TMonitorSettings, percent: number) => void; + updateAllAnimationDuration: (value: number) => void; + updatedAnimationDuration: (monitorSettings: TMonitorSettings, value: number) => void; + createMonitor: (monitorSettings?: TMonitorSettings) => HTMLDivElement; +} diff --git a/web/monitorUI.js b/web/monitorUI.js index 3918c74..8816b70 100644 --- a/web/monitorUI.js +++ b/web/monitorUI.js @@ -1 +1,241 @@ -"use strict"; +import { app } from './comfy/index.js'; +import { ProgressBarUIBase } from './progressBarUI.js'; +export class MonitorUI extends ProgressBarUIBase { + constructor(monitorCPUElement, monitorRAMElement, monitorHDDElement, monitorGPUSettings, monitorVRAMSettings, monitorTemperatureSettings, currentRate) { + super(); + Object.defineProperty(this, "monitorCPUElement", { + enumerable: true, + configurable: true, + writable: true, + value: monitorCPUElement + }); + Object.defineProperty(this, "monitorRAMElement", { + enumerable: true, + configurable: true, + writable: true, + value: monitorRAMElement + }); + Object.defineProperty(this, "monitorHDDElement", { + enumerable: true, + configurable: true, + writable: true, + value: monitorHDDElement + }); + Object.defineProperty(this, "monitorGPUSettings", { + enumerable: true, + configurable: true, + writable: true, + value: monitorGPUSettings + }); + Object.defineProperty(this, "monitorVRAMSettings", { + enumerable: true, + configurable: true, + writable: true, + value: monitorVRAMSettings + }); + Object.defineProperty(this, "monitorTemperatureSettings", { + enumerable: true, + configurable: true, + writable: true, + value: monitorTemperatureSettings + }); + Object.defineProperty(this, "currentRate", { + enumerable: true, + configurable: true, + writable: true, + value: currentRate + }); + Object.defineProperty(this, "refreshDisplay", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + this.updateAllWidget(); + } + }); + Object.defineProperty(this, "createDOM", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + this.htmlContainer.append(this.createMonitor(this.monitorCPUElement)); + this.htmlContainer.append(this.createMonitor(this.monitorRAMElement)); + this.monitorGPUSettings.forEach((_monitorSettings, index) => { + this.monitorGPUSettings[index] && this.htmlContainer.append(this.createMonitor(this.monitorGPUSettings[index])); + this.monitorVRAMSettings[index] && this.htmlContainer.append(this.createMonitor(this.monitorVRAMSettings[index])); + this.monitorTemperatureSettings[index] && + this.htmlContainer.append(this.createMonitor(this.monitorTemperatureSettings[index])); + }); + this.htmlContainer.append(this.createMonitor(this.monitorHDDElement)); + this.updateAllAnimationDuration(this.currentRate); + this.updateAllWidget(); + } + }); + Object.defineProperty(this, "updateAllWidget", { + enumerable: true, + configurable: true, + writable: true, + value: () => { + this.updateWidget(this.monitorCPUElement); + this.updateWidget(this.monitorRAMElement); + this.updateWidget(this.monitorHDDElement); + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + this.monitorTemperatureSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + } + }); + Object.defineProperty(this, "updateWidget", { + enumerable: true, + configurable: true, + writable: true, + value: (monitorSettings) => { + const value = app.ui.settings.getSettingValue(monitorSettings.id, monitorSettings.defaultValue); + if (monitorSettings.htmlMonitorRef) { + monitorSettings.htmlMonitorRef.style.display = value ? 'flex' : 'none'; + } + } + }); + Object.defineProperty(this, "updateAllMonitors", { + enumerable: true, + configurable: true, + writable: true, + value: (data) => { + this.updateMonitor(this.monitorCPUElement, data.cpu_utilization); + this.updateMonitor(this.monitorRAMElement, data.ram_used_percent); + this.updateMonitor(this.monitorHDDElement, data.hdd_used_percent); + if (data.gpus === undefined || data.gpus.length === 0) { + console.warn('UpdateAllMonitors: no GPU data'); + return; + } + this.monitorGPUSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + return; + } + this.updateMonitor(monitorSettings, gpu.gpu_utilization); + } + else { + } + }); + this.monitorVRAMSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + return; + } + this.updateMonitor(monitorSettings, gpu.vram_used_percent); + } + else { + } + }); + this.monitorTemperatureSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + return; + } + this.updateMonitor(monitorSettings, gpu.gpu_temperature); + if (monitorSettings.cssColorFinal && monitorSettings.htmlMonitorSliderRef) { + monitorSettings.htmlMonitorSliderRef.style.backgroundColor = + `color-mix(in srgb, ${monitorSettings.cssColorFinal} ${gpu.gpu_temperature}%, ${monitorSettings.cssColor})`; + } + } + else { + } + }); + } + }); + Object.defineProperty(this, "updateMonitor", { + enumerable: true, + configurable: true, + writable: true, + value: (monitorSettings, percent) => { + if (!(monitorSettings.htmlMonitorSliderRef && monitorSettings.htmlMonitorLabelRef)) { + return; + } + monitorSettings.htmlMonitorLabelRef.innerHTML = `${Math.floor(percent)}${monitorSettings.symbol}`; + monitorSettings.htmlMonitorSliderRef.style.width = `${Math.floor(percent)}%`; + } + }); + Object.defineProperty(this, "updateAllAnimationDuration", { + enumerable: true, + configurable: true, + writable: true, + value: (value) => { + this.updatedAnimationDuration(this.monitorCPUElement, value); + this.updatedAnimationDuration(this.monitorRAMElement, value); + this.updatedAnimationDuration(this.monitorHDDElement, value); + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + this.monitorTemperatureSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + } + }); + Object.defineProperty(this, "updatedAnimationDuration", { + enumerable: true, + configurable: true, + writable: true, + value: (monitorSettings, value) => { + const slider = monitorSettings.htmlMonitorSliderRef; + if (!slider) { + return; + } + slider.style.transition = `width ${value.toFixed(1)}s`; + } + }); + Object.defineProperty(this, "createMonitor", { + enumerable: true, + configurable: true, + writable: true, + value: (monitorSettings) => { + if (!monitorSettings) { + return document.createElement('div'); + } + const htmlMain = document.createElement('div'); + htmlMain.setAttribute('id', monitorSettings.id); + htmlMain.classList.add('crystools-monitor'); + monitorSettings.htmlMonitorRef = htmlMain; + if (monitorSettings.title) { + htmlMain.title = monitorSettings.title; + } + const htmlMonitorText = document.createElement('div'); + htmlMonitorText.classList.add('crystools-text'); + htmlMonitorText.innerHTML = monitorSettings.label; + htmlMain.append(htmlMonitorText); + const htmlMonitorContent = document.createElement('div'); + htmlMonitorContent.classList.add('crystools-content'); + htmlMain.append(htmlMonitorContent); + const htmlMonitorSlider = document.createElement('div'); + htmlMonitorSlider.classList.add('crystools-slider'); + if (monitorSettings.cssColorFinal) { + htmlMonitorSlider.style.backgroundColor = + `color-mix(in srgb, ${monitorSettings.cssColorFinal} 0%, ${monitorSettings.cssColor})`; + } + else { + htmlMonitorSlider.style.backgroundColor = monitorSettings.cssColor; + } + monitorSettings.htmlMonitorSliderRef = htmlMonitorSlider; + htmlMonitorContent.append(htmlMonitorSlider); + const htmlMonitorLabel = document.createElement('div'); + htmlMonitorLabel.classList.add('crystools-label'); + monitorSettings.htmlMonitorLabelRef = htmlMonitorLabel; + htmlMonitorContent.append(htmlMonitorLabel); + htmlMonitorLabel.innerHTML = '0%'; + return monitorSettings.htmlMonitorRef; + } + }); + this.createDOM(); + } +} diff --git a/web/monitorUI.ts b/web/monitorUI.ts index 49c54b1..5b40235 100644 --- a/web/monitorUI.ts +++ b/web/monitorUI.ts @@ -1,213 +1,213 @@ -// import { app } from './comfy/index.js'; -// import { ProgressBarUIBase } from './progressBarUI.js'; -// -// export class MonitorUI extends ProgressBarUIBase { -// constructor( -// private monitorCPUElement: TMonitorSettings, -// private monitorRAMElement: TMonitorSettings, -// private monitorHDDElement: TMonitorSettings, -// private monitorGPUSettings: TMonitorSettings[], -// private monitorVRAMSettings: TMonitorSettings[], -// private monitorTemperatureSettings: TMonitorSettings[], -// private currentRate: number -// ) { -// super(); -// this.createDOM(); -// } -// -// refreshDisplay = (): void => { -// // console.log('refreshDisplay'); -// this.updateAllWidget(); -// }; -// -// override createDOM = (): void => { -// this.htmlContainer.append(this.createMonitor(this.monitorCPUElement)); -// this.htmlContainer.append(this.createMonitor(this.monitorRAMElement)); -// -// // gpu0 > gpu1 > vram0 > vram1 -// // this.monitorGPUSettings.forEach((monitorSettings) => { -// // monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); -// // }); -// // this.monitorVRAMSettings.forEach((monitorSettings) => { -// // monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); -// // }); -// // this.monitorTemperatureSettings.forEach((monitorSettings) => { -// // monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); -// // }); -// -// // gpu0 > vram0 > gpu1 > vram1 -// this.monitorGPUSettings.forEach((_monitorSettings, index) => { -// this.monitorGPUSettings[index] && this.htmlContainer.append(this.createMonitor(this.monitorGPUSettings[index])); -// this.monitorVRAMSettings[index] && this.htmlContainer.append(this.createMonitor(this.monitorVRAMSettings[index])); -// this.monitorTemperatureSettings[index] && -// this.htmlContainer.append(this.createMonitor(this.monitorTemperatureSettings[index])); -// }); -// -// this.htmlContainer.append(this.createMonitor(this.monitorHDDElement)); -// -// this.updateAllAnimationDuration(this.currentRate); -// this.updateAllWidget(); -// }; -// -// -// updateAllWidget = (): void => { -// this.updateWidget(this.monitorCPUElement); -// this.updateWidget(this.monitorRAMElement); -// this.updateWidget(this.monitorHDDElement); -// -// this.monitorGPUSettings.forEach((monitorSettings) => { -// monitorSettings && this.updateWidget(monitorSettings); -// }); -// this.monitorVRAMSettings.forEach((monitorSettings) => { -// monitorSettings && this.updateWidget(monitorSettings); -// }); -// this.monitorTemperatureSettings.forEach((monitorSettings) => { -// monitorSettings && this.updateWidget(monitorSettings); -// }); -// }; -// -// /** -// * for the settings menu -// * @param monitorSettings -// */ -// updateWidget = (monitorSettings: TMonitorSettings): void => { -// const value = app.ui.settings.getSettingValue(monitorSettings.id, monitorSettings.defaultValue); -// if (monitorSettings.htmlMonitorRef) { -// monitorSettings.htmlMonitorRef.style.display = value ? 'flex' : 'none'; -// } -// }; -// -// updateAllMonitors = (data: TStatsData): void => { -// // console.log('updateAllMonitors', data); -// this.updateMonitor(this.monitorCPUElement, data.cpu_utilization); -// this.updateMonitor(this.monitorRAMElement, data.ram_used_percent); -// this.updateMonitor(this.monitorHDDElement, data.hdd_used_percent); -// -// if (data.gpus === undefined || data.gpus.length === 0) { -// console.warn('UpdateAllMonitors: no GPU data'); -// return; -// } -// -// this.monitorGPUSettings.forEach((monitorSettings, index) => { -// if (data.gpus[index]) { -// const gpu = data.gpus[index]; -// if (gpu === undefined) { -// // console.error('UpdateAllMonitors: no GPU data for index', index); -// return; -// } -// -// this.updateMonitor(monitorSettings, gpu.gpu_utilization); -// } else { -// // console.error('UpdateAllMonitors: no GPU data for index', index); -// } -// }); -// -// this.monitorVRAMSettings.forEach((monitorSettings, index) => { -// if (data.gpus[index]) { -// const gpu = data.gpus[index]; -// if (gpu === undefined) { -// // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); -// return; -// } -// -// this.updateMonitor(monitorSettings, gpu.vram_used_percent); -// } else { -// // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); -// } -// }); -// -// this.monitorTemperatureSettings.forEach((monitorSettings, index) => { -// if (data.gpus[index]) { -// const gpu = data.gpus[index]; -// if (gpu === undefined) { -// // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); -// return; -// } -// -// this.updateMonitor(monitorSettings, gpu.gpu_temperature); -// if(monitorSettings.cssColorFinal && monitorSettings.htmlMonitorSliderRef){ -// monitorSettings.htmlMonitorSliderRef.style.backgroundColor = -// `color-mix(in srgb, ${monitorSettings.cssColorFinal} ${gpu.gpu_temperature}%, ${monitorSettings.cssColor})`; -// } -// } else { -// // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); -// } -// }); -// }; -// -// updateMonitor = (monitorSettings: TMonitorSettings, percent: number): void => { -// if (!(monitorSettings.htmlMonitorSliderRef && monitorSettings.htmlMonitorLabelRef)) { -// return; -// } -// -// monitorSettings.htmlMonitorLabelRef.innerHTML = `${Math.floor(percent)}${monitorSettings.symbol}`; -// monitorSettings.htmlMonitorSliderRef.style.width = `${Math.floor(percent)}%`; -// }; -// -// updateAllAnimationDuration = (value: number): void => { -// this.updatedAnimationDuration(this.monitorCPUElement, value); -// this.updatedAnimationDuration(this.monitorRAMElement, value); -// this.updatedAnimationDuration(this.monitorHDDElement, value); -// this.monitorGPUSettings.forEach((monitorSettings) => { -// monitorSettings && this.updatedAnimationDuration(monitorSettings, value); -// }); -// this.monitorVRAMSettings.forEach((monitorSettings) => { -// monitorSettings && this.updatedAnimationDuration(monitorSettings, value); -// }); -// this.monitorTemperatureSettings.forEach((monitorSettings) => { -// monitorSettings && this.updatedAnimationDuration(monitorSettings, value); -// }); -// }; -// -// updatedAnimationDuration = (monitorSettings: TMonitorSettings, value: number): void => { -// const slider = monitorSettings.htmlMonitorSliderRef; -// if (!slider) { -// return; -// } -// -// slider.style.transition = `width ${value.toFixed(1)}s`; -// }; -// -// -// createMonitor = (monitorSettings?: TMonitorSettings): HTMLDivElement => { -// if (!monitorSettings) { -// // just for typescript -// return document.createElement('div'); -// } -// const htmlMain = document.createElement('div'); -// htmlMain.setAttribute('id', monitorSettings.id); -// htmlMain.classList.add('crystools-monitor'); -// monitorSettings.htmlMonitorRef = htmlMain; -// -// if (monitorSettings.title) { -// htmlMain.title = monitorSettings.title; -// } -// -// const htmlMonitorText = document.createElement('div'); -// htmlMonitorText.classList.add('crystools-text'); -// htmlMonitorText.innerHTML = monitorSettings.label; -// htmlMain.append(htmlMonitorText); -// -// const htmlMonitorContent = document.createElement('div'); -// htmlMonitorContent.classList.add('crystools-content'); -// htmlMain.append(htmlMonitorContent); -// -// const htmlMonitorSlider = document.createElement('div'); -// htmlMonitorSlider.classList.add('crystools-slider'); -// if(monitorSettings.cssColorFinal){ -// htmlMonitorSlider.style.backgroundColor = -// `color-mix(in srgb, ${monitorSettings.cssColorFinal} 0%, ${monitorSettings.cssColor})`; -// } else { -// htmlMonitorSlider.style.backgroundColor = monitorSettings.cssColor; -// } -// monitorSettings.htmlMonitorSliderRef = htmlMonitorSlider; -// htmlMonitorContent.append(htmlMonitorSlider); -// -// const htmlMonitorLabel = document.createElement('div'); -// htmlMonitorLabel.classList.add('crystools-label'); -// monitorSettings.htmlMonitorLabelRef = htmlMonitorLabel; -// htmlMonitorContent.append(htmlMonitorLabel); -// htmlMonitorLabel.innerHTML = '0%'; -// return monitorSettings.htmlMonitorRef; -// }; -// } +import { app } from './comfy/index.js'; +import { ProgressBarUIBase } from './progressBarUI.js'; + +export class MonitorUI extends ProgressBarUIBase { + constructor( + private monitorCPUElement: TMonitorSettings, + private monitorRAMElement: TMonitorSettings, + private monitorHDDElement: TMonitorSettings, + private monitorGPUSettings: TMonitorSettings[], + private monitorVRAMSettings: TMonitorSettings[], + private monitorTemperatureSettings: TMonitorSettings[], + private currentRate: number + ) { + super(); + this.createDOM(); + } + + refreshDisplay = (): void => { + // console.log('refreshDisplay'); + this.updateAllWidget(); + }; + + override createDOM = (): void => { + this.htmlContainer.append(this.createMonitor(this.monitorCPUElement)); + this.htmlContainer.append(this.createMonitor(this.monitorRAMElement)); + + // gpu0 > gpu1 > vram0 > vram1 + // this.monitorGPUSettings.forEach((monitorSettings) => { + // monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); + // }); + // this.monitorVRAMSettings.forEach((monitorSettings) => { + // monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); + // }); + // this.monitorTemperatureSettings.forEach((monitorSettings) => { + // monitorSettings && htmlContainer.append(this.createMonitor(monitorSettings)); + // }); + + // gpu0 > vram0 > gpu1 > vram1 + this.monitorGPUSettings.forEach((_monitorSettings, index) => { + this.monitorGPUSettings[index] && this.htmlContainer.append(this.createMonitor(this.monitorGPUSettings[index])); + this.monitorVRAMSettings[index] && this.htmlContainer.append(this.createMonitor(this.monitorVRAMSettings[index])); + this.monitorTemperatureSettings[index] && + this.htmlContainer.append(this.createMonitor(this.monitorTemperatureSettings[index])); + }); + + this.htmlContainer.append(this.createMonitor(this.monitorHDDElement)); + + this.updateAllAnimationDuration(this.currentRate); + this.updateAllWidget(); + }; + + + updateAllWidget = (): void => { + this.updateWidget(this.monitorCPUElement); + this.updateWidget(this.monitorRAMElement); + this.updateWidget(this.monitorHDDElement); + + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + this.monitorTemperatureSettings.forEach((monitorSettings) => { + monitorSettings && this.updateWidget(monitorSettings); + }); + }; + + /** + * for the settings menu + * @param monitorSettings + */ + updateWidget = (monitorSettings: TMonitorSettings): void => { + const value = app.ui.settings.getSettingValue(monitorSettings.id, monitorSettings.defaultValue); + if (monitorSettings.htmlMonitorRef) { + monitorSettings.htmlMonitorRef.style.display = value ? 'flex' : 'none'; + } + }; + + updateAllMonitors = (data: TStatsData): void => { + // console.log('updateAllMonitors', data); + this.updateMonitor(this.monitorCPUElement, data.cpu_utilization); + this.updateMonitor(this.monitorRAMElement, data.ram_used_percent); + this.updateMonitor(this.monitorHDDElement, data.hdd_used_percent); + + if (data.gpus === undefined || data.gpus.length === 0) { + console.warn('UpdateAllMonitors: no GPU data'); + return; + } + + this.monitorGPUSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + // console.error('UpdateAllMonitors: no GPU data for index', index); + return; + } + + this.updateMonitor(monitorSettings, gpu.gpu_utilization); + } else { + // console.error('UpdateAllMonitors: no GPU data for index', index); + } + }); + + this.monitorVRAMSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); + return; + } + + this.updateMonitor(monitorSettings, gpu.vram_used_percent); + } else { + // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); + } + }); + + this.monitorTemperatureSettings.forEach((monitorSettings, index) => { + if (data.gpus[index]) { + const gpu = data.gpus[index]; + if (gpu === undefined) { + // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); + return; + } + + this.updateMonitor(monitorSettings, gpu.gpu_temperature); + if(monitorSettings.cssColorFinal && monitorSettings.htmlMonitorSliderRef){ + monitorSettings.htmlMonitorSliderRef.style.backgroundColor = + `color-mix(in srgb, ${monitorSettings.cssColorFinal} ${gpu.gpu_temperature}%, ${monitorSettings.cssColor})`; + } + } else { + // console.error('UpdateAllMonitors: no GPU VRAM data for index', index); + } + }); + }; + + updateMonitor = (monitorSettings: TMonitorSettings, percent: number): void => { + if (!(monitorSettings.htmlMonitorSliderRef && monitorSettings.htmlMonitorLabelRef)) { + return; + } + + monitorSettings.htmlMonitorLabelRef.innerHTML = `${Math.floor(percent)}${monitorSettings.symbol}`; + monitorSettings.htmlMonitorSliderRef.style.width = `${Math.floor(percent)}%`; + }; + + updateAllAnimationDuration = (value: number): void => { + this.updatedAnimationDuration(this.monitorCPUElement, value); + this.updatedAnimationDuration(this.monitorRAMElement, value); + this.updatedAnimationDuration(this.monitorHDDElement, value); + this.monitorGPUSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + this.monitorVRAMSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + this.monitorTemperatureSettings.forEach((monitorSettings) => { + monitorSettings && this.updatedAnimationDuration(monitorSettings, value); + }); + }; + + updatedAnimationDuration = (monitorSettings: TMonitorSettings, value: number): void => { + const slider = monitorSettings.htmlMonitorSliderRef; + if (!slider) { + return; + } + + slider.style.transition = `width ${value.toFixed(1)}s`; + }; + + + createMonitor = (monitorSettings?: TMonitorSettings): HTMLDivElement => { + if (!monitorSettings) { + // just for typescript + return document.createElement('div'); + } + const htmlMain = document.createElement('div'); + htmlMain.setAttribute('id', monitorSettings.id); + htmlMain.classList.add('crystools-monitor'); + monitorSettings.htmlMonitorRef = htmlMain; + + if (monitorSettings.title) { + htmlMain.title = monitorSettings.title; + } + + const htmlMonitorText = document.createElement('div'); + htmlMonitorText.classList.add('crystools-text'); + htmlMonitorText.innerHTML = monitorSettings.label; + htmlMain.append(htmlMonitorText); + + const htmlMonitorContent = document.createElement('div'); + htmlMonitorContent.classList.add('crystools-content'); + htmlMain.append(htmlMonitorContent); + + const htmlMonitorSlider = document.createElement('div'); + htmlMonitorSlider.classList.add('crystools-slider'); + if(monitorSettings.cssColorFinal){ + htmlMonitorSlider.style.backgroundColor = + `color-mix(in srgb, ${monitorSettings.cssColorFinal} 0%, ${monitorSettings.cssColor})`; + } else { + htmlMonitorSlider.style.backgroundColor = monitorSettings.cssColor; + } + monitorSettings.htmlMonitorSliderRef = htmlMonitorSlider; + htmlMonitorContent.append(htmlMonitorSlider); + + const htmlMonitorLabel = document.createElement('div'); + htmlMonitorLabel.classList.add('crystools-label'); + monitorSettings.htmlMonitorLabelRef = htmlMonitorLabel; + htmlMonitorContent.append(htmlMonitorLabel); + htmlMonitorLabel.innerHTML = '0%'; + return monitorSettings.htmlMonitorRef; + }; +} diff --git a/web/progressBar.js b/web/progressBar.js index 07ac324..d064aa6 100644 --- a/web/progressBar.js +++ b/web/progressBar.js @@ -102,7 +102,6 @@ class CrystoolsProgressBar { configurable: true, writable: true, value: (value) => { - console.log('showProgressBar', value, this.newMenu); if (this.newMenu === NewMenuOptions.Disabled) { const container = document.getElementById(this.htmlIdCrystoolsProgressBarContainer); if (container) { @@ -116,7 +115,6 @@ class CrystoolsProgressBar { configurable: true, writable: true, value: () => { - console.log('updateDisplay'); const newMenu = app.ui.settings.getSettingValue('Comfy.UseNewMenu', 'Disabled'); if (newMenu !== this.newMenu) { this.newMenu = newMenu; @@ -125,7 +123,6 @@ class CrystoolsProgressBar { this.setup(); break; default: - console.log('new menu', this.newMenu); } } if (this.newMenu === NewMenuOptions.Disabled) { diff --git a/web/progressBar.ts b/web/progressBar.ts index 797c280..8dbaef9 100644 --- a/web/progressBar.ts +++ b/web/progressBar.ts @@ -41,7 +41,6 @@ class CrystoolsProgressBar { }; showProgressBar = (value: boolean): void => { - console.log('showProgressBar', value, this.newMenu); if (this.newMenu === NewMenuOptions.Disabled) { const container = document.getElementById(this.htmlIdCrystoolsProgressBarContainer); @@ -54,7 +53,6 @@ class CrystoolsProgressBar { }; updateDisplay = (): void => { - console.log('updateDisplay'); const newMenu = app.ui.settings.getSettingValue('Comfy.UseNewMenu', 'Disabled'); if (newMenu !== this.newMenu) { @@ -65,7 +63,7 @@ class CrystoolsProgressBar { this.setup(); break; default: - console.log('new menu', this.newMenu); + // console.log('new menu', this.newMenu); } } diff --git a/web/progressBarUI.js b/web/progressBarUI.js index e78f32e..b9c8562 100644 --- a/web/progressBarUI.js +++ b/web/progressBarUI.js @@ -38,7 +38,6 @@ export class ProgressBarUIBase { value: NewMenuOptions.Disabled }); this.newMenu = app.ui.settings.getSettingValue('Comfy.UseNewMenu', 'Disabled'); - console.log('menu', this.newMenu); if (this.newMenu === NewMenuOptions.Disabled) { this.createRoot(); } @@ -106,7 +105,6 @@ export class ProgressBarUI extends ProgressBarUIBase { configurable: true, writable: true, value: () => { - console.log('create'); const htmlContainer = document.createElement('div'); htmlContainer.setAttribute('id', this.htmlIdCrystoolsProgressBarContainer); htmlContainer.setAttribute('title', 'click to see the current working node'); diff --git a/web/progressBarUI.ts b/web/progressBarUI.ts index ad92368..fdcf220 100644 --- a/web/progressBarUI.ts +++ b/web/progressBarUI.ts @@ -20,11 +20,9 @@ export abstract class ProgressBarUIBase { protected constructor() { this.newMenu = app.ui.settings.getSettingValue('Comfy.UseNewMenu', 'Disabled'); - console.log('menu', this.newMenu); if(this.newMenu === NewMenuOptions.Disabled) { this.createRoot(); } - // window.addEventListener('resize', () => this.refreshDisplay()); } createRoot(): void { @@ -66,7 +64,6 @@ export class ProgressBarUI extends ProgressBarUIBase{ } createDOM = (): void => { - console.log('create'); const htmlContainer = document.createElement('div'); htmlContainer.setAttribute('id', this.htmlIdCrystoolsProgressBarContainer); htmlContainer.setAttribute('title', 'click to see the current working node'); diff --git a/web/types.d.ts b/web/types.d.ts index e1eee71..690086d 100644 --- a/web/types.d.ts +++ b/web/types.d.ts @@ -48,9 +48,10 @@ type TMonitorSettings = { symbol: string, // on monitor title?: string, // on monitor tooltip?: string, // on settings - type: 'boolean' | 'number' | 'string', - defaultValue: boolean, - onChange: (value: boolean) => Promise, + type: 'boolean' | 'number' | 'string' | 'slider' | 'combo', + defaultValue: boolean | number | string, + data?: any, + onChange: (value: boolean | number | string) => Promise, htmlMonitorRef?: HTMLDivElement, htmlMonitorSliderRef?: HTMLDivElement, htmlMonitorLabelRef?: HTMLDivElement,