fix: correzione installabilità PWA e integrazione prompt installazione nativo

- Cambiate le proprietà 'scope' e 'start_url' in manifest.webmanifest a valori relativi ('./') al posto di un valore hardcoded '/ionic/'. Questo risolve il problema di installazione quando l'app viene pubblicata in directory diverse (es. root '/' vs sotto-cartella '/ionic/').
- Aggiunto il tracciamento del prompt di installazione nativo tramite l'evento 'beforeinstallprompt' nel SettingsService.
- Aggiunta la rilevazione dello stato standalone (app già installata) e del sistema operativo iOS.
- Inserita una sezione premium dedicata all'installazione nelle Impostazioni:
  * Su Android/Chrome: mostra un pulsante 'Installa' quando il browser conferma l'installabilità.
  * Su iOS (iPhone/iPad): mostra una guida collassabile con le istruzioni per installare l'app manualmente da Safari ('Condividi' -> 'Aggiungi alla schermata Home').
This commit is contained in:
David Frassi
2026-05-20 16:51:24 +02:00
parent e18c1c120b
commit d82d56a3cc
5 changed files with 104 additions and 3 deletions
+49
View File
@@ -49,7 +49,41 @@ export class SettingsService {
private wakeLock: any = null;
// PWA installation signals
public deferredPrompt = signal<any>(null);
public showInstallButton = signal<boolean>(false);
public isStandalone = signal<boolean>(false);
public isIos = signal<boolean>(false);
constructor() {
// Detect PWA status
try {
this.isStandalone.set(
window.matchMedia('(display-mode: standalone)').matches ||
(window.navigator as any).standalone === true
);
this.isIos.set(
/iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream
);
} catch (e) {
console.warn('Browser environment does not support display-mode media query');
}
window.addEventListener('beforeinstallprompt', (e: any) => {
// Prevent the mini-infobar from appearing on mobile
e.preventDefault();
// Stash the event so it can be triggered later.
this.deferredPrompt.set(e);
// Update UI notify the user they can install the PWA
this.showInstallButton.set(true);
});
window.addEventListener('appinstalled', () => {
this.deferredPrompt.set(null);
this.showInstallButton.set(false);
this.isStandalone.set(true);
console.log('PWA was installed');
});
const savedChords = localStorage.getItem('show-chords-default');
if (savedChords !== null) {
this.showChordsDefault.set(savedChords === 'true');
@@ -298,4 +332,19 @@ export class SettingsService {
this.enableAcousticAutoscroll.set(newValue);
localStorage.setItem('enable-acoustic-autoscroll', newValue.toString());
}
async installPwa() {
const promptEvent = this.deferredPrompt();
if (!promptEvent) {
return;
}
// Show the install prompt
promptEvent.prompt();
// Wait for the user to respond to the prompt
const { outcome } = await promptEvent.userChoice;
console.log(`User response to the install prompt: ${outcome}`);
// We've used the prompt, and can't use it again, discard it
this.deferredPrompt.set(null);
this.showInstallButton.set(false);
}
}