Files
m8chat-app2/web/push_sw.js
help4bis 1cffe09faf feat: web push notifications, image fullscreen, public room browser
- Web Push: push_sw.js service worker + VAPID subscription registered
  on login; Matrix pusher registered pointing to Sygnal on
  https://matrix.m8chat.au/_matrix/push/v1/notify
- Chat: tap image -> fullscreen InteractiveViewer (pinch/zoom)
- Rooms: public room browser via Matrix room directory (FAB + empty state)

Build fixes applied to web_push_service.dart:
  - dart:js_interop_unsafe import added for getProperty on JSObject
  - client.setPusher -> client.postPusher (matrix 0.33.0 API)
  - keyBytes.toJS removed (JSUint8Array already a JS type)
  - register() script URL coerced with .toJS (String -> JSAny)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 06:48:48 +10:00

65 lines
1.9 KiB
JavaScript

// Version: 1.0.0 | Created: 2026-04-27
// Web Push service worker for M8Chat.
// Receives push events from the browser and shows system notifications.
// This script is registered separately from flutter_service_worker.js.
'use strict';
self.addEventListener('push', function (event) {
if (!event.data) return;
let data = {};
try {
data = event.data.json();
} catch (_) {
data = { notification: { body: event.data.text() } };
}
// Sygnal delivers: { notification: { content: { body, msgtype, ... }, room_name, sender_display_name, ... } }
const notif = data.notification || {};
const content = notif.content || {};
const sender = notif.sender_display_name || notif.sender || 'M8Chat';
const room = notif.room_name || notif.room_alias || '';
const body = content.body || notif.body || 'New message';
const title = room ? `${sender} in ${room}` : sender;
const options = {
body: body,
icon: '/icons/Icon-192.png',
badge: '/icons/Icon-192.png',
tag: notif.room_id || 'm8chat',
data: {
roomId: notif.room_id,
url: self.location.origin + (notif.room_id
? '/rooms/' + encodeURIComponent(notif.room_id)
: '/rooms'),
},
requireInteraction: false,
};
event.waitUntil(self.registration.showNotification(title, options));
});
self.addEventListener('notificationclick', function (event) {
event.notification.close();
const url = (event.notification.data && event.notification.data.url)
? event.notification.data.url
: self.location.origin + '/rooms';
event.waitUntil(
clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function (clientList) {
for (const client of clientList) {
if (client.url === url && 'focus' in client) {
return client.focus();
}
}
if (clients.openWindow) {
return clients.openWindow(url);
}
})
);
});