rmaps-online/src/hooks/useServiceWorkerMessages.ts

77 lines
2.1 KiB
TypeScript

'use client';
import { useEffect, useCallback, useRef } from 'react';
// Background Sync API types (not in default TypeScript libs)
interface SyncManager {
register(tag: string): Promise<void>;
}
interface ServiceWorkerRegistrationWithSync extends ServiceWorkerRegistration {
sync: SyncManager;
}
interface UseServiceWorkerMessagesOptions {
onLocationRequest?: () => void;
onLocationSync?: () => void;
}
/**
* Hook to handle messages from the service worker
* Used for background location sync and silent push notifications
*/
export function useServiceWorkerMessages(options: UseServiceWorkerMessagesOptions = {}) {
const optionsRef = useRef(options);
optionsRef.current = options;
useEffect(() => {
if (!('serviceWorker' in navigator)) {
return;
}
const handleMessage = (event: MessageEvent) => {
console.log('[App] Service worker message:', event.data);
switch (event.data?.type) {
case 'REQUEST_LOCATION_UPDATE':
// Service worker is requesting a location update (from silent push)
optionsRef.current.onLocationRequest?.();
break;
case 'REQUEST_LOCATION_SYNC':
// Service worker wants to sync location (device came back online)
optionsRef.current.onLocationSync?.();
break;
}
};
navigator.serviceWorker.addEventListener('message', handleMessage);
return () => {
navigator.serviceWorker.removeEventListener('message', handleMessage);
};
}, []);
// Register for background sync
const registerBackgroundSync = useCallback(async () => {
if (!('serviceWorker' in navigator) || !('SyncManager' in window)) {
console.log('[App] Background sync not supported');
return false;
}
try {
const registration = await navigator.serviceWorker.ready as ServiceWorkerRegistrationWithSync;
await registration.sync.register('rmaps-location-sync');
console.log('[App] Background sync registered');
return true;
} catch (error) {
console.error('[App] Background sync registration failed:', error);
return false;
}
}, []);
return {
registerBackgroundSync,
};
}