How to call button tap functionality outside of button in Flutter - flutter

I want to call the onTap functionality outside of my button. As soon as I receive my OTP, I want to call the onTap of my manually created widget. I have a custom widget called as LoginCTA and I want to call it's onTap after I receive my OTP in initSmsListener method which I called in initState.
My code -
String _comingSms = 'Unknown';
Future<void> initSmsListener() async {
String comingSms;
try {
comingSms = await AltSmsAutofill().listenForSms??"";
} on PlatformException {
comingSms = 'Failed to get Sms.';
}
if(!mounted)
return;
setState(() {
_comingSms=comingSms;
print("\n \n \n Coming SMS - $_comingSms");
otpController.text = _comingSms[23] + _comingSms[24] + _comingSms[25] + _comingSms[26]
+ _comingSms[27] + _comingSms[28];
});
//Apply here -
}
#override
void initState() {
initSmsListener();
super.initState();
}
isOTP
? LoginCTA(
//After input otp
onPressed: () async {
print(Provider.of<APIData>(context, listen: false)
.loggedIN);
if (emailEntered &&
otpController.text.length == 6) {
bool res;
try {
res = await widget.signInWithOTP(
contactController.text, otpController.text);
} catch (e) {
res = false;
print(e);
}
if (res) {
Fluttertoast.showToast(
msg: "Verifying OTP...",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
textColor: cardColor,
backgroundColor: primaryTextColor,
fontSize: 16.0,
);
Timer(Duration(seconds: 2), () {
print(Provider.of<APIData>(context,
listen: false)
.loggedIN);
if (Provider.of<APIData>(context,
listen: false)
.loggedIN ==
1) {
Navigator.pop(context);
}
});
}
}
},
btnText: otpButtonText,
isDisabled: isDisabled,
)
: LoginCTA(
//After input mobile number
onPressed: () async {
if (emailEntered &&
contactController.text.length == 10) {
widget.sendOTP(contactController.text);
setState(() {
isOTP = true;
isDisabled = true;
});
} else {
print('kuch na kuch glti');
}
},
btnText: buttonText,
isDisabled: isDisabled,
hasIcon: hasIcon,
),

Just extract the functionality out into its own function. Then you can assign the function to onTap and also call it whenever you like.

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),
),
),
),
),

Flutter call function from other class?

Hi I am building flutter function which able to capture qr code and after display the result after user scan QR Code. I need user to be able navigate to previous scanning screen by using button if they need rescan or scan new qr code. This is code for button which on Scanview class.
SizedBox(height: 40,),
CupertinoButton(
color: Color(0xFF88070B),
child:Text("Re-scan QR "),
onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => **ScanFunction**(),
),
);
}
)
I want to call this _scanQR method from other class ScanFunction . What is proper way when user tap Re-scan QR button and call _scanQR method which is on other class? How to access method from other class? Thanks for help.
class ScanFunction extends StatefulWidget {
#override
ScanFunctionState createState() {
return ScanFunctionState();
}
}
class ScanFunctionState extends State<ScanFunction> {
String result = "Maklumat Inventori";
Future _scanQR() async {
try {
String qrResult = await BarcodeScanner.scan();
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Scanresultview(qrResult),
),
);
} on PlatformException catch (ex) {
if (ex.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
result = "Kebenaran kamera telah ditolak";
});
} else {
setState(() {
result = "Ralat tidak diketahui$ex";
});
}
} on FormatException {
setState(() {
result = "Anda menekan butang belakang sebelum mengimbas apa-apa";
});
} catch (ex) {
setState(() {
result = "Ralat tidak diketahui $ex";
});
}
}
You can call this method from initState.
class ScanFunction extends StatefulWidget {
#override
ScanFunctionState createState() {
return ScanFunctionState();
}
}
class ScanFunctionState extends State<ScanFunction> {
#override
void initState() {
_scanQR();
super.initState();
}
String result = "Maklumat Inventori";
Future _scanQR() async {
try {
String qrResult = await BarcodeScanner.scan();
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Scanresultview(qrResult),
),
);
} on PlatformException catch (ex) {
if (ex.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
result = "Kebenaran kamera telah ditolak";
});
} else {
setState(() {
result = "Ralat tidak diketahui$ex";
});
}
} on FormatException {
setState(() {
result = "Anda menekan butang belakang sebelum mengimbas apa-apa";
});
} catch (ex) {
setState(() {
result = "Ralat tidak diketahui $ex";
});
}
}

file downloader app with package sn progress dialog

How to change the progress_dialog package to the sn_progress_dialog package? I'm trying to make a file downloader app with a progress dialog, but the progress_dialog package is not null safety.
Future _downloadAndSaveFileToStorage(String urlPath) async {
final name = urlPdf.split('/').last;
ProgressDialog pr;
pr = ProgressDialog(context, type: ProgressDialogType.Normal);
pr.style(message: "Download file ...");
try{
await pr.show();
final Directory _documentDir = Directory('/storage/emulated/0/MyDocuments/$name');
await dio!.download(urlPath, _documentDir.path, onReceiveProgress: (rec, total){
setState(() {
_isLoading = true;
progress = ((rec / total)*100).toStringAsFixed(0) + " %";
print(progress);
pr.update(message: "Please wait : $progress");
});
});
pr.hide();
_fileFullPath = _documentDir.path;
} catch (e) {
print(e);
}
setState(() {
_isLoading = false;
});
}
And this is my screenshot app with progress_dialog package.
Just do like this :
Future _downloadAndSaveFileToStorage(String urlPath) async {
final name = urlPdf.split('/').last;
ProgressDialog pd = ProgressDialog(context: context);
try{
pd.show(max: 100, msg: 'Download file ...');
final Directory _documentDir = Directory('/storage/emulated/0/MyDocuments/$name');
await dio!.download(urlPath, _documentDir.path, onReceiveProgress: (rec, total){
setState(() {
_isLoading = true;
progress = ((rec / total)*100).toStringAsFixed(0) + " %";
print(progress);
pd.update(progress);
});
});
pd.close();
_fileFullPath = _documentDir.path;
} catch (e) {
pd.close();
print(e);
}
setState(() {
_isLoading = false;
});
}
and you can change color or message in show method like this :
pd.show(
max: 100,
msg: 'Preparing Download...',
progressType: ProgressType.valuable,
backgroundColor: Color(0xff212121),
progressValueColor: Color(0xff3550B4),
progressBgColor: Colors.white70,
msgColor: Colors.white,
valueColor: Colors.white);
just need a little tweaking :
Future _downloadAndSaveFileToStorage(String urlPath) async {
final name = urlPdf.split('/').last;
ProgressDialog pd = ProgressDialog(context: context);
try{
pd.show(
max: 100,
msg: 'Preparing Download...',
progressType: ProgressType.valuable,
backgroundColor: Color(0xff212121),
progressValueColor: Color(0xff3550B4),
progressBgColor: Colors.white70,
msgColor: Colors.white,
valueColor: Colors.white
);
final Directory _documentDir = Directory('/storage/emulated/0/MYDocuments/$name');
await dio!.download(urlPath, _documentDir.path, onReceiveProgress: (rec, total){
setState(() {
_isLoading = true;
int progress = (((rec / total) * 100).toInt());
print(progress);
pd.update(value: progress, msg: 'File Downloading');
});
});
pd.close();
_fileFullPath = _documentDir.path;
} catch (e) {
pd.close();
print(e);
}
setState(() {
_isLoading = false;
});
}

flutter how to terminate all ongoing actions when the back button is pressed?

I want to terminate any currently executing function task when the back button is clicked.How can I do it?(I want to terminate the below function if I press back button)
void getData(String locale, String searchKey, List<String> contentType,
int categoryID, int start, int limit) async {
print('get data');
temp = (await context.read(knowledgeBaseViewModelProvider).getCategoryData(
locale, searchKey, contentType, categoryID, start, limit))!;
_isLoding = false;
if(mounted){
setState(() {
if (temp.length == 0 ) {
isEnd = true;
momAlertBox(
context,
"Alert",
"No More Data.Try Another Category!",
"Oky.",
() => Navigator.pop(context, 'OK'),
);
} else {
isEnd = false;
}
isLodingState = false;
items.addAll(temp);
});
}
}
The back button
BackButton(
onPress: () => {
Navigator.pop(context)},
svgAssetsPath: "assets/icons/icon_back.svg",
height: SizeConfig.devicePixelRatio * 8,
width: SizeConfig.devicePixelRatio * 8,
),

flutter : disable button after fetch data

I am trying to implement a flutter app to fetch data from an API end point. I've already implemented the fetch function on button press.
Although, I want the button (Enregistrer) to get disabled (to avoid multiple clicks) while the request is being fetched or after success editing (name, adress ...) !
I implemented it using the dart http package.
Here's my code for the same:
Container(
margin: EdgeInsets.symmetric(
vertical: 10),
width: size.width * 0.4,
child: ElevatedButton(
onPressed: () {
if (_nameController.text ==
"" &&
_emailController.text ==
"" &&
_adressController
.text ==
"") {
setState(() =>
isButtonDisabled =
true);
} else {
editUserProfile();
}
},
child: Text('Enregistrer'),
void editUserProfile() async {
setState(() {});
// if (_formKey.currentState.validate()) {
String name = _nameController.text;
String email = _emailController.text;
String adress = _adressController.text;
userApi.editUserProfile(name, email, adress).then((data) {
if (data != null) {
}
setState(() {
enableup = false;
enableadress = false;
enableemail = false;
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(data)));
// ScaffoldMessenger.of(context).showSnackBar(snackBar3);
}).catchError((error) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(error.toString())));
});
setState(() {});
}
if you set null onPressed you actualy disable the click
onPressed: isButtonDisabled ? null : () {
if (_nameController.text == "" &&
_emailController.text == "" &&
_adressController.text == "") {
setState(() =>
isButtonDisabled = true);
} else {
editUserProfile();
}
}