I'm building a webapp with flutter and Navigator 2.0.
The in app navigation work fine. But as soon as I publish my app on a webserver and try to got to a url that points to a rout in my app the routes aren't loaded and the app starts at the homepage.
For example:
Link I click from outside: https://flutter-project.com/#/contacts/ID6Nx2wTxgFcNW3gvMb2
Location the app opens in the browser: https://flutter-project.com/#/
Is there a way to make this possible so that users can share links to other people and they can open them?
Currenty the only way to open links is to open the webapp and then paste the link in the browserwindow where the app already was started but that is not the behaviour I expect from a webapp. I want to click the link and be right where it points at.
I also have this problem.
This is my web site: patrickferreira.com.br
It has these routes:
/calculadoracelular
/calculadorapc
/robotrader
if you try patrickferreira.com.br and click in one of the items in the fourth section it navigates to the routes as expected
But if you try to land directly on a subpage it throws a broken link error.
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case '/calculadoracelular':
return MaterialPageRoute(builder: (_) => ProductPage(work: tradeSizeCalculatorForMobile));
case '/calculadorapc':
return MaterialPageRoute(builder: (_) => ProductPage(work: tradeSizeCalculatorForDesktop));
case '/robotrader':
return MaterialPageRoute(builder: (_) => ProductPage(work: tradingBot));
default:
return MaterialPageRoute(builder: (_) => const MyHomePage(title: 'Portfólio Patrick Ferreira'));
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Portfólio Patrick Ferreira',
debugShowCheckedModeBanner: false,
theme: ThemeData(
fontFamily: "Ubuntu",
primarySwatch: Colors.deepOrange,
),
onGenerateRoute: (settings) => generateRoute(settings),
initialRoute: '/#',
routes: {
'/': (context) => const MyHomePage(title: 'Portfólio Patrick Ferreira'),
'/calculadorapc': (context) => ProductPage(work: tradeSizeCalculatorForDesktop),
'/calculadoracelular': (context) => ProductPage(work: tradeSizeCalculatorForMobile),
'/robotrader': (context) => ProductPage(work: tradingBot),
},
);
}
}
Related
This is my web site: https://patrickferreira.com.br
It has these routes:
/calculadoracelular
/calculadorapc
/robotrader
I will use the route /robotrader as an example but this happens with any route.
When I run the webapp on localhost I can access a subpage by typing on the browser: localhost:70721/robotrader which is what I expect. But when the site hosted on the web, it shows an error when I try to access the subpage in patrickferreira.com.br/robotrader.
Something weird is that if you access the home page in patrickferreira.com.br, and then access the subpages through there, the browser shows the correct url as patrickferreira.com.br/robotrader
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case '/calculadoracelular':
return MaterialPageRoute(builder: (_) => ProductPage(work: tradeSizeCalculatorForMobile));
case '/calculadorapc':
return MaterialPageRoute(builder: (_) => ProductPage(work: tradeSizeCalculatorForDesktop));
case '/robotrader':
return MaterialPageRoute(builder: (_) => ProductPage(work: tradingBot));
default:
return MaterialPageRoute(builder: (_) => const MyHomePage(title: 'Portfólio Patrick Ferreira'));
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Portfólio Patrick Ferreira',
debugShowCheckedModeBanner: false,
theme: ThemeData(
fontFamily: "Ubuntu",
primarySwatch: Colors.deepOrange,
),
onGenerateRoute: (settings) => generateRoute(settings),
initialRoute: '/#',
routes: {
'/': (context) => const MyHomePage(title: 'Portfólio Patrick Ferreira'),
'/calculadorapc': (context) => ProductPage(work: tradeSizeCalculatorForDesktop),
'/calculadoracelular': (context) => ProductPage(work: tradeSizeCalculatorForMobile),
'/robotrader': (context) => ProductPage(work: tradingBot),
},
);
}
}
I wonder how to manage screen navigation when your app is connected to Firebase.
When my app was offline I used a routes table, but Im not sure how to do now. Could I do as I show with my code below; use a streambuilder that switches between the AuthScreen when logged out and HomeScreen when logged in, and a routes table to switch with the following screens also when signed in.
I tried this approach but when im signing out from another screen than the HomeScreen the user stays signed in.
How can I set up my routes so that the user always signs out independent from which screen the user's currently on.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FlutterApp',
theme: ThemeData(
primarySwatch: Colors.orange,
),
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (
ctx,
userSnapshot,
) {
if (userSnapshot.hasData) {
return HomeScreen();
}
return AuthScreen();
}),
routes: {
Screen1.routeName: (ctx) => Screen1(),
Screen2.routeName: (ctx) => Screen2(),
Screen3.routeName: (ctx) => Screen3(),
Screen4.routeName: (ctx) => Screen4(),
});
}
}
I don't think you're going about this the right way.
They are various ways of doing this. Here's mine.
Firstly, I think you should define an initial route that checks if the user is signed in.
Widget build(BuildContext context) {
return MaterialApp(
title: 'FlutterApp',
theme: ThemeData(
primarySwatch: Colors.orange,
),
initialRoute:
FirebaseAuth.instance.currentUser == null ? "/login" : "/home",
routes: {
"/home": (ctx) => HomeScreen(),
"/login": (ctx) => AuthScreen(),
Screen1.routeName: (ctx) => Screen1(),
Screen2.routeName: (ctx) => Screen2(),
Screen3.routeName: (ctx) => Screen3(),
Screen4.routeName: (ctx) => Screen4(),
});
}
Note: "/home" & "/login" could be whatever you want as long as it's a string.
For logout, you need to replace the current screen with the login page, something like this should do.
Navigator.pushNamedAndRemoveUntil(context, '/login', (route) => false);
I am new to flutter and trying to get this to work. I have a Welcome() page, which has two buttons (SignUp and SignIn), which take you to SignUp() and SignIn() pages. After successfully authenticating, the app should navigate to Home(), but it does not. Neither does it go back to Welcome() page if user logs out. Also, if the app is started and user was already logged in, it doesn't automatically go to Home(), it stays at Welcome(). What am I doing wrong here?
I am using a StreamProvider like so
if (snapshot.connectionState == ConnectionState.done) {
return StreamProvider<User>.value(
value: AuthService().user, child: Wrapper());
}
And my wrapper looks like this:
class Wrapper extends StatelessWidget {
const Wrapper({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
if (user != null)
print(user.id);
else
print("User is null");
return MaterialApp(initialRoute: '/', routes: {
'/': (context) => user == null ? Welcome() : Home(),
'/signup': (context) => SignUp(),
'/signin': (context) => SignIn()
'/profile': (context) => Profile(),
'/edit': (context) => Edit()
});
}
This prints the user ID, which means the user is not null, but it does not navigate to Home().
I'm not dictating you what to do but i will just show you how i usually do.
The concept is simple. When the user successfull login or signup, you must save this information in a shared_preference. It may be like auth : true.
You must also wait on the app launching process to see if the user already login or not and based on that, you can navigate to another screen.
To check at startup if user is authenticated, you must read the auth property you previously added in shared_preference. Look at this code :
void main() async {
var mapp;
var routes = <String, WidgetBuilder>{
'/initialize': (BuildContext context) => Initialize(),
'/register': (BuildContext context) => Register(),
'/home': (BuildContext context) => Home(),
};
print("Initializing.");
WidgetsFlutterBinding.ensureInitialized();
await SharedPreferencesClass.restore("initialized").then((value) {
if (value) {
mapp = MaterialApp(
debugShowCheckedModeBanner: false,
title: 'AppName',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: routes,
home: Home(),
);
} else {
mapp = MaterialApp(
debugShowCheckedModeBanner: false,
title: 'AppName',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: routes,
home: Initialize(),
);
}
});
print("Done.");
runApp(mapp);
}
This code is so self explanatory. You can adapt it to your edge.
To navigate to a new screen it is simple, just use this code :
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
i'm new to flutter ... i created a page and the i linked it to another, but after routing it, i am getting this error whenever i want to click on the buttons on the next page cause i did'nt have the route specified in all the pages. i can i import for all pages?
Another exception was thrown: Could not find a generator for route RouteSettings("/transfer", null) in the _WidgetsAppState.
this was how i specified in the first page...
import 'package:mynewapp/wallet.dart';
import 'package:mynewapp/cards.dart';
void main() => runApp(
MaterialApp(
theme: ThemeData(),
initialRoute: '/',
routes: {
'/': (context) => HomePage(),
'/topup': (context) => TopUp(),
'/transfer': (context) => Transfer(),
'/invest': (context) => Invest(),
'/wallet': (context) => Wallet(),
'/cards': (context) => Cards(),
},
),
);
After a search through Stackoverflow, This works for me
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new TopUp(),
),
);
the problem has been with the calling along, but a new error came up, tho, it works now.....
Another exception was thrown: SocketException: Failed host lookup: 'o.remove.bg' (OS Error: No address associated with hostname, errno = 7)
i don't understand what this error means.
Edit the following line
import 'package:mynewapp/wallet.dart';
import 'package:mynewapp/cards.dart';
void main() => runApp(
MaterialApp(
theme: ThemeData(),
initialRoute: '/',
routes: <String, WidgetBuilder>{//this line
'/home': (BuildContext context) => HomePage(),
'/topup': (BuildContext context) => TopUp(),
'/transfer': (BuildContext context) => Transfer(),
'/invest': (BuildContext context) => Invest(),
'/wallet': (BuildContext context) => Wallet(),
'/cards': (BuildContext context) => Cards(),
},
),
);
routes: <String, WidgetBuilder>{
'/home': (context) => HomePage(),
Use some route name for your homepage().
class HomePage extends StatefulWidget {
static final String routeName = '/home';
Define the same name in the HomePage()
Note: It is not necessary to use a '/' in your routeName.
In the beginning of every screen, don't forget to assign a static variable like this:
static String routeName = "HomeScreen";
The best way to use Named routes is as follows:
Firstly, you need to set an initial route in for your app to start with. you can do that by using the initialRoute attribute of MaterialApp()
runApp(MaterialApp(initialRoute: SplashScreen.routeName,));
Once that is done, setup routes for all the screens present in your app by using routes attribute of MaterialApp().
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: SplashScreen.routeName,
routes: {
SplashScreen.routeName: (context) => SplashScreen(),
HomeScreen.routeName: (context) => HomeScreen(),
LoginScreen.routeName: (context) => LoginScreen(),
}));
Now, your task for setting up Routes is done. All you need to do is write the Navigation code correctly in all the screens.
For example, in the code that I have shared above, if I want to navigate from SplashScreen to HomeScreen, I will write the code as:
Navigator.pushReplacementNamed(context, HomeScreen.routeName);
(or)
Navigator.pushNamed(context, HomeScreen.routeName);
This procedure is a generalized approach which can be used to overcome almost all routing problems.
After a search through Stackoverflow, This works for me
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new TopUp(),
),
);
the problem has been with the calling along.
I want to stay on the same page(such as otpPage)until and unless a condition is verified.
Condition networkutil.verify == "Y".
This is my main.dart
final routes = {
'/':(context)=> SignIn() ,
'/SignIn': (context)=> SignIn(),
'/Home': (context)=> Home(),
'/Register': (context) => Register(),
'/OtpPage': (context) => OtpPage()
};
class A extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: './',
routes: routes,
);
}
}
You can use BLoC Pattern, where you will put a condition :
if the user is registered, then Welcome page else, SignIn Page.
Hope you can get some idea from this repo:
https://github.com/samrat19/login_bloc