mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
feat: add update badge to model modal versions tab
- Add CSS styling for tab badges with update indicator animation - Include update_available flag in model data parsing - Display animated badge on versions tab when updates are available - Improve tab button layout with flexbox alignment and spacing
This commit is contained in:
@@ -323,6 +323,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tab-btn {
|
.tab-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: var(--space-1);
|
||||||
padding: var(--space-1) var(--space-2);
|
padding: var(--space-1) var(--space-2);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -346,6 +350,51 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-btn .tab-label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn .tab-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: var(--border-radius-xs);
|
||||||
|
background: var(--badge-update-bg);
|
||||||
|
color: var(--badge-update-text);
|
||||||
|
font-size: 0.68em;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
box-shadow: 0 3px 10px var(--badge-update-glow);
|
||||||
|
border: 1px solid color-mix(in oklab, var(--badge-update-bg) 55%, transparent);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-badge--update {
|
||||||
|
animation: tab-badge-pulse 2.8s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn--has-update:not(.active) {
|
||||||
|
color: color-mix(in oklch, var(--text-color) 70%, var(--badge-update-bg) 30%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn--has-update.active {
|
||||||
|
border-bottom-color: var(--badge-update-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tab-badge-pulse {
|
||||||
|
0%, 100% {
|
||||||
|
box-shadow: 0 3px 10px color-mix(in oklch, var(--badge-update-glow) 100%, transparent);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 5px 14px color-mix(in oklch, var(--badge-update-glow) 90%, transparent);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tab-content {
|
.tab-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ async function showModelModalFromCard(card, modelType) {
|
|||||||
// Parse civitai metadata from the card's dataset
|
// Parse civitai metadata from the card's dataset
|
||||||
civitai: JSON.parse(card.dataset.meta || '{}'),
|
civitai: JSON.parse(card.dataset.meta || '{}'),
|
||||||
tags: JSON.parse(card.dataset.tags || '[]'),
|
tags: JSON.parse(card.dataset.tags || '[]'),
|
||||||
|
update_available: card.dataset.update_available === 'true',
|
||||||
modelDescription: card.dataset.modelDescription || '',
|
modelDescription: card.dataset.modelDescription || '',
|
||||||
// LoRA specific fields
|
// LoRA specific fields
|
||||||
...(modelType === MODEL_TYPES.LORA && {
|
...(modelType === MODEL_TYPES.LORA && {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export async function showModelModal(model, modelType) {
|
|||||||
...model,
|
...model,
|
||||||
civitai: completeCivitaiData
|
civitai: completeCivitaiData
|
||||||
};
|
};
|
||||||
|
const hasUpdateAvailable = Boolean(modelWithFullData.update_available);
|
||||||
|
|
||||||
// Prepare LoRA specific data with complete civitai data
|
// Prepare LoRA specific data with complete civitai data
|
||||||
const escapedWords = (modelType === 'loras' || modelType === 'embeddings') && modelWithFullData.civitai?.trainedWords?.length ?
|
const escapedWords = (modelType === 'loras' || modelType === 'embeddings') && modelWithFullData.civitai?.trainedWords?.length ?
|
||||||
@@ -67,15 +68,27 @@ export async function showModelModal(model, modelType) {
|
|||||||
const descriptionText = translate('modals.model.tabs.description', {}, 'Model Description');
|
const descriptionText = translate('modals.model.tabs.description', {}, 'Model Description');
|
||||||
const recipesText = translate('modals.model.tabs.recipes', {}, 'Recipes');
|
const recipesText = translate('modals.model.tabs.recipes', {}, 'Recipes');
|
||||||
const versionsText = translate('modals.model.tabs.versions', {}, 'Versions');
|
const versionsText = translate('modals.model.tabs.versions', {}, 'Versions');
|
||||||
|
const versionsBadgeLabel = translate('modelCard.badges.update', {}, 'Update');
|
||||||
|
const versionsTabBadge = hasUpdateAvailable
|
||||||
|
? `<span class="tab-badge tab-badge--update">${versionsBadgeLabel}</span>`
|
||||||
|
: '';
|
||||||
|
const versionsTabClasses = ['tab-btn'];
|
||||||
|
if (hasUpdateAvailable) {
|
||||||
|
versionsTabClasses.push('tab-btn--has-update');
|
||||||
|
}
|
||||||
|
const versionsTabButton = `<button class="${versionsTabClasses.join(' ')}" data-tab="versions">
|
||||||
|
<span class="tab-label">${versionsText}</span>
|
||||||
|
${versionsTabBadge}
|
||||||
|
</button>`.trim();
|
||||||
|
|
||||||
const tabsContent = modelType === 'loras' ?
|
const tabsContent = modelType === 'loras' ?
|
||||||
`<button class="tab-btn active" data-tab="showcase">${examplesText}</button>
|
`<button class="tab-btn active" data-tab="showcase">${examplesText}</button>
|
||||||
<button class="tab-btn" data-tab="description">${descriptionText}</button>
|
<button class="tab-btn" data-tab="description">${descriptionText}</button>
|
||||||
<button class="tab-btn" data-tab="recipes">${recipesText}</button>
|
${versionsTabButton}
|
||||||
<button class="tab-btn" data-tab="versions">${versionsText}</button>` :
|
<button class="tab-btn" data-tab="recipes">${recipesText}</button>` :
|
||||||
`<button class="tab-btn active" data-tab="showcase">${examplesText}</button>
|
`<button class="tab-btn active" data-tab="showcase">${examplesText}</button>
|
||||||
<button class="tab-btn" data-tab="description">${descriptionText}</button>
|
<button class="tab-btn" data-tab="description">${descriptionText}</button>
|
||||||
<button class="tab-btn" data-tab="versions">${versionsText}</button>`;
|
${versionsTabButton}`;
|
||||||
|
|
||||||
const loadingExampleImagesText = translate('modals.model.loading.exampleImages', {}, 'Loading example images...');
|
const loadingExampleImagesText = translate('modals.model.loading.exampleImages', {}, 'Loading example images...');
|
||||||
const loadingDescriptionText = translate('modals.model.loading.description', {}, 'Loading model description...');
|
const loadingDescriptionText = translate('modals.model.loading.description', {}, 'Loading model description...');
|
||||||
@@ -102,12 +115,6 @@ export async function showModelModal(model, modelType) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="recipes-tab" class="tab-pane">
|
|
||||||
<div class="recipes-loading">
|
|
||||||
<i class="fas fa-spinner fa-spin"></i> ${loadingRecipesText}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="versions-tab" class="tab-pane">
|
<div id="versions-tab" class="tab-pane">
|
||||||
<div class="model-versions-tab" data-model-id="${civitaiModelId}" data-model-type="${modelType}" data-current-version-id="${civitaiVersionId}">
|
<div class="model-versions-tab" data-model-id="${civitaiModelId}" data-model-type="${modelType}" data-current-version-id="${civitaiVersionId}">
|
||||||
@@ -115,6 +122,12 @@ export async function showModelModal(model, modelType) {
|
|||||||
<i class="fas fa-spinner fa-spin"></i> ${loadingVersionsText}
|
<i class="fas fa-spinner fa-spin"></i> ${loadingVersionsText}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="recipes-tab" class="tab-pane">
|
||||||
|
<div class="recipes-loading">
|
||||||
|
<i class="fas fa-spinner fa-spin"></i> ${loadingRecipesText}
|
||||||
|
</div>
|
||||||
</div>` :
|
</div>` :
|
||||||
`<div id="showcase-tab" class="tab-pane active">
|
`<div id="showcase-tab" class="tab-pane active">
|
||||||
<div class="recipes-loading">
|
<div class="recipes-loading">
|
||||||
|
|||||||
Reference in New Issue
Block a user