feat: allinea lo swipe e lo scroll con l'avanzamento karaoke, aggiungi frecce di navigazione canti nel titolo

This commit is contained in:
David Frassi
2026-06-04 19:09:46 +02:00
parent 960c73fbd0
commit 92e955915e
12 changed files with 820 additions and 151 deletions
+90 -41
View File
@@ -19,68 +19,117 @@ export class AppComponent {
this.setupUpdates();
}
private async forceBypassCacheAndCheck(): Promise<boolean> {
try {
// 1. Forza il browser mobile a controllare la rete per aggiornamenti al Service Worker nativo
if ('serviceWorker' in navigator) {
const registrations = await navigator.serviceWorker.getRegistrations();
for (const registration of registrations) {
await registration.update();
console.log('[PWA-Update] Native Service Worker updated');
}
}
// 2. Forza il caricamento di ngsw.json bypassando le cache intermedie e locali
await fetch(`/ngsw.json?cb=${Date.now()}`, { cache: 'no-store' });
await fetch('/ngsw.json', { cache: 'reload' });
console.log('[PWA-Update] Caches successfully busted for ngsw.json');
} catch (e) {
console.warn('[PWA-Update] Failed to bust cache for ngsw.json:', e);
}
return await this.swUpdate.checkForUpdate();
}
private setupUpdates() {
if (this.swUpdate.isEnabled) {
// Wait for the application to stabilize before running update checks or starting intervals
const launchTime = Date.now();
// Ricarica automaticamente se il Service Worker controller cambia per garantire la freschezza immediata
if ('serviceWorker' in navigator) {
navigator.serviceWorker.addEventListener('controllerchange', () => {
console.log('[PWA-Update] Controller changed. Reloading page...');
window.location.reload();
});
}
// 1. Sottoscrizione all'evento di versione scaricata/pronta
this.swUpdate.versionUpdates
.pipe(filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'))
.subscribe(async () => {
const timeSinceLaunch = Date.now() - launchTime;
console.log(`[PWA-Update] New version ready! Time since launch: ${timeSinceLaunch}ms`);
if (timeSinceLaunch < 8000) {
// Se l'applicazione è appena stata aperta (< 8s), la aggiorniamo ed eseguiamo il reload immediato e silenzioso
console.log('[PWA-Update] Auto-activating update on startup...');
try {
await this.swUpdate.activateUpdate();
console.log('[PWA-Update] Update activated successfully, reloading page...');
window.location.reload();
} catch (err) {
console.error('[PWA-Update] Auto-activation failed on startup:', err);
// Fallback: ricarica comunque per provare a forzare l'attivazione
window.location.reload();
}
} else {
// Altrimenti mostriamo il prompt interattivo per evitare interruzioni improvvise
console.log('[PWA-Update] Showing toast prompt for active user...');
const toast = await this.toastCtrl.create({
message: 'Nuova versione dell\'applicazione disponibile!',
position: 'bottom',
color: 'secondary',
buttons: [
{
text: 'Aggiorna',
role: 'cancel',
handler: () => {
console.log('[PWA-Update] Activating update and reloading...');
this.swUpdate.activateUpdate().then(() => {
window.location.replace(window.location.origin + window.location.pathname + '?update=' + Date.now());
});
}
}
]
});
await toast.present();
}
});
// 2. Controllo IMMEDIATO all'avvio dell'applicazione (senza attendere lo stato isStable)
console.log('[PWA-Update] Startup: Checking for PWA updates immediately...');
this.forceBypassCacheAndCheck().catch(err => {
console.warn('[PWA-Update] Startup update check failed:', err);
});
// 3. Attiva i controlli periodici in background solo DOPO la stabilizzazione dell'app
this.appRef.isStable.pipe(
filter(stable => stable),
first()
).subscribe(() => {
console.log('[PWA-Update] App is stable. Initializing update checks...');
console.log('[PWA-Update] App is stable. Initializing background updates...');
// 1. Check for updates immediately
this.swUpdate.checkForUpdate().catch(err => {
console.warn('[PWA-Update] Failed immediate startup update check:', err);
});
// 2. Periodic check in background every 30 seconds
const every30Seconds$ = interval(30 * 1000);
every30Seconds$.subscribe(async () => {
console.log('[PWA-Update] Periodic check for updates (every 30s)...');
// Controllo periodico ogni 60 secondi
const every60Seconds$ = interval(60 * 1000);
every60Seconds$.subscribe(async () => {
console.log('[PWA-Update] Periodic check for updates (every 60s)...');
try {
await this.swUpdate.checkForUpdate();
await this.forceBypassCacheAndCheck();
} catch (err) {
console.warn('[PWA-Update] Failed periodic update check:', err);
console.warn('[PWA-Update] Periodic update check failed:', err);
}
});
});
// 3. Check for updates when the app is resumed/focused
// 4. Controllo quando l'utente torna sulla scheda o ripristina l'app (Visibility Change)
fromEvent(document, 'visibilitychange')
.pipe(filter(() => document.visibilityState === 'visible'))
.subscribe(async () => {
console.log('[PWA-Update] App resumed, checking for PWA updates...');
try {
await this.swUpdate.checkForUpdate();
await this.forceBypassCacheAndCheck();
} catch (err) {
console.warn('[PWA-Update] Failed visible resume update check:', err);
console.warn('[PWA-Update] Resume update check failed:', err);
}
});
// 4. Activate update and reload when a new version is ready (Show interactive toast)
this.swUpdate.versionUpdates
.pipe(filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'))
.subscribe(async () => {
console.log('[PWA-Update] New version ready! Showing toast prompt...');
const toast = await this.toastCtrl.create({
message: 'Nuova versione dell\'applicazione disponibile!',
position: 'bottom',
color: 'secondary',
buttons: [
{
text: 'Aggiorna',
role: 'cancel',
handler: () => {
console.log('[PWA-Update] Activating update and reloading...');
this.swUpdate.activateUpdate().then(() => {
window.location.replace(window.location.origin + window.location.pathname + '?update=' + Date.now());
});
}
}
]
});
await toast.present();
});
}
}
}