147 lines
5.2 KiB
TypeScript
147 lines
5.2 KiB
TypeScript
/**
|
|
* useFCM Hook - Platform-aware FCM token management
|
|
*
|
|
* Native: Full FCM support with token registration and notification handling
|
|
* Web: Gracefully skips FCM (web push requires additional service worker setup)
|
|
*/
|
|
import { useEffect, useRef } from 'react';
|
|
import { Platform, AppState, AppStateStatus } from 'react-native';
|
|
import { useAuthStore } from '../stores/authStore';
|
|
|
|
// Only import FCMService and messaging on native platforms
|
|
let FCMService: any = null;
|
|
let messaging: any = null;
|
|
|
|
if (Platform.OS !== 'web') {
|
|
FCMService = require('../services/fcmService').FCMService;
|
|
messaging = require('@react-native-firebase/messaging').default;
|
|
}
|
|
|
|
/**
|
|
* Hook to manage FCM token registration and notification handling
|
|
* Call this hook once at the app root level when user is authenticated
|
|
*/
|
|
export const useFCM = () => {
|
|
const { user } = useAuthStore();
|
|
const foregroundUnsubscribeRef = useRef<(() => void) | null>(null);
|
|
const notificationOpenedUnsubscribeRef = useRef<(() => void) | null>(null);
|
|
const initializedUserIdRef = useRef<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
// Skip FCM on web platform
|
|
if (Platform.OS === 'web' || !FCMService) {
|
|
return;
|
|
}
|
|
|
|
if (!user) {
|
|
// User logged out - clean up
|
|
if (initializedUserIdRef.current) {
|
|
FCMService.cleanup();
|
|
if (foregroundUnsubscribeRef.current) {
|
|
foregroundUnsubscribeRef.current();
|
|
foregroundUnsubscribeRef.current = null;
|
|
}
|
|
if (notificationOpenedUnsubscribeRef.current) {
|
|
notificationOpenedUnsubscribeRef.current();
|
|
notificationOpenedUnsubscribeRef.current = null;
|
|
}
|
|
initializedUserIdRef.current = null;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// User is authenticated - initialize FCM
|
|
// Clean up previous user's listeners if user changed
|
|
if (initializedUserIdRef.current && initializedUserIdRef.current !== user.uid) {
|
|
FCMService.cleanup();
|
|
if (foregroundUnsubscribeRef.current) {
|
|
foregroundUnsubscribeRef.current();
|
|
foregroundUnsubscribeRef.current = null;
|
|
}
|
|
if (notificationOpenedUnsubscribeRef.current) {
|
|
notificationOpenedUnsubscribeRef.current();
|
|
notificationOpenedUnsubscribeRef.current = null;
|
|
}
|
|
}
|
|
|
|
initializedUserIdRef.current = user.uid;
|
|
|
|
// Update FCM token for the existing user
|
|
FCMService.updateTokenForExistingUser(user.uid).catch((error: any) => {
|
|
console.error('Failed to update FCM token:', error);
|
|
});
|
|
|
|
// Set up handlers only if not already set up for this user
|
|
if (!foregroundUnsubscribeRef.current) {
|
|
// Set up foreground message handler
|
|
foregroundUnsubscribeRef.current = FCMService.setupForegroundMessageHandler();
|
|
|
|
// Set up notification opened handler
|
|
notificationOpenedUnsubscribeRef.current = FCMService.setupNotificationOpenedHandler(
|
|
(remoteMessage: any) => {
|
|
console.log('Notification opened:', remoteMessage);
|
|
}
|
|
);
|
|
|
|
// Check if app was opened from a notification
|
|
FCMService.getInitialNotification().then((remoteMessage: any) => {
|
|
if (remoteMessage) {
|
|
console.log('App opened from notification:', remoteMessage);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Cleanup on unmount
|
|
return () => {
|
|
if (foregroundUnsubscribeRef.current) {
|
|
foregroundUnsubscribeRef.current();
|
|
foregroundUnsubscribeRef.current = null;
|
|
}
|
|
if (notificationOpenedUnsubscribeRef.current) {
|
|
notificationOpenedUnsubscribeRef.current();
|
|
notificationOpenedUnsubscribeRef.current = null;
|
|
}
|
|
};
|
|
}, [user]);
|
|
|
|
// Save token when app comes to foreground
|
|
useEffect(() => {
|
|
// Skip on web
|
|
if (Platform.OS === 'web' || !FCMService || !user) {
|
|
return;
|
|
}
|
|
|
|
const handleAppStateChange = (nextAppState: AppStateStatus) => {
|
|
if (nextAppState === 'active' && user) {
|
|
FCMService.updateTokenForExistingUser(user.uid).catch((error: any) => {
|
|
console.error('Failed to refresh FCM token on app foreground:', error);
|
|
});
|
|
}
|
|
};
|
|
|
|
const subscription = AppState.addEventListener('change', handleAppStateChange);
|
|
|
|
return () => {
|
|
subscription.remove();
|
|
};
|
|
}, [user]);
|
|
|
|
// Clean up on unmount
|
|
useEffect(() => {
|
|
// Skip on web
|
|
if (Platform.OS === 'web' || !FCMService) {
|
|
return;
|
|
}
|
|
|
|
return () => {
|
|
FCMService.cleanup();
|
|
if (foregroundUnsubscribeRef.current) {
|
|
foregroundUnsubscribeRef.current();
|
|
}
|
|
if (notificationOpenedUnsubscribeRef.current) {
|
|
notificationOpenedUnsubscribeRef.current();
|
|
}
|
|
};
|
|
}, []);
|
|
};
|