mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Add update notifications
This commit is contained in:
@@ -535,7 +535,7 @@ body.modal-open {
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--border-radius-xs);
|
||||
color: var(--text-color);
|
||||
color: var (--text-color);
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
overflow-x: auto;
|
||||
@@ -1131,4 +1131,232 @@ body.modal-open {
|
||||
.support-links {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update Modal Styles */
|
||||
.update-modal {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.update-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
margin-bottom: var(--space-3);
|
||||
padding-bottom: var(--space-2);
|
||||
border-bottom: 1px solid var(--lora-border);
|
||||
}
|
||||
|
||||
.update-icon {
|
||||
font-size: 1.8em;
|
||||
color: var(--lora-accent);
|
||||
animation: bounce 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
}
|
||||
|
||||
.update-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.update-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--lora-border);
|
||||
border-radius: var(--border-radius-sm);
|
||||
padding: var(--space-2);
|
||||
}
|
||||
|
||||
.version-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.current-version, .new-version {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 0.9em;
|
||||
color: var(--text-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.version-number {
|
||||
font-family: monospace;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.new-version .version-number {
|
||||
color: var(--lora-accent);
|
||||
}
|
||||
|
||||
.update-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
background: var(--lora-surface);
|
||||
border: 1px solid var(--lora-border);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
color: var(--text-color);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.update-link:hover {
|
||||
background: var(--lora-accent);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.changelog-section, .update-instructions {
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--lora-border);
|
||||
border-radius: var(--border-radius-sm);
|
||||
padding: var(--space-2);
|
||||
}
|
||||
|
||||
.changelog-section h3, .update-instructions h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: var(--space-2);
|
||||
color: var(--lora-accent);
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.changelog-content {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.changelog-item {
|
||||
margin-bottom: var(--space-2);
|
||||
padding-bottom: var(--space-2);
|
||||
border-bottom: 1px solid var(--lora-border);
|
||||
}
|
||||
|
||||
.changelog-item:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.changelog-item h4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
font-size: 1em;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.changelog-item ul {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.changelog-item li {
|
||||
margin-bottom: 4px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background: var(--lora-surface);
|
||||
border: 1px solid var(--lora-border);
|
||||
border-radius: var(--border-radius-xs);
|
||||
padding: var(--space-1) var(--space-2);
|
||||
margin: var(--space-1) 0;
|
||||
font-family: monospace;
|
||||
color: var(--text-color);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.update-info {
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.version-info {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update preferences section */
|
||||
.update-preferences {
|
||||
border-top: 1px solid var(--lora-border);
|
||||
margin-top: var(--space-2);
|
||||
padding-top: var(--space-2);
|
||||
}
|
||||
|
||||
/* Toggle switch styles */
|
||||
.toggle-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.toggle-switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.toggle-slider {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background-color: var(--border-color);
|
||||
border-radius: 20px;
|
||||
transition: .4s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.toggle-slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .toggle-slider {
|
||||
background-color: var(--lora-accent);
|
||||
}
|
||||
|
||||
input:checked + .toggle-slider:before {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.toggle-label {
|
||||
font-size: 0.9em;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.preference-note {
|
||||
margin-top: 4px;
|
||||
font-size: 0.8em;
|
||||
color: var(--text-color);
|
||||
opacity: 0.7;
|
||||
margin-left: 52px;
|
||||
}
|
||||
@@ -162,16 +162,109 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Update corner-controls for collapsible behavior */
|
||||
.corner-controls {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
z-index: var(--z-overlay);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.corner-controls-toggle {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
z-index: 2;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.corner-controls-toggle:hover {
|
||||
background: var(--lora-accent);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.corner-controls-items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
opacity: 0;
|
||||
transform: translateY(-10px) scale(0.9);
|
||||
transition: all 0.3s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Expanded state */
|
||||
.corner-controls.expanded .corner-controls-items {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
/* Expanded state - only expand on hover if not already expanded by click */
|
||||
.corner-controls:hover:not(.expanded) .corner-controls-items {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
/* Ensure hidden class works properly */
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Update toggle button styles */
|
||||
.update-toggle {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-color); /* Changed from var(--lora-accent) to match other toggles */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.update-toggle:hover {
|
||||
background: var(--lora-accent);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Update badge styles */
|
||||
.update-badge {
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
background-color: var(--lora-error);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 2px var(--card-bg);
|
||||
}
|
||||
|
||||
/* Badge on corner toggle */
|
||||
.corner-badge {
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* Folder Tags Container */
|
||||
.folder-tags-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@@ -560,10 +653,16 @@
|
||||
}
|
||||
|
||||
.corner-controls {
|
||||
/* Keep the fixed positioning even on mobile */
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.corner-controls-items {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.corner-controls.expanded .corner-controls-items {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.back-to-top {
|
||||
|
||||
@@ -2,6 +2,7 @@ export class ModalManager {
|
||||
constructor() {
|
||||
this.modals = new Map();
|
||||
this.scrollPosition = 0;
|
||||
this.updateAvailable = false;
|
||||
}
|
||||
|
||||
initialize() {
|
||||
@@ -62,8 +63,21 @@ export class ModalManager {
|
||||
}
|
||||
});
|
||||
|
||||
// Add updateModal registration
|
||||
this.registerModal('updateModal', {
|
||||
element: document.getElementById('updateModal'),
|
||||
onClose: () => {
|
||||
this.getModal('updateModal').element.style.display = 'none';
|
||||
document.body.classList.remove('modal-open');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', this.boundHandleEscape);
|
||||
this.initialized = true;
|
||||
|
||||
// Initialize corner controls and update modal
|
||||
this.initCornerControls();
|
||||
this.initUpdateModal();
|
||||
}
|
||||
|
||||
registerModal(id, config) {
|
||||
@@ -144,6 +158,82 @@ export class ModalManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add method to initialize corner controls behavior
|
||||
initCornerControls() {
|
||||
const cornerControls = document.querySelector('.corner-controls');
|
||||
const cornerControlsToggle = document.querySelector('.corner-controls-toggle');
|
||||
|
||||
if(cornerControls && cornerControlsToggle) {
|
||||
// Check for updates (mock implementation)
|
||||
this.checkForUpdates();
|
||||
|
||||
// Apply the initial badge state based on localStorage
|
||||
const showUpdates = localStorage.getItem('show_update_notifications');
|
||||
if (showUpdates === 'false') {
|
||||
this.updateBadgeVisibility(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modified update checker
|
||||
checkForUpdates() {
|
||||
// First check if user has disabled update notifications
|
||||
const showUpdates = localStorage.getItem('show_update_notifications');
|
||||
|
||||
// For demo purposes, we'll simulate an update being available
|
||||
setTimeout(() => {
|
||||
// We have an update available (mock)
|
||||
this.updateAvailable = true;
|
||||
|
||||
// Only show badges if notifications are enabled
|
||||
const shouldShow = showUpdates !== 'false';
|
||||
this.updateBadgeVisibility(shouldShow);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// Add method to initialize update modal
|
||||
initUpdateModal() {
|
||||
const updateModal = document.getElementById('updateModal');
|
||||
if (!updateModal) return;
|
||||
|
||||
const checkbox = updateModal.querySelector('#updateNotifications');
|
||||
if (!checkbox) return;
|
||||
|
||||
// Set initial state from localStorage or default to true
|
||||
const showUpdates = localStorage.getItem('show_update_notifications');
|
||||
checkbox.checked = showUpdates === null || showUpdates === 'true';
|
||||
|
||||
// Apply the initial badge visibility based on checkbox state
|
||||
this.updateBadgeVisibility(checkbox.checked);
|
||||
|
||||
// Add event listener for changes
|
||||
checkbox.addEventListener('change', (e) => {
|
||||
localStorage.setItem('show_update_notifications', e.target.checked);
|
||||
|
||||
// Immediately update badge visibility based on the new setting
|
||||
this.updateBadgeVisibility(e.target.checked);
|
||||
});
|
||||
}
|
||||
|
||||
// Enhanced helper method to update badge visibility
|
||||
updateBadgeVisibility(show) {
|
||||
const updateToggle = document.querySelector('.update-toggle');
|
||||
const updateBadge = document.querySelector('.update-toggle .update-badge');
|
||||
const cornerBadge = document.querySelector('.corner-badge');
|
||||
|
||||
if (updateToggle) {
|
||||
updateToggle.title = show && this.updateAvailable ? "Update Available" : "Check Updates";
|
||||
}
|
||||
|
||||
if (updateBadge) {
|
||||
updateBadge.classList.toggle('hidden', !(show && this.updateAvailable));
|
||||
}
|
||||
|
||||
if (cornerBadge) {
|
||||
cornerBadge.classList.toggle('hidden', !(show && this.updateAvailable));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export a singleton instance
|
||||
|
||||
@@ -16,13 +16,6 @@ export class SettingsManager {
|
||||
this.isOpen = !this.isOpen;
|
||||
}
|
||||
|
||||
/*
|
||||
showSettings() {
|
||||
console.log('Opening settings modal...'); // Debug log
|
||||
modalManager.showModal('settingsModal');
|
||||
}
|
||||
*/
|
||||
|
||||
async saveSettings() {
|
||||
const apiKey = document.getElementById('civitaiApiKey').value;
|
||||
|
||||
|
||||
@@ -215,4 +215,64 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Update Modal -->
|
||||
<div id="updateModal" class="modal">
|
||||
<div class="modal-content update-modal">
|
||||
<button class="close" onclick="modalManager.closeModal('updateModal')">×</button>
|
||||
<div class="update-header">
|
||||
<i class="fas fa-bell update-icon"></i>
|
||||
<h2>Update Available</h2>
|
||||
</div>
|
||||
<div class="update-content">
|
||||
<div class="update-info">
|
||||
<div class="version-info">
|
||||
<div class="current-version">
|
||||
<span class="label">Current Version:</span>
|
||||
<span class="version-number">v1.0.0</span>
|
||||
</div>
|
||||
<div class="new-version">
|
||||
<span class="label">New Version:</span>
|
||||
<span class="version-number">v1.1.0</span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/willmiao/ComfyUI-Lora-Manager" target="_blank" class="update-link">
|
||||
<i class="fas fa-external-link-alt"></i> View on GitHub
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="changelog-section">
|
||||
<h3>Changelog</h3>
|
||||
<div class="changelog-content">
|
||||
<div class="changelog-item">
|
||||
<h4>Version 1.1.0</h4>
|
||||
<ul>
|
||||
<li>Added support for custom folder structures</li>
|
||||
<li>Improved search functionality</li>
|
||||
<li>Fixed bug with loading large libraries</li>
|
||||
<li>Added new sorting options</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="update-instructions">
|
||||
<h3>How to Update</h3>
|
||||
<p>To update LoRA Manager, run the following command in your ComfyUI directory:</p>
|
||||
<div class="code-block">
|
||||
<code>git pull origin main</code>
|
||||
</div>
|
||||
<p>Or update through the ComfyUI Manager if you installed it that way.</p>
|
||||
</div>
|
||||
|
||||
<div class="update-preferences">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="updateNotifications" checked>
|
||||
<span class="toggle-slider"></span>
|
||||
<span class="toggle-label">Show update notifications</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,15 +47,25 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="corner-controls">
|
||||
<div class="theme-toggle" onclick="toggleTheme()" title="Toggle theme">
|
||||
<img src="/loras_static/images/theme-toggle-light.svg" alt="Theme" class="theme-icon light-icon">
|
||||
<img src="/loras_static/images/theme-toggle-dark.svg" alt="Theme" class="theme-icon dark-icon">
|
||||
<div class="corner-controls-toggle">
|
||||
<i class="fas fa-ellipsis-v"></i>
|
||||
<span class="update-badge corner-badge hidden"></span>
|
||||
</div>
|
||||
<div class="support-toggle" onclick="modalManager.showModal('supportModal')" title="Support">
|
||||
<i class="fas fa-heart"></i>
|
||||
</div>
|
||||
<div class="settings-toggle" onclick="settingsManager.toggleSettings()" title="Settings">
|
||||
<i class="fas fa-cog"></i>
|
||||
<div class="corner-controls-items">
|
||||
<div class="theme-toggle" onclick="toggleTheme()" title="Toggle theme">
|
||||
<img src="/loras_static/images/theme-toggle-light.svg" alt="Theme" class="theme-icon light-icon">
|
||||
<img src="/loras_static/images/theme-toggle-dark.svg" alt="Theme" class="theme-icon dark-icon">
|
||||
</div>
|
||||
<div class="update-toggle" onclick="modalManager.showModal('updateModal')" title="Check Updates">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span class="update-badge hidden"></span>
|
||||
</div>
|
||||
<div class="support-toggle" onclick="modalManager.showModal('supportModal')" title="Support">
|
||||
<i class="fas fa-heart"></i>
|
||||
</div>
|
||||
<div class="settings-toggle" onclick="settingsManager.toggleSettings()" title="Settings">
|
||||
<i class="fas fa-cog"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user