Add update notifications

This commit is contained in:
Will Miao
2025-03-05 22:03:54 +08:00
parent 493dff5c19
commit 5e6cce936d
6 changed files with 503 additions and 23 deletions

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;

View File

@@ -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')">&times;</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>

View File

@@ -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>