again push for merge code
This commit is contained in:
@@ -5,17 +5,20 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import { PaperProvider } from 'react-native-paper';
|
||||
import AppNavigator from './src/navigation/AppNavigator';
|
||||
import notifee from '@notifee/react-native';
|
||||
import { backgroundHandler, foregroundListener, requestPermission, tokenRefreshHandler } from './src/utils/firebase/firebaseServices';
|
||||
import { backgroundHandler, foregroundListener, requestPermission, setupFirebaseHandlers, setupNotificationPressHandlers, tokenRefreshHandler } from './src/utils/firebase/firebaseServices';
|
||||
|
||||
function App() {
|
||||
const isDarkMode = useColorScheme() === 'dark';
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// 🔹 Ask for permission
|
||||
requestPermission();
|
||||
|
||||
// 🔹 Handle background + quit state
|
||||
backgroundHandler();
|
||||
backgroundHandler();
|
||||
setupFirebaseHandlers()
|
||||
setupNotificationPressHandlers()
|
||||
|
||||
// 🔹 Listen for foreground messages
|
||||
const unsubscribe = foregroundListener();
|
||||
|
||||
@@ -22,6 +22,8 @@ import TransactionsList from "../screens/transaction/TransactionList";
|
||||
import RandomSelectUserScreen from "../screens/management/RandomSelectUserScreen";
|
||||
import Notification from "../screens/notification/Notification";
|
||||
import ManagementScreen from "../screens/management/ManagementScreen";
|
||||
import { navigationRef } from "../utils/navigationService";
|
||||
import NotificationRedirection from "../screens/NotificationRedirection";
|
||||
|
||||
export type RootStackParamList = {
|
||||
Splash: undefined;
|
||||
@@ -44,6 +46,7 @@ export type RootStackParamList = {
|
||||
TransactionList: undefined
|
||||
RandomSelectUserScreen: { groupId: string | number, cycleNumber: number };
|
||||
Notification: undefined;
|
||||
NotificationRedirection:{ data: any };
|
||||
Management:
|
||||
| { actionTab: "My Groups" }
|
||||
| { actionTab1: "Joined Groups" }
|
||||
@@ -88,8 +91,8 @@ export default function AppNavigator() {
|
||||
|
||||
|
||||
return (
|
||||
<NavigationContainer linking={linking}>
|
||||
<Stack.Navigator initialRouteName="Splash">
|
||||
<NavigationContainer linking={linking} ref={navigationRef}>
|
||||
<Stack.Navigator initialRouteName="Splash" >
|
||||
<Stack.Screen name="Splash" component={SplashScreen} options={{ headerShown: false }} />
|
||||
<Stack.Screen name="Home" component={BottomTabs} options={{ headerShown: false }} />
|
||||
<Stack.Screen name="Login" component={LoginScreen} options={{ headerShown: false }} />
|
||||
@@ -111,6 +114,7 @@ export default function AppNavigator() {
|
||||
<Stack.Screen name="RandomSelectUserScreen" component={RandomSelectUserScreen} options={{ headerShown: false }} />
|
||||
<Stack.Screen name="Notification" component={Notification} options={{ headerShown: false }} />
|
||||
<Stack.Screen name="Management" component={ManagementScreen} options={{ headerShown: false }} />
|
||||
<Stack.Screen name="NotificationRedirection" component={NotificationRedirection} options={{ headerShown: false }} />
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// src/screens/NotificationRedirection.tsx
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { View, StyleSheet, ActivityIndicator, Text } from 'react-native';
|
||||
import { useRoute, RouteProp, useNavigation } from '@react-navigation/native';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { RootStackParamList } from '../navigation/types';
|
||||
|
||||
// Define the specific route prop type for this screen
|
||||
type NotificationRedirectionRouteProp = RouteProp<RootStackParamList, 'NotificationRedirection'>;
|
||||
|
||||
const NotificationRedirection: React.FC = () => {
|
||||
const route = useRoute<NotificationRedirectionRouteProp>();
|
||||
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
|
||||
const { data } = route.params;
|
||||
|
||||
useEffect(() => {
|
||||
// This effect runs once when the component mounts
|
||||
if (data) {
|
||||
console.log('🔄 Processing notification data:', data);
|
||||
|
||||
// --- Your Redirection Logic Goes Here ---
|
||||
// Use the 'data' object to decide where to go.
|
||||
// For this example, we'll navigate based on 'msgType'.
|
||||
|
||||
let destination: keyof RootStackParamList = 'Home'; // Default destination
|
||||
let params: object | undefined = undefined;
|
||||
|
||||
switch (data.msgType) {
|
||||
case 'JOIN_REQUEST':
|
||||
destination = 'Home';
|
||||
params = {
|
||||
screen: 'Management',
|
||||
params: { actionTab: 'Requests' },
|
||||
};
|
||||
break;
|
||||
case 'JOIN_APPROVED':
|
||||
destination = 'Home';
|
||||
params = {
|
||||
screen: 'Management',
|
||||
params: { actionTab: 'Joined Groups' },
|
||||
};
|
||||
break;
|
||||
case 'GROUP_STARTED':
|
||||
destination = 'GroupDetails';
|
||||
params = {
|
||||
item: {id: data?.groupId,
|
||||
},
|
||||
};
|
||||
break;
|
||||
// 'ManagementTabs', { groupId: group.id }
|
||||
case 'CONTRIBUTION':
|
||||
destination = 'ManagementTabs';
|
||||
params = {
|
||||
screen:'Payments',
|
||||
groupId: data.groupId
|
||||
};
|
||||
break;
|
||||
// navigation.navigate('ManagementTabs', { groupId: group.id });
|
||||
|
||||
default:
|
||||
// Keep the default destination as 'Home'
|
||||
break;
|
||||
}
|
||||
|
||||
// Use replace to prevent the user from navigating back to this loading screen
|
||||
navigation.replace(destination, params);
|
||||
|
||||
} else {
|
||||
// If no data is passed for some reason, just go to the home screen
|
||||
console.warn('⚠ No data found in notification, redirecting to Home.');
|
||||
navigation.replace('Home');
|
||||
}
|
||||
}, [data, navigation]); // Effect dependencies
|
||||
|
||||
// This is the only UI the user will see: a clean loading indicator
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ActivityIndicator size="large" color="#007AFF" />
|
||||
<Text style={styles.loadingText}>Loading...</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#f5f5f5',
|
||||
},
|
||||
loadingText: {
|
||||
marginTop: 10,
|
||||
fontSize: 16,
|
||||
color: '#666',
|
||||
},
|
||||
});
|
||||
|
||||
export default NotificationRedirection;
|
||||
@@ -129,11 +129,12 @@
|
||||
|
||||
|
||||
import messaging from '@react-native-firebase/messaging';
|
||||
import notifee, { AndroidImportance } from '@notifee/react-native';
|
||||
import notifee, { AndroidImportance, EventType } from '@notifee/react-native';
|
||||
import { apiCall } from '../ApiHelper';
|
||||
import { REMOVE_FCM_TOKEN, STORE_FCM_TOKEN } from '../ApiUrls';
|
||||
import { store } from '../../redux/store'; // Import store directly
|
||||
import { addNotification } from '../../redux/notificationSlice';
|
||||
import { navigate } from '../navigationService';
|
||||
|
||||
// 🔹 Request notification permission
|
||||
export const requestPermission = async () => {
|
||||
@@ -257,7 +258,7 @@ export const foregroundListener = () => {
|
||||
|
||||
if (!remoteMessage) return;
|
||||
|
||||
const { notification, data } = remoteMessage;
|
||||
const { notification, data } = remoteMessage;
|
||||
const title = notification?.title || data?.title || 'New Message';
|
||||
const body = notification?.body || data?.body || '';
|
||||
|
||||
@@ -313,6 +314,38 @@ export const tokenRefreshHandler = () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const handleNotificationNavigation = (data: any) => {
|
||||
if (!data || !data.msgType) {
|
||||
return console.log('❌ No msgType in notification data for navigation.');
|
||||
}
|
||||
|
||||
console.log('🧭 Navigating based on msgType:', data.msgType);
|
||||
navigate('NotificationRedirection',{data:data});
|
||||
};
|
||||
|
||||
export const setupFirebaseHandlers = () => {
|
||||
messaging().onNotificationOpenedApp(remoteMessage => {
|
||||
console.log('📱 App opened from background via FCM tap');
|
||||
handleNotificationNavigation(remoteMessage.data);
|
||||
});
|
||||
|
||||
messaging().getInitialNotification().then(remoteMessage => {
|
||||
if (remoteMessage) {
|
||||
console.log('💀 App opened from quit state via FCM tap');
|
||||
handleNotificationNavigation(remoteMessage.data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const setupNotificationPressHandlers = () => {
|
||||
notifee.onForegroundEvent(({ type, detail }) => {
|
||||
if (type === EventType.PRESS) {
|
||||
console.log('👆 User pressed a Notifee notification in the foreground');
|
||||
console.log("Notification data:", detail.notification?.data);
|
||||
handleNotificationNavigation(detail.notification?.data);
|
||||
}
|
||||
});
|
||||
};
|
||||
// Optional: Export all functions as a single object for easier imports
|
||||
export default {
|
||||
requestPermission,
|
||||
@@ -322,4 +355,5 @@ export default {
|
||||
foregroundListener,
|
||||
backgroundHandler,
|
||||
tokenRefreshHandler,
|
||||
handleNotificationNavigation
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
// src/utils/navigationService.ts
|
||||
import { createNavigationContainerRef } from '@react-navigation/native';
|
||||
import { RootStackParamList } from '../navigation/types'; // ✅ Your import path
|
||||
|
||||
export const navigationRef = createNavigationContainerRef<RootStackParamList>();
|
||||
|
||||
/**
|
||||
* A type-safe navigation function with debug logs.
|
||||
* It correctly infers the parameters required for each route in your RootStack.
|
||||
*/
|
||||
export function navigate<RouteName extends keyof RootStackParamList>(
|
||||
...args: undefined extends RootStackParamList[RouteName]
|
||||
// Handles routes with optional or no params
|
||||
? [screen: RouteName, params?: RootStackParamList[RouteName]]
|
||||
// Handles routes that require params
|
||||
: [screen: RouteName, params: RootStackParamList[RouteName]]
|
||||
) {
|
||||
// Log the initial call to the navigate function
|
||||
console.log('⏩ [navigationService] Navigate called with:', args);
|
||||
|
||||
if (navigationRef.isReady()) {
|
||||
// Log immediate navigation
|
||||
console.log('✅ [navigationService] Ref is ready. Navigating now.');
|
||||
navigationRef.navigate(...(args as [string, object]));
|
||||
} else {
|
||||
// Warn that navigation is being delayed
|
||||
console.warn('⚠ [navigationService] Ref not ready. Retrying in 300ms...');
|
||||
|
||||
setTimeout(() => {
|
||||
if (navigationRef.isReady()) {
|
||||
// Log the successful retry
|
||||
console.log('✅ [navigationService] Retry successful. Navigating now.');
|
||||
navigationRef.navigate(...(args as [string, object]));
|
||||
} else {
|
||||
// Log a critical failure if the retry also fails
|
||||
console.error('❌ [navigationService] Navigation failed on retry. Ref still not ready.');
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user