Please anyone suggest a way to secure "auto_route" routes using "flutter_bloc". In the above example My bloc state has been changed i.e. "authenticated" (Center text has been change to authenticated) But auth_guard never push route. Anyone help.
app_widget.dart
class AppWidget extends StatelessWidget {
AppWidget({Key? key}) : super(key: key);
final _appRouter = getIt<AppRouter>();
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
routerDelegate: _appRouter.delegate(),
routeInformationParser: _appRouter.defaultRouteParser(),
builder: (context, child) => BlocProvider(
create: (context) => getIt<UserAuthenticationBloc>(),
child: child,
),
);
}
}
user_authentication_page.dart
class UserAuthenticationPage extends StatelessWidget {
const UserAuthenticationPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocConsumer<UserAuthenticationBloc, UserAuthenticationState>(
listener: (context, state) {
state.maybeMap(
orElse: () => null,
authenticated: (_) => context.router.push<bool>(const HomeRoute()),
);
},
builder: (context, state) {
return BlocBuilder<UserAuthenticationBloc, UserAuthenticationState>(
builder: (context, state) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Text(
state.map(
authenticated: (_) => "authenticated",
unAuthenticated: (_) => "unAuthenticated",
loading: (_) => "loading",
),
),
),
Align(
alignment: FractionalOffset.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.maxFinite,
margin: const EdgeInsets.only(bottom: 24.0),
child: ElevatedButton(
onPressed: () => context
.read<UserAuthenticationBloc>()
.add(
const UserAuthenticationEvent.requestLogin()),
child: const Text('Get Started'),
style: ButtonStyle(
shape: MaterialStateProperty.resolveWith(
(_) => const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
),
),
),
),
),
),
if (state == const UserAuthenticationState.loading()) ...[
SizedBox(height: MediaQuery.of(context).size.height * 0.01),
const LinearProgressIndicator(value: null),
],
],
),
);
},
);
},
);
}
}
user_authentication_bloc.dart
@injectable
class UserAuthenticationBloc
extends Bloc<UserAuthenticationEvent, UserAuthenticationState> {
UserAuthenticationBloc(this._userAuthenticationRepository)
: super(
const UserAuthenticationState.unAuthenticated(),
) {
on<_RequestLogin>(_requestLogin);
}
final IUserAuthenticationRepository _userAuthenticationRepository;
void _requestLogin(
_RequestLogin event, Emitter<UserAuthenticationState> emit) async {
emit(const UserAuthenticationState.loading());
return emit(await _userAuthenticationRepository
.redirectToLogin()
.then(
(value) => value.fold(
(l) => const UserAuthenticationState.unAuthenticated(),
(r) => const UserAuthenticationState.authenticated(),
),
)
.catchError((_) => const UserAuthenticationState.unAuthenticated()));
}
}
router.dart
@MaterialAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AutoRoute(
path: '/login',
page: UserAuthenticationPage,
),
AutoRoute(
path: '/',
page: HomePage,
guards: [AuthGuard],
children: [
AutoRoute(
path: 'dashboard',
name: 'dashboardRouter',
page: EmptyRouterPage,
children: [
AutoRoute(
path: '',
page: DashboardPage,
),
],
),
AutoRoute(
path: 'notifications',
name: 'notificationRouter',
page: EmptyRouterPage,
children: [
AutoRoute(
path: '',
page: NotificationPage,
),
],
),
AutoRoute(
path: 'settings',
name: 'settingsRouter',
page: EmptyRouterPage,
children: [
AutoRoute(
path: '',
page: SettingsPage,
),
],
),
],
)
],
)
class $AppRouter {}
auth_guard.dart
@injectable
class AuthGuard extends AutoRouteGuard {
final UserAuthenticationBloc userAuthenticationBloc;
AuthGuard(this.userAuthenticationBloc);
@override
void onNavigation(NavigationResolver resolver, StackRouter router) {
userAuthenticationBloc.state.map(
loading: (_) => null,
unAuthenticated: (_) => router.push(const UserAuthenticationRoute()),
authenticated: (_) => resolver.next(),
);
}
}
Solution 1: Dagmawi Asfaw
The reason it doesn't navigate is because it is not getting the latest updated state. In order to get that you would have to listen to the state stream.
@override
void onNavigation(NavigationResolver resolver, StackRouter router) {
userAuthenticationBloc.stream.listen((state) {
if (state is authenticated && !resolver.isResolved) {
// TODO: ROUTE TO THE PAGE YOU WANT TO GO TO
resolver.next(true);
}
},);
}