Untitled
unknown
plain_text
7 months ago
7.3 kB
5
Indexable
import { useEffect, useRef, useState } from 'react';
import * as Notifications from 'expo-notifications';
import { EventSubscription } from 'expo-modules-core';
import notificationService from '../services/notificationService';
import firebaseMessagingService from '../services/firebaseMessagingService';
import { Platform } from 'react-native';
import messaging from '@react-native-firebase/messaging';
export const useNotifications = () => {
const notificationListener = useRef<EventSubscription>();
const responseListener = useRef<EventSubscription>();
const firebaseMessageListener = useRef<() => void>();
const firebaseNotificationOpenListener = useRef<() => void>();
const [fcmToken, setFcmToken] = useState<string | null>(null);
useEffect(() => {
const setupNotifications = async () => {
try {
console.log('Setting up notifications...');
// Try Firebase first
try {
console.log('Setting up Firebase messaging...');
// Request permission for Firebase notifications
const hasPermission = await firebaseMessagingService.requestPermission();
if (hasPermission) {
console.log('Firebase permission granted, getting FCM token...');
// For iOS, we need to make sure we're registered for remote notifications
if (Platform.OS === 'ios') {
try {
// Force register for remote messages
await messaging().registerDeviceForRemoteMessages();
console.log('Successfully registered for remote messages');
} catch (registerError) {
console.error('Error registering for remote messages:', registerError);
}
}
// Get the FCM token
const token = await firebaseMessagingService.getFCMToken();
if (token) {
setFcmToken(token);
console.log('Firebase Messaging Token:', token);
// Set up Android notification channel
if (Platform.OS === 'android') {
await firebaseMessagingService.createAndroidChannel();
}
} else {
console.error('Failed to get FCM token even though permission was granted');
}
} else {
console.warn('Firebase messaging permission not granted');
}
} catch (firebaseError) {
console.error('Error setting up Firebase messaging:', firebaseError);
}
// Register for Expo push notifications as a fallback
console.log('Setting up Expo notifications...');
const expoPushToken = await notificationService.registerForPushNotifications();
console.log('Expo Push Token:', expoPushToken);
// Add Expo notification listeners
notificationListener.current = notificationService.addNotificationReceivedListener(
notification => {
console.log('Expo notification received in listener:', notification);
// You can show a local notification here if needed
}
);
responseListener.current = notificationService.addNotificationResponseReceivedListener(
response => {
console.log('Expo notification response in listener:', response);
// Handle notification response (e.g., navigate to a screen)
}
);
// Add Firebase notification listeners
firebaseMessageListener.current = firebaseMessagingService.onForegroundMessage(
remoteMessage => {
console.log('Firebase foreground message received in listener:', remoteMessage);
// Show a local notification for Firebase messages received in foreground
if (remoteMessage.notification) {
notificationService.scheduleLocalNotification(
remoteMessage.notification.title || 'New Message',
remoteMessage.notification.body || 'You have a new notification',
0
);
}
}
);
firebaseNotificationOpenListener.current = firebaseMessagingService.onNotificationOpen(
remoteMessage => {
console.log('Firebase notification opened in listener:', remoteMessage);
// Handle notification open (e.g., navigate to a screen)
}
);
// Check if app was opened from a Firebase notification
const initialNotification = await firebaseMessagingService.getInitialNotification();
if (initialNotification) {
console.log('App opened from Firebase notification:', initialNotification);
// Handle initial notification (e.g., navigate to a screen)
}
} catch (error) {
console.error('Error setting up notifications:', error);
}
};
setupNotifications();
// Cleanup listeners on unmount
return () => {
if (notificationListener.current) {
notificationListener.current.remove();
}
if (responseListener.current) {
responseListener.current.remove();
}
if (firebaseMessageListener.current) {
firebaseMessageListener.current();
}
if (firebaseNotificationOpenListener.current) {
firebaseNotificationOpenListener.current();
}
};
}, []);
const sendTestNotification = async () => {
await notificationService.scheduleLocalNotification(
'Test Notification',
'This is a test notification!',
2 // Show after 2 seconds
);
};
const sendRemoteTestNotification = async (
token: string,
title: string,
body: string,
data: Record<string, any> = {}
) => {
await notificationService.sendRemotePushNotification(token, title, body, data);
};
const subscribeToTopic = async (topic: string) => {
await firebaseMessagingService.subscribeToTopic(topic);
};
const unsubscribeFromTopic = async (topic: string) => {
await firebaseMessagingService.unsubscribeFromTopic(topic);
};
// Get the best available token for push notifications
const getBestAvailableToken = (): string | undefined => {
// Prefer FCM token if available
if (fcmToken) {
return fcmToken;
}
// Fall back to Expo Push Token
return notificationService.expoPushToken;
};
// Function to manually retry getting the FCM token
const retryGetFCMToken = async (): Promise<void> => {
try {
console.log('Manually retrying to get FCM token...');
const token = await firebaseMessagingService.getFCMToken();
if (token) {
setFcmToken(token);
console.log('Successfully got FCM token on retry:', token);
} else {
console.error('Failed to get FCM token on retry');
}
} catch (error) {
console.error('Error retrying to get FCM token:', error);
}
};
return {
expoPushToken: notificationService.expoPushToken,
fcmToken,
// Provide a best available token that will use FCM if available, otherwise Expo
bestAvailableToken: getBestAvailableToken(),
sendTestNotification,
sendRemoteTestNotification,
subscribeToTopic,
unsubscribeFromTopic,
retryGetFCMToken, // Add the retry function
};
};
Editor is loading...
Leave a Comment