fix(pwa): progress bar setup loading, PWA install detection, Miei filter chip & UI cleanup
This commit is contained in:
+82
-66
@@ -304,30 +304,70 @@ export class AppComponent implements OnInit {
|
||||
console.log('[AppComponent] PWA appinstalled event caught.');
|
||||
localStorage.setItem('pwa-installed', 'true');
|
||||
this.isPwaInstalled.set(true);
|
||||
this.isInstalling.set(false);
|
||||
this.isRedirecting.set(true);
|
||||
this.showInstallOverlay.set(false);
|
||||
this.showRedirectOverlay.set(false);
|
||||
|
||||
if ((window as any).PwaLoader) {
|
||||
(window as any).PwaLoader.show();
|
||||
(window as any).PwaLoader.update({
|
||||
title: 'Chiudi il browser',
|
||||
desc: 'Applicazione installata con successo! Chiudi il browser e continua sulla PWA.',
|
||||
isRedirect: true
|
||||
});
|
||||
}
|
||||
|
||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||||
console.log('[AppComponent] Running on localhost - skipping protocol link redirect on appinstalled.');
|
||||
// Se la finestra è GIÀ stata trasformata in PWA standalone (es. Desktop Mac/Windows)
|
||||
const isStandalone = window.matchMedia('(display-mode: standalone)').matches || (navigator as any).standalone;
|
||||
if (isStandalone) {
|
||||
this.isInstalling.set(false);
|
||||
this.isRedirecting.set(false);
|
||||
this.checkLoaderDismissal();
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = this.protocolLink;
|
||||
}, 1000);
|
||||
// Su Android, l'evento 'appinstalled' scatta in 2-3 secondi, MA l'OS impiega 10-12s
|
||||
// per pacchettizzare e registrare il WebAPK nella schermata Home.
|
||||
// Calibriamo la progress bar spalmata su ~11 secondi reali prima del reindirizzamento.
|
||||
this.isInstalling.set(true);
|
||||
this.isRedirecting.set(false);
|
||||
|
||||
if ((window as any).PwaLoader) {
|
||||
(window as any).PwaLoader.show();
|
||||
(window as any).PwaLoader.update({
|
||||
title: 'Installazione applicazione',
|
||||
phase: 'Fase: Registrazione',
|
||||
desc: 'Generazione e registrazione dell\'applicazione sul dispositivo in corso...',
|
||||
percent: 15
|
||||
});
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
const TARGET_DURATION_MS = 11000; // 11 secondi reali per completare l'installazione WebAPK
|
||||
|
||||
const timer = setInterval(() => {
|
||||
const elapsed = Date.now() - startTime;
|
||||
let pct = Math.min(100, Math.round(15 + (elapsed / TARGET_DURATION_MS) * 85));
|
||||
|
||||
if ((window as any).PwaLoader) {
|
||||
(window as any).PwaLoader.update({ percent: pct });
|
||||
}
|
||||
|
||||
if (pct >= 100) {
|
||||
clearInterval(timer);
|
||||
this.isInstalling.set(false);
|
||||
this.isRedirecting.set(true);
|
||||
|
||||
if ((window as any).PwaLoader) {
|
||||
(window as any).PwaLoader.update({
|
||||
title: 'Chiudi il browser',
|
||||
desc: 'Applicazione installata con successo! Chiudi il browser e continua sulla PWA.',
|
||||
isRedirect: true
|
||||
});
|
||||
}
|
||||
|
||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||||
console.log('[AppComponent] Running on localhost - skipping protocol link redirect on appinstalled.');
|
||||
this.isRedirecting.set(false);
|
||||
this.checkLoaderDismissal();
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = this.protocolLink;
|
||||
}, 1000);
|
||||
}
|
||||
}, 250);
|
||||
});
|
||||
|
||||
this.checkAndRedirectToPwa();
|
||||
@@ -375,9 +415,8 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
|
||||
async checkVersionSync(): Promise<boolean> {
|
||||
// Controlla SEMPRE version.json per primo — è il modo più affidabile per
|
||||
// rilevare un disallineamento di versione, indipendentemente dallo stato del SW.
|
||||
// Su mobile, checkForUpdate() può essere lento o inaffidabile.
|
||||
// Verifica all'avvio se è disponibile una nuova versione remota (sia tramite version.json che SwUpdate)
|
||||
// Se disponibile, viene aggiornata e attivata automaticamente senza richiedere l'intervento dell'utente.
|
||||
try {
|
||||
console.log(`[PWA-Update] Verifica version.json all'avvio (locale=${VERSION})...`);
|
||||
const response = await Promise.race([
|
||||
@@ -387,10 +426,9 @@ export class AppComponent implements OnInit {
|
||||
if (response && response.ok) {
|
||||
const data = await response.json();
|
||||
if (data && data.version && data.version !== VERSION) {
|
||||
console.log(`[PWA-Update] Mismatch rilevato: locale=${VERSION}, remota=${data.version}. Forza aggiornamento...`);
|
||||
const overlay = showFullscreenUpdateOverlay();
|
||||
console.log(`[PWA-Update] Mismatch rilevato: locale=${VERSION}, remota=${data.version}. Avvio aggiornamento automatico...`);
|
||||
|
||||
// Prova ad attivare tramite SwUpdate se abilitato (scarica il nuovo bundle SW)
|
||||
// Scarica e attiva il nuovo Service Worker se abilitato
|
||||
if (this.swUpdate.isEnabled) {
|
||||
try {
|
||||
const hasSwUpdate = await Promise.race([
|
||||
@@ -398,7 +436,7 @@ export class AppComponent implements OnInit {
|
||||
new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 8000))
|
||||
]);
|
||||
if (hasSwUpdate) {
|
||||
console.log('[PWA-Update] SW aggiornamento disponibile, attivazione...');
|
||||
console.log('[PWA-Update] SW aggiornamento disponibile, attivazione automatica...');
|
||||
await Promise.race([
|
||||
this.swUpdate.activateUpdate(),
|
||||
new Promise<void>((resolve) => setTimeout(resolve, 5000))
|
||||
@@ -409,7 +447,7 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiorna anche la registrazione SW direttamente (doppia sicurezza)
|
||||
// Forziamo il controllo di aggiornamento della registrazione Service Worker
|
||||
if ('serviceWorker' in navigator) {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
@@ -419,7 +457,7 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
// Disattiva service worker attivi per forzare il refresh completo
|
||||
// Deregistra i vecchi Service Worker per applicare la nuova versione pulita
|
||||
if ('serviceWorker' in navigator) {
|
||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||
for (const registration of registrations) {
|
||||
@@ -427,7 +465,7 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
// Cancella le cache del browser
|
||||
// Pulisci le cache del browser
|
||||
if ('caches' in window) {
|
||||
const keys = await caches.keys();
|
||||
for (const key of keys) {
|
||||
@@ -435,9 +473,7 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
overlay.finish();
|
||||
|
||||
// Ricarica con parametro cache-busting per forzare l'allineamento remoto
|
||||
// Ricarica la pagina in modo trasparente
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('update_cb', Date.now().toString());
|
||||
window.location.replace(url.toString());
|
||||
@@ -450,13 +486,12 @@ export class AppComponent implements OnInit {
|
||||
console.warn('[PWA-Update] version.json check fallito:', e);
|
||||
}
|
||||
|
||||
// 2. Fallback: Prova SwUpdate nel caso in cui il controllo version.json sia fallito o sia stato servito dalla cache
|
||||
// Fallback: Controlla direttamente tramite SwUpdate se non intercettato da version.json
|
||||
if (this.swUpdate.isEnabled) {
|
||||
try {
|
||||
console.log('[PWA-Update] Verifica aggiornamenti via SwUpdate all\'avvio...');
|
||||
|
||||
let activated = false;
|
||||
let overlay: any = null;
|
||||
|
||||
const activateAndReload = async () => {
|
||||
if (activated) return;
|
||||
@@ -467,7 +502,6 @@ export class AppComponent implements OnInit {
|
||||
console.warn('[PWA-Update] activateUpdate fallito all\'avvio:', e);
|
||||
}
|
||||
|
||||
// Deregistra i vecchi SW e cancella le cache per un ricaricamento pulito
|
||||
if ('serviceWorker' in navigator) {
|
||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||
for (const reg of registrations) {
|
||||
@@ -481,43 +515,36 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
if (overlay) overlay.finish();
|
||||
setTimeout(() => {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('update_cb', Date.now().toString());
|
||||
window.location.replace(url.toString());
|
||||
}, 600);
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('update_cb', Date.now().toString());
|
||||
window.location.replace(url.toString());
|
||||
};
|
||||
|
||||
// Sottoscrivi PRIMA di verificare l'aggiornamento per evitare race condition
|
||||
const sub = this.swUpdate.versionUpdates
|
||||
.pipe(
|
||||
filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'),
|
||||
first()
|
||||
)
|
||||
.subscribe(() => {
|
||||
console.log('[PWA-Update] VERSION_READY ricevuto all\'avvio');
|
||||
console.log('[PWA-Update] VERSION_READY ricevuto all\'avvio, ricaricamento automatico...');
|
||||
activateAndReload();
|
||||
});
|
||||
|
||||
// Concedi fino a 8 secondi al controllo SW — le connessioni mobili possono essere lente
|
||||
const hasUpdate = await Promise.race([
|
||||
this.swUpdate.checkForUpdate(),
|
||||
new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 8000))
|
||||
]);
|
||||
|
||||
if (hasUpdate) {
|
||||
console.log('[PWA-Update] Aggiornamento rilevato via SwUpdate. Avvio download...');
|
||||
overlay = showFullscreenUpdateOverlay();
|
||||
console.log('[PWA-Update] Aggiornamento rilevato via SwUpdate. Applicazione automatica...');
|
||||
|
||||
// Timeout di sicurezza di 25 secondi: se VERSION_READY non arriva, attiva comunque
|
||||
setTimeout(() => {
|
||||
console.log('[PWA-Update] Safety timeout raggiunto all\'avvio, procedo...');
|
||||
sub.unsubscribe();
|
||||
activateAndReload();
|
||||
}, 25000);
|
||||
}, 15000);
|
||||
|
||||
return true; // Attendi il ricaricamento
|
||||
return true;
|
||||
} else {
|
||||
sub.unsubscribe();
|
||||
}
|
||||
@@ -546,34 +573,23 @@ export class AppComponent implements OnInit {
|
||||
const path = window.location.pathname;
|
||||
this.protocolLink = `web+canti://open${path}${search}`;
|
||||
|
||||
// Controlliamo se abbiamo già salvato che l'app è installata o se possiamo verificarlo
|
||||
let isInstalled = localStorage.getItem('pwa-installed') === 'true';
|
||||
if (!isInstalled && 'getInstalledRelatedApps' in navigator) {
|
||||
let isInstalled = false;
|
||||
if ('getInstalledRelatedApps' in navigator) {
|
||||
try {
|
||||
const relatedApps = await (navigator as any).getInstalledRelatedApps();
|
||||
isInstalled = relatedApps.length > 0;
|
||||
if (isInstalled) {
|
||||
localStorage.setItem('pwa-installed', 'true');
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to check installed apps:', e);
|
||||
}
|
||||
} else {
|
||||
isInstalled = localStorage.getItem('pwa-installed') === 'true';
|
||||
}
|
||||
|
||||
// Se non è rilevata in localStorage/relatedApps ed è Android o Desktop con supporto ai prompt:
|
||||
// attendiamo 1.5s per dare tempo all'evento 'beforeinstallprompt' di scattare.
|
||||
// Se non scatta, significa che l'app è già installata.
|
||||
if (!isInstalled && !this.settingsService.isIos() && ('onbeforeinstallprompt' in window)) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
isInstalled = localStorage.getItem('pwa-installed') === 'true';
|
||||
if (!isInstalled) {
|
||||
const hasPrompt = this.settingsService.showInstallButton() || this.settingsService.deferredPrompt();
|
||||
if (!hasPrompt) {
|
||||
console.log('[AppComponent] PWA detected as already installed (onbeforeinstallprompt supported but no prompt fired).');
|
||||
isInstalled = true;
|
||||
localStorage.setItem('pwa-installed', 'true');
|
||||
}
|
||||
}
|
||||
// Se prima era salvata come installata ma l'utente riceve il prima possibile un beforeinstallprompt,
|
||||
// significa che l'app è stata disinstallata!
|
||||
if (this.settingsService.deferredPrompt() || this.settingsService.showInstallButton()) {
|
||||
isInstalled = false;
|
||||
localStorage.setItem('pwa-installed', 'false');
|
||||
}
|
||||
|
||||
this.isPwaInstalled.set(isInstalled);
|
||||
|
||||
Reference in New Issue
Block a user