Skip to content

Conversation

@ekrem-qb
Copy link

@ekrem-qb ekrem-qb commented Nov 9, 2024

App closes when nested router has no entries, according to code and logic it should pop in parent router but it doesn't. I fixed that behavior.

@Milad-Akarie
Copy link
Owner

@ekrem-qb not sure if I understand the setup you're referring to but I tried and it works fine the way it as?

@ekrem-qb
Copy link
Author

ekrem-qb commented Mar 3, 2025

I use removeLast() instead of pop() to show placeholderof AutoRouter widget after going back on last sub-route in nested navigation and hide last layer of Stack widget in declarative dialog navigation.

Nested Navigation Example Code

import 'package:auto_route/auto_route.dart';
import 'package:example/nested-navigation/nested_navigation.router.gr.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(NestedNavigationApp());
}

class NestedNavigationApp extends StatelessWidget {
  NestedNavigationApp({super.key});

  final nestedRouter = NestedRouter();

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      darkTheme: ThemeData.dark(),
      routerConfig: nestedRouter.config(),
    );
  }
}

@AutoRouterConfig(generateForDir: ['lib/nested-navigation'])
class NestedRouter extends RootStackRouter {
  @override
  List<AutoRoute> get routes => [
        AutoRoute(
          initial: true,
          page: HostRoute.page,
          children: [
            AutoRoute(page: FirstRoute.page, initial: true),
            AutoRoute(page: SecondRoute.page, children: [
              AutoRoute(page: FirstSubRoute.page),
              AutoRoute(page: SecondSubRoute.page),
              AutoRoute(page: ThirdSubRoute.page),
            ]),
          ],
        ),
      ];
}

@RoutePage()
class HostScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Host Screen'),

        /// This will automatically display a back button if the nested router can pop
        leading: AutoLeadingButton(),
      ),
      body: AutoRouter(),
    );
  }
}

@RoutePage()
class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => context.pushRoute(SecondRoute()),
          child: Text('Go to second screen'),
        ),
      ),
    );
  }
}

@RoutePage()
class FirstSubScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (final didPop, final result) {
        if (!didPop && context.mounted) {
          context.router.removeLast();
        }
      },
      child: Scaffold(
        appBar: AppBar(
          leading: AutoLeadingButton(),
        ),
        body: Center(
          child: Text('1'),
        ),
      ),
    );
  }
}

@RoutePage()
class SecondSubScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (final didPop, final result) {
        if (!didPop && context.mounted) {
          context.router.removeLast();
        }
      },
      child: Scaffold(
        appBar: AppBar(
          leading: AutoLeadingButton(),
        ),
        body: Center(
          child: Text('2'),
        ),
      ),
    );
  }
}

@RoutePage()
class ThirdSubScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (final didPop, final result) {
        if (!didPop && context.mounted) {
          context.router.removeLast();
        }
      },
      child: Scaffold(
        appBar: AppBar(
          leading: AutoLeadingButton(),
        ),
        body: Center(
          child: Text('3'),
        ),
      ),
    );
  }
}

@RoutePage()
class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          Flexible(
            flex: 1,
            child: Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Card(
                    child: ListTile(
                      title: Text('Open 1'),
                      onTap: () => context.pushRoute(FirstSubRoute()),
                    ),
                  ),
                  Card(
                    child: ListTile(
                      title: Text('Open 2'),
                      onTap: () => context.pushRoute(SecondSubRoute()),
                    ),
                  ),
                  Card(
                    child: ListTile(
                      title: Text('Open 3'),
                      onTap: () => context.pushRoute(ThirdSubRoute()),
                    ),
                  ),
                ],
              ),
            ),
          ),
          Flexible(
            flex: 2,
            child: Card.outlined(
              child: AutoRouter(
                placeholder: (context) {
                  return Center(
                    child: Text('No route selected'),
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Nested Navigation Example Video

screen-20250303-041409.2.mp4

The declarative dialog navigation example is a bit longer, but I can send it if needed.

@mrverdant13
Copy link

What do the introduced changes actually imply?
Looks like there is no effective updates on the codebase behaviour.
Is the use of SynchronousFuture the root of the reported issue?
If so, maybe some tests would also help avoiding a regression.

@ekrem-qb
Copy link
Author

ekrem-qb commented Mar 8, 2025

@mrverdant13 The problem is that it immediately returns false and doesn't try to pop the parent navigator when child navigator is null.

P.S. It could be language barrier but why does your comment looks like AI nonsense? And why did you leave dislike on my PR?

@mrverdant13
Copy link

The problem is that it immediately returns false and doesn't try to pop the parent navigator when child navigator is null

Makes sense. Apologies for the confusion here.


why does your comment looks like AI nonsense?

Yeah, sorry about that. English is not my native language.

why did you leave dislike on my PR?

Sorry about that too. I totally messed up 🤦🏼‍♂️. I was trying to react with 👀 instead of 👎🏼

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

Successfully merging this pull request may close these issues.

3 participants