Compare commits

..

2 Commits

4 changed files with 55 additions and 22 deletions
+1 -1
View File
@@ -1 +1 @@
0.1.0.92
0.1.0.93
@@ -6,7 +6,8 @@ import {
enableCollaboratorChangePush,
fetchPushPrefs,
getNotificationPermission,
isPushSupported
isPushSupported,
preloadPushService
} from '../services/pushNotifications.js'
import { isIosDevice, isRunningStandalone } from '../hooks/usePwaInstall.js'
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
@@ -28,6 +29,7 @@ export default function PushNotificationSettings() {
setLoading(false)
return
}
void preloadPushService()
try {
const prefs = await fetchPushPrefs()
setEnabled(prefs.collaboratorChangesEnabled)
+3 -1
View File
@@ -10,7 +10,8 @@ import { apiFetch } from '../services/api.js'
import {
enableCollaboratorChangePush,
isCollaboratorPushActive,
isPushSupported
isPushSupported,
preloadPushService
} from '../services/pushNotifications.js'
import { isIosDevice, isRunningStandalone } from '../hooks/usePwaInstall.js'
@@ -55,6 +56,7 @@ export default function SettingsForm({ logbookId, onLogbookRestored }: SettingsF
loadCollaborators()
loadShareLink()
}
void preloadPushService()
}, [logbookId])
const loadShareLink = async () => {
+48 -19
View File
@@ -27,17 +27,41 @@ export function getNotificationPermission(): NotificationPermission | 'unsupport
return Notification.permission
}
let cachedVapidKey: string | null = null
let cachedRegistration: ServiceWorkerRegistration | null = null
export async function preloadPushService(): Promise<void> {
if (!isPushSupported()) return
try {
if (!cachedVapidKey) {
await fetchVapidPublicKey()
}
if (!cachedRegistration) {
cachedRegistration = await navigator.serviceWorker.ready
}
} catch (err) {
console.warn('Failed to preload push service:', err)
}
}
async function fetchVapidPublicKey(): Promise<string | null> {
if (cachedVapidKey) return cachedVapidKey
const envKey = import.meta.env.VITE_VAPID_PUBLIC_KEY
if (typeof envKey === 'string' && envKey.trim()) {
return envKey.trim()
cachedVapidKey = envKey.trim()
return cachedVapidKey
}
try {
const res = await fetch(`${API_BASE}/vapid-public-key`)
if (!res.ok) return null
const data = await res.json()
return typeof data.publicKey === 'string' ? data.publicKey : null
if (typeof data.publicKey === 'string') {
cachedVapidKey = data.publicKey.trim()
return cachedVapidKey
}
return null
} catch {
return null
}
@@ -98,27 +122,28 @@ export async function subscribeToPush(): Promise<void> {
throw new Error('Push notifications are not supported on this device')
}
// Pre-resolve registration and VAPID key synchronously if preloaded.
// This keeps the user gesture active for iOS Safari.
const registration = cachedRegistration || await navigator.serviceWorker.ready
const publicKey = cachedVapidKey || await fetchVapidPublicKey()
if (!publicKey) {
throw new Error('Push notifications are not configured on this server')
}
const permission = await Notification.requestPermission()
if (permission !== 'granted') {
throw new Error('Notification permission denied')
}
const publicKey = await fetchVapidPublicKey()
if (!publicKey) {
throw new Error('Push notifications are not configured on this server')
}
const registration = await navigator.serviceWorker.ready
let subscription = await registration.pushManager.getSubscription()
if (!subscription) {
const keyBytes = urlBase64ToUint8Array(publicKey)
const applicationServerKey = new Uint8Array(keyBytes)
subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey
})
}
const keyBytes = urlBase64ToUint8Array(publicKey)
const applicationServerKey = new Uint8Array(keyBytes)
// Always call subscribe to renew/ensure subscription without reusing stale state
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey
})
await saveSubscriptionToServer(subscription)
}
@@ -126,7 +151,7 @@ export async function subscribeToPush(): Promise<void> {
export async function unsubscribeFromPush(): Promise<void> {
if (!isPushSupported()) return
const registration = await navigator.serviceWorker.ready
const registration = cachedRegistration || await navigator.serviceWorker.ready
const subscription = await registration.pushManager.getSubscription()
if (!subscription) return
@@ -164,3 +189,7 @@ export async function disableCollaboratorChangePush(): Promise<void> {
await savePushPrefs(false)
await unsubscribeFromPush()
}
if (isPushSupported()) {
void preloadPushService()
}