推播通知行为主要分成视觉、後续事件两大部分,前几天的文章开箱了:
这篇文章主要会更进一步解说视觉上可以进行设定的参数,以及收到通知後的行为,关於行为相关的参数如下。
{
"//": "行为相关参数",
"tag": "<String>",
"renotify": "<Boolean>",
"data": "<Anything>",
"requireInteraction": "<boolean>",
"silent": "<Boolean>",
"//": "视觉与行为参数",
"actions": "<Array of Strings>"
}
如果担心觉得太抽象,欢迎先用以下连结的通知产生器先试玩:
https://tests.peter.sh/notification-generator/
这次的 Demo 连结如下也欢迎各位大大试玩看看:
https://linyencheng-push-notification.herokuapp.com/
除了单纯 UI 显示相关的参数以外,接下来介绍一些会影响流程的相关参数:
Tag 这个设定是方便让讯息不要一直叠加,只要有同个 Tag 的新讯息就会关掉旧的并用新的取代,要注意的是後面取代的通知都不会触发装置的声音或是震动。
const title = "Notification 1 of 3";
const options = {
body: "With 'tag' of 'message-group-1'",
tag: "message-group-1",
};
registration.showNotification(title, options);
因为 Tag 的实作不会触发声音或是震动,在聊天软件中的某些情况下需要再次被叮咚,所以在 tag 的基础上增加了 renotify
这个配置。
const title = "Notification 2 of 2";
const options = {
tag: "renotify",
renotify: true,
};
registration.showNotification(title, options);
停用震动、铃声硬体通知。
const title = "Silent Notification";
const options = {
silent: true,
};
registration.showNotification(title, options);
需要等使用者针对通知互动後才会关闭通知,Android 没有这个问题但 Windows 7 桌面版本的通知会在一定时间後消失,直到 Windows 10 才会在通知列,所以有了这个配置。
const title = "Require Interaction Notification";
const options = {
body: "With \"requireInteraction: 'true'\".",
requireInteraction: true,
};
registration.showNotification(title, options);
透过定义 actions
就能够让通知带有按钮,将通知加上按钮後,就可以针对按钮补上後续的事件,以这次小编实作的功能来说,就是以下的配置。
self.registration.showNotification(data.title, {
image: "https://linyencheng.github.io/img/404-bg.jpg",
icon: "https://linyencheng.github.io/img/icon_wechat.png",
vibrate: [200, 100, 200, 100, 400],
body: "嗨,我是彦成,喜欢爬山的前端工程师,有个部落格叫前端三分钟 :)",
actions: [
{ action: "know-more", title: "了解更多" },
{ action: "fans", title: "按赞粉专" },
],
});
实作後实际的画面
经过相关进阶设定後,就是针对相关的事件进行後续的处理和优化:
透过 service worker 去监听点击的事件做後续处理。
self.addEventListener("notificationclick", function (event) {
const clickedNotification = event.notification;
});
点击通知後开启视窗并开启网页。
const examplePage = "/hello.html";
const promiseChain = clients.openWindow(examplePage);
event.waitUntil(promiseChain);
如果 URL 已经在浏览器中被开启就直接到那个页面。
const urlToOpen = new URL(examplePage, self.location.origin).href;
const promiseChain = clients
.matchAll({
type: "window",
includeUncontrolled: true,
})
.then((windowClients) => {
let matchingClient = null;
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
if (windowClient.url === urlToOpen) {
matchingClient = windowClient;
break;
}
}
if (matchingClient) {
return matchingClient.focus();
} else {
return clients.openWindow(urlToOpen);
}
});
event.waitUntil(promiseChain);
关闭通知也有相关事件。
self.addEventListener("notificationclose", function (event) {
const dismissedNotification = event.notification;
});
假设今天加入了 requireInteraction
通知就会常驻,若是通知一直叠加上去也是非常恼人,这时候就可以透过合并通知的设计来优化用户体验。
const promiseChain = registration.getNotifications().then((notifications) => {
let currentNotification;
for (let i = 0; i < notifications.length; i++) {
if (notifications[i].data && notifications[i].data.userName === userName) {
currentNotification = notifications[i];
}
}
return currentNotification;
});
if (currentNotification) {
currentNotification.close();
}
这次小编实作的程序码如下:
self.addEventListener("install", function (event) {
self.skipWaiting();
});
self.addEventListener("push", (event) => {
const data = event.data.json();
switch (data.title) {
case "前端三分钟":
self.registration.showNotification(data.title, {
image: "https://linyencheng.github.io/img/404-bg.jpg",
icon: "https://linyencheng.github.io/img/icon_wechat.png",
vibrate: [200, 100, 200, 100, 400],
body: "嗨,我是彦成,喜欢爬山的前端工程师,有个部落格叫前端三分钟 :)",
actions: [
{ action: "know-more", title: "了解更多" },
{ action: "fans", title: "按赞粉专" },
],
});
break;
default:
self.registration.showNotification(data.title, {
icon: "https://linyencheng.github.io/img/icon_wechat.png",
body: "恭喜! 成功注册推播通知",
});
break;
}
});
self.addEventListener("notificationclick", function (event) {
let url;
if (!event.action) {
console.log("Notification Click.");
return;
}
switch (event.action) {
case "know-more":
url = "https://linyencheng.github.io/";
break;
case "fans":
url = "https://www.facebook.com/linyencheng.tw";
break;
default:
console.log(`Unknown action clicked: '${event.action}'`);
break;
}
event.notification.close(); // Android 需要触发关闭
event.waitUntil(
clients.matchAll({ type: "window" }).then((windowClients) => {
// 看有没有开过了
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
// 有的话就 Focus 就好了
if (client.url === url && "focus" in client) {
return client.focus();
}
}
// 开新的页面
if (clients.openWindow) {
return clients.openWindow(url);
}
})
);
});
<<: 【程序】说是说不 转生成恶役菜鸟工程师避免 Bad End 的 30 件事 - 25
我跟男友开发这个聊天软件三年,刚刚回去算我们截至今天为止,总共在 firebase 上做了 168 ...
任何软件应用程序的开发都采用一种系统方法,该方法涉及从规划到部署的多个步骤,该方法称为软件开发生命周...
参考文章: https://medium.com/easons-murmuring/%E5%9C%A...
既然是电子书阅读器,一般人最常拿来用的功能应该就是看电子书吧。看电子书时如果要翻页的话,通常会点击画...
forEach 来看看forEach在MDN的定义 Array.prototype.forEach(...