Merge branch 'main' of https://github.com/hayden-fr/ComfyUI-Model-Manager
This commit is contained in:
@@ -205,6 +205,7 @@ def ui_rules():
|
|||||||
Rule("sidebar-control-always-compact", False, bool),
|
Rule("sidebar-control-always-compact", False, bool),
|
||||||
Rule("sidebar-default-width", 0.5, float, 0.0, 1.0),
|
Rule("sidebar-default-width", 0.5, float, 0.0, 1.0),
|
||||||
Rule("sidebar-default-height", 0.5, float, 0.0, 1.0),
|
Rule("sidebar-default-height", 0.5, float, 0.0, 1.0),
|
||||||
|
Rule("sidebar-default-state", "None", str),
|
||||||
Rule("text-input-always-hide-search-button", False, bool),
|
Rule("text-input-always-hide-search-button", False, bool),
|
||||||
Rule("text-input-always-hide-clear-button", False, bool),
|
Rule("text-input-always-hide-clear-button", False, bool),
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 2000; /*needs to be below the dialog modal element*/
|
z-index: 1100; /*needs to be below the dialog modal element*/
|
||||||
|
|
||||||
/*override comfy-modal settings*/
|
/*override comfy-modal settings*/
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@@ -91,6 +91,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: var(--input-text);
|
color: var(--input-text);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
@@ -152,7 +153,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.model-manager button {
|
.model-manager button, .model-manager .model-manager-head .topbar-right select {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 2px solid var(--border-color);
|
border: 2px solid var(--border-color);
|
||||||
}
|
}
|
||||||
@@ -172,6 +173,11 @@
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.model-manager select:hover{
|
||||||
|
filter: brightness(1.2);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.model-manager button.block {
|
.model-manager button.block {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -256,7 +262,7 @@
|
|||||||
.model-manager .model-tab-group {
|
.model-manager .model-tab-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
height: 40px;
|
height: 44px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.model-manager .model-tab-group .tab-button {
|
.model-manager .model-tab-group .tab-button {
|
||||||
@@ -272,6 +278,7 @@
|
|||||||
|
|
||||||
.model-manager .model-tab-group .tab-button.active {
|
.model-manager .model-tab-group .tab-button.active {
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
|
margin-bottom: -2px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@@ -462,7 +469,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.model-manager .comfy-grid .model-label {
|
.model-manager .comfy-grid .model-label {
|
||||||
background-color: rgb(from var(--content-hover-bg) r g b / 0.5);
|
background-color: rgb(from var(--content-hover-bg) r g b / 0.6);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2.2rem;
|
height: 2.2rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -600,7 +607,8 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
|
text-align-last: center;
|
||||||
-o-appearance: none;
|
-o-appearance: none;
|
||||||
-ms-appearance: none;
|
-ms-appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
@@ -701,7 +709,7 @@
|
|||||||
|
|
||||||
.model-manager .model-manager-settings input[type="number"],
|
.model-manager .model-manager-settings input[type="number"],
|
||||||
.model-manager .tag-generator-settings input[type="number"]{
|
.model-manager .tag-generator-settings input[type="number"]{
|
||||||
width: 50px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.model-manager .search-settings-text {
|
.model-manager .search-settings-text {
|
||||||
|
|||||||
@@ -97,35 +97,8 @@ class KeyComboListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// This is used in Firefox to bypass the ‘dragend’ event because it returns incorrect ‘clientX’ and ‘clientY’
|
||||||
* Handles Firefox's drag event, which returns different coordinates and then fails when calling `elementFromPoint`.
|
const IS_FIREFOX = navigator.userAgent.indexOf('Firefox') > -1;
|
||||||
* @param {DragEvent} event
|
|
||||||
* @returns {[Number, Number, HTMLElement]} [clientX, clientY, targetElement]
|
|
||||||
*/
|
|
||||||
function elementFromDragEvent(event) {
|
|
||||||
let clientX = null;
|
|
||||||
let clientY = null;
|
|
||||||
let target;
|
|
||||||
const userAgentString = navigator.userAgent;
|
|
||||||
if (userAgentString.indexOf('Firefox') > -1) {
|
|
||||||
clientX = event.clientX;
|
|
||||||
clientY = event.clientY;
|
|
||||||
const screenOffsetX = window.screenLeft;
|
|
||||||
if (clientX >= screenOffsetX) {
|
|
||||||
clientX = clientX - screenOffsetX;
|
|
||||||
}
|
|
||||||
const screenOffsetY = window.screenTop;
|
|
||||||
if (clientY >= screenOffsetY) {
|
|
||||||
clientY = clientY - screenOffsetY;
|
|
||||||
}
|
|
||||||
target = document.elementFromPoint(clientX, clientY);
|
|
||||||
} else {
|
|
||||||
clientX = event.clientX;
|
|
||||||
clientY = event.clientY;
|
|
||||||
target = document.elementFromPoint(event.clientX, event.clientY);
|
|
||||||
}
|
|
||||||
return [clientX, clientY, target];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} url
|
* @param {string} url
|
||||||
@@ -1970,20 +1943,16 @@ class ModelGrid {
|
|||||||
* @param {boolean} removeEmbeddingExtension
|
* @param {boolean} removeEmbeddingExtension
|
||||||
* @param {boolean} strictlyOnWidget
|
* @param {boolean} strictlyOnWidget
|
||||||
*/
|
*/
|
||||||
static #dragAddModel(
|
static dragAddModel(
|
||||||
event,
|
event,
|
||||||
modelType,
|
modelType,
|
||||||
path,
|
path,
|
||||||
removeEmbeddingExtension,
|
removeEmbeddingExtension,
|
||||||
strictlyOnWidget,
|
strictlyOnWidget,
|
||||||
) {
|
) {
|
||||||
const [clientX, clientY, target] = elementFromDragEvent(event);
|
const target = document.elementFromPoint(event.clientX, event.clientY);
|
||||||
if (modelType !== 'embeddings' && target.id === 'graph-canvas') {
|
if (modelType !== 'embeddings' && target.id === 'graph-canvas') {
|
||||||
//const pos = app.canvas.convertEventToCanvasOffset(event);
|
const pos = app.canvas.convertEventToCanvasOffset(event);
|
||||||
const pos = app.canvas.convertEventToCanvasOffset({
|
|
||||||
clientX: clientX,
|
|
||||||
clientY: clientY,
|
|
||||||
});
|
|
||||||
|
|
||||||
const node = app.graph.getNodeOnPos(
|
const node = app.graph.getNodeOnPos(
|
||||||
pos[0],
|
pos[0],
|
||||||
@@ -2152,6 +2121,47 @@ class ModelGrid {
|
|||||||
const previewThumbnailFormat =
|
const previewThumbnailFormat =
|
||||||
settingsElements['model-preview-thumbnail-type'].value;
|
settingsElements['model-preview-thumbnail-type'].value;
|
||||||
if (models.length > 0) {
|
if (models.length > 0) {
|
||||||
|
|
||||||
|
const $overlay = IS_FIREFOX
|
||||||
|
? ((
|
||||||
|
modelType,
|
||||||
|
path,
|
||||||
|
removeEmbeddingExtension,
|
||||||
|
strictDragToAdd,
|
||||||
|
) => {
|
||||||
|
return $el('div.model-preview-overlay', {
|
||||||
|
ondragstart: (e) =>{
|
||||||
|
const data = {
|
||||||
|
modelType: modelType,
|
||||||
|
path: path,
|
||||||
|
removeEmbeddingExtension: removeEmbeddingExtension,
|
||||||
|
strictDragToAdd: strictDragToAdd,
|
||||||
|
};
|
||||||
|
e.dataTransfer.setData('manager-model', JSON.stringify(data));
|
||||||
|
e.dataTransfer.setData('text/plain', '');
|
||||||
|
},
|
||||||
|
draggable: true,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
: ((
|
||||||
|
modelType,
|
||||||
|
path,
|
||||||
|
removeEmbeddingExtension,
|
||||||
|
strictDragToAdd,
|
||||||
|
) => {
|
||||||
|
return $el('div.model-preview-overlay', {
|
||||||
|
ondragend: (e) =>
|
||||||
|
ModelGrid.dragAddModel(
|
||||||
|
e,
|
||||||
|
modelType,
|
||||||
|
path,
|
||||||
|
removeEmbeddingExtension,
|
||||||
|
strictDragToAdd,
|
||||||
|
),
|
||||||
|
draggable: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return models.map((item) => {
|
return models.map((item) => {
|
||||||
const previewInfo = item.preview;
|
const previewInfo = item.preview;
|
||||||
const previewThumbnail = $el('img.model-preview', {
|
const previewThumbnail = $el('img.model-preview', {
|
||||||
@@ -2262,20 +2272,14 @@ class ModelGrid {
|
|||||||
},
|
},
|
||||||
}).element,
|
}).element,
|
||||||
];
|
];
|
||||||
const dragAdd = (e) =>
|
return $el('div.item', {}, [
|
||||||
ModelGrid.#dragAddModel(
|
previewThumbnail,
|
||||||
e,
|
$overlay(
|
||||||
modelType,
|
modelType,
|
||||||
path,
|
path,
|
||||||
removeEmbeddingExtension,
|
removeEmbeddingExtension,
|
||||||
strictDragToAdd,
|
strictDragToAdd,
|
||||||
);
|
),
|
||||||
return $el('div.item', {}, [
|
|
||||||
previewThumbnail,
|
|
||||||
$el('div.model-preview-overlay', {
|
|
||||||
ondragend: (e) => dragAdd(e),
|
|
||||||
draggable: true,
|
|
||||||
}),
|
|
||||||
$el(
|
$el(
|
||||||
'div.model-preview-top-right',
|
'div.model-preview-top-right',
|
||||||
{
|
{
|
||||||
@@ -4644,6 +4648,9 @@ class SettingsView {
|
|||||||
/** @return {() => Promise<void>} */
|
/** @return {() => Promise<void>} */
|
||||||
#updateModels = async () => {};
|
#updateModels = async () => {};
|
||||||
|
|
||||||
|
/** @return {() => void} */
|
||||||
|
#updateSidebarSettings = () => {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} settingsData
|
* @param {Object} settingsData
|
||||||
* @param {boolean} updateModels
|
* @param {boolean} updateModels
|
||||||
@@ -4677,6 +4684,8 @@ class SettingsView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.#updateSidebarSettings(settings);
|
||||||
|
|
||||||
if (updateModels) {
|
if (updateModels) {
|
||||||
await this.#updateModels(); // Is this slow?
|
await this.#updateModels(); // Is this slow?
|
||||||
}
|
}
|
||||||
@@ -4741,9 +4750,11 @@ class SettingsView {
|
|||||||
/**
|
/**
|
||||||
* @param {() => Promise<void>} updateModels
|
* @param {() => Promise<void>} updateModels
|
||||||
* @param {() => void} updateSidebarButtons
|
* @param {() => void} updateSidebarButtons
|
||||||
|
* @param {(settings: Object) => void} updateSidebarSettings
|
||||||
*/
|
*/
|
||||||
constructor(updateModels, updateSidebarButtons) {
|
constructor(updateModels, updateSidebarButtons, updateSidebarSettings) {
|
||||||
this.#updateModels = updateModels;
|
this.#updateModels = updateModels;
|
||||||
|
this.#updateSidebarSettings = updateSidebarSettings;
|
||||||
const settings = this.elements.settings;
|
const settings = this.elements.settings;
|
||||||
|
|
||||||
const sidebarControl = $checkbox({
|
const sidebarControl = $checkbox({
|
||||||
@@ -4851,6 +4862,7 @@ class SettingsView {
|
|||||||
{
|
{
|
||||||
style: { color: 'var(--fg-color)' },
|
style: { color: 'var(--fg-color)' },
|
||||||
href: 'https://github.com/hayden-fr/ComfyUI-Model-Manager/issues/',
|
href: 'https://github.com/hayden-fr/ComfyUI-Model-Manager/issues/',
|
||||||
|
target: '_blank',
|
||||||
},
|
},
|
||||||
['File bugs and issues here.'],
|
['File bugs and issues here.'],
|
||||||
),
|
),
|
||||||
@@ -4886,6 +4898,11 @@ class SettingsView {
|
|||||||
'vae_approx',
|
'vae_approx',
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
$select({
|
||||||
|
$: (el) => (settings['sidebar-default-state'] = el),
|
||||||
|
textContent: 'Default model manager position (on start up)',
|
||||||
|
options: ['Left', 'Right', 'Top', 'Bottom', 'None'],
|
||||||
|
}),
|
||||||
$checkbox({
|
$checkbox({
|
||||||
$: (el) => (settings['model-real-time-search'] = el),
|
$: (el) => (settings['model-real-time-search'] = el),
|
||||||
textContent: 'Real-time search',
|
textContent: 'Real-time search',
|
||||||
@@ -5119,6 +5136,7 @@ function GenerateSidebarToggleRadioAndSelect(labels, activationCallbacks = []) {
|
|||||||
'select',
|
'select',
|
||||||
{
|
{
|
||||||
name: 'sidebar-select',
|
name: 'sidebar-select',
|
||||||
|
classList: 'icon-button',
|
||||||
onchange: (event) => {
|
onchange: (event) => {
|
||||||
const select = event.target;
|
const select = event.target;
|
||||||
const children = select.children;
|
const children = select.children;
|
||||||
@@ -5197,9 +5215,7 @@ function GenerateSidebarToggleRadioAndSelect(labels, activationCallbacks = []) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
radioButtonGroup.append.apply(radioButtonGroup, buttons);
|
radioButtonGroup.append.apply(radioButtonGroup, buttons);
|
||||||
buttons[0].click();
|
|
||||||
buttons[0].style.display = 'none';
|
buttons[0].style.display = 'none';
|
||||||
|
|
||||||
return [radioButtonGroup, select];
|
return [radioButtonGroup, select];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5256,6 +5272,7 @@ class ModelManager extends ComfyDialog {
|
|||||||
|
|
||||||
this.#settingsView = new SettingsView(this.#refreshModels, () =>
|
this.#settingsView = new SettingsView(this.#refreshModels, () =>
|
||||||
this.#updateSidebarButtons(),
|
this.#updateSidebarButtons(),
|
||||||
|
this.#updateSidebarSettings,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.#modelInfo = new ModelInfo(
|
this.#modelInfo = new ModelInfo(
|
||||||
@@ -5306,11 +5323,7 @@ class ModelManager extends ComfyDialog {
|
|||||||
['◼', '◨', '⬒', '⬓', '◧'],
|
['◼', '◨', '⬒', '⬓', '◧'],
|
||||||
[
|
[
|
||||||
() => {
|
() => {
|
||||||
const element = this.element;
|
this.element.dataset['sidebarState'] = 'none';
|
||||||
if (element) {
|
|
||||||
// callback on initialization as default state
|
|
||||||
element.dataset['sidebarState'] = 'none';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.element.dataset['sidebarState'] = 'right';
|
this.element.dataset['sidebarState'] = 'right';
|
||||||
@@ -5631,6 +5644,20 @@ class ModelManager extends ComfyDialog {
|
|||||||
updateDragSidebar(e, e.touches[0].clientX, e.touches[0].clientY),
|
updateDragSidebar(e, e.touches[0].clientX, e.touches[0].clientY),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(IS_FIREFOX){
|
||||||
|
app.canvasContainer.addEventListener('drop', (e) => {
|
||||||
|
if (e.dataTransfer.types.includes('manager-model')){
|
||||||
|
const data = JSON.parse(e.dataTransfer.getData('manager-model'));
|
||||||
|
ModelGrid.dragAddModel(
|
||||||
|
e,
|
||||||
|
data.modelType,
|
||||||
|
data.path,
|
||||||
|
data.removeEmbeddingExtension,
|
||||||
|
data.strictDragToAdd,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
this.#init();
|
this.#init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5641,16 +5668,19 @@ class ModelManager extends ComfyDialog {
|
|||||||
const settings = this.#settingsView.elements.settings;
|
const settings = this.#settingsView.elements.settings;
|
||||||
|
|
||||||
{
|
{
|
||||||
// initialize buttons' visibility state
|
// set initial sidebar state
|
||||||
const hideSearchButtons =
|
const newSidebarState = settings['sidebar-default-state'].value;
|
||||||
settings['text-input-always-hide-search-button'].checked;
|
let buttonNumb = 0;
|
||||||
const hideClearSearchButtons =
|
if (newSidebarState === 'Right') {
|
||||||
settings['text-input-always-hide-clear-button'].checked;
|
buttonNumb = 1;
|
||||||
this.#downloadView.elements.searchButton.style.display = hideSearchButtons
|
} else if (newSidebarState === 'Top') {
|
||||||
? 'none'
|
buttonNumb = 2;
|
||||||
: '';
|
} else if (newSidebarState === 'Bottom') {
|
||||||
this.#downloadView.elements.clearSearchButton.style.display =
|
buttonNumb = 3;
|
||||||
hideClearSearchButtons ? 'none' : '';
|
} else if (newSidebarState === 'Left') {
|
||||||
|
buttonNumb = 4;
|
||||||
|
}
|
||||||
|
this.#sidebarButtonGroup.children[buttonNumb].click();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -5695,6 +5725,21 @@ class ModelManager extends ComfyDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#updateSidebarSettings = (settings) => {
|
||||||
|
{
|
||||||
|
// update buttons' visibility state
|
||||||
|
const hideSearchButtons =
|
||||||
|
settings['text-input-always-hide-search-button'].checked;
|
||||||
|
const hideClearSearchButtons =
|
||||||
|
settings['text-input-always-hide-clear-button'].checked;
|
||||||
|
this.#downloadView.elements.searchButton.style.display = hideSearchButtons
|
||||||
|
? 'none'
|
||||||
|
: '';
|
||||||
|
this.#downloadView.elements.clearSearchButton.style.display =
|
||||||
|
hideClearSearchButtons ? 'none' : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#resetManagerContentsScroll = () => {
|
#resetManagerContentsScroll = () => {
|
||||||
this.#tabManagerContents.scrollTop = 0;
|
this.#tabManagerContents.scrollTop = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user