Spaces:
Running
on
Zero
Running
on
Zero
import { app } from '../../scripts/app.js' | |
import { api } from '../../scripts/api.js' | |
// import * as shared from './comfy_shared.js' | |
import { | |
// defineCSSClass, | |
ensureMTBStyles, | |
makeElement, | |
makeSelect, | |
makeSlider, | |
renderSidebar, | |
} from './mtb_ui.js' | |
let offset = 0 | |
let currentWidth = 200 | |
let currentMode = 'input' | |
let currentSort = 'None' | |
const IMAGE_NODES = ['LoadImage'] | |
const updateImage = (node, image) => { | |
if (IMAGE_NODES.includes(node.type)) { | |
const w = node.widgets?.find((w) => w.name === 'image') | |
if (w) { | |
w.value = image | |
w.callback() | |
} | |
} | |
} | |
const getImgsFromUrls = (urls, target) => { | |
const imgs = [] | |
if (urls === undefined) { | |
return imgs | |
} | |
for (const [key, url] of Object.entries(urls)) { | |
const a = makeElement('img') | |
a.src = url | |
a.width = currentWidth | |
if (currentMode === 'input') { | |
a.onclick = (_e) => { | |
const selected = app.canvas.selected_nodes | |
if (selected && Object.keys(selected).length === 0) { | |
app.extensionManager.toast.add({ | |
severity: 'warn', | |
summary: 'No LoadImage node selected!', | |
detail: | |
'For now the only action when clicking images in the sidebar is to set the image on all selected LoadImage nodes.', | |
life: 5000, | |
}) | |
return | |
} | |
for (const [_id, node] of Object.entries(app.canvas.selected_nodes)) { | |
updateImage(node, `${key}.png`) | |
} | |
} | |
} else { | |
a.onclick = (_e) => | |
// window.MTB?.notify?.("Output import isn't supported yet...", 5000) | |
app.extensionManager.toast.add({ | |
severity: 'warn', | |
summary: 'Outputs not supported', | |
detail: | |
'For now only inputs can be clicked to load the image on the active LoadImage node.', | |
life: 5000, | |
}) | |
} | |
imgs.push(a) | |
} | |
if (target !== undefined) { | |
target.append(...imgs) | |
} | |
return imgs | |
} | |
const getUrls = async () => { | |
const count = await api.getSetting('mtb.io-sidebar.count') | |
console.log('Sidebar count', count) | |
const inputs = await api.fetchApi('/mtb/actions', { | |
method: 'POST', | |
body: JSON.stringify({ | |
name: 'getUserImages', | |
// mode, count, offset | |
args: [currentMode, count, offset, currentSort], | |
}), | |
}) | |
const output = await inputs.json() | |
return output?.result || {} | |
} | |
if (window?.__COMFYUI_FRONTEND_VERSION__) { | |
let handle | |
const version = window?.__COMFYUI_FRONTEND_VERSION__ | |
console.log(`%c ${version}`, 'background: orange; color: white;') | |
ensureMTBStyles() | |
app.ui.settings.addSetting({ | |
id: 'mtb.io-sidebar.count', | |
category: ['mtb', 'Input & Output Sidebar', 'count'], | |
name: 'Number of images to fetch', | |
type: 'number', | |
defaultValue: 1000, | |
tooltip: | |
"This setting affects the input/output sidebar to determine how many images to fetch per pagination (pagination is not yet supported so for now it's the static total)", | |
attrs: { | |
style: { | |
// fontFamily: 'monospace', | |
}, | |
}, | |
}) | |
app.ui.settings.addSetting({ | |
id: 'mtb.io-sidebar.img-size', | |
category: ['mtb', 'Input & Output Sidebar', 'img-size'], | |
name: 'Resolution of the images', | |
type: 'number', | |
defaultValue: 512, | |
tooltip: "It's recommended to keep it at 512px", | |
attrs: { | |
style: { | |
// fontFamily: 'monospace', | |
}, | |
}, | |
}) | |
app.ui.settings.addSetting({ | |
id: 'mtb.io-sidebar.sort', | |
category: ['mtb', 'Input & Output Sidebar', 'sort'], | |
name: 'Default sort mode', | |
type: 'combo', | |
onChange: (v) => { | |
// alert(`Sort is now ${v}`) | |
currentSort = v | |
}, | |
defaultValue: 'Modified', | |
// tooltip: "It's recommended to keep it at 512px", | |
options: ['None', 'Modified', 'Modified-Reverse', 'Name', 'Name-Reverse'], | |
}) | |
app.extensionManager.registerSidebarTab({ | |
id: 'mtb-inputs-outputs', | |
icon: 'pi pi-images', | |
title: 'Input & Outputs', | |
tooltip: 'MTB: Browse inputs and outputs directories.', | |
type: 'custom', | |
// this is run everytime the tab's diplay is toggled on. | |
render: async (el) => { | |
if (handle) { | |
handle.unregister() | |
handle = undefined | |
} | |
if (el.parentNode) { | |
el.parentNode.style.overflowY = 'clip' | |
} | |
const urls = await getUrls(currentMode) | |
let imgs = {} | |
const cont = makeElement('div.mtb_sidebar') | |
const imgGrid = makeElement('div.mtb_img_grid') | |
const selector = makeSelect(['input', 'output'], currentMode) | |
selector.addEventListener('change', async (e) => { | |
const newMode = e.target.value | |
const changed = newMode !== currentMode | |
currentMode = newMode | |
if (changed) { | |
imgGrid.innerHTML = '' | |
const urls = await getUrls() | |
if (urls) { | |
imgs = getImgsFromUrls(urls, imgGrid) | |
} | |
} | |
}) | |
const imgTools = makeElement('div.mtb_tools') | |
const orderSelect = makeSelect( | |
['None', 'Modified', 'Modified-Reverse', 'Name', 'Name-Reverse'], | |
currentSort, | |
) | |
orderSelect.addEventListener('change', async (e) => { | |
const newSort = e.target.value | |
const changed = newSort !== currentSort | |
currentSort = newSort | |
if (changed) { | |
imgGrid.innerHTML = '' | |
const urls = await getUrls() | |
if (urls) { | |
imgs = getImgsFromUrls(urls, imgGrid) | |
} | |
} | |
}) | |
const sizeSlider = makeSlider(64, 1024, currentWidth, 1) | |
imgTools.appendChild(orderSelect) | |
imgTools.appendChild(sizeSlider) | |
imgs = getImgsFromUrls(urls, imgGrid) | |
sizeSlider.addEventListener('input', (e) => { | |
currentWidth = e.target.value | |
for (const img of imgs) { | |
img.style.width = `${e.target.value}px` | |
} | |
}) | |
handle = renderSidebar(el, cont, [selector, imgGrid, imgTools]) | |
}, | |
destroy: () => { | |
if (handle) { | |
handle.unregister() | |
handle = undefined | |
} | |
}, | |
}) | |
} | |