Las notificaciones de iOS pueden perder el permiso para enviar si el usuario está activo actualmente

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 userVisibleOnly en 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 userVisibleOnly resultará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.

8 Me gusta

@Falco / @featheredtoast ¿opiniones sobre esto?

¿Qué impacto tendría eliminar tanto la comprobación de cierre como la de inactividad?

En general, no estoy seguro en absoluto sobre esta comprobación de inactividad, siento que solo está causando confusión.

En el peor de los casos, si requerimos esto en Android o Desktop (no Safari), siempre podemos agregar una condición aquí, pero mi sensación es que deberíamos simplemente eliminar el código aquí.

Excelente depuración @dfabulich :hugs:

3 Me gusta

Entiendo que está bien hacer el cierre, supongo, siempre y cuando se haga después de llamar a showNotification.

… pero sinceramente no le veo el sentido a cerrar las notificaciones en absoluto. Bien podrían dejarse acumular en la bandeja de notificaciones, en mi opinión.

Nota: Esta API no debe usarse solo para eliminar la notificación de la pantalla después de un tiempo determinado, ya que este método también eliminará la notificación de cualquier bandeja de notificaciones, lo que impedirá que los usuarios interactúen con ella después de que se mostrara inicialmente. Un uso válido para esta API sería eliminar una notificación que ya no es relevante (por ejemplo, el usuario ya leyó la notificación en la página web en el caso de una aplicación de mensajería o la siguiente canción ya se está reproduciendo en una aplicación de música).

3 Me gusta

Según lo que he leído sobre este tema durante el fin de semana, ni siquiera podemos usar async/promises en el controlador de eventos push, debemos mostrarlo lo antes posible o Apple revocará sus derechos de notificación.

Todo esto concuerda con lo que dice @dfabulich.

Creo que estamos siendo demasiado “inteligentes” para nuestro propio bien, de hecho deberíamos eliminar todas las comprobaciones y simplemente mostrar la notificación.

6 Me gusta

¡No puedo agradecerte lo suficiente @dfabulich por descubrir esto!

3 Me gusta

OK, tengo una PR para esto.

@Falco / @featheredtoast ¿deberíamos fusionarla?

Si necesitamos omitir las notificaciones push, tenemos que hacerlo en el servidor, no en el cliente. La lógica de colapso siempre fue algo cuestionable, las aplicaciones no suelen hacer eso.

2 Me gusta

Ohh sí, tiene mucho más sentido enviar notificaciones solo cuando necesitan mostrarse. Debería suprimir notificaciones excesivas en otros lugares eventualmente, pero estoy de acuerdo con fusionar esto aquí :+1:

Re: colapso de notificaciones, es una lástima perderlo, pero… idealmente podríamos hacer algo similar a la autodestrucción de otras aplicaciones a medida que un usuario revisa las notificaciones en cualquier dispositivo conectado, pero eso podría requerir algo de trabajo adicional. La intención es la misma, nunca tener una avalancha de notificaciones obsoletas acumulándose. De nuevo, está bien, pero necesitamos revisarlo más tarde, dependiendo de cuánto problema cause.

2 Me gusta