How to catch the purchaseCancelledError from RevenueCat in Flutter - flutter

I have a loading spinner that I would like to turn off if the user cancels the purchase using RevenueCat inside of flutter.
I have a try catch block that I use to make the purchase but the error block is never initiated because the try block is always successful.
Here is the code:
purchase(BuildContext ctx, PaymentPlanType selectedPlanType) async {
final offerings = await PurchaseApi.fetchOffers();
try {
if (selectedPlanType == PaymentPlanType.weekly) {
await PurchaseApi.purchasePackage(offerings[0].availablePackages[0]);
} else if (selectedPlanType == PaymentPlanType.monthly) {
await PurchaseApi.purchasePackage(offerings[0].availablePackages[1]);
} else if (selectedPlanType == PaymentPlanType.yearly) {
await PurchaseApi.purchasePackage(offerings[0].availablePackages[2]);
}
} on PlatformException catch (e) {
var errorCode = PurchasesErrorHelper.getErrorCode(e);
if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
showDialog(
context: ctx,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text(e.toString()),
actions: [
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text('OK'))
],
);
});
}
}
}
How do I just catch that error so I can change an isLoading bool to false?

Related

Stop CircularProgressIndicator when error occurs

I built a login page using firebase. When the user clicks the login button, a CircularProgressIndicator is started and if the user gave the correct credentials everything works perfectly but if there is an error (e.g user not found OR wrong password) the user will be not forwarded to the next page but the CircularProgressIndicator will not stop showing.
The aim is, that if there is an error, I want to stop the CircularProgressIndicator and want to show an error message but I don't know how to stop the CircularProgressIndicator.
My code looks the following:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
final navigatorKey = GlobalKey<NavigatorState>();
class LoginUser {
Future loginUser(userEmail, userPassword, context) async {
navigatorKey: navigatorKey;
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => Center(child: CircularProgressIndicator())
);
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: userEmail,
password: userPassword
);
// Close Dialog when route changes
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
return "ec-unf";
} else if (e.code == 'wrong-password') {
return "ec-wp";
}
navigatorKey.currentState!.popUntil((route) => route.isFirst);
}
}
}
Does anybody know how to do this?
Thanks!
Chris
maybe you can add isLoading and finaly condition after try catch
isLoading = true
try {
//your code
print("done !");
isLoading
} catch (err) {
print("error");
isLoading = false
} finally {
print("Finish "); //error and success
isLoading = false
}
Just for completeness, here is how i solved it.
I created a separate function in the login file and when i clicked the Sign in buttton, the following function was executed:
Future login() async{
isSignInLoading = true; // START LOADING CYCLE
// --- LOADING CYCLE - START ---
if (isSignInLoading == true) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => Center(child: CircularProgressIndicator())
);
}
// --- LOADING CYCLE - END ---
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _controllerEmail.text,
password: _controllerPassword.text
);
} catch (e) {
isSignInLoading = false; // START LOADING CYCLE
isErrorLogin = true; // START LOADING CYCLE
}
Navigator.of(context).pop();
// --- ERROR MESSAGE - START ---
if (isErrorLogin == true) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => Center(child:
AlertDialog(
title: const Text('Something went wrong!'),
content: const Text('Please check your entries, either the user does not exist or the password is incorrect.'),
actions: [
TextButton(
child: const Text(
'Close',
style: TextStyle(
color: Color(0xff004494),
fontWeight: FontWeight.w500
),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
)
)
);
}
// --- ERROR MESSAGE - END ---
//var loginInfo = await LoginUser().loginUser(_controllerEmail.text,_controllerPassword.text, context);
if (FirebaseAuth.instance.currentUser != null) {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("userLoginStatus", true);
Navigator.popAndPushNamed(context, '/overview');
}
}
Pretty sure there is a way better way to do it but this worked for me.

Can't dimiss showdialog with setstate flutter

I want to verify if the phone number the user enter is in firebase, so I am using a showDialog to show a spinner, I want to dismiss the showdialog if that phone number already exist. I have tried setState to but the showddialog won't dismiss automatically avail
_phoneExist(phone) {
if (loading) {
showDialog(
context: context,
builder: (c) {
return Center(
child: SpinKitChasingDots(
color: Colors.brown,
size: 50.0,
),
);
});
}
firestoreInstance
.collection("partners")
.where("phone", isEqualTo: phone)
.getDocuments()
.then((value) {
value.documents.forEach((result) {
if (result.exists) {
print(result['phone']);
setState(() {
_userExist = true;
loading = false;
});
} else {
print('ghhgghgh');
}
});
});
if (_userExist) {
Scaffold.of(context).showSnackBar(snackBar2('$phone Aleady Exists'));
setState(() {
_userExist = false;
});
} else {
print('gghhgghgchgc');
print(phone);
// _registerUser();
}
}
You can try with the below lines
BuildContext buildContext;
_phoneExist(phone) {
if (loading) {
showDialog(
context: context,
builder: (BuildContext context) {
buildContext = context; // Assign your context to buildcontext
return Center(
child: SpinKitChasingDots(color: Colors.brown,size: 50.0,
),
);
});
}
firestoreInstance
.collection("partners").where("phone", isEqualTo: phone).getDocuments()
.then((value) {
value.documents.forEach((result) {
if (result.exists) {
setState(() {
_userExist = true;
loading = false;
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.pop(buildContext);
}); // By adding this you can close your pop up
});
} else {
}
});
});
if (_userExist) {
Scaffold.of(context).showSnackBar(snackBar2('$phone Aleady Exists'));
setState(() {
_userExist = false;
});
} else {
// _registerUser();
}
}
To hide a dialog you can use:
Navigator.pop(context);
If your app has multiple Navigator objects you can use:
Navigator.of(context, rootNavigator: true).pop();
You can see the docs here: https://api.flutter.dev/flutter/material/showDialog.html

Flutter Modular Mobx - Observable doesn't update inside of onpress

I am new with Flutter and I am having a problem. I'm using mobx. In my view I have a button and inside of this button, I am waiting for the showDialog property to change in order to show the dialog view . However, within onpress the showdialog does not work. Is there any other way to do this?
My controller
#observable
bool showDialog = false;
#action
Future callLoginService() async {
await Future.delayed(Duration(seconds: 6));
showDialog = true;
}
view
Observer(
builder: (_) {
return Center(
child: RaisedButton(
child: Text("TESTE"),
onPressed: () async {
controller.callLoginService();
if (controller.showDialog) {
final action = await InfoDialogView.showAlertDialog(
context, "Try again", 'Invalid user');
if (action == DialogAction.abort) {
controller.showDialog = false;
}
}
},
),
);
},
),
This is because your onPressed method is asynchronous but you haven't used 'await' keyword ahead of controller.callLoginService().
Observer(
builder: (_) {
return Center(
child: RaisedButton(
child: Text("TESTE"),
onPressed: () async {
await controller.callLoginService(); //put await for calling asynchronous methods
if (controller.showDialog) {
final action = await InfoDialogView.showAlertDialog(
context, "Try again", 'Invalid user');
if (action == DialogAction.abort) {
controller.showDialog = false;
}
}
},
),
);
},
),

How to put an if inside an if statement in initState in flutter?

I am trying to put an if statement inside another if inside an insitstate in flutter app as I did it but It did't do what it is supposed to do like if the initstate focused on being a function instead of being an initstate here is my code :
#override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((res) {
print(res);
if (res != null) {
if (userType == 'Student') {
Navigator.pushReplacementNamed(context, '/StudentsPage');
} else if (userType == 'Teacher') {
Navigator.pushReplacementNamed(context, '/TeacherPage');
} else if (userType == 'Admin') {
Navigator.pushReplacementNamed(context, '/AdminPage');
}
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text('Error In Validating Your Account.'),
actions: [
FlatButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
});
}
It is supposed to get the firebase user which it did but It doesn't do auto login when I do restart which it happens by deleting the second if and only doing one Navigation without controlling it, So any Ideas what is the proplem, because I reached a dead end XD.
Where I assign a val to userType 'Which is working as I printed Its val':
void getUserData() async {
try {
firestoreInstance
.collection('Users')
.document(usernameController.text)
.get()
.then((value) {
setState(() {
email = (value.data)['email'];
password = (value.data)['password'];
gender = (value.data)['gender'];
username = (value.data)['username'];
userType = (value.data)['userType'];
});
print('$userType');
});
} catch (e) {
print(e.toString);
}
}

show dialog when there is a problem in the internet network

I mean when I log in, but the network to the database there is a problem, an information dialog will appear that the network has a problem. I'm confused about using else if here..
_login() async {
if (formKey.currentState.validate()) {
formKey.currentState.save();
try {
final response = await UserController.login({
"username": username,
"password": password,
});
if (response != null && response["success"]) {
Http.setAccessToken(response["token"]);
return Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => MainActivity(),
));
} else {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Information"),
content: Text("Your account is not registered!"),
actions: <Widget>[
FlatButton(
child: Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
} catch (e) {
print(e.message);
}
}
}
how do I put conditions if the network has a problem then return showDialog ??
Check out the connectivity package from the Flutter Team. https://pub.dev/packages/connectivity
You can listen for any issues in changes to your network then show a snackbar or dialogbox if disconnected.
I hope this helps.
JC