This commit is contained in:
Christian Bastian
2024-09-23 23:15:32 -04:00
3 changed files with 102 additions and 33 deletions

View File

@@ -187,12 +187,15 @@ def ui_rules():
Rule("model-preview-thumbnail-type", "AUTO", str), Rule("model-preview-thumbnail-type", "AUTO", str),
Rule("model-preview-fallback-search-safetensors-thumbnail", False, bool), Rule("model-preview-fallback-search-safetensors-thumbnail", False, bool),
Rule("model-preview-thumbnail-width", 240, int, 150, 480),
Rule("model-preview-thumbnail-height", 360, int, 185, 480),
Rule("model-show-label-extensions", False, bool), Rule("model-show-label-extensions", False, bool),
Rule("model-show-add-button", True, bool), Rule("model-show-add-button", True, bool),
Rule("model-show-copy-button", True, bool), Rule("model-show-copy-button", True, bool),
Rule("model-show-load-workflow-button", True, bool), Rule("model-show-load-workflow-button", True, bool),
Rule("model-show-open-model-url-button", False, bool), Rule("model-show-open-model-url-button", False, bool),
Rule("model-info-button-on-left", False, bool), Rule("model-info-button-on-left", False, bool),
Rule("model-buttons-only-on-hover", False, bool),
Rule("model-add-embedding-extension", False, bool), Rule("model-add-embedding-extension", False, bool),
Rule("model-add-drag-strict-on-field", False, bool), Rule("model-add-drag-strict-on-field", False, bool),

View File

@@ -55,6 +55,9 @@
--model-manager-sidebar-height-top: 50vh; --model-manager-sidebar-height-top: 50vh;
--model-manager-sidebar-height-bottom: 50vh; --model-manager-sidebar-height-bottom: 50vh;
--model-manager-thumbnail-width: 240px;
--model-manager-thumbnail-height: 360px;
--model-manager-left: 0; --model-manager-left: 0;
--model-manager-right: 0; --model-manager-right: 0;
--model-manager-top: 0; --model-manager-top: 0;
@@ -407,8 +410,8 @@
/* preview image */ /* preview image */
.model-manager .item { .model-manager .item {
position: relative; position: relative;
width: 240px; width: var(--model-manager-thumbnail-width);;
height: 360px; height: var(--model-manager-thumbnail-height);;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;
border-radius: 8px; border-radius: 8px;
@@ -500,7 +503,6 @@
.model-manager .comfy-grid .model-preview-top-right, .model-manager .comfy-grid .model-preview-top-right,
.model-manager .comfy-grid .model-preview-top-left { .model-manager .comfy-grid .model-preview-top-left {
position: absolute; position: absolute;
display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
top: 8px; top: 8px;
@@ -514,6 +516,15 @@
left: 8px; left: 8px;
} }
.model-manager .item .model-buttons-hidden {
display: none;
}
.model-manager .item:hover .model-buttons-hidden,
.model-manager .comfy-grid .model-buttons-visible {
display: flex;
}
.model-manager .comfy-grid .model-button { .model-manager .comfy-grid .model-button {
opacity: 0.65; opacity: 0.65;
} }

View File

@@ -312,8 +312,6 @@ class SearchPath {
return uri; return uri;
} }
const PREVIEW_NONE_URI = imageUri(); const PREVIEW_NONE_URI = imageUri();
const PREVIEW_THUMBNAIL_WIDTH = 320;
const PREVIEW_THUMBNAIL_HEIGHT = 480;
/** /**
* *
@@ -2132,6 +2130,12 @@ class ModelGrid {
!settingsElements['model-add-embedding-extension'].checked; !settingsElements['model-add-embedding-extension'].checked;
const previewThumbnailFormat = const previewThumbnailFormat =
settingsElements['model-preview-thumbnail-type'].value; settingsElements['model-preview-thumbnail-type'].value;
const previewThumbnailWidth =
Math.round(settingsElements['model-preview-thumbnail-width'].value / 0.75);
const previewThumbnailHeight =
Math.round(settingsElements['model-preview-thumbnail-height'].value / 0.75);
const buttonsOnlyOnHover =
settingsElements['model-buttons-only-on-hover'].checked;
if (models.length > 0) { if (models.length > 0) {
const $overlay = IS_FIREFOX const $overlay = IS_FIREFOX
@@ -2173,6 +2177,8 @@ class ModelGrid {
draggable: true, draggable: true,
}); });
}); });
const forHiddingButtonsClass = buttonsOnlyOnHover
? 'model-buttons-hidden' : 'model-buttons-visible';
return models.map((item) => { return models.map((item) => {
const previewInfo = item.preview; const previewInfo = item.preview;
@@ -2182,8 +2188,8 @@ class ModelGrid {
src: imageUri( src: imageUri(
previewInfo?.path ? encodeURIComponent(previewInfo.path) : undefined, previewInfo?.path ? encodeURIComponent(previewInfo.path) : undefined,
previewInfo?.dateModified ? encodeURIComponent(previewInfo.dateModified) : undefined, previewInfo?.dateModified ? encodeURIComponent(previewInfo.dateModified) : undefined,
PREVIEW_THUMBNAIL_WIDTH, previewThumbnailWidth,
PREVIEW_THUMBNAIL_HEIGHT, previewThumbnailHeight,
previewThumbnailFormat, previewThumbnailFormat,
), ),
draggable: false, draggable: false,
@@ -2293,14 +2299,14 @@ class ModelGrid {
strictDragToAdd, strictDragToAdd,
), ),
$el( $el(
'div.model-preview-top-right', 'div.model-preview-top-right.' + forHiddingButtonsClass,
{ {
draggable: false, draggable: false,
}, },
modelInfoButtonOnLeft ? infoButtons : actionButtons, modelInfoButtonOnLeft ? infoButtons : actionButtons,
), ),
$el( $el(
'div.model-preview-top-left', 'div.model-preview-top-left.' + forHiddingButtonsClass,
{ {
draggable: false, draggable: false,
}, },
@@ -2432,7 +2438,7 @@ class ModelInfo {
/** /**
* @param {ModelData} modelData * @param {ModelData} modelData
* @param {() => Promise<void>} updateModels * @param {(withoutComfyRefresh?: boolean) => Promise<void>} updateModels
* @param {any} settingsElements * @param {any} settingsElements
* @param {() => Promise<void>} tryHideModelInfo * @param {() => Promise<void>} tryHideModelInfo
*/ */
@@ -2511,7 +2517,7 @@ class ModelInfo {
}); });
} }
if (updatedPreview) { if (updatedPreview) {
updateModels(); updateModels(true);
const previewSelect = this.previewSelect; const previewSelect = this.previewSelect;
previewSelect.elements.defaultUrl.dataset.noimage = previewSelect.elements.defaultUrl.dataset.noimage =
PREVIEW_NONE_URI; PREVIEW_NONE_URI;
@@ -2734,7 +2740,7 @@ class ModelInfo {
/** /**
* @param {string} searchPath * @param {string} searchPath
* @param {() => Promise<void>} updateModels * @param {(withoutComfyRefresh?: boolean) => Promise<void>} updateModels
* @param {string} searchSeparator * @param {string} searchSeparator
*/ */
async update(searchPath, updateModels, searchSeparator) { async update(searchPath, updateModels, searchSeparator) {
@@ -3901,13 +3907,13 @@ class DownloadView {
/** @type {Object.<string, HTMLElement>} */ /** @type {Object.<string, HTMLElement>} */
#settings = null; #settings = null;
/** @type {() => Promise<void>} */ /** @type {(withoutComfyRefresh?: boolean) => Promise<void>} */
#updateModels = () => {}; #updateModels = () => {};
/** /**
* @param {ModelData} modelData * @param {ModelData} modelData
* @param {Object.<string, HTMLElement>} settings * @param {Object.<string, HTMLElement>} settings
* @param {() => Promise<void>} updateModels * @param {(withoutComfyRefresh?: boolean) => Promise<void>} updateModels
*/ */
constructor(modelData, settings, updateModels) { constructor(modelData, settings, updateModels) {
this.#domParser = new DOMParser(); this.#domParser = new DOMParser();
@@ -4383,7 +4389,7 @@ class BrowseView {
/** @type {ModelData} */ /** @type {ModelData} */
#modelData = null; #modelData = null;
/** @type {@param {() => Promise<void>}} */ /** @type {(withoutComfyRefresh?: boolean) => Promise<void>} */
#updateModels = null; #updateModels = null;
/** */ /** */
@@ -4393,7 +4399,7 @@ class BrowseView {
updateModelGrid = () => {}; updateModelGrid = () => {};
/** /**
* @param {() => Promise<void>} updateModels * @param {(withoutComfyRefresh?: boolean) => Promise<void>} updateModels
* @param {ModelData} modelData * @param {ModelData} modelData
* @param {(searchPath: string) => Promise<void>} showModelInfo * @param {(searchPath: string) => Promise<void>} showModelInfo
* @param {() => void} updateModelGridCallback * @param {() => void} updateModelGridCallback
@@ -4625,6 +4631,8 @@ class SettingsView {
/** @type {HTMLInputElement} */ 'model-persistent-search': null, /** @type {HTMLInputElement} */ 'model-persistent-search': null,
/** @type {HTMLInputElement} */ 'model-preview-thumbnail-type': null, /** @type {HTMLInputElement} */ 'model-preview-thumbnail-type': null,
/** @type {HTMLInputElement} */ 'model-preview-thumbnail-width': null,
/** @type {HTMLInputElement} */ 'model-preview-thumbnail-height': null,
/** @type {HTMLInputElement} */ 'model-preview-fallback-search-safetensors-thumbnail': /** @type {HTMLInputElement} */ 'model-preview-fallback-search-safetensors-thumbnail':
null, null,
/** @type {HTMLInputElement} */ 'model-show-label-extensions': null, /** @type {HTMLInputElement} */ 'model-show-label-extensions': null,
@@ -4633,6 +4641,7 @@ class SettingsView {
/** @type {HTMLInputElement} */ 'model-show-load-workflow-button': null, /** @type {HTMLInputElement} */ 'model-show-load-workflow-button': null,
/** @type {HTMLInputElement} */ 'model-show-open-model-url-button': null, /** @type {HTMLInputElement} */ 'model-show-open-model-url-button': null,
/** @type {HTMLInputElement} */ 'model-info-button-on-left': null, /** @type {HTMLInputElement} */ 'model-info-button-on-left': null,
/** @type {HTMLInputElement} */ 'model-buttons-only-on-hover': null,
/** @type {HTMLInputElement} */ 'model-add-embedding-extension': null, /** @type {HTMLInputElement} */ 'model-add-embedding-extension': null,
/** @type {HTMLInputElement} */ 'model-add-drag-strict-on-field': null, /** @type {HTMLInputElement} */ 'model-add-drag-strict-on-field': null,
@@ -4657,7 +4666,7 @@ class SettingsView {
}, },
}; };
/** @return {() => Promise<void>} */ /** @return {(withoutComfyRefresh?: boolean) => Promise<void>} */
#updateModels = async () => {}; #updateModels = async () => {};
/** @return {() => void} */ /** @return {() => void} */
@@ -4665,9 +4674,9 @@ class SettingsView {
/** /**
* @param {Object} settingsData * @param {Object} settingsData
* @param {boolean} updateModels * @param {boolean} withoutComfyRefresh
*/ */
async #setSettings(settingsData, updateModels) { async #setSettings(settingsData, withoutComfyRefresh) {
const settings = this.elements.settings; const settings = this.elements.settings;
for (const [key, value] of Object.entries(settingsData)) { for (const [key, value] of Object.entries(settingsData)) {
const setting = settings[key]; const setting = settings[key];
@@ -4695,22 +4704,18 @@ class SettingsView {
console.warn(`Unknown settings input type '${type}'!`); console.warn(`Unknown settings input type '${type}'!`);
} }
} }
this.#updateSidebarSettings(settings); this.#updateSidebarSettings(settings);
await this.#updateModels(withoutComfyRefresh);
if (updateModels) {
await this.#updateModels(); // Is this slow?
}
} }
/** /**
* @param {boolean} updateModels * @param {boolean} withoutComfyRefresh
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async reload(updateModels) { async reload(withoutComfyRefresh) {
const data = await comfyRequest('/model-manager/settings/load'); const data = await comfyRequest('/model-manager/settings/load');
const settingsData = data['settings']; const settingsData = data['settings'];
await this.#setSettings(settingsData, updateModels); await this.#setSettings(settingsData, withoutComfyRefresh);
comfyButtonAlert(this.elements.reloadButton, true); comfyButtonAlert(this.elements.reloadButton, true);
} }
@@ -4760,7 +4765,7 @@ class SettingsView {
} }
/** /**
* @param {() => Promise<void>} updateModels * @param {(withoutComfyRefresh?: boolean) => Promise<void>} updateModels
* @param {() => void} updateSidebarButtons * @param {() => void} updateSidebarButtons
* @param {(settings: Object) => void} updateSidebarSettings * @param {(settings: Object) => void} updateSidebarSettings
*/ */
@@ -4956,6 +4961,34 @@ class SettingsView {
textContent: 'Preview thumbnail type', textContent: 'Preview thumbnail type',
options: ['AUTO', 'JPEG'], // should use AUTO to avoid artifacts from changing between formats; use JPEG for backward compatibility options: ['AUTO', 'JPEG'], // should use AUTO to avoid artifacts from changing between formats; use JPEG for backward compatibility
}), }),
$el('label', [
'Preview thumbnail width',
$el('input', {
$: (el) => (settings['model-preview-thumbnail-width'] = el),
type: 'range',
name: 'default thumbnail width',
value: 240,
min: 150,
max: 480,
step: 5,
oninput: function(){ this.nextElementSibling.textContent = this.value + 'px'},
}),
$el('span'),
]),
$el('label', [
'Preview thumbnail height',
$el('input', {
$: (el) => (settings['model-preview-thumbnail-height'] = el),
type: 'range',
name: 'default thumbnail height',
value: 360,
min: 185,
max: 480,
step: 5,
oninput: function(){ this.nextElementSibling.textContent = this.value + 'px'},
}),
$el('span'),
]),
$checkbox({ $checkbox({
$: (el) => $: (el) =>
(settings['model-preview-fallback-search-safetensors-thumbnail'] = (settings['model-preview-fallback-search-safetensors-thumbnail'] =
@@ -4985,6 +5018,10 @@ class SettingsView {
$: (el) => (settings['model-info-button-on-left'] = el), $: (el) => (settings['model-info-button-on-left'] = el),
textContent: '"Model Info" button on left', textContent: '"Model Info" button on left',
}), }),
$checkbox({
$: (el) => (settings['model-buttons-only-on-hover'] = el),
textContent: 'Show buttons on hover only',
}),
$el('h2', ['Node Graph']), $el('h2', ['Node Graph']),
$checkbox({ $checkbox({
$: (el) => (settings['model-add-embedding-extension'] = el), $: (el) => (settings['model-add-embedding-extension'] = el),
@@ -5707,8 +5744,7 @@ class ModelManager extends ComfyDialog {
} }
async #init() { async #init() {
await this.#settingsView.reload(false); await this.#settingsView.reload(true)
await this.#refreshModels();
const settings = this.#settingsView.elements.settings; const settings = this.#settingsView.elements.settings;
@@ -5783,13 +5819,31 @@ class ModelManager extends ComfyDialog {
this.#downloadView.elements.clearSearchButton.style.display = this.#downloadView.elements.clearSearchButton.style.display =
hideClearSearchButtons ? 'none' : ''; hideClearSearchButtons ? 'none' : '';
} }
{
// update thumbnail widths & heights
const thumbnailWidthEl = settings['model-preview-thumbnail-width'];
const thumbnailHeightEl = settings['model-preview-thumbnail-height'];
this.element.style.setProperty(
'--model-manager-thumbnail-width',
thumbnailWidthEl.value.toString() + 'px',
);
thumbnailWidthEl.dispatchEvent(new Event('input'));
this.element.style.setProperty(
'--model-manager-thumbnail-height',
thumbnailHeightEl.value.toString() + 'px',
);
thumbnailHeightEl.dispatchEvent(new Event('input'));
}
} }
#resetManagerContentsScroll = () => { #resetManagerContentsScroll = () => {
this.#tabManagerContents.scrollTop = 0; this.#tabManagerContents.scrollTop = 0;
}; };
#refreshModels = async () => { #refreshModels = async (withoutComfyRefresh = false) => {
const modelData = this.#modelData; const modelData = this.#modelData;
modelData.systemSeparator = await comfyRequest( modelData.systemSeparator = await comfyRequest(
'/model-manager/system-separator', '/model-manager/system-separator',
@@ -5803,8 +5857,9 @@ class ModelManager extends ComfyDialog {
this.#browseView.updateModelGrid(); this.#browseView.updateModelGrid();
await this.#tryHideModelInfo(false); await this.#tryHideModelInfo(false);
if (!withoutComfyRefresh){
document.getElementById('comfy-refresh-button')?.click(); document.getElementById('comfy-refresh-button')?.click();
}
}; };
/** /**