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

Popping the last page of the flow should complete the flow #104

Open
alestiago opened this issue Aug 26, 2022 · 1 comment
Open

Popping the last page of the flow should complete the flow #104

alestiago opened this issue Aug 26, 2022 · 1 comment

Comments

@alestiago
Copy link
Contributor

alestiago commented Aug 26, 2022

Is your feature request related to a problem? Please describe.
Since using Navigator.pop() goes back in the flow, it would be nice if this remains consistent even when the flow only has one page. I would expect popping the last page to complete the flow.

Having the above functionality makes nesting FlowBuilders very convenient.

Example
import 'package:flow_builder/flow_builder.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: _HomeFlow()));
}

enum _HomeFlowState {
  home,
  settings,
}

class _HomeFlow extends StatelessWidget {
  const _HomeFlow({Key? key}) : super(key: key);

  static List<Page> _onGeneratePages(_HomeFlowState state, List<Page> pages) {
    switch (state) {
      case _HomeFlowState.home:
        return [_HomePage.page()];
      case _HomeFlowState.settings:
        return [_HomePage.page(), _SettingsFlow.page()];
    }
  }

  @override
  Widget build(BuildContext context) {
    return const FlowBuilder(
      state: _HomeFlowState.home,
      onGeneratePages: _onGeneratePages,
    );
  }
}

class _HomePage extends StatelessWidget {
  const _HomePage({Key? key}) : super(key: key);

  static Page<void> page() => const MaterialPage<void>(child: _HomePage());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            onPressed: () => context
                .flow<_HomeFlowState>()
                .update((_) => _HomeFlowState.settings),
            icon: const Icon(Icons.settings),
          ),
        ],
      ),
      body: const Center(child: Text('home')),
    );
  }
}

enum _SettingsFlowState {
  settings,
  about,
  support,
}

class _SettingsFlow extends StatelessWidget {
  const _SettingsFlow({Key? key}) : super(key: key);

  static Page<void> page() => const MaterialPage<void>(child: _SettingsFlow());

  static List<Page> _onGeneratePages(
      _SettingsFlowState state, List<Page> pages) {
    switch (state) {
      case _SettingsFlowState.settings:
        return [_SettingsPage.page()];
      case _SettingsFlowState.about:
        return [_SettingsPage.page(), _AboutPage.page()];
      case _SettingsFlowState.support:
        return [_SettingsPage.page(), _SupportPage.page()];
    }
  }

  @override
  Widget build(BuildContext context) {
    return const FlowBuilder(
      state: _SettingsFlowState.settings,
      onGeneratePages: _onGeneratePages,
    );
  }
}

class _SettingsPage extends StatelessWidget {
  const _SettingsPage({Key? key}) : super(key: key);

  static Page<void> page() => const MaterialPage<void>(child: _SettingsPage());

  @override
  Widget build(BuildContext context) {
   // Native pop should also complete the flow.
    return Scaffold(
      appBar: AppBar(
        leading: BackButton(onPressed: () => Navigator.of(context).pop()), // Should complete the flow
        title: const Text('Settings'),
      ),
      body: Center(
        child: Column(
          children: [
            TextButton(
              onPressed: () => context
                  .flow<_SettingsFlowState>()
                  .update((_) => _SettingsFlowState.about),
              child: const Text('About'),
            ),
            TextButton(
              onPressed: () => context
                  .flow<_SettingsFlowState>()
                  .update((_) => _SettingsFlowState.support),
              child: const Text('Support'),
            ),
          ],
        ),
      ),
    );
  }
}

class _AboutPage extends StatelessWidget {
  const _AboutPage({Key? key}) : super(key: key);

  static Page<void> page() => const MaterialPage<void>(child: _AboutPage());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('About')),
      body: const Center(child: Text('About')),
    );
  }
}

class _SupportPage extends StatelessWidget {
  const _SupportPage({Key? key}) : super(key: key);

  static Page<void> page() => const MaterialPage<void>(child: _SupportPage());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Support')),
      body: const Center(child: Text('Support')),
    );
  }
}

Describe the solution you'd like
I would like to have some logic that makes the flow complete whenever the last page of the flow is popped.

Describe alternatives you've considered
N/A

Additional context
N/A

@anjerukare
Copy link

Sorry for offtop, but what is the right way to do nested FlowBuilders?

In the example from @alestiago FlowBuilders are actually nested, but in the examples from the repository Navigator.of(context).push(...) is used to begin some flow. The last one looks like a mix of declarative and imperative approaches, which does not seem quite right.

Is there any cons to the approach that @alestiago uses?

Related:

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

2 participants