Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hooks 组件件 push一个新的webview返回旧的webview,旧webview invoke定义的原生方法丢失 #40

Open
zhaozedong opened this issue Jan 18, 2021 · 0 comments

Comments

@zhaozedong
Copy link

import { StackHeaderOptions } from '@react-navigation/stack/lib/typescript/src/types';
import React, { useCallback, useContext, useEffect, useRef } from 'react';
import {
View,
Platform,
StatusBar,
Keyboard,
BackHandler,
KeyboardEvent,
NativeModules,
StatusBarStyle,
AppState,
AppStateStatus
}
from 'react-native';
import { _openCamera, _openPicker } from '../../moudles/tokenPhoto';
import WebView from 'react-native-webview';
import createInvoke, { IMessager } from 'react-native-webview-invoke/native';
import { _testwebviewUrl } from '../../config/url';
import askPermission from '../../moudles/AskPermission';
import { getLocation } from '../../moudles/Location';
import JPush from 'jpush-react-native';
import styles from './indexstyle';
import { StoreContext } from '../../store';
import LoadError from '../../components/LoadErr';
import { useFocusEffect, useIsFocused } from '@react-navigation/native';

let statusBarHeight: number | undefined = 20;

const _PLATFROM = Platform.OS;

if (_PLATFROM === 'ios') {
NativeModules.StatusBarManager.getHeight((s:any) => {
statusBarHeight = s.height;
});
}
else statusBarHeight = StatusBar.currentHeight;

function Home(props:any) {

const webviewRef = useRef<WebView<{}>>(null);
const Invoke: IMessager = createInvoke(()=>webviewRef.current); // 创建注入原生方法的实列
const { state } = useContext(StoreContext);
const isFocused = useIsFocused();

const _keyboardDidShow:(e:KeyboardEvent)=>void = (e) => {  // 键盘弹起
    const js = ` window.keyboardDidShow && window.keyboardDidShow(${ e.endCoordinates.height })`;
    webviewRef.current && webviewRef.current.injectJavaScript(js);
};
const _keyboardDidHide:()=>void = () => {  // 键盘收起
    const js = 'window.keyboardDidHide && window.keyboardDidHide()';
    webviewRef.current && webviewRef.current.injectJavaScript(js);
};
const _onBackHander:()=>boolean = ()=>{  // 物理返回键
    const js = 'window.onBackHander && window.onBackHander()';
    webviewRef.current && webviewRef.current.injectJavaScript(js);
    return true;
}
const _onAppState:(nextAppState:AppStateStatus)=>void = (nextAppState)=>{  //App前后台切换状态
    const currAppState = AppState.currentState;
    const js = `window.onAppState && window.onAppState(${currAppState},${nextAppState})`;
    webviewRef.current && webviewRef.current.injectJavaScript(js);
}
const _push = (url:string, data?:{[key:string]:any},headerOptions?:StackHeaderOptions):void=>{ // 打开一个新的webview
    console.log(99999)
   props.navigation.push('Home',{
       url,
       ...data,
       headerOptions
   })
};
const _pop = ()=>{ // 返回上一个路由栈
    props.navigation.goBack();
}
const _setBarStyle = (color:StatusBarStyle)=>{  // 设置状态栏字体颜色
    if(_PLATFROM == 'ios') NativeModules.Tools.setBarStyle(color);
    else StatusBar.setBarStyle(color);
}
const _getStatusBarHeight:()=>number | undefined = ()=>{  // 获取状态栏高度
    return statusBarHeight
};
const _exitApp:()=>void = ()=>{  // 退出app
    if(_PLATFROM == 'android') BackHandler.exitApp();
}
const _reload:()=>void = ()=>{  // 重新加载
    webviewRef.current?.reload();
}

useEffect(()=>{ //   定义注入webview的原生方法
    //  打开一个新的webview 
    Invoke.define('push',_push);
    //  回退路由栈
    Invoke.define('pop',_pop)  
    //  设置状态栏样式'default' | 'light-content' | 'dark-content';
    Invoke.define('setBarStyle', _setBarStyle);
    //  获取状态栏高度
    Invoke.define('getStatusBarHeight', _getStatusBarHeight);
    //  android  请求权限询问
    Invoke.define('askPermission', askPermission);

    // 选择相册
    Invoke.define('openPicker', _openPicker);
    // 拍照
    Invoke.define('openCamera', _openCamera);

    // 退出App
    Invoke.define('exitApp', _exitApp);
    // 重载
    Invoke.define('reload', _reload);
    // 定位
    Invoke.define('getLocation', getLocation);
 

},[]);

useEffect(()=>{  // 监听 (键盘 | 物理返回 | AppState | 推送监听)

    const keyboardDidShow = Keyboard.addListener("keyboardDidShow", _keyboardDidShow);
    const keyboardDidHide = Keyboard.addListener("keyboardDidHide", _keyboardDidHide);

    const backHander = BackHandler.addEventListener('hardwareBackPress', _onBackHander);

    AppState.addEventListener('change', _onAppState);

    JPush.addNotificationListener(res => {
        let {url} = res.extras || {url: null},
          type = res.notificationEventType;
        if (type == 'notificationOpened' && url) {
          let json = JSON.stringify({url: url});
          const js = ` window.recievedPushMessage && window.recievedPushMessage(${json})`;
          webviewRef.current?.injectJavaScript(js);
        }
    });

    return () => {
        keyboardDidShow.remove();
        keyboardDidHide.remove();

        backHander.remove();

        AppState.removeEventListener('change', _onAppState);
        JPush.removeListener(()=>{});
    };
},[]);
useFocusEffect(useCallback(()=>{
    if(!isFocused){
        const js = ` window.screenIsFocused && window.screenIsFocused()`;
        webviewRef.current?.injectJavaScript(js);
    }
    
},[isFocused]))
let _webviewUrl: string = state?.webviewUrl || ''
_webviewUrl = _testwebviewUrl;
return(
    <View
        style={ styles.container }
    >
        { _PLATFROM == 'android' ?  <StatusBar  translucent={true} backgroundColor={'rgba(255,255,255,0)'} /> : null }
        <WebView
            ref={ webviewRef }
            style={{flex: 1}}
            sharedCookiesEnabled={true}
            useSharedProcessPool={true}
            source={{uri: props.route.params?.url || _webviewUrl }}  
            onLoadEnd={() => {}}
            mixedContentMode={'always'} // compatibility
            startInLoadingState={true}
            textZoom={100}
            allowsInlineMediaPlayback={true}
            scrollEnabled={ props.route.params?.scrollEnabled || false }
            onMessage={ Invoke.listener }
            renderError={()=>(
                <LoadError setBarStyle={ _setBarStyle } reload={ _reload }/>
            )}
        />   
    </View>
    
)

}

export default Home;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant