我们如何根据icon
和body
动态定制浏览器通知@challenge.image
和@challenge.description
?
点击webpush-button
,我收到了弹出通知,但只有消息的title
动态更改。如何才能使其适用于body
和icon
?
挑战/ show.html.erb
<script>
$('.webpush-button').on('click', (e) => {
navigator.serviceWorker.ready
.then((serviceWorkerRegistration) => {
serviceWorkerRegistration.pushManager.getSubscription()
.then((subscription) => {
$.post('/push', {
subscription: subscription.toJSON(),
message: "<%= @challenge.name %>", # This works dynamically for the title, but how can I get message to also dynamically send body and icon so I can use <%= @challenge.image %> for icon and <%= @challenge.description %> for body?
});
});
});
});
</script>
push_notifications_controller
class PushNotificationsController < ApplicationController
def push
Webpush.payload_send(
message: params[:message],
endpoint: params[:subscription][:endpoint],
p256dh: params[:subscription][:keys][:p256dh],
auth: params[:subscription][:keys][:auth],
vapid: {
subject: "mailto:sender@example.com",
public_key: ENV['VAPID_PUBLIC_KEY'],
private_key: ENV['VAPID_PRIVATE_KEY']
}
)
end
end
的application.js
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/serviceworker.js')
.then(function(reg) {
console.log('Service worker change, registered the service worker');
});
}
// Otherwise, no push notifications :(
else {
console.error('Service worker is not supported in this browser');
}
// When serviceWorker is supported, installed, and activated,
// subscribe the pushManager property with the vapidPublicKey
navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
serviceWorkerRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: window.vapidPublicKey
});
});
// Let's check if the browser supports notifications
if (!("Notification" in window)) {
console.error("This browser does not support desktop notification");
}
// Let's check whether notification permissions have already been granted
else if (Notification.permission === "granted") {
console.log("Permission to receive notifications has been granted");
}
// Otherwise, we need to ask the user for permission
else if (Notification.permission !== 'denied') {
Notification.requestPermission(function (permission) {
// If the user accepts, let's create a notification
if (permission === "granted") {
console.log("Permission to receive notifications has been granted");
}
});
}
serviceworker.js.erb
console.log('[Service Worker] Hello world!');
var CACHE_VERSION = 'v1';
var CACHE_NAME = CACHE_VERSION + ':sw-cache-';
function onInstall(event) {
console.log('[Serviceworker]', "Installing!", event);
event.waitUntil(
caches.open(CACHE_NAME).then(function prefill(cache) {
return cache.addAll([
// make sure serviceworker.js is not required by application.js
// if you want to reference application.js from here
'<%#= asset_path "application.js" %>',
'<%= asset_path "application.css" %>',
'/offline.html',
]);
})
);
}
function onActivate(event) {
console.log('[Serviceworker]', "Activating!", event);
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName) {
// Return true if you want to remove this cache,
// but remember that caches are shared across
// the whole origin
return cacheName.indexOf(CACHE_VERSION) !== 0;
}).map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
);
}
// Borrowed from https://github.com/TalAter/UpUp
function onFetch(event) {
event.respondWith(
// try to return untouched request from network first
fetch(event.request).catch(function() {
// if it fails, try to return request from the cache
return caches.match(event.request).then(function(response) {
if (response) {
return response;
}
// if not found in cache, return default offline content for navigate requests
if (event.request.mode === 'navigate' ||
(event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
console.log('[Serviceworker]', "Fetching offline content", event);
return caches.match('/offline.html');
}
})
})
);
}
self.addEventListener("push", (event) => {
let title = (event.data && event.data.text()) || "Yay a message";
let body = "We have received a push message";
let icon = '/assets/default.png';
event.waitUntil(
self.registration.showNotification(title, { title,body, icon })
)
});
self.addEventListener('install', onInstall);
self.addEventListener('activate', onActivate);
self.addEventListener('fetch', onFetch);
serviceworker-companion.js
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/serviceworker.js', { scope: './' })
.then(function(reg) {
console.log('[Companion]', 'Service worker registered!');
});
}
答案 0 :(得分:1)
event.data
中的self.addEventListener("push", (event)=> {...})
对象有一个方法json()
,该方法将event.data
值转换为json。
仅当发送的数据采用正确的json格式时,此功能才有效。
以下是我使用网络推送的示例:
self.addEventListener("push", function onPush(event) {
var data = event.data.json()
event.waitUntil(self.registration.showNotification(data.message.title, {
body: data.message.body,
icon: data.message.icon,
actions: [
{ action: 'Button one', title: "Button one text" },
{ action: 'Button two', title: "Button two text" }
]
}));
});
以下是来自我的user.rb模型的方法:
def send_web_push(title: , body: )
# the web_push is a payload with I save to the user record,
# that's allow me to send web push with background worker.
payload = {
endpoint: web_push['endpoint'],
keys: {
auth: web_push['auth'],
p256dh: web_push['p256dh']
}
}
push = WebPush.new(payload)
push.set_vapid_details(
'mailto:support@awesomesupewebapp.com',
Rails.application.secrets.web_push_public_key,
Rails.application.secrets.web_push_private_key
)
# below is a `:message` key in json format
push.send_notification({
message: {
title: title,
body: body,
icon: "/this_is_my_icon.png"
}
}.to_json)
end
我为web_push使用了一些其他ruby gem,但我认为它很常见。从该示例中,您应该看到如何更改正文,标题和图标键。
答案 1 :(得分:0)
查看强>
<%= content_tag(:button, "Foo", class: "webpush-button") %>
<script>
$('.webpush-button').on('click', (e) => {
navigator.serviceWorker.ready
.then((serviceWorkerRegistration) => {
serviceWorkerRegistration.pushManager.getSubscription()
.then((subscription) => {
$.post('/push', {
subscription: subscription.toJSON(),
message: "<%= @challenge.name %>",
body: "<%= @challenge.why %>",
icon: "/assets/default.png"
});
});
});
});
</script>
<强>控制器强>
class PushNotificationsController < ApplicationController
def push
Webpush.payload_send(
message: JSON.generate({
title: params[:message],
body: params[:body],
icon: params[:icon]
}),
endpoint: params[:subscription][:endpoint],
p256dh: params[:subscription][:keys][:p256dh],
auth: params[:subscription][:keys][:auth],
vapid: {
subject: "mailto:sender@example.com",
public_key: ENV['VAPID_PUBLIC_KEY'],
private_key: ENV['VAPID_PRIVATE_KEY']
}
)
end
end
<强> JS 强>
self.addEventListener("push", (event) => {
var data = event.data.json();
let title = (event.data && data.title) || "Yay a message";
let body = (event.data && data.body) || "We have received a push message";
let icon = (event.data && data.icon) || "/assets/blue-astronaut.png";
event.waitUntil(
self.registration.showNotification(title, { title,body, icon })
)
});