إبلاغك بالتغييرات التي تطرأ على الإشعارات

أولاً، نعتذر عن هذا العنوان السيئ، ولكن لم يكن بإمكاننا تجنُّبه.

في Chrome 44، تتم إضافة Notfication.data و ServiceWorkerRegistration.getNotifications() يتم فتحهما أو تبسيط بعض حالات الاستخدام الشائعة عند التعامل مع الإشعارات التي تحتوي على رسائل فورية.

بيانات الإشعارات

تتيح لك Notification.data ربط كائن JavaScript بالإشعار.

في الأساس، يعني ذلك أنّه عند تلقّي رسالة فورية، يمكنك إنشاء إشعار يتضمّن بعض البيانات، ثم في حدث النقر على الإشعار، يمكنك الحصول على الإشعار الذي تم النقر عليه والاطّلاع على بياناته.

على سبيل المثال، إنشاء عنصر بيانات وإضافته إلى خيارات الإشعارات على النحو التالي:

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

يعني ذلك أنّه يمكننا الحصول على المعلومات في حدث notificationclick:

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

قبل ذلك، كان عليك تخزين البيانات في IndexDB أو وضع شيء ما في نهاية عنوان URL الخاص بالرمز - حسنًا.

ServiceWorkerRegistration.getNotifications()

من الطلبات الشائعة التي يقدّمها المطوّرون الذين يعملون على إشعارات فورية هي التمكّن من التحكّم بشكلٍ أفضل في الإشعارات التي يتم عرضها.

على سبيل المثال، تطبيق محادثة يرسل فيه المستخدم عدة رسائل ويعرض المستلِم إشعارات متعددة. من المفترض أن يرصد تطبيق الويب أنّ لديك عدة إشعارات لم تتم مشاهدتها ويدمجها في إشعار واحد.

بدون الإجراء getNotifications() ، أفضل ما يمكنك فعله هو استبدال الإشعار السابق بأحدث رسالة. باستخدام getNotifications()‎، يمكنك "تصغير" الإشعارات إذا سبق أن تم عرض إشعار، ما يؤدي إلى توفير تجربة أفضل للمستخدم.

مثال على تجميع الإشعارات معًا

إنّ الرمز البرمجي لتنفيذ ذلك بسيط نسبيًا. من داخل الحدث الفوري، يمكنك استدعاء ServiceWorkerregister.getNotifications() للحصول على مجموعة من الإشعارات الحالية وتحديد السلوك الصحيح، سواء كان ذلك تصغير جميع الإشعارات أو باستخدام Notification.tag.

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

أول ما يجب تسليط الضوء عليه في مقتطف الرمز البرمجي هذا هو أنّنا لفلترة الإشعارات، نُمرِّر عنصر فلتر إلى getNotifications(). وهذا يعني أنّه يمكننا الحصول على قائمة بالإشعارات لعلامة معيّنة (في هذا المثال، لمناقشة معيّنة).

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

بعد ذلك، نراجع الإشعارات المرئية ونتحقق ممّا إذا كان هناك عدد إشعارات مرتبط بهذا الإشعار ونزيده استنادًا إلى ذلك. بهذه الطريقة، إذا كان هناك إشعار واحد يخبر المستخدم بوجود رسالتين غير مقروءتين، فإننا نرغب في الإشارة إلى وجود ثلاث رسائل غير مقروءة عندما تصل دفعة جديدة.

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

يُرجى العِلم أنّه عليك الاتصال بالرقم close() في الإشعار لتأكيد إزالة الإشعار من قائمة الإشعارات. وهذا خطأ في Chrome إذ يتم استبدال كل إشعار بالإشعار الذي يليه بسبب استخدام العلامة نفسها. في الوقت الحالي، لا يظهر هذا الاستبدال في الصفيف المعروض من getNotifications().

هذا مثال واحد فقط على دالة getNotifications()، وكما يمكنك أن تتخيل، توفّر واجهة برمجة التطبيقات هذه مجموعة من حالات الاستخدام الأخرى.

NotificationOptions.vibrate

اعتبارًا من الإصدار 45 من Chrome، يمكنك تحديد نمط الاهتزاز عند إنشاء إعلام. يتيح لك هذا الإعداد تخصيص نمط الاهتزاز الذي سيتم استخدامه عند عرض الإشعار على الأجهزة المتوافقة مع واجهة برمجة تطبيقات الاهتزاز (Chrome لنظام Android فقط) حاليًا.

يمكن أن يكون نمط الاهتزاز صفيفًا من الأرقام أو رقمًا واحدًا يتم التعامل معه كصفيف من رقم واحد. تمثّل القيم في المصفوفة الأوقات بالمللي ثانية، مع الإشارة إلى أنّ الفهارس الزوجية (0 و2 و4 وما إلى ذلك) هي المدة التي يتم فيها الاهتزاز، وتكون الفهارس الفردية هي المدة التي يتم فيها التوقف قبل الاهتزاز التالي.

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

طلبات الميزات الشائعة المتبقية

إنّ الميزة الشائعة المتبقية التي يطلبها المطوّرون هي إمكانية إغلاق إشعار بعد فترة زمنية معيّنة أو إمكانية إرسال إشعار push بغرض إغلاق إشعار فقط إذا كان مرئيًا.

في الوقت الحالي، لا تتوفّر طريقة لإجراء ذلك ولا تتضمّن المواصفات أيّ ميزة تسمح بذلك :( ولكنّ فريق هندسة Chrome على دراية بهذه الحالة.

إشعارات Android

على الكمبيوتر المكتبي، يمكنك إنشاء إشعار باستخدام الرمز البرمجي التالي:

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

لم يكن هذا الإجراء متوافقًا مع Android مطلقًا بسبب قيود النظام الأساسي: لا يمكن لتطبيق Chrome تحديدًا إتاحة طلبات إعادة الاتصال في عنصر الإشعار، مثل onclick. ولكن يتم استخدامه على سطح المكتب لعرض إشعارات لتطبيقات الويب التي قد تكون مفتوحة حاليًا.

السبب الوحيد الذي أشير إليه هو أنّ ميزة رصد بسيطة مثل الميزة أدناه ستساعدك في الأصل على إتاحة التطبيق على أجهزة الكمبيوتر المكتبي ولن تتسبب في أي أخطاء على Android:

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

ومع ذلك، أصبح من الممكن إنشاء إشعارات من ServiceWorker بدلاً من الإشعارات الفورية على Chrome لنظام Android الآن، ولكن ليس من صفحة ويب، ما يعني أنّ اكتشاف هذه الميزة لم يعد مناسبًا. إذا حاولت إنشاء إشعار على Chrome لنظام التشغيل Android، ستظهر لك رسالة الخطأ التالية:

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

في الوقت الحالي، أفضل طريقة لرصد الميزات على أجهزة Android وأجهزة الكمبيوتر المكتبي هي تنفيذ الخطوات التالية:

    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;
    }

ويمكن استخدامها على النحو التالي:

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