Abbonamento alle notifiche push in iOS PWA che fallisce silenziosamente a causa di SW che non controlla l'app

Ciao :waving_hand:

Abbiamo riscontrato un comportamento strano (o probabilmente un bug…) nella configurazione delle notifiche push nella PWA per iOS. L’interfaccia utente sembra indicare che la sottoscrizione alle notifiche push sia stata configurata, mentre in background non è ancora successo nulla e l’utente non riceverà mai nessuna notifica push.

(tl;dr: credo di sapere come risolverlo e posso fornire una PR)

Passaggi per riprodurre il problema :footprints:

Il problema riguarda l’abilitazione delle notifiche push immediatamente dopo l’installazione della PWA su iOS.

  1. Apri la tua istanza di Discourse su Safari mobile per iOS
  2. Apri il menu Condividi e scegli “Aggiungi alla schermata Home”
  3. Apri la nuova PWA dalla tua schermata Home
  4. Vedi un banner che ti chiede se desideri abilitare le notifiche push
  5. Clicca sul link “Abilita notifiche”
    1. Vedi un dialogo di sistema: “xyz” vorrebbe inviarti delle notifiche" - accettalo.
  6. Navigando verso le tue preferenze di notifica, vedrai che le notifiche in tempo reale non sono abilitate.
    1. Controllando sul server, non troverai nemmeno un nuovo record PushSubscription per l’utente.

Comportamento atteso :books:

Dopo il passaggio 5, dovresti giĂ  ricevere una notifica push che indica che le notifiche sono state abilitate. Dovrebbe esserci anche un nuovo record PushSubscription per il tuo utente corrente nel database e la sua impostazione per ricevere notifiche in tempo reale nella PWA dovrebbe essere abilitata.

Problema :bug:

Su una PWA appena avviata, il service worker è stato installato e attivato, ma non controlla ancora la pagina. Di conseguenza, il controllo in lib/push-notifications.js, isPushNotificationsSupported(), restituirà ancora false, poiché navigator.serviceWorker.controller restituisce null. Queste sono le due righe importanti:

navigator.serviceWorker.controller &&
navigator.serviceWorker.controller.state === "activated"

Di conseguenza, l’interfaccia utente suggerisce all’utente che tutto è a posto con la sua configurazione, ma non riceverà mai nessuna notifica push.

Al primo caricamento, la PWA non è controllata e la chiamata a subscribe() non viene mai eseguita, anche se l’utente ha concesso il permesso… :bug:

Gli utenti possono risolvere il problema da soli, se sanno come fare:

  1. Chiudere completamente la PWA (scorri via…)
  2. Riapri la PWA
  3. Vai alle tue preferenze di notifica
  4. Riabilita le notifiche in tempo reale
  5. → Questa volta, dovrebbe esserci un nuovo record PushSubscription e le notifiche saranno configurate correttamente.

Soluzione potenziale :adhesive_bandage:

Ho aggirato questo problema registrando un altro service worker che chiama skipWaiting() e clients.claim() durante l’installazione/attivazione. In questo modo, assume immediatamente il controllo della PWA, la sottoscrizione ha successo e viene creato il rispettivo record PushSubscription.

Ho distribuito questa soluzione come “hotfix” come parte di uno dei miei plugin personalizzati, in modo da poter risolvere la situazione per i miei utenti senza dover entrare in un fork del core di Discourse…

Sono solo due modifiche:

# plugin.rb
register_service_worker "push-notification-setup.js"
// assets/push-notification-setup.js
self.addEventListener("install", function () {
  self.skipWaiting();
});
		
		
self.addEventListener("activate", function (event) {	
  event.waitUntil(self.clients.claim());
});

Penso che questa correzione debba essere integrata nel core di Discourse. Con la mia soluzione attuale, il plugin assume un controllo non necessario sulla PWA. Posso fornire una PR che adatta i controlli nel core di Discourse in modo che la sottoscrizione funzioni effettivamente. Lascio la discussione qui, ma sentitevi liberi di esprimere le vostre opinioni sull’argomento.

1 Mi Piace

Questo è il PR con una correzione per il core di Discourse - FIX: Allow push notification subscriptions on first launch of iOS PWA · Pull Request #39885 · discourse/discourse

Risolto il problema descritto qui, con l’abbonamento che fallisce silenziosamente senza raggiungere il server. Ma ciò che manca ancora, per essere assolutamente sicuri, è che la prima notifica push ricevuta non sarà instradabile all’interno dell’app senza che il service worker controlli l’app, quindi senza che l’utente riavvii l’app.

Potrei aggiungere anche questo al mio PR. Ma non sono al 100% sicuro che la correzione sia quella desiderata.

1 Mi Piace