mirror of
https://github.com/Tony0410/nextstep.git
synced 2026-05-24 21:31:43 +08:00
Add timeouts and better error handling for push notifications
- Add 10s timeout for service worker ready state - Add 15s timeout for push subscription - Check for PushManager support early (shows unsupported on incompatible devices) - Provide specific error messages for different failure modes This prevents the enable button from spinning forever on iOS devices where push subscription may hang silently. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,15 +31,28 @@ export function NotificationPermission({ workspaceId }: NotificationPermissionPr
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if PushManager is available (not available in all browsers/contexts)
|
||||||
|
if (!('PushManager' in window)) {
|
||||||
|
setPermission('unsupported')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const perm = Notification.permission as PermissionState
|
const perm = Notification.permission as PermissionState
|
||||||
setPermission(perm)
|
setPermission(perm)
|
||||||
|
|
||||||
if (perm === 'granted') {
|
if (perm === 'granted') {
|
||||||
// Check if already subscribed
|
// Check if already subscribed with timeout
|
||||||
try {
|
try {
|
||||||
const registration = await navigator.serviceWorker.ready
|
const registrationPromise = navigator.serviceWorker.ready
|
||||||
|
const timeoutPromise = new Promise<ServiceWorkerRegistration>((_, reject) =>
|
||||||
|
setTimeout(() => reject(new Error('Timeout')), 5000)
|
||||||
|
)
|
||||||
|
const registration = await Promise.race([registrationPromise, timeoutPromise])
|
||||||
|
|
||||||
|
if (registration.pushManager) {
|
||||||
const subscription = await registration.pushManager.getSubscription()
|
const subscription = await registration.pushManager.getSubscription()
|
||||||
setIsSubscribed(!!subscription)
|
setIsSubscribed(!!subscription)
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to check subscription:', err)
|
console.error('Failed to check subscription:', err)
|
||||||
}
|
}
|
||||||
@@ -66,14 +79,27 @@ export function NotificationPermission({ workspaceId }: NotificationPermissionPr
|
|||||||
}
|
}
|
||||||
const { publicKey } = await keyResponse.json()
|
const { publicKey } = await keyResponse.json()
|
||||||
|
|
||||||
// Register service worker if not already registered
|
// Wait for service worker with timeout
|
||||||
const registration = await navigator.serviceWorker.ready
|
const registrationPromise = navigator.serviceWorker.ready
|
||||||
|
const timeoutPromise = new Promise<never>((_, reject) =>
|
||||||
|
setTimeout(() => reject(new Error('Service worker not ready - try refreshing the page')), 10000)
|
||||||
|
)
|
||||||
|
const registration = await Promise.race([registrationPromise, timeoutPromise])
|
||||||
|
|
||||||
// Subscribe to push
|
// Check if push manager is available
|
||||||
const subscription = await registration.pushManager.subscribe({
|
if (!registration.pushManager) {
|
||||||
|
throw new Error('Push notifications not supported on this device')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe to push with timeout
|
||||||
|
const subscribePromise = registration.pushManager.subscribe({
|
||||||
userVisibleOnly: true,
|
userVisibleOnly: true,
|
||||||
applicationServerKey: urlBase64ToUint8Array(publicKey),
|
applicationServerKey: urlBase64ToUint8Array(publicKey),
|
||||||
})
|
})
|
||||||
|
const subscribeTimeout = new Promise<never>((_, reject) =>
|
||||||
|
setTimeout(() => reject(new Error('Push subscription timed out - this device may not support web push')), 15000)
|
||||||
|
)
|
||||||
|
const subscription = await Promise.race([subscribePromise, subscribeTimeout])
|
||||||
|
|
||||||
// Send subscription to server
|
// Send subscription to server
|
||||||
const response = await fetch('/api/notifications/subscribe', {
|
const response = await fetch('/api/notifications/subscribe', {
|
||||||
|
|||||||
Reference in New Issue
Block a user