Notification des modifications apportées aux notifications

Tout d'abord, je m'excuse pour ce titre horrible, mais je ne pouvais pas faire autrement.

Dans Chrome 44, Notfication.data et ServiceWorkerRegistration.getNotifications() sont ajoutés et ouvrent / simplifient certains cas d'utilisation courants concernant les notifications avec des messages push.

Données des notifications

Notification.data vous permet d'associer un objet JavaScript à une notification.

Pour résumer, lorsque vous recevez un message push, vous pouvez créer une notification avec certaines données. Dans l'événement de clic sur une notification, vous pouvez recevoir la notification sur laquelle l'utilisateur a cliqué et obtenir ses données.

Par exemple, créez un objet de données et ajoutez-le à vos options de notification comme suit:

self.addEventListener('push', function(event) {
    console.log('Received a push message', event);

    var title = 'Yay a message.';
    var body = 'We have received a push message.';
    var icon = '/images/icon-192x192.png';
    var tag = 'simple-push-demo-notification-tag';
    var data = {
    doge: {
        wow: 'such amaze notification data'
    }
    };

    event.waitUntil(
    self.registration.showNotification(title, {
        body: body,
        icon: icon,
        tag: tag,
        data: data
    })
    );
});

Cela signifie que nous pouvons obtenir les informations dans l'événement "notificationclick" :

self.addEventListener('notificationclick', function(event) {
    var doge = event.notification.data.doge;
    console.log(doge.wow);
});

Avant cela, vous deviez conserver des données dans IndexDB ou placer quelque chose à la fin de l'URL de l'icône.

ServiceWorkerRegistration.getNotifications()

Les développeurs qui travaillent sur les notifications push demandent souvent à mieux contrôler les notifications qu'ils affichent.

Un exemple de cas d'utilisation est une application de chat dans laquelle un utilisateur envoie plusieurs messages et que le destinataire affiche plusieurs notifications. Dans l'idéal, l'application Web devrait pouvoir détecter que vous avez plusieurs notifications qui n'ont pas été consultées et les regrouper dans une seule notification.

Sans getNotifications(), le mieux que vous puissiez faire est de remplacer la notification précédente par le dernier message. Avec getNotifications(), vous pouvez "réduire" les notifications si une notification est déjà affichée, ce qui améliore considérablement l'expérience utilisateur.

Exemple de regroupement de notifications.

Le code à utiliser est relativement simple. Dans votre événement push, appelez ServiceWorkerRegistration.getNotifications() pour obtenir un tableau des notifications actuelles, puis déterminez le comportement approprié, qu'il s'agisse de réduire toutes les notifications ou d'utiliser la balise Notification.

function showNotification(title, body, icon, data) {
    var notificationOptions = {
    body: body,
    icon: icon ? icon : 'images/touch/chrome-touch-icon-192x192.png',
    tag: 'simple-push-demo-notification',
    data: data
    };

    self.registration.showNotification(title, notificationOptions);
    return;
}

self.addEventListener('push', function(event) {
    console.log('Received a push message', event);

    // Since this is no payload data with the first version
    // of Push notifications, here we'll grab some data from
    // an API and use it to populate a notification
    event.waitUntil(
    fetch(API_ENDPOINT).then(function(response) {
        if (response.status !== 200) {
        console.log('Looks like there was a problem. Status Code: ' +
            response.status);
        // Throw an error so the promise is rejected and catch() is executed
        throw new Error();
        }

        // Examine the text in the response
        return response.json().then(function(data) {
        var title = 'You have a new message';
        var message = data.message;
        var icon = 'images/notification-icon.png';
        var notificationTag = 'chat-message';

        var notificationFilter = {
            tag: notificationTag
        };
        return self.registration.getNotifications(notificationFilter)
            .then(function(notifications) {
            if (notifications && notifications.length > 0) {
                // Start with one to account for the new notification
                // we are adding
                var notificationCount = 1;
                for (var i = 0; i < notifications.length; i++) {
                var existingNotification = notifications[i];
                if (existingNotification.data &&
                    existingNotification.data.notificationCount) {
                    notificationCount +=
existingNotification.data.notificationCount;
                } else {
                    notificationCount++;
                }
                existingNotification.close();
                }
                message = 'You have ' + notificationCount +
                ' weather updates.';
                notificationData.notificationCount = notificationCount;
            }

            return showNotification(title, message, icon, notificationData);
            });
        });
    }).catch(function(err) {
        console.error('Unable to retrieve data', err);

        var title = 'An error occurred';
        var message = 'We were unable to get the information for this ' +
        'push message';

        return showNotification(title, message);
    })
    );
});

self.addEventListener('notificationclick', function(event) {
    console.log('On notification click: ', event);

    if (Notification.prototype.hasOwnProperty('data')) {
    console.log('Using Data');
    var url = event.notification.data.url;
    event.waitUntil(clients.openWindow(url));
    } else {
    event.waitUntil(getIdb().get(KEY_VALUE_STORE_NAME,
event.notification.tag).then(function(url) {
        // At the moment you cannot open third party URL's, a simple trick
        // is to redirect to the desired URL from a URL on your domain
        var redirectUrl = '/redirect.html?redirect=' +
        url;
        return clients.openWindow(redirectUrl);
    }));
    }
});

La première chose à souligner avec cet extrait de code est que nous filtrons nos notifications en transmettant un objet de filtre à getNotifications(). Cela signifie que nous pouvons obtenir une liste de notifications pour une balise spécifique (dans cet exemple, pour une conversation particulière).

var notificationFilter = {
    tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)

Nous examinons ensuite les notifications visibles et vérifions si un nombre de notifications est associé à cette notification, et nous l'incrémentons en conséquence. Ainsi, si une notification indique à l'utilisateur qu'il y a deux messages non lus, nous souhaitons indiquer qu'il y en a trois lorsque qu'un nouveau push arrive.

var notificationCount = 1;
for (var i = 0; i < notifications.length; i++) {
    var existingNotification = notifications[i];
    if (existingNotification.data && existingNotification.data.notificationCount) {
    notificationCount += existingNotification.data.notificationCount;
    } else {
    notificationCount++;
    }
    existingNotification.close();
}

Une subtilité à souligner est que vous devez appeler close() sur la notification pour vous assurer qu'elle est supprimée de la liste des notifications. Il s'agit d'un bug dans Chrome, car chaque notification est remplacée par la suivante, car la même balise est utilisée. Pour le moment, ce remplacement n'est pas reflété dans le tableau renvoyé par getNotifications().

Il ne s'agit que d'un exemple d'utilisation de getNotifications() et, comme vous pouvez l'imaginer, cette API ouvre un éventail d'autres cas d'utilisation.

NotificationOptions.vibrate

Depuis Chrome 45, vous pouvez spécifier un modèle de vibration lorsque vous créez une notification. Sur les appareils compatibles avec l'API Vibration (actuellement, Chrome pour Android uniquement), vous pouvez personnaliser le motif de vibration utilisé lorsque la notification s'affiche.

Un modèle de vibration peut être un tableau de nombres ou un seul nombre traité comme un tableau d'un seul nombre. Les valeurs du tableau représentent les durées en millisecondes. Les indices pairs (0, 2, 4, etc.) représentent la durée de la vibration et les indices impairs la durée de pause à mettre en pause avant la prochaine vibration.

self.registration.showNotification('Buzz!', {
    body: 'Bzzz bzzzz',
    vibrate: [300, 100, 400] // Vibrate 300ms, pause 100ms, then vibrate 400ms
});

Autres demandes de fonctionnalités courantes restantes

La dernière demande de fonctionnalité courante des développeurs est la possibilité de fermer une notification après une certaine période ou la possibilité d'envoyer une notification push dans le seul but de fermer une notification si elle est visible.

Pour le moment, il n'existe aucun moyen de le faire, et rien dans la spécification ne le permet :( mais l'équipe d'ingénieurs Chrome est au courant de ce cas d'utilisation.

Notifications Android

Sur ordinateur, vous pouvez créer une notification avec le code suivant:

new Notification('Hello', {body: 'Yay!'});

Cette fonctionnalité n'a jamais été prise en charge sur Android en raison des restrictions de la plate-forme. Plus précisément, Chrome ne prend pas en charge les rappels sur l'objet Notification, tels que onclick. Toutefois, sur ordinateur, il est utilisé pour afficher les notifications des applications Web que vous avez peut-être ouvertes.

La seule raison pour laquelle je le mentionne est qu'à l'origine, une simple détection de fonctionnalités comme celle ci-dessous vous aiderait à prendre en charge le bureau et à ne pas générer d'erreurs sur Android:

if (!'Notification' in window) {
    // Notifications aren't supported
    return;
}

Toutefois, grâce à la prise en charge des notifications push dans Chrome pour Android, les notifications peuvent être créées à partir d'un ServiceWorker, mais pas à partir d'une page Web, ce qui signifie que cette fonctionnalité de détection n'est plus appropriée. Si vous essayez de créer une notification dans Chrome pour Android, le message d'erreur suivant s'affiche:

_Uncaught TypeError: Failed to construct 'Notification': Illegal constructor.
Use ServiceWorkerRegistration.showNotification() instead_

Pour le moment, le meilleur moyen de détecter des fonctionnalités pour Android et les ordinateurs est de procéder comme suit:

    function isNewNotificationSupported() {
        if (!window.Notification || !Notification.requestPermission)
            return false;
        if (Notification.permission == 'granted')
            throw new Error('You must only call this \*before\* calling
    Notification.requestPermission(), otherwise this feature detect would bug the
    user with an actual notification!');
        try {
            new Notification('');
        } catch (e) {
            if (e.name == 'TypeError')
                return false;
        }
        return true;
    }

Vous pouvez l'utiliser comme suit:

    if (window.Notification && Notification.permission == 'granted') {
        // We would only have prompted the user for permission if new
        // Notification was supported (see below), so assume it is supported.
        doStuffThatUsesNewNotification();
    } else if (isNewNotificationSupported()) {
        // new Notification is supported, so prompt the user for permission.
        showOptInUIForNotifications();
    }
.