getx icon indicating copy to clipboard operation
getx copied to clipboard

BUG: [GETX] GOING TO ROUTE interacts with a dialog and making invalid route. And the Get.previousRoute cann't back to empty value.

Open SittiphanSittisak opened this issue 3 years ago • 3 comments
trafficstars

It happened when using the Get.toNamed(). It works fine with Navigator.push() but I need Get.toNamed for the web app.

The first page has a button that will show the first dialog. The first dialog will show the order type button list. When pressing an order type button, the program will find a new order of this type and open the second page with a new order data. The second page has some work to do and this work will open the second dialog. After finishing this work, the user will click on the back button back to the first page and find a new order again.

The problem is when the second dialog works on the second page. The first dialog on the first page will not work.

see video example: https://user-images.githubusercontent.com/59549741/184571169-01a030db-59a1-4618-a8c8-003a14e88b10.mp4

web example: web exam github_2502

code example:

import 'package:flutter/material.dart';
import 'package:flutter_test_exam_bug/config/path/page_path.dart';
import 'package:get/get.dart';

Future<void> _showMyDialog({required BuildContext context, required Widget child}) async {
  return showDialog<void>(
    context: context,
    builder: (BuildContext context) => child,
  );
}

class PageTest extends StatefulWidget {
  const PageTest({Key? key}) : super(key: key);

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

class _PageTestState extends State<PageTest> {
  @override
  Widget build(BuildContext context) {
    Widget dialog_ = Center(
            child: ElevatedButton(onPressed: () => Get.toNamed(PagePath.test2), child: const Text("Open second page"))),
        openDialogButton_ = ElevatedButton(
            onPressed: () => _showMyDialog(context: context, child: dialog_), child: const Text("Open first dialog"));

    return Scaffold(body: SafeArea(child: Center(child: openDialogButton_)));
  }
}

class PageTest2 extends StatefulWidget {
  const PageTest2({Key? key}) : super(key: key);

  @override
  State<PageTest2> createState() => _PageTest2State();
}

class _PageTest2State extends State<PageTest2> {
  ButtonStyle buttonStyle = ElevatedButton.styleFrom(primary: Colors.green);

  @override
  Widget build(BuildContext context) {
    Widget dialog_ = Center(
            child: ElevatedButton(
                onPressed: () => Navigator.pop(context), child: const Text("I am second dialog"), style: buttonStyle)),
        openDialogButton_ = ElevatedButton(
            onPressed: () => _showMyDialog(context: context, child: dialog_),
            child: const Text("Open second dialog"),
            style: buttonStyle);

    return Scaffold(appBar: AppBar(), body: SafeArea(child: Center(child: openDialogButton_)));
  }
}

flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.0.5, on Microsoft Windows [Version 10.0.19044.1889], locale th-TH)
[√] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.1.5)
[√] Android Studio (version 2021.2)
[√] VS Code (version 1.70.1)
[√] Connected device (3 available)
[√] HTTP Host Availability

• No issues found!

SittiphanSittisak avatar Aug 15 '22 03:08 SittiphanSittisak

I found the case of this issue. The issue is when opening a dialog, the rouse name will think that is a new route. Assume the previous route is A and the current route is B and the dialog route is C. After opening the dialog, the current route will change from B to C and the previous route will change from A to B. This is a basic step but the c route is a dialog and not defined in GetMaterialApp. So, the C route is equivalent to the B route. At the moment, the previous route is B => Get.previousRoute = B the current route is C => Get.currentRoute= C but C = B then Get.currentRoute= B Did you see that? Even though we used Ger.back the previous route and the current route still B. Then we can go to route B again because the current route is already B! For using ModalRoute.of(context)!.settings.name, this is working successfully but this can't use with Get.context. This is a bug! Please, fix it.

You can see this issue in a new video: https://user-images.githubusercontent.com/59549741/188280286-aa3f0cfe-d63a-4bce-bf9d-433a56e73275.mp4

web example: web exam github_2502

code: main.dart

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_test_exam_bug/page/page_github2502.dart';
import 'package:get/get.dart';

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      scrollBehavior: MyCustomScrollBehavior(),
      initialRoute: "/github_2502",
      getPages: [
        GetPage(name: "/github_2502", page: () => const PageGithub2502()),
        GetPage(name: "/github_2502_Page_2", page: () => const PageGithub2502Page2()),
      ],
    );
  }
}

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}

page_github2502.dart

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

Future<void> _showMyDialog({required BuildContext context, required Widget child}) async {
  return showDialog<void>(
    context: context,
    builder: (BuildContext context) => child,
  );
}

class PageGithub2502 extends StatefulWidget {
  const PageGithub2502({Key? key}) : super(key: key);

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

class _PageGithub2502State extends State<PageGithub2502> {
  @override
  Widget build(BuildContext context) {
    Widget dialog_ = Center(
            child: ElevatedButton(
                onPressed: () async {
                  print("\n--- Before open the second page ---");
                  print("previous route :${Get.previousRoute}");
                  print("current route :${Get.currentRoute}");
                  print("ModalRoute.of(context)!.settings.name: ${ModalRoute.of(context)!.settings.name}");
                  await Get.toNamed("/github_2502_Page_2");
                  print("\n--- After open the second page ---");
                  print("previous route :${Get.previousRoute}");
                  print("current route :${Get.currentRoute}");
                  print("ModalRoute.of(context)!.settings.name: ${ModalRoute.of(context)!.settings.name}");
                },
                child: const Text("Open second page"))),
        openDialogButton_ = ElevatedButton(
            onPressed: () async {
              print("\n+++ Before open a first dialog +++");
              print("previous route :${Get.previousRoute}");
              print("current route :${Get.currentRoute}");
              print("ModalRoute.of(context)!.settings.name: ${ModalRoute.of(context)!.settings.name}");
              await _showMyDialog(context: context, child: dialog_);
              print("\n+++ Before open a first dialog +++");
              print("previous route :${Get.previousRoute}");
              print("current route :${Get.currentRoute}");
              print("ModalRoute.of(context)!.settings.name: ${ModalRoute.of(context)!.settings.name}");
            },
            child: const Text("Open first dialog"));

    return Scaffold(backgroundColor: Colors.brown, body: SafeArea(child: Center(child: openDialogButton_)));
  }
}

class PageGithub2502Page2 extends StatefulWidget {
  const PageGithub2502Page2({Key? key}) : super(key: key);

  @override
  State<PageGithub2502Page2> createState() => _PageGithub2502Page2State();
}

class _PageGithub2502Page2State extends State<PageGithub2502Page2> {
  ButtonStyle buttonStyle = ElevatedButton.styleFrom(primary: Colors.brown);

  @override
  Widget build(BuildContext context) {
    Widget dialog_ = Center(
            child: ElevatedButton(
                onPressed: () => Navigator.pop(context), child: const Text("I am second dialog"), style: buttonStyle)),
        openDialogButton_ = ElevatedButton(
            onPressed: () async {
              print("\n*** Before open a second dialog ***");
              print("previous route :${Get.previousRoute}");
              print("current route :${Get.currentRoute}");
              print("ModalRoute.of(context)!.settings.name: ${ModalRoute.of(context)!.settings.name}");
              await _showMyDialog(context: context, child: dialog_);
              print("\n*** After open a second dialog ***");
              print("previous route :${Get.previousRoute}");
              print("current route :${Get.currentRoute}");
              print("ModalRoute.of(context)!.settings.name: ${ModalRoute.of(context)!.settings.name}");
            },
            child: const Text("Open second dialog"),
            style: buttonStyle);

    return Scaffold(
      appBar: AppBar(backgroundColor: Colors.blueAccent),
      backgroundColor: Colors.blueAccent,
      body: SafeArea(child: Center(child: openDialogButton_)),
    );
  }
}

SittiphanSittisak avatar Sep 03 '22 16:09 SittiphanSittisak

I found more problems. In the situation that Get.previousRoute is empty.

In A page Get.previousRoute = ''; Get.currentRoute= 'A';

Open B page Get.previousRoute = 'A'; Get.currentRoute= 'B';

Using Get.back() back to A page Get.previousRoute = 'A'; Get.currentRoute= 'A';

The problem is the Get.previousRoute doesn't back to empty. You can see this problem in this video: https://user-images.githubusercontent.com/59549741/188297758-ac9c425f-540c-45d3-baa2-966a700808b8.mp4

So, this issue contains 2 bugs with

  1. The Get.previousRoute and Get.currentRoute have interaction with a dialog.
  2. The Get.previousRoute can't go back to empty.

SittiphanSittisak avatar Sep 04 '22 04:09 SittiphanSittisak

I'm also using version 4.6.5 and have the same problem. It seems that this problem has always existed and has not been solved yet

wilhantian avatar Sep 11 '22 03:09 wilhantian

+1

heshesh2010 avatar Oct 29 '22 23:10 heshesh2010

+1

nullhandler avatar Feb 28 '23 10:02 nullhandler

The problem occurs when you use Get.showDialog instead of showDialog?

jonataslaw avatar Feb 28 '23 13:02 jonataslaw

The problem occurs when you use Get.showDialog instead of showDialog?

yes

heshesh2010 avatar Feb 28 '23 13:02 heshesh2010

For me, it doesnt matter whether I use Get.showDialog or showDialog.

Root -> Bottomsheet -> Page1 -> Dialog

Pop 2 times.

Root -> Bottomsheet

Now, cannot go to Page1 since currentRoute is set to Page1

@jonataslaw what is the tag for version 4.6.5, I checked out to both the branch 4.6.5 and tag 4.6.5, it contains some other changes which are not there in pub variant.

nullhandler avatar Feb 28 '23 14:02 nullhandler

I have the same problem, had to use preventDuplicates: false to overcome this

ngthailam avatar Sep 26 '23 15:09 ngthailam