The code powering m.abunchtell.com https://m.abunchtell.com
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

105 行
3.4 KiB

  1. const handlePush = (event) => {
  2. const options = event.data.json();
  3. options.body = options.data.nsfw || options.data.content;
  4. options.image = options.image || undefined; // Null results in a network request (404)
  5. options.timestamp = options.timestamp && new Date(options.timestamp);
  6. const expandAction = options.data.actions.find(action => action.todo === 'expand');
  7. if (expandAction) {
  8. options.actions = [expandAction];
  9. options.hiddenActions = options.data.actions.filter(action => action !== expandAction);
  10. options.data.hiddenImage = options.image;
  11. options.image = undefined;
  12. } else {
  13. options.actions = options.data.actions;
  14. }
  15. event.waitUntil(self.registration.showNotification(options.title, options));
  16. };
  17. const cloneNotification = (notification) => {
  18. const clone = { };
  19. for(var k in notification) {
  20. clone[k] = notification[k];
  21. }
  22. return clone;
  23. };
  24. const expandNotification = (notification) => {
  25. const nextNotification = cloneNotification(notification);
  26. nextNotification.body = notification.data.content;
  27. nextNotification.image = notification.data.hiddenImage;
  28. nextNotification.actions = notification.data.actions.filter(action => action.todo !== 'expand');
  29. return self.registration.showNotification(nextNotification.title, nextNotification);
  30. };
  31. const makeRequest = (notification, action) =>
  32. fetch(action.action, {
  33. headers: {
  34. 'Authorization': `Bearer ${notification.data.access_token}`,
  35. 'Content-Type': 'application/json',
  36. },
  37. method: action.method,
  38. credentials: 'include',
  39. });
  40. const openUrl = url =>
  41. self.clients.matchAll({ type: 'window' }).then(clientList => {
  42. if (clientList.length !== 0 && 'navigate' in clientList[0]) { // Chrome 42-48 does not support navigate
  43. const webClients = clientList
  44. .filter(client => /\/web\//.test(client.url))
  45. .sort(client => client !== 'visible');
  46. const visibleClient = clientList.find(client => client.visibilityState === 'visible');
  47. const focusedClient = clientList.find(client => client.focused);
  48. const client = webClients[0] || visibleClient || focusedClient || clientList[0];
  49. return client.navigate(url).then(client => client.focus());
  50. } else {
  51. return self.clients.openWindow(url);
  52. }
  53. });
  54. const removeActionFromNotification = (notification, action) => {
  55. const actions = notification.actions.filter(act => act.action !== action.action);
  56. const nextNotification = cloneNotification(notification);
  57. nextNotification.actions = actions;
  58. return self.registration.showNotification(nextNotification.title, nextNotification);
  59. };
  60. const handleNotificationClick = (event) => {
  61. const reactToNotificationClick = new Promise((resolve, reject) => {
  62. if (event.action) {
  63. const action = event.notification.data.actions.find(({ action }) => action === event.action);
  64. if (action.todo === 'expand') {
  65. resolve(expandNotification(event.notification));
  66. } else if (action.todo === 'request') {
  67. resolve(makeRequest(event.notification, action)
  68. .then(() => removeActionFromNotification(event.notification, action)));
  69. } else {
  70. reject(`Unknown action: ${action.todo}`);
  71. }
  72. } else {
  73. event.notification.close();
  74. resolve(openUrl(event.notification.data.url));
  75. }
  76. });
  77. event.waitUntil(reactToNotificationClick);
  78. };
  79. self.addEventListener('push', handlePush);
  80. self.addEventListener('notificationclick', handleNotificationClick);