App widget is not generating the route | firebase signup - flutter

Upon successful signup, I am trying to send users to the homepage (home) explaining how to use the app. I am doing so through this code block on my signup.dart
onPressed: () async {
try {
User user =
(await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
))
.user;
if (user != null) {
user.updateProfile(displayName: _nameController.text);
Navigator.of(context).pushNamed(AppRoutes.home);
}
}
Which is pointing to the home route
class AppRoutes {
AppRoutes._();
static const String authLogin = '/auth-login';
static const String authSignUp = '/auth-signup';
static const String home = '/home';
static Map<String, WidgetBuilder> define() {
return {
authLogin: (context) => Login(),
authSignUp: (context) => SignUp(),
home: (context) => Home(),
};
}
}
However, when I sign up, the data is rendering in firebase, but the user is not being sent to the home page, and throws this error in my console
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.
Unfortunately, onUnknownRoute was not set.
Any thoughts on how to rectify?

Have you added onGenerateRoute in your MaterialApp? Like this:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
onGenerateRoute: Router.generateRoute,
initialRoute: yourRoute,
child: YouApp(),
);
}
}
class Router {
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case AppRoutes.home:
return MaterialPageRoute(builder: (_) => Home());
case AppRoutes.authLogin:
return MaterialPageRoute(builder: (_) => Login());
case AppRoutes.authSignUp:
return MaterialPageRoute(builder: (_) => SignUp());
default:
return MaterialPageRoute(
builder: (_) => Scaffold(
body: Center(
child: Text('No route defined for ${settings.name}')),
));
}
}
}
}
}

Related

How to pass in arguments in flutter when user input URL address (using auto_route)

My app uses flutter with auto_router 0.6.9 package, and I want user to be able to type in a web address http://localhost/#/book/123 and be able to access book 123 and display book123, their name, and email if they are logged in. I had figured out the routing part with auto_router but when the user put the address directly into the browser, the arguments should be passed into the page are null.
I was wondering is there a way to parse the url and pass in the arguments required before displaying the page. Thanks for any help or hints!
My router.dart page:
#MaterialAutoRouter(
routes: <AutoRoute>[
// some other pages...
MaterialRoute(path: "/book/:id", page: MultiProvider),
],
)
class $ModularRouter {}
The router.gr.dart generated for multiprovider arguments class is:
/// MultiProvider arguments holder class
class MultiProviderArguments {
final Key key;
final List<SingleChildWidget> providers;
final Widget child;
final Widget Function(BuildContext, Widget) builder;
MultiProviderArguments(
{this.key, #required this.providers, this.child, this.builder});
}
My book menu page contains a navigation:
(this is an example of how I normally call the BookPage in another page)
child: GestureDetector(
onTap: () => ExtendedNavigator.of(context).push(
Routes.multiProvider(id: book[index].bookID),
arguments: MultiProviderArguments(
providers: [
Provider<UserData>.value(
value: userdata,
),
Provider<List<BookInfo>>.value(
value: book,
),
],
child: BookPage(
bookId: book[index].bookID,
name: userdata.userName,
email: userdata.email,
),
),
),
...
And BookPage takes in 3 arguments bookId, name and email:
class BookPage extends StatefulWidget {
final String bookId;
final String name;
final String email;
BookPage({
this.bookId,
this.name,
this.email,
});
...
}
...
class _BookPageState extends State<BookPage> {
...
Widget build(BuildContext context) {
final currentUser = Provider.of<UserData>(context, listen: false);
final currentBook = Provider.of<List<BookInfo>>(context, listen: false);
...
}
}
I had figured out a Band-Aid solution (which I don't consider to be permanent):
I had abandoned using auto-route which I have no idea how to parse the url and use onGenerateRoute instead:
onGenerateRoute: (settings) {
final settingsUri = Uri.parse(settings.name);
final user = Provider.of<User>(context);
if (user == null) {
return MaterialPageRoute(
builder: (context) {
return LogInPage();
}
);
} else {
// Handle '/'
if (settingsUri.pathSegments.length == 0) {
return MaterialPageRoute(
builder: (context) {
return PageWrapper(false, bookid);
}
);
}
// Handle '/book/:id'
if (settingsUri.pathSegments.length == 2) {
if (settingsUri.pathSegments.first != 'book') {
return MaterialPageRoute(
builder: (context) {
return UnknownPage();
}
);
}
final bookid = settingsUri.pathSegments.elementAt(1);
if (bookid == null) {
return MaterialPageRoute(
builder: (context) {
return UnknownPage();
}
);
}
return MaterialPageRoute(
builder: (context) {
return PageWrapper(false, bookid);
}
);
}
}
//Handle other unknown Routes
return MaterialPageRoute(
builder: (context) {
return UnknownPage();
}
);
}
The PageWrapper authenticates user, build providers, and call BookPage class, I put the code in a place where userData providers had already been initialized:
if (this.needRedirect == true) {
return Scaffold(
...
body: FutureBuilder(
future: Future.wait([userData]),
builder: (context, snapshot) {
return MultiProvider(
providers: [
//initialize using streamproviders
...
],
child: BookPage(
bookId: book[index].bookID,
name: userdata.userName,
email: userdata.email,
),
);
}),
);
}
else {...}
The short answer is I had called the WrapperPage in onGenerateRoutes because the providers are not initialized in main.dart, but they are initialized in WrapperPage. Then I put the redirect code after provider initialization in WrapperPage and called BookPage.
This method had caused other bugs, but it had achieved its purpose.

getting query parameter on initial route flutter

I'm working on a flutter application mainly for the web, and I'm unable to add/get the query
parameter from the URL, the query parameter will contain an id, and this id should be used inside the app
this my route setup on my app state:
return MaterialApp(navigatorKey: key, initialRoute: '/main',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/main': (context) => Map_View(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => TaskClosed(),
},onGenerateRoute: RouteGenerator.generateRoute,);
}
class RouteGenerator{
static Route<dynamic> generateRoute(RouteSettings settings){
final args = settings.arguments;
print(args);
var routingData = settings.name;
}}
the settings.arguments are always null
so what should I pass to initialRoute to make it accept arguments on the first screen
for example, the calling URL should be like this:
https:example.com/main?123
so how to get this parameter from the URL
I tried this code:
class RouteGenerator {
static Route<dynamic> generateRoute(RouteSettings settings) {
String? route;
Map? queryParameters;
if (settings.name != null) {
var uriData = Uri.parse(settings.name!);
route = uriData.path;
queryParameters = uriData.queryParameters;
}
var message =
'generateRoute: Route $route, QueryParameters $queryParameters';
print(message);
return MaterialPageRoute(
builder: (context) {
return MyHomePage(title: message);
},
settings: settings,
);
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/main',
routes: {
// '/': (context) {
// print('route: /');
// return MyHomePage(title: 'Home');
// },
'/main': (context) {
print('route: /main');
return MyHomePage(title: 'route: Main');
},
'/second': (context) {
print('route: /second');
return MyHomePage(title: 'route: Second');
},
},
onGenerateRoute: RouteGenerator.generateRoute,
);
}
}
When I run the app with the URL http://localhost:55260/#/main?123, I get this output:
generateRoute: Route /, QueryParameters {}
generateRoute: Route /main, QueryParameters {123: }
The screen is displayed for /main and the URL is displayed correctly.
Sorry, I misunderstand the scenario. Here is my suggest
remove routes
return MaterialApp(navigatorKey: key, initialRoute: '/main',
//routes: {
// When navigating to the "/" route, build the FirstScreen widget.
//'/main': (context) => Map_View(),
// When navigating to the "/second" route, build the SecondScreen widget.
//'/second': (context) => TaskClosed(),
// },
onGenerateRoute: RouteGenerator.generateRoute,);
}
And change like
class RouteGenerator {
static Route<dynamic> generateRoute(RouteSettings settings) {
final args = settings.arguments;
print(args);
var routingData = settings.name;
switch (routingData) {
case "/main":
return MaterialPageRoute(
builder: (context) {
return Map_View();
},
settings: settings,
);
break;
case "/second":
return MaterialPageRoute(
builder: (context) {
return TaskClosed();
},
settings: settings,
);
break;
default:
return MaterialPageRoute(
builder: (context) {
return YouUnKnowPage();
},
settings: settings,
);
}
}
}
when you call Navigator.of(context).pushNamed("/main",arguments:"123");
It will move to TaskClosed and print 123 in the console
Furthermore, if you directly type the link like https:example.com/main?123
It will lead to YouUnKnowPage instead of Map_View and the arguments will be null. Try to use Navigator.of(context).pushNamed("/main",arguments:"123");
If you insist on directly type the link, you can try this
class RouteGenerator {
static Route<dynamic> generateRoute(RouteSettings settings) {
String routingData;
var arguments;
if (settings.name != null) {
routingData = settings.name;
}
final args = settings.arguments;
if (args != null) {
arguments = args;
} else {
Uri settingsUri = Uri.parse(settings.name);
if (settingsUri.hasQuery) {
arguments = "${settingsUri.queryParameters}";
}
if (settingsUri.pathSegments.length > 1) {
routingData =
"/" + settingsUri.pathSegments[settingsUri.pathSegments.length - 1];
}
}
if (arguments != null) {
print(arguments);
}
switch (routingData) {
case "/main":
return MaterialPageRoute(
builder: (context) {
return Map_View();
},
settings: settings,
);
break;
case "/second":
return MaterialPageRoute(
builder: (context) {
return TaskClosed();
},
settings: settings,
);
break;
default:
return MaterialPageRoute(
builder: (context) {
return YouUnKnowPage();
},
settings: settings,
);
}
}
}
Now it will move to TaskClosed and print {123:} in the console

Flutter Provider rebuilt widget before parent's Consumer

I have got a problem with the provider package.
I want to be able to clean an attribute (_user = null) of a provider ChangeNotifier class (it is a logout feature).
The problem is when I am doing that from a Widget that use info from this Provider.
My main app is like :
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => AuthProvider(),
builder: (context, _) => App(),
),
);
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<AuthProvider>(builder: (_, auth, __) {
Widget displayedWidget;
switch (auth.loginState) {
case ApplicationLoginState.initializing:
displayedWidget = LoadingAppScreen();
break;
case ApplicationLoginState.loggedIn:
displayedWidget = HomeScreen();
break;
case ApplicationLoginState.loggedOut:
default:
displayedWidget = AuthenticationScreen(
signInWithEmailAndPassword: auth.signInWithEmailAndPassword,
registerAccount: auth.registerAccount,
);
}
return MaterialApp(
title: 'My App',
home: displayedWidget,
routes: {
ProfileScreen.routeName: (_) => ProfileScreen(),
},
);
});
}
}
My Provider class (simplified) :
class AuthProvider extends ChangeNotifier {
ApplicationLoginState _loginState;
ApplicationLoginState get loginState => _loginState;
bool get loggedIn => _loginState == ApplicationLoginState.loggedIn;
User _user;
User get user => _user;
void signOut() async {
// Cleaning the user which lead to the error later
_user = null;
_loginState = ApplicationLoginState.loggedOut;
notifyListeners();
}
}
My Profile screen which is accessible via named Route
class ProfileScreen extends StatelessWidget {
static const routeName = '/profile';
#override
Widget build(BuildContext context) {
final User user = Provider.of<AuthProvider>(context).user;
return Scaffold(
// drawer: AppDrawer(),
appBar: AppBar(
title: Text('Profile'),
),
body: Column(
children: [
Text(user.displayName),
FlatButton(
child: Text('logout'),
onPressed: () {
// Navigator.pushAndRemoveUntil(
// context,
// MaterialPageRoute(builder: (BuildContext context) => App()),
// ModalRoute.withName('/'),
// );
Provider.of<AuthProvider>(context, listen: false).signOut();
},
)
],
),
);
}
}
When I click the logout button from the profile screen, I don't understand why i get the error :
As I am using a Consumer<AuthProvider> at the top level of my app (this one includes my route (ProfileScreen), I thought it would redirect to the AuthenticationScreen due to the displayedWidget computed from the switch.
But it seems to rebuild the ProfileScreen first leading to the error. the change of displayedWidget do not seems to have any effect.
I'm pretty new to Provider. I don't understand what I am missing in the Provider pattern here ? Is my App / Consumer wrongly used ?
I hope you can help me understand what I've done wrong here ! Thank you.
Note : the commented Navigator.pushAndRemoveUntil redirect correctly to the login screen but I can see the error screen within a few milliseconds.
Your user is null, and you tried to get the name of him. You need to check it before using it. It will look like this:
user == null ?
Text("User Not Found!"),
Text(user.displayName),
From the provider API reference of Provider.of :
Obtains the nearest Provider up its widget tree and returns its
value.
If listen is true, later value changes will trigger a new State.build
to widgets, and State.didChangeDependencies for StatefulWidget.
So I think the line final User user = Provider.of<AuthProvider>(context).user; in your profile screen calls a rebuild when the _user variable is modified, and then the _user can be null in your ProfileScreen.
Have you tried to Navigator.pop the profile screen before clearing the _user variable?

Declarative auth routing with Firebase

Rather than pushing the user around with Navigator.push when they sign in or out, I've been using a stream to listen for sign in and sign out events.
StreamProvider<FirebaseUser>.value(
value: FirebaseAuth.instance.onAuthStateChanged,
)
It works great for the home route as it handles logging in users immediately if they're still authed.
Consumer<FirebaseUser>(
builder: (_, user, __) {
final isLoggedIn = user != null;
return MaterialApp(
home: isLoggedIn ? HomePage() : AuthPage(),
// ...
);
},
);
However, that's just for the home route. For example, if the user then navigates to a settings page where they click a button to sign out, there's no programmatic logging out and kicking to the auth screen again. I either have to say Navigator.of(context).pushNamedAndRemoveUntil('/auth', (_) => false) or get an error about user being null.
This makes sense. I'm just looking for possibly another way that when they do get logged out I don't have to do any stack management myself.
I got close by adding the builder property to the MaterialApp
builder: (_, widget) {
return isLoggedIn ? widget : AuthPage();
},
This successfully moved me to the auth page after I was unauthenticated but as it turns out, widget is actually the Navigator. And that means when I went back to AuthPage I couldn't call anything that relied on a parent Navigator.
What about this,you wrap all your screens that depend on this stream with this widget which hides from you the logic of listening to the stream and updating accordingly(you should provide the stream as you did in your question):
class AuthDependentWidget extends StatelessWidget {
final Widget childWidget;
const AuthDependentWidget({Key key, #required this.childWidget})
: super(key: key);
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {//you handle other cases...
if (snapshot.currentUser() != null) return childWidget();
} else {
return AuthScreen();
}
},
);
}
}
And then you can use it when pushing from other pages as follows:
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (ctx) => AuthDependentWidget(
childWidget: SettingsScreen(),//or any other screen that should listen to the stream
)));
I found a way to accomplish this (LoVe's great answer is still completely valid) in case anyone else steps on this issue:
You'll need to take advantage of nested navigators. The Root will be the inner navigator and the outer navigator is created by MaterialApp:
return MaterialApp(
home: isLoggedIn ? Root() : AuthPage(),
routes: {
Root.routeName: (_) => Root(),
AuthPage.routeName: (_) => AuthPage(),
},
);
Your Root will hold the navigation for an authed user
class Root extends StatefulWidget {
static const String routeName = '/root';
#override
_RootState createState() => _RootState();
}
class _RootState extends State<Root> {
final _appNavigatorKey = GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final canPop = _appNavigatorKey.currentState.canPop();
if (canPop) {
await _appNavigatorKey.currentState.maybePop();
}
return !canPop;
},
child: Navigator(
initialRoute: HomePage.routeName,
onGenerateRoute: (RouteSettings routeSettings) {
return MaterialPageRoute(builder: (_) {
switch (routeSettings.name) {
case HomePage.routeName:
return HomePage();
case AboutPage.routeName:
return AboutPage();
case TermsOfUsePage.routeName:
return TermsOfUsePage();
case SettingsPage.routeName:
return SettingsPage();
case EditorPage.routeName:
return EditorPage();
default:
throw 'Unknown route ${routeSettings.name}';
}
});
},
),
);
}
}
Now you can unauthenticate (FirebaseAuth.instance.signout()) inside of the settings page (or any other page) and immediately get kicked out to the auth page without calling a Navigator method.

How can a named route have URL parameters in flutter web?

I'm building a web-app which needs to have a route that gets a post ID and then it will fetch the post using the ID.
How can I have URL arguments let's say /post/:id so id is the argument
My app looks like that currently:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
// title: "Paste",
initialRoute: "/",
theme: ThemeData(
primarySwatch: Colors.green,
primaryColor: Colors.blue
),
routes: {
"/": (context) => HomePage(),
"/post": (context) => PastieRoute()
},
debugShowCheckedModeBanner: false
);
}
}
EDIT:
This is what I tried according to #BloodLoss and for some reason I don't get anything to the console when accessing localhost:8080/post?id=123
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/",
routes: {
"/": (context) => HomePage(),
"/post": (context) => PastieRoute()
},
onGenerateRoute: (settings) {
if (settings.name == "/post") {
print(settings.arguments); // Doesn't fire :(
return MaterialPageRoute(
builder: (context) {
// TODO
}
);
}
},
debugShowCheckedModeBanner: false
);
}
}
tl;dr
//in your example: settings.name = "/post?id=123"
final settingsUri = Uri.parse(settings.name);
//settingsUri.queryParameters is a map of all the query keys and values
final postID = settingsUri.queryParameters['id'];
print(postID); //will print "123"
Drilldown
In a perfect world you would access queryParameters with Uri.base.queryParameters because:
Uri.base
Returns the natural base URI for the current platform.
When running in a browser this is the current URL of the current page (from window.location.href).
When not running in a browser this is the file URI referencing the current working directory.
But currently there is an issue in flutter where you have #/ in your path which messes the Uri.base interpretation of the Uri.
Follow the issue #33245 until this matter is addressed and you will be able to use Uri.base.queryParameters
please follow this link further information https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments
on your MaterialApp
onGenerateRoute: (settings) {
// If you push the PassArguments route
if (settings.name == PassArgumentsScreen.routeName) {
// Cast the arguments to the correct type: ScreenArguments.
final ScreenArguments args = settings.arguments;
// Then, extract the required data from the arguments and
// pass the data to the correct screen.
return MaterialPageRoute(
builder: (context) {
return PassArgumentsScreen(
title: args.title,
message: args.message,
);
},
or you can nativate like web using this plugin fluro
This is how I did it. You can edit it as per your requirements. If you want to use ?q= then use the split by or regex accordingly
Here is the example of both passing in argument as well as passing in url as /topic/:id
Route<dynamic> generateRoute(RouteSettings settings) {
List<String> pathComponents = settings.name.split('/');
final Map<String, dynamic> arguments = settings.arguments;
switch ("/"+pathComponents[1]) {
case shareTopicView:
return MaterialPageRoute(
builder: (context) => TopicPageLayout(topicID: pathComponents[2]));
case internalTopicView:
return MaterialPageRoute(
builder: (context) => TopicPageLayout(topicID: arguments['topicID']));
default:
return MaterialPageRoute(builder: (context) => LandingPage());
}
}
I'm new to Flutter, and I found a quirky workaround,...
import 'dart:html';
String itemID;
//My url looks like this,... http://localhost:57887/#item_screen/12345
//Counted 13 characters for '#item_screen/' then got the substring as below
itemID = window.location.hash.substring(13);
print(itemID) //12345
Not very sophisticated, but worked :-D
Add flutter_modular to your flutter web project.
current version: flutter_modular: ^3.1.1
Read dynamic routes section in: https://pub.dev/packages/flutter_modular#dynamic-routes
Example for the URL /post?id=123
Create your main widget with a MaterialApp and call the ´´´MaterialApp().modular()´´´ method.
// app_widget.dart
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
class AppWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/",
).modular();
}
}
Create your project module file extending Module:
// app_module.dart
class AppModule extends Module {
#override
final List<Bind> binds = [];
#override
final List<ModularRoute> routes = [
ChildRoute('/', child: (_, __) => HomePage()),
ChildRoute('/post', child: (_, args) => PostPage(id: args.queryParams['id'])),
];
}
3.In main.dart file, wrap the main module in ModularApp to initialize it with Modular:
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'app/app_module.dart';
void main() => runApp(ModularApp(module: AppModule(), child: AppWidget()));
And here is another way to do it:
My url pattern: www.app.com/#/xLZppqzSiSxaFu4PB7Ui
onGenerateRoute: (settings) {
List<String> pathComponents = settings.name.split('/');
if (pathComponents[1] == 'invoice') {
return MaterialPageRoute(
builder: (context) {
return Invoice(arguments: pathComponents.last);
},
);
} else
return MaterialPageRoute(
builder: (context) {
return LandingPage();
},
);
;
},
Here's a workaround that uses the 'default' route as my main route.
I did this because it seems to be the only way that Flutter will allow me to open a URL with an ID in it, that doesn't return a 404.
E.g. Flutter does not seem to respect the '?' separator. So a URL with an ID in it, is read by flutter as an unknown URL. E.g. site.com/invoice?id=999 will return a 404, even in /invoice is set up as route.
My goal: I have a 1-page web app that simply displays a single invoice at a time, which corresponds to the ID in the URL.
My URL
app.com/#/xLZppqzSiSxaFu4PB7Ui
The number at the end of the URL is a FireStore Doc ID.
Here's the code in MyApp:
onGenerateRoute: (settings) {
List<String> pathComponents = settings.name.split('/');
switch (settings.name) {
case '/':
return MaterialPageRoute(
builder: (context) => Invoice(),
);
break;
default:
return MaterialPageRoute(
builder: (context) => Invoice(
arguments: pathComponents.last,
),
);
}
},
This sends 'xLZppqzSiSxaFu4PB7Ui' to the 'Invoice' widget.
Try onGenerateRoute with below sample
final info = settings.arguments as Mediainfo?;
settings = settings.copyWith(
name: settings.name! + "?info=" + info!.name, arguments: info);
return MaterialPageRoute(
builder: (_) => MediaDetails(info: info), settings: settings);
This was my solution:
First, kind of seperate, I have an abstract class, AppRoutes, which is just a collection of string-routes, that way they're easily maintainable and switchable.
abstract class AppRoutes {
static const String guestGetMember = "/guest_getMember";
...
static render(String url, {Map<String, dynamic>? params}) {
return Uri(path: url, queryParameters: params ?? {}).toString();
}
}
Now for the code:
Route<dynamic> generateRoute(RouteSettings settings) {
Uri uri = Uri.parse(settings.name ?? "");
Map<String, dynamic> params = {};
// Convert numeric values to numbers. This is optional.
// You can instead `int.parse` where needed.
uri.queryParameters.forEach((key, value) {
params[key] = int.tryParse(value) ?? value;
});
final Map<dynamic, dynamic> arguments = (settings.arguments ?? {}) as Map<dynamic, dynamic>;
return MaterialPageRoute(builder: (context) {
switch (uri.path) {
case AppRoutes.guestGetMember:
return CardGuestViewProfile(memberID: params['memberID']!);
case AppRoutes...:
return...;
default:
return AppScreen();
}
// Navigator routes update web URLs by default,
// while `onGeneratedRoute` does not. That last
// line forces it to. The whole of using url
// variables for me was so that certainly URLs
// were easily copiable for sharing.
}, settings: (RouteSettings(name: settings.name)));
}
And then I call it with
Navigator.pushNamed(context,
AppRoutes.render(AppRoutes.guestGetMember,
params: {'memberID': memberID.toString()}),
arguments: {}));
params will be easily visible to web-users because it's a URL variable, while arguments will not be. This of course doesn't mean that arguments is by any means secure, it just means that non-essential information can be passed through this.