import { MaterialCommunityIcons } from "@expo/vector-icons"; import { useFocusEffect } from "expo-router"; import { Alert, Linking, Platform, ScrollView, Text, View, } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; import { Children, Fragment, useCallback, useState } from "react"; import { SettingsRow } from "@/components/settings-row"; import { type Lang, type ThemeMode, useSettingsStore, } from "@/lib/settings"; import { useT } from "@/lib/i18n"; import { useLocationPermission } from "@/lib/use-location-permission"; type IconName = React.ComponentProps["name"]; const SectionHeader = ({ title }: { title: string }) => ( {title} ); /** * A grouped settings card. Renders an optional muted description header, then * its children with an automatic divider between each row — so callers never * hand-thread `border-t` wrapper Views. Null/conditional children (and arrays * from `.map`) are flattened by `Children.toArray`, so conditionals like * `status !== "granted" ? : null` and `options.map(...)` both work. */ const SettingsCard = ({ description, children, }: { description?: string; children: React.ReactNode; }) => { const rows = Children.toArray(children); return ( {description ? ( {description} ) : null} {rows.map((row, index) => ( {index > 0 ? ( ) : null} {row} ))} ); }; const Settings = () => { const t = useT(); const mode = useSettingsStore((state) => state.mode); const setMode = useSettingsStore((state) => state.setMode); const lang = useSettingsStore((state) => state.lang); const setLang = useSettingsStore((state) => state.setLang); const keepAwake = useSettingsStore((state) => state.keepAwake); const setKeepAwake = useSettingsStore((state) => state.setKeepAwake); const overlayRequested = useSettingsStore( (state) => state.overlayRequested, ); const setOverlayRequested = useSettingsStore( (state) => state.setOverlayRequested, ); const { status, refresh, openSettings } = useLocationPermission(); useFocusEffect( useCallback(() => { void refresh(); }, [refresh]), ); const [expandedSafety, setExpandedSafety] = useState(null); const locationStatusLabel = status === "granted" ? t("settings.maps.statusGranted") : status === "denied" ? t("settings.maps.statusDenied") : status === "blocked" ? t("settings.maps.statusBlocked") : t("settings.maps.statusUnknown"); const callEmergency = useCallback(async () => { try { await Linking.openURL("tel:112"); } catch { Alert.alert( t("settings.safety.callFailedTitle"), t("settings.safety.callFailedBody"), ); } }, [t]); const chooseLanguage = useCallback( (next: Lang) => { const switchingToOrFromRTL = next === "ar" || lang === "ar"; setLang(next); if (switchingToOrFromRTL) { Alert.alert( t("settings.language.rtlRestartTitle"), t("settings.language.rtlRestartBody"), ); } }, [lang, setLang, t], ); const openOverlaySettings = useCallback(async () => { setOverlayRequested(true); try { await Linking.openSettings(); } catch { // already flagged; nothing more to do } }, [setOverlayRequested]); const appearanceOptions: { mode: ThemeMode; icon: IconName }[] = [ { mode: "light", icon: "white-balance-sunny" }, { mode: "dark", icon: "weather-night" }, { mode: "system", icon: "theme-light-dark" }, ]; const languageOptions: { lang: Lang; icon: IconName }[] = [ { lang: "en", icon: "alpha-e-box" }, { lang: "ar", icon: "alpha-a-box" }, { lang: "fr", icon: "alpha-f-box" }, ]; const safetyTiles: { key: string; icon: IconName; title: string; body: string }[] = [ { key: "proactive", icon: "shield-account", title: t("settings.safety.proactive.title"), body: t("settings.safety.proactive.body"), }, { key: "verification", icon: "account-check", title: t("settings.safety.verification.title"), body: t("settings.safety.verification.body"), }, { key: "privacy", icon: "lock", title: t("settings.safety.privacy.title"), body: t("settings.safety.privacy.body"), }, ]; return ( {t("settings.title")} {/* 1. Maps & Navigation */} {status !== "granted" ? ( ) : null} {/* 2. Appearance */} {appearanceOptions.map((option) => ( setMode(option.mode)} /> ))} {/* 3. Safety */} {safetyTiles.map((tile) => ( setExpandedSafety((current) => current === tile.key ? null : tile.key, ) } /> ))} {/* 4. Language */} {languageOptions.map((option) => ( chooseLanguage(option.lang)} /> ))} {/* 5. General — keep-awake toggle + (Android) display-over-other-apps */} {Platform.OS === "android" ? ( ) : null} ); }; export default Settings;