Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions js/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ function showBgNotification(content) {
const options = {
body: msg.join('\n'),
tag: 'nid' + content.nid,
data: {
link: content.link,
},
}
return self.registration.showNotification(title, options)
}
Expand Down Expand Up @@ -88,6 +91,25 @@ self.addEventListener('push', function(event) {
}
})

self.addEventListener('notificationclick', function(event) {
event.notification.close()
const link = event.notification.data && event.notification.data.link
if (!link) {
// no target: focus an existing window of this instance if any
event.waitUntil(self.clients.matchAll({ type: 'window' }).then((clientList) => {
for (const client of clientList) {
if (client.url.startsWith(self.location.origin)) {
return client.focus()
}
}
}))
return
}
// always a new tab: existing tabs may be pinned or parked there on purpose
// and the client API cannot tell those apart
event.waitUntil(self.clients.openWindow(link))
})

self.addEventListener('pushsubscriptionchange', function(event) {
console.log('Push Subscription Change', event)
event.waitUntil(self.clients.matchAll()
Expand Down
9 changes: 8 additions & 1 deletion lib/Push.php
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ protected function callSafelyForToken(IToken $token, string $method): ?int {
* @param INotification $notification
* @param int $maxLength max length of the push notification (shorter than 240 for proxy push, 3993 for webpush)
* @return array
* @psalm-return array{nid: int, app: string, subject: string, type: string, id: string}
* @psalm-return array{nid: int, app: string, subject: string, type: string, id: string, link?: string}
*/
protected function encodeNotif(int $id, INotification $notification, int $maxLength): array {
$data = [
Expand All @@ -913,6 +913,13 @@ protected function encodeNotif(int $id, INotification $notification, int $maxLen
'id' => $notification->getObjectId(),
];

// The link lets the service worker navigate on notificationclick; the
// subject budget below shrinks accordingly, very long links are dropped
$link = $notification->getLink();
if ($link !== '' && strlen($link) < 128) {
$data['link'] = $link;
}

// Max length of encryption is ~240, so we need to make sure the subject is shorter.
// Also, subtract two for encapsulating quotes will be added.
$maxDataLength = $maxLength - strlen((string)json_encode($data)) - 2;
Expand Down
22 changes: 22 additions & 0 deletions src/workers/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ function showBgNotification(content) {
const options = {
body: msg.join('\n'),
tag: 'nid' + content.nid,
data: {
link: content.link,
},
}
return self.registration.showNotification(title, options)
}
Expand Down Expand Up @@ -88,6 +91,25 @@ self.addEventListener('push', function(event) {
}
})

self.addEventListener('notificationclick', function(event) {
event.notification.close()
const link = event.notification.data && event.notification.data.link
if (!link) {
// no target: focus an existing window of this instance if any
event.waitUntil(self.clients.matchAll({ type: 'window' }).then((clientList) => {
for (const client of clientList) {
if (client.url.startsWith(self.location.origin)) {
return client.focus()
}
}
}))
return
}
// always a new tab: existing tabs may be pinned or parked there on purpose
// and the client API cannot tell those apart
event.waitUntil(self.clients.openWindow(link))
})

self.addEventListener('pushsubscriptionchange', function(event) {
console.log('Push Subscription Change', event)
event.waitUntil(self.clients.matchAll()
Expand Down
Loading