RN code push自訂彈框

來源:互聯網
上載者:User

標籤:touch   radius   ble   timer   rip   使用   err   des   ati   

最近在弄react native的code push熱更新問題。開始是用的後台默默更新配置。由於微軟伺服器速度問題,經常遇到使用者一直在下載中問題。而使用者也不知道代碼需要更新才能使用新功能,影響了正常商務程序。而目前公司也無力搭建自己的伺服器和dns設定。所以比較快速的方案就是,前端自訂熱更新彈框,在需要更新代碼的情況下禁止使用者向下操作。

ok,廢話少說,直接上代碼:

這是構建一個彈框,強制文案提示和非強制文案提示彈框。

/** * Created by susie on 2018/9/20. */import React, { Component } from ‘react‘;import {View, Text, StyleSheet, Modal, TouchableOpacity, Image , Dimensions , Alert} from ‘react-native‘import CodePush from "react-native-code-push"import Progress from ‘./CusProgressBar‘;import color from ‘../../styles/theme‘;import {showLoadingImg,hideLoadingImg,px2pt} from ‘../../utils/util‘;import Global from "../../constants/global";let SCREEN_WIDTH = Dimensions.get(‘window‘).width;//寬let SCREEN_HEIGHT = Dimensions.get(‘window‘).height;//高let codePushOptions = {    checkFrequency : CodePush.CheckFrequency.ON_APP_START,    installMode: CodePush.InstallMode.IMMEDIATE} class CodePushModal extends Component {    constructor(props) {        super(props)        this.currProgress = 0.0        this.syncMessage = ‘‘        this.state = {            modalVisible: false, //是否有更新            isMandatory: false, //是否為強制更新            immediateUpdate: false, //是否在更新中            updateInfo: {}        }    }    codePushStatusDidChange(syncStatus) {        if (this.state.immediateUpdate) {            switch(syncStatus) {                case CodePush.SyncStatus.CHECKING_FOR_UPDATE:                    this.syncMessage = ‘Checking for update‘                    break;                case CodePush.SyncStatus.DOWNLOADING_PACKAGE:                    this.syncMessage = ‘Downloading package‘                    break;                case CodePush.SyncStatus.AWAITING_USER_ACTION:                    this.syncMessage = ‘Awaiting user action‘                    break;                case CodePush.SyncStatus.INSTALLING_UPDATE:                    this.syncMessage = ‘Installing update‘                    break;                case CodePush.SyncStatus.UP_TO_DATE:                    this.syncMessage = ‘App up to date.‘                    break;                case CodePush.SyncStatus.UPDATE_IGNORED:                    this.syncMessage = ‘Update cancelled by user‘                    break;                case CodePush.SyncStatus.UPDATE_INSTALLED:                    this.syncMessage = ‘Update installed and will be applied on restart.‘                    break;                case CodePush.SyncStatus.UNKNOWN_ERROR:                    this.syncMessage = ‘An unknown error occurred‘                    //Toast.showError(‘更新出錯,請重啟應用!‘)                    this.setState({modalVisible: false})                    CodePush.allowRestart();                    break;            }        }    }    codePushDownloadDidProgress(progress) {        var self = this;        if(self.state.immediateUpdate){            self.currProgress = parseFloat(progress.receivedBytes / progress.totalBytes).toFixed(2);            if(self.currProgress >= 1) {                self.setState({modalVisible: false})            } else if(self.refs.progressBar) {                self.refs.progressBar.progress = self.currProgress;                self.refs.progressBar.buffer = self.currProgress;            }        }    }     syncImmediate() {        CodePush.checkForUpdate().then((update) => {            Global.isCheckCodePush = false;            hideLoadingImg();            if (!update) {                CodePush.allowRestart();            } else {                this.setState({modalVisible: true, updateInfo: update, isMandatory: update.isMandatory})            }        }).catch(function () {            Global.isCheckCodePush = false;            CodePush.allowRestart();        })    }    componentWillMount() {        Global.isCheckCodePush = true;        showLoadingImg();        CodePush.disallowRestart()        this.syncImmediate()    }    componentDidMount() {        //CodePush.allowRestart()    }    _immediateUpdateNew() {        this.setState({immediateUpdate: true});        let self = this;        var timer = setTimeout(function () {            CodePush.sync(                {                    updateDialog: {},                    installMode: CodePush.InstallMode.IMMEDIATE},                self.codePushStatusDidChange.bind(self),                self.codePushDownloadDidProgress.bind(self)            )            clearTimeout(timer);            CodePush.allowRestart();        },10);    }    render() {        return (            <View style={styles.container}>            <Modal                animationType={"none"}                transparent={true}                onRequestClose={() => {}}                visible={this.state.modalVisible}            >                <View style={styles.modal}>                    <View style={styles.modalContainer}>                        {                            !this.state.immediateUpdate ?                                <View>                                    <View style={styles.modalContent}>                                        <View>                                            <Text style={styles.modalTitle}>頁面升級</Text>                                        </View>                                        <View style={styles.updateDes}>                                            <Text style={styles.updateDesText}>升級內容:</Text>                                            <Text style={styles.updateDesText}>{this.state.updateInfo.description}</Text>                                        </View>                                        <View style={styles.updateTip}>                                            <Text style={styles.updateTipText}>本升級非APP更新,wifi環境下30s內即可完成</Text>                                        </View>                                        {                                            !this.state.isMandatory ?                                                <View style={styles.updateBtns}>                                                    <TouchableOpacity                                                        onPress={() => this.setState({modalVisible: false})}>                                                        <View style={[styles.btnRight,styles.btnLeft]}>                                                            <Text style={{fontSize: 16, color: ‘#989898‘}}>殘忍拒絕</Text>                                                        </View>                                                    </TouchableOpacity>                                                    <TouchableOpacity                                                        style={styles.btnRight}                                                        onPress={() => this._immediateUpdateNew()}                                                    >                                                        <View style={styles.btnRightText}>                                                            <Text style={{fontSize: 16, color: color.theme}}>立即升級</Text>                                                        </View>                                                    </TouchableOpacity>                                                </View> :                                                <View style={styles.updateBtns}>                                                    <TouchableOpacity                                                        style={[styles.btnRight,styles.onlyBtn]}                                                        onPress={() => this._immediateUpdateNew()}                                                    >                                                        <View style={[styles.btnRightText,{marginHorizontal: 40}]}>                                                            <Text style={{fontSize: 16, color: color.theme, letterSpacing:1}}>立即升級</Text>                                                        </View>                                                    </TouchableOpacity>                                                </View>                                        }                                    </View>                                </View> : <View style={styles.modalContent}>                                        <View>                                            <Text style={styles.modalTitle}>頁面升級中</Text>                                        </View>                                        <View style={{ paddingVertical: 20, alignItems: ‘center‘}}>                                            <Progress                                                ref="progressBar"                                                progressColor={‘#89C0FF‘}                                                style={{                                                    marginTop: 20,                                                    width: SCREEN_WIDTH - 80,                                                    marginLeft:10,                                                    marginRight:10                                                }}                                            />                                            <View style={styles.updateTip}>                                                <Text style={styles.updateTipText}>本升級非APP更新,wifi環境下30s內即可完成</Text>                                            </View>                                        </View>                                </View>                        }                    </View>                </View>            </Modal>            </View>        );    }}let modalW = SCREEN_WIDTH - 40;const styles = StyleSheet.create({    container: {        flex: 1,        justifyContent: ‘center‘,        alignItems: ‘center‘    },    modal: {        height: SCREEN_HEIGHT,        width: SCREEN_WIDTH,        alignItems: ‘center‘,        justifyContent: ‘center‘,        backgroundColor: ‘rgba(0,0,0,0.3)‘    },    modalContainer: {        marginHorizontal: px2pt(120),        borderBottomLeftRadius: px2pt(20),        borderBottomRightRadius: px2pt(20),    },    modalContent:{        backgroundColor: ‘#FFF‘,        borderRadius:5,        width: modalW    },    modalTitle:{        marginTop:px2pt(70),        fontSize:px2pt(36),        color:color.gray3,        textAlign:‘center‘,        width:‘100%‘    },    modalTips:{        fontSize:px2pt(28),        color:color.darkOrange,        textAlign:‘center‘,        marginBottom:px2pt(10)    },    updateDes:{        marginLeft:px2pt(40),        marginRight:px2pt(40),        marginTop:px2pt(30)    },    updateDesText:{        fontSize:px2pt(32),        color: color.gray6,        lineHeight:px2pt(44)    },    updateTip:{        alignItems: ‘center‘,        marginTop: px2pt(40)    },    updateTipText:{        fontSize: px2pt(28),        color: color.gray6    },    updateBtns:{        flexDirection: ‘row‘,        height: px2pt(100),        alignItems: ‘center‘,        marginTop: px2pt(40),        borderTopColor: ‘#E6E6E6‘,        borderTopWidth: 1    },    btnLeft:{        borderRightColor: ‘#E6E6E6‘,        borderRightWidth: 1    },    btnRight:{        flexDirection: ‘row‘,        alignItems: ‘center‘,        width: modalW / 2,        height:px2pt(100),        justifyContent: ‘center‘    },    btnRightText:{        flex: 1,        height:px2pt(80),        alignItems: ‘center‘,        justifyContent: ‘center‘    },    onlyBtn:{        width: modalW    }})export default CodePush(codePushOptions)(CodePushModal)

  其中,注意installMode 的設定問題,在初始化CodePush參數時,就要設定。否則在非強制更新下會出現 不立即重新整理的問題。

然後是進度條展示處理:

/** * Created by susie on 2018/9/20. */import React, {Component}from ‘react‘import {View, StyleSheet, Animated, Easing,Text}from ‘react-native‘import LinearGradient from ‘react-native-linear-gradient‘import PropTypes from ‘prop-types‘export default class CusProgressBar extends Component {    static propTypes = {        ...View.propTypes,        // 當前進度        progress: PropTypes.number,        // second progress進度        buffer: PropTypes.number,        // 進度條顏色        progressColor: PropTypes.string,        // 進度動畫時間長度        progressAniDuration: PropTypes.number,        // buffer動畫時間長度        bufferAniDuration: PropTypes.number    }    static defaultProps = {        // 進度條顏色        progressColor: ‘white‘,        // 進度條動畫時間長度        progressAniDuration: 100,        // buffer進度條動畫時間長度        bufferAniDuration: 100    }    constructor(props) {        super(props)        this._progressAni = new Animated.Value(0)        this._bufferAni = new Animated.Value(0)    }    componentWillReceiveProps(nextProps) {        this._progress = nextProps.progress        this._buffer = nextProps.buffer    }    componentWillMount() {        this._progress = this.props.progress        this._buffer = this.props.buffer    }    render() {        return (            <View                style={[styles.container,this.props.style]}                onLayout={this._onLayout.bind(this)}>                <LinearGradient colors={[‘#daddff‘, ‘#d3eeff‘]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={{position:‘absolute‘,borderRadius:10,width:‘100%‘,height:‘100%‘}}></LinearGradient>                <Animated.View                    ref="progress"                    style={{                        position:‘absolute‘,                        width: this._progressAni,                        borderRadius:10                    }}>                    <LinearGradient colors={[‘#4669ff‘, ‘#3eefff‘]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={{borderRadius:10,width:‘100%‘,height:‘100%‘}}></LinearGradient>                </Animated.View>                <Animated.Image                    ref="buffer"                    style={{                        position:‘absolute‘,                        left: this._bufferAni,                        marginLeft:0,                        top : -3,                        width:35                    }}  source={require(‘../../styles/images/huojian.png‘)}  />            </View>        )    }    _onLayout({nativeEvent: {layout:{width, height}}}) {        // 防止多次調用,當第一次擷取後,後面就不再去擷取了        if (width > 0 && this.totalWidth !== width) {            // 擷取progress控制項引用            let progress = this._getProgress()            // 擷取buffer控制項引用            let buffer = this._getBuffer()            // 擷取父布局寬度            this.totalWidth = width            //給progress控制項設定高度            progress.setNativeProps({                style: {                    height: height                }            })            // 給buffer控制項設定高度            buffer.setNativeProps({                style: {                    height: height+6                }            })        }    }    _startAniProgress(progress) {        if (this._progress >= 0 && this.totalWidth !== 0) {            Animated.timing(this._progressAni, {                toValue: progress * this.totalWidth,                duration: this.props.progressAniDuration,                easing: Easing.linear            }).start()        }    }    _startAniBuffer(buffer) {        if (this._buffer >= 0 && this.totalWidth !== 0) {            Animated.timing(this._bufferAni, {                toValue: buffer * this.totalWidth,                duration: this.props.bufferAniDuration,            }).start()        }    }    _getProgress() {        if (typeof this.refs.progress.refs.node !== ‘undefined‘) {            return this.refs.progress.refs.node        }        return this.refs.progress._component    }    _getBuffer() {        if (typeof this.refs.buffer.refs.node !== ‘undefined‘) {            return this.refs.buffer.refs.node;        }        return this.refs.buffer._component;    }}Object.defineProperty(CusProgressBar.prototype, ‘progress‘, {    set(value){        if (value >= 0 && this._progress !== value) {            this._progress = value;            this._startAniProgress(value);        }    },    get() {        return this._progress;    },    enumerable: true,})Object.defineProperty(CusProgressBar.prototype, ‘buffer‘, {    set(value){        if (value >= 0 && this._buffer !== value) {            this._buffer = value;            this._startAniBuffer(value);        }    },    get() {        return this._buffer;    },    enumerable: true,})const styles = StyleSheet.create({    container: {        height: 12    }})

 以上就完成了自訂 code push彈框的自訂展示。

 

RN code push自訂彈框

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.