diff --git a/locales/de.json b/locales/de.json index 69b50f6f..951794a8 100644 --- a/locales/de.json +++ b/locales/de.json @@ -692,6 +692,7 @@ "unfavorite": "Aus Favoriten entfernen", "deleteAll": "Ausgewählte löschen", "downloadMissingLoras": "Fehlende LoRAs herunterladen", + "downloadExamples": "Beispielbilder herunterladen", "clear": "Auswahl löschen", "skipMetadataRefreshCount": "Überspringen({count} Modelle)", "resumeMetadataRefreshCount": "Fortsetzen({count} Modelle)", diff --git a/locales/en.json b/locales/en.json index 0a1235e4..6aa15b5f 100644 --- a/locales/en.json +++ b/locales/en.json @@ -692,6 +692,7 @@ "unfavorite": "Remove from Favorites", "deleteAll": "Delete Selected", "downloadMissingLoras": "Download Missing LoRAs", + "downloadExamples": "Download Example Images", "clear": "Clear Selection", "skipMetadataRefreshCount": "Skip ({count} models)", "resumeMetadataRefreshCount": "Resume ({count} models)", diff --git a/locales/es.json b/locales/es.json index 571bd7b7..c6f43f0c 100644 --- a/locales/es.json +++ b/locales/es.json @@ -692,6 +692,7 @@ "unfavorite": "Quitar de favoritos", "deleteAll": "Eliminar seleccionados", "downloadMissingLoras": "Descargar LoRAs faltantes", + "downloadExamples": "Descargar imágenes de ejemplo", "clear": "Limpiar selección", "skipMetadataRefreshCount": "Omitir({count} modelos)", "resumeMetadataRefreshCount": "Reanudar({count} modelos)", diff --git a/locales/fr.json b/locales/fr.json index 74c723a4..8bfe3876 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -692,6 +692,7 @@ "unfavorite": "Retirer des favoris", "deleteAll": "Supprimer la sélection", "downloadMissingLoras": "Télécharger les LoRAs manquants", + "downloadExamples": "Télécharger les images d'exemple", "clear": "Effacer la sélection", "skipMetadataRefreshCount": "Ignorer({count} modèles)", "resumeMetadataRefreshCount": "Reprendre({count} modèles)", diff --git a/locales/he.json b/locales/he.json index 59875292..73a914e1 100644 --- a/locales/he.json +++ b/locales/he.json @@ -692,6 +692,7 @@ "unfavorite": "הסר ממועדפים", "deleteAll": "מחק נבחרים", "downloadMissingLoras": "הורדת LoRAs חסרים", + "downloadExamples": "הורד תמונות דוגמה", "clear": "נקה בחירה", "skipMetadataRefreshCount": "דילוג({count} מודלים)", "resumeMetadataRefreshCount": "המשך({count} מודלים)", diff --git a/locales/ja.json b/locales/ja.json index 12098f5f..42c95e00 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -692,6 +692,7 @@ "unfavorite": "お気に入りから削除", "deleteAll": "選択したものを削除", "downloadMissingLoras": "不足している LoRA をダウンロード", + "downloadExamples": "例画像をダウンロード", "clear": "選択をクリア", "skipMetadataRefreshCount": "スキップ({count}モデル)", "resumeMetadataRefreshCount": "再開({count}モデル)", diff --git a/locales/ko.json b/locales/ko.json index add2583d..7a6a4d99 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -692,6 +692,7 @@ "unfavorite": "즐겨찾기 해제", "deleteAll": "선택된 항목 삭제", "downloadMissingLoras": "누락된 LoRA 다운로드", + "downloadExamples": "예시 이미지 다운로드", "clear": "선택 지우기", "skipMetadataRefreshCount": "건너뛰기({count}개 모델)", "resumeMetadataRefreshCount": "재개({count}개 모델)", diff --git a/locales/ru.json b/locales/ru.json index 0f83a9aa..16b3cb8f 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -692,6 +692,7 @@ "unfavorite": "Удалить из избранного", "deleteAll": "Удалить выбранные", "downloadMissingLoras": "Скачать отсутствующие LoRAs", + "downloadExamples": "Загрузить примеры изображений", "clear": "Очистить выбор", "skipMetadataRefreshCount": "Пропустить({count} моделей)", "resumeMetadataRefreshCount": "Возобновить({count} моделей)", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 6c7f3856..b5478abd 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -692,6 +692,7 @@ "unfavorite": "取消收藏", "deleteAll": "删除已选", "downloadMissingLoras": "下载缺失的 LoRAs", + "downloadExamples": "下载示例图片", "clear": "清除选择", "skipMetadataRefreshCount": "跳过({count} 个模型)", "resumeMetadataRefreshCount": "恢复({count} 个模型)", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 07f070f9..ce60948b 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -692,6 +692,7 @@ "unfavorite": "取消收藏", "deleteAll": "刪除所選", "downloadMissingLoras": "下載缺失的 LoRAs", + "downloadExamples": "下載範例圖片", "clear": "清除選取", "skipMetadataRefreshCount": "跳過({count} 個模型)", "resumeMetadataRefreshCount": "恢復({count} 個模型)", diff --git a/static/js/components/ContextMenu/BulkContextMenu.js b/static/js/components/ContextMenu/BulkContextMenu.js index 993af247..e63ad7f8 100644 --- a/static/js/components/ContextMenu/BulkContextMenu.js +++ b/static/js/components/ContextMenu/BulkContextMenu.js @@ -4,6 +4,7 @@ import { bulkManager } from '../../managers/BulkManager.js'; import { updateElementText, translate } from '../../utils/i18nHelpers.js'; import { bulkMissingLoraDownloadManager } from '../../managers/BulkMissingLoraDownloadManager.js'; import { showToast } from '../../utils/uiHelpers.js'; +import { getModelApiClient } from '../../api/modelApiFactory.js'; export class BulkContextMenu extends BaseContextMenu { constructor() { @@ -107,6 +108,13 @@ export class BulkContextMenu extends BaseContextMenu { downloadMissingLorasItem.style.display = currentModelType === 'recipes' ? 'flex' : 'none'; } + const downloadExampleImagesItem = this.menu.querySelector('[data-action="download-example-images"]'); + if (downloadExampleImagesItem) { + // Show on model pages (loras, checkpoints, embeddings), hide on recipes + const modelPages = ['loras', 'checkpoints', 'embeddings']; + downloadExampleImagesItem.style.display = modelPages.includes(currentModelType) ? 'flex' : 'none'; + } + const skipMetadataRefreshItem = this.menu.querySelector('[data-action="skip-metadata-refresh"]'); const resumeMetadataRefreshItem = this.menu.querySelector('[data-action="resume-metadata-refresh"]'); @@ -235,6 +243,9 @@ export class BulkContextMenu extends BaseContextMenu { case 'download-missing-loras': this.handleDownloadMissingLoras(); break; + case 'download-example-images': + this.handleDownloadExampleImages(); + break; case 'clear': bulkManager.clearSelection(); break; @@ -277,4 +288,31 @@ export class BulkContextMenu extends BaseContextMenu { await bulkMissingLoraDownloadManager.downloadMissingLoras(selectedRecipes); } + + async handleDownloadExampleImages() { + if (state.selectedModels.size === 0) { + return; + } + + const hashes = new Set(); + for (const filePath of state.selectedModels) { + const escapedPath = CSS.escape(filePath); + const card = document.querySelector(`.model-card[data-filepath="${escapedPath}"]`); + if (card?.dataset?.sha256) { + hashes.add(card.dataset.sha256); + } + } + + if (hashes.size === 0) { + showToast('No valid model hashes found in selection', {}, 'warning'); + return; + } + + try { + const apiClient = getModelApiClient(); + await apiClient.downloadExampleImages([...hashes]); + } catch (error) { + console.error('Bulk download example images failed:', error); + } + } } diff --git a/templates/components/context_menu.html b/templates/components/context_menu.html index c0de9c5a..e98c88d3 100644 --- a/templates/components/context_menu.html +++ b/templates/components/context_menu.html @@ -71,6 +71,9 @@
{{ t('loras.bulkOperations.autoOrganize') }}
+
+ {{ t('loras.bulkOperations.downloadExamples') }} +
{{ t('loras.bulkOperations.addTags') }}