Implement early access handling and UI enhancements for LoRA downloads

- Added error handling for early access restrictions in the API routes, returning appropriate status codes and messages.
- Enhanced the Civitai client to log unauthorized access attempts and provide user-friendly error messages.
- Updated the download manager to check for early access requirements and log warnings accordingly.
- Introduced UI elements to indicate early access status for LoRAs, including badges and warning messages in the import manager.
- Improved toast notifications to inform users about early access download failures and provide relevant information.
This commit is contained in:
Will Miao
2025-03-23 14:45:11 +08:00
parent 93329abe8b
commit c402f53258
12 changed files with 448 additions and 27 deletions

View File

@@ -98,6 +98,7 @@
.version-info {
display: flex;
flex-wrap: wrap;
flex-direction: row !important;
gap: 8px;
align-items: center;
font-size: 0.9em;

View File

@@ -207,6 +207,15 @@
border-left: 4px solid var(--lora-warning);
}
.lora-item.is-early-access {
background: rgba(0, 184, 122, 0.05);
border-left: 4px solid #00B87A;
}
.lora-item.missing-locally {
border-left: 4px solid var(--lora-error);
}
.lora-thumbnail {
width: 80px;
height: 80px;
@@ -297,6 +306,12 @@
border-bottom: none;
}
.missing-lora-item.is-early-access {
background: rgba(0, 184, 122, 0.05);
border-left: 3px solid #00B87A;
padding-left: 10px;
}
.missing-badge {
display: inline-flex;
align-items: center;
@@ -682,3 +697,39 @@
min-height: 20px; /* Ensure there's always space for the error message */
font-weight: 500;
}
.early-access-warning {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 12px 16px;
background: rgba(0, 184, 122, 0.1);
border: 1px solid #00B87A;
border-radius: var(--border-radius-sm);
color: var(--text-color);
margin-bottom: var(--space-2);
}
/* Add special styling for early access badge in the missing loras list */
.missing-lora-item .early-access-badge {
padding: 2px 6px;
font-size: 0.75em;
margin-top: 4px;
display: inline-flex;
}
/* Specific styling for the early access warning container in import modal */
.early-access-warning .warning-icon {
color: #00B87A;
font-size: 1.2em;
}
.early-access-warning .warning-title {
font-weight: 600;
margin-bottom: 4px;
}
.early-access-warning .warning-text {
font-size: 0.9em;
line-height: 1.4;
}

View File

@@ -21,6 +21,59 @@
font-size: 0.9em;
}
/* Early Access Badge */
.early-access-badge {
display: inline-flex;
align-items: center;
background: #00B87A; /* Green for early access */
color: white;
padding: 4px 8px;
border-radius: var(--border-radius-xs);
font-size: 0.8em;
font-weight: 500;
white-space: nowrap;
flex-shrink: 0;
position: relative;
/* Force hardware acceleration to prevent Chrome scroll issues */
transform: translateZ(0);
will-change: transform;
}
.early-access-badge i {
margin-right: 4px;
font-size: 0.9em;
}
.early-access-info {
display: none;
position: absolute;
top: 100%;
right: 0;
background: var(--card-bg);
border: 1px solid #00B87A;
border-radius: var(--border-radius-xs);
padding: var(--space-1);
margin-top: 4px;
font-size: 0.9em;
color: var(--text-color);
white-space: normal;
word-break: break-all;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
z-index: 100; /* Higher z-index to ensure it's above other elements */
min-width: 300px;
max-width: 300px;
/* Create a separate layer with hardware acceleration */
transform: translateZ(0);
/* Use a fixed position to ensure it's in a separate layer from scrollable content */
position: fixed;
pointer-events: none; /* Don't block mouse events */
}
.early-access-badge:hover .early-access-info {
display: block;
pointer-events: auto; /* Allow interaction with the tooltip when visible */
}
.local-path {
display: none;
position: absolute;

View File

@@ -120,4 +120,63 @@
.tooltip:hover::after {
opacity: 1;
}
/* Toast Container for stacked notifications */
.toast-container {
position: fixed;
top: 0;
right: 0;
z-index: calc(var(--z-overlay) + 10);
display: flex;
flex-direction: column;
gap: 10px;
padding: 20px;
pointer-events: none; /* Allow clicking through the container */
width: 400px;
max-width: 100%;
}
/* Ensure each toast has pointer events */
.toast-container .toast {
pointer-events: auto;
position: relative; /* Override fixed positioning */
top: 0 !important; /* Let the container handle positioning */
right: 0 !important;
margin-bottom: 10px;
}
/* Add missing warning toast style */
.toast-warning {
border-left: 4px solid var(--lora-warning);
}
.toast-warning::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ff9800'%3E%3Cpath d='M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z'/%3E%3C/svg%3E");
}
/* Improve toast animation */
.toast {
transform: translateX(120%);
opacity: 0;
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.toast.show {
transform: translateX(0);
opacity: 1;
}
/* Responsive adjustments */
@media (max-width: 480px) {
.toast-container {
width: 100%;
padding: 10px;
}
.toast {
width: 100%;
max-width: none;
}
}