Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Includes 30 custom nodes committed directly, 7 Civitai-exclusive loras stored via Git LFS, and a setup script that installs all dependencies and downloads HuggingFace-hosted models on vast.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
187 lines
5.7 KiB
JavaScript
187 lines
5.7 KiB
JavaScript
export function sleep(ms = 100, value) {
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
resolve(value);
|
|
}, ms);
|
|
});
|
|
}
|
|
export function addPreconnect(href, crossorigin=false){
|
|
const preconnect = document.createElement("link");
|
|
preconnect.rel = 'preconnect'
|
|
preconnect.href = href
|
|
if(crossorigin) preconnect.crossorigin = ''
|
|
document.head.appendChild(preconnect);
|
|
}
|
|
export function addCss(href, base=true) {
|
|
const link = document.createElement("link");
|
|
link.rel = "stylesheet";
|
|
link.type = "text/css";
|
|
link.href = base ? "extensions/ComfyUI-Easy-Use/"+href : href;
|
|
document.head.appendChild(link);
|
|
}
|
|
|
|
export function addMeta(name, content) {
|
|
const meta = document.createElement("meta");
|
|
meta.setAttribute("name", name);
|
|
meta.setAttribute('content', content);
|
|
document.head.appendChild(meta);
|
|
}
|
|
|
|
export function deepEqual(obj1, obj2) {
|
|
if (typeof obj1 !== typeof obj2) {
|
|
return false
|
|
}
|
|
if (typeof obj1 !== 'object' || obj1 === null || obj2 === null) {
|
|
return obj1 === obj2
|
|
}
|
|
const keys1 = Object.keys(obj1)
|
|
const keys2 = Object.keys(obj2)
|
|
if (keys1.length !== keys2.length) {
|
|
return false
|
|
}
|
|
for (let key of keys1) {
|
|
if (!deepEqual(obj1[key], obj2[key])) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
|
|
export function getLocale(){
|
|
const locale = localStorage['AGL.Locale'] || localStorage['Comfy.Settings.AGL.Locale'] || 'en-US'
|
|
return locale
|
|
}
|
|
|
|
export function spliceExtension(fileName){
|
|
return fileName.substring(0,fileName.lastIndexOf('.'))
|
|
}
|
|
export function getExtension(fileName){
|
|
return fileName.substring(fileName.lastIndexOf('.') + 1)
|
|
}
|
|
|
|
export function formatTime(time, format) {
|
|
time = typeof (time) === "number" ? time : (time instanceof Date ? time.getTime() : parseInt(time));
|
|
if (isNaN(time)) return null;
|
|
if (typeof (format) !== 'string' || !format) format = 'yyyy-MM-dd hh:mm:ss';
|
|
let _time = new Date(time);
|
|
time = _time.toString().split(/[\s\:]/g).slice(0, -2);
|
|
time[1] = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'][_time.getMonth()];
|
|
let _mapping = {
|
|
MM: 1,
|
|
dd: 2,
|
|
yyyy: 3,
|
|
hh: 4,
|
|
mm: 5,
|
|
ss: 6
|
|
};
|
|
return format.replace(/([Mmdhs]|y{2})\1/g, (key) => time[_mapping[key]]);
|
|
}
|
|
|
|
|
|
let origProps = {};
|
|
export const findWidgetByName = (node, name) => node.widgets.find((w) => w.name === name);
|
|
|
|
export const doesInputWithNameExist = (node, name) => node.inputs ? node.inputs.some((input) => input.name === name) : false;
|
|
|
|
export function updateNodeHeight(node) {node.setSize([node.size[0], node.computeSize()[1]]);}
|
|
|
|
export function toggleWidget(node, widget, show = false, suffix = "") {
|
|
if (!widget || doesInputWithNameExist(node, widget.name)) return;
|
|
if (!origProps[widget.name]) {
|
|
origProps[widget.name] = { origType: widget.type, origComputeSize: widget.computeSize };
|
|
}
|
|
const origSize = node.size;
|
|
|
|
widget.type = show ? origProps[widget.name].origType : "easyHidden" + suffix;
|
|
widget.computeSize = show ? origProps[widget.name].origComputeSize : () => [0, -4];
|
|
|
|
widget.linkedWidgets?.forEach(w => toggleWidget(node, w, ":" + widget.name, show));
|
|
|
|
const height = show ? Math.max(node.computeSize()[1], origSize[1]) : node.size[1];
|
|
node.setSize([node.size[0], height]);
|
|
}
|
|
|
|
export function isLocalNetwork(ip) {
|
|
const localNetworkRanges = [
|
|
'192.168.',
|
|
'10.',
|
|
'127.',
|
|
/^172\.((1[6-9]|2[0-9]|3[0-1])\.)/
|
|
];
|
|
|
|
return localNetworkRanges.some(range => {
|
|
if (typeof range === 'string') {
|
|
return ip.startsWith(range);
|
|
} else {
|
|
return range.test(ip);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* accAdd 高精度加法
|
|
* @since 1.0.10
|
|
* @param {Number} arg1
|
|
* @param {Number} arg2
|
|
* @return {Number}
|
|
*/
|
|
export function accAdd(arg1, arg2) {
|
|
let r1, r2, s1, s2,max;
|
|
s1 = typeof arg1 == 'string' ? arg1 : arg1.toString()
|
|
s2 = typeof arg2 == 'string' ? arg2 : arg2.toString()
|
|
try { r1 = s1.split(".")[1].length } catch (e) { r1 = 0 }
|
|
try { r2 = s2.split(".")[1].length } catch (e) { r2 = 0 }
|
|
max = Math.pow(10, Math.max(r1, r2))
|
|
return (arg1 * max + arg2 * max) / max
|
|
}
|
|
/**
|
|
* accSub 高精度减法
|
|
* @since 1.0.10
|
|
* @param {Number} arg1
|
|
* @param {Number} arg2
|
|
* @return {Number}
|
|
*/
|
|
export function accSub(arg1, arg2) {
|
|
let r1, r2, max, min,s1,s2;
|
|
s1 = typeof arg1 == 'string' ? arg1 : arg1.toString()
|
|
s2 = typeof arg2 == 'string' ? arg2 : arg2.toString()
|
|
try { r1 = s1.split(".")[1].length } catch (e) { r1 = 0 }
|
|
try { r2 = s2.split(".")[1].length } catch (e) { r2 = 0 }
|
|
max = Math.pow(10, Math.max(r1, r2));
|
|
//动态控制精度长度
|
|
min = (r1 >= r2) ? r1 : r2;
|
|
return ((arg1 * max - arg2 * max) / max).toFixed(min)
|
|
}
|
|
/**
|
|
* accMul 高精度乘法
|
|
* @since 1.0.10
|
|
* @param {Number} arg1
|
|
* @param {Number} arg2
|
|
* @return {Number}
|
|
*/
|
|
export function accMul(arg1, arg2) {
|
|
let max = 0, s1 = typeof arg1 == 'string' ? arg1 : arg1.toString(), s2 = typeof arg2 == 'string' ? arg2 : arg2.toString();
|
|
try { max += s1.split(".")[1].length } catch (e) { }
|
|
try { max += s2.split(".")[1].length } catch (e) { }
|
|
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, max)
|
|
}
|
|
/**
|
|
* accDiv 高精度除法
|
|
* @since 1.0.10
|
|
* @param {Number} arg1
|
|
* @param {Number} arg2
|
|
* @return {Number}
|
|
*/
|
|
export function accDiv(arg1, arg2) {
|
|
let t1 = 0, t2 = 0, r1, r2,s1 = typeof arg1 == 'string' ? arg1 : arg1.toString(), s2 = typeof arg2 == 'string' ? arg2 : arg2.toString();
|
|
try { t1 = s1.toString().split(".")[1].length } catch (e) { }
|
|
try { t2 = s2.toString().split(".")[1].length } catch (e) { }
|
|
r1 = Number(s1.toString().replace(".", ""))
|
|
r2 = Number(s2.toString().replace(".", ""))
|
|
return (r1 / r2) * Math.pow(10, t2 - t1)
|
|
}
|
|
Number.prototype.div = function (arg) {
|
|
return accDiv(this, arg);
|
|
} |