From 87546bc99f5aca1da148b91556d5c61e2329ed58 Mon Sep 17 00:00:00 2001 From: Muhammad-Al-amin Date: Sat, 25 Jul 2026 18:11:29 +0100 Subject: [PATCH 1/4] feat(settings): add network environment status section and hook Create a new `useNetworkEnvironment` hook that parses environment variables to classify network tier, format host URLs, determine vault status, and generate relevant warnings. Add a new Network & Environment section to the settings screen displaying network details, RPC hosts, vault mode, masked contract ID, and environment warnings. Export reusable types and the hook from the new `src/features/settings` module. --- app/(tabs)/settings.tsx | 681 ++++++++++++------ src/features/settings/index.ts | 7 + .../settings/useNetworkEnvironment.ts | 156 ++++ 3 files changed, 643 insertions(+), 201 deletions(-) create mode 100644 src/features/settings/index.ts create mode 100644 src/features/settings/useNetworkEnvironment.ts diff --git a/app/(tabs)/settings.tsx b/app/(tabs)/settings.tsx index f92a9c2..84d6263 100644 --- a/app/(tabs)/settings.tsx +++ b/app/(tabs)/settings.tsx @@ -1,7 +1,32 @@ -import React, { useState } from 'react'; -import { View, Text, StyleSheet, ScrollView, Alert, Switch, TouchableOpacity } from 'react-native'; +import React, { useState, useMemo } from 'react'; +import { + View, + Text, + StyleSheet, + ScrollView, + Alert, + Switch, + TouchableOpacity, +} from 'react-native'; import { useRouter } from 'expo-router'; import Constants from 'expo-constants'; +import { + Shield, + Sun, + Moon, + Monitor, + Users, + KeyRound, + Globe, + Server, + PiggyBank, + Info, + AlertTriangle, + ShieldAlert, + Activity, + ChevronRight, + CheckCircle2, +} from 'lucide-react-native'; import { Button } from '../../src/components/Button'; import { SIZES, RADIUS, ThemeColors } from '../../src/constants/theme'; import { useTheme } from '../../src/hooks/useTheme'; @@ -12,11 +37,9 @@ import { } from '../../src/utils/walletStorageErrors'; import { useAppLockStore } from '../../src/store/appLockStore'; import { ThemeMode } from '../../src/store/appStore'; -import { Moon, Sun, Monitor, Shield, Info } from 'lucide-react-native'; -import { Moon, Sun, Monitor, Shield, Info, Globe } from 'lucide-react-native';import { WalletResetConfirmModal } from '../../src/components/WalletResetConfirmModal'; -import { Moon, Sun, Monitor, Shield, AlertTriangle, Activity } from 'lucide-react-native'; -import { SecretKeyReveal } from '../../src/components/SecretKeyReveal'; import { WalletResetConfirmModal } from '../../src/components/WalletResetConfirmModal'; +import { SecretKeyReveal } from '../../src/components/SecretKeyReveal'; +import { useNetworkEnvironment, EnvironmentWarning } from '../../src/features/settings'; const THEME_OPTIONS: { mode: ThemeMode; label: string; Icon: typeof Sun }[] = [ { mode: 'light', label: 'Light', Icon: Sun }, @@ -24,25 +47,29 @@ const THEME_OPTIONS: { mode: ThemeMode; label: string; Icon: typeof Sun }[] = [ { mode: 'system', label: 'System', Icon: Monitor }, ]; +const WARNING_ICON = { + info: Info, + warning: AlertTriangle, + error: ShieldAlert, +} as const; + export default function SettingsScreen() { const router = useRouter(); const { clearWallet, getSecretKey } = useWalletStore(); const { colors, themeMode, setThemeMode } = useTheme(); const { isLockEnabled, enableLock, disableLock, authenticate } = useAppLockStore(); + const env = useNetworkEnvironment(); + const [showSecret, setShowSecret] = useState(false); const [secretKey, setSecretKey] = useState(null); const [showResetModal, setShowResetModal] = useState(false); const [isResetting, setIsResetting] = useState(false); - const styles = createStyles(colors); + const styles = useMemo(() => createStyles(colors), [colors]); - // Read version from Expo manifest, with graceful fallback const appVersion = Constants.expoConfig?.version ?? Constants.nativeAppVersion ?? '1.0.0'; const appName = Constants.expoConfig?.name ?? 'Stellar PocketPay'; - // Read network from environment variable, with a fallback - const activeNetwork = process.env.EXPO_PUBLIC_STELLAR_NETWORK ?? 'TESTNET'; - const handleExportKey = async () => { if (!showSecret) { const secret = await getSecretKey(); @@ -50,10 +77,7 @@ export default function SettingsScreen() { setSecretKey(secret); setShowSecret(true); } else { - Alert.alert( - 'Unable to Access Secret Key', - WALLET_SECRET_ACCESS_MESSAGE - ); + Alert.alert('Unable to Access Secret Key', WALLET_SECRET_ACCESS_MESSAGE); } } else { setShowSecret(false); @@ -61,9 +85,7 @@ export default function SettingsScreen() { } }; - const handleSignOut = () => { - setShowResetModal(true); - }; + const handleSignOut = () => setShowResetModal(true); const handleResetConfirm = async () => { setIsResetting(true); @@ -99,37 +121,32 @@ export default function SettingsScreen() { return ( <> - - {/* Preferences */} + + {/* ── Preferences ────────────────────────────────────────── */} Preferences + - + App Lock Require biometrics or passcode to open - + - - - + - + {THEME_OPTIONS.map(({ mode, label, Icon }) => { const selected = themeMode === mode; return ( @@ -137,9 +154,15 @@ export default function SettingsScreen() { key={mode} style={[styles.themeOption, selected && styles.themeOptionSelected]} onPress={() => setThemeMode(mode)} + activeOpacity={0.7} > - - + + {label} @@ -147,91 +170,175 @@ export default function SettingsScreen() { })} + - {/* Wallet */} + {/* ── Wallet ─────────────────────────────────────────────── */} Wallet + -