Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent Redirect() behavior in Indexed Pages navigation #321

Open
maikeriva opened this issue Jan 31, 2023 · 0 comments
Open

Inconsistent Redirect() behavior in Indexed Pages navigation #321

maikeriva opened this issue Jan 31, 2023 · 0 comments

Comments

@maikeriva
Copy link

In my android app I am using Routemaster for navigation and Riverpod for state management.

The app starts off on an Indexed Page with a bottom bar, which provides access to two subpaths. One of them should be only accessible if the user is logged in, else he should be redirected to a login page. This is accomplished through Route-swapping as described in the FAQ here (https://github.com/tomgilder/routemaster#swap-routing-map), but using Riverpod rather than Provider.

I experience inconsistent behaviour of the Redirect() route, as sometimes it is rendered INSIDE the Indexed page stack, and sometimes OUTSIDE. I would like to achieve a consistent behaviour.

Check out this simplified sample then read the sample flow further below.

Sample app:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:routemaster/routemaster.dart';

final isLoggedInProvider = StateProvider((ref) => false);

final routerMapProvider = Provider((ref) {
  final isLoggedIn = ref.watch(isLoggedInProvider);
  return RouteMap(
    routes: {
      '/': (_) => const IndexedPage(
            child: Home(),
            paths: [
              '/path1',
              '/path2',
            ],
          ),
      '/path1': (_) => const MaterialPage(child: Path1()),
      '/path2': (_) => isLoggedIn
          ? const MaterialPage(child: Path2())
          : const Redirect('/login'),
      '/login': (_) => isLoggedIn
          ? const Redirect('/path1')
          : const MaterialPage(child: Login()),
    },
  );
});

main() {
  runApp(const ProviderScope(child: App()));
}

class App extends ConsumerWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) => MaterialApp.router(
        title: 'Demo',
        routerDelegate: RoutemasterDelegate(
          routesBuilder: (context) => ref.watch(routerMapProvider),
        ),
        routeInformationParser: const RoutemasterParser(),
      );
}

class Home extends ConsumerWidget {
  const Home({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final indexedPageStack = IndexedPage.of(context);
    return Scaffold(
      body: PageStackNavigator(
        stack: indexedPageStack.currentStack,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.one_k),
            label: 'Path 1',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.two_k),
            label: 'Path 2',
          ),
        ],
        currentIndex: indexedPageStack.index,
        onTap: (index) {
          indexedPageStack.index = index;
        },
      ),
    );
  }
}

class Path1 extends ConsumerWidget {
  const Path1({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) => const Center(
        child: Text("This is always accessible"),
      );
}

class Path2 extends ConsumerWidget {
  const Path2({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) => Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text("Currently logged in (Path 2)"),
          ElevatedButton(
              onPressed: () {
                ref.read(isLoggedInProvider.notifier).state = false;
              },
              child: const Text("Log out")),
        ],
      );
}

class Login extends ConsumerWidget {
  const Login({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) => Scaffold(
        appBar: AppBar(
          title: const Text("Login Page"),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text(
                  "This is the login page, bottom bar SHOULD NOT be visible"),
              ElevatedButton(
                  onPressed: () {
                    ref.read(isLoggedInProvider.notifier).state = true;
                  },
                  child: const Text("Log in")),
            ],
          ),
        ),
      );
}

Sample flow:

  1. The app starts, and the user is NOT logged in.
  2. The user taps on Path 2 and the redirect triggers. The login page is rendered WITHIN the Indexed Page stack (the bottom bar is still visible). I am not sure this is the supposed behaviour, as '/login' is outside the paths in the indexed stack, thus I would expect the login page to be rendered ON TOP of the current page. However, if this is how redirects are supposed to work then it's ok as long as the behavior is consistent.
  3. The user logs in. The route map is swapped and the user is redirected on '/path1'.
  4. The user now choses to log out from '/path1'. The route map is swapped again and the '/login' page REPLACES the Indexed Page stack. No bottom navigation bar is visible anymore. Obviously this is inconsistent with what happened when the user first logged in.
  5. Furthermore, in this situation the behavior of the top-left back button is different than the one obtained by pressing the Android back button. The former returns to '/' (and thus '/path1'), the latter exits the application entirely.

Expected behaviour:

  • For the '/login' page to be consistently rendered as a REPLACEMENT for the Indexed Page stack, as it is not among the specified indexed paths.
  • For the back buttons behaviour to be identical wherever, preferably reverse-cronological.

Thanks for any feedback, hope I am just doing something wrong rather than it being a bug :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant