How to pass data to another bloc - flutter

I have a login block, if the login data is successful, I need the OTP verification request, I need the successful login data to request the verification block. how do i get the data in the verification block?? by implementing a clean architecture

Navigate with named routes and pass it as an argument, put it inside the widget constructor or wrap your MaterialApp with your Bloc to access the instance globally.
You could also work with singletons, service locators, etc. This may also help you https://pub.dev/packages/get_it

Related

Can a cubit inside feature "A" pull from a repository inside feature "B"? Is this bad design?

I'm using a Cubit-repository-datasource design separated by feature.
Title mostly says it all, but to extrapolate: I have an authentication Cubit. It is under the /authentication feature. I have another feature, /posts , that needs an access token from the /authentication feature to send an API request. This token is provided to it from the widget tree (authentication cubit is provided from the top of the widget tree). When a method from /posts's cubit is called: getPosts(int numOfPosts, String accessToken), it takes an access token from the provided widget tree's authentication cubit and passes it to the posts cubit. From here, it sends the request down to the repository layer, then to the data layer.
HOWEVER, what happens if the token is invalid? What happens if it has been tampered with? What happens if it's null? Then, I'd like the token to first be refreshed, and then to repeat the same call for posts using the refreshed access token. However, that "refresh the access token" method is inside the authentication cubit, not the posts cubit. How then should I call it? Can I call the refreshAccessToken() method (inside the /authentication feature's repository or data layer) from inside the repository or data layer of the /posts feature?
Is this sort of "crossing-feature" bad?
Thanks!
I second the comment made by #FabriBertani. The bloc/cubit shouldn't know anything about how to get the posts. It should just do getPosts(int numberOfPosts).
That method should e.g. come from an interface (abstract class in Dart) which in turn is implemented in a different layer (e.g. data/repository/service layer).
That implementation can then in turn handle what is needed to fetch the data from your API. It could e.g. have an authentication service injected to it from where it gets the token.

Flutter navigation auth middleware

I have built an application that uses local auth, I want if a user does not use the software for a long time (whether web or mobile app) I can detect it and take it to the password login page.
I try to use RouteObserver and I write a custom observer but is not good for navigation, it good for log and track.
medium
I know it's possible to add conditions before all my Navigator.push(), but I'm looking for a way to add middleware to all my routes.
use onGenerateRoute named parameter of 'MaterialApp` Widget.

Storing session data in flutter across pages best practice

I have a Flutter app which holds a username and a token to communicate with a web service.
How can I manage the username and token efficiently using best practices? Currently I am writing them into a DB and select them each time I want to do a request.
I tried to use bloc provider flutter bloc with a BlocProvider. I have the states LoggedIn and LoggedOut and the events Login and Logout.
Furthermore, I had a look at
secure storage, but I can't get the data available throughout all pages.
Also, I am not using the firebase API.
Let me know if I should provide some code snippets.
I use SharedPreferences now. The API is very simple and I wrote a wrapper to get rid of the (Strings) keys. Furthermore, the wrapper holds the values for the current session. The advantage of that is, that I can address the values directly instead of needing to read them asynchronously.

How to pass value from one provider to another directly in flutter

I have 2 provider, general provider and blog provider. general provider is called on splash screen and here I normally call API that fetch most common data like blog, category, tags, notification and is stored in general provider. How can I use the same data and populate other provider from the 'general provider' itself ? reason to do so is save number of calls made on the start of the app.

Global dependency on flutter_bloc

I have a problem implementing an app on Flutter using flutter_bloc. I understood the core concepts but I found an "edge case" where there is not examples or guides (at least that I could find):
(I will simplify the problem) I have a bloc called AuthBloc that manages the App. If the state is NotAuthenticated then the App should show the LoginScreen but if is Authenticated the App should show the HomeScreen. Inside the HomeScreen I have 4 blocs, where each bloc has its states and events, but all of them has dependencies on different Repositories to get some data from an API.
All the Repositories need a token to make the API requests. The first problem came here. How can I get the token from all the repositories? If I use a UserRepository to store the token, I will need to pass it as dependency to each Repository (probably works but I don't think its the right way to do it). So, what can be the right way to manage this?
The second problem is:
If somehow I can get the token on all the repositories queries, what happens when the token is revoked? The app should return to the LoginScreen and for that I would need to notify the AuthBloc through an event (for example InvalidTokenEvent). And the AuthBloc should change its state to NotAuthenticated and that will rebuild the LoginScreen. But the question is: How can I notify the AuthBloc from other blocs or repositories? The first idea I had is through dependency injection: I can pass the AuthBloc to every other bloc in the constructor, so when the repository request returns a token expired, the XBloc can call AuthBloc.add(InvalidTokenEvent). But again, if I have a lot of blocs I would need to do that in each bloc. So, what's the right way to do this?
Thank you for any help!
To answer your first problem:
Your repositories should not be handling the API authentication. That should be the job of the data layer under the repository layer.
What I recommend is having one instance of a http client and then provide this instance to all the repositories. This way your client can have an interceptor that handles adding the saved token to all your requests. So your repositories could look something like this:
class OrderRepository {
const OrderRepository(this.httpClient);
final HttpClient httpClient;
}
Then the rest would be as simple as initializing your httpclient then pass it to your repositories which you can provide to your app and blocs by using RepositoryProvider or MultiRepositoryProvider. Then do the same thing with your repositories and blocs passing your repositories to your blocs inside of your blocproviders.
To answer your second problem:
If authenticating and passing your token to all requests can be handled at the http client layer so should unauthenticating and revoking the token. Therefore to reflect this in your authentication state your AuthRepository should listen to your http client and similarly your AuthBloc should listen to your AuthRepository. You can do this by exposing a stream of your authentication status in both your http client and your AuthRepository that gets listened to in your auth bloc.
So it would look like this:
http client gets a 401 error so it removes the token from storage and then adds the unauthenticated status to the stream. This stream is then exposed in auth repository and then in auth bloc have a stream subscription which listens to the authentication status to emit an unauthenticated state.
All the Repositories need a token to make the API requests. The first
problem came here. How can I get the token from all the repositories?
If I use a UserRepository to store the token, I will need to pass it
as dependency to each Repository (probably works but I don't think its
the right way to do it). So, what can be the right way to manage this?
This is not a bad practice to apply (adding it as dependency), but to make it easier, you can use getIt and injectable libraries to have a proper dependency injection solution.
Another way is, adding an interceptor to your networking layer, which is, before making a http request you can intercept your request, add token to your request in that layer and proceed to requesting phase.
Most of the networking libraries has request and response interceptors like below:
Dio
Chopper
But this is not an issue of Bloc library.
If somehow I can get the token on all the repositories queries, what
happens when the token is revoked?
You can add another response interceptor to detect if you have unauthenticated response so you can logout user.
Using getIt, you can gether that bloc from your global dependency container and logout user.