import React , { FunctionComponent , useCallback , useEffect , useRef , useState , } from "react" ; import { BackHandler , Platform } from "react-native" ; import WebView , { WebViewMessageEvent } from "react-native-webview" ; import { useStyle } from "../../../../styles" ; import { Keplr } from "@keplr-wallet/provider" ; import { RNMessageRequesterExternal } from "../../../../router" ; import { RNInjectedKeplr } from "../../../../injected/injected-provider" ; import RNFS from "react-native-fs" ; import EventEmitter from "eventemitter3" ; import { PageWithViewInBottomTabView } from "../../../../components/page" ; import { OnScreenWebpageScreenHeader } from "../header" ; import { useIsFocused , useNavigation } from "@react-navigation/native" ; import { WebViewStateContext } from "../context" ; import { URL } from "react-native-url-polyfill" ; import { observer } from "mobx-react-lite" ; import { useStore } from "../../../../stores" ; export const useInjectedSourceCode = ( ) => { const [ code , setCode ] = useState < string | undefined > ( ) ; useEffect ( ( ) => { if ( Platform . OS === "ios" ) { RNFS . readFile ( `${ RNFS . MainBundlePath }/injected-provider.bundle.js` ) . then ( ( r ) => setCode ( r ) ) ; } else { RNFS . readFileAssets ( "injected-provider.bundle.js" ) . then ( ( r ) => setCode ( r ) ) ; } } , [ ] ) ; return code ; } ; export const WebpageScreen = observer ( ( props ) => { const { keyRingStore } = useStore ( ) ; const style = useStyle ( ) ; const webviewRef = useRef < WebView | null > ( null ) ; const [ currentURL , setCurrentURL ] = useState ( ( ) => { if ( props . source && "uri" in props . source ) { return props . source . uri ; } return "" ; } ) ; const [ keplr ] = useState ( ( ) => new Keplr ( "0.0.1" , "core" , new RNMessageRequesterExternal ( ( ) => { if ( ! webviewRef . current ) { throw new Error ( "Webview not initialized yet" ) ; } if ( ! currentURL ) { throw new Error ( "Current URL is empty" ) ; } return { url : currentURL , origin : new URL ( currentURL ) . origin , } ; } ) ) ) ; const [ eventEmitter ] = useState ( ( ) => new EventEmitter ( ) ) ; const onMessage = useCallback ( ( event ) => { eventEmitter . emit ( "message" , event . nativeEvent ) ; } , [ eventEmitter ] ) ; useEffect ( ( ) => { RNInjectedKeplr . startProxy ( keplr , { addMessageListener : ( fn ) => { eventEmitter . addListener ( "message" , fn ) ; } , postMessage : ( message ) => { webviewRef . current ?. injectJavaScript ( `
                window.postMessage(${ JSON . stringify ( message ) }, window.location.origin);
                true; // note: this is required, or you'll sometimes get silent failures
              ` ) ; } , } , RNInjectedKeplr . parseWebviewMessage ) ; } , [ eventEmitter , keplr ] ) ; useEffect ( ( ) => { const keyStoreChangedListener = ( ) => { webviewRef . current ?. injectJavaScript ( `
            window.dispatchEvent(new Event("keplr_keystorechange"));
            true; // note: this is required, or you'll sometimes get silent failures
          ` ) ; } ; keyRingStore . addKeyStoreChangedListener ( keyStoreChangedListener ) ; return ( ) => { keyRingStore . removeKeyStoreChangedListener ( keyStoreChangedListener ) ; } ; } , [ keyRingStore ] ) ; const [ canGoBack , setCanGoBack ] = useState ( false ) ; const [ canGoForward , setCanGoForward ] = useState ( false ) ; const isFocused = useIsFocused ( ) ; useEffect ( ( ) => { const backHandler = ( ) => { if ( ! isFocused || webviewRef . current == null ) { return false ; } if ( ! canGoBack ) { return false ; } webviewRef . current . goBack ( ) ; return true ; } ; if ( isFocused ) { BackHandler . addEventListener ( "hardwareBackPress" , backHandler ) ; } return ( ) => { BackHandler . removeEventListener ( "hardwareBackPress" , backHandler ) ; } ; } , [ canGoBack , isFocused ] ) ; const navigation = useNavigation ( ) ; useEffect ( ( ) => { if ( Platform . OS === "ios" ) { navigation . setOptions ( { gestureEnabled : ! canGoBack , } ) ; } } , [ canGoBack , navigation ] ) ; const sourceCode = useInjectedSourceCode ( ) ; return ( < PageWithViewInBottomTabView style = { style . flatten ( [ "padding-0" ] ) } > < WebViewStateContext . Provider value = { { webView : webviewRef . current , name : props . name , url : currentURL , canGoBack , canGoForward , } } > < OnScreenWebpageScreenHeader /> < /WebViewStateContext.Provider> { sourceCode ? ( < WebView ref = { webviewRef } injectedJavaScriptBeforeContentLoaded = { sourceCode } onMessage = { onMessage } onNavigationStateChange = { ( e ) => { setCanGoBack ( e . canGoBack ) ; setCanGoForward ( e . canGoForward ) ; setCurrentURL ( e . url ) ; } } onLoadProgress = { ( e ) => { setCanGoBack ( e . nativeEvent . canGoBack ) ; setCanGoForward ( e . nativeEvent . canGoForward ) ; setCurrentURL ( e . nativeEvent . url ) ; } } contentInsetAdjustmentBehavior = "never" automaticallyAdjustContentInsets = { false } decelerationRate = "normal" allowsBackForwardNavigationGestures = { true } { ... props } />) : null} < /PageWithViewInBottomTabView>); } ) ; export * from "./screen-options" ;