slovnicki / beamer

A routing package built on top of Router and Navigator's pages API, supporting arbitrary nested navigation, guards and more.
MIT License
591 stars 129 forks source link

Doing a pop removes all pages from the stack, not just the last one #585

Open mladjomilunovic opened 1 year ago

mladjomilunovic commented 1 year ago

I am new to beamer, so sorry if this is obvious.

I have my locations defined with the following class:

class BeamerLocations extends BeamLocation<BeamState> {
  BeamerLocations(RouteInformation routeInformation) : super(routeInformation);

  @override
  List<Pattern> get pathPatterns => [
        '/login',
        '/register',
      ];

  @override
  List<BeamPage> buildPages(BuildContext context, BeamState state) {
    return [
      if (state.uri.pathSegments.contains('register') ||
          state.uri.pathSegments.contains('login'))
        const BeamPage(
          key: ValueKey('login'),
          title: 'Login',
          child: LoginPage(),
        ),
      if (state.uri.pathSegments.contains('register'))
        const BeamPage(
          key: ValueKey('register'),
          title: 'Register',
          child: RegisterPage(),
        ),
    ];
  }
}

Now when I go to register i see that my page stack is ['login', 'register']. When i press the back button in the AppBar(which based on documentation should just pop the last page) my page is stack is empty instead of just ['login'] and i get an exception "The Navigator.pages must not be empty to use the Navigator.pages API".

Any idea what am I doing wrong?

Thank you and again sorry if it's something obvious!

felipe-xavier commented 1 year ago

@mladjomilunovic I think this is because the path is just one segment, like just 'login' or just 'register', and when you pop, you get '/' which is not set on your pathPatterns.

Maybe adding a fallback to login() page for '/' (which is an empty pathSegment) could solve it: I haven't tested it but I hope it gives some idea

class BeamerLocations extends BeamLocation<BeamState> {
  BeamerLocations(RouteInformation routeInformation) : super(routeInformation);

  @override
  List<Pattern> get pathPatterns => [
        '/',
        '/login',
        '/register',
      ];

  @override
  List<BeamPage> buildPages(BuildContext context, BeamState state) {
    return [

      if (state.uri.pathSegments.contains('login') || state.uri.pathSegments.isEmpty)
        const BeamPage(
          key: ValueKey('login'),
          title: 'Login',
          child: LoginPage(),
        ),
      if (state.uri.pathSegments.contains('register'))
        const BeamPage(
          key: ValueKey('register'),
          title: 'Register',
          child: RegisterPage(),
        ),
    ];
  }
}
mladjomilunovic commented 1 year ago

@felipe-xavier I kinda get what you are saying, but I don't think that's what I want. I if you see my page stack when I am on register page i have ['login', 'register']. Popping from there should mean I have ['login'] left. Isn't the point of building a stack explicitly so Beamer can know where to go back? In my case I would like when I am on /register that my pop takes me to /login. I have fixed it by adding popToNamed parameter. I also tried /login/register without popToNamed and it didn't work(altough I would prefer not to go in that way).

My point is if I am build a stack of pages explicitly using buildPages it seems reduntant that I have to specify how to pop a page from the stack using popToName instead of justing popping the last page.

But I think I get it, you are saying that Beamer performs it's operations only on the path string, without regards of the actual stack being built?

shilangyu commented 1 year ago

But I think I get it, you are saying that Beamer performs it's operations only on the path string, without regards of the actual stack being built?

This sounds very backwards to me. Isn't the whole point of the page stack to decide what is the order of pages?

I am facing a similar issue. If my page stack is:

- /store/:storeId
- /store/:storeId/book/:bookId

And I perform a pop, instead of ending up in /store/:storeId, I end up in /store/:storeId/book which is not a valid page. So the last URI segment was popped, not the page. Is there any page stack based pop available?