diff --git a/locales/de.json b/locales/de.json index daad230e..e0b905e5 100644 --- a/locales/de.json +++ b/locales/de.json @@ -314,6 +314,7 @@ "downloads": "Downloads", "videoSettings": "Video-Einstellungen", "layoutSettings": "Layout-Einstellungen", + "licenseIcons": "Lizenzsymbole", "misc": "Verschiedenes", "backup": "Backups", "folderSettings": "Standard-Roots", @@ -594,6 +595,10 @@ "label": "Früher Zugriff Updates ausblenden", "help": "Nur Early-Access-Updates" }, + "licenseIcons": { + "useNewStyle": "Aktualisierte Lizenzsymbole verwenden", + "useNewStyleHelp": "Lizenzberechtigungen mit farbigen Indikatoren (neuer Stil) oder nur Einschränkungssymbolen (klassischer Stil) anzeigen. Orientiert sich am aktuellen CivitAI-Design." + }, "misc": { "includeTriggerWords": "Trigger Words in LoRA-Syntax einschließen", "includeTriggerWordsHelp": "Trainierte Trigger Words beim Kopieren der LoRA-Syntax in die Zwischenablage einschließen", diff --git a/locales/en.json b/locales/en.json index b4c52e2f..9d47c8f1 100644 --- a/locales/en.json +++ b/locales/en.json @@ -314,6 +314,7 @@ "downloads": "Downloads", "videoSettings": "Video Settings", "layoutSettings": "Layout Settings", + "licenseIcons": "License Icons", "misc": "Miscellaneous", "backup": "Backups", "folderSettings": "Default Roots", @@ -594,6 +595,10 @@ "label": "Hide Early Access Updates", "help": "When enabled, models with only early access updates will not show 'Update available' badge" }, + "licenseIcons": { + "useNewStyle": "Use updated license icons", + "useNewStyleHelp": "Display license permissions with colored indicators (new style) or restriction-only icons (classic style). Mirroring the current CivitAI design." + }, "misc": { "includeTriggerWords": "Include Trigger Words in LoRA Syntax", "includeTriggerWordsHelp": "Include trained trigger words when copying LoRA syntax to clipboard", diff --git a/locales/es.json b/locales/es.json index 11de9284..8883c1a7 100644 --- a/locales/es.json +++ b/locales/es.json @@ -314,6 +314,7 @@ "downloads": "Descargas", "videoSettings": "Configuración de video", "layoutSettings": "Configuración de diseño", + "licenseIcons": "Iconos de licencia", "misc": "Varios", "backup": "Copias de seguridad", "folderSettings": "Raíces predeterminadas", @@ -594,6 +595,10 @@ "label": "Ocultar actualizaciones de acceso temprano", "help": "Solo actualizaciones de acceso temprano" }, + "licenseIcons": { + "useNewStyle": "Usar iconos de licencia actualizados", + "useNewStyleHelp": "Mostrar permisos de licencia con indicadores de color (nuevo estilo) o solo iconos de restricción (estilo clásico). Refleja el diseño actual de CivitAI." + }, "misc": { "includeTriggerWords": "Incluir palabras clave en la sintaxis de LoRA", "includeTriggerWordsHelp": "Incluir palabras clave entrenadas al copiar la sintaxis de LoRA al portapapeles", diff --git a/locales/fr.json b/locales/fr.json index 8bd3035a..2f6d6290 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -314,6 +314,7 @@ "downloads": "Téléchargements", "videoSettings": "Paramètres vidéo", "layoutSettings": "Paramètres d'affichage", + "licenseIcons": "Icônes de licence", "misc": "Divers", "backup": "Sauvegardes", "folderSettings": "Racines par défaut", @@ -594,6 +595,10 @@ "label": "Masquer les mises à jour en accès anticipé", "help": "Seulement les mises à jour en accès anticipé" }, + "licenseIcons": { + "useNewStyle": "Utiliser les icônes de licence mises à jour", + "useNewStyleHelp": "Afficher les permissions de licence avec des indicateurs colorés (nouveau style) ou des icônes de restriction uniquement (style classique). Reprend le design actuel de CivitAI." + }, "misc": { "includeTriggerWords": "Inclure les mots-clés dans la syntaxe LoRA", "includeTriggerWordsHelp": "Inclure les mots-clés d'entraînement lors de la copie de la syntaxe LoRA dans le presse-papiers", diff --git a/locales/he.json b/locales/he.json index e6da1428..74f230e7 100644 --- a/locales/he.json +++ b/locales/he.json @@ -314,6 +314,7 @@ "downloads": "הורדות", "videoSettings": "הגדרות וידאו", "layoutSettings": "הגדרות פריסה", + "licenseIcons": "סמלי רישיון", "misc": "שונות", "backup": "גיבויים", "folderSettings": "תיקיות ברירת מחדל", @@ -594,6 +595,10 @@ "label": "הסתר עדכוני גישה מוקדמת", "help": "רק עדכוני גישה מוקדמת" }, + "licenseIcons": { + "useNewStyle": "השתמש בסמלי רישיון מעודכנים", + "useNewStyleHelp": "הצג הרשאות רישיון עם מחוונים צבעוניים (סגנון חדש) או סמלי הגבלה בלבד (סגנון קלאסי). משקף את העיצוב העדכני של CivitAI." + }, "misc": { "includeTriggerWords": "כלול מילות טריגר בתחביר LoRA", "includeTriggerWordsHelp": "כלול מילות טריגר מאומנות בעת העתקת תחביר LoRA ללוח", diff --git a/locales/ja.json b/locales/ja.json index 9012ac58..b6384dd8 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -314,6 +314,7 @@ "downloads": "ダウンロード", "videoSettings": "動画設定", "layoutSettings": "レイアウト設定", + "licenseIcons": "ライセンスアイコン", "misc": "その他", "backup": "バックアップ", "folderSettings": "デフォルトルート", @@ -594,6 +595,10 @@ "label": "早期アクセス更新を非表示", "help": "早期アクセスのみの更新" }, + "licenseIcons": { + "useNewStyle": "更新されたライセンスアイコンを使用", + "useNewStyleHelp": "カラーインジケーター付きでライセンス許可を表示(新スタイル)するか、制限のみのアイコンを表示(クラシックスタイル)します。現在のCivitAIデザインを反映しています。" + }, "misc": { "includeTriggerWords": "LoRA構文にトリガーワードを含める", "includeTriggerWordsHelp": "LoRA構文をクリップボードにコピーする際、学習済みトリガーワードを含めます", diff --git a/locales/ko.json b/locales/ko.json index d5fdbe33..25f54734 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -314,6 +314,7 @@ "downloads": "다운로드", "videoSettings": "비디오 설정", "layoutSettings": "레이아웃 설정", + "licenseIcons": "라이선스 아이콘", "misc": "기타", "backup": "백업", "folderSettings": "기본 루트", @@ -594,6 +595,10 @@ "label": "얼리 액세스 업데이트 숨기기", "help": "얼리 액세스 업데이트만" }, + "licenseIcons": { + "useNewStyle": "업데이트된 라이선스 아이콘 사용", + "useNewStyleHelp": "색상 표시기가 있는 라이선스 권한(새 스타일) 또는 제한 전용 아이콘(클래식 스타일)을 표시합니다. 현재 CivitAI 디자인을 반영합니다." + }, "misc": { "includeTriggerWords": "LoRA 문법에 트리거 단어 포함", "includeTriggerWordsHelp": "LoRA 문법을 클립보드에 복사할 때 학습된 트리거 단어를 포함합니다", diff --git a/locales/ru.json b/locales/ru.json index 7729b395..caab1fb6 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -314,6 +314,7 @@ "downloads": "Загрузки", "videoSettings": "Настройки видео", "layoutSettings": "Настройки макета", + "licenseIcons": "Значки лицензии", "misc": "Разное", "backup": "Резервные копии", "folderSettings": "Корневые папки", @@ -594,6 +595,10 @@ "label": "Скрыть обновления раннего доступа", "help": "Только обновления раннего доступа" }, + "licenseIcons": { + "useNewStyle": "Использовать обновлённые значки лицензии", + "useNewStyleHelp": "Отображать разрешения лицензии с цветными индикаторами (новый стиль) или только значки ограничений (классический стиль). Соответствует текущему дизайну CivitAI." + }, "misc": { "includeTriggerWords": "Включать триггерные слова в синтаксис LoRA", "includeTriggerWordsHelp": "Включать обученные триггерные слова при копировании синтаксиса LoRA в буфер обмена", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index a08697c2..40ce0a5e 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -314,6 +314,7 @@ "downloads": "下载", "videoSettings": "视频设置", "layoutSettings": "布局设置", + "licenseIcons": "许可协议图标", "misc": "其他", "backup": "备份", "folderSettings": "默认根目录", @@ -594,6 +595,10 @@ "label": "隐藏抢先体验更新", "help": "抢先体验更新" }, + "licenseIcons": { + "useNewStyle": "使用新版许可协议图标", + "useNewStyleHelp": "以彩色指示器显示许可权限(新样式),或仅显示限制图标(经典样式)。与当前 CivitAI 设计保持一致。" + }, "misc": { "includeTriggerWords": "复制 LoRA 语法时包含触发词", "includeTriggerWordsHelp": "复制 LoRA 语法到剪贴板时包含训练触发词", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index d1550428..556d2c9b 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -314,6 +314,7 @@ "downloads": "下載", "videoSettings": "影片設定", "layoutSettings": "版面設定", + "licenseIcons": "許可協議圖標", "misc": "其他", "backup": "備份", "folderSettings": "預設根目錄", @@ -594,6 +595,10 @@ "label": "隱藏搶先體驗更新", "help": "搶先體驗更新" }, + "licenseIcons": { + "useNewStyle": "使用新版許可協議圖標", + "useNewStyleHelp": "以彩色指示器顯示許可權限(新樣式),或僅顯示限制圖標(經典樣式)。與當前 CivitAI 設計保持一致。" + }, "misc": { "includeTriggerWords": "在 LoRA 語法中包含觸發詞", "includeTriggerWordsHelp": "複製 LoRA 語法到剪貼簿時包含訓練觸發詞", diff --git a/py/routes/handlers/model_handlers.py b/py/routes/handlers/model_handlers.py index 89c64c8e..4812b858 100644 --- a/py/routes/handlers/model_handlers.py +++ b/py/routes/handlers/model_handlers.py @@ -1272,6 +1272,14 @@ class ModelQueryHandler: license_flags = (model_data or {}).get("license_flags") if license_flags is not None: response_payload["license_flags"] = int(license_flags) + # Include the user's license icon style preference so the + # ComfyUI tooltip can pick the right set without a separate + # API call. + try: + settings = get_settings_manager() + response_payload["use_new_license_icons"] = settings.get("use_new_license_icons", True) + except Exception: + pass return web.json_response(response_payload) return web.json_response( { diff --git a/py/services/settings_manager.py b/py/services/settings_manager.py index 4a697f14..a7ad599c 100644 --- a/py/services/settings_manager.py +++ b/py/services/settings_manager.py @@ -105,6 +105,7 @@ DEFAULT_SETTINGS: Dict[str, Any] = { "download_skip_base_models": [], "backup_auto_enabled": True, "backup_retention_count": 5, + "use_new_license_icons": True, } diff --git a/static/css/components/lora-modal/lora-modal.css b/static/css/components/lora-modal/lora-modal.css index 5f851e81..5296130e 100644 --- a/static/css/components/lora-modal/lora-modal.css +++ b/static/css/components/lora-modal/lora-modal.css @@ -72,6 +72,10 @@ margin-left: auto; } +.modal-header-actions .license-permissions { + margin-left: auto; +} + .license-restrictions { display: flex; align-items: center; @@ -95,6 +99,41 @@ transform: translateY(-1px); } +/* Set 2 — New style permission indicators */ +.license-permissions { + display: flex; + gap: 4px; + align-items: center; +} + +.license-icon-new { + width: 22px; + height: 22px; + display: inline-block; + border-radius: 4px; + background-color: var(--text-muted); + -webkit-mask: var(--license-icon-image) center/contain no-repeat; + mask: var(--license-icon-image) center/contain no-repeat; + transition: background-color 0.2s ease, transform 0.2s ease; + cursor: default; + outline: 2px solid transparent; + outline-offset: 1px; +} + +.license-icon-new.allowed { + background-color: var(--color-success, #40c057); + outline-color: color-mix(in oklch, var(--color-success, #40c057) 30%, transparent); +} + +.license-icon-new.denied { + background-color: var(--color-error, #fa5252); + outline-color: color-mix(in oklch, var(--color-error, #fa5252) 30%, transparent); +} + +.license-icon-new:hover { + transform: translateY(-1px); +} + /* Info Grid */ .info-grid { display: grid; diff --git a/static/images/tabler/brush.svg b/static/images/tabler/brush.svg new file mode 100644 index 00000000..369d4816 --- /dev/null +++ b/static/images/tabler/brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/tabler/currency-dollar.svg b/static/images/tabler/currency-dollar.svg new file mode 100644 index 00000000..0fb18a6b --- /dev/null +++ b/static/images/tabler/currency-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/tabler/git-merge.svg b/static/images/tabler/git-merge.svg new file mode 100644 index 00000000..7a2db0c2 --- /dev/null +++ b/static/images/tabler/git-merge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/tabler/license.svg b/static/images/tabler/license.svg new file mode 100644 index 00000000..a24f5189 --- /dev/null +++ b/static/images/tabler/license.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/tabler/user.svg b/static/images/tabler/user.svg new file mode 100644 index 00000000..cbc61153 --- /dev/null +++ b/static/images/tabler/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/js/components/shared/ModelModal.js b/static/js/components/shared/ModelModal.js index 41de7b75..04493932 100644 --- a/static/js/components/shared/ModelModal.js +++ b/static/js/components/shared/ModelModal.js @@ -234,6 +234,95 @@ function renderLicenseIcons(modelData) { `; } +// ── Set 2 (new CivitAI-style) permission icons ── + +const NEW_LICENSE_ICON_CONFIG = [ + { + key: 'commercial', + icon: 'currency-dollar.svg', + allowedFn: (license) => { + const uses = license.allowCommercialUse || []; + return uses.includes('Image') || uses.includes('Sell'); + }, + labelAllowed: 'Commercial use allowed', + labelDenied: 'No commercial use' + }, + { + key: 'genServices', + icon: 'brush.svg', + allowedFn: (license) => { + const uses = license.allowCommercialUse || []; + return uses.includes('RentCivit') || uses.includes('Rent'); + }, + labelAllowed: 'Generation services allowed', + labelDenied: 'No generation services' + }, + { + key: 'credit', + icon: 'user.svg', + allowedFn: (license) => !!license.allowNoCredit, + labelAllowed: 'No credit required', + labelDenied: 'Creator credit required' + }, + { + key: 'derivatives', + icon: 'git-merge.svg', + allowedFn: (license) => !!license.allowDerivatives, + labelAllowed: 'Merges allowed', + labelDenied: 'No merges allowed' + }, + { + key: 'relicense', + icon: 'license.svg', + allowedFn: (license) => !!license.allowDifferentLicense, + labelAllowed: 'Different permissions allowed on merges', + labelDenied: 'Same permissions required on merges' + } +]; + +function createNewLicenseIconMarkup(icon, allowed, label) { + const safeLabel = escapeAttribute(label); + const iconPath = `/loras_static/images/tabler/${icon}`; + const stateClass = allowed ? 'allowed' : 'denied'; + return ``; +} + +function renderNewLicenseIcons(modelData) { + const license = modelData?.civitai?.model; + if (!license) { + return ''; + } + + const icons = []; + NEW_LICENSE_ICON_CONFIG.forEach((config) => { + if (config.key === 'credit' && !hasLicenseField(license, 'allowNoCredit')) { + return; + } + if (config.key === 'derivatives' && !hasLicenseField(license, 'allowDerivatives')) { + return; + } + if (config.key === 'relicense' && !hasLicenseField(license, 'allowDifferentLicense')) { + return; + } + if ((config.key === 'commercial' || config.key === 'genServices') && !hasLicenseField(license, 'allowCommercialUse')) { + return; + } + const allowed = config.allowedFn(license); + const label = allowed ? config.labelAllowed : config.labelDenied; + icons.push(createNewLicenseIconMarkup(config.icon, allowed, label)); + }); + + if (!icons.length) { + return ''; + } + + const containerLabel = translate('modals.model.license.restrictionsLabel', {}, 'License permissions'); + const safeContainerLabel = escapeAttribute(containerLabel); + return `
`; +} + /** * Display the model modal with the given model data * @param {Object} model - Model data object @@ -264,7 +353,10 @@ export async function showModelModal(model, modelType) { }; const escapedFilePathAttr = escapeAttribute(modelWithFullData.file_path || ''); const escapedFolderPath = escapeHtml((modelWithFullData.file_path || '').replace(/[^/]+$/, '') || 'N/A'); - const licenseIcons = renderLicenseIcons(modelWithFullData); + const useNewIcons = state.global.settings.use_new_license_icons !== false; + const licenseIcons = useNewIcons + ? renderNewLicenseIcons(modelWithFullData) + : renderLicenseIcons(modelWithFullData); const viewOnCivitaiAction = modelWithFullData.from_civitai ? `