Las notificaciones de iOS pueden perder el permiso de envío si la notificación se suprime. El código de Discourse está configurado para suprimir opcionalmente las notificaciones y, por lo tanto, perderá el permiso de envío cuando esto ocurra tres veces.
Aquí está el código para el service worker de notificaciones push.
Este código tiene un error crítico en la línea 178. Allí, el service worker comprueba si el usuario está activo (es decir, no inactivo). En ese caso, el evento push devuelve falso sin mostrar una notificación.
(También comprueba payload.hide_when_active, pero resulta que hide_when_active es siempre verdadero, y por lo tanto este código siempre devuelve falso cuando el usuario está activo).
Apple prohíbe los envíos silenciosos, revocando el permiso de envío después de tres eventos que no muestran notificaciones
Esto no es aceptable según las reglas de Apple para las notificaciones push.
https://webkit.org/blog/12945/meet-web-push/
Potencia y privacidad
Tanto el proyecto de código abierto WebKit como Apple tratan la privacidad como un derecho humano fundamental. Al igual que con otras características privilegiadas de la plataforma web, solicitar una suscripción push requiere un gesto explícito del usuario. También requiere que establezca el indicador
userVisibleOnlyen verdadero, y que cumpla esa promesa mostrando siempre una notificación en respuesta a un mensaje push.La API Web Push no es una invitación para la ejecución en segundo plano silenciosa, ya que violaría la confianza del usuario y afectaría la duración de la batería del usuario.
Las violaciones de la promesa
userVisibleOnlyresultarán en la revocación de una suscripción push.
(énfasis mío)
Esto se explica con más detalle en el video WWDC de Apple sobre Web Pushes, en el minuto 9:57.
https://developer.apple.com/videos/play/wwdc2022/10098/?time=596
Observe que declaramos explícitamente que prometemos que las notificaciones push siempre serán visibles para el usuario. Si bien el estándar para la API JavaScript Push acomoda opcionalmente la ejecución en segundo plano silenciosa en respuesta a un push, la mayoría de los navegadores no lo admiten. Safari no lo admite.
… y luego en el minuto 13:35:
https://developer.apple.com/videos/play/wwdc2022/10098/?time=814
Como mencioné cuando les mostré el código sobre cómo solicitar una suscripción push, deben prometer que las notificaciones push serán visibles para el usuario. Manejar un evento push no es una invitación para que su JavaScript obtenga ejecución en segundo plano silenciosa. Hacerlo violaría tanto la confianza del usuario como la duración de la batería del usuario. Al manejar un evento push, de hecho se le exige que publique una notificación en el Centro de Notificaciones. Todos los demás navegadores tienen contramedidas contra la violación de la promesa de hacer visibles las notificaciones push, y Safari también. En la versión beta de macOS Ventura, después de tres eventos push en los que no se publique una notificación a tiempo, se revocará la suscripción push de su sitio. Deberá pasar nuevamente por el flujo de trabajo de permisos.
(énfasis mío)
Apple recomienda mostrar notificaciones inmediatamente, no después de cerrar notificaciones
El código recomendado por Apple se ve así, en el minuto 11:39:
https://developer.apple.com/videos/play/wwdc2022/10098/?time=699
self.addEventListener('push', (event) => {
let pushMessageJSON = event.data.json();
// Nuestro servidor pone todo lo necesario para mostrar la notificación
// en nuestros datos JSON.
event.waitUntil(self.registration.showNotification(pushMessageJSON.title, {
body: pushMessageJSON.body,
tag: pushMessageJSON.tag,
actions: [{
action: pushMessageJSON.actionURL,
title: pushMessageJSON.actionTitle,
}]
}));
}
¿Recuerdan que cuando nos suscribimos para recibir notificaciones push, nuestro JavaScript prometió que siempre serían visibles para el usuario? Eso significa que siempre debemos mostrar una notificación nativa de la plataforma en respuesta a cada push. Es mejor hacerlo lo antes posible en su manejador de eventos push.
El código de Discourse no sigue la mejor práctica recomendada. El código de Discourse primero cierra todas las notificaciones y solo después muestra una notificación.
Discourse siempre debe llamar a showNotification en respuesta a un evento push, y siempre debe hacerlo lo antes posible.