feat: implement push notification subscription handling and improve service worker configuration
This commit is contained in:
parent
cc3cd03e41
commit
c415493ee1
@ -33,6 +33,38 @@ function getIsSupported(): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendSubscriptionToServer(
|
||||||
|
subscription: PushSubscription,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const { endpoint } = subscription;
|
||||||
|
const key = subscription.getKey('p256dh');
|
||||||
|
const auth = subscription.getKey('auth');
|
||||||
|
|
||||||
|
const response = await fetch('/api/push/subscribe', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'X-XSRF-TOKEN': decodeURIComponent(
|
||||||
|
document.cookie.match(/XSRF-TOKEN=([^;]+)/)?.[1] ?? '',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify({
|
||||||
|
endpoint,
|
||||||
|
public_key: key
|
||||||
|
? btoa(String.fromCharCode(...new Uint8Array(key)))
|
||||||
|
: null,
|
||||||
|
auth_token: auth
|
||||||
|
? btoa(String.fromCharCode(...new Uint8Array(auth)))
|
||||||
|
: null,
|
||||||
|
content_encoding: 'aes128gcm',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.ok;
|
||||||
|
}
|
||||||
|
|
||||||
export function usePushNotification() {
|
export function usePushNotification() {
|
||||||
const [permission, setPermission] =
|
const [permission, setPermission] =
|
||||||
useState<PermissionStatus>(getInitialPermission);
|
useState<PermissionStatus>(getInitialPermission);
|
||||||
@ -54,40 +86,29 @@ export function usePushNotification() {
|
|||||||
async (vapidPublicKey: string): Promise<boolean> => {
|
async (vapidPublicKey: string): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
const registration = await navigator.serviceWorker.ready;
|
const registration = await navigator.serviceWorker.ready;
|
||||||
const subscription = await registration.pushManager.subscribe({
|
|
||||||
|
const existingSubscription =
|
||||||
|
await registration.pushManager.getSubscription();
|
||||||
|
|
||||||
|
if (existingSubscription) {
|
||||||
|
const synced = await sendSubscriptionToServer(
|
||||||
|
existingSubscription,
|
||||||
|
);
|
||||||
|
|
||||||
|
return synced;
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscription =
|
||||||
|
await registration.pushManager.subscribe({
|
||||||
userVisibleOnly: true,
|
userVisibleOnly: true,
|
||||||
applicationServerKey: urlBase64ToUint8Array(
|
applicationServerKey: urlBase64ToUint8Array(
|
||||||
vapidPublicKey,
|
vapidPublicKey,
|
||||||
) as BufferSource,
|
) as BufferSource,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { endpoint } = subscription;
|
const saved = await sendSubscriptionToServer(subscription);
|
||||||
const key = subscription.getKey('p256dh');
|
|
||||||
const auth = subscription.getKey('auth');
|
|
||||||
|
|
||||||
const response = await fetch('/api/push/subscribe', {
|
return saved;
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-Requested-With': 'XMLHttpRequest',
|
|
||||||
'X-XSRF-TOKEN': decodeURIComponent(
|
|
||||||
document.cookie.match(/XSRF-TOKEN=([^;]+)/)?.[1] ??
|
|
||||||
'',
|
|
||||||
),
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
endpoint,
|
|
||||||
public_key: key
|
|
||||||
? btoa(String.fromCharCode(...new Uint8Array(key)))
|
|
||||||
: null,
|
|
||||||
auth_token: auth
|
|
||||||
? btoa(String.fromCharCode(...new Uint8Array(auth)))
|
|
||||||
: null,
|
|
||||||
content_encoding: 'aes128gcm',
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
return response.ok;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error(
|
||||||
'Failed to subscribe to push notifications:',
|
'Failed to subscribe to push notifications:',
|
||||||
@ -119,6 +140,7 @@ export function usePushNotification() {
|
|||||||
document.cookie.match(/XSRF-TOKEN=([^;]+)/)?.[1] ?? '',
|
document.cookie.match(/XSRF-TOKEN=([^;]+)/)?.[1] ?? '',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
credentials: 'same-origin',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
endpoint: subscription.endpoint,
|
endpoint: subscription.endpoint,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -37,7 +37,9 @@ export default defineConfig({
|
|||||||
manifest: false,
|
manifest: false,
|
||||||
srcDir: 'resources/js',
|
srcDir: 'resources/js',
|
||||||
filename: 'sw.ts',
|
filename: 'sw.ts',
|
||||||
workbox: {
|
scope: '/',
|
||||||
|
strategies: 'injectManifest',
|
||||||
|
injectManifest: {
|
||||||
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff,woff2}'],
|
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff,woff2}'],
|
||||||
},
|
},
|
||||||
devOptions: {
|
devOptions: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user