diff --git a/src/components/update-notification.js b/src/components/update-notification.js
index af5532e..7df6e44 100644
--- a/src/components/update-notification.js
+++ b/src/components/update-notification.js
@@ -35,7 +35,7 @@ export class UpdateNotification {
if (getUpdateManager()) {
console.log('✅ [UpdateNotification] UpdateManager trovato, bind eventi notifica');
this.bindEvents();
-
+
// RIMOSSO: Il controllo dello stato iniziale può causare problemi
// L'updateManager dovrebbe emettere gli eventi corretti al momento giusto
} else {
@@ -357,10 +357,23 @@ export class UpdateNotification {
*/
bindButtonEvents() {
const buttons = this.container.querySelectorAll('[data-action]');
+ console.log('🔔 [UpdateNotification] Trovati', buttons.length, 'pulsanti con data-action');
buttons.forEach(button => {
+ console.log('🔔 [UpdateNotification] Binding evento per pulsante:', button.dataset.action);
button.addEventListener('click', (e) => {
- const action = e.target.dataset.action;
- this.handleAction(action);
+ // Trova il pulsante con data-action, anche se si clicca su un elemento figlio (come l'icona SVG)
+ let target = e.target;
+ while (target && !target.dataset.action) {
+ target = target.parentElement;
+ }
+
+ const action = target ? target.dataset.action : null;
+ console.log('🔔 [UpdateNotification] Target trovato:', target, 'Action:', action);
+ if (action) {
+ this.handleAction(action);
+ } else {
+ console.warn('🔔 [UpdateNotification] Nessuna azione trovata per questo click');
+ }
});
});
}
@@ -369,6 +382,7 @@ export class UpdateNotification {
* Handles button actions
*/
handleAction(action) {
+ console.log('🔔 [UpdateNotification] Azione pulsante:', action);
switch (action) {
case 'download':
this.startDownload();
@@ -538,14 +552,15 @@ export class UpdateNotification {
}
// Verifica se siamo in modalità sviluppo senza test mode
- const updateManager = getUpdateManager();
- if (updateManager && updateManager.isDevelopmentMode && updateManager.isDevelopmentMode()) {
- const hasTestMode = localStorage.getItem('presto_force_update_test') === 'true';
- if (!hasTestMode) {
- console.log('🔍 [UpdateNotification] Modalità sviluppo senza test mode - non mostro notifica');
- return;
- }
- }
+ // RIMOSSO: Ora permettiamo la notifica anche in modalità sviluppo per GitHub releases
+ // const updateManager = getUpdateManager();
+ // if (updateManager && updateManager.isDevelopmentMode && updateManager.isDevelopmentMode()) {
+ // const hasTestMode = localStorage.getItem('presto_force_update_test') === 'true';
+ // if (!hasTestMode) {
+ // console.log('🔍 [UpdateNotification] Modalità sviluppo senza test mode - non mostro notifica');
+ // return;
+ // }
+ // }
// Don't show if this version has been skipped
if (this.isVersionSkipped(updateInfo.version)) {
@@ -659,5 +674,5 @@ export class UpdateNotification {
}
}
-// Export singleton instance
-export const updateNotification = new UpdateNotification();
+// Export the class, not an instance - let main.js handle initialization
+// export const updateNotification = new UpdateNotification();
diff --git a/src/main.js b/src/main.js
index 2a22798..4e8d477 100644
--- a/src/main.js
+++ b/src/main.js
@@ -6,7 +6,7 @@ import { TeamManager } from './managers/team-manager.js';
// Auth manager will be imported after Supabase is loaded
import { PomodoroTimer } from './core/pomodoro-timer.js';
import { NotificationUtils } from './utils/common-utils.js';
-// Removed unused import: updateNotification
+import { UpdateNotification } from './components/update-notification.js';
// Global application state
let timer = null;
@@ -299,31 +299,31 @@ async function initializeEarlyTheme() {
// Helper function to check if Tauri is available and ready
function isTauriReady() {
- return typeof window !== 'undefined' &&
- window.__TAURI__ &&
- window.__TAURI__.core &&
- typeof window.__TAURI__.core.invoke === 'function';
+ return typeof window !== 'undefined' &&
+ window.__TAURI__ &&
+ window.__TAURI__.core &&
+ typeof window.__TAURI__.core.invoke === 'function';
}
// Helper function to wait for Tauri to be ready (with timeout)
function waitForTauri(maxWaitTime = 2000) {
return new Promise((resolve) => {
const startTime = Date.now();
-
+
const checkTauri = () => {
if (isTauriReady()) {
resolve(true);
return;
}
-
+
if (Date.now() - startTime > maxWaitTime) {
resolve(false);
return;
}
-
+
setTimeout(checkTauri, 50);
};
-
+
checkTauri();
});
}
@@ -331,10 +331,10 @@ async function initializeEarlyTheme() {
try {
// Wait for Tauri to be ready before trying to load settings
const tauriReady = await waitForTauri();
-
+
if (tauriReady) {
console.log('🎨 Tauri is ready, loading theme from settings...');
-
+
try {
const { invoke } = window.__TAURI__.core;
const savedSettings = await invoke('load_settings');
@@ -1467,19 +1467,19 @@ async function initializeApplication() {
console.log('🚀 Application already fully initialized, skipping...');
return;
}
-
+
// Prevent concurrent initialization attempts
if (window._appInitializing) {
console.log('🚀 Application initialization already in progress, skipping...');
return;
}
-
+
// Set initialization flag early to prevent race conditions
window._appInitializing = true;
-
+
try {
console.log('🚀 Initializing Presto application...');
-
+
// Show loading state
const loadingOverlay = document.createElement('div');
loadingOverlay.id = 'app-loading';
@@ -1512,7 +1512,7 @@ async function initializeApplication() {
if (stuckOverlay) {
console.error('⚠️ Initialization timeout - removing loading overlay');
stuckOverlay.remove();
-
+
// Show error message
NotificationUtils.showNotificationPing('Initialization timed out. Please refresh! 🔄', 'error');
}
@@ -1556,6 +1556,11 @@ async function initializeApplication() {
window.updateManager.loadPreferences(); // Carica le preferenze salvate se supportato
}
+ // Initialize Update Notification component
+ console.log('🔔 Initializing Update Notification...');
+ const updateNotification = new UpdateNotification();
+ window.updateNotification = updateNotification; // Make it globally available
+
// Skip first run authentication - proceed directly with guest mode
if (authManager.isFirstRun()) {
console.log('👋 First run detected, proceeding as guest...');
@@ -1613,7 +1618,7 @@ async function initializeApplication() {
// Clear safety timeout
clearTimeout(safetyTimeout);
-
+
// Mark as fully initialized
window._appFullyInitialized = true;
window._appInitializing = false;
@@ -1629,21 +1634,21 @@ async function initializeApplication() {
} catch (error) {
console.error('❌ Failed to initialize application:', error);
-
+
// Clear safety timeout and remove loading overlay even on error
clearTimeout(safetyTimeout);
const loadingOverlayError = document.getElementById('app-loading');
if (loadingOverlayError) {
loadingOverlayError.remove();
}
-
+
// Show error notification
NotificationUtils.showNotificationPing('Failed to initialize app. Please refresh! 🔄', 'error');
-
+
// Reset initialization flags on error so user can retry
window._appInitializing = false;
window._appFullyInitialized = false;
-
+
// Show error screen instead of leaving user with blank screen
const errorScreen = document.createElement('div');
errorScreen.id = 'app-error';
@@ -1891,9 +1896,10 @@ function setupUpdateManagement() {
}
});
- updateManager.on('checkError', () => {
+ updateManager.on('checkError', (event) => {
if (updateStatus) {
- updateStatus.innerHTML = 'Check failed';
+ const errorMessage = event?.detail?.message || 'Check failed';
+ updateStatus.innerHTML = `${errorMessage}`;
}
});
diff --git a/src/managers/update-manager-global.js b/src/managers/update-manager-global.js
index 632fe7a..6f7ed58 100644
--- a/src/managers/update-manager-global.js
+++ b/src/managers/update-manager-global.js
@@ -19,10 +19,8 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
// Eventi personalizzati
this.eventTarget = new EventTarget();
- // Inizializza il controllo automatico solo se non siamo in dev mode
- if (!this.isDevelopmentMode()) {
- this.startAutoCheck();
- }
+ // Inizializza il controllo automatico sempre (ora funziona anche in dev mode)
+ this.startAutoCheck();
console.log('✅ UpdateManager v2 inizializzato (global)');
}
@@ -99,15 +97,15 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
if (window.__TAURI__?.app?.getVersion) {
return await window.__TAURI__.app.getVersion();
}
-
+
if (window.__TAURI__?.core?.invoke) {
return await window.__TAURI__.core.invoke('plugin:app|version');
}
throw new Error('API versione non disponibile');
} catch (error) {
- console.warn('❌ Errore recupero versione:', error);
- return '0.2.2'; // fallback
+ console.error('❌ Impossibile ottenere la versione dell\'app:', error);
+ throw new Error('Impossibile determinare la versione corrente dell\'applicazione');
}
}
@@ -142,7 +140,7 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
enableTestMode() {
localStorage.setItem('presto_force_update_test', 'true');
console.warn('⚠️ MODALITÀ TEST AGGIORNAMENTI ATTIVATA');
-
+
if (!this.isDevelopmentMode() && this.autoCheck && !this.checkInterval) {
this.startAutoCheck();
}
@@ -156,7 +154,7 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
disableTestMode() {
localStorage.removeItem('presto_force_update_test');
console.log('ℹ️ Modalità test aggiornamenti disattivata');
-
+
if (this.isDevelopmentMode()) {
this.stopAutoCheck();
}
@@ -245,16 +243,18 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
* Avvia il controllo automatico degli aggiornamenti
*/
startAutoCheck() {
- if (this.autoCheck && !this.checkInterval && !this.isDevelopmentMode()) {
+ if (this.autoCheck && !this.checkInterval) {
// Controlla ogni ora
this.checkInterval = setInterval(() => {
+ console.log('🔄 Controllo automatico periodico degli aggiornamenti...');
this.checkForUpdates(false); // silent check
}, 60 * 60 * 1000);
- // Controllo iniziale dopo 30 secondi
+ // Controllo iniziale dopo 5 secondi
setTimeout(() => {
- this.checkForUpdates(false);
- }, 30000);
+ console.log('🔄 Controllo automatico iniziale degli aggiornamenti...');
+ this.checkForUpdates(false); // silent - mostra il banner se c'è un aggiornamento
+ }, 5000);
console.log('🔄 Controllo automatico aggiornamenti avviato');
}
@@ -277,7 +277,7 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
compareVersions(a, b) {
const cleanA = a.replace(/^v/, '');
const cleanB = b.replace(/^v/, '');
-
+
const aParts = cleanA.split('.').map(n => parseInt(n) || 0);
const bParts = cleanB.split('.').map(n => parseInt(n) || 0);
@@ -292,6 +292,83 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
return 0;
}
+ /**
+ * Controlla solo la versione da GitHub senza tentare l'installazione (per modalità sviluppo)
+ */
+ async checkVersionFromGitHub(showDialog = true) {
+ try {
+ // Ottieni versione corrente
+ let currentVersion;
+ try {
+ currentVersion = await this.getAppVersion();
+ console.log(`📋 Versione corrente: ${currentVersion}`);
+ } catch (error) {
+ console.error('❌ Errore nel recupero della versione corrente:', error);
+ this.emit('checkError', { error: 'Impossibile determinare la versione corrente' });
+ if (showDialog) {
+ alert('Impossibile verificare gli aggiornamenti: versione corrente non determinabile');
+ }
+ return false;
+ }
+
+ // Controlla ultima release su GitHub
+ const response = await fetch('https://api.github.com/repos/murdercode/presto/releases/latest');
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}`);
+ }
+
+ const githubRelease = await response.json();
+ const latestVersion = githubRelease.tag_name.replace(/^v/, '');
+
+ console.log(`📋 Ultima versione GitHub: ${latestVersion}`);
+
+ // Confronta versioni
+ if (this.compareVersions(latestVersion, currentVersion) <= 0) {
+ console.log('✅ Nessun aggiornamento disponibile');
+ this.updateAvailable = false;
+ this.currentUpdate = null;
+ this.emit('updateNotAvailable');
+
+ if (showDialog) {
+ alert(`Nessun aggiornamento disponibile.\n\nVersione corrente: ${currentVersion}\nUltima versione: ${latestVersion}`);
+ }
+ return false;
+ }
+
+ // Aggiornamento disponibile
+ console.log(`🎉 Aggiornamento disponibile: ${latestVersion}`);
+ this.updateAvailable = true;
+ this.currentUpdate = {
+ version: latestVersion,
+ body: githubRelease.body || '',
+ date: githubRelease.published_at
+ };
+
+ // console.log('📢 Emetto evento updateAvailable con:', this.currentUpdate); // Debug rimosso
+ this.emit('updateAvailable', this.currentUpdate);
+
+ if (showDialog) {
+ const message = `🎉 Aggiornamento disponibile!\n\n` +
+ `Versione corrente: ${currentVersion}\n` +
+ `Nuova versione: ${latestVersion}\n\n` +
+ `Nota: In modalità sviluppo, scarica manualmente da GitHub.`;
+ alert(message);
+ }
+
+ return true;
+
+ } catch (error) {
+ console.error('❌ Errore controllo versione GitHub:', error);
+ this.emit('checkError', { error: `Errore di rete: ${error.message}` });
+ if (showDialog) {
+ alert(`Errore nel controllo degli aggiornamenti:\n${error.message}`);
+ }
+ return false;
+ } finally {
+ this.isChecking = false;
+ }
+ }
+
/**
* Controlla se sono disponibili aggiornamenti usando approccio ibrido sicuro
*/
@@ -312,12 +389,9 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
const hasTestMode = localStorage.getItem('presto_force_update_test') === 'true';
if (isDevMode && !hasTestMode) {
- console.warn('⚠️ Modalità sviluppo - controllo disabilitato');
- this.emit('updateNotAvailable');
- if (showDialog) {
- await this.showDevelopmentMessage();
- }
- return false;
+ console.log('🔍 Modalità sviluppo - controllo tramite GitHub API senza installazione');
+ // In modalità sviluppo facciamo solo il controllo della versione senza installazione
+ return await this.checkVersionFromGitHub(showDialog);
}
// Se è modalità test, simula un aggiornamento
@@ -329,8 +403,21 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
// Controlla aggiornamenti reali
// 1. Prima prova con l'API GitHub per avere info complete
- const currentVersion = await this.getAppVersion();
- console.log(`📋 Versione corrente: ${currentVersion}`);
+ let currentVersion;
+ try {
+ currentVersion = await this.getAppVersion();
+ console.log(`📋 Versione corrente: ${currentVersion}`);
+ } catch (versionError) {
+ console.error('❌ Impossibile ottenere la versione corrente:', versionError.message);
+ this.updateAvailable = false;
+ this.currentUpdate = null;
+ if (!silent) {
+ this.eventTarget.dispatchEvent(new CustomEvent('checkError', {
+ detail: { message: 'Impossibile verificare la versione corrente dell\'applicazione' }
+ }));
+ }
+ return false;
+ }
// Controlla GitHub API
const response = await fetch('https://api.github.com/repos/StefanoNovelli/presto/releases/latest');
@@ -360,7 +447,7 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
if (tauriAPI) {
console.log('🔄 Usando API Tauri updater...');
const tauriUpdate = await tauriAPI.check();
-
+
if (tauriUpdate && tauriUpdate.available) {
console.log('✅ Aggiornamento confermato via Tauri API');
this.updateAvailable = true;
@@ -417,10 +504,10 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
*/
async simulateUpdate() {
console.log('🧪 Simulazione aggiornamento per test...');
-
+
const currentVersion = await this.getAppVersion();
const simulatedNewVersion = this.incrementVersion(currentVersion);
-
+
const update = {
version: simulatedNewVersion,
date: new Date().toISOString(),
@@ -490,16 +577,16 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
// Se supporta download automatico via Tauri
if (this.currentUpdate.isAutoDownloadable && this.currentUpdate.source === 'tauri-api') {
console.log('📥 Download automatico via Tauri...');
-
+
const tauriAPI = await this.getTauriUpdaterAPI();
if (tauriAPI && tauriAPI.downloadAndInstall) {
await tauriAPI.downloadAndInstall((progress) => {
console.log(`📥 Progresso download: ${progress}%`);
this.downloadProgress = progress;
- this.emit('downloadProgress', {
+ this.emit('downloadProgress', {
progress,
chunkLength: progress,
- contentLength: 100
+ contentLength: 100
});
});
@@ -511,10 +598,10 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
});
this.emit('downloadFinished');
-
+
// Installa e riavvia
this.emit('installFinished');
-
+
const shouldRestart = await this.askConfirmation(
'Aggiornamento scaricato e installato con successo!\n\nVuoi riavviare ora l\'applicazione?',
{ title: 'Aggiornamento Completato' }
@@ -528,7 +615,7 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
// Download manuale
console.log('🌐 Reindirizzamento a download manuale...');
await this.openDownloadUrl(this.currentUpdate.downloadUrl);
-
+
this.emit('downloadError', new Error('Download manuale richiesto'));
}
@@ -546,15 +633,15 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
*/
async simulateDownloadAndInstall() {
console.log('🧪 Simulazione download...');
-
+
// Simula progresso download
for (let i = 0; i <= 100; i += 10) {
await new Promise(resolve => setTimeout(resolve, 100));
this.downloadProgress = i;
- this.emit('downloadProgress', {
+ this.emit('downloadProgress', {
progress: i,
chunkLength: i,
- contentLength: 100
+ contentLength: 100
});
}
@@ -584,7 +671,7 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
*/
setAutoCheck(enabled) {
this.autoCheck = enabled;
-
+
if (enabled) {
this.startAutoCheck();
} else {
@@ -623,6 +710,7 @@ window.UpdateManagerV2 = class UpdateManagerV2 {
}
emit(event, data = null) {
+ // console.log(`📢 [UpdateManager] Emetto evento: ${event}`, data); // Debug rimosso
this.eventTarget.dispatchEvent(new CustomEvent(event, { detail: data }));
}
diff --git a/src/utils/theme-loader.js b/src/utils/theme-loader.js
index b121c03..a2f9c22 100644
--- a/src/utils/theme-loader.js
+++ b/src/utils/theme-loader.js
@@ -39,7 +39,7 @@ class ThemeLoader {
// that gets updated by the build process or manually maintained
// This could be enhanced to use a build-time script that generates this list
- const knownThemes = [
+ const knownThemes = [
'espresso.css',
'pipboy.css',
'pommodore64.css'