// App.tsx import AsyncStorage from '@react-native-async-storage/async-storage'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { toastConfig } from 'components/CustomAlertModal'; import { navigationRef } from 'components/NavigationRef'; import SplashScreen from 'components/SplashScreen'; import i18n from 'i18n/i18n'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { I18nextProvider } from 'react-i18next'; import { Animated, Dimensions, LogBox, PermissionsAndroid, Platform, StatusBar, StyleSheet, View, } from 'react-native'; import Toast from 'react-native-toast-message'; // Screens import notifee, { AndroidImportance } from '@notifee/react-native'; import { getApp } from '@react-native-firebase/app'; import { getInitialNotification, getMessaging, getToken, onMessage, onNotificationOpenedApp, } from '@react-native-firebase/messaging'; import DeviceInfo from 'react-native-device-info'; import Login from 'screens/auth/login/ui'; import Confirm from 'screens/auth/login/ui/Confirm'; import Register from 'screens/auth/registeration/ui'; import SecondStep from 'screens/auth/registeration/ui/SecondStep'; import TermsAndConditions from 'screens/auth/registeration/ui/TermsAndConditions'; import SelectAuth from 'screens/auth/select-auth/SelectAuth'; import Branches from 'screens/home/branches/ui/Branches'; import ListBranches from 'screens/home/branches/ui/ListBranches'; import CargoPrices from 'screens/home/cargoPrices/ui/CargoPrices'; import Home from 'screens/home/home/ui/Home'; import RestrictedProduct from 'screens/home/restrictedProduct/ui/RestrictedProduct'; import CreatePassword from 'screens/passport/createPassport/ui/CreatePassword'; import Passport from 'screens/passport/myPassport/ui/Passport'; import Profile from 'screens/profile/myProfile/ui/Profile'; import Notifications from 'screens/profile/notifications/ui/Notifications'; import AddedLock from 'screens/profile/settings/ui/AddedLock'; import Settings from 'screens/profile/settings/ui/Settings'; import SettingsLock from 'screens/profile/settings/ui/SettingsLock'; import Support from 'screens/profile/support/ui/Support'; import Warehouses from 'screens/profile/warehouses/ui/Warehouses'; import Status from 'screens/status/ui/Status'; import EnterCard from 'screens/wallet/enterCard/ui/EnterCard'; import Wallet from 'screens/wallet/payment/ui/Wallet'; import PaymentMethod from 'screens/wallet/paymentMethod/ui/PaymentMethod'; import PaymentQrCode from 'screens/wallet/successPayment/ui/PaymentQrCode'; import Onboarding from 'screens/welcome/Onboarding'; LogBox.ignoreLogs([ 'Non-serializable values were found in the navigation state', 'ViewPropTypes will be removed', ]); const Stack = createNativeStackNavigator(); const screenWidth = Dimensions.get('window').width; const queryClient = new QueryClient(); const saveNotification = async (remoteMessage: any) => { try { const stored = await AsyncStorage.getItem('notifications'); const notifications = stored ? JSON.parse(stored) : []; const newNotification = { id: Date.now(), title: remoteMessage.notification?.title || remoteMessage.data?.title || 'Yangi bildirishnoma', message: remoteMessage.notification?.body || remoteMessage.data?.body || 'Matn yo‘q', sentTime: remoteMessage.sentTime || Date.now(), }; await AsyncStorage.setItem( 'notifications', JSON.stringify([newNotification, ...notifications]), ); } catch (e) { console.error('Notification saqlashda xato:', e); } }; async function onDisplayNotification(remoteMessage: any) { const channelId = await notifee.createChannel({ id: 'default', name: 'Umumiy bildirishnomalar', sound: 'default', importance: AndroidImportance.HIGH, }); await notifee.displayNotification({ title: remoteMessage.notification?.title || remoteMessage.data?.title || 'Yangi xabar', body: remoteMessage.notification?.body || remoteMessage.data?.body || 'Matn yo‘q', android: { channelId, smallIcon: 'ic_launcher_foreground', sound: 'default', pressAction: { id: 'default', }, }, }); } async function requestNotificationPermission() { if (Platform.OS === 'android' && Platform.Version >= 33) { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS, ); console.log('POST_NOTIFICATIONS permission:', granted); } } export default function App() { const [initialRoute, setInitialRoute] = useState(null); const slideAnim = useRef(new Animated.Value(0)).current; const [isSplashVisible, setIsSplashVisible] = useState(true); useEffect(() => { requestNotificationPermission(); const messagingInstance = getMessaging(); const unsubscribe = onMessage(messagingInstance, async remoteMessage => { console.log('Foreground message:', remoteMessage); await saveNotification(remoteMessage); await onDisplayNotification(remoteMessage); }); const unsubscribeOpened = onNotificationOpenedApp( messagingInstance, remoteMessage => { console.log('Backgrounddan ochildi:', remoteMessage); saveNotification(remoteMessage); }, ); (async () => { const remoteMessage = await getInitialNotification(messagingInstance); if (remoteMessage) { console.log('Killeddan ochildi:', remoteMessage); saveNotification(remoteMessage); } })(); return () => { unsubscribe(); unsubscribeOpened(); }; }, []); useEffect(() => { const initializeApp = async () => { try { const [seen, token, lang] = await Promise.all([ AsyncStorage.getItem('hasSeenOnboarding'), AsyncStorage.getItem('token'), AsyncStorage.getItem('language'), ]); if (lang) await i18n.changeLanguage(lang); const initialRouteName = !seen ? 'Onboarding' : token ? 'Home' : 'select-auth'; setInitialRoute(initialRouteName); } catch (error) { console.error('App initialization error:', error); setInitialRoute('select-auth'); } }; initializeApp(); }, []); const handleSplashFinish = useMemo( () => () => { Animated.timing(slideAnim, { toValue: -screenWidth, duration: 600, useNativeDriver: true, }).start(() => setIsSplashVisible(false)); }, [slideAnim], ); const handleOnboardingFinish = useMemo( () => async (navigation: any) => { await AsyncStorage.setItem('hasSeenOnboarding', 'true'); navigation.replace('select-auth'); }, [], ); const [firebaseToken, setFirebseToken] = useState<{ fcmToken: string; deviceId: string; deviceName: string; } | null>(); const app = getApp(); const messaging = getMessaging(app); const getDeviceData = async () => { try { const fcmToken = await getToken(messaging); return { fcmToken, deviceId: await DeviceInfo.getUniqueId(), deviceName: await DeviceInfo.getDeviceName(), }; } catch (e) { console.log('Xato:', e); return null; } }; console.log(firebaseToken); useEffect(() => { getDeviceData().then(data => { setFirebseToken(data); }); }, []); if (!initialRoute) return null; return ( {props => ( handleOnboardingFinish(props.navigation)} /> )} {/* Splash transition */} {isSplashVisible && ( )} ); }