mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
Merge pull request #684 from willmiao/codex/add-check-update-to-single-model-context-menu
Add single-model update checks to context menus
This commit is contained in:
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "Civitai-Daten aktualisieren",
|
"refreshMetadata": "Civitai-Daten aktualisieren",
|
||||||
|
"checkUpdates": "Updates prüfen",
|
||||||
"relinkCivitai": "Mit Civitai neu verknüpfen",
|
"relinkCivitai": "Mit Civitai neu verknüpfen",
|
||||||
"copySyntax": "LoRA-Syntax kopieren",
|
"copySyntax": "LoRA-Syntax kopieren",
|
||||||
"copyFilename": "Modell-Dateiname kopieren",
|
"copyFilename": "Modell-Dateiname kopieren",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "Refresh Civitai Data",
|
"refreshMetadata": "Refresh Civitai Data",
|
||||||
|
"checkUpdates": "Check Updates",
|
||||||
"relinkCivitai": "Re-link to Civitai",
|
"relinkCivitai": "Re-link to Civitai",
|
||||||
"copySyntax": "Copy LoRA Syntax",
|
"copySyntax": "Copy LoRA Syntax",
|
||||||
"copyFilename": "Copy Model Filename",
|
"copyFilename": "Copy Model Filename",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "Actualizar datos de Civitai",
|
"refreshMetadata": "Actualizar datos de Civitai",
|
||||||
|
"checkUpdates": "Comprobar actualizaciones",
|
||||||
"relinkCivitai": "Re-vincular a Civitai",
|
"relinkCivitai": "Re-vincular a Civitai",
|
||||||
"copySyntax": "Copiar sintaxis de LoRA",
|
"copySyntax": "Copiar sintaxis de LoRA",
|
||||||
"copyFilename": "Copiar nombre de archivo del modelo",
|
"copyFilename": "Copiar nombre de archivo del modelo",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "Actualiser les données Civitai",
|
"refreshMetadata": "Actualiser les données Civitai",
|
||||||
|
"checkUpdates": "Vérifier les mises à jour",
|
||||||
"relinkCivitai": "Relier à nouveau à Civitai",
|
"relinkCivitai": "Relier à nouveau à Civitai",
|
||||||
"copySyntax": "Copier la syntaxe LoRA",
|
"copySyntax": "Copier la syntaxe LoRA",
|
||||||
"copyFilename": "Copier le nom de fichier du modèle",
|
"copyFilename": "Copier le nom de fichier du modèle",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "רענן נתוני Civitai",
|
"refreshMetadata": "רענן נתוני Civitai",
|
||||||
|
"checkUpdates": "בדוק עדכונים",
|
||||||
"relinkCivitai": "קשר מחדש ל-Civitai",
|
"relinkCivitai": "קשר מחדש ל-Civitai",
|
||||||
"copySyntax": "העתק תחביר LoRA",
|
"copySyntax": "העתק תחביר LoRA",
|
||||||
"copyFilename": "העתק שם קובץ מודל",
|
"copyFilename": "העתק שם קובץ מודל",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "Civitaiデータを更新",
|
"refreshMetadata": "Civitaiデータを更新",
|
||||||
|
"checkUpdates": "更新確認",
|
||||||
"relinkCivitai": "Civitaiに再リンク",
|
"relinkCivitai": "Civitaiに再リンク",
|
||||||
"copySyntax": "LoRA構文をコピー",
|
"copySyntax": "LoRA構文をコピー",
|
||||||
"copyFilename": "モデルファイル名をコピー",
|
"copyFilename": "モデルファイル名をコピー",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "Civitai 데이터 새로고침",
|
"refreshMetadata": "Civitai 데이터 새로고침",
|
||||||
|
"checkUpdates": "업데이트 확인",
|
||||||
"relinkCivitai": "Civitai에 다시 연결",
|
"relinkCivitai": "Civitai에 다시 연결",
|
||||||
"copySyntax": "LoRA 문법 복사",
|
"copySyntax": "LoRA 문법 복사",
|
||||||
"copyFilename": "모델 파일명 복사",
|
"copyFilename": "모델 파일명 복사",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "Обновить данные Civitai",
|
"refreshMetadata": "Обновить данные Civitai",
|
||||||
|
"checkUpdates": "Проверить обновления",
|
||||||
"relinkCivitai": "Пересвязать с Civitai",
|
"relinkCivitai": "Пересвязать с Civitai",
|
||||||
"copySyntax": "Копировать синтаксис LoRA",
|
"copySyntax": "Копировать синтаксис LoRA",
|
||||||
"copyFilename": "Копировать имя файла модели",
|
"copyFilename": "Копировать имя файла модели",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "刷新 Civitai 数据",
|
"refreshMetadata": "刷新 Civitai 数据",
|
||||||
|
"checkUpdates": "检查更新",
|
||||||
"relinkCivitai": "重新关联到 Civitai",
|
"relinkCivitai": "重新关联到 Civitai",
|
||||||
"copySyntax": "复制 LoRA 语法",
|
"copySyntax": "复制 LoRA 语法",
|
||||||
"copyFilename": "复制模型文件名",
|
"copyFilename": "复制模型文件名",
|
||||||
|
|||||||
@@ -496,6 +496,7 @@
|
|||||||
},
|
},
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
"refreshMetadata": "刷新 Civitai 資料",
|
"refreshMetadata": "刷新 Civitai 資料",
|
||||||
|
"checkUpdates": "檢查更新",
|
||||||
"relinkCivitai": "重新連結 Civitai",
|
"relinkCivitai": "重新連結 Civitai",
|
||||||
"copySyntax": "複製 LoRA 語法",
|
"copySyntax": "複製 LoRA 語法",
|
||||||
"copyFilename": "複製模型檔名",
|
"copyFilename": "複製模型檔名",
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { showToast, getNSFWLevelName, openExampleImagesFolder } from '../../utils/uiHelpers.js';
|
import { showToast, getNSFWLevelName, openExampleImagesFolder } from '../../utils/uiHelpers.js';
|
||||||
import { modalManager } from '../../managers/ModalManager.js';
|
import { modalManager } from '../../managers/ModalManager.js';
|
||||||
import { state } from '../../state/index.js';
|
import { state } from '../../state/index.js';
|
||||||
import { getModelApiClient } from '../../api/modelApiFactory.js';
|
import { getModelApiClient, resetAndReload } from '../../api/modelApiFactory.js';
|
||||||
import { bulkManager } from '../../managers/BulkManager.js';
|
import { bulkManager } from '../../managers/BulkManager.js';
|
||||||
|
import { MODEL_CONFIG } from '../../api/apiConfig.js';
|
||||||
|
import { translate } from '../../utils/i18nHelpers.js';
|
||||||
|
|
||||||
// Mixin with shared functionality for LoraContextMenu and CheckpointContextMenu
|
// Mixin with shared functionality for LoraContextMenu and CheckpointContextMenu
|
||||||
export const ModelContextMenuMixin = {
|
export const ModelContextMenuMixin = {
|
||||||
@@ -246,6 +248,101 @@ export const ModelContextMenuMixin = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
parseModelId(value) {
|
||||||
|
if (value === undefined || value === null || value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = Number.parseInt(value, 10);
|
||||||
|
return Number.isNaN(parsed) ? null : parsed;
|
||||||
|
},
|
||||||
|
|
||||||
|
getModelIdFromCard(card) {
|
||||||
|
if (!card) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const directValue = this.parseModelId(card.dataset?.modelId);
|
||||||
|
if (directValue !== null) {
|
||||||
|
return directValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card.dataset?.meta) {
|
||||||
|
try {
|
||||||
|
const meta = JSON.parse(card.dataset.meta);
|
||||||
|
const metaValue = this.parseModelId(meta?.modelId ?? meta?.model_id);
|
||||||
|
if (metaValue !== null) {
|
||||||
|
return metaValue;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Unable to parse card metadata for model ID', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
async checkUpdatesForCurrentModel() {
|
||||||
|
const card = this.currentCard;
|
||||||
|
if (!card) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelId = this.getModelIdFromCard(card);
|
||||||
|
const typeConfig = MODEL_CONFIG[this.modelType] || {};
|
||||||
|
const typeLabel = (typeConfig.displayName || 'Model').toLowerCase();
|
||||||
|
|
||||||
|
if (modelId === null) {
|
||||||
|
showToast('toast.models.bulkUpdatesMissing', { type: typeLabel }, 'warning');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiClient = getModelApiClient();
|
||||||
|
if (!apiClient || typeof apiClient.refreshUpdatesForModels !== 'function') {
|
||||||
|
console.warn('Model API client does not support refreshUpdatesForModels');
|
||||||
|
showToast('toast.models.bulkUpdatesFailed', { type: typeLabel, message: 'Operation not supported' }, 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadingMessage = translate(
|
||||||
|
'toast.models.bulkUpdatesChecking',
|
||||||
|
{ count: 1, type: typeLabel },
|
||||||
|
`Checking selected ${typeLabel}(s) for updates...`
|
||||||
|
);
|
||||||
|
state.loadingManager?.showSimpleLoading?.(loadingMessage);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await apiClient.refreshUpdatesForModels([modelId]);
|
||||||
|
const records = Array.isArray(response?.records) ? response.records : [];
|
||||||
|
const updatesCount = records.length;
|
||||||
|
|
||||||
|
if (updatesCount > 0) {
|
||||||
|
showToast('toast.models.bulkUpdatesSuccess', { count: updatesCount, type: typeLabel }, 'success');
|
||||||
|
} else {
|
||||||
|
showToast('toast.models.bulkUpdatesNone', { type: typeLabel }, 'info');
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetFn = this.resetAndReload || resetAndReload;
|
||||||
|
if (typeof resetFn === 'function') {
|
||||||
|
await resetFn(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking updates for model:', error);
|
||||||
|
showToast(
|
||||||
|
'toast.models.bulkUpdatesFailed',
|
||||||
|
{ type: typeLabel, message: error?.message ?? 'Unknown error' },
|
||||||
|
'error'
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
if (state.loadingManager?.hide) {
|
||||||
|
state.loadingManager.hide();
|
||||||
|
}
|
||||||
|
if (typeof state.loadingManager?.restoreProgressBar === 'function') {
|
||||||
|
state.loadingManager.restoreProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Common action handlers
|
// Common action handlers
|
||||||
handleCommonMenuActions(action) {
|
handleCommonMenuActions(action) {
|
||||||
switch(action) {
|
switch(action) {
|
||||||
@@ -272,6 +369,9 @@ export const ModelContextMenuMixin = {
|
|||||||
case 'set-nsfw':
|
case 'set-nsfw':
|
||||||
this.showNSFWLevelSelector(null, null, this.currentCard);
|
this.showNSFWLevelSelector(null, null, this.currentCard);
|
||||||
return true;
|
return true;
|
||||||
|
case 'check-updates':
|
||||||
|
this.checkUpdatesForCurrentModel();
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
<div class="context-menu-item" data-action="refresh-metadata">
|
<div class="context-menu-item" data-action="refresh-metadata">
|
||||||
<i class="fas fa-sync"></i> <span>{{ t('loras.contextMenu.refreshMetadata') }}</span>
|
<i class="fas fa-sync"></i> <span>{{ t('loras.contextMenu.refreshMetadata') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="context-menu-item" data-action="check-updates">
|
||||||
|
<i class="fas fa-bell"></i> <span>{{ t('loras.contextMenu.checkUpdates') }}</span>
|
||||||
|
</div>
|
||||||
<div class="context-menu-item" data-action="relink-civitai">
|
<div class="context-menu-item" data-action="relink-civitai">
|
||||||
<i class="fas fa-link"></i> <span>{{ t('loras.contextMenu.relinkCivitai') }}</span>
|
<i class="fas fa-link"></i> <span>{{ t('loras.contextMenu.relinkCivitai') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user