import {app} from "../../../../scripts/app.js"; import {api} from "../../../../scripts/api.js"; import {$el} from "../../../../scripts/ui.js"; import {$t} from "../common/i18n.js"; import {getExtension, spliceExtension} from '../common/utils.js' import {toast} from "../common/toast.js"; const setting_id = "Comfy.EasyUse.MenuNestSub" let enableMenuNestSub = false let thumbnails = [] export function addMenuNestSubSetting(app) { app.ui.settings.addSetting({ id: setting_id, name: $t("Enable ContextMenu Auto Nest Subdirectories (ComfyUI-Easy-Use)"), type: "boolean", defaultValue: enableMenuNestSub, onChange(value) { enableMenuNestSub = !!value; }, }); } const getEnableMenuNestSub = _ => app.ui.settings.getSettingValue(setting_id, enableMenuNestSub) const Loaders = ['easy fullLoader','easy a1111Loader','easy comfyLoader'] app.registerExtension({ name:"comfy.easyUse.contextMenu", async setup(app){ addMenuNestSubSetting(app) // 获取所有模型图像 const imgRes = await api.fetchApi(`/easyuse/models/thumbnail`) if (imgRes.status === 200) { let data = await imgRes.json(); thumbnails = data } else if(getEnableMenuNestSub()){ toast.error($t("Too many thumbnails, have closed the display")) } const existingContextMenu = LiteGraph.ContextMenu; LiteGraph.ContextMenu = function(values,options){ const threshold = 10; const enabled = getEnableMenuNestSub(); if(!enabled || (values?.length || 0) <= threshold || !(options?.callback) || values.some(i => typeof i !== 'string')){ if(enabled){ // console.log('Skipping context menu auto nesting for incompatible menu.'); } return existingContextMenu.apply(this,[...arguments]); } const compatValues = values; const originalValues = [...compatValues]; const folders = {}; const specialOps = []; const folderless = []; for(const value of compatValues){ const splitBy = value.indexOf('/') > -1 ? '/' : '\\'; const valueSplit = value.split(splitBy); if(valueSplit.length > 1){ const key = valueSplit.shift(); folders[key] = folders[key] || []; folders[key].push(valueSplit.join(splitBy)); }else if(value === 'CHOOSE' || value.startsWith('DISABLE ')){ specialOps.push(value); }else{ folderless.push(value); } } const foldersCount = Object.values(folders).length; if(foldersCount > 0){ const oldcallback = options.callback; options.callback = null; const newCallback = (item,options) => { if(['None','无','無','なし'].includes(item.content)) oldcallback('None',options) else oldcallback(originalValues.find(i => i.endsWith(item.content),options)); }; const addContent = (content, folderName='') => { const name = folderName ? folderName + '\\' + spliceExtension(content) : spliceExtension(content); const ext = getExtension(content) const time = new Date().getTime() let thumbnail = '' if(['ckpt', 'pt', 'bin', 'pth', 'safetensors'].includes(ext)){ for(let i=0;i { let subs = [] let less = [] const b = folder.map(name=> { const _folders = {}; const splitBy = name.indexOf('/') > -1 ? '/' : '\\'; const valueSplit = name.split(splitBy); if(valueSplit.length > 1){ const key = valueSplit.shift(); _folders[key] = _folders[key] || []; _folders[key].push(valueSplit.join(splitBy)); } const foldersCount = Object.values(folders).length; if(foldersCount > 0){ let key = Object.keys(_folders)[0] if(key && _folders[key]) subs.push({key, value:_folders[key][0]}) else{ less.push(addContent(name,key)) } } return addContent(name,folderName) }) if(subs.length>0){ let subs_obj = {} subs.forEach(item => { subs_obj[item.key] = subs_obj[item.key] || [] subs_obj[item.key].push(item.value) }) return [...Object.entries(subs_obj).map(f => { return { content: f[0], has_submenu: true, callback: () => {}, submenu: { options: add_sub_folder(f[1], f[0]), } } }),...less] } else return b } for(const [folderName,folder] of Object.entries(folders)){ newValues.push({ content:folderName, has_submenu:true, callback:() => {}, submenu:{ options:add_sub_folder(folder,folderName), } }); } newValues.push(...folderless.map(f => addContent(f, ''))); if(specialOps.length > 0) newValues.push(...specialOps.map(f => addContent(f, ''))); return existingContextMenu.call(this,newValues,options); } return existingContextMenu.apply(this,[...arguments]); } LiteGraph.ContextMenu.prototype = existingContextMenu.prototype; }, })