feat : can turn off notifcation
This commit is contained in:
@@ -1,18 +1,63 @@
|
||||
'use client';
|
||||
|
||||
// All notification features share one browser permission and root service worker.
|
||||
export async function syncSitePush(userId: string) {
|
||||
const configResponse = await fetch('/api/commission/push-subscription', { cache: 'no-store' });
|
||||
if (!configResponse.ok) throw new Error('push-config-failed');
|
||||
const config = await configResponse.json() as { publicKey: string; canAdmin: boolean };
|
||||
const registration = await navigator.serviceWorker.register('/commission-push-sw.js', { scope: '/' });
|
||||
const subscription = await registration.pushManager.getSubscription() ?? await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: config.publicKey });
|
||||
const data = subscription.toJSON();
|
||||
const registrations = [
|
||||
{ url: '/api/comments/push-subscription', body: data },
|
||||
{ url: '/api/commission/push-subscription', body: { ...data, scope: config.canAdmin ? 'admin' : 'customer' } },
|
||||
];
|
||||
const responses = await Promise.all(registrations.map(feature => fetch(feature.url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(feature.body) })));
|
||||
if (responses.some(response => !response.ok)) throw new Error('push-subscription-failed');
|
||||
sessionStorage.setItem(`site-push-synced-${userId}`, '1');
|
||||
import { useSyncExternalStore } from 'react';
|
||||
|
||||
const disabledKey = 'site-push-disabled';
|
||||
const preferenceEvent = 'notifications:preference';
|
||||
export function sitePushDisabled() { return localStorage.getItem(disabledKey) === '1'; }
|
||||
export function setSitePushDisabled(disabled: boolean) {
|
||||
if (disabled) localStorage.setItem(disabledKey, '1');
|
||||
else localStorage.removeItem(disabledKey);
|
||||
window.dispatchEvent(new Event(preferenceEvent));
|
||||
}
|
||||
function subscribePreference(onChange: () => void) {
|
||||
window.addEventListener(preferenceEvent, onChange);
|
||||
window.addEventListener('storage', onChange);
|
||||
return () => {
|
||||
window.removeEventListener(preferenceEvent, onChange);
|
||||
window.removeEventListener('storage', onChange);
|
||||
};
|
||||
}
|
||||
export function useSitePushDisabled() {
|
||||
return useSyncExternalStore(subscribePreference, sitePushDisabled, () => false);
|
||||
}
|
||||
|
||||
// Serialize subscription changes so pausing also stops an in-flight automatic sync.
|
||||
let pending: Promise<unknown> = Promise.resolve();
|
||||
function updateSubscription<T>(operation: () => Promise<T>): Promise<T> {
|
||||
const result = pending.then(operation, operation);
|
||||
pending = result.catch(() => undefined);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function disableSitePush(userId?: string) {
|
||||
return updateSubscription(async () => {
|
||||
if ('serviceWorker' in navigator) {
|
||||
const registration = await navigator.serviceWorker.getRegistration('/');
|
||||
const subscription = await registration?.pushManager.getSubscription();
|
||||
if (subscription && !await subscription.unsubscribe()) throw new Error('push-unsubscribe-failed');
|
||||
}
|
||||
if (userId) sessionStorage.removeItem(`site-push-synced-${userId}`);
|
||||
setSitePushDisabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
// All notification features share one browser permission and root service worker.
|
||||
export function syncSitePush(userId: string, resume = false) {
|
||||
return updateSubscription(async () => {
|
||||
if (!resume && sitePushDisabled()) return;
|
||||
const configResponse = await fetch('/api/commission/push-subscription', { cache: 'no-store' });
|
||||
if (!configResponse.ok) throw new Error('push-config-failed');
|
||||
const config = await configResponse.json() as { publicKey: string; canAdmin: boolean };
|
||||
const registration = await navigator.serviceWorker.register('/commission-push-sw.js', { scope: '/' });
|
||||
const subscription = await registration.pushManager.getSubscription() ?? await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: config.publicKey });
|
||||
const data = subscription.toJSON();
|
||||
const registrations = [
|
||||
{ url: '/api/comments/push-subscription', body: data },
|
||||
{ url: '/api/commission/push-subscription', body: { ...data, scope: config.canAdmin ? 'admin' : 'customer' } },
|
||||
];
|
||||
const responses = await Promise.all(registrations.map(feature => fetch(feature.url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(feature.body) })));
|
||||
if (responses.some(response => !response.ok)) throw new Error('push-subscription-failed');
|
||||
sessionStorage.setItem(`site-push-synced-${userId}`, '1');
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user