again push for merge code

This commit is contained in:
Jaanu423
2025-10-10 13:23:27 +05:30
parent cd91774d0e
commit ae35611bdb
5 changed files with 186 additions and 6 deletions
+4 -1
View File
@@ -5,17 +5,20 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
import { PaperProvider } from 'react-native-paper'; import { PaperProvider } from 'react-native-paper';
import AppNavigator from './src/navigation/AppNavigator'; import AppNavigator from './src/navigation/AppNavigator';
import notifee from '@notifee/react-native'; 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() { function App() {
const isDarkMode = useColorScheme() === 'dark'; const isDarkMode = useColorScheme() === 'dark';
useEffect(() => { useEffect(() => {
// 🔹 Ask for permission // 🔹 Ask for permission
requestPermission(); requestPermission();
// 🔹 Handle background + quit state // 🔹 Handle background + quit state
backgroundHandler(); backgroundHandler();
setupFirebaseHandlers()
setupNotificationPressHandlers()
// 🔹 Listen for foreground messages // 🔹 Listen for foreground messages
const unsubscribe = foregroundListener(); const unsubscribe = foregroundListener();
+6 -2
View File
@@ -22,6 +22,8 @@ import TransactionsList from "../screens/transaction/TransactionList";
import RandomSelectUserScreen from "../screens/management/RandomSelectUserScreen"; import RandomSelectUserScreen from "../screens/management/RandomSelectUserScreen";
import Notification from "../screens/notification/Notification"; import Notification from "../screens/notification/Notification";
import ManagementScreen from "../screens/management/ManagementScreen"; import ManagementScreen from "../screens/management/ManagementScreen";
import { navigationRef } from "../utils/navigationService";
import NotificationRedirection from "../screens/NotificationRedirection";
export type RootStackParamList = { export type RootStackParamList = {
Splash: undefined; Splash: undefined;
@@ -44,6 +46,7 @@ export type RootStackParamList = {
TransactionList: undefined TransactionList: undefined
RandomSelectUserScreen: { groupId: string | number, cycleNumber: number }; RandomSelectUserScreen: { groupId: string | number, cycleNumber: number };
Notification: undefined; Notification: undefined;
NotificationRedirection:{ data: any };
Management: Management:
| { actionTab: "My Groups" } | { actionTab: "My Groups" }
| { actionTab1: "Joined Groups" } | { actionTab1: "Joined Groups" }
@@ -88,8 +91,8 @@ export default function AppNavigator() {
return ( return (
<NavigationContainer linking={linking}> <NavigationContainer linking={linking} ref={navigationRef}>
<Stack.Navigator initialRouteName="Splash"> <Stack.Navigator initialRouteName="Splash" >
<Stack.Screen name="Splash" component={SplashScreen} options={{ headerShown: false }} /> <Stack.Screen name="Splash" component={SplashScreen} options={{ headerShown: false }} />
<Stack.Screen name="Home" component={BottomTabs} options={{ headerShown: false }} /> <Stack.Screen name="Home" component={BottomTabs} options={{ headerShown: false }} />
<Stack.Screen name="Login" component={LoginScreen} 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="RandomSelectUserScreen" component={RandomSelectUserScreen} options={{ headerShown: false }} />
<Stack.Screen name="Notification" component={Notification} options={{ headerShown: false }} /> <Stack.Screen name="Notification" component={Notification} options={{ headerShown: false }} />
<Stack.Screen name="Management" component={ManagementScreen} options={{ headerShown: false }} /> <Stack.Screen name="Management" component={ManagementScreen} options={{ headerShown: false }} />
<Stack.Screen name="NotificationRedirection" component={NotificationRedirection} options={{ headerShown: false }} />
</Stack.Navigator> </Stack.Navigator>
</NavigationContainer> </NavigationContainer>
); );
+99
View File
@@ -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;
+35 -1
View File
@@ -129,11 +129,12 @@
import messaging from '@react-native-firebase/messaging'; 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 { apiCall } from '../ApiHelper';
import { REMOVE_FCM_TOKEN, STORE_FCM_TOKEN } from '../ApiUrls'; import { REMOVE_FCM_TOKEN, STORE_FCM_TOKEN } from '../ApiUrls';
import { store } from '../../redux/store'; // Import store directly import { store } from '../../redux/store'; // Import store directly
import { addNotification } from '../../redux/notificationSlice'; import { addNotification } from '../../redux/notificationSlice';
import { navigate } from '../navigationService';
// 🔹 Request notification permission // 🔹 Request notification permission
export const requestPermission = async () => { export const requestPermission = async () => {
@@ -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 // Optional: Export all functions as a single object for easier imports
export default { export default {
requestPermission, requestPermission,
@@ -322,4 +355,5 @@ export default {
foregroundListener, foregroundListener,
backgroundHandler, backgroundHandler,
tokenRefreshHandler, tokenRefreshHandler,
handleNotificationNavigation
}; };
+40
View File
@@ -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);
}
}