mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
feat: add update available indicator to model cards
- Add CSS custom properties for update badge styling in both light and dark themes - Create new card header info layout with flexbox for better content organization - Implement model-update-badge component with glow effects and proper spacing - Add has-update class to cards when updates are available with visual border indicators - Update ModelCard.js to conditionally render update badges based on model data - Include internationalization support for update badge labels and tooltips The changes provide users with clear visual indicators when model updates are available, improving the user experience by making update status immediately visible without requiring manual checks.
This commit is contained in:
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "Fehler beim Überprüfen der Beispielbilder",
|
"checkError": "Fehler beim Überprüfen der Beispielbilder",
|
||||||
"missingHash": "Fehlende Modell-Hash-Informationen.",
|
"missingHash": "Fehlende Modell-Hash-Informationen.",
|
||||||
"noRemoteImagesAvailable": "Keine Remote-Beispielbilder für dieses Modell auf Civitai verfügbar"
|
"noRemoteImagesAvailable": "Keine Remote-Beispielbilder für dieses Modell auf Civitai verfügbar"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "Update",
|
||||||
|
"updateAvailable": "Update verfügbar"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "Error checking for example images",
|
"checkError": "Error checking for example images",
|
||||||
"missingHash": "Missing model hash information.",
|
"missingHash": "Missing model hash information.",
|
||||||
"noRemoteImagesAvailable": "No remote example images available for this model on Civitai"
|
"noRemoteImagesAvailable": "No remote example images available for this model on Civitai"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "Update",
|
||||||
|
"updateAvailable": "Update available"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "Error al verificar imágenes de ejemplo",
|
"checkError": "Error al verificar imágenes de ejemplo",
|
||||||
"missingHash": "Falta información del hash del modelo.",
|
"missingHash": "Falta información del hash del modelo.",
|
||||||
"noRemoteImagesAvailable": "No hay imágenes de ejemplo remotas disponibles para este modelo en Civitai"
|
"noRemoteImagesAvailable": "No hay imágenes de ejemplo remotas disponibles para este modelo en Civitai"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "Actualización",
|
||||||
|
"updateAvailable": "Actualización disponible"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "Erreur lors de la vérification des images d'exemple",
|
"checkError": "Erreur lors de la vérification des images d'exemple",
|
||||||
"missingHash": "Informations de hachage du modèle manquantes.",
|
"missingHash": "Informations de hachage du modèle manquantes.",
|
||||||
"noRemoteImagesAvailable": "Aucune image d'exemple distante disponible pour ce modèle sur Civitai"
|
"noRemoteImagesAvailable": "Aucune image d'exemple distante disponible pour ce modèle sur Civitai"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "Mise à jour",
|
||||||
|
"updateAvailable": "Mise à jour disponible"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "שגיאה בבדיקת תמונות דוגמה",
|
"checkError": "שגיאה בבדיקת תמונות דוגמה",
|
||||||
"missingHash": "חסר מידע hash של המודל.",
|
"missingHash": "חסר מידע hash של המודל.",
|
||||||
"noRemoteImagesAvailable": "אין תמונות דוגמה מרוחקות זמינות למודל זה ב-Civitai"
|
"noRemoteImagesAvailable": "אין תמונות דוגמה מרוחקות זמינות למודל זה ב-Civitai"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "עדכון",
|
||||||
|
"updateAvailable": "עדכון זמין"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "例画像の確認中にエラーが発生しました",
|
"checkError": "例画像の確認中にエラーが発生しました",
|
||||||
"missingHash": "モデルハッシュ情報がありません。",
|
"missingHash": "モデルハッシュ情報がありません。",
|
||||||
"noRemoteImagesAvailable": "このモデルのCivitaiでのリモート例画像は利用できません"
|
"noRemoteImagesAvailable": "このモデルのCivitaiでのリモート例画像は利用できません"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "アップデート",
|
||||||
|
"updateAvailable": "アップデートがあります"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "예시 이미지 확인 중 오류",
|
"checkError": "예시 이미지 확인 중 오류",
|
||||||
"missingHash": "모델 해시 정보가 없습니다.",
|
"missingHash": "모델 해시 정보가 없습니다.",
|
||||||
"noRemoteImagesAvailable": "Civitai에서 이 모델의 원격 예시 이미지를 사용할 수 없습니다"
|
"noRemoteImagesAvailable": "Civitai에서 이 모델의 원격 예시 이미지를 사용할 수 없습니다"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "업데이트",
|
||||||
|
"updateAvailable": "업데이트 가능"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "Ошибка проверки примеров изображений",
|
"checkError": "Ошибка проверки примеров изображений",
|
||||||
"missingHash": "Отсутствует хеш модели.",
|
"missingHash": "Отсутствует хеш модели.",
|
||||||
"noRemoteImagesAvailable": "Нет удаленных примеров изображений для этой модели на Civitai"
|
"noRemoteImagesAvailable": "Нет удаленных примеров изображений для этой модели на Civitai"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "Обновление",
|
||||||
|
"updateAvailable": "Доступно обновление"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "检查示例图片时出错",
|
"checkError": "检查示例图片时出错",
|
||||||
"missingHash": "缺少模型哈希信息。",
|
"missingHash": "缺少模型哈希信息。",
|
||||||
"noRemoteImagesAvailable": "此模型在 Civitai 上没有远程示例图片"
|
"noRemoteImagesAvailable": "此模型在 Civitai 上没有远程示例图片"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "更新",
|
||||||
|
"updateAvailable": "有可用更新"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"checkError": "檢查範例圖片時發生錯誤",
|
"checkError": "檢查範例圖片時發生錯誤",
|
||||||
"missingHash": "缺少模型雜湊資訊。",
|
"missingHash": "缺少模型雜湊資訊。",
|
||||||
"noRemoteImagesAvailable": "此模型在 Civitai 上無遠端範例圖片"
|
"noRemoteImagesAvailable": "此模型在 Civitai 上無遠端範例圖片"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"update": "更新",
|
||||||
|
"updateAvailable": "有可用更新"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalContextMenu": {
|
"globalContextMenu": {
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ html, body {
|
|||||||
--lora-error: oklch(75% 0.32 29);
|
--lora-error: oklch(75% 0.32 29);
|
||||||
--lora-warning: oklch(var(--lora-warning-l) var(--lora-warning-c) var(--lora-warning-h));
|
--lora-warning: oklch(var(--lora-warning-l) var(--lora-warning-c) var(--lora-warning-h));
|
||||||
--lora-success: oklch(var(--lora-success-l) var(--lora-success-c) var(--lora-success-h));
|
--lora-success: oklch(var(--lora-success-l) var(--lora-success-c) var(--lora-success-h));
|
||||||
|
--badge-update-bg: oklch(72% 0.2 220);
|
||||||
|
--badge-update-text: oklch(28% 0.03 220);
|
||||||
|
--badge-update-glow: oklch(72% 0.2 220 / 0.28);
|
||||||
|
|
||||||
/* Spacing Scale */
|
/* Spacing Scale */
|
||||||
--space-1: calc(8px * 1);
|
--space-1: calc(8px * 1);
|
||||||
@@ -100,6 +103,9 @@ html[data-theme="light"] {
|
|||||||
--lora-border: oklch(90% 0.02 256 / 0.15);
|
--lora-border: oklch(90% 0.02 256 / 0.15);
|
||||||
--lora-text: oklch(98% 0.02 256);
|
--lora-text: oklch(98% 0.02 256);
|
||||||
--lora-warning: oklch(75% 0.25 80); /* Modified to be used with oklch() */
|
--lora-warning: oklch(75% 0.25 80); /* Modified to be used with oklch() */
|
||||||
|
--badge-update-bg: oklch(62% 0.18 220);
|
||||||
|
--badge-update-text: oklch(98% 0.02 240);
|
||||||
|
--badge-update-glow: oklch(62% 0.18 220 / 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|||||||
@@ -296,6 +296,18 @@
|
|||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-header-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header-info .base-model-label {
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.card-actions i {
|
.card-actions i {
|
||||||
margin-left: var(--space-1);
|
margin-left: var(--space-1);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -422,6 +434,7 @@
|
|||||||
border-radius: var(--border-radius-xs);
|
border-radius: var(--border-radius-xs);
|
||||||
backdrop-filter: blur(2px);
|
backdrop-filter: blur(2px);
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Style for version name */
|
/* Style for version name */
|
||||||
@@ -575,4 +588,26 @@
|
|||||||
15% { opacity: 1; transform: translateY(0); }
|
15% { opacity: 1; transform: translateY(0); }
|
||||||
85% { opacity: 1; transform: translateY(0); }
|
85% { opacity: 1; transform: translateY(0); }
|
||||||
100% { opacity: 0; transform: translateY(0); }
|
100% { opacity: 0; transform: translateY(0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.model-card.has-update {
|
||||||
|
border-color: color-mix(in oklab, var(--badge-update-bg) 60%, transparent);
|
||||||
|
box-shadow: 0 0 0 1px color-mix(in oklab, var(--badge-update-bg) 45%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-update-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: var(--border-radius-xs);
|
||||||
|
background: var(--badge-update-bg);
|
||||||
|
color: var(--badge-update-text);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
box-shadow: 0 4px 12px var(--badge-update-glow);
|
||||||
|
border: 1px solid color-mix(in oklab, var(--badge-update-bg) 55%, transparent);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|||||||
@@ -432,6 +432,8 @@ export function createModelCard(model, modelType) {
|
|||||||
card.dataset.notes = model.notes || '';
|
card.dataset.notes = model.notes || '';
|
||||||
card.dataset.base_model = model.base_model || 'Unknown';
|
card.dataset.base_model = model.base_model || 'Unknown';
|
||||||
card.dataset.favorite = model.favorite ? 'true' : 'false';
|
card.dataset.favorite = model.favorite ? 'true' : 'false';
|
||||||
|
const hasUpdateAvailable = Boolean(model.update_available);
|
||||||
|
card.dataset.update_available = hasUpdateAvailable ? 'true' : 'false';
|
||||||
|
|
||||||
// LoRA specific data
|
// LoRA specific data
|
||||||
if (modelType === MODEL_TYPES.LORA) {
|
if (modelType === MODEL_TYPES.LORA) {
|
||||||
@@ -507,6 +509,9 @@ export function createModelCard(model, modelType) {
|
|||||||
|
|
||||||
// Get favorite status from model data
|
// Get favorite status from model data
|
||||||
const isFavorite = model.favorite === true;
|
const isFavorite = model.favorite === true;
|
||||||
|
if (hasUpdateAvailable) {
|
||||||
|
card.classList.add('has-update');
|
||||||
|
}
|
||||||
|
|
||||||
// Generate action icons based on model type with i18n support
|
// Generate action icons based on model type with i18n support
|
||||||
const favoriteTitle = isFavorite ?
|
const favoriteTitle = isFavorite ?
|
||||||
@@ -531,6 +536,8 @@ export function createModelCard(model, modelType) {
|
|||||||
copyTitle = translate('modelCard.actions.copyLoRASyntax', {}, 'Copy value');
|
copyTitle = translate('modelCard.actions.copyLoRASyntax', {}, 'Copy value');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateBadgeLabel = translate('modelCard.badges.update', {}, 'Update');
|
||||||
|
const updateBadgeTooltip = translate('modelCard.badges.updateAvailable', {}, 'Update available');
|
||||||
const actionIcons = `
|
const actionIcons = `
|
||||||
<i class="${isFavorite ? 'fas fa-star favorite-active' : 'far fa-star'}"
|
<i class="${isFavorite ? 'fas fa-star favorite-active' : 'far fa-star'}"
|
||||||
title="${favoriteTitle}">
|
title="${favoriteTitle}">
|
||||||
@@ -568,9 +575,16 @@ export function createModelCard(model, modelType) {
|
|||||||
`<button class="toggle-blur-btn" title="${toggleBlurTitle}">
|
`<button class="toggle-blur-btn" title="${toggleBlurTitle}">
|
||||||
<i class="fas fa-eye"></i>
|
<i class="fas fa-eye"></i>
|
||||||
</button>` : ''}
|
</button>` : ''}
|
||||||
<span class="base-model-label ${shouldBlur ? 'with-toggle' : ''}" title="${model.base_model}">
|
<div class="card-header-info">
|
||||||
${model.base_model}
|
<span class="base-model-label ${shouldBlur ? 'with-toggle' : ''}" title="${model.base_model}">
|
||||||
</span>
|
${model.base_model}
|
||||||
|
</span>
|
||||||
|
${hasUpdateAvailable ? `
|
||||||
|
<span class="model-update-badge" title="${updateBadgeTooltip}">
|
||||||
|
${updateBadgeLabel}
|
||||||
|
</span>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
${actionIcons}
|
${actionIcons}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user