modular icon indicating copy to clipboard operation
modular copied to clipboard

flutter_modular - Navigation open two pages in same time

Open thobiassilva opened this issue 2 years ago • 11 comments

When we click on two points on the screen simultaneously to do navigation (with Modular.pushNamed ), it opens two pages together.

Using flutter's native navigation, the problem doesn't happen

How can I deal with this?

https://user-images.githubusercontent.com/39360514/191567777-cd4ac566-3973-4b9e-a185-fbb91ae8c330.mp4

thobiassilva avatar Sep 21 '22 17:09 thobiassilva

I found a way to solve it, but I don't know if it's the best

I added a variable to control the current state pushing, I change it to true after starting the navigation, and at the end I change it to false again.


  @override
  Future<T?> pushNamed<T extends Object?>(String routeName,
      {Object? arguments, bool forRoot = false}) async {
    if (pushing) return null;
    pushing = true;

    final popComplete = Completer();
    var book = await parser.selectBook(routeName,
        arguments: arguments, popCallback: popComplete.complete);
    if (forRoot) {
      book = currentConfiguration!.copyWith(routes: [
        ...currentConfiguration!.routes,
        book.routes.last.copyWith(schema: '')
      ]);
      await setNewRoutePath(book);
    } else {
      final list = [...currentConfiguration!.routes];

      for (var route in book.routes.reversed) {
        if (list
                .firstWhere(
                    (element) => element.uri.toString() == route.uri.toString(),
                    orElse: () => ParallelRoute.empty())
                .name ==
            '') {
          list.add(route);
        }
      }

      if (currentConfiguration!.routes.length == list.length) {
        list.add(book.routes.last);
      }

      await setNewRoutePath(book.copyWith(routes: list));
    }

    pushing = false;
    return await popComplete.future;
  }

What do you think?

thobiassilva avatar Sep 21 '22 21:09 thobiassilva

Any updates?

develogo avatar Aug 04 '23 17:08 develogo

This error persist on v6?

jacobaraujo7 avatar Aug 09 '23 18:08 jacobaraujo7

This error persist on v6?

Yes, i did the test on v6 and the problem persists.

develogo avatar Aug 09 '23 18:08 develogo

Do you have any examples?

jacobaraujo7 avatar Aug 09 '23 22:08 jacobaraujo7

Do you have any examples?

When clicking both buttons at the same time, both navigations are performed, something that doesn't happen with the standard navigation.

Modular

https://github.com/Flutterando/modular/assets/18041980/d152af1b-fdf3-4dbd-a363-306498e31782

Flutter navigation

https://github.com/Flutterando/modular/assets/18041980/567f0d38-e27d-4e69-a6bc-225777fb4c7d

develogo avatar Aug 09 '23 22:08 develogo

Flutter Modular

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: [
          Positioned(
            top: 100,
            child: ElevatedButton(
              onPressed: () {
                Modular.to.pushNamed('/test1');
              },
              child: const Icon(Icons.remove),
            ),
          ),
          Positioned(
            bottom: 100,
            child: ElevatedButton(
              onPressed: () {
                Modular.to.pushNamed('/test2');
              },
              child: const Icon(Icons.add),
            ),
          ),
        ],
      ),
    );
  }
}

Flutter Navigation

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: [
          Positioned(
            top: 100,
            child: ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => const SecondPage(),
                  ),
                );
              },
              child: const Icon(Icons.remove),
            ),
          ),
          Positioned(
            bottom: 100,
            child: ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => const ThirdPage(),
                  ),
                );
              },
              child: const Icon(Icons.add),
            ),
          ),
        ],
      ),
    );
  }

develogo avatar Aug 09 '23 23:08 develogo

This error persist on v6?

I looked at the current code and it follows the same without changes. What do you think of my previous suggestion? I based it on the navigator that uses status to validate

thobiassilva avatar Aug 09 '23 23:08 thobiassilva

Flutter Modular

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: [
          Positioned(
            top: 100,
            child: ElevatedButton(
              onPressed: () {
                Modular.to.pushNamed('/test1');
              },
              child: const Icon(Icons.remove),
            ),
          ),
          Positioned(
            bottom: 100,
            child: ElevatedButton(
              onPressed: () {
                Modular.to.pushNamed('/test2');
              },
              child: const Icon(Icons.add),
            ),
          ),
        ],
      ),
    );
  }
}

Flutter Navigation

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: [
          Positioned(
            top: 100,
            child: ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => const SecondPage(),
                  ),
                );
              },
              child: const Icon(Icons.remove),
            ),
          ),
          Positioned(
            bottom: 100,
            child: ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => const ThirdPage(),
                  ),
                );
              },
              child: const Icon(Icons.add),
            ),
          ),
        ],
      ),
    );
  }

Can you provide a complete example?

jacobaraujo7 avatar Aug 10 '23 16:08 jacobaraujo7

I'm running into this issue as well. This issue has been the most painful of all because users can open multiple items on a listview and open multiple navigations. Even if this issue is fixed on some recent version, I won't be able to migrate because there is not enough documentation for migration from v5 to v6 as for the scenarios mentioned in this issue #901.

Z3rolive avatar Oct 04 '23 01:10 Z3rolive

@jacobaraujo7 Can you provide a complete example?

Flutter Standard Navigation:

import 'package:flutter/material.dart';

void main() {
  runApp(const AppWidget());
}

class AppWidget extends StatelessWidget {
  const AppWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: {
        '/': (context) => const HomePage(),
        '/first': (context) => const FirstPage(),
        '/second': (context) => const SecondPage(),
      },
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Column(
        children: [
          Expanded(
            child: GestureDetector(
              onTap: () async {
                print('TAP 1');
                Navigator.pushNamed(context, '/first');
              },
              child: Container(color: Colors.blue),
            ),
          ),
          Expanded(
            child: GestureDetector(
              onTap: () async {
                print('TAP 2');
                Navigator.pushNamed(context, '/second');
              },
              child: Container(color: Colors.red),
            ),
          ),
        ],
      ),
    ));
  }
}

class FirstPage extends StatelessWidget {
  const FirstPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Return 1'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  const SecondPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Return 2'),
        ),
      ),
    );
  }
}

Modular Navigation:

import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';

void main() {
  runApp(ModularApp(module: AppModule(), child: const AppWidget()));
}

class AppWidget extends StatelessWidget {
  const AppWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: Modular.routerConfig,
    );
  }
}

class AppModule extends Module {
  @override
  void binds(i) {}

  @override
  void routes(r) {
    r.child('/', child: (context) => const HomePage());
    r.child('/first', child: (context) => const FirstPage());
    r.child('/second', child: (context) => const SecondPage());
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Column(
        children: [
          Expanded(
            child: GestureDetector(
              onTap: () {
                print('TAP 1');
                Modular.to.pushNamed('/first');
              },
              child: Container(color: Colors.blue),
            ),
          ),
          Expanded(
            child: GestureDetector(
              onTap: () async {
                print('TAP 2');
                Modular.to.pushNamed('/second');
              },
              child: Container(color: Colors.red),
            ),
          ),
        ],
      ),
    ));
  }
}

class FirstPage extends StatelessWidget {
  const FirstPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => Modular.to.pop(),
          child: const Text('Return 1'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  const SecondPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => Modular.to.pop(),
          child: const Text('Return 2'),
        ),
      ),
    );
  }
}

eduardoflorence avatar Oct 25 '23 15:10 eduardoflorence