StreamBuilder is not able to re-route even though condition is true - flutter

I am building Flutter authentication app using firebase. Upon successful login, StreamBuilder gets new data but not redirecting to desired component, instead it stays on login page. Here is the code snippet:
StreamBuilder<UserModel>(
stream: _authService.user,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
return DashboardScreen(snapshot.data);
}
return HomeScreen();
// return snapshot.hasData
// ? DashboardScreen(snapshot.data)
// : HomeScreen();
},
)
The only thing You should know that from HomeScreen user can choose Login or Register option. That will open up new screen(AuthScreen) and on that screen I've Login/Register form. after successful login/Register, it stays on the same page even though snapshot.hasData is true. Is that an issue? Is flutter not able to figure out previous route? I really appreciate some help here.

Imagine routes as a deck of cards, if you route to another screen, that's a new card on top of your current cards.
The StreamBuilder is probably updating just fine, you can check this by refreshing the Flutter Inspector widget tree, seeing there the DashboardScreen. But you won't see it on the screen because the route is on top of it.
After a successful login pop your route and see if works.

Related

StreamBuilder for Amplify Auth State on flutter?

Trying to update BottomNavigationBarItems based on user successful signUp/signIn.
Not an expert in flutter or AWS, but have tried using either of the following to update a bool flag to render _listA or _listB
Amplify.Auth.fetchAuthSession()
Amplify.Auth.getCurrentUser()
The problem I'm having is the BottomNavigationBar renders faster than the above functions and app needs to reload to show the correct bar items.
Is there a solution like the following?
bottomNavigationBar: StreamBuilder<SomeState>(
stream: Amplify.Auth.SomeState,
builder: (context, snapshot) {
return BottomNavigationBar(
...
Any other alternative would be appreciated as well.

Flutter Webview with GoRouter (navigation 2.0) - how to handle back button press

According to this blog, if using Navigator 2.0 and/or (in my case) GoRouter you can no longer override the phone's back button using the "WillPopScope" and onWillPop function call. Navigator 2.0 now uses PopRoute to go back.
This causes an issue when using webview on a flutter page. If the user navigates to another web page within that webview and then clicks the back button on their phone they naturally expect the webview navigate back to the previous web page. But instead it takes the user off that page and back to their previous flutter page.
Is there any way around this? Can I have my back button first check whether there is a controller.canGoBack() like I used to be able to do with the old Navigator system?
I have found a solution. Convoluted, but functional:
I had to create a custom "backButtonDispatcher" and add it to the main.dart MaterialApp.router function
child: Builder(builder: (BuildContext context) {
final router = Provider.of<MainRouter>(context, listen: false).router;
backbuttondispatcher = backButtonDispatcher(router.routerDelegate, settings);
return MaterialApp.router(
routeInformationParser: router.routeInformationParser,
routeInformationProvider: router.routeInformationProvider,
routerDelegate: router.routerDelegate,
backButtonDispatcher: backbuttondispatcher,
.
.
.
I created the new dispatcher in the router folder and called it "backbuttondispatcher.dart.
import 'package:flutter/material.dart';
class backButtonDispatcher extends RootBackButtonDispatcher {
final RouterDelegate _routerDelegate;
final _settings;
backButtonDispatcher(this._routerDelegate,this._settings)
: super();
Future<bool> didPopRoute() async {
//Can user leave the page?
if (!_settings.canLeavePage) {
//no, as the webview widget has flagged canLeavePage as false
_settings.goBackToPreviousWebsite();
return true;
}else{
//yes, perform standard popRoute call
return _routerDelegate.popRoute();
}
}
}
Using a shared class reference (I used "_settings") I store a flag that says whether or not the user has traversed through more than one web page - if TRUE, the back button dispatcher won't go back to a previous route/page and instead call another function (pointer) that handles going back to a previous web page in the webview widget route. But if FALSE, the dispatcher performs it's standard didPopRoute function.
Additionally, on all other routes/pages with a webview, the pointer function and boolean need to reset to null and false. This is not ideal but fortunately there aren't that many pages in the app.
It annoys me that they changed the back button functionality for main route/page navigation but didn't take in to consideration the fact that the back button can also be used for going back to a previous webpage. I understand that we shouldn't really be showing web pages with apps anyway but we lowly developers don't always have the power to deny app requirements from higher up.

How to return some data from a page in flutter using Navigator 2.0?

I'm using flutter navigator 2.0 in my app and I'm trying to return some data from another screen when it pops. Here's the code for the same:
This is what I'm using to push/add a new page. After the user has made changes to the edit profile page, I'm trying to update the data on the existing page (profile page).
appState.currentAction = PageAction(
state: PageState.addPage,
widget: EditProfile(currentUserId: currentUserId),
page: Edit_Profile_PageConfig,
);
After the changes are made on the edit profile page, this is what I'm doing to pop:
appState.currentAction = PageAction(state: PageState.pop);
But I'm not sure how can I pass the data from the edit profile page back to the profile page. In the old navigator style, it was pretty easy to have a then function, like this:
var callBack = await Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => EditProfile( )));
But I'm not sure how to achieve this using Navigator 2.0. I referred to these two references for developing the navigation in the app.
Flutter Navigator 2.0
Google Docs
when calling navigator.pop add your data as a second argument.
Navigator.pop(context, data);

Flutter: Changing Cards in Screen without rebuilding the whole page

I am pretty new to Flutter / Dart and right now, I have a problem. I have a homepage in my App and it displays an AppBar, a BottomNavigationBar and a body. The body is a simple card with content in it. The problem is: I need to be able to display three different cards, depending on the status I get from a server.
So there is the ActiveCard, the InactiveCard and the ErrorCard. The ErrorCard has a Button to go back to the InactiveCard and the ActiveCard as well as the InactiveCard should be wrapped in an Inkwell or similar to start a ride for example.
Now I am wondering: I am not sure how to implement all this. Can I just create three Stateless Widgets for each Card and depending on the server status just "replace" or "change" the body in my homepage? And where can I "control" the current status? Like I said, the Cards need to be clickable and "erase" themselves to make space for the following card (e.g: InactiveTrip gets clicked, now there should be the Card for ActiveTrip, because I started my trip and the user should see that my trip is currently active)
I cant provide code really, because so far I have not really something with will be even close to the result I expect.
Maybe you have some tips and packages I can use.
You can convert the statelessWidget to statefulWidget ans use setState() method.This is
recommended for small application but if your apps have more complexity then you have learn the state Management like provider,bloc pattern or Mvvm architechture.
yes, you can use statelessWidget for this purpose.
and you can use bloc pattern
to manage the page state.
I will use stateless for page and stream for the card content:
//Card model is your data modal
StreamController<Card> _streamController = StreamController();
Card _currentCard = /* default inactivate */;
StreamBuilder<bool>(
stream: _streamController.stream,
initialData: _currentCard,
builder: (BuildContext context, AsyncSnapshot<Card> snapshot) {
//return Container(/*content of your card*/);
},
),
//Everytime you need to change the card content, you sink the new value
_streamController.sink.add(_currentCard = /*new card data modal*/);

Screen does not refresh after a Stream has changed in Flutter

In my Flutter application my '/' route is set to Wrapper(),
In that Wrapper, I have the following:
FirebaseUser user = context.watch<FirebaseUser>();
if (user == null) {
return Authentication();
} else {
return Home();
}
The problem I a having with this code is that if I update the Navigation stack with, for example, Navigator.pushNamed(context, "/login"), the return statement from above does not update the screen.
For instance, after the Authentication() page I redirect to either Login or Register page with Flutter's Navigator. And if the state of the FirebaseUser changes from one of those pages, I do not get redirected to Home() from my Wrapper(). I need to update the screen manually (press back on Android Emulator) and only then will I be redirected to Home().
I am also open to complete 'redesigns' of the structure of my app if needed.
EDIT: Also, do I even need the wrapper? I implemented it to make sure the user get to the right screen, since I did not know if there are any workarounds with the state of the app. Can I get by with just using the navigation without all of the Wrapper nonsense?