Add update check and change log

This commit is contained in:
Will Miao
2025-03-06 17:28:18 +08:00
parent 5e6cce936d
commit 61ea42353d
7 changed files with 386 additions and 112 deletions

View File

@@ -1,6 +1,7 @@
import { debounce } from './utils/debounce.js';
import { LoadingManager } from './managers/LoadingManager.js';
import { modalManager } from './managers/ModalManager.js';
import { updateService } from './managers/UpdateService.js';
import { state } from './state/index.js';
import { showLoraModal, toggleShowcase, scrollToTop } from './components/LoraCard.js';
import { loadMoreLoras, fetchCivitai, deleteModel, replacePreview, resetAndReload, refreshLoras } from './api/loraApi.js';
@@ -50,9 +51,10 @@ window.toggleShowcase = toggleShowcase;
window.scrollToTop = scrollToTop;
// Initialize everything when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
document.addEventListener('DOMContentLoaded', async () => {
state.loadingManager = new LoadingManager();
modalManager.initialize(); // Initialize modalManager after DOM is loaded
updateService.initialize(); // Initialize updateService after modalManager
window.downloadManager = new DownloadManager(); // Move this after modalManager initialization
window.filterManager = new FilterManager(); // Initialize filter manager

View File

@@ -2,7 +2,6 @@ export class ModalManager {
constructor() {
this.modals = new Map();
this.scrollPosition = 0;
this.updateAvailable = false;
}
initialize() {
@@ -75,9 +74,8 @@ export class ModalManager {
document.addEventListener('keydown', this.boundHandleEscape);
this.initialized = true;
// Initialize corner controls and update modal
// Initialize corner controls
this.initCornerControls();
this.initUpdateModal();
}
registerModal(id, config) {
@@ -159,79 +157,16 @@ export class ModalManager {
}
}
// Add method to initialize corner controls behavior
// Keep only the corner controls initialization
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));
// Toggle corner controls visibility
cornerControlsToggle.addEventListener('click', () => {
cornerControls.classList.toggle('expanded');
});
}
}
}

View File

@@ -0,0 +1,183 @@
import { modalManager } from './ModalManager.js';
export class UpdateService {
constructor() {
this.updateCheckInterval = 24 * 60 * 60 * 1000; // 24 hours
this.currentVersion = "v0.0.0"; // Initialize with default values
this.latestVersion = "v0.0.0"; // Initialize with default values
this.updateInfo = null;
this.updateAvailable = false;
this.updateNotificationsEnabled = localStorage.getItem('show_update_notifications') !== 'false';
this.lastCheckTime = parseInt(localStorage.getItem('last_update_check') || '0');
}
initialize() {
// Initialize update preferences from localStorage
const showUpdates = localStorage.getItem('show_update_notifications');
this.updateNotificationsEnabled = showUpdates === null || showUpdates === 'true';
// Register event listener for update notification toggle
const updateCheckbox = document.getElementById('updateNotifications');
if (updateCheckbox) {
updateCheckbox.checked = this.updateNotificationsEnabled;
updateCheckbox.addEventListener('change', (e) => {
this.updateNotificationsEnabled = e.target.checked;
localStorage.setItem('show_update_notifications', e.target.checked);
this.updateBadgeVisibility();
});
}
// Perform update check if needed
this.checkForUpdates();
// Set up event listener for update button
const updateToggle = document.querySelector('.update-toggle');
if (updateToggle) {
updateToggle.addEventListener('click', () => this.showUpdateModal());
}
// Immediately update modal content with current values (even if from default)
this.updateModalContent();
}
async checkForUpdates() {
// Check if we should perform an update check
const now = Date.now();
if (now - this.lastCheckTime < this.updateCheckInterval) {
// If we already have update info, just update the UI
if (this.updateAvailable) {
this.updateBadgeVisibility();
}
return;
}
try {
// Call backend API to check for updates
const response = await fetch('/loras/api/check-updates');
const data = await response.json();
if (data.success) {
this.currentVersion = data.current_version || "v0.0.0";
this.latestVersion = data.latest_version || "v0.0.0";
this.updateInfo = data;
// Determine if update is available
this.updateAvailable = data.update_available;
// Update last check time
this.lastCheckTime = now;
localStorage.setItem('last_update_check', now.toString());
// Update UI
this.updateBadgeVisibility();
this.updateModalContent();
console.log("Update check complete:", {
currentVersion: this.currentVersion,
latestVersion: this.latestVersion,
updateAvailable: this.updateAvailable
});
}
} catch (error) {
console.error('Failed to check for updates:', error);
}
}
updateBadgeVisibility() {
const updateToggle = document.querySelector('.update-toggle');
const updateBadge = document.querySelector('.update-toggle .update-badge');
const cornerBadge = document.querySelector('.corner-badge');
if (updateToggle) {
updateToggle.title = this.updateNotificationsEnabled && this.updateAvailable
? "Update Available"
: "Check Updates";
}
if (updateBadge) {
const shouldShow = this.updateNotificationsEnabled && this.updateAvailable;
updateBadge.classList.toggle('hidden', !shouldShow);
}
if (cornerBadge) {
const shouldShow = this.updateNotificationsEnabled && this.updateAvailable;
cornerBadge.classList.toggle('hidden', !shouldShow);
}
}
updateModalContent() {
const modal = document.getElementById('updateModal');
if (!modal) return;
// Update title based on update availability
const headerTitle = modal.querySelector('.update-header h2');
if (headerTitle) {
headerTitle.textContent = this.updateAvailable ? "Update Available" : "Check for Updates";
}
// Always update version information, even if updateInfo is null
const currentVersionEl = modal.querySelector('.current-version .version-number');
const newVersionEl = modal.querySelector('.new-version .version-number');
if (currentVersionEl) currentVersionEl.textContent = this.currentVersion;
if (newVersionEl) newVersionEl.textContent = this.latestVersion;
// Update changelog content if available
if (this.updateInfo && this.updateInfo.changelog) {
const changelogContent = modal.querySelector('.changelog-content');
if (changelogContent) {
changelogContent.innerHTML = ''; // Clear existing content
// Create changelog item
const changelogItem = document.createElement('div');
changelogItem.className = 'changelog-item';
const versionHeader = document.createElement('h4');
versionHeader.textContent = `Version ${this.latestVersion}`;
changelogItem.appendChild(versionHeader);
// Create changelog list
const changelogList = document.createElement('ul');
if (this.updateInfo.changelog && this.updateInfo.changelog.length > 0) {
this.updateInfo.changelog.forEach(item => {
const listItem = document.createElement('li');
listItem.textContent = item;
changelogList.appendChild(listItem);
});
} else {
// If no changelog items available
const listItem = document.createElement('li');
listItem.textContent = "No detailed changelog available. Check GitHub for more information.";
changelogList.appendChild(listItem);
}
changelogItem.appendChild(changelogList);
changelogContent.appendChild(changelogItem);
}
}
// Update GitHub link to point to the specific release if available
const githubLink = modal.querySelector('.update-link');
if (githubLink && this.latestVersion) {
const versionTag = this.latestVersion.replace(/^v/, '');
githubLink.href = `https://github.com/willmiao/ComfyUI-Lora-Manager/releases/tag/v${versionTag}`;
}
}
showUpdateModal() {
// Force a check for updates when showing the modal
this.manualCheckForUpdates().then(() => {
// Show the modal after update check completes
modalManager.showModal('updateModal');
});
}
async manualCheckForUpdates() {
this.lastCheckTime = 0; // Reset last check time to force check
await this.checkForUpdates();
}
}
// Create and export singleton instance
export const updateService = new UpdateService();