feat: Add context menu option to move checkpoint models between type folders and complete various UI translations.

This commit is contained in:
Will Miao
2025-12-28 17:50:22 +08:00
parent e43aa5cae4
commit e5b557504e
12 changed files with 169 additions and 77 deletions

View File

@@ -532,7 +532,7 @@
"replacePreview": "Vorschau ersetzen",
"setContentRating": "Inhaltsbewertung festlegen",
"moveToFolder": "In Ordner verschieben",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "Metadaten reparieren",
"excludeModel": "Modell ausschließen",
"deleteModel": "Modell löschen",
"shareRecipe": "Rezept teilen",
@@ -650,16 +650,23 @@
"prepareError": "Fehler beim Vorbereiten der LoRAs für den Download: {message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "Rezept-Metadaten werden repariert...",
"success": "Rezept-Metadaten erfolgreich repariert",
"skipped": "Rezept bereits in der neuesten Version, keine Reparatur erforderlich",
"failed": "Rezept-Reparatur fehlgeschlagen: {message}",
"missingId": "Rezept kann nicht repariert werden: Fehlende Rezept-ID"
}
}
},
"checkpoints": {
"title": "Checkpoint-Modelle"
"title": "Checkpoint-Modelle",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "In {otherType}-Ordner verschieben"
}
},
"embeddings": {
"title": "Embedding-Modelle"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -659,7 +659,14 @@
}
},
"checkpoints": {
"title": "Checkpoint Models"
"title": "Checkpoint Models",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "Move to {otherType} Folder"
}
},
"embeddings": {
"title": "Embedding Models"

View File

@@ -532,7 +532,7 @@
"replacePreview": "Reemplazar vista previa",
"setContentRating": "Establecer clasificación de contenido",
"moveToFolder": "Mover a carpeta",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "Reparar metadatos",
"excludeModel": "Excluir modelo",
"deleteModel": "Eliminar modelo",
"shareRecipe": "Compartir receta",
@@ -650,16 +650,23 @@
"prepareError": "Error preparando LoRAs para descarga: {message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "Reparando metadatos de la receta...",
"success": "Metadatos de la receta reparados con éxito",
"skipped": "La receta ya está en la última versión, no se necesita reparación",
"failed": "Error al reparar la receta: {message}",
"missingId": "No se puede reparar la receta: falta el ID de la receta"
}
}
},
"checkpoints": {
"title": "Modelos checkpoint"
"title": "Modelos checkpoint",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "Mover a la carpeta {otherType}"
}
},
"embeddings": {
"title": "Modelos embedding"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -532,7 +532,7 @@
"replacePreview": "Remplacer l'aperçu",
"setContentRating": "Définir la classification du contenu",
"moveToFolder": "Déplacer vers un dossier",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "Réparer les métadonnées",
"excludeModel": "Exclure le modèle",
"deleteModel": "Supprimer le modèle",
"shareRecipe": "Partager la recipe",
@@ -650,16 +650,23 @@
"prepareError": "Erreur lors de la préparation des LoRAs pour le téléchargement : {message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "Réparation des métadonnées de la recette...",
"success": "Métadonnées de la recette réparées avec succès",
"skipped": "Recette déjà à la version la plus récente, aucune réparation nécessaire",
"failed": "Échec de la réparation de la recette : {message}",
"missingId": "Impossible de réparer la recette : ID de recette manquant"
}
}
},
"checkpoints": {
"title": "Modèles Checkpoint"
"title": "Modèles Checkpoint",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "Déplacer vers le dossier {otherType}"
}
},
"embeddings": {
"title": "Modèles Embedding"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -532,7 +532,7 @@
"replacePreview": "החלף תצוגה מקדימה",
"setContentRating": "הגדר דירוג תוכן",
"moveToFolder": "העבר לתיקייה",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "תיקון מטא-דאטה",
"excludeModel": "החרג מודל",
"deleteModel": "מחק מודל",
"shareRecipe": "שתף מתכון",
@@ -650,16 +650,23 @@
"prepareError": "שגיאה בהכנת LoRAs להורדה: {message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "מתקן מטא-דאטה של מתכון...",
"success": "מטא-דאטה של מתכון תוקן בהצלחה",
"skipped": "המתכון כבר בגרסה העדכנית ביותר, אין צורך בתיקון",
"failed": "תיקון המתכון נכשל: {message}",
"missingId": "לא ניתן לתקן את המתכון: חסר מזהה מתכון"
}
}
},
"checkpoints": {
"title": "מודלי Checkpoint"
"title": "מודלי Checkpoint",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "העבר לתיקיית {otherType}"
}
},
"embeddings": {
"title": "מודלי Embedding"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -532,7 +532,7 @@
"replacePreview": "プレビューを置換",
"setContentRating": "コンテンツレーティングを設定",
"moveToFolder": "フォルダに移動",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "メタデータを修復",
"excludeModel": "モデルを除外",
"deleteModel": "モデルを削除",
"shareRecipe": "レシピを共有",
@@ -650,16 +650,23 @@
"prepareError": "ダウンロード用LoRAの準備中にエラー{message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "レシピのメタデータを修復中...",
"success": "レシピのメタデータが正常に修復されました",
"skipped": "レシピはすでに最新バージョンです。修復は不要です",
"failed": "レシピの修復に失敗しました: {message}",
"missingId": "レシピを修復できません: レシピIDがありません"
}
}
},
"checkpoints": {
"title": "Checkpointモデル"
"title": "Checkpointモデル",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "{otherType} フォルダに移動"
}
},
"embeddings": {
"title": "Embeddingモデル"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -532,7 +532,7 @@
"replacePreview": "미리보기 교체",
"setContentRating": "콘텐츠 등급 설정",
"moveToFolder": "폴더로 이동",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "메타데이터 복구",
"excludeModel": "모델 제외",
"deleteModel": "모델 삭제",
"shareRecipe": "레시피 공유",
@@ -650,16 +650,23 @@
"prepareError": "LoRA 다운로드 준비 중 오류: {message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "레시피 메타데이터 복구 중...",
"success": "레시피 메타데이터가 성공적으로 복구되었습니다",
"skipped": "레시피가 이미 최신 버전입니다. 복구가 필요하지 않습니다",
"failed": "레시피 복구 실패: {message}",
"missingId": "레시피를 복구할 수 없음: 레시피 ID 누락"
}
}
},
"checkpoints": {
"title": "Checkpoint 모델"
"title": "Checkpoint 모델",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "{otherType} 폴더로 이동"
}
},
"embeddings": {
"title": "Embedding 모델"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -532,7 +532,7 @@
"replacePreview": "Заменить превью",
"setContentRating": "Установить рейтинг контента",
"moveToFolder": "Переместить в папку",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "Восстановить метаданные",
"excludeModel": "Исключить модель",
"deleteModel": "Удалить модель",
"shareRecipe": "Поделиться рецептом",
@@ -650,16 +650,23 @@
"prepareError": "Ошибка подготовки LoRAs для загрузки: {message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "Восстановление метаданных рецепта...",
"success": "Метаданные рецепта успешно восстановлены",
"skipped": "Рецепт уже последней версии, восстановление не требуется",
"failed": "Не удалось восстановить рецепт: {message}",
"missingId": "Не удалось восстановить рецепт: отсутствует ID рецепта"
}
}
},
"checkpoints": {
"title": "Модели Checkpoint"
"title": "Модели Checkpoint",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "Переместить в папку {otherType}"
}
},
"embeddings": {
"title": "Модели Embedding"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -532,7 +532,7 @@
"replacePreview": "替换预览",
"setContentRating": "设置内容评级",
"moveToFolder": "移动到文件夹",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "修复元数据",
"excludeModel": "排除模型",
"deleteModel": "删除模型",
"shareRecipe": "分享配方",
@@ -650,16 +650,23 @@
"prepareError": "准备下载 LoRA 时出错:{message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "正在修复配方元数据...",
"success": "配方元数据修复成功",
"skipped": "配方已是最新版本,无需修复",
"failed": "修复配方失败:{message}",
"missingId": "无法修复配方:缺少配方 ID"
}
}
},
"checkpoints": {
"title": "Checkpoint 模型"
"title": "Checkpoint 模型",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "移动到 {otherType} 文件夹"
}
},
"embeddings": {
"title": "Embedding 模型"
@@ -1518,4 +1525,4 @@
"learnMore": "浏览器插件教程"
}
}
}
}

View File

@@ -532,7 +532,7 @@
"replacePreview": "更換預覽圖",
"setContentRating": "設定內容分級",
"moveToFolder": "移動到資料夾",
"repairMetadata": "[TODO: Translate] Repair metadata",
"repairMetadata": "修復元數據",
"excludeModel": "排除模型",
"deleteModel": "刪除模型",
"shareRecipe": "分享配方",
@@ -650,16 +650,23 @@
"prepareError": "準備下載 LoRA 時發生錯誤:{message}"
},
"repair": {
"starting": "[TODO: Translate] Repairing recipe metadata...",
"success": "[TODO: Translate] Recipe metadata repaired successfully",
"skipped": "[TODO: Translate] Recipe already at latest version, no repair needed",
"failed": "[TODO: Translate] Failed to repair recipe: {message}",
"missingId": "[TODO: Translate] Cannot repair recipe: Missing recipe ID"
"starting": "正在修復配方元數據...",
"success": "配方元數據修復成功",
"skipped": "配方已是最新版本,無需修復",
"failed": "修復配方失敗:{message}",
"missingId": "無法修復配方:缺少配方 ID"
}
}
},
"checkpoints": {
"title": "Checkpoint 模型"
"title": "Checkpoint 模型",
"modelTypes": {
"checkpoint": "Checkpoint",
"diffusion_model": "Diffusion Model"
},
"contextMenu": {
"moveToOtherTypeFolder": "移動到 {otherType} 資料夾"
}
},
"embeddings": {
"title": "Embedding 模型"
@@ -1518,4 +1525,4 @@
"learnMore": "LM Civitai Extension Tutorial"
}
}
}
}

View File

@@ -3,6 +3,7 @@ import { ModelContextMenuMixin } from './ModelContextMenuMixin.js';
import { getModelApiClient, resetAndReload } from '../../api/modelApiFactory.js';
import { showDeleteModal, showExcludeModal } from '../../utils/modalUtils.js';
import { moveManager } from '../../managers/MoveManager.js';
import { i18n } from '../../i18n/index.js';
export class CheckpointContextMenu extends BaseContextMenu {
constructor() {
@@ -10,15 +11,28 @@ export class CheckpointContextMenu extends BaseContextMenu {
this.nsfwSelector = document.getElementById('nsfwLevelSelector');
this.modelType = 'checkpoint';
this.resetAndReload = resetAndReload;
this.initNSFWSelector();
}
// Implementation needed by the mixin
async saveModelMetadata(filePath, data) {
return getModelApiClient().saveModelMetadata(filePath, data);
}
showMenu(x, y, card) {
super.showMenu(x, y, card);
// Update the "Move to other root" label based on current model type
const moveOtherItem = this.menu.querySelector('[data-action="move-other"]');
if (moveOtherItem) {
const currentType = card.dataset.model_type || 'checkpoint';
const otherType = currentType === 'checkpoint' ? 'diffusion_model' : 'checkpoint';
const typeLabel = i18n.t(`checkpoints.modelTypes.${otherType}`);
moveOtherItem.innerHTML = `<i class="fas fa-exchange-alt"></i> ${i18n.t('checkpoints.contextMenu.moveToOtherTypeFolder', { otherType: typeLabel })}`;
}
}
handleMenuAction(action) {
// First try to handle with common actions
if (ModelContextMenuMixin.handleCommonMenuActions.call(this, action)) {
@@ -28,7 +42,7 @@ export class CheckpointContextMenu extends BaseContextMenu {
const apiClient = getModelApiClient();
// Otherwise handle checkpoint-specific actions
switch(action) {
switch (action) {
case 'details':
// Show checkpoint details
this.currentCard.click();
@@ -53,6 +67,13 @@ export class CheckpointContextMenu extends BaseContextMenu {
case 'move':
moveManager.showMoveModal(this.currentCard.dataset.filepath, this.currentCard.dataset.model_type);
break;
case 'move-other':
{
const currentType = this.currentCard.dataset.model_type || 'checkpoint';
const otherType = currentType === 'checkpoint' ? 'diffusion_model' : 'checkpoint';
moveManager.showMoveModal(this.currentCard.dataset.filepath, otherType);
}
break;
case 'exclude':
showExcludeModal(this.currentCard.dataset.filepath);
break;

View File

@@ -19,6 +19,7 @@
<div class="context-menu-item" data-action="set-nsfw"><i class="fas fa-exclamation-triangle"></i> {{ t('loras.contextMenu.setContentRating') }}</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item" data-action="move"><i class="fas fa-folder-open"></i> {{ t('loras.contextMenu.moveToFolder') }}</div>
<div class="context-menu-item" data-action="move-other"><i class="fas fa-exchange-alt"></i> {{ t('checkpoints.contextMenu.moveToOtherTypeFolder', {otherType: '...'}) }}</div>
<div class="context-menu-item" data-action="exclude"><i class="fas fa-eye-slash"></i> {{ t('loras.contextMenu.excludeModel') }}</div>
<div class="context-menu-item delete-item" data-action="delete"><i class="fas fa-trash"></i> {{ t('loras.contextMenu.deleteModel') }}</div>
</div>