Update react native app with code push - react-native

I'm trying to update my app with code-push. I have next code-push options in my index file:
let codePushOptions = {
checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
installMode: codePush.InstallMode.ON_NEXT_RESUME,
minimumBackgroundDuration: 60 * 5
};
MainApp = codePush(codePushOptions)(Item);
export default MainApp;
Thus, on every app resume it will be checked if there is an update, but the update will be installed on next app resume.
But I want to show a button on a home screen to the users that the update is available if it is available, that they can install it manually on button click.
The problem is that the button is shown on main screen and they can see it if the update is still downloading in the background and if they click during the downloading process nothing happens. Only when the update is downloaded then the click on the button will install it. I try to AVOID that the button is show during downloading update.
I want to show the button only if the update is downloaded completely.
I check if the update is available in componentDidMount as follows:
checkForNewUpdate(){
let self = this;
codePush.checkForUpdate().then(update => {
if (!update) {
codePush.getUpdateMetadata(codePush.UpdateState.PENDING).then((data) => {
if (data) {
self.setState({updateAvailable: true, checkingForUpdate: false})
}else{
self.setState({updateAvailable: false, checkingForUpdate: false})
}
});
}else{
self.setState({updateAvailable: true, checkingForUpdate: false})
}
})
}
And I show button depending on the state as follows:
if(this.state.checkingForUpdate){
return (
<View style={{paddingTop: 10, paddingBottom: 10, alignItems: 'center'}}>
<Text style={{color: s.success, fontSize: 12}}>{gettext("Checking for update...")}</Text>
</View>
)
}
if (this.state.updateAvailable){
return (
<View style={{flexDirection: "row", alignItems: "center", justifyContent: "center", padding: 5, backgroundColor: s.success}}>
<Text style={styles.updateText}>{gettext("Update available")}</Text>
<TouchableHighlight style={styles.updateButton} underlayColor={"transparent"} onPress={this.handleUpdate.bind(this)}>
<Text style={styles.updateButtonText}>{gettext("Click to install")}</Text>
</TouchableHighlight>
</View>
)
}
Any idea how to solve it?

Related

Disable back button while opening Paypal webview in React Native App

I have a Webview from react-native-webview which open to Paypal's payment url. This is my code :
const PaypalWebview = ({ route }) => {
const url = route?.params.url ?? '';
const { setCartPaymentSuccess } = cart.actions;
const dispatch = useDispatch();
const insets = useSafeAreaInsets();
const cancel = () => {
goBack();
BottomMsgService.showMessage("Payment canceled")
}
const handleUrlChange = ({ url }) => {
console.log(url);
if (url.includes('finish')) {
dispatch(setCartPaymentSuccess());
navigate('ResultScreen');
return false
}
else return true
}
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<View style={{ width: '100%', height: insets.top / 1.5, }}></View>
<View style={{
flexDirection: 'row', width: '100%', height: 60, alignItems: 'center'
}}>
<Pressable hitSlop={8} onPress={cancel}>
<Icon type="antdesign" name="close" size={14} color={'black'}
style={{ marginLeft: 20 }}
/>
</Pressable>
</View>
<WebView
style={{ flexGrow: 1, flexBasis: 1 }}
//onNavigationStateChange={handleUrlChange}
onShouldStartLoadWithRequest={handleUrlChange}
source={{ uri: url }}
/>
</View>
)
}
You can see I have a back button which go back to previous screen if user want to cancel payment. What I want to achieve is when user press "Continue" button in the webview (to proceed payment), the back button will be disabled (prevent user going back while payment is processing, image below ).I don't know if Paypal button can send any event to my app so the app can listen the event and make the back button disable. Anyone can give me some solutions? Thanks.
"Continue" does not confirm the payment, there is supposed to be an order review step before capture. If you intend to capture immediately on return you should correct your integration to make the PayPal button's verbiage say "Pay Now". This correction is much more important than worrying about the back button, which should be able to stay as it is and function normally (there's no trigger to change it anyway other than the return URI itself loading, which might then be able to disable the back button initially if you actually needed it to)
If using the v2/checkout/orders API, the parameter to set in the order creation request body is application_context.user_action to PAY_NOW; other integration methods/APIs will have an equivalent parameter.

How to display a button at the bottom of a Webview in react-native?

Inside my component (PrivacyPolicy.js), i have a header view, a webview, and a footer view. the webview, depending on the size, gets scrollable. my issue is that the footer view is displayed at the bottom of the screen like if its style was "position: 'absolute'" so it keeps displayed while scrolling. I need to have it after all webview is displayed.
<View style={styles.main_container}>
<View style={styles.header_container}>
...
</View>
<WebView originWhitelist={['*']} source={{ html: privacyPolicyContent }}/>
<View style={styles.footer_container}>
<CheckBox
disabled={false}
value={this.state.isChecked}
onValueChange={(newValue) => this.setState({
isChecked: newValue
})}
style={styles.checkbox}
tintColors={{ true: '#157dfa' }}
/>
<Text style={styles.checkbox_text}>I have read and accept the Privacy Polic</Text>
</View>
</View>
My styles:
const styles = StyleSheet.create({
main_container: {
flex: 1,
paddingHorizontal:'5%'
},
header_container: {
height: scale(90),
flexDirection: 'row',
marginLeft: 10
},
checkbox_container: {
flexDirection: 'row'
},
checkbox: {
marginLeft: -5,
},
checkbox_text: {
marginTop: 8,
fontSize: 10
}
})
I can see few suggestions:
Since your button is a React Native Button => You can show/hide based on the scrollY positions. For that, you need to communicate over the Bridge to dispatch an event accordingly.
As an alternative solution => You can create the button on the Webview its self to have the same functionality.

Android: React Native Overlap TouchableOpacity and View behave differently when there is backgroundColor style

I created 2 Views that display overlaps to each others. The top and the bottom
When the bottom view background wasn't configured. It responded to the press event correctly. Let's say when I press on the overlap zone, it showed that the bottom one had been pressed
However, when I configured the bottom view backgroundColor. When I pressed on the overlap zone, on Android, it responded as I pressed on the top view which I think it's incorrect. (iOS it responded correctly that the bottom was pressed)
Steps To Reproduce
Provide a detailed list of steps that reproduce the issue.
Here is an example component
const OverlapseTouchExample = ({backgroundColor}) => {
const [pressedBox, setPressefBox] = React.useState('')
return (
<View>
<Text>{pressedBox} pressed</Text>
<TouchableOpacity style={[styles.box, {backgroundColor: 'blue'}]} onPress={() => setPressefBox('top')} />
<View style={backgroundColor ? { backgroundColor: 'orange' } : null}>
<View style={{marginTop: -75}}>
<TouchableOpacity style={[styles.boxBottom, backgroundColor ? { backgroundColor: 'green '} : null]} onPress={() => setPressefBox('bottom')} />
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
box: {
width: 150,
height: 150,
borderWidth: 1,
},
boxBottom: {
width: 120,
height: 200,
borderWidth: 1,
}
})
The problem found when set the backgroundColor to true
<OverlapseTouchExample backgroundColor={true} />
You could see it in Snack https://snack.expo.io/#gie3d/9b6c32 (Android)

How to show loading icon in react native until the API response in react native?

I am creating a new app. After tapping the submit button I want to show the loading icon in the login page until the API response. Please help me
First create a state variable for showing and hiding loader as follows
this.state = {
..
loading: false,
..
};
In the api call before the request send, you can set loading state to true and after completing the response set it to false
getData() {
this.setState({loading:true});// For showing loader
axios.get('api_link_goes_here')
.then(response => {
this.setState({loading:false});// For hiding loader
console.log(response.data);
})
.catch(error => {
this.setState({loading:false});// For hiding loader
console.log(error);
});
}
In your render template, you can add a View for showing the loader based on the state, You can add it to the bottom and position and make it full screen to avoid further clicks until response is received
render() {
return (
<View style={container}>
.....
{this.state.loading === true &&
<View style={styles.myloader}>
<CustomLoader /> // You can define this in another component or simply write <Text>Please wait...</Text>
</View>
}
....
</View>
)}
Style is given below for loader container
const styles = StyleSheet.create({
.....
myloader: {
position: "absolute",
top: 0,
left: 0,
zIndex: 10,
backgroundColor: "#ffffff",
opacity: 0.9,
justifyContent: 'center',
alignItems: 'center',
width: "100%",
height: "100%"
}
...
});

Setting initial offset value is not working

I'm using react-native-simple-modal for displaying models in android devices. Here the model always opens at the center of the screen. Setting the initial offset value in constructor has no effect. However moveUp function is working well. How to show the model at the top of the screen initially? Moreover I need to put the model just below a component.
CODE:
constructor(props) {
super(props);
this.state = {
open: false,
offset: -200,
};
}
moveUp = () => this.setState({offset: -200})
openModal = () => this.setState({open: true})
closeModal = () => this.setState({open: false})
render() {
return (
<View style={{flex: 1, justifyContent: 'flex-start', alignItems: 'center'}}>
<TouchableOpacity onPress={this.openModal}>
<Text>Open modal</Text>
</TouchableOpacity>
<Modal
offset={this.state.offset}
open={this.state.open}
modalDidOpen={this.modalDidOpen}
modalDidClose={this.modalDidClose}>
<View style={{alignItems: 'center'}}>
<Text style={{fontSize: 20, marginBottom: 10}}>Hello world!</Text>
<TouchableOpacity
onPress={this.moveUp}>
<Text>Move modal up</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.resetPosition}>
<Text>Reset modal position</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.closeModal}>
<Text>Close modal</Text>
</TouchableOpacity>
</View>
</Modal>
</View>
)
};
Currently there is no option to align your modal according to your offset in a initial stage. I just went through the internal code of react-native-simple-modal and found out that on the first time this doesn't understand the offset sent through the props. If you want this to be implemented then you can ask the author of this module to update the following code or you can just merge a PR on this module.
Inside the main index.js file of react-native-simple-modal you can see that the default state offset is being set as 0 instead of understanding it through the offset sent from props. So change the below line as:-
state = {
opacity: new Animated.Value(0),
scale: new Animated.Value(0.8),
offset: new Animated.Value(0)
};
to the code below:-
state = {
opacity: new Animated.Value(0),
scale: new Animated.Value(0.8),
offset: new Animated.Value(this.props.offset) ===>> update this initial value.
};
This offset works fine after the initial phase because the author of the module has understood the props offset in the componentWillReceiveProps lifecycle hook of the component. So just ask the author to update this or you can just raise the PR for this. I have checked this by updating the value in node_modules and if you just want to check if its working according to your requirement then you can also update it once and check that out.
I hope this will help you and still if you have any problem then let me know.