0

I have a LandingScreen which uses NavigationRail on the left and my screens (Home, Live, Settings ...) on the right, but I'm not sure on how to put it all together.

What I want to achieve is:

  • /
  • /login
  • /profileSelecting

then once authenticated and inside the app, the second part of the route (i.e /landing/XX) should change according to the user click on the NavigationRailItem.

  • /landing/home
  • /landing/live
  • /landing/settings ... etc

How can I make this ?

Here's my GoRouter instance:

final goRouterProvider = Provider<GoRouter>((ref) {
  return GoRouter(
    navigatorKey: _rootNavigatorKey,
    debugLogDiagnostics: true,
    initialLocation: Routes.root,
    refreshListenable: ref.watch(authNotifier),
    errorBuilder: (_, state) => NavigationErrorScreen(state.error!),
    routes: [
      GoRoute(
        path: Routes.navigationError,
        name: Routes.navigationError,
        builder: (_, state) => NavigationErrorScreen(state.error!),
      ),
      GoRoute(
        path: Routes.root,
        name: Routes.root,
        redirect: (_, state) {
          final isAuthenticated =
              ref.read(authNotifier.notifier).isAuthenticated;

          if (isAuthenticated) return Routes.profileSelecting;
          return Routes.login;
        },
        builder: (_, __) => const VialisApp(),
      ),
      GoRoute(
        path: Routes.login,
        name: Routes.login,
        builder: (_, __) => const LoginScreen(),
      ),
      GoRoute(
        path: Routes.profileSelecting,
        name: Routes.profileSelecting,
        redirect: (_, state) async {
          final stbAccount = await ref.read(asyncAccountProvider.future);

          final isMultipleProfiles = stbAccount.data.profiles!.length > 1;
          if (isMultipleProfiles) {
            return Routes.profileSelecting;
          }

          return Routes.landing;
        },
        builder: (_, __) => const ProfileSelectionScreen(),
      ),
      ShellRoute(
        navigatorKey: _landingNavigatorKey,
        builder: (context, state, child) => const LandingScreen(child: child),
        routes: [
          GoRoute(
            path: Routes.home,
            name: Routes.home,
            builder: (_, __) => const HomeScreen(),
          ),
          GoRoute(
            path: Routes.live,
            name: Routes.live,
            builder: (_, __) => const LiveScreen(),
          ),
          GoRoute(
            path: Routes.tvGuide,
            name: Routes.tvGuide,
            builder: (_, __) => const TVGuideScreen(),
          ),
          GoRoute(
            path: Routes.weekly,
            name: Routes.weekly,
            builder: (_, __) => const WeeklyGuideScreen(),
          ),
          GoRoute(
            path: Routes.recordings,
            name: Routes.recordings,
            builder: (_, __) => const RecordingsScreen(),
          ),
          GoRoute(
            path: Routes.settings,
            name: Routes.settings,
            builder: (_, __) => const SettingsScreen(),
          ),
        ],
      ),
    ],
  );
});

My LandingScreen looks like this:


class LandingScreen extends ConsumerStatefulWidget {
  final Widget child;
  const LandingScreen({super.key, required this.child});

  @override
  ConsumerState<ConsumerStatefulWidget> createState() => _LandingScreenState();
}

class _LandingScreenState extends ConsumerState<LandingScreen> {
  final double _iconWidth = 24.0;
  final _railItemPadding = const EdgeInsets.only(left: 8.0);

  @override
  void initState() {
    super.initState();

    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
  }

  @override
  Widget build(BuildContext context) {
    final index = ref.watch(landingIndexProvider);

    final currentProfileName = ref.watch(currentProfileStateProvider);
    ref.watch(asyncProfilesProvider(currentProfileName));

    return Scaffold(
      backgroundColor: black,
      body: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Expanded(
            flex: 0,
            child: NavigationRail(
              leading: Image.asset(
                'assets/vialis_logo_operator.png',
                width: 55,
              ),
              extended: true,
              backgroundColor: grey,
              minExtendedWidth: 55,
              minWidth: 55,
              selectedIndex: index,
              useIndicator: true,
              indicatorColor: blue,
              onDestinationSelected: (index) =>
                  ref.read(landingIndexProvider.notifier).updateIndex(index),
              destinations: <NavigationRailDestination>[
                //home
                NavigationRailDestination(
                  padding: _railItemPadding,
                  icon: Icon(Icons.home_filled, color: white, size: _iconWidth),
                  selectedIcon:
                      Icon(Icons.home_filled, color: white, size: _iconWidth),
                  label: const Text(''),
                ),

                //live
                NavigationRailDestination(
                  padding: _railItemPadding,
                  icon: Image.asset('assets/icon_live.webp', width: _iconWidth),
                  selectedIcon:
                      Image.asset('assets/icon_live.webp', width: _iconWidth),
                  label: const Text(''),
                ),

                //tv guide
                NavigationRailDestination(
                  padding: _railItemPadding,
                  icon: Image.asset('assets/icon_guid_tv.webp',
                      width: _iconWidth),
                  selectedIcon: Image.asset('assets/icon_guid_tv.webp',
                      width: _iconWidth),
                  label: const Text(''),
                ),

                //weekly guide
                NavigationRailDestination(
                  padding: _railItemPadding,
                  icon: Image.asset('assets/icon_guid_week.webp',
                      width: _iconWidth),
                  selectedIcon: Image.asset('assets/icon_guid_week.webp',
                      width: _iconWidth),
                  label: const Text(''),
                ),

                //recordings
                NavigationRailDestination(
                  padding: _railItemPadding,
                  icon:
                      Image.asset('assets/icon_record.webp', width: _iconWidth),
                  selectedIcon:
                      Image.asset('assets/icon_record.webp', width: _iconWidth),
                  label: const Text(''),
                ),

                //settings
                NavigationRailDestination(
                  padding: _railItemPadding,
                  icon: Image.asset('assets/icon_gear.webp', width: _iconWidth),
                  selectedIcon:
                      Image.asset('assets/icon_gear.webp', width: _iconWidth),
                  label: const Text(''),
                ),
              ],
            ),
          ),
          Expanded(flex: 7, child: widget.child),
        ],
      ),
    );
  }
}

0 Answers0