Prevent refresh button or prompt message if click refresh (flutter web) - flutter

i know that for back button we can do by using the willpopscope,
but right now i' m trying to prevent user from refreshing the page, is there a way to disable the refresh button or prompt a message if user click the refresh button?
example of willpopscope
return WillPopScope (
onWillPop: () async {
return shouldPop;
},
child: const Text('WillPopScope sample'),
);

Adding this to lib/web/index.html will display a confirmation dialog:
...
<body>
<script type="text/javascript">
window.onbeforeunload = function() {
return "Changes that you made may not be saved.";
}
</script>
...
</body>
...
Like so:

A more elegant solution for web would be:
import 'dart:html' as html;
html.window.onBeforeUnload.listen((event) async {
if (event is html.BeforeUnloadEvent) event.returnValue = "Don't go!";
});
Like this only the page where you want to warn, triggers the event. Otherwise all windows would trigger the event.

Related

How can I change or override android/ios back button's action in flutter

I need to make a change in my page (changing a bool in setState etc...) when the user presses the back button.
I looked it up and I know people use WillPopScope to override the default "back" action, but in all of the examples they were just popping the page, and I need to do a custom function instead of that, and have no Idea how to do so.
my function looks like this, and I need to run in when the user pressed the back button:
Future<void> backToCats() async{
setState(() {
isLoaded=false;
});
if(isFromSearch){
loadCategories();
}
setState(() {
showingBrands=false;
isLoaded=true;
});
}
You can perform custom logic in the onWillPop argument of a WillPopScope widget. Just make sure to return true or false at the end to indicate whether the page is allowed to pop. WillPopScope will activate for the back button, and other actions that automatically navigate back such as swiping from the side of the screen on iOS.
For example, if you need to set a bool to false in your stateful widget, it would look something like this
WillPopScope(
onWillPop: () async {
setState(() => myBool = false);
return true;
}
child: ...
);

Flutter GetX refresh page after Get.back() [duplicate]

I need to reload page after Get.back(). How to do it? How to call any method on previous page as soon as possible after using Get.back()?
For example:
I'm on Page1
Go to Page2
Use Get.back(), so user back to Page1
Usually user now see Page1 exactly like when he leave Page1. How to reload now view Page1?
Maybe is any method to override what I can call every time after navigate one page back? This method must come from Page1, not from Page2
you can do await while navigating to page 2.
Example:
await Get.to(()=> Page2());
setState({
// perform update
});
the setState will get fired once you come back to page 1 from page 2
another, similar example, code from Page1:
ListTile(
title: const Text("Item"),
onTap: () async {
await Get.toNamed(page2);
setState(() {});
}),
Using this sample, refresh (setState) fired after return from Page2 to Page1.
on Page 2: You need to write this
Get.back(result: true);
on Page 1: wait for response
var response = await Get.to(()=> Page2());
if(response){setState({
// perform update
});}

Flutter: How to call function of Home button (home button default of Android)?

I have a button on the View and how to call function of Home button in onClick function of button?
Code example:
InkWell(
onTap: () {
//function of home button
},)
You could use this package:
https://pub.dev/packages/move_to_background
Meaning your code could be something like this:
InkWell(
onTap: () {
MoveToBackground.moveTaskToBack();
},
)
For what you are trying to achieve you need a background notifier because the home button sends app to background. There is a package called flutter_fgbg which can help you - click here pub.dev. Then you can proceed to stream background events, eg:
import 'package:flutter_fgbg/flutter_fgbg.dart';
StreamSubscription<FGBGType> subscription;
...
// in initState
subscription = FGBGEvents.stream.listen((event) {
if (event == FGBGType.foreground){
//if its come back to foreground, then restart your app
} else {
//if its gone to background
}
});
// in dispose
subscription.cancel();
For more assistance, you can check this link, for visual aid in solving problems Mufungo Geeks YouTube

How to implement reCaptcha into a flutter app

I am trying to implement the reCaptcha function to my flutter app, but in the captcha registration I need to provide a domain which I don't have one for a mobile app. I have browsed several guides teaching how to implement reCaptcha into a mobile app, yet those guides registered their reCaptcha with package names but not domains. What is the correct way to implement reCaptcha in a flutter app, or any mobile app in 2020?
You can use this plugin, flutter_recaptcha.
For the domain, I had the same issue. I first found that I needed to use the "I'm not a robot" checkbox option from here and I had to check the github repository to find this information, "!!! Remember to add this domain into the reCaptcha setting: recaptcha-flutter-plugin.firebaseapp.com," which explains it.
I was lost for a bit after not seeing that on the main page, but now it makes sense. Hopefully it helps.
Edit
I noticed something after trying it out, that I'd like to mention. The plugin does not provide a captcha response for using to authenticate the user server-side, so it does not seem very useful as it is. However, it is a simple plugin, so it may be possible to use it as an example. The steps, I think, would be to create a webpage with the captcha. As with the plugin, use a webview to open the page, then capture the post output of the form and ip address of user submitting the form, using something like this, then send it to flutter and then submit your request with that information, and use the Google library to verify the captcha.
Instructions
I just finished implementing this and I found a good way that works.
First, create an html page, like this:
<html>
<head>
<title>reCAPTCHA</title>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body style='background-color: aqua;'>
<div style='height: 60px;'></div>
<form action="?" method="POST">
<div class="g-recaptcha"
data-sitekey="YOUR-SITE-KEY"
data-callback="captchaCallback"></div>
</form>
<script>
function captchaCallback(response){
//console.log(response);
if(typeof Captcha!=="undefined"){
Captcha.postMessage(response);
}
}
</script>
</body>
</html>
Then, host that on your domain, say example.com/captcha.
Then, create a flutter Widget, like this:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class Captcha extends StatefulWidget{
Function callback;
Captcha(this.callback);
#override
State<StatefulWidget> createState() {
return CaptchaState();
}
}
class CaptchaState extends State<Captcha>{
WebViewController webViewController;
#override
initState(){
super.initState();
}
#override
Widget build(BuildContext context) {
return Center(
child: WebView(
initialUrl: "https://example.com/captcha.html",
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: Set.from([
JavascriptChannel(
name: 'Captcha',
onMessageReceived: (JavascriptMessage message) {
//This is where you receive message from
//javascript code and handle in Flutter/Dart
//like here, the message is just being printed
//in Run/LogCat window of android studio
//print(message.message);
widget.callback(message.message);
Navigator.of(context).pop();
})
]),
onWebViewCreated: (WebViewController w) {
webViewController = w;
},
)
);
}
}
Make sure you registered for a captcha key at https://www.google.com/recaptcha (click on "Admin Console" at the top-right).
Then, you have the front-end built. To call a captcha, just run:
Navigator.of(context).push(
MaterialPageRoute(
builder: (context){
return Captcha((String code)=>print("Code returned: "+code));
}
),
);
You can use whatever callback you want to, like this:
class GenericState extends State<Generic>{
void methodWithCaptcha(String captchaCode){
// Do something with captchaCode
}
#override
Widget build(BuildContext context) {
return Center(child:FlatButton(
child: Text("Click here!"),
onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (context){
return Captcha(methodWithCaptcha);
}
),
);
}
}
}
Server-side, you can follow the instructions here (I followed the sections "Direct Download" and "Usage"). I found that for the usage, I could simply use the code:
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp);
if ($resp->isSuccess()) {
// Verified!
} else {
$errors = $resp->getErrorCodes();
}
Using setExpectedHostname, like in the example, was unnecessary.
After that, everything works! I think this is currently the best way to implement Google reCaptcha V2 in flutter (for both iOS and Android).
If you are looking for Flutter WEB, You can try g_recaptcha_v3 package
Note:
it supports reCAPTCHA V3 only and not V2
its for Flutter Web only and no other platform supports
I've improved #JVE999 approach and created a new package:
flutter_firebase_recaptcha
The package uses InAppWebView for recapcha HTML rendering, so you don't need separate web page anymore.
My widget supports 'visible' and 'invisible' recapcha. Invisible recapcha allows you try to get recapcha token without showing anything to your user.

How can I control what is passed to Navigator.pop() when clicking outside of a showModalBottomSheet?

I launch a modal bottom sheet, then use the data that is returned as its future.
var modalFuture = showModalBottomSheet(
// ...
);
modalFuture.then((data) {
// Use data
});
I return data to it from the modal widget with:
Navigator.pop(context, data);
This is working well when completing the modal interaction with a widget I've set up.
I encounter my issue when clicking outside of the modal. Clicking outside of the modal causes the modal to dismiss automatically (with a Navigator.pop(context) call?). I am okay with this closing interaction, but I would like to send data back with it (with a Navigator.pop(context, data) call). Is there anyway to override the implicit pop when clicking outside of a showModalBottomSheet modal?
You can wrap your ModalWidget with WillPopScope. You can see the example below
WillPopScope(
onWillPop: () async {
Navigator.pop(context, data);
return true; // return true if needs to be popped
},
child: ModelWidget(
…
),
);
This will ensure that Navigator.pop is called when auto popped using the back button.