couldn't create named routes in Flutter - flutter

I defined needed routes in Material App and everything works fine, bit I have to add another button which should lead to authorisation page and now I am getting this error:
The following assertion was thrown while handling a gesture:
Could not find a generator for route RouteSettings("/changeUsers", null) in the _WidgetsAppState.
Make sure your root app widget has provided a way to generate
this route.
Generators for routes are searched for in the following order:
1. For the "/" route, the "home" property, if non-null, is used.
2. Otherwise, the "routes" table is used, if it has an entry for the route.
3. Otherwise, onGenerateRoute is called. It should return a non-null value for any valid route not handled by "home" and "routes".
4. Finally if all else fails onUnknownRoute is called.
My code look like this:
return MaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: {
'/': (context) => const AuthorizationPage(),
'/adminLogin': (context) => const AuthInsertLogging(),
'/mainPageUsers': (context) => const TabBarBottomUsers(),
'/mainPageAdmin': (context) => const TabBarBottom(),
"/logout": (_) => new AuthorizationPage(),
'/changeUsers': (_) => AuthorizationPage(),
},
);
}
This is the button I tried to make route:
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/changeUsers');
},
child: Text(
'Change User',
style: GoogleFonts.montserrat(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w500,
letterSpacing: 2),
),

This is because you use the AuthorizationPage for '/' home, '/logout' and '/changeUsers' routes. There is a rule for routes property in Flutter documentation. See details here
If home is specified, then it implies an entry in this table for the
Navigator.defaultRouteName route ( here '/' ), and it is an error to
redundantly provide such a route in the routes table.
The rule says there must be only one home route ( here '/' route ) is specified. Here there are three routes pointing to same page.
So, just remove '/logout' and '/changeUers' routes and write onPressed function as follows.
Navigator.pushNamed(context, '/');

Related

Flutter GetX - how to implement a loading screen that check the token

So this is the scenario:
I build an app that the first route or the first thing to do is check with a API REST a verification of a token that I already have on localsorage. If the token is valid, proceed to the home page route, if don't we need to redirect them to login screen. All this is async. I already try to get this working adding a route like this:
Widget build(BuildContext context) {
return GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => const AppPage(),
middlewares: [AppPageMiddleware()],
),
GetPage(name: '/login', page: () => const LoginPage()),
GetPage(
name: '/operator', page: () => const OperatorHomePage(), transition: Transition.zoom),
],
);
As you can see, I load a AppPage that the only thing that they do is show the loading spinner. The middleware called AppPageMiddleware uses this:
GetPageBuilder onPageBuildStart(GetPageBuilder? page) async {
// here I perform the call to the API and wait for the response.
// If the API response is true, I need to save the response
// and redirect to OperatorHomePage
print('Bindings of ${page.toString()} are ready');
return page!;
}
But I have an error here because I can't add async.
Maybe this is not the best way to do this, if you can suggest me another way, I will appreciate so much. Sorry, I'm new with GetX.

onGenerateRoute not redirecting with unauthenticated user

I am trying to redirect users to my login page if they visit my site without being logged in. I'm trying to use onGenerateRoute to do this. My code in main is this:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseAuth auth = FirebaseAuth.instance;
bool isAuth = auth.currentUser!=null ? true : false;
runApp(MaterialApp(
initialRoute: '/initial',
title: 'Repeater Delivery',
theme: ThemeData(...),
onGenerateRoute: (settings) {
if (!isAuth){
print(settings);
return MaterialPageRoute(
builder: (context) => Login(),
settings: RouteSettings(name: '/login'),
);
}
},
routes: {
'/initial': (context) => Home(),
'/home': (context) => Home(),
'/login': (context) => Login(),
'/signup': (context) => Signup(),
'/how_it_works': (context) => HowItWorks(),
'/profile': (context) => UserProfile(),
},
));
}
The page enters the if statement, so I know that that's working correctly, but I'm not sure how to then redirect to my login page. Also, when I go to a page on my site like www.site.com/#/profile and print out the settings from onGenerateRoute, it just prints a setting name of '/' instead of '/profile'. What am I doing wrong?
According to documentation MaterialApp.onGenerateRoute :
The route generator callback used when the app is navigated to a named
route.
If this returns null when building the routes to handle the specified
initialRoute, then all the routes are discarded and
Navigator.defaultRouteName is used instead (/). See initialRoute.
During normal app operation, the onGenerateRoute callback will only be
applied to route names pushed by the application, and so should never
return null.
This is used if routes does not contain the requested route.
The Navigator is only built if routes are provided (either via home,
routes, onGenerateRoute, or onUnknownRoute); if they are not, builder
must not be null.
Here, your initialRoute is passed to onGenerateRoute, which is not always returning a route (because of the Auth condition). So Navigator is giving another route (the "/") as the initial one. onGenerateRoute must never return null on the App launch task.
Your routes property is only used when you're using pushNamed Navigator's method

Flutter web redirect user if not authentiacted

I have a GetMaterialApp with named routes to be used in Flutter web for a dashboard project. However, I am struggling to check whether the user is authenticated and redirect the user depending on the auth state. This is my App Code:
GetMaterialApp(
initialBinding: InitialBinding(),
debugShowCheckedModeBanner: false,
theme: CustomTheme().getLightTheme,
themeMode: ThemeMode.light,
title: "----------",
initialRoute: "/login",
unknownRoute: GetPage(name: "/notfound", page: () => NotFoundPage()),
getPages: [
GetPage(name: "/login", page: () => Root()),
GetPage(name: "/dashboard", page: () => Dashboard()),
],
),
I am using GetX to handle the authentication state. Therefore, I have access to the authentication state throughout the web app. The Root widget consists of a simple Obx to check the authentication state and send the user to the dashboard:
return Obx(() => (Get.find<AuthController>().loggedIn) ? Dashboard() : LoginScreen());
Sadly, that does not do the trick, as the url does not change, simply the content does. The url remains at /login.
I could simply call Get.toNamed("dashboard") when the user is logged in, but then the dashboard page would be exposed to the url, allowing the user to reach the /dashboard url even if he is not logged in.
I also do not want to create a check in every Widget or page I create, since that would be inefficient. Is there a way to check whether the user is logged in and, if not, redirect the user to the login page on every url entered?
Example:
www.adress.com/dashboard would redirect to www.adress.com/login if the user is not logged in
Is there a way to generally check the auth-state and redirect the user accordingly using GetX?
Side Note: I am able to get the correct authentication state every time, that is not the problem, as I use GetX.
Short Summary:
Is it possible to check the auth state outside the actual widget (e.g. in the GetMaterialApp) and redirect any not-authenticated users to the login page, even if they type in the /dashboard url?
Use middleware for check if user is authenticated or not
GetMaterialApp(
initialBinding: InitialBinding(),
debugShowCheckedModeBanner: false,
theme: CustomTheme().getLightTheme,
themeMode: ThemeMode.light,
title: "----------",
initialRoute: "/dashboard",
unknownRoute: GetPage(name: "/notfound", page: () => NotFoundPage()),
getPages: [
GetPage(name: "/login", page: () => Root()),
GetPage(name: "/dashboard", page: () => Dashboard(), middleware: [AuthMiddleware()]),
],
),
class AuthMiddlware extends Middlware {
RouteSetting? redirect(String? route) => !isAuthenticated ? RouteSetting(name="/login") : null;
}
If the user requests an arbitrary page within your web app, then you may want to intercept with the login page before continuing to the requested page. You can do this by passing a return url to the login page...
main.dart
GetMaterialApp(
...
initialRoute: "/dashboard",
getPages: [
GetPage(name: "/login", page: () => Root()),
GetPage(
name: "/dashboard",
page: () => Dashboard(),
middlewares: [AuthMiddleware()]
),
],
),
class AuthMiddleware extends GetMiddleware {
RouteSettings? redirect(String? route) {
String returnUrl = Uri.encodeFull(route ?? '');
return !isAuthenticated
? RouteSettings(name: "/login?return=" + returnUrl)
: null;
}
}
Then in your login page, after logging in you can direct back to where the original request intended...
login.dart
//after successful login...
String returnUrl = Get.parameters['return'] ?? '/';
Get.offAllNamed(returnUrl);

how to refresh current page while doing pull to refresh (LiquidPullToRefresh) in Flutter Bloc

am using bloc method for home screen. I want to do pull to refresh in home screen...
I tired too many ways not getting solution...could you please suggest some solution.
In side onrefresh() I added few changes
1 . BlocProvider(
create: (context) => OttGetAllMovie(httpClient: http.Client())
..add(FeedsFetched(widget.title, "homePage")),
//child: HomePage(),
child: OttGetHomeInnerCatPage(
wtitle: widget.title, mixpanelinner: widget.mixpanel),
)
2. _feedsBloc.add(FeedsFetched(widget.wtitle, "homePage"));
3. setState(() {
_feedsBloc.add(FeedsFetched(widget.wtitle, "homePage"));
BlocProvider(
create: (context) => OttGetAllMovie(httpClient: http.Client())
..add(FeedsFetched(widget.title, "homePage")),
//child: HomePage(),
child: OttGetHomeInnerCatPage(
wtitle: widget.title, mixpanelinner: widget.mixpanel),
)
});
While
this seems to be the method you're using to fetch data
OttGetAllMovie(httpClient: http.Client())
..add(FeedsFetched(widget.title, "homePage")),
Wrap your body in liquid pull to refresh
LiquidPullToRefresh(
key: _refreshIndicatorKey, // key if you want to add
onRefresh: ()async{
//cal your data source
OttGetAllMovie(httpClient: http.Client())
..add(FeedsFetched(widget.title, "homePage")),
}
child: ListView(), // scroll view
);

How to get argument from url in flutter web using get: ^3.26.0

return GetMaterialApp(
title: title,
theme: appTheme,
getPages: [
GetPage(name: '/', page: () => Splash()),
GetPage(name: '/update', page: () => Update()),
GetPage(name: '/login', page: () => SignIn()),
GetPage(name: '/reference', page: () => Reference()),
],
home: Splash(),
);
this is my route code and now i want to user enter url like : xyz.com/login/jayesh , then i want to get user name in login screen using getx state management.
In your route:
xyz.com/login?username=jayesh
And in your controller or in your view:
var username = Get.parameters["username"];
A good place to get your arguments or parameters may be in your controllers onInit or your views build method
add page with name in GetMaterialApp
getPages:[
GetPage(name: '/login/:refId', page: () => SignIn()),
],
you can retrive data(perameter) like:
var data = Get.parameters;
String id = data['refId'];