Untitled

 avatar
unknown
plain_text
16 days ago
7.3 kB
4
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