import { StatusBar } from 'expo-status-bar'; import { useEffect, useMemo, useRef, useState } from 'react'; import { BackHandler, Linking, Platform, StyleSheet, View } from 'react-native'; import type { WebViewMessageEvent } from 'react-native-webview'; import { WebView } from 'react-native-webview'; import { handleMobileHostBridgeMessage, MOBILE_HOST_CAPABILITIES, } from './src/mobileHostBridge'; import { shouldOpenInMobileShellWebView } from './src/mobileShellNavigation'; import { buildMobileShellUrl } from './src/mobileShellUrl'; const defaultWebUrl = 'http://127.0.0.1:3000/'; export default function App() { const webViewRef = useRef(null); const [canGoBack, setCanGoBack] = useState(false); const webUrl = useMemo( () => buildMobileShellUrl( process.env.EXPO_PUBLIC_GENARRATIVE_WEB_URL || defaultWebUrl, { platform: Platform.OS === 'ios' ? 'ios' : 'android', hostVersion: '0.1.0', capabilities: MOBILE_HOST_CAPABILITIES, }, ), [], ); const allowedWebOrigin = useMemo(() => new URL(webUrl).origin, [webUrl]); useEffect(() => { const subscription = BackHandler.addEventListener( 'hardwareBackPress', () => { if (!canGoBack) { return false; } webViewRef.current?.goBack(); return true; }, ); return () => subscription.remove(); }, [canGoBack]); const handleMessage = (event: WebViewMessageEvent) => { void handleMobileHostBridgeMessage(event.nativeEvent.data, (response) => { webViewRef.current?.injectJavaScript( `window.dispatchEvent(new MessageEvent('message', { data: ${JSON.stringify( JSON.stringify(response), )} })); true;`, ); }); }; const handleShouldStartLoad = (request: { url: string }) => { if (shouldOpenInMobileShellWebView(request.url, allowedWebOrigin)) { return true; } void Linking.openURL(request.url).catch(() => undefined); return false; }; return ( setCanGoBack(event.canGoBack)} setSupportMultipleWindows={false} /> ); } const styles = StyleSheet.create({ root: { flex: 1, backgroundColor: '#fffdf9', }, });