Suscripción a notificaciones push en iOS PWA falla silenciosamente porque el SW no controla la app

¡Hola :waving_hand:

Nos hemos encontrado con un comportamiento extraño (o probablemente un error…) al configurar las notificaciones push en la PWA de iOS. La interfaz de usuario actúa como si la suscripción a notificaciones push ya estuviera configurada, pero en segundo plano no ha ocurrido nada y el usuario nunca recibirá ninguna notificación push.

(tl;dr: Creo que sé cómo solucionarlo y puedo proporcionar un PR)

Pasos para reproducir :footprints:

El problema se refiere a habilitar las notificaciones push inmediatamente después de instalar la PWA en iOS.

  1. Abre tu instancia de Discourse en Safari móvil en iOS.
  2. Abre el menú de compartir y selecciona “Añadir a la pantalla de inicio”.
  3. Abre la nueva PWA desde tu pantalla de inicio.
  4. Verás un banner preguntándote si deseas habilitar las notificaciones push.
  5. Haz clic en el enlace “habilitar notificaciones”.
    1. Verás un diálogo del sistema: “xyz” desea enviarte notificaciones" - Acepta.
  6. Al navegar a tus preferencias de notificación, verás que las notificaciones en vivo no están habilitadas.
    1. Al verificar en el servidor, tampoco encontrarás un nuevo registro PushSubscription para el usuario.

Comportamiento esperado :books:

Después del paso 5, ya deberías recibir una notificación push indicando que las notificaciones están habilitadas. También debería haber un nuevo registro PushSubscription para tu usuario actual en la base de datos y su configuración para recibir notificaciones en vivo en la PWA debería estar habilitada.

Problema :bug:

En una PWA recién iniciada, el service worker se ha instalado y activado, pero aún no controla la página. Con esto, la verificación en lib/push-notifications.js, isPushNotificationsSupported(), seguirá devolviendo false, ya que navigation.serviceworker.controller devuelve null. Estas son las dos líneas importantes:

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

Con esto, la interfaz de usuario sugiere al usuario que todo está bien con su configuración, pero nunca recibirán ninguna notificación push.

En la primera carga, la PWA no está controlada y la llamada a subscribe() nunca se realiza, aunque el usuario haya concedido el permiso… :bug:

Los usuarios pueden solucionar el problema por sí mismos si saben cómo:

  1. Cierra completamente la PWA (deslízala hacia arriba para cerrarla…)
  2. Abre la PWA nuevamente.
  3. Ve a tus preferencias de notificación.
  4. Habilita notificaciones en vivo nuevamente.
  5. Esta vez, debería haber un nuevo registro PushSubscription y las notificaciones estarán configuradas.

Solución potencial :adhesive_bandage:

Solucioné este problema registrando otro service worker que llama a skipWaiting() y clients.claim() al instalar/activar. Al hacerlo, toma inmediatamente el control de la PWA, la suscripción se realiza correctamente y se crea el registro PushSubscription correspondiente.

Implementé esto como una “parche rápido” como parte de uno de mis plugins personalizados, para poder solucionar la situación para mis usuarios sin tener que profundizar en un fork del núcleo de Discourse…

Son solo dos cambios:

# 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());
});

Sin embargo, creo que esta corrección debería formar parte del núcleo de Discourse. Con lo que estoy haciendo, el plugin asume un control innecesario sobre la PWA. Puedo proporcionar un PR que ajuste las verificaciones en el núcleo de Discourse para que la suscripción funcione correctamente. Me gustaría escuchar tus opiniones al respecto, pero siéntete libre de expresarlas ahora mismo.

1 me gusta

Este es el PR con una corrección para el núcleo de Discourse → FIX: Allow push notification subscriptions on first launch of iOS PWA · Pull Request #39885 · discourse/discourse

Resuelve el problema descrito aquí, donde la suscripción falla silenciosamente y no llega al servidor. Sin embargo, lo que aún falta para estar absolutamente seguros es que la primera notificación push recibida no será enrutable dentro de la aplicación sin que el service worker controle la aplicación, por lo que sin que el usuario reinicie la aplicación.

Esto es algo que también podría agregar sobre mi PR. Pero no estoy 100% seguro de si la corrección es lo que se desea.

1 me gusta