Skip to content

Instantly share code, notes, and snippets.

@RaschidJFR
Created November 14, 2019 20:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RaschidJFR/0ccccb022b369d1456155e0fda1aab3f to your computer and use it in GitHub Desktop.
Save RaschidJFR/0ccccb022b369d1456155e0fda1aab3f to your computer and use it in GitHub Desktop.
Ionic-Angular Updates Service (service worker)
// 1. Install Angular Service Worker: `$ ng add @angular/pwa --project app`
// 2. Generate icons: https://app-manifest.firebaseapp.com/
// 3. Add PWA icons for iOS in `index.html`:
// ```
// <link rel="apple-touch-icon" sizes="512x512" href="assets/icons/icon-512x512.png">
// <link rel="apple-touch-icon" sizes="192x192" href="assets/icons/icon-192x192.png">
// ```
// 4. Configure service worker in `ngsw-config.json`. Don't forget to add missing Ionic .svg files in `assetGroups[].resources.files`.
import { Injectable, ApplicationRef } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';
import { Platform, AlertController, ToastController } from '@ionic/angular';
import { first } from 'rxjs/operators';
/**
* This services handles automatic installation and updates for PWAs
*/
@Injectable({
providedIn: 'root'
})
export class UpdatesService {
private promptInstallEvent;
private toast: HTMLIonToastElement;
constructor(
private updates: SwUpdate,
private appRef: ApplicationRef,
private toastCtrl: ToastController,
private alertCtrl: AlertController,
private platform: Platform) {
this.appRef.isStable
.pipe(first(stable => stable === true))
.subscribe(() => this.init());
}
get isMobile() {
return this.platform.is('mobile');
}
get isPWAInstalled(): boolean {
return window.matchMedia('(display-mode: standalone)').matches || (window.navigator as any).standalone;
}
async init() {
console.log(`Runing app ${this.isPWAInstalled ? 'standalone' : 'in browser'}`);
this.updates.available.subscribe(async event => {
console.log('current version is', event.current);
console.log('available version is', event.available);
if (event.current !== event.available) {
const alert = await this.alertCtrl.create({
header: 'Actualización Disponible',
subHeader: 'Hay una nueva versión de la aplicación disponible',
message: '¿Deseas descargarla ahora?',
buttons: [
{
text: 'Actualizar',
handler: () => { this.updates.activateUpdate(); }
},
'Después'
]
});
alert.present();
}
});
this.updates.activated.subscribe(event => {
console.log('old version was', event.previous);
console.log('new version is', event.current);
});
await this.platform.ready();
if (!this.isMobile) {
this.checkForUpdate();
if (!this.isPWAInstalled) this.listenForInstallEvent();
}
}
async checkForUpdate() {
console.log('Check for updates');
try {
await this.updates.checkForUpdate();
} catch (e) {
console.debug('service worker not available');
}
}
private listenForInstallEvent() {
window.addEventListener('beforeinstallprompt', async (e) => {
e.preventDefault();
this.promptInstallEvent = e;
setTimeout(() => {
this.suggestInstall();
}, 3e3);
});
}
private async suggestInstall() {
this.toast = await this.toastCtrl.create({
message: 'Puedes usar esta app sin conexión',
buttons: [{
text: 'Descargar',
handler: () => { this.installPWA(); },
}, {
text: '',
icon: 'close'
}],
duration: 0,
});
this.toast.present();
}
private installPWA() {
this.toast.dismiss();
// Show the prompt
this.promptInstallEvent.prompt();
// Wait for the user to respond to the prompt
this.promptInstallEvent.userChoice
.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('User accepted the A2HS prompt');
} else {
console.log('User dismissed the A2HS prompt');
}
this.promptInstallEvent = null;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment