import * as React from 'react'; import { Observer, Provider } from 'mobx-react'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { NavigationContainer, DarkTheme } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { SafeAreaProvider, SafeAreaView, initialWindowMetrics } from 'react-native-safe-area-context'; import { BackHandler, NativeEventSubscription, Platform, StatusBar, AppState } from 'react-native'; import { activityStore, alertStore, balanceStore, cashuStore, channelBackupStore, channelsStore, connectivityStore, contactStore, feeStore, fiatStore, inventoryStore, invoicesStore, lightningAddressStore, lnurlPayStore, lspStore, messageSignStore, modalStore, nodeInfoStore, notesStore, offersStore, paymentsStore, posStore, settingsStore, swapStore, syncStore, transactionsStore, unitsStore, utxosStore, sweepStore, nostrWalletConnectStore } from './stores/Stores'; import NavigationService from './NavigationService'; import PushNotificationManager from './PushNotificationManager'; import StealthModeUtils from './utils/StealthModeUtils'; import StealthModeWrapper from './components/StealthModeWrapper'; import { AppContainer } from './components/layout/AppContainer'; import CopiedToastHost from './components/CopiedToast'; import AlertModal from './components/Modals/AlertModal'; import ExternalLinkModal from './components/Modals/ExternalLinkModal'; import AndroidNfcModal from './components/Modals/AndroidNfcModal'; import InfoModal from './components/Modals/InfoModal'; import ShareModal from './components/Modals/ShareModal'; import NewChannelModal from './components/Modals/NewChannelModal'; import GraphSyncPromptModal from './components/Modals/GraphSyncPromptModal'; import RatingModal from './components/Modals/RatingModal'; import RestoreChannelModal from './components/Modals/RestoreChannelModal'; // Views import Transaction from './views/Transaction'; import Wallet from './views/Wallet/Wallet'; import Send from './views/Send'; import LnurlPay from './views/LnurlPay/LnurlPay'; import ClinkPay from './views/ClinkPay/ClinkPay'; import LnurlChannel from './views/LnurlChannel'; import LnurlAuth from './views/LnurlAuth'; import Receive from './views/Receive'; import PaymentRequest from './views/PaymentRequest'; import HandleAnythingQRScanner from './views/HandleAnythingQRScanner'; import SwapsQRScanner from './views/SwapsQRScanner'; import RefundSwapQRScanner from './views/RefundSwapQRScanner'; import NodeQRScanner from './views/NodeQRScanner'; import OpenChannel from './views/OpenChannel'; import SendingOnChain from './views/SendingOnChain'; import VerifyOnChain from './views/VerifyOnChain'; import SendingLightning from './views/SendingLightning'; import Channel from './views/Channels/Channel'; import Payment from './views/Payment'; import PaymentPaths from './views/PaymentPaths'; import Invoice from './views/Invoice'; import OnChainAddresses from './views/OnChainAddresses'; import DonateToZEUS from './views/DonateToZEUS'; import ChangeDonationSettings from './views/ChangeDonationSettings'; import NodeInfo from './views/NodeInfo'; import Lockscreen from './views/Lockscreen'; import NostrContacts from './views/NostrContacts'; import MultiQR from './views/MultiQR'; // Settings views import Settings from './views/Settings/Settings'; import WalletConfiguration from './views/Settings/WalletConfiguration'; import Wallets from './views/Settings/Wallets'; import Networking from './views/Settings/Networking'; import Privacy from './views/Settings/Privacy'; import StealthMode from './views/Settings/StealthMode'; import Security from './views/Settings/Security'; import SetPassword from './views/Settings/SetPassword'; import SetDuressPassword from './views/Settings/SetDuressPassword'; import SetPin from './views/Settings/SetPin'; import SetDuressPin from './views/Settings/SetDuressPin'; import Language from './views/Settings/Language'; import Currency from './views/Settings/Currency'; import SelectCurrency from './views/Settings/SelectCurrency'; import Display from './views/Settings/Display'; import CertInstallInstructions from './views/Settings/CertInstallInstructions'; import Support from './views/Settings/Support'; import Help from './views/Settings/Help'; import SocialMedia from './views/Settings/SocialMedia'; import Sponsors from './views/Settings/Sponsors'; import Olympians from './views/Settings/Olympians'; import Gods from './views/Settings/Gods'; import Mortals from './views/Settings/Mortals'; import PointOfSale from './views/Settings/PointOfSale'; import PointOfSaleRecon from './views/Settings/PointOfSaleRecon'; import PointOfSaleReconExport from './views/Settings/PointOfSaleReconExport'; import Categories from './views/POS/Categories'; import ProductCategoryDetails from './views/POS/ProductCategoryDetails'; import Products from './views/POS/Products'; import ProductDetails from './views/POS/ProductDetails'; import PaymentsSettings from './views/Settings/PaymentsSettings'; import InvoicesSettings from './views/Settings/InvoicesSettings'; import LSP from './views/Settings/LSP'; import ChannelsSettings from './views/Settings/ChannelsSettings'; import SetWalletPicture from './views/Settings/SetWalletPicture'; import ChoosePaymentMethod from './views/ChoosePaymentMethod'; import NWCConnectionsList from './views/Settings/NostrWalletConnect/NWCConnectionsList'; import AddOrEditNWCConnection from './views/Settings/NostrWalletConnect/AddOrEditNWCConnection'; import NWCConnectionDetails from './views/Settings/NostrWalletConnect/NWCConnectionDetails'; import NWCConnectionQR from './views/Settings/NostrWalletConnect/NWCConnectionQR'; import NWCSettings from './views/Settings/NostrWalletConnect/NWCSettings'; import NWCConnectionActivity from './views/Settings/NostrWalletConnect/NWCConnectionActivity'; import NWCConnectionActivityFilter from './views/Settings/NostrWalletConnect/NWCConnectionActivityFilter'; // Lightning address import LightningAddress from './views/LightningAddress'; import CreateZaplockerLightningAddress from './views/LightningAddress/CreateZaplockerLightningAddress'; import CreateNWCLightningAddress from './views/LightningAddress/CreateNWCLightningAddress'; import ZaplockerGetChan from './views/LightningAddress/ZaplockerGetChan'; import ZaplockerInfo from './views/LightningAddress/ZaplockerInfo'; import NWCAddressInfo from './views/LightningAddress/NWCAddressInfo'; import LightningAddressSettings from './views/LightningAddress/LightningAddressSettings'; import LightningAddressQR from './views/LightningAddress/LightningAddressQR'; import NWCAddressSettings from './views/LightningAddress/NWCAddressSettings'; import Attestation from './views/LightningAddress/Attestation'; import Attestations from './views/LightningAddress/Attestations'; import NostrKeys from './views/LightningAddress/NostrKeys'; import NostrRelays from './views/LightningAddress/NostrRelays'; import ChangeAddress from './views/LightningAddress/ChangeAddress'; import EditProfile from './views/LightningAddress/EditProfile'; import ZeusPayPlus from './views/LightningAddress/ZeusPayPlus'; import ZeusPayPlusPerks from './views/LightningAddress/ZeusPayPlusPerks'; import WebPortalPOS from './views/LightningAddress/WebPortalPOS'; // BOLT 12 import PayCodes from './views/PayCodes'; import PayCode from './views/PayCode'; import CreatePayCode from './views/PayCodeCreate'; import Bolt12Address from './views/Settings/Bolt12Address'; // Embedded Node import EmbeddedNode from './views/Settings/EmbeddedNode'; import DisasterRecovery from './views/Settings/EmbeddedNode/DisasterRecovery'; import DisasterRecoveryAdvanced from './views/Settings/EmbeddedNode/DisasterRecoveryAdvanced'; import Pathfinding from './views/Settings/EmbeddedNode/Pathfinding'; import ExpressGraphSync from './views/Settings/EmbeddedNode/ExpressGraphSync'; import RapidGossipSync from './views/Settings/EmbeddedNode/RapidGossipSync'; import EsploraServer from './views/Settings/EmbeddedNode/EsploraServer'; import VssServer from './views/Settings/EmbeddedNode/VssServer'; import PathfindingScorer from './views/Settings/EmbeddedNode/PathfindingScorer'; import LNDLogs from './views/Settings/EmbeddedNode/LNDLogs'; import LDKLogs from './views/Settings/EmbeddedNode/LDKLogs'; import Peers from './views/Settings/EmbeddedNode/Peers'; import NeutrinoPeers from './views/Settings/EmbeddedNode/Peers/NeutrinoPeers'; import ZeroConfPeers from './views/Settings/EmbeddedNode/Peers/ZeroConfPeers'; import Advanced from './views/Settings/EmbeddedNode/Advanced'; import AdvancedRescan from './views/Settings/EmbeddedNode/AdvancedRescan'; import Troubleshooting from './views/Settings/EmbeddedNode/Troubleshooting'; // Routing import Routing from './views/Routing/Routing'; import RoutingEvent from './views/Routing/RoutingEvent'; import SetFees from './views/Routing/SetFees'; // new views import Activity from './views/Activity/Activity'; import ActivityFilter from './views/Activity/ActivityFilter'; import CoinControl from './views/UTXOs/CoinControl'; import Utxo from './views/UTXOs/UTXO'; import QR from './views/QR'; import AddNotes from './views/AddNotes'; import Contacts from './views/Settings/Contacts'; import AddContact from './views/Settings/AddContact'; import ContactDetails from './views/ContactDetails'; import PendingHTLCs from './views/PendingHTLCs'; import Swaps from './views/Swaps/index'; import SwapDetails from './views/Swaps/SwapDetails'; import SwapsPane from './views/Swaps/SwapsPane'; import RefundSwap from './views/Swaps/Refund'; import SwapSettings from './views/Swaps/Settings'; // POS import Order from './views/Order'; import IntroSplash from './views/IntroSplash'; // Onboarding import Onboarding1 from './views/Onboarding/Onboarding1'; import RecommendedSettings from './views/Onboarding/RecommendedSettings'; import WalletSetup from './views/Onboarding/WalletSetup'; import WalletType from './views/Onboarding/WalletType'; import NodeChoice from './views/Onboarding/NodeChoice'; import MintDiscovery from './views/Onboarding/MintDiscovery'; import WalletSettings from './views/Onboarding/WalletSettings'; import EditFee from './views/EditFee'; // Embedded LND/LDK import Seed from './views/Settings/Seed'; import SeedRecovery from './views/Settings/SeedRecovery'; import LdkWalletRecoverySettings from './views/Settings/LdkRecovery/LdkWalletRecoverySettings'; import LdkRecoveryVssServer from './views/Settings/LdkRecovery/LdkRecoveryVssServer'; import SeedQRExport from './views/Settings/SeedQRExport'; import Sync from './views/Sync'; import SyncRecovery from './views/SyncRecovery'; import LspExplanationFees from './views/Explanations/LspExplanationFees'; import LspExplanationRouting from './views/Explanations/LspExplanationRouting'; import LspExplanationWrappedInvoices from './views/Explanations/LspExplanationWrappedInvoices'; import LspExplanationOverview from './views/Explanations/LspExplanationOverview'; import RestoreChannelBackups from './views/Settings/EmbeddedNode/RestoreChannelBackups'; // LSP import LSPServicesList from './views/Settings/LSPServicesList'; // LSPS1 import LSPS1 from './views/LSPS1/index'; import LSPS1Settings from './views/LSPS1/Settings'; import OrdersPane from './views/LSPS1/OrdersPane'; import LSPS1Order from './views/LSPS1/Order'; import LSPPaymentAwait from './views/LSPS/LSPPaymentAwait'; // LSPS7 import LSPS7 from './views/LSPS7/index'; import LSPS7Order from './views/LSPS7/Order'; // Cashu Ecash import EcashSettings from './views/Settings/EcashSettings'; import ReceiveEcash from './views/Cashu/ReceiveEcash'; import CashuInvoice from './views/Cashu/CashuInvoice'; import CashuPayment from './views/Cashu/CashuPayment'; import CashuPaymentRequest from './views/Cashu/CashuPaymentRequest'; import CashuSendingLightning from './views/Cashu/CashuSendingLightning'; import MultimintPayment from './views/Cashu/MultimintPayment'; import Mint from './views/Cashu/Mint'; import Mints from './views/Cashu/Mints'; import AddMint from './views/Cashu/AddMint'; import CashuToken from './views/Cashu/CashuToken'; import SendEcash from './views/Cashu/SendEcash'; import UnspentTokens from './views/Cashu/UnspentTokens'; import CashuSeed from './views/Cashu/CashuSeed'; import CashuLockSettings from './views/Cashu/CashuLockSettings'; import LegacySeedRecovery from './views/Cashu/LegacySeedRecovery'; import RecoverMintQuote from './views/Cashu/RecoverMintQuote'; // Cashu Lightning address import CreateCashuLightningAddress from './views/Cashu/LightningAddress/CreateCashuLightningAddress'; import CashuLightningAddressInfo from './views/Cashu/LightningAddress/LightningAddressInfo'; import CashuLightningAddressSettings from './views/Cashu/LightningAddress/LightningAddressSettings'; // Chantools import Chantools from './views/Settings/EmbeddedNode/Chantools'; import Sweepremoteclosed from './views/Settings/EmbeddedNode/Chantools/Sweepremoteclosed'; import RawTxHex from './views/RawTxHex'; import AmountKeypad from './views/AmountKeypad'; import CustodialWalletWarning from './views/Settings/CustodialWalletWarning'; import PSBT from './views/PSBT'; import TxHex from './views/TxHex'; import Menu from './views/Menu'; // Tools import Tools from './views/Tools'; import ActivityExport from './views/Tools/ActivityExport'; import BumpFee from './views/Tools/BumpFee'; import CurrencyConverter from './views/Tools/CurrencyConverter'; import DeveloperTools from './views/Tools/DeveloperTools'; import Rebalance from './views/Tools/Rebalance'; import RebalancingChannels from './views/Tools/RebalancingChannels'; import SignVerifyMessage from './views/Tools/SignVerifyMessage'; import Sweep from './views/Tools/Sweep'; import Accounts from './views/Tools/Accounts/Accounts'; import ImportAccount from './views/Tools/Accounts/ImportAccount'; import ImportingAccount from './views/Tools/Accounts/ImportingAccount'; import CashuTools from './views/Tools/CashuTools'; import NostrKeysTools from './views/Tools/NostrKeys'; import NostrMintSync from './views/Tools/NostrKeys/NostrMintSync'; import NodeConfigExportImport from './views/Tools/NodeConfigExportImport'; import Watchtowers from './views/Tools/Watchtowers/WatchtowerList'; import AddWatchtower from './views/Tools/Watchtowers/AddWatchtower'; import WatchtowerDetails from './views/Tools/Watchtowers/WatchtowerDetails'; import ShareIntentProcessing from './views/ShareIntentProcessing'; import WIFSweeper from './views/Tools/WIFSweeper'; import { isLightTheme, themeColor } from './utils/ThemeUtils'; import LinkingUtils from './utils/LinkingUtils'; import CreateWithdrawalRequest from './views/Tools/CreateWithdrawalRequest'; import WithdrawalRequestInfo from './views/WithdrawalRequestInfo'; import RedeemWithdrawalRequest from './views/RedeemWithdrawalRequest'; const Stack = createNativeStackNavigator(); export default class App extends React.PureComponent { private backPressListenerSubscription: NativeEventSubscription; private appStateSubscription: NativeEventSubscription; private navigation: any = null; private static SCREENS_WITH_CUSTOM_BACK_HANDLER = [ 'SendingLightning', 'SendingOnChain', 'CashuSendingLightning', 'IntroSplash', 'NostrContacts' ]; private handleBackPress = (navigation: any) => { const dialogHasBeenClosed = modalStore.closeVisibleModalDialog(); if (dialogHasBeenClosed) { return true; } if (settingsStore.loginRequired()) { BackHandler.exitApp(); return true; } const navigationState = navigation.getState(); const currentRoute = navigationState.routes[navigationState.routes.length - 1]; if (App.SCREENS_WITH_CUSTOM_BACK_HANDLER.includes(currentRoute?.name)) { return false; } if (navigationState.routes.length > 1) { navigation.pop(); return true; } return false; }; componentDidMount() { this.appStateSubscription = AppState.addEventListener( 'change', this.handleAppStateChange ); // Ensure stealth mode is in a valid state (safety check) StealthModeUtils.fixStealthModeIfNeeded(); } componentWillUnmount() { if (this.appStateSubscription) { this.appStateSubscription.remove(); } } handleAppStateChange = async (nextAppState: string) => { if (nextAppState === 'active' && this.navigation) { LinkingUtils.resetShareIntentFlag(); if (Platform.OS === 'android') { setTimeout(() => { LinkingUtils.handleAndroidIntents(this.navigation); }, 100); } } // Sync stealth mode when app goes to background if (nextAppState === 'background') { try { const settings = await settingsStore.getSettings(); if (settings?.privacy?.stealthMode) { const stealthApp = settings.privacy.stealthApp || 'calculator'; await StealthModeUtils.enableStealthMode(stealthApp); } else { // If stealth was toggled off but native state wasn't // synced (e.g. user pressed Home instead of Back), // disable it now const nativeActive = await StealthModeUtils.isStealthModeActive(); if (nativeActive) { await StealthModeUtils.disableStealthMode(); } } } catch (error) { console.error( 'Error applying stealth mode on background:', error ); } } }; render() { return ( {() => ( <> { if (nav != null) { this.navigation = nav; NavigationService.setTopLevelNavigator( // @ts-ignore:next-line nav ); } }} // @ts-ignore:next-line theme={{ ...DarkTheme, colors: { ...DarkTheme.colors, background: themeColor( 'background' ), card: themeColor( 'background' ), notification: themeColor( 'text' ), primary: themeColor( 'highlight' ), text: themeColor( 'text' ) } }} > ({ headerShown: false, animationDuration: Platform.OS === 'android' ? 300 : 350, // Only override animation when explicitly provided - undefined breaks shared element transitions ...(( route.params as any )?.animation != null && { animation: ( route.params as any ).animation }) })} screenListeners={({ navigation }) => ({ focus: () => { this.backPressListenerSubscription?.remove(); this.backPressListenerSubscription = BackHandler.addEventListener( 'hardwareBackPress', () => this.handleBackPress( navigation ) ); }, blur: () => this.backPressListenerSubscription?.remove() })} > )} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} {/* @ts-ignore:next-line */} ); } }