Skip to content

Canonical way for popping outer ImplicitNavigator in nested scenarios #7

Description

@btrautmann

So I'm playing with ImplicitNavigator to get a feel for the sweet spot between imperative APIs and the behemoth that is GoRouter, and one thing I'm not finding intuitive is handling completion of "flows" when in a nested ImplicitNavigator scenario. Given the following "flow":

sealed class RootFlowStep {}

base class Start extends RootFlowStep {}

base class AddFix extends RootFlowStep {}

base class ViewFixDetails extends RootFlowStep {
  final String fixId;

  ViewFixDetails(this.fixId);
}

base class Settings extends RootFlowStep {}

class RootFlow extends StatelessWidget {
  final ValueNotifier<RootFlowStep> _flow = ValueNotifier(Start());
  RootFlow({super.key});

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(value: _flow),
      ],
      child: ImplicitNavigator.fromValueNotifier(
        valueNotifier: _flow,
        builder: (
          BuildContext context,
          RootFlowStep value,
          Animation<double> animation,
          Animation<double> secondaryAnimation,
        ) {
          switch (value) {
            case Start():
              return const FixesPage();
            case AddFix():
              return AddFixFlow(onComplete: () {
                // TODO: Best way to show `Start()` here?
              });
            case ViewFixDetails():
              return FixDetailsFlow(
                fixId: value.fixId,
                onComplete: () {
                  // TODO: Best way to show `Start()` here?
                },
              );
            case Settings():
              return const SettingsPage();
          }
        },
      ),
    );
  }
}

In the above, AddFix and ViewFixDetails() are both "sub-flows" that use their own ImplicitNavigators to show various "screens" that allow users to take action. Once they are "done", onComplete is invoked. It makes sense to me to have the parent flow (in this case RootFlow) own the completion behavior, but doing so is proving to be finicky.

Attempt 1:

Originally I simply did _flow.value = Start() but this results in a new page being added to the stack, such that the resulting stack is:

RootFlow (Start) => AddFixFlow (_) => Start

Attempt 2:

Second, I tried ImplicitNavigator.of(context).pop() but this results in a pop being called on the AddFixFlow's ImplicitNavigator and the user is simply sent back a single page.

Attempt 3:

For funsies, I gave ImplicitNavigator.of(context, root: true).pop() a whirl, but this had no real effect (visually at least)


So, what's the "correct" way to do this, and/or how should I be thinking about this differently?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions