feat: Gateway 웹 알림 설정과 PWA 구독 화면을 추가한다
계정 화면에서 profile별 9개 알림을 기본 꺼짐으로 설정하고 Android, iPhone 홈 화면 앱, Windows 브라우저용 service worker 구독 흐름을 제공한다. 전송 비활성 상태와 모바일 Chromium 경계를 E2E로 검증한다.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
const ALLOWED_NOTIFICATION_PATH = /^\/(?:gateway|che|hwe|kwe|pwe|twe|nya|pya)(?:\/|$)/u;
|
||||
|
||||
const safeNotificationUrl = (value) => {
|
||||
try {
|
||||
const url = new URL(typeof value === 'string' ? value : '/gateway/', self.location.origin);
|
||||
if (url.origin !== self.location.origin || !ALLOWED_NOTIFICATION_PATH.test(url.pathname)) {
|
||||
return '/gateway/';
|
||||
}
|
||||
return `${url.pathname}${url.search}${url.hash}`;
|
||||
} catch {
|
||||
return '/gateway/';
|
||||
}
|
||||
};
|
||||
|
||||
self.addEventListener('push', (event) => {
|
||||
let payload;
|
||||
try {
|
||||
payload = event.data?.json() ?? {};
|
||||
} catch {
|
||||
payload = {};
|
||||
}
|
||||
const title = typeof payload.title === 'string' ? payload.title : '삼국지 모의전투';
|
||||
const body = typeof payload.body === 'string' ? payload.body : '새 알림이 있습니다.';
|
||||
const tag = typeof payload.tag === 'string' ? payload.tag : 'sammo-notification';
|
||||
event.waitUntil(
|
||||
self.registration.showNotification(title, {
|
||||
body,
|
||||
tag,
|
||||
icon: './web-push-icon.svg',
|
||||
badge: './web-push-icon.svg',
|
||||
data: { url: safeNotificationUrl(payload.url) },
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('notificationclick', (event) => {
|
||||
event.notification.close();
|
||||
const targetPath = safeNotificationUrl(event.notification.data?.url);
|
||||
event.waitUntil(
|
||||
self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(async (clients) => {
|
||||
const targetUrl = new URL(targetPath, self.location.origin).href;
|
||||
for (const client of clients) {
|
||||
if (new URL(client.url).origin !== self.location.origin) continue;
|
||||
await client.navigate(targetUrl);
|
||||
return client.focus();
|
||||
}
|
||||
return self.clients.openWindow(targetUrl);
|
||||
})
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user