Snackbar is not showing up and pushes user to the next page - flutter

I added a snackbar for the user which shows up when all fields aren't filled or when the sign up form is partially filled. Instead of displaying the snackbar, it takes the user to the next screen. I am wondering how it is managing to do that and getting past the if/else statement blocks. I'd appreciate if anyone could give tips or showcase what I am doing wrong.
final emailRegistered = signupEmailController.text.trim();
final usernameRegistered = signupNameController.text.trim();
final passwordRegistered = signupPasswordController.text.trim();
final retypePassRegistered = signupConfirmPasswordController.text.trim();
// final user = ParseUser.createUser()
// If form is valid then move forward
if (_formKey.currentState!.validate()) {
final user = ParseUser.createUser(usernameRegistered, passwordRegistered, emailRegistered);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const InterestsPage()),
);
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(content: Text('Processing Data')),);
} else {
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(content: Text('Field is unfilled', style: TextStyle(fontSize: 12),)),);
if (usernameRegistered.isEmpty == true &&
passwordRegistered.isEmpty == true &&
retypePassRegistered.isEmpty == true && emailRegistered.isEmpty == true) {
final materialBanner = MaterialBanner(
/// need to set following properties for best effect of awesome_snackbar_content
elevation: 0,
backgroundColor: Colors.transparent,
forceActionsBelow: true,
content: AwesomeSnackbarContent(
title: 'All fields are empty',
message:
'This is an example error message that will be shown in the body of materialBanner!',
/// change contentType to ContentType.success, ContentType.warning or ContentType.help for variants
contentType: ContentType.success,
// to configure for material banner
inMaterialBanner: true,
),
actions: const [SizedBox.shrink()],
);
ScaffoldMessenger.of(context)
..hideCurrentMaterialBanner()
..showMaterialBanner(materialBanner);
} else if (emailRegistered.isEmpty == true) {
final materialBanner = MaterialBanner(
/// need to set following properties for best effect of awesome_snackbar_content
elevation: 0,
backgroundColor: Colors.transparent,
forceActionsBelow: true,
content: AwesomeSnackbarContent(
title: 'Email is empty!',
message:
'This is an example error message that will be shown in the body of materialBanner!',
/// change contentType to ContentType.success, ContentType.warning or ContentType.help for variants
contentType: ContentType.success,
// to configure for material banner
inMaterialBanner: true,
),
actions: const [SizedBox.shrink()],
);
ScaffoldMessenger.of(context)
..hideCurrentMaterialBanner()
..showMaterialBanner(materialBanner);
} else if (passwordRegistered.isEmpty == true) {
const SnackBar(content: Text('Password is unfilled.'));
} else if (passwordRegistered != retypePassRegistered) {
const SnackBar(content: Text('Passwords do not match.'));
} else if (usernameRegistered.isEmpty == true) {
const SnackBar(content: Text('Username is unfilled'));
}
}

you forgot to call ScaffoldMessenger.of(context).showSnackBar method to create one snack bar variable then after showing snack bar.
For eg:
onPressed:(){
var snackBar;
if(){
//your other stuff
} else if (passwordRegistered.isEmpty == true) {
snackBar = SnackBar(content: Text('Password is unfilled.'));
} else if (passwordRegistered != retypePassRegistered) {
snackBar = SnackBar(content: Text('Passwords do not match.'));
} else if (usernameRegistered.isEmpty == true) {
snackBar = SnackBar(content: Text('Username is unfilled'));
}
ScaffoldMessenger.of(context).showSnackBar(snackBar);//important point
}//completion on pressed

Related

Force routing without context

am working on chat app , now am stuck on the idea of , if one of the two users left the page i wanna force the other user also to leave the page and back to home screen , i tried many things , boolean , conditions , will pop , nothing work , how can i implement a function to do this job , am using flutter , much appreciate .
i tried using boolean to set a condition to check if user exist , i tried to use will pop , i saw a couple of articles bout it , i even tried to set timer to force the second user to leave , but nothing happened , the problem is there's no action from the other user that make him leave the page , with or without on press , while the first user did the action and pressed the button to leave .
this is the button in the home page who do logic to match through firebase
child: ElevatedButton(
onPressed: () async {
var res = await FirebaseFirestore.instance
.doc(
'match/$_currentValue1$_currentValue2$_currentThumbValue')
.get();
var value = res.exists;
print('RESULT = $value');
/// If Code Is Not Exist
try {
if (value == false) {
/// Create Code In Match Document
await FirebaseFirestore.instance
.collection('match')
.doc('$_currentValue1$_currentValue2$_currentThumbValue')
.set({
'user1Id': FirebaseAuth.instance.currentUser!.uid,
'user1Name': userInfo['displayName'] ?? 'username',
'user2Id': '',
'user2Name': '',
});
print('Match Created By ${userInfo['displayName']}');
/// Create Code Reference In Real Time
await codeRef.set({
'code': '$_currentValue1$_currentValue2$_currentThumbValue',
'user1Id': FirebaseAuth.instance.currentUser!.uid,
'user1Name': userInfo['displayName'] ?? 'username',
'user2Id': '',
'user2Name': '',
});
/// Timer To Delete Code If No Match Found
var counter = 10;
Timer.periodic(const Duration(seconds: 1),
(timer) async {
setState(() {
isMatchVisible = false;
});
print(timer.tick);
print('Data Value During Countdown : $value');
counter--;
/// Check If User2 Exist Im Match Document
DocumentSnapshot documentSnapshot =
await FirebaseFirestore.instance
.collection('match')
.doc('$_currentValue1$_currentValue2$_currentThumbValue')
.get();
///
if (documentSnapshot.get('user2Id') != '') {
timer.cancel();
var goToPageUser1 = 2;
Timer.periodic(const Duration(seconds: 2),
(timer) async {
goToPageUser1--;
if (goToPageUser1 == 0) {
timer.cancel();
/// Go To Chat Screen
await Get.toNamed(
'/ChatScreen',
arguments:
'$_currentValue1$_currentValue2$_currentThumbValue',
parameters: {
'name1': userInfo['displayName'],
'Id1': user!.uid,
},
preventDuplicates: false,
);
}
});
} else {
if (counter == 0) {
var failCounter = 5;
Timer.periodic(const Duration(seconds: 1),
(timer) {
setState(() {
showFailResult = true;
});
failCounter--;
if (failCounter == 0) {
timer.cancel();
setState(() {
showFailResult = false;
});
}
});
/// Delete Code From Match Collection
DocumentReference docCode = FirebaseFirestore
.instance
.collection('match')
.doc(
'${_currentValue1.toString()}${_currentValue2.toString()}${_currentThumbValue.toString()}');
await docCode
.delete()
.then((value) =>
print('Match Code Deleted'))
.catchError((error) => print(
"Failed To Delete Match Code: $error"));
/// Delete Room From Real Time
await codeRef.remove();
print('Cancel timer');
timer.cancel();
setState(() {
value = false;
isMatchVisible = true;
print(
'Data Value After Countdown : $value');
});
}
}
});
/// If Code Is Exist
} else if (value == true) {
/// Update Match Document For User1 AND User2
await FirebaseFirestore.instance
.collection('match')
.doc(
'${_currentValue1.toString()}${_currentValue2.toString()}${_currentThumbValue.toString()}',
)
.update({
'user2Id':
FirebaseAuth.instance.currentUser!.uid,
'user2Name':
userInfo['displayName'] ?? 'username',
});
/// Update Match Code In Real Time
await codeRef.update({
'user2Id':
FirebaseAuth.instance.currentUser!.uid,
'user2Name':
userInfo['displayName'] ?? 'username',
});
var goToPageUser2 = 2;
Timer.periodic(const Duration(seconds: 2),
(timer) async {
goToPageUser2--;
if (goToPageUser2 == 0) {
timer.cancel();
/// Go To Chat Screen
await Get.toNamed(
'/ChatScreen',
arguments:
'$_currentValue1$_currentValue2$_currentThumbValue',
parameters: {
'name2': userInfo['displayName'],
'Id2': user!.uid,
},
preventDuplicates: false,
);
}
});
}
} on FirebaseAuthException catch (e) {
showSnackBar(context, e.message!);
}
},
child: SizedBox(
width: 100,
height: 50,
child: Center(
child: Text(
'Match'.tr,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 20),
),
),
),
),

uploading An Image to Database using MultiPartFile in Flutter

I want to upload an image that I have already retrieved from the database(product table) to the cart table.
The issue is, I can't use the .path with the MultipartFile("file", image.path);
I am getting an error if I try using .path with my image variable. I've also tried several methods but none is working... I'll attach my codes below
The image is already stored in a map(revievedMap) which I receivr from the previous screen so I'm not using an imagePicker, the product image I'm trying to access is already stored in the database.
request.fields['image'] = "http://10.0.2.2:/shopice/assets/${args.product.image}";
request.fields['image'] = "http://localhost:/shopice/assets/${args.product.image}";
I tried the code above, obviously didn't work.
var pic = await http.MultipartFile.fromPath("image", args.product.image!);
//request.files.add(pic);
I also tried this, but I need to set the path on the second argument, but args.product.image.path(), is returning this error
[the getter 'path' isn't defined for the type 'String'. (Documentation) Try importing the library that defines 'path', correcting the name to the name of an existing getter, or defining a getter or field named 'path'.]
here is the code:
//args.receivedMap: is my buyer detials
//args.product: is the product i'm trying to add to cart, which //contains the image
args.seller: is the seller details
child: FlatButton(
onPressed: ()async {
if(!args.receivedMap.isEmpty){
final uri = Uri.parse("http://10.0.2.2:/shopice/api/buyer/addToCart");
var request = http.MultipartRequest('POST', uri);
request.fields['buyer_id'] =args.receivedMap['id'];
request.fields['seller_id'] = args.seller.id.toString();
request.fields['seller_name'] = args.seller.name!;
request.fields['buyer_name'] = args.receivedMap['name'];
request.fields['price'] = args.product.pricePerKg!;
request.fields['product_name'] = args.product.name!;
//request.fields['image'] = "http://10.0.2.2:/shopice/assets/${args.product.image}";
//var pic = await http.MultipartFile.fromPath("image", "http://localhost:/shopice/assets/${args.product.image}");
//File file = "http://10.0.2.2:/shopice/assets/${args.product.image}" as File;
//var pic = await http.MultipartFile.fromString("image", args.product.image!);
//request.files.add(pic);
var bytes = (await rootBundle.load('http://localhost/shopice/assets/${args.product.image}')).buffer.asUint8List();
var mpFile = http.MultipartFile.fromBytes('img', bytes);
request.files.add(mpFile);
var response = await request.send();
print(args.product.image);
if (response.statusCode == 200) {
showModalBottomSheet(context: context, builder: (context){
return Wrap(children: [ListTile(leading: Icon(Icons.done_outline), title: Text('Product Added TO Cart'),)],);
});
}
else if (response.statusCode == 500) {
showModalBottomSheet(context: context, builder: (context){
return Wrap(children: [ListTile(leading: Icon(Icons.done_outline), title: Text('Server Error '),)],);
});
}
else {
showModalBottomSheet(context: context, builder: (context){
return Wrap(children: [ListTile(leading: Icon(Icons.done_outline), title: Text('ERROR WHILE PERFORMING OPPERATION\n CONTACT SUPPORT'),)],);
});
}
}
else if(args.receivedMap.isEmpty){
var snackbar = SnackBar(
content: Text('Login To Add Product To Cart!',
style: TextStyle(fontSize: 16.0)),
backgroundColor:
const Color(0xff4A777A),
padding: EdgeInsets.only(left: 50.0),
);
ScaffoldMessenger.of(context)
.showSnackBar(snackbar);
}
},
child: Text(
'Add to Cart',
style: GoogleFonts.poppins(
color: Color(0xff4A777A)),
)),
i simply add the image from the backend and forget about doing it with flutter, i moved the image with php and did some trial and error which later worked

How to send a verification email on registerUsingEmailPassword() in flutter

I wan't when a user clicks sign up button an email verification is sent. So far with my code on signup an email verification is sent but user can't navigate to the next page (CircularProgressIndicator keeps on loading)
Here is my code
onPressed: () async {
if (_regFormKey.currentState!.validate()) {
setState(() {
_isProcessing = true;
});
User? user = await FireAuth.registerUsingEmailPassword(
name: nameController,
email: _emailController.text,
password: _passwordController.text,
);
if (user != null) {
bool EmailSent = user.sendEmailVerification() as bool;
//I think something is wrong here
if (EmailSent) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => ProfilePage(user: user),
),
ModalRoute.withName('/'),
); }
} else{
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(' Account exists or Network problems'),
backgroundColor: Colors.red,
));}
setState(() {
_isProcessing = false;
});
}}
sendEmailVerification() returns a Future<void> so EmailSent is not going to get set. You should await the verification call in a try...catch to handle the response.
More like this:
if (user != null) {
try {
await user.sendEmailVerification();
/// sent successfully
// TODO: put your navigation here
} catch (e) {
/// error sending verification
// TODO: show snackbar
// TODO: set _isProcessing to false
}
}

flutter calculator - how to show an error msg when user divide by zero

I'm trying to validate that the second number is not zero only when user try to divide
my code
onPressed: () {
if (int.parse(secondNumberController.text) == 0) {
// show error message here
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('second num should not be zero!'),
),
);
return;
}
setState(() {
double divide = int.parse(firstNumberController.text) /
int.parse(secondNumberController.text);
result = divide.toString();
});
},

Can layout and logic separated in flutter?

I understand presence Bloc and Scoped Model in flutter.
But that isn't separate like a layout file in java's SpringBoot.
You can actually separate layout and logic in flutter. I have an example.
In my LoginForm I have a function
_attemptLogin() {
BlocProvider.of<LoginBloc>(context).add(
LoginButtonPressed(
context: context,
email: _tecEmail.text,
password: _tecPassword.text,
),
);
}
called by
RaisedButton(
color: Colors.blue,
child: const Text(
'Login',
style: TextStyle(
color: Colors.white,
),
),
onPressed: (state is LoginProcessing)
? null
: _attemptLogin,
),
and in my LoginBloc, I have the ff code inside mapEventToState
#override
Stream<LoginState> mapEventToState(LoginEvent event) async* {
if (event is LoginButtonPressed) {
yield LoginProcessing();
await Future.delayed(const Duration(milliseconds: 250));
try {
var loginResponse =
await _attemptLogin(userRepository, event.email, event.password);
/// Get Firebase Token
final firebaseToken =
await Provider.of<FirebaseMessagingProvider>(context).getToken();
if (loginResponse['data'] != null && firebaseToken != null) {
User user =
_setUserFromJsonMap(context, loginResponse['data']['user']);
IdentityToken identityToken = _setIdentityTokenFromJsonMap(
context, loginResponse['data']['token']);
/// Request Firebase Token Update
var jsonCreateUserFirebaseTokenResponse =
await _attemptFirebaseTokenUpdate(context, firebaseToken);
if (jsonCreateUserFirebaseTokenResponse != null) {
authBloc.add(LoggedIn(identityToken: identityToken));
yield LoginInitial();
}
} else {
yield LoginFailure(message: 'Login failed.');
}
} catch (error, stackTrace) {
print(error);
print(stackTrace);
await Future.delayed(const Duration(seconds: 1));
yield LoginFailure(
message: 'Login failed. Please check your internet connection.');
}
}
}
I didn't include all the other functions/classes as I have already deleted several lines of code to make it look readable, since it contains a ton of code already; which is unnecessary for only trying to prove a point that you can actually separate code for your view and logic.