import { type NavigationProp, type ParamListBase, useNavigation } from "@react-navigation/native"; import { useCallback, useLayoutEffect, useState } from "react"; import { ActivityIndicator, Linking, Pressable, View } from "react-native"; import { WebView } from "react-native-webview"; import { AppText as Text } from "../../../components/AppText"; import { LoadingStrip } from "../../../components/LoadingStrip"; import { SymbolView } from "../../../components/AppSymbol"; import { useThemeColor } from "../../../lib/useThemeColor"; import { isLegalDocumentUrl, LEGAL_URL } from "../lib/legal-document-url"; export function SettingsLegalDocumentCloseHeaderButton() { const navigation = useNavigation(); const iconColor = useThemeColor("--color-icon"); return ( navigation.goBack()} className="p-2 active:opacity-60" > ); } export function SettingsLegalDocumentExternalHeaderButton({ externalUrl = LEGAL_URL, }: { readonly externalUrl?: string; }) { const iconColor = useThemeColor("--color-icon"); const safeExternalUrl = isLegalDocumentUrl(externalUrl) ? externalUrl : LEGAL_URL; return ( void Linking.openURL(safeExternalUrl).catch(() => undefined)} className="p-2 active:opacity-60" > ); } interface SettingsLegalDocumentRouteScreenProps { readonly documentName: string; readonly documentUrl: string; } export function SettingsLegalDocumentRouteScreen({ documentName, documentUrl, }: SettingsLegalDocumentRouteScreenProps) { const navigation = useNavigation>(); const iconColor = useThemeColor("--color-icon"); const [reloadKey, setReloadKey] = useState(0); const [loadProgress, setLoadProgress] = useState(0); const [loadError, setLoadError] = useState(null); const [externalUrl, setExternalUrl] = useState(documentUrl); const renderExternalHeaderButton = useCallback( () => , [externalUrl], ); useLayoutEffect(() => { navigation.setOptions({ headerRight: renderExternalHeaderButton, }); }, [navigation, renderExternalHeaderButton]); const openExternalUrl = useCallback((url: string) => { void Linking.openURL(url).catch(() => undefined); }, []); if (loadError) { return ( Couldn't load the {documentName.toLowerCase()} {loadError} { setLoadError(null); setReloadKey((value) => value + 1); }} className="items-center rounded-xl bg-foreground px-4 py-3 active:opacity-80" > Try Again openExternalUrl(documentUrl)} className="items-center rounded-xl px-4 py-3 active:bg-foreground/5" > Open in Browser ); } return ( {loadProgress > 0 && loadProgress < 1 ? : null} { if (isLegalDocumentUrl(request.url)) return true; openExternalUrl(request.url); return false; }} onLoadProgress={(event) => { setLoadProgress(event.nativeEvent.progress); }} onLoadStart={() => { setLoadProgress(0.05); setLoadError(null); }} onLoadEnd={(event) => { if (isLegalDocumentUrl(event.nativeEvent.url)) { setExternalUrl(event.nativeEvent.url); } setLoadProgress(0); }} onError={(event) => { setLoadProgress(0); setLoadError(event.nativeEvent.description || "The page could not be loaded."); }} onHttpError={(event) => { if (!isLegalDocumentUrl(event.nativeEvent.url)) return; setLoadProgress(0); setLoadError(`The server returned status ${event.nativeEvent.statusCode}.`); }} renderLoading={() => ( )} style={{ flex: 1, backgroundColor: "transparent" }} /> ); }