I have a flutter app wherein user can come to home screen via 3 ways: signup, signin or user is already signedin (config bloc). When any of the flow returns a success state (have used bloc for that) i store the value of user in a User object. And then I route to home page which is 0th tab from amongst 4 tabs. I am using go_router package for navigation like so:
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return MainWrapper(navigationShell: navigationShell);
},
branches: <StatefulShellBranch>[
/// Branch Home
StatefulShellBranch(
navigatorKey: _shellNavigatorHome,
routes: <RouteBase>[
GoRoute(
path: "/home",
name: "home",
builder: (BuildContext context, GoRouterState state) {
return HomeScreen();
}),
],
),
// / Branch Notifications
StatefulShellBranch(
navigatorKey: _shellNavigatorBookings,
routes: <RouteBase>[
GoRoute(
path: "/bookings",
name: "bookings",
builder: (BuildContext context, GoRouterState state) {
return BookingsScreen();
}),
],
),
// / Branch favourites
StatefulShellBranch(
navigatorKey: _shellNavigatorFavourites,
routes: <RouteBase>[
GoRoute(
path: "/favourites",
name: "favourites",
builder: (BuildContext context, GoRouterState state) {
return FavouritesScreen();
}),
],
),
/// Branch Profile
StatefulShellBranch(
navigatorKey: _shellNavigatorProfile,
routes: <RouteBase>[
GoRoute(
path: "/profile",
name: "profile",
builder: (BuildContext context, GoRouterState state) {
return ProfileScreen();
}),
],
),
],
),
Let’s say I want to provide user object to all these screens, can I achieve it? I know how to do it to a single route like so:
GoRoute(
path: AppRoutes.otpVerify,
name: AppRoutes.otpVerify,
pageBuilder: (context, state) {
final extras = state.extra as Map<String, dynamic>?;
final contact = extras?[AppConstants.contact] as String;
final flowType = extras?[AppConstants.flowType] as FlowType;
final user = extras?[AppConstants.user] as User?;
final userID = extras?[AppConstants.userId] as String?;
return CustomTransitionPage<void>(
key: state.pageKey,
child: BlocProvider(
create: (context) => OtpBloc(
otpRepository: OtpRepository(otpVerification: OTPImp())),
child: OtpVerficationScreen(
user: user,
contact: contact,
type: flowType,
userID: userID,
),
),
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) =>
FadeTransition(opacity: animation, child: child),
);
},
),
and adding info as extra
context.push(AppRoutes.otpVerify,
extra: {
AppConstants.contact:
_emailPhoneController.text,
AppConstants.flowType:
FlowType.forgotPassword,
AppConstants.userId:
value.message.userID
});
But how do I provide user to my Main Wrapper? The signin bloc is as follows:
class SignInBloc extends Bloc<SignInEvent, SignInState> {
SignInRepository signInRepository;
User? user;
SignInBloc({required this.signInRepository}) : super(const _Initial()) {
on<_ClickedSignInButton>(_onClickedSignInButton);
}
void _onClickedSignInButton(event, emit) async {
emit(const SignInState.signingIn());
await Future.delayed(const Duration(seconds: 2));
try {
final response = await signInRepository.signUpUser(event.data);
user = response;
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(AppConstants.user, jsonEncode(response!.toJson()));
emit(SignInState.success(
msg: "Welcome ${response.firstname}", user: response));
} catch (e) {
emit(SignInState.failure(error: e.toString()));
}
}
}
Config (user already signed in) bloc and signup bloc are similar to it.
The success states are
user = response;
emit(ConfigState.success(user: user!));
and
user = response;
emit(SignupState.success(
msg: "Welcome ${response.firstname}", user: response));
In all 3 flows, user goes to home page tab, how do I inject object to MainWrapper so that it’s accessible throughout the app?