import { useApolloClient } from "@apollo/client" ; import PushNotificationIOS from "@react-native-community/push-notification-ios" ; import messaging from "@react-native-firebase/messaging" ; import { createBottomTabNavigator } from "@react-navigation/bottom-tabs" ; import { CardStyleInterpolators , createStackNavigator } from "@react-navigation/stack" ; import i18n from "i18n-js" ; import "node-libs-react-native/globals" ; import * as React from "react" ; import { useCallback , useEffect } from "react" ; import { AppState } from "react-native" ; import EStyleSheet from "react-native-extended-stylesheet" ; import * as RNLocalize from "react-native-localize" ; import Icon from "react-native-vector-icons/Ionicons" ; import analytics from "@react-native-firebase/analytics" ; import { translate } from "../i18n" ; import { AuthenticationScreen , AuthenticationCheckScreen , } from "../screens/authentication-screen" ; import { PinScreen } from "../screens/authentication-screen/pin-screen" ; import { ContactsScreen , ContactsDetailScreen } from "../screens/contacts-screen" ; import { DebugScreen } from "../screens/debug-screen" ; import { EarnMapDataInjected } from "../screens/earns-map-screen" ; import { EarnQuiz , EarnSection } from "../screens/earns-screen" ; import { SectionCompleted } from "../screens/earns-screen/section-completed" ; import { GetStartedScreen } from "../screens/get-started-screen" ; import { MapScreen } from "../screens/map-screen/map-screen" ; import { MoveMoneyScreenDataInjected } from "../screens/move-money-screen" ; import { WelcomePhoneInputScreen , WelcomePhoneValidationScreenDataInjected , } from "../screens/phone-auth-screen" ; import { PriceScreen } from "../screens/price-screen/price-screen" ; import { ReceiveBitcoinScreen } from "../screens/receive-bitcoin-screen" ; import { ScanningQRCodeScreen , SendBitcoinConfirmationScreen , SendBitcoinScreen , } from "../screens/send-bitcoin-screen" ; import { SettingsScreen , UsernameScreen } from "../screens/settings-screen" ; import { LanguageScreen } from "../screens/settings-screen/language-screen" ; import { SecurityScreen } from "../screens/settings-screen/security-screen" ; import { TransactionDetailScreen } from "../screens/transaction-detail-screen" ; import { TransactionHistoryScreenDataInjected } from "../screens/transaction-screen/transaction-screen" ; import { WelcomeFirstScreen } from "../screens/welcome-screens" ; import { palette } from "../theme/palette" ; import { AccountType } from "../utils/enum" ; import { addDeviceToken } from "../utils/notifications" ; import useToken from "../utils/use-token" ; import { showModalClipboardIfValidPayment } from "../utils/clipboard" ; import { ContactStackParamList , MoveMoneyStackParamList , PhoneValidationStackParamList , PrimaryStackParamList , RootStackParamList , } from "./stack-param-lists" ; import type { NavigatorType } from "../types/jsx" ; import PushNotification from "react-native-push-notification" ; import useMainQuery from "@app/hooks/use-main-query" ; PushNotification . configure ( { onRegister ( token ) { console . log ( "TOKEN:" , token ) ; } , onNotification ( notification ) { console . log ( "NOTIFICATION:" , notification ) ; notification . finish ( PushNotificationIOS . FetchResult . NoData ) ; } , onAction ( notification ) { console . log ( "ACTION:" , notification . action ) ; console . log ( "NOTIFICATION:" , notification ) ; } , onRegistrationError ( err ) { console . error ( `onRegistration error: ${ err . message }` , err ) ; } , permissions : { alert : true , badge : true , sound : true , } , popInitialNotification : false , /**
     * (optional) default: true
     * - Specified if permissions (ios) and token (android and ios) will requested or not,
     * - if not, you must call PushNotificationsHandler.requestPermissions() later
     * - if you are not using remote notification or do not have Firebase installed, use this:
     *     requestPermissions: Platform.OS === 'ios'
     */ requestPermissions : false , } ) ; const styles = EStyleSheet . create ( { bottomNavigatorStyle : { height : "10%" , } , } ) ; const size = 32 ; const RootNavigator = createStackNavigator < RootStackParamList > ( ) ; export const RootStack = ( ) => { const appState = React . useRef ( AppState . currentState ) ; const client = useApolloClient ( ) ; const { token , hasToken , tokenNetwork } = useToken ( ) ; const { userPreferredLanguage , myPubKey , username } = useMainQuery ( ) ; const _handleAppStateChange = useCallback ( async ( nextAppState ) => { if ( appState . current . match ( /background/ ) && nextAppState === "active" ) { console . log ( "App has come to the foreground!" ) ; hasToken && showModalClipboardIfValidPayment ( { client , network : tokenNetwork , myPubKey , username , } ) ; } appState . current = nextAppState ; } , [ client , hasToken , tokenNetwork , myPubKey , username ] ) ; useEffect ( ( ) => { const subscription = AppState . addEventListener ( "change" , _handleAppStateChange ) ; return ( ) => subscription . remove ( ) ; } , [ _handleAppStateChange ] ) ; const showNotification = ( remoteMessage ) => { const soundName = undefined ; PushNotification . localNotification ( { ticker : "My Notification Ticker" , autoCancel : true , largeIcon : "ic_launcher" , smallIcon : "ic_notification" , vibrate : true , vibration : 300 , tag : "some_tag" , group : "group" , ongoing : false , category : "" , title : remoteMessage . notification . title , message : remoteMessage . notification . body , userInfo : { screen : "home" } , playSound : ! ! soundName , soundName : soundName || "default" , } ) ; } ; const fallback = RNLocalize . getLocales ( ) ?. [ 0 ] ?? { languageTag : "es-SV" , isRTL : false } ; const { languageTag } = RNLocalize . findBestAvailableLanguage ( Object . keys ( i18n . translations ) ) || fallback ; i18n . locale = ! userPreferredLanguage || userPreferredLanguage === "DEFAULT" ? languageTag : userPreferredLanguage ; useEffect ( ( ) => { const unsubscribe = messaging ( ) . onMessage ( async ( remoteMessage ) => { console . log ( "onMessage" ) ; showNotification ( remoteMessage ) ; } ) ; return unsubscribe ; } , [ ] ) ; useEffect ( ( ) => { messaging ( ) . setBackgroundMessageHandler ( async ( remoteMessage ) => { console . log ( "background arrived from setBackgroundMessageHandler" ) ; showNotification ( remoteMessage ) ; } ) ; } , [ ] ) ; useEffect ( ( ) => { messaging ( ) . onNotificationOpenedApp ( ( _remoteMessage ) => { } ) ; messaging ( ) . getInitialNotification ( ) . then ( ( _remoteMessage ) => { } ) ; } , [ ] ) ; useEffect ( ( ) => messaging ( ) . onTokenRefresh ( ( ) => token && addDeviceToken ( client ) ) , [ client , token ] ) ; return ( < RootNavigator . Navigator screenOptions = { { gestureEnabled : false , headerBackTitle : translate ( "common.back" ) , } } initialRouteName = { token ? "authenticationCheck" : "getStarted" } > < RootNavigator . Screen name = "getStarted" component = { GetStartedScreen } options = { { headerShown : false , animationEnabled : false , } } /> < RootNavigator . Screen name = "welcomeFirst" component = { WelcomeFirstScreen } options = { { headerShown : false } } /> < RootNavigator . Screen name = "authenticationCheck" component = { AuthenticationCheckScreen } options = { { headerShown : false , animationEnabled : false } } /> < RootNavigator . Screen name = "authentication" component = { AuthenticationScreen } options = { { headerShown : false , animationEnabled : false } } /> < RootNavigator . Screen name = "pin" component = { PinScreen } options = { { headerShown : false } } /> < RootNavigator . Screen name = "Primary" component = { PrimaryNavigator } options = { { headerShown : false , animationEnabled : false , title : translate ( "PrimaryScreen.title" ) , } } /> < StackMoveMoney . Screen name = "scanningQRCode" component = { ScanningQRCodeScreen } options = { { title : translate ( "ScanningQRCodeScreen.title" ) , headerShown : false , cardStyleInterpolator : CardStyleInterpolators . forHorizontalIOS , } } /> < StackMoveMoney . Screen name = "sendBitcoin" component = { SendBitcoinScreen } options = { { title : translate ( "SendBitcoinScreen.title" ) } } /> < StackMoveMoney . Screen name = "sendBitcoinConfirmation" component = { SendBitcoinConfirmationScreen } options = { { title : translate ( "SendBitcoinConfirmationScreen.title" ) } } /> < StackMoveMoney . Screen name = "receiveBitcoin" component = { ReceiveBitcoinScreen } options = { { title : translate ( "ReceiveBitcoinScreen.title" ) , } } /> < RootNavigator . Screen name = "earnsSection" component = { EarnSection } options = { { cardStyleInterpolator : CardStyleInterpolators . forHorizontalIOS , headerStyle : { backgroundColor : palette . blue } , headerTintColor : palette . white , headerTitleStyle : { fontWeight : "bold" , fontSize : 18 , } , } } /> < RootNavigator . Screen name = "earnsQuiz" component = { EarnQuiz } options = { { headerShown : false , cardStyleInterpolator : CardStyleInterpolators . forVerticalIOS , } } /> < RootNavigator . Screen name = "settings" component = { SettingsScreen } options = { ( ) => ( { title : translate ( "SettingsScreen.title" ) , } ) } /> < RootNavigator . Screen name = "setUsername" component = { UsernameScreen } options = { ( ) => ( { title : "" , } ) } /> < RootNavigator . Screen name = "language" component = { LanguageScreen } options = { { title : translate ( "common.languagePreference" ) } } /> < RootNavigator . Screen name = "security" component = { SecurityScreen } options = { { title : translate ( "common.security" ) } } /> < RootNavigator . Screen name = "Profile" component = { DebugScreen } / > < RootNavigator . Screen name = "sectionCompleted" component = { SectionCompleted } options = { { headerShown : false , cardStyleInterpolator : CardStyleInterpolators . forVerticalIOS , } } /> < RootNavigator . Screen name = "phoneValidation" component = { PhoneValidationNavigator } options = { { headerShown : false , cardStyleInterpolator : CardStyleInterpolators . forVerticalIOS , } } /> < RootNavigator . Screen name = "transactionDetail" component = { TransactionDetailScreen } options = { { headerShown : false , } } /> < RootNavigator . Screen name = "transactionHistory" component = { TransactionHistoryScreenDataInjected } options = { { title : translate ( "TransactionScreen.transactionHistoryTitle" ) } } /> < RootNavigator . Screen name = "priceDetail" component = { PriceScreen } options = { { cardStyleInterpolator : CardStyleInterpolators . forHorizontalIOS , title : translate ( "common.bitcoinPrice" ) , } } initialParams = { { account : AccountType . Bitcoin } } /> < /RootNavigator.Navigator>); } ; const StackContacts = createStackNavigator < ContactStackParamList > ( ) ; export const ContactNavigator = ( ) => ( < StackContacts . Navigator > < StackContacts . Screen name = "Contacts" component = { ContactsScreen } options = { { title : translate ( "ContactsScreen.title" ) , headerShown : false , } } /> < StackContacts . Screen name = "contactDetail" component = { ContactsDetailScreen } options = { { headerShown : false } } /> < /StackContacts.Navigator>); const StackMoveMoney = createStackNavigator < MoveMoneyStackParamList > ( ) ; export const MoveMoneyNavigator = ( ) => ( < StackMoveMoney . Navigator > < StackMoveMoney . Screen name = "moveMoney" component = { MoveMoneyScreenDataInjected } options = { { headerShown : false , title : translate ( "MoveMoneyScreen.title" ) , } } /> < /StackMoveMoney.Navigator>); const StackPhoneValidation = createStackNavigator < PhoneValidationStackParamList > ( ) ; export const PhoneValidationNavigator = ( ) => ( < StackPhoneValidation . Navigator > < StackPhoneValidation . Screen name = "welcomePhoneInput" options = { { headerShown : false , title : translate ( "common.phoneNumber" ) , } } component = { WelcomePhoneInputScreen } / > < StackPhoneValidation . Screen name = "welcomePhoneValidation" component = { WelcomePhoneValidationScreenDataInjected } options = { { title : "" , } } /> < /StackPhoneValidation.Navigator>); const Tab = createBottomTabNavigator < PrimaryStackParamList > ( ) ; type TabProps = { color : string ; } ; export const PrimaryNavigator = ( ) => { const { tokenNetwork } = useToken ( ) ; React . useEffect ( ( ) => { if ( tokenNetwork ) { analytics ( ) . setUserProperties ( { network : tokenNetwork } ) ; } } , [ tokenNetwork ] ) ; return ( < Tab . Navigator initialRouteName = "MoveMoney" screenOptions = { { tabBarActiveTintColor : tokenNetwork === "mainnet" ? palette . lightBlue : palette . orange , tabBarInactiveTintColor : palette . midGrey , tabBarStyle : styles . bottomNavigatorStyle , tabBarLabelStyle : { paddingBottom : 6 } , tabBarHideOnKeyboard : true , } } > < Tab . Screen name = "MoveMoney" component = { MoveMoneyNavigator } options = { { title : translate ( "MoveMoneyScreen.title" ) , tabBarIcon : ( { color } ) => ( < Icon name = "ios-home" size = { size } color = { color } / > ) , headerShown : false , } } /> < Tab . Screen name = "Contacts" component = { ContactNavigator } options = { { title : translate ( "ContactsScreen.title" ) , tabBarIcon : ( { color } ) => ( < Icon name = "ios-people-outline" size = { size } color = { color } / > ) , } } /> < Tab . Screen name = "Map" component = { MapScreen } options = { { title : translate ( "MapScreen.title" ) , headerShown : false , tabBarIcon : ( { color } ) => ( < Icon name = "ios-map-outline" size = { size } color = { color } / > ) , } } /> < Tab . Screen name = "Earn" component = { EarnMapDataInjected } options = { { title : translate ( "EarnScreen.title" ) , headerShown : false , tabBarIcon : ( { color } ) => ( < Icon name = "ios-rocket" size = { size } color = { color } / > ) , } } /> < /Tab.Navigator>); } ;