Jonny Borges
Committed by GitHub

Merge pull request #2145 from jonataslaw/refactor-nav

Refactor nav
Showing 53 changed files with 2061 additions and 1295 deletions

Too many changes to show.

To preserve performance only 53 of 53+ files are displayed.

@@ -14,11 +14,11 @@ class MyApp extends StatelessWidget { @@ -14,11 +14,11 @@ class MyApp extends StatelessWidget {
14 14
15 @override 15 @override
16 Widget build(BuildContext context) { 16 Widget build(BuildContext context) {
17 - return GetMaterialApp.router( 17 + return GetMaterialApp(
18 debugShowCheckedModeBanner: false, 18 debugShowCheckedModeBanner: false,
19 enableLog: true, 19 enableLog: true,
20 logWriterCallback: Logger.write, 20 logWriterCallback: Logger.write,
21 - // initialRoute: AppPages.INITIAL, 21 + initialRoute: AppPages.INITIAL,
22 getPages: AppPages.routes, 22 getPages: AppPages.routes,
23 locale: TranslationService.locale, 23 locale: TranslationService.locale,
24 fallbackLocale: TranslationService.fallbackLocale, 24 fallbackLocale: TranslationService.fallbackLocale,
@@ -5,13 +5,11 @@ import '../data/home_repository.dart'; @@ -5,13 +5,11 @@ import '../data/home_repository.dart';
5 import '../domain/adapters/repository_adapter.dart'; 5 import '../domain/adapters/repository_adapter.dart';
6 import '../presentation/controllers/home_controller.dart'; 6 import '../presentation/controllers/home_controller.dart';
7 7
8 -class HomeBinding extends Binding { 8 +class HomeBinding extends Bindings {
9 @override 9 @override
10 - List<Bind> dependencies() {  
11 - return [  
12 - Bind.lazyPut<IHomeProvider>(() => HomeProvider()),  
13 - Bind.lazyPut<IHomeRepository>(() => HomeRepository(provider: Get.find())),  
14 - Bind.lazyPut(() => HomeController(homeRepository: Get.find())),  
15 - ]; 10 + void dependencies() {
  11 + Get.lazyPut<IHomeProvider>(() => HomeProvider());
  12 + Get.lazyPut<IHomeRepository>(() => HomeRepository(provider: Get.find()));
  13 + Get.lazyPut(() => HomeController(homeRepository: Get.find()));
16 } 14 }
17 } 15 }
@@ -6,6 +6,7 @@ import 'package:get/get.dart'; @@ -6,6 +6,7 @@ import 'package:get/get.dart';
6 import '../controllers/home_controller.dart'; 6 import '../controllers/home_controller.dart';
7 7
8 class CountryView extends GetView<HomeController> { 8 class CountryView extends GetView<HomeController> {
  9 + const CountryView({Key? key}) : super(key: key);
9 @override 10 @override
10 Widget build(BuildContext context) { 11 Widget build(BuildContext context) {
11 return Container( 12 return Container(
@@ -32,10 +33,11 @@ class CountryView extends GetView<HomeController> { @@ -32,10 +33,11 @@ class CountryView extends GetView<HomeController> {
32 itemBuilder: (context, index) { 33 itemBuilder: (context, index) {
33 final country = controller.state.countries[index]; 34 final country = controller.state.countries[index];
34 return ListTile( 35 return ListTile(
35 - onTap: () { 36 + onTap: () async {
36 //Get.rootDelegate.toNamed('/home/country'); 37 //Get.rootDelegate.toNamed('/home/country');
37 - Get.rootDelegate  
38 - .toNamed('/home/country/details?id=$index'); 38 + final data = await Get.toNamed(
  39 + '/home/country/details?id=$index');
  40 + print(data);
39 }, 41 },
40 trailing: CircleAvatar( 42 trailing: CircleAvatar(
41 backgroundImage: NetworkImage( 43 backgroundImage: NetworkImage(
@@ -2,12 +2,14 @@ import 'dart:ui'; @@ -2,12 +2,14 @@ import 'dart:ui';
2 2
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
4 import 'package:get/get.dart'; 4 import 'package:get/get.dart';
  5 +
5 import '../controllers/home_controller.dart'; 6 import '../controllers/home_controller.dart';
6 7
7 class DetailsView extends GetView<HomeController> { 8 class DetailsView extends GetView<HomeController> {
  9 + const DetailsView({Key? key}) : super(key: key);
8 @override 10 @override
9 Widget build(BuildContext context) { 11 Widget build(BuildContext context) {
10 - final parameter = Get.rootDelegate.parameters; 12 + final parameter = context.params; //Get.parameters;
11 final country = controller.getCountryById(parameter['id'] ?? ''); 13 final country = controller.getCountryById(parameter['id'] ?? '');
12 return Container( 14 return Container(
13 decoration: BoxDecoration( 15 decoration: BoxDecoration(
@@ -76,6 +78,11 @@ class DetailsView extends GetView<HomeController> { @@ -76,6 +78,11 @@ class DetailsView extends GetView<HomeController> {
76 '${country.totalRecovered}', 78 '${country.totalRecovered}',
77 style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold), 79 style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
78 ), 80 ),
  81 + TextButton(
  82 + onPressed: () {
  83 + Get.back(result: 'djsoidjsoidj');
  84 + },
  85 + child: Text('back'))
79 ], 86 ],
80 )), 87 )),
81 ), 88 ),
@@ -4,6 +4,8 @@ import 'package:get/get.dart'; @@ -4,6 +4,8 @@ import 'package:get/get.dart';
4 import '../controllers/home_controller.dart'; 4 import '../controllers/home_controller.dart';
5 5
6 class HomeView extends GetView<HomeController> { 6 class HomeView extends GetView<HomeController> {
  7 + const HomeView({Key? key}) : super(key: key);
  8 +
7 @override 9 @override
8 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
9 return Container( 11 return Container(
@@ -75,7 +77,8 @@ class HomeView extends GetView<HomeController> { @@ -75,7 +77,8 @@ class HomeView extends GetView<HomeController> {
75 shape: StadiumBorder(), 77 shape: StadiumBorder(),
76 ), 78 ),
77 onPressed: () async { 79 onPressed: () async {
78 - await Get.rootDelegate.toNamed('/home/country'); 80 + //await Navigation Get.rootDelegate.toNamed('/home/country');
  81 + Get.toNamed('/home/country');
79 }, 82 },
80 child: Text( 83 child: Text(
81 'fetch_country'.tr, 84 'fetch_country'.tr,
@@ -13,20 +13,21 @@ class AppPages { @@ -13,20 +13,21 @@ class AppPages {
13 13
14 static final routes = [ 14 static final routes = [
15 GetPage( 15 GetPage(
16 - name: Routes.HOME,  
17 - page: () => HomeView(),  
18 - binding: HomeBinding(),  
19 - children: [  
20 - GetPage(  
21 - name: Routes.COUNTRY,  
22 - page: () => CountryView(),  
23 - children: [  
24 - GetPage(  
25 - name: Routes.DETAILS,  
26 - page: () => DetailsView(),  
27 - ),  
28 - ],  
29 - ),  
30 - ]), 16 + name: Routes.HOME,
  17 + page: () => HomeView(),
  18 + bindings: [HomeBinding()],
  19 + children: [
  20 + GetPage(
  21 + name: Routes.COUNTRY,
  22 + page: () => CountryView(),
  23 + children: [
  24 + GetPage(
  25 + name: Routes.DETAILS,
  26 + page: () => DetailsView(),
  27 + ),
  28 + ],
  29 + ),
  30 + ],
  31 + ),
31 ]; 32 ];
32 } 33 }
@@ -4,4 +4,8 @@ abstract class Routes { @@ -4,4 +4,8 @@ abstract class Routes {
4 static const HOME = '/home'; 4 static const HOME = '/home';
5 static const COUNTRY = '/country'; 5 static const COUNTRY = '/country';
6 static const DETAILS = '/details'; 6 static const DETAILS = '/details';
  7 +
  8 + static const DASHBOARD = '/dashboard';
  9 + static const PROFILE = '/profile';
  10 + static const PRODUCTS = '/products';
7 } 11 }
@@ -5,29 +5,31 @@ import '../routes/app_pages.dart'; @@ -5,29 +5,31 @@ import '../routes/app_pages.dart';
5 5
6 class EnsureAuthMiddleware extends GetMiddleware { 6 class EnsureAuthMiddleware extends GetMiddleware {
7 @override 7 @override
8 - Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async { 8 + Future<RouteDecoder?> redirect(RouteDecoder route) async {
9 // you can do whatever you want here 9 // you can do whatever you want here
10 // but it's preferable to make this method fast 10 // but it's preferable to make this method fast
11 // await Future.delayed(Duration(milliseconds: 500)); 11 // await Future.delayed(Duration(milliseconds: 500));
12 12
13 if (!AuthService.to.isLoggedInValue) { 13 if (!AuthService.to.isLoggedInValue) {
14 - final newRoute = Routes.LOGIN_THEN(route.location!);  
15 - return GetNavConfig.fromRoute(newRoute); 14 + final path = route.args.name as String;
  15 + final newRoute = Routes.LOGIN_THEN(path);
  16 +
  17 + return RouteDecoder.fromRoute(newRoute);
16 } 18 }
17 - return await super.redirectDelegate(route); 19 + return await super.redirect(route);
18 } 20 }
19 } 21 }
20 22
21 class EnsureNotAuthedMiddleware extends GetMiddleware { 23 class EnsureNotAuthedMiddleware extends GetMiddleware {
22 @override 24 @override
23 - Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async { 25 + Future<RouteDecoder?> redirect(RouteDecoder route) async {
24 if (AuthService.to.isLoggedInValue) { 26 if (AuthService.to.isLoggedInValue) {
25 //NEVER navigate to auth screen, when user is already authed 27 //NEVER navigate to auth screen, when user is already authed
26 return null; 28 return null;
27 29
28 //OR redirect user to another screen 30 //OR redirect user to another screen
29 - //return GetNavConfig.fromRoute(Routes.PROFILE); 31 + //return RouteDecoder.fromRoute(Routes.PROFILE);
30 } 32 }
31 - return await super.redirectDelegate(route); 33 + return await super.redirect(route);
32 } 34 }
33 } 35 }
@@ -10,19 +10,19 @@ class HomeView extends GetView<HomeController> { @@ -10,19 +10,19 @@ class HomeView extends GetView<HomeController> {
10 return GetRouterOutlet.builder( 10 return GetRouterOutlet.builder(
11 builder: (context, delegate, currentRoute) { 11 builder: (context, delegate, currentRoute) {
12 //This router outlet handles the appbar and the bottom navigation bar 12 //This router outlet handles the appbar and the bottom navigation bar
13 - final currentLocation = currentRoute?.location; 13 + final currentLocation = context.location;
14 var currentIndex = 0; 14 var currentIndex = 0;
15 - if (currentLocation?.startsWith(Routes.PRODUCTS) == true) { 15 + if (currentLocation.startsWith(Routes.PRODUCTS) == true) {
16 currentIndex = 2; 16 currentIndex = 2;
17 } 17 }
18 - if (currentLocation?.startsWith(Routes.PROFILE) == true) { 18 + if (currentLocation.startsWith(Routes.PROFILE) == true) {
19 currentIndex = 1; 19 currentIndex = 1;
20 } 20 }
21 return Scaffold( 21 return Scaffold(
22 body: GetRouterOutlet( 22 body: GetRouterOutlet(
23 initialRoute: Routes.DASHBOARD, 23 initialRoute: Routes.DASHBOARD,
24 // anchorRoute: Routes.HOME, 24 // anchorRoute: Routes.HOME,
25 - key: Get.nestedKey(Routes.HOME), 25 + // key: Get.nestedKey(Routes.HOME),
26 ), 26 ),
27 bottomNavigationBar: BottomNavigationBar( 27 bottomNavigationBar: BottomNavigationBar(
28 currentIndex: currentIndex, 28 currentIndex: currentIndex,
@@ -31,9 +31,8 @@ class LoginView extends GetView<LoginController> { @@ -31,9 +31,8 @@ class LoginView extends GetView<LoginController> {
31 ), 31 ),
32 onPressed: () { 32 onPressed: () {
33 AuthService.to.login(); 33 AuthService.to.login();
34 - final thenTo = Get.rootDelegate.currentConfiguration!  
35 - .currentPage!.parameters?['then'];  
36 - Get.rootDelegate.offNamed(thenTo ?? Routes.HOME); 34 + final thenTo = context.params['then'];
  35 + Get.offNamed(thenTo ?? Routes.HOME);
37 }, 36 },
38 ), 37 ),
39 ], 38 ],
@@ -31,8 +31,7 @@ class ProductsView extends GetView<ProductsController> { @@ -31,8 +31,7 @@ class ProductsView extends GetView<ProductsController> {
31 final item = controller.products[index]; 31 final item = controller.products[index];
32 return ListTile( 32 return ListTile(
33 onTap: () { 33 onTap: () {
34 - Get.rootDelegate  
35 - .toNamed(Routes.PRODUCT_DETAILS(item.id)); 34 + Get.toNamed(Routes.PRODUCT_DETAILS(item.id));
36 }, 35 },
37 title: Text(item.name), 36 title: Text(item.name),
38 subtitle: Text(item.id), 37 subtitle: Text(item.id),
@@ -39,7 +39,8 @@ class ProfileView extends GetView<ProfileController> { @@ -39,7 +39,8 @@ class ProfileView extends GetView<ProfileController> {
39 Get.defaultDialog( 39 Get.defaultDialog(
40 title: 'Test Dialog In Home Outlet !!', 40 title: 'Test Dialog In Home Outlet !!',
41 barrierDismissible: true, 41 barrierDismissible: true,
42 - navigatorKey: Get.nestedKey(Routes.HOME), 42 + id: Routes.HOME,
  43 + // navigatorKey: Get.nestedKey(Routes.HOME),
43 ); 44 );
44 }, 45 },
45 ) 46 )
@@ -21,7 +21,7 @@ class DrawerWidget extends StatelessWidget { @@ -21,7 +21,7 @@ class DrawerWidget extends StatelessWidget {
21 ListTile( 21 ListTile(
22 title: Text('Home'), 22 title: Text('Home'),
23 onTap: () { 23 onTap: () {
24 - Get.rootDelegate.toNamed(Routes.HOME); 24 + Get.toNamed(Routes.HOME);
25 //to close the drawer 25 //to close the drawer
26 26
27 Navigator.of(context).pop(); 27 Navigator.of(context).pop();
@@ -30,7 +30,7 @@ class DrawerWidget extends StatelessWidget { @@ -30,7 +30,7 @@ class DrawerWidget extends StatelessWidget {
30 ListTile( 30 ListTile(
31 title: Text('Settings'), 31 title: Text('Settings'),
32 onTap: () { 32 onTap: () {
33 - Get.rootDelegate.toNamed(Routes.SETTINGS); 33 + Get.toNamed(Routes.SETTINGS);
34 //to close the drawer 34 //to close the drawer
35 35
36 Navigator.of(context).pop(); 36 Navigator.of(context).pop();
@@ -46,7 +46,7 @@ class DrawerWidget extends StatelessWidget { @@ -46,7 +46,7 @@ class DrawerWidget extends StatelessWidget {
46 ), 46 ),
47 onTap: () { 47 onTap: () {
48 AuthService.to.logout(); 48 AuthService.to.logout();
49 - Get.rootDelegate.toNamed(Routes.LOGIN); 49 + Get.toNamed(Routes.LOGIN);
50 //to close the drawer 50 //to close the drawer
51 51
52 Navigator.of(context).pop(); 52 Navigator.of(context).pop();
@@ -61,7 +61,7 @@ class DrawerWidget extends StatelessWidget { @@ -61,7 +61,7 @@ class DrawerWidget extends StatelessWidget {
61 ), 61 ),
62 ), 62 ),
63 onTap: () { 63 onTap: () {
64 - Get.rootDelegate.toNamed(Routes.LOGIN); 64 + Get.toNamed(Routes.LOGIN);
65 //to close the drawer 65 //to close the drawer
66 66
67 Navigator.of(context).pop(); 67 Navigator.of(context).pop();
@@ -10,11 +10,11 @@ class RootView extends GetView<RootController> { @@ -10,11 +10,11 @@ class RootView extends GetView<RootController> {
10 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
11 return GetRouterOutlet.builder( 11 return GetRouterOutlet.builder(
12 builder: (context, delegate, current) { 12 builder: (context, delegate, current) {
13 - final title = current?.location; 13 + final title = context.location;
14 return Scaffold( 14 return Scaffold(
15 drawer: DrawerWidget(), 15 drawer: DrawerWidget(),
16 appBar: AppBar( 16 appBar: AppBar(
17 - title: Text(title ?? ''), 17 + title: Text(title),
18 centerTitle: true, 18 centerTitle: true,
19 ), 19 ),
20 body: GetRouterOutlet( 20 body: GetRouterOutlet(
@@ -29,7 +29,7 @@ class AppPages { @@ -29,7 +29,7 @@ class AppPages {
29 GetPage( 29 GetPage(
30 name: '/', 30 name: '/',
31 page: () => RootView(), 31 page: () => RootView(),
32 - binding: RootBinding(), 32 + bindings: [RootBinding()],
33 participatesInRootNavigator: true, 33 participatesInRootNavigator: true,
34 preventDuplicates: true, 34 preventDuplicates: true,
35 children: [ 35 children: [
@@ -40,19 +40,23 @@ class AppPages { @@ -40,19 +40,23 @@ class AppPages {
40 ], 40 ],
41 name: _Paths.LOGIN, 41 name: _Paths.LOGIN,
42 page: () => LoginView(), 42 page: () => LoginView(),
43 - binding: LoginBinding(), 43 + bindings: [LoginBinding()],
44 ), 44 ),
45 GetPage( 45 GetPage(
46 preventDuplicates: true, 46 preventDuplicates: true,
47 name: _Paths.HOME, 47 name: _Paths.HOME,
48 page: () => HomeView(), 48 page: () => HomeView(),
49 - binding: HomeBinding(), 49 + bindings: [
  50 + HomeBinding(),
  51 + ],
50 title: null, 52 title: null,
51 children: [ 53 children: [
52 GetPage( 54 GetPage(
53 name: _Paths.DASHBOARD, 55 name: _Paths.DASHBOARD,
54 page: () => DashboardView(), 56 page: () => DashboardView(),
55 - binding: DashboardBinding(), 57 + bindings: [
  58 + DashboardBinding(),
  59 + ],
56 ), 60 ),
57 GetPage( 61 GetPage(
58 middlewares: [ 62 middlewares: [
@@ -63,19 +67,19 @@ class AppPages { @@ -63,19 +67,19 @@ class AppPages {
63 page: () => ProfileView(), 67 page: () => ProfileView(),
64 title: 'Profile', 68 title: 'Profile',
65 transition: Transition.size, 69 transition: Transition.size,
66 - binding: ProfileBinding(), 70 + bindings: [ProfileBinding()],
67 ), 71 ),
68 GetPage( 72 GetPage(
69 name: _Paths.PRODUCTS, 73 name: _Paths.PRODUCTS,
70 page: () => ProductsView(), 74 page: () => ProductsView(),
71 title: 'Products', 75 title: 'Products',
72 transition: Transition.zoom, 76 transition: Transition.zoom,
73 - binding: ProductsBinding(), 77 + bindings: [ProductsBinding()],
74 children: [ 78 children: [
75 GetPage( 79 GetPage(
76 name: _Paths.PRODUCT_DETAILS, 80 name: _Paths.PRODUCT_DETAILS,
77 page: () => ProductDetailsView(), 81 page: () => ProductDetailsView(),
78 - binding: ProductDetailsBinding(), 82 + bindings: [ProductDetailsBinding()],
79 middlewares: [ 83 middlewares: [
80 //only enter this route when authed 84 //only enter this route when authed
81 EnsureAuthMiddleware(), 85 EnsureAuthMiddleware(),
@@ -88,7 +92,9 @@ class AppPages { @@ -88,7 +92,9 @@ class AppPages {
88 GetPage( 92 GetPage(
89 name: _Paths.SETTINGS, 93 name: _Paths.SETTINGS,
90 page: () => SettingsView(), 94 page: () => SettingsView(),
91 - binding: SettingsBinding(), 95 + bindings: [
  96 + SettingsBinding(),
  97 + ],
92 ), 98 ),
93 ], 99 ],
94 ), 100 ),
@@ -7,7 +7,6 @@ environment: @@ -7,7 +7,6 @@ environment:
7 7
8 dependencies: 8 dependencies:
9 cupertino_icons: ^1.0.2 9 cupertino_icons: ^1.0.2
10 - effective_dart: 1.3.1  
11 # get: ^4.1.4 10 # get: ^4.1.4
12 get: 11 get:
13 path: ../ 12 path: ../
@@ -7,7 +7,7 @@ export 'get_common/get_reset.dart'; @@ -7,7 +7,7 @@ export 'get_common/get_reset.dart';
7 export 'get_connect/connect.dart'; 7 export 'get_connect/connect.dart';
8 export 'get_core/get_core.dart'; 8 export 'get_core/get_core.dart';
9 export 'get_instance/get_instance.dart'; 9 export 'get_instance/get_instance.dart';
10 -export 'get_navigation/get_navigation.dart'; 10 +export 'get_navigation/get_navigation.dart' hide FirstWhereOrNullExt;
11 export 'get_rx/get_rx.dart'; 11 export 'get_rx/get_rx.dart';
12 export 'get_state_manager/get_state_manager.dart'; 12 export 'get_state_manager/get_state_manager.dart';
13 export 'get_utils/get_utils.dart'; 13 export 'get_utils/get_utils.dart';
@@ -2,11 +2,6 @@ library get_navigation; @@ -2,11 +2,6 @@ library get_navigation;
2 2
3 export 'src/bottomsheet/bottomsheet.dart'; 3 export 'src/bottomsheet/bottomsheet.dart';
4 export 'src/extension_navigation.dart'; 4 export 'src/extension_navigation.dart';
5 -export 'src/nav2/get_information_parser.dart';  
6 -export 'src/nav2/get_nav_config.dart';  
7 -export 'src/nav2/get_navigator.dart';  
8 -export 'src/nav2/get_router_delegate.dart';  
9 -export 'src/nav2/router_outlet.dart';  
10 export 'src/root/get_cupertino_app.dart'; 5 export 'src/root/get_cupertino_app.dart';
11 export 'src/root/get_material_app.dart'; 6 export 'src/root/get_material_app.dart';
12 export 'src/root/internacionalization.dart'; 7 export 'src/root/internacionalization.dart';
@@ -14,6 +9,7 @@ export 'src/root/root_controller.dart'; @@ -14,6 +9,7 @@ export 'src/root/root_controller.dart';
14 export 'src/routes/custom_transition.dart'; 9 export 'src/routes/custom_transition.dart';
15 export 'src/routes/default_route.dart'; 10 export 'src/routes/default_route.dart';
16 export 'src/routes/get_route.dart'; 11 export 'src/routes/get_route.dart';
  12 +export 'src/routes/index.dart';
17 export 'src/routes/observers/route_observer.dart'; 13 export 'src/routes/observers/route_observer.dart';
18 export 'src/routes/route_middleware.dart'; 14 export 'src/routes/route_middleware.dart';
19 export 'src/routes/transitions_type.dart'; 15 export 'src/routes/transitions_type.dart';
@@ -5,16 +5,14 @@ import 'package:flutter/scheduler.dart'; @@ -5,16 +5,14 @@ import 'package:flutter/scheduler.dart';
5 5
6 import '../../get_core/get_core.dart'; 6 import '../../get_core/get_core.dart';
7 import '../../get_instance/src/bindings_interface.dart'; 7 import '../../get_instance/src/bindings_interface.dart';
8 -import '../../get_state_manager/src/simple/get_state.dart';  
9 import '../../get_utils/get_utils.dart'; 8 import '../../get_utils/get_utils.dart';
10 import '../get_navigation.dart'; 9 import '../get_navigation.dart';
11 import 'dialog/dialog_route.dart'; 10 import 'dialog/dialog_route.dart';
12 -import 'root/parse_route.dart';  
13 11
14 /// It replaces the Flutter Navigator, but needs no context. 12 /// It replaces the Flutter Navigator, but needs no context.
15 /// You can to use navigator.push(YourRoute()) rather 13 /// You can to use navigator.push(YourRoute()) rather
16 /// Navigator.push(context, YourRoute()); 14 /// Navigator.push(context, YourRoute());
17 -NavigatorState? get navigator => GetNavigation(Get).key.currentState; 15 +NavigatorState? get navigator => GetNavigationExt(Get).key.currentState;
18 16
19 extension ExtensionBottomSheet on GetInterface { 17 extension ExtensionBottomSheet on GetInterface {
20 Future<T?> bottomSheet<T>( 18 Future<T?> bottomSheet<T>(
@@ -78,6 +76,7 @@ extension ExtensionDialog on GetInterface { @@ -78,6 +76,7 @@ extension ExtensionDialog on GetInterface {
78 Curve? transitionCurve, 76 Curve? transitionCurve,
79 String? name, 77 String? name,
80 RouteSettings? routeSettings, 78 RouteSettings? routeSettings,
  79 + dynamic id,
81 }) { 80 }) {
82 assert(debugCheckHasMaterialLocalizations(context!)); 81 assert(debugCheckHasMaterialLocalizations(context!));
83 82
@@ -110,22 +109,24 @@ extension ExtensionDialog on GetInterface { @@ -110,22 +109,24 @@ extension ExtensionDialog on GetInterface {
110 navigatorKey: navigatorKey, 109 navigatorKey: navigatorKey,
111 routeSettings: 110 routeSettings:
112 routeSettings ?? RouteSettings(arguments: arguments, name: name), 111 routeSettings ?? RouteSettings(arguments: arguments, name: name),
  112 + id: id,
113 ); 113 );
114 } 114 }
115 115
116 /// Api from showGeneralDialog with no context 116 /// Api from showGeneralDialog with no context
117 - Future<T?> generalDialog<T>({  
118 - required RoutePageBuilder pageBuilder,  
119 - bool barrierDismissible = false,  
120 - String? barrierLabel,  
121 - Color barrierColor = const Color(0x80000000),  
122 - Duration transitionDuration = const Duration(milliseconds: 200),  
123 - RouteTransitionsBuilder? transitionBuilder,  
124 - GlobalKey<NavigatorState>? navigatorKey,  
125 - RouteSettings? routeSettings,  
126 - }) { 117 + Future<T?> generalDialog<T>(
  118 + {required RoutePageBuilder pageBuilder,
  119 + bool barrierDismissible = false,
  120 + String? barrierLabel,
  121 + Color barrierColor = const Color(0x80000000),
  122 + Duration transitionDuration = const Duration(milliseconds: 200),
  123 + RouteTransitionsBuilder? transitionBuilder,
  124 + GlobalKey<NavigatorState>? navigatorKey,
  125 + RouteSettings? routeSettings,
  126 + dynamic id}) {
127 assert(!barrierDismissible || barrierLabel != null); 127 assert(!barrierDismissible || barrierLabel != null);
128 - final nav = navigatorKey?.currentState ?? 128 + final key = navigatorKey ?? Get.nestedKey(id)?.navigatorKey;
  129 + final nav = key?.currentState ??
129 Navigator.of(overlayContext!, 130 Navigator.of(overlayContext!,
130 rootNavigator: 131 rootNavigator:
131 true); //overlay context will always return the root navigator 132 true); //overlay context will always return the root navigator
@@ -148,6 +149,7 @@ extension ExtensionDialog on GetInterface { @@ -148,6 +149,7 @@ extension ExtensionDialog on GetInterface {
148 EdgeInsetsGeometry? titlePadding, 149 EdgeInsetsGeometry? titlePadding,
149 TextStyle? titleStyle, 150 TextStyle? titleStyle,
150 Widget? content, 151 Widget? content,
  152 + dynamic id,
151 EdgeInsetsGeometry? contentPadding, 153 EdgeInsetsGeometry? contentPadding,
152 VoidCallback? onConfirm, 154 VoidCallback? onConfirm,
153 VoidCallback? onCancel, 155 VoidCallback? onCancel,
@@ -269,6 +271,7 @@ extension ExtensionDialog on GetInterface { @@ -269,6 +271,7 @@ extension ExtensionDialog on GetInterface {
269 : baseAlertDialog, 271 : baseAlertDialog,
270 barrierDismissible: barrierDismissible, 272 barrierDismissible: barrierDismissible,
271 navigatorKey: navigatorKey, 273 navigatorKey: navigatorKey,
  274 + id: id,
272 ); 275 );
273 } 276 }
274 } 277 }
@@ -474,7 +477,7 @@ extension ExtensionSnackbar on GetInterface { @@ -474,7 +477,7 @@ extension ExtensionSnackbar on GetInterface {
474 } 477 }
475 } 478 }
476 479
477 -extension GetNavigation on GetInterface { 480 +extension GetNavigationExt on GetInterface {
478 /// **Navigation.push()** shortcut.<br><br> 481 /// **Navigation.push()** shortcut.<br><br>
479 /// 482 ///
480 /// Pushes a new `page` to the stack 483 /// Pushes a new `page` to the stack
@@ -499,66 +502,60 @@ extension GetNavigation on GetInterface { @@ -499,66 +502,60 @@ extension GetNavigation on GetInterface {
499 /// 502 ///
500 /// By default, GetX will prevent you from push a route that you already in, 503 /// By default, GetX will prevent you from push a route that you already in,
501 /// if you want to push anyway, set [preventDuplicates] to false 504 /// if you want to push anyway, set [preventDuplicates] to false
502 - Future<T?>? to<T>(  
503 - dynamic page, {  
504 - bool? opaque,  
505 - Transition? transition,  
506 - Curve? curve,  
507 - Duration? duration,  
508 - int? id,  
509 - String? routeName,  
510 - bool fullscreenDialog = false,  
511 - dynamic arguments,  
512 - Binding? binding,  
513 - bool preventDuplicates = true,  
514 - bool? popGesture,  
515 - bool showCupertinoParallax = true,  
516 - double Function(BuildContext context)? gestureWidth,  
517 - }) {  
518 - // var routeName = "/${page.runtimeType}";  
519 - routeName ??= "/${page.runtimeType}";  
520 - routeName = _cleanRouteName(routeName);  
521 - if (preventDuplicates && routeName == currentRoute) {  
522 - return null;  
523 - }  
524 - return global(id).currentState?.push<T>(  
525 - GetPageRoute<T>(  
526 - opaque: opaque ?? true,  
527 - page: _resolvePage(page, 'to'),  
528 - routeName: routeName,  
529 - gestureWidth: gestureWidth,  
530 - showCupertinoParallax: showCupertinoParallax,  
531 - settings: RouteSettings(  
532 - name: routeName,  
533 - arguments: arguments,  
534 - ),  
535 - popGesture: popGesture ?? defaultPopGesture,  
536 - transition: transition ?? defaultTransition,  
537 - curve: curve ?? defaultTransitionCurve,  
538 - fullscreenDialog: fullscreenDialog,  
539 - binding: binding,  
540 - transitionDuration: duration ?? defaultTransitionDuration,  
541 - ),  
542 - ); 505 + Future<T?>? to<T>(Widget Function() page,
  506 + {bool? opaque,
  507 + Transition? transition,
  508 + Curve? curve,
  509 + Duration? duration,
  510 + int? id,
  511 + String? routeName,
  512 + bool fullscreenDialog = false,
  513 + dynamic arguments,
  514 + List<BindingsInterface>? bindings,
  515 + bool preventDuplicates = true,
  516 + bool? popGesture,
  517 + bool showCupertinoParallax = true,
  518 + double Function(BuildContext context)? gestureWidth,
  519 + bool rebuildStack = true,
  520 + PreventDuplicateHandlingMode preventDuplicateHandlingMode =
  521 + PreventDuplicateHandlingMode.ReorderRoutes}) {
  522 + searchDelegate(id).to(
  523 + page,
  524 + opaque: opaque,
  525 + transition: transition,
  526 + curve: curve,
  527 + duration: duration,
  528 + id: id,
  529 + routeName: routeName,
  530 + fullscreenDialog: fullscreenDialog,
  531 + arguments: arguments,
  532 + bindings: bindings,
  533 + preventDuplicates: preventDuplicates,
  534 + popGesture: popGesture,
  535 + showCupertinoParallax: showCupertinoParallax,
  536 + gestureWidth: gestureWidth,
  537 + rebuildStack: rebuildStack,
  538 + preventDuplicateHandlingMode: preventDuplicateHandlingMode,
  539 + );
543 } 540 }
544 541
545 - GetPageBuilder _resolvePage(dynamic page, String method) {  
546 - if (page is GetPageBuilder) {  
547 - return page;  
548 - } else if (page is Widget) {  
549 - Get.log(  
550 - '''WARNING, consider using: "Get.$method(() => Page())" instead of "Get.$method(Page())".  
551 -Using a widget function instead of a widget fully guarantees that the widget and its controllers will be removed from memory when they are no longer used.  
552 - ''');  
553 - return () => page;  
554 - } else if (page is String) {  
555 - throw '''Unexpected String,  
556 -use toNamed() instead''';  
557 - } else {  
558 - throw '''Unexpected format,  
559 -you can only use widgets and widget functions here''';  
560 - }  
561 - } 542 +// GetPageBuilder _resolvePage(dynamic page, String method) {
  543 +// if (page is GetPageBuilder) {
  544 +// return page;
  545 +// } else if (page is Widget) {
  546 +// Get.log(
  547 +// '''WARNING, consider using: "Get.$method(() => Page())" instead of "Get.$method(Page())".
  548 +// Using a widget function instead of a widget fully guarantees that the widget and its controllers will be removed from memory when they are no longer used.
  549 +// ''');
  550 +// return () => page;
  551 +// } else if (page is String) {
  552 +// throw '''Unexpected String,
  553 +// use toNamed() instead''';
  554 +// } else {
  555 +// throw '''Unexpected format,
  556 +// you can only use widgets and widget functions here''';
  557 +// }
  558 +// }
562 559
563 /// **Navigation.pushNamed()** shortcut.<br><br> 560 /// **Navigation.pushNamed()** shortcut.<br><br>
564 /// 561 ///
@@ -592,10 +589,13 @@ you can only use widgets and widget functions here'''; @@ -592,10 +589,13 @@ you can only use widgets and widget functions here''';
592 page = uri.toString(); 589 page = uri.toString();
593 } 590 }
594 591
595 - return global(id).currentState?.pushNamed<T>(  
596 - page,  
597 - arguments: arguments,  
598 - ); 592 + return searchDelegate(id).toNamed(
  593 + page,
  594 + arguments: arguments,
  595 + id: id,
  596 + preventDuplicates: preventDuplicates,
  597 + parameters: parameters,
  598 + );
599 } 599 }
600 600
601 /// **Navigation.pushReplacementNamed()** shortcut.<br><br> 601 /// **Navigation.pushReplacementNamed()** shortcut.<br><br>
@@ -618,21 +618,23 @@ you can only use widgets and widget functions here'''; @@ -618,21 +618,23 @@ you can only use widgets and widget functions here''';
618 String page, { 618 String page, {
619 dynamic arguments, 619 dynamic arguments,
620 int? id, 620 int? id,
621 - bool preventDuplicates = true,  
622 Map<String, String>? parameters, 621 Map<String, String>? parameters,
623 }) { 622 }) {
624 - if (preventDuplicates && page == currentRoute) {  
625 - return null;  
626 - } 623 + // if (preventDuplicates && page == currentRoute) {
  624 + // return null;
  625 + // }
627 626
628 if (parameters != null) { 627 if (parameters != null) {
629 final uri = Uri(path: page, queryParameters: parameters); 628 final uri = Uri(path: page, queryParameters: parameters);
630 page = uri.toString(); 629 page = uri.toString();
631 } 630 }
632 - return global(id).currentState?.pushReplacementNamed(  
633 - page,  
634 - arguments: arguments,  
635 - ); 631 + return searchDelegate(id).offNamed(
  632 + page,
  633 + arguments: arguments,
  634 + id: id,
  635 + // preventDuplicates: preventDuplicates,
  636 + parameters: parameters,
  637 + );
636 } 638 }
637 639
638 /// **Navigation.popUntil()** shortcut.<br><br> 640 /// **Navigation.popUntil()** shortcut.<br><br>
@@ -648,34 +650,10 @@ you can only use widgets and widget functions here'''; @@ -648,34 +650,10 @@ you can only use widgets and widget functions here''';
648 /// or also like this: 650 /// or also like this:
649 /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the 651 /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the
650 /// dialog is closed 652 /// dialog is closed
651 - void until(RoutePredicate predicate, {int? id}) { 653 + void until(bool Function(GetPage<dynamic>) predicate, {int? id}) {
652 // if (key.currentState.mounted) // add this if appear problems on future with route navigate 654 // if (key.currentState.mounted) // add this if appear problems on future with route navigate
653 // when widget don't mounted 655 // when widget don't mounted
654 - return global(id).currentState?.popUntil(predicate);  
655 - }  
656 -  
657 - /// **Navigation.pushAndRemoveUntil()** shortcut.<br><br>  
658 - ///  
659 - /// Push the given `page`, and then pop several pages in the stack until  
660 - /// [predicate] returns true  
661 - ///  
662 - /// [id] is for when you are using nested navigation,  
663 - /// as explained in documentation  
664 - ///  
665 - /// Obs: unlike other get methods, this one you need to send a function  
666 - /// that returns the widget to the page argument, like this:  
667 - /// Get.offUntil(GetPageRoute(page: () => HomePage()), predicate)  
668 - ///  
669 - /// [predicate] can be used like this:  
670 - /// `Get.offUntil(page, (route) => (route as GetPageRoute).routeName == '/home')`  
671 - /// to pop routes in stack until home,  
672 - /// or also like this:  
673 - /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog  
674 - /// is closed  
675 - Future<T?>? offUntil<T>(Route<T> page, RoutePredicate predicate, {int? id}) {  
676 - // if (key.currentState.mounted) // add this if appear problems on future with route navigate  
677 - // when widget don't mounted  
678 - return global(id).currentState?.pushAndRemoveUntil<T>(page, predicate); 656 + return searchDelegate(id).backUntil(predicate);
679 } 657 }
680 658
681 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> 659 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
@@ -698,7 +676,7 @@ you can only use widgets and widget functions here'''; @@ -698,7 +676,7 @@ you can only use widgets and widget functions here''';
698 /// Note: Always put a slash on the route name ('/page1'), to avoid unexpected errors 676 /// Note: Always put a slash on the route name ('/page1'), to avoid unexpected errors
699 Future<T?>? offNamedUntil<T>( 677 Future<T?>? offNamedUntil<T>(
700 String page, 678 String page,
701 - RoutePredicate predicate, { 679 + bool Function(GetPage<dynamic>)? predicate, {
702 int? id, 680 int? id,
703 dynamic arguments, 681 dynamic arguments,
704 Map<String, String>? parameters, 682 Map<String, String>? parameters,
@@ -708,11 +686,13 @@ you can only use widgets and widget functions here'''; @@ -708,11 +686,13 @@ you can only use widgets and widget functions here''';
708 page = uri.toString(); 686 page = uri.toString();
709 } 687 }
710 688
711 - return global(id).currentState?.pushNamedAndRemoveUntil<T>(  
712 - page,  
713 - predicate,  
714 - arguments: arguments,  
715 - ); 689 + return searchDelegate(id).offNamedUntil<T>(
  690 + page,
  691 + predicate: predicate,
  692 + id: id,
  693 + arguments: arguments,
  694 + parameters: parameters,
  695 + );
716 } 696 }
717 697
718 /// **Navigation.popAndPushNamed()** shortcut.<br><br> 698 /// **Navigation.popAndPushNamed()** shortcut.<br><br>
@@ -737,11 +717,11 @@ you can only use widgets and widget functions here'''; @@ -737,11 +717,11 @@ you can only use widgets and widget functions here''';
737 final uri = Uri(path: page, queryParameters: parameters); 717 final uri = Uri(path: page, queryParameters: parameters);
738 page = uri.toString(); 718 page = uri.toString();
739 } 719 }
740 - return global(id).currentState?.popAndPushNamed(  
741 - page,  
742 - arguments: arguments,  
743 - result: result,  
744 - ); 720 + return searchDelegate(id).backAndtoNamed(
  721 + page,
  722 + arguments: arguments,
  723 + result: result,
  724 + );
745 } 725 }
746 726
747 /// **Navigation.removeRoute()** shortcut.<br><br> 727 /// **Navigation.removeRoute()** shortcut.<br><br>
@@ -750,8 +730,8 @@ you can only use widgets and widget functions here'''; @@ -750,8 +730,8 @@ you can only use widgets and widget functions here''';
750 /// 730 ///
751 /// [id] is for when you are using nested navigation, 731 /// [id] is for when you are using nested navigation,
752 /// as explained in documentation 732 /// as explained in documentation
753 - void removeRoute(Route<dynamic> route, {int? id}) {  
754 - return global(id).currentState?.removeRoute(route); 733 + void removeRoute(String name, {int? id}) {
  734 + return searchDelegate(id).removeRoute(name);
755 } 735 }
756 736
757 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> 737 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
@@ -776,7 +756,7 @@ you can only use widgets and widget functions here'''; @@ -776,7 +756,7 @@ you can only use widgets and widget functions here''';
776 /// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors 756 /// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors
777 Future<T?>? offAllNamed<T>( 757 Future<T?>? offAllNamed<T>(
778 String newRouteName, { 758 String newRouteName, {
779 - RoutePredicate? predicate, 759 + // bool Function(GetPage<dynamic>)? predicate,
780 dynamic arguments, 760 dynamic arguments,
781 int? id, 761 int? id,
782 Map<String, String>? parameters, 762 Map<String, String>? parameters,
@@ -786,11 +766,13 @@ you can only use widgets and widget functions here'''; @@ -786,11 +766,13 @@ you can only use widgets and widget functions here''';
786 newRouteName = uri.toString(); 766 newRouteName = uri.toString();
787 } 767 }
788 768
789 - return global(id).currentState?.pushNamedAndRemoveUntil<T>(  
790 - newRouteName,  
791 - predicate ?? (_) => false,  
792 - arguments: arguments,  
793 - ); 769 + return searchDelegate(id).offAllNamed<T>(
  770 + newRouteName,
  771 + //predicate: predicate ?? (_) => false,
  772 + arguments: arguments,
  773 + id: id,
  774 + parameters: parameters,
  775 + );
794 } 776 }
795 777
796 /// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN 778 /// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN
@@ -819,6 +801,13 @@ you can only use widgets and widget functions here'''; @@ -819,6 +801,13 @@ you can only use widgets and widget functions here''';
819 bool canPop = true, 801 bool canPop = true,
820 int? id, 802 int? id,
821 }) { 803 }) {
  804 + //TODO: remove this when change own api to Dialog and BottomSheets
  805 + //to declarative way
  806 + if (isDialogOpen! || isBottomSheetOpen!) {
  807 + searchDelegate(id).navigatorKey.currentState?.pop();
  808 + return;
  809 + }
  810 +
822 //TODO: This code brings compatibility of the new snackbar with GetX 4, 811 //TODO: This code brings compatibility of the new snackbar with GetX 4,
823 // remove this code in version 5 812 // remove this code in version 5
824 if (isSnackbarOpen && !closeOverlays) { 813 if (isSnackbarOpen && !closeOverlays) {
@@ -832,16 +821,21 @@ you can only use widgets and widget functions here'''; @@ -832,16 +821,21 @@ you can only use widgets and widget functions here''';
832 if (isSnackbarOpen) { 821 if (isSnackbarOpen) {
833 closeAllSnackbars(); 822 closeAllSnackbars();
834 } 823 }
835 - navigator?.popUntil((route) {  
836 - return (!isDialogOpen! && !isBottomSheetOpen!);  
837 - }); 824 +
  825 + while ((isDialogOpen! && isBottomSheetOpen!)) {
  826 + searchDelegate(id).navigatorKey.currentState?.pop();
  827 + }
  828 +
  829 + // navigator?.popUntil((route) {
  830 + // return;
  831 + // });
838 } 832 }
839 if (canPop) { 833 if (canPop) {
840 - if (global(id).currentState?.canPop() == true) {  
841 - global(id).currentState?.pop<T>(result); 834 + if (searchDelegate(id).canBack == true) {
  835 + searchDelegate(id).back<T>(result);
842 } 836 }
843 } else { 837 } else {
844 - global(id).currentState?.pop<T>(result); 838 + searchDelegate(id).back<T>(result);
845 } 839 }
846 } 840 }
847 841
@@ -856,7 +850,7 @@ you can only use widgets and widget functions here'''; @@ -856,7 +850,7 @@ you can only use widgets and widget functions here''';
856 times = 1; 850 times = 1;
857 } 851 }
858 var count = 0; 852 var count = 0;
859 - var back = global(id).currentState?.popUntil((route) => count++ == times); 853 + var back = searchDelegate(id).backUntil((route) => count++ == times);
860 854
861 return back; 855 return back;
862 } 856 }
@@ -887,15 +881,15 @@ you can only use widgets and widget functions here'''; @@ -887,15 +881,15 @@ you can only use widgets and widget functions here''';
887 /// By default, GetX will prevent you from push a route that you already in, 881 /// By default, GetX will prevent you from push a route that you already in,
888 /// if you want to push anyway, set [preventDuplicates] to false 882 /// if you want to push anyway, set [preventDuplicates] to false
889 Future<T?>? off<T>( 883 Future<T?>? off<T>(
890 - dynamic page, {  
891 - bool opaque = false, 884 + Widget Function() page, {
  885 + bool? opaque,
892 Transition? transition, 886 Transition? transition,
893 Curve? curve, 887 Curve? curve,
894 bool? popGesture, 888 bool? popGesture,
895 int? id, 889 int? id,
896 String? routeName, 890 String? routeName,
897 dynamic arguments, 891 dynamic arguments,
898 - Binding? binding, 892 + List<BindingsInterface>? bindings,
899 bool fullscreenDialog = false, 893 bool fullscreenDialog = false,
900 bool preventDuplicates = true, 894 bool preventDuplicates = true,
901 Duration? duration, 895 Duration? duration,
@@ -906,21 +900,34 @@ you can only use widgets and widget functions here'''; @@ -906,21 +900,34 @@ you can only use widgets and widget functions here''';
906 if (preventDuplicates && routeName == currentRoute) { 900 if (preventDuplicates && routeName == currentRoute) {
907 return null; 901 return null;
908 } 902 }
909 - return global(id).currentState?.pushReplacement(GetPageRoute(  
910 - opaque: opaque,  
911 - gestureWidth: gestureWidth,  
912 - page: _resolvePage(page, 'off'),  
913 - binding: binding,  
914 - settings: RouteSettings(  
915 - arguments: arguments,  
916 - name: routeName,  
917 - ),  
918 - routeName: routeName,  
919 - fullscreenDialog: fullscreenDialog,  
920 - popGesture: popGesture ?? defaultPopGesture,  
921 - transition: transition ?? defaultTransition,  
922 - curve: curve ?? defaultTransitionCurve,  
923 - transitionDuration: duration ?? defaultTransitionDuration)); 903 + return searchDelegate(id).off(
  904 + page,
  905 + opaque: opaque ?? true,
  906 + transition: transition,
  907 + curve: curve,
  908 + popGesture: popGesture,
  909 + id: id,
  910 + routeName: routeName,
  911 + arguments: arguments,
  912 + bindings: bindings,
  913 + fullscreenDialog: fullscreenDialog,
  914 + preventDuplicates: preventDuplicates,
  915 + duration: duration,
  916 + gestureWidth: gestureWidth,
  917 + );
  918 + }
  919 +
  920 + Future<T?> offUntil<T>(
  921 + Widget Function() page,
  922 + bool Function(GetPage) predicate, [
  923 + Object? arguments,
  924 + int? id,
  925 + ]) {
  926 + return searchDelegate(id).offUntil(
  927 + page,
  928 + predicate,
  929 + arguments,
  930 + );
924 } 931 }
925 932
926 /// 933 ///
@@ -954,14 +961,14 @@ you can only use widgets and widget functions here'''; @@ -954,14 +961,14 @@ you can only use widgets and widget functions here''';
954 /// By default, GetX will prevent you from push a route that you already in, 961 /// By default, GetX will prevent you from push a route that you already in,
955 /// if you want to push anyway, set [preventDuplicates] to false 962 /// if you want to push anyway, set [preventDuplicates] to false
956 Future<T?>? offAll<T>( 963 Future<T?>? offAll<T>(
957 - dynamic page, {  
958 - RoutePredicate? predicate,  
959 - bool opaque = false, 964 + Widget Function() page, {
  965 + bool Function(GetPage<dynamic>)? predicate,
  966 + bool? opaque,
960 bool? popGesture, 967 bool? popGesture,
961 int? id, 968 int? id,
962 String? routeName, 969 String? routeName,
963 dynamic arguments, 970 dynamic arguments,
964 - Binding? binding, 971 + List<BindingsInterface>? bindings,
965 bool fullscreenDialog = false, 972 bool fullscreenDialog = false,
966 Transition? transition, 973 Transition? transition,
967 Curve? curve, 974 Curve? curve,
@@ -970,24 +977,21 @@ you can only use widgets and widget functions here'''; @@ -970,24 +977,21 @@ you can only use widgets and widget functions here''';
970 }) { 977 }) {
971 routeName ??= "/${page.runtimeType.toString()}"; 978 routeName ??= "/${page.runtimeType.toString()}";
972 routeName = _cleanRouteName(routeName); 979 routeName = _cleanRouteName(routeName);
973 - return global(id).currentState?.pushAndRemoveUntil<T>(  
974 - GetPageRoute<T>(  
975 - opaque: opaque,  
976 - popGesture: popGesture ?? defaultPopGesture,  
977 - page: _resolvePage(page, 'offAll'),  
978 - binding: binding,  
979 - gestureWidth: gestureWidth,  
980 - settings: RouteSettings(  
981 - name: routeName,  
982 - arguments: arguments,  
983 - ),  
984 - fullscreenDialog: fullscreenDialog,  
985 - routeName: routeName,  
986 - transition: transition ?? defaultTransition,  
987 - curve: curve ?? defaultTransitionCurve,  
988 - transitionDuration: duration ?? defaultTransitionDuration,  
989 - ),  
990 - predicate ?? (route) => false); 980 + return searchDelegate(id).offAll<T>(
  981 + page,
  982 + predicate: predicate,
  983 + opaque: opaque ?? true,
  984 + popGesture: popGesture,
  985 + id: id,
  986 + // routeName routeName,
  987 + arguments: arguments,
  988 + bindings: bindings,
  989 + fullscreenDialog: fullscreenDialog,
  990 + transition: transition,
  991 + curve: curve,
  992 + duration: duration,
  993 + gestureWidth: gestureWidth,
  994 + );
991 } 995 }
992 996
993 /// Takes a route [name] String generated by [to], [off], [offAll] 997 /// Takes a route [name] String generated by [to], [off], [offAll]
@@ -1072,20 +1076,21 @@ you can only use widgets and widget functions here'''; @@ -1072,20 +1076,21 @@ you can only use widgets and widget functions here''';
1072 return _getxController.addKey(newKey); 1076 return _getxController.addKey(newKey);
1073 } 1077 }
1074 1078
1075 - GlobalKey<NavigatorState>? nestedKey(dynamic key) { 1079 + GetDelegate? nestedKey(dynamic key) {
1076 keys.putIfAbsent( 1080 keys.putIfAbsent(
1077 key, 1081 key,
1078 - () => GlobalKey<NavigatorState>(  
1079 - debugLabel: 'Getx nested key: ${key.toString()}', 1082 + () => GetDelegate(
  1083 + //debugLabel: 'Getx nested key: ${key.toString()}',
  1084 + pages: [],
1080 ), 1085 ),
1081 ); 1086 );
1082 return keys[key]; 1087 return keys[key];
1083 } 1088 }
1084 1089
1085 - GlobalKey<NavigatorState> global(int? k) {  
1086 - GlobalKey<NavigatorState> _key; 1090 + GetDelegate searchDelegate(int? k) {
  1091 + GetDelegate _key;
1087 if (k == null) { 1092 if (k == null) {
1088 - _key = key; 1093 + _key = Get.rootController.rootDelegate;
1089 } else { 1094 } else {
1090 if (!keys.containsKey(k)) { 1095 if (!keys.containsKey(k)) {
1091 throw 'Route id ($k) not found'; 1096 throw 'Route id ($k) not found';
@@ -1093,21 +1098,22 @@ you can only use widgets and widget functions here'''; @@ -1093,21 +1098,22 @@ you can only use widgets and widget functions here''';
1093 _key = keys[k]!; 1098 _key = keys[k]!;
1094 } 1099 }
1095 1100
1096 - if (_key.currentContext == null && !testMode) {  
1097 - throw """You are trying to use contextless navigation without  
1098 - a GetMaterialApp or Get.key.  
1099 - If you are testing your app, you can use:  
1100 - [Get.testMode = true], or if you are running your app on  
1101 - a physical device or emulator, you must exchange your [MaterialApp]  
1102 - for a [GetMaterialApp].  
1103 - """;  
1104 - } 1101 + // if (_key.listenersLength == 0 && !testMode) {
  1102 + // throw """You are trying to use contextless navigation without
  1103 + // a GetMaterialApp or Get.key.
  1104 + // If you are testing your app, you can use:
  1105 + // [Get.testMode = true], or if you are running your app on
  1106 + // a physical device or emulator, you must exchange your [MaterialApp]
  1107 + // for a [GetMaterialApp].
  1108 + // """;
  1109 + // }
1105 1110
1106 return _key; 1111 return _key;
1107 } 1112 }
1108 1113
1109 /// give current arguments 1114 /// give current arguments
1110 - dynamic get arguments => routing.args; 1115 + //dynamic get arguments => routing.args;
  1116 + dynamic get arguments => _getxController.rootDelegate.arguments();
1111 1117
1112 /// give name from current route 1118 /// give name from current route
1113 String get currentRoute => routing.current; 1119 String get currentRoute => routing.current;
@@ -1225,7 +1231,7 @@ you can only use widgets and widget functions here'''; @@ -1225,7 +1231,7 @@ you can only use widgets and widget functions here''';
1225 1231
1226 GlobalKey<NavigatorState> get key => _getxController.key; 1232 GlobalKey<NavigatorState> get key => _getxController.key;
1227 1233
1228 - Map<dynamic, GlobalKey<NavigatorState>> get keys => _getxController.keys; 1234 + Map<dynamic, GetDelegate> get keys => _getxController.keys;
1229 1235
1230 GetMaterialController get rootController => _getxController; 1236 GetMaterialController get rootController => _getxController;
1231 1237
@@ -1250,7 +1256,8 @@ you can only use widgets and widget functions here'''; @@ -1250,7 +1256,8 @@ you can only use widgets and widget functions here''';
1250 1256
1251 Routing get routing => _getxController.routing; 1257 Routing get routing => _getxController.routing;
1252 1258
1253 - Map<String, String?> get parameters => _getxController.parameters; 1259 + Map<String, String?> get parameters =>
  1260 + _getxController.rootDelegate.parameters;
1254 set parameters(Map<String, String?> newParameters) => 1261 set parameters(Map<String, String?> newParameters) =>
1255 _getxController.parameters = newParameters; 1262 _getxController.parameters = newParameters;
1256 1263
@@ -1280,10 +1287,15 @@ extension NavTwoExt on GetInterface { @@ -1280,10 +1287,15 @@ extension NavTwoExt on GetInterface {
1280 static late final _routeTree = ParseRouteTree(routes: []); 1287 static late final _routeTree = ParseRouteTree(routes: []);
1281 1288
1282 ParseRouteTree get routeTree => _routeTree; 1289 ParseRouteTree get routeTree => _routeTree;
  1290 +
1283 void addPage(GetPage getPage) { 1291 void addPage(GetPage getPage) {
1284 routeTree.addRoute(getPage); 1292 routeTree.addRoute(getPage);
1285 } 1293 }
1286 1294
  1295 + void removePage(GetPage getPage) {
  1296 + routeTree.removeRoute(getPage);
  1297 + }
  1298 +
1287 /// Casts the stored router delegate to a desired type 1299 /// Casts the stored router delegate to a desired type
1288 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => 1300 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() =>
1289 routerDelegate as TDelegate?; 1301 routerDelegate as TDelegate?;
@@ -1307,15 +1319,15 @@ extension NavTwoExt on GetInterface { @@ -1307,15 +1319,15 @@ extension NavTwoExt on GetInterface {
1307 1319
1308 // static GetDelegate? _delegate; 1320 // static GetDelegate? _delegate;
1309 1321
1310 - GetDelegate get rootDelegate => createDelegate();  
1311 -  
1312 GetDelegate createDelegate({ 1322 GetDelegate createDelegate({
1313 GetPage<dynamic>? notFoundRoute, 1323 GetPage<dynamic>? notFoundRoute,
  1324 + List<GetPage> pages = const [],
1314 List<NavigatorObserver>? navigatorObservers, 1325 List<NavigatorObserver>? navigatorObservers,
1315 TransitionDelegate<dynamic>? transitionDelegate, 1326 TransitionDelegate<dynamic>? transitionDelegate,
1316 PopMode backButtonPopMode = PopMode.History, 1327 PopMode backButtonPopMode = PopMode.History,
1317 PreventDuplicateHandlingMode preventDuplicateHandlingMode = 1328 PreventDuplicateHandlingMode preventDuplicateHandlingMode =
1318 PreventDuplicateHandlingMode.ReorderRoutes, 1329 PreventDuplicateHandlingMode.ReorderRoutes,
  1330 + GlobalKey<NavigatorState>? navigatorKey,
1319 }) { 1331 }) {
1320 if (routerDelegate == null) { 1332 if (routerDelegate == null) {
1321 return routerDelegate = GetDelegate( 1333 return routerDelegate = GetDelegate(
@@ -1324,6 +1336,8 @@ extension NavTwoExt on GetInterface { @@ -1324,6 +1336,8 @@ extension NavTwoExt on GetInterface {
1324 transitionDelegate: transitionDelegate, 1336 transitionDelegate: transitionDelegate,
1325 backButtonPopMode: backButtonPopMode, 1337 backButtonPopMode: backButtonPopMode,
1326 preventDuplicateHandlingMode: preventDuplicateHandlingMode, 1338 preventDuplicateHandlingMode: preventDuplicateHandlingMode,
  1339 + pages: pages,
  1340 + navigatorKey: navigatorKey,
1327 ); 1341 );
1328 } else { 1342 } else {
1329 return routerDelegate as GetDelegate; 1343 return routerDelegate as GetDelegate;
1 -import 'package:flutter/widgets.dart';  
2 -  
3 -import '../../../get.dart';  
4 -  
5 -// class GetRouterState extends GetxController {  
6 -// GetRouterState({required this.currentTreeBranch});  
7 -// final List<GetPage> currentTreeBranch;  
8 -// GetPage? get currentPage => currentTreeBranch.last;  
9 -  
10 -// static GetNavConfig? fromRoute(String route) {  
11 -// final res = Get.routeTree.matchRoute(route);  
12 -// if (res.treeBranch.isEmpty) return null;  
13 -// return GetNavConfig(  
14 -// currentTreeBranch: res.treeBranch,  
15 -// location: route,  
16 -// state: null,  
17 -// );  
18 -// }  
19 -// }  
20 -  
21 -/// This config enables us to navigate directly to a sub-url  
22 -class GetNavConfig extends RouteInformation {  
23 - final List<GetPage> currentTreeBranch;  
24 - GetPage? get currentPage => currentTreeBranch.last;  
25 -  
26 - GetNavConfig({  
27 - required this.currentTreeBranch,  
28 - required String? location,  
29 - required Object? state,  
30 - }) : super(  
31 - location: location,  
32 - state: state,  
33 - );  
34 -  
35 - GetNavConfig copyWith({  
36 - List<GetPage>? currentTreeBranch,  
37 - required String? location,  
38 - required Object? state,  
39 - }) {  
40 - return GetNavConfig(  
41 - currentTreeBranch: currentTreeBranch ?? this.currentTreeBranch,  
42 - location: location ?? this.location,  
43 - state: state ?? this.state,  
44 - );  
45 - }  
46 -  
47 - static GetNavConfig? fromRoute(String route) {  
48 - final res = Get.routeTree.matchRoute(route);  
49 - if (res.treeBranch.isEmpty) return null;  
50 - return GetNavConfig(  
51 - currentTreeBranch: res.treeBranch,  
52 - location: route,  
53 - state: null,  
54 - );  
55 - }  
56 -  
57 - @override  
58 - String toString() => '''  
59 -======GetNavConfig=====\nlocation: $location\ncurrentTreeBranch: $currentTreeBranch\n======GetNavConfig=====''';  
60 -}  
1 -import 'dart:async';  
2 -  
3 -import 'package:flutter/foundation.dart';  
4 -import 'package:flutter/material.dart';  
5 -  
6 -import '../../../get.dart';  
7 -import '../../../get_state_manager/src/simple/list_notifier.dart';  
8 -  
9 -/// Enables the user to customize the intended pop behavior  
10 -///  
11 -/// Goes to either the previous history entry or the previous page entry  
12 -///  
13 -/// e.g. if the user navigates to these pages  
14 -/// 1) /home  
15 -/// 2) /home/products/1234  
16 -///  
17 -/// when popping on [History] mode, it will emulate a browser back button.  
18 -///  
19 -/// so the new history stack will be:  
20 -/// 1) /home  
21 -///  
22 -/// when popping on [Page] mode, it will only remove the last part of the route  
23 -/// so the new history stack will be:  
24 -/// 1) /home  
25 -/// 2) /home/products  
26 -///  
27 -/// another pop will change the history stack to:  
28 -/// 1) /home  
29 -enum PopMode {  
30 - History,  
31 - Page,  
32 -}  
33 -  
34 -/// Enables the user to customize the behavior when pushing multiple routes that  
35 -/// shouldn't be duplicates  
36 -enum PreventDuplicateHandlingMode {  
37 - /// Removes the history entries until it reaches the old route  
38 - PopUntilOriginalRoute,  
39 -  
40 - /// Simply don't push the new route  
41 - DoNothing,  
42 -  
43 - /// Recommended - Moves the old route entry to the front  
44 - ///  
45 - /// With this mode, you guarantee there will be only one  
46 - /// route entry for each location  
47 - ReorderRoutes  
48 -}  
49 -  
50 -class GetDelegate extends RouterDelegate<GetNavConfig>  
51 - with ListNotifierSingleMixin {  
52 - final List<GetNavConfig> history = <GetNavConfig>[];  
53 - final PopMode backButtonPopMode;  
54 - final PreventDuplicateHandlingMode preventDuplicateHandlingMode;  
55 -  
56 - final GetPage notFoundRoute;  
57 -  
58 - final List<NavigatorObserver>? navigatorObservers;  
59 - final TransitionDelegate<dynamic>? transitionDelegate;  
60 -  
61 - final Iterable<GetPage> Function(GetNavConfig currentNavStack)?  
62 - pickPagesForRootNavigator;  
63 -  
64 - GlobalKey<NavigatorState> get navigatorKey => Get.key;  
65 -  
66 - GetDelegate({  
67 - GetPage? notFoundRoute,  
68 - this.navigatorObservers,  
69 - this.transitionDelegate,  
70 - this.backButtonPopMode = PopMode.History,  
71 - this.preventDuplicateHandlingMode =  
72 - PreventDuplicateHandlingMode.ReorderRoutes,  
73 - this.pickPagesForRootNavigator,  
74 - }) : notFoundRoute = notFoundRoute ??  
75 - GetPage(  
76 - name: '/404',  
77 - page: () => Scaffold(  
78 - body: Text('Route not found'),  
79 - ),  
80 - ) {  
81 - Get.log('GetDelegate is created !');  
82 - }  
83 -  
84 - Future<GetNavConfig?> runMiddleware(GetNavConfig config) async {  
85 - final middlewares = config.currentTreeBranch.last.middlewares;  
86 - if (middlewares == null) {  
87 - return config;  
88 - }  
89 - var iterator = config;  
90 - for (var item in middlewares) {  
91 - var redirectRes = await item.redirectDelegate(iterator);  
92 - if (redirectRes == null) return null;  
93 - iterator = redirectRes;  
94 - }  
95 - return iterator;  
96 - }  
97 -  
98 - Future<void> _unsafeHistoryAdd(GetNavConfig config) async {  
99 - final res = await runMiddleware(config);  
100 - if (res == null) return;  
101 - history.add(res);  
102 - }  
103 -  
104 - Future<void> _unsafeHistoryRemove(GetNavConfig config) async {  
105 - var index = history.indexOf(config);  
106 - if (index >= 0) await _unsafeHistoryRemoveAt(index);  
107 - }  
108 -  
109 - Future<GetNavConfig?> _unsafeHistoryRemoveAt(int index) async {  
110 - if (index == history.length - 1 && history.length > 1) {  
111 - //removing WILL update the current route  
112 - final toCheck = history[history.length - 2];  
113 - final resMiddleware = await runMiddleware(toCheck);  
114 - if (resMiddleware == null) return null;  
115 - history[history.length - 2] = resMiddleware;  
116 - }  
117 - return history.removeAt(index);  
118 - }  
119 -  
120 - T arguments<T>() {  
121 - return currentConfiguration?.currentPage?.arguments as T;  
122 - }  
123 -  
124 - Map<String, String> get parameters {  
125 - return currentConfiguration?.currentPage?.parameters ?? {};  
126 - }  
127 -  
128 - /// Adds a new history entry and waits for the result  
129 - Future<void> pushHistory(  
130 - GetNavConfig config, {  
131 - bool rebuildStack = true,  
132 - }) async {  
133 - //this changes the currentConfiguration  
134 - await _pushHistory(config);  
135 - if (rebuildStack) {  
136 - refresh();  
137 - }  
138 - }  
139 -  
140 - Future<void> _removeHistoryEntry(GetNavConfig entry) async {  
141 - await _unsafeHistoryRemove(entry);  
142 - }  
143 -  
144 - Future<void> _pushHistory(GetNavConfig config) async {  
145 - if (config.currentPage!.preventDuplicates) {  
146 - final originalEntryIndex =  
147 - history.indexWhere((element) => element.location == config.location);  
148 - if (originalEntryIndex >= 0) {  
149 - switch (preventDuplicateHandlingMode) {  
150 - case PreventDuplicateHandlingMode.PopUntilOriginalRoute:  
151 - await backUntil(config.location!, popMode: PopMode.Page);  
152 - break;  
153 - case PreventDuplicateHandlingMode.ReorderRoutes:  
154 - await _unsafeHistoryRemoveAt(originalEntryIndex);  
155 - await _unsafeHistoryAdd(config);  
156 - break;  
157 - case PreventDuplicateHandlingMode.DoNothing:  
158 - default:  
159 - break;  
160 - }  
161 - return;  
162 - }  
163 - }  
164 - await _unsafeHistoryAdd(config);  
165 - }  
166 -  
167 - Future<GetNavConfig?> _popHistory() async {  
168 - if (!_canPopHistory()) return null;  
169 - return await _doPopHistory();  
170 - }  
171 -  
172 - Future<GetNavConfig?> _doPopHistory() async {  
173 - return await _unsafeHistoryRemoveAt(history.length - 1);  
174 - }  
175 -  
176 - Future<GetNavConfig?> _popPage() async {  
177 - if (!_canPopPage()) return null;  
178 - return await _doPopPage();  
179 - }  
180 -  
181 - Future<GetNavConfig?> _pop(PopMode mode) async {  
182 - switch (mode) {  
183 - case PopMode.History:  
184 - return await _popHistory();  
185 - case PopMode.Page:  
186 - return await _popPage();  
187 - default:  
188 - return null;  
189 - }  
190 - }  
191 -  
192 - // returns the popped page  
193 - Future<GetNavConfig?> _doPopPage() async {  
194 - final currentBranch = currentConfiguration?.currentTreeBranch;  
195 - if (currentBranch != null && currentBranch.length > 1) {  
196 - //remove last part only  
197 - final remaining = currentBranch.take(currentBranch.length - 1);  
198 - final prevHistoryEntry =  
199 - history.length > 1 ? history[history.length - 2] : null;  
200 -  
201 - //check if current route is the same as the previous route  
202 - if (prevHistoryEntry != null) {  
203 - //if so, pop the entire history entry  
204 - final newLocation = remaining.last.name;  
205 - final prevLocation = prevHistoryEntry.location;  
206 - if (newLocation == prevLocation) {  
207 - //pop the entire history entry  
208 - return await _popHistory();  
209 - }  
210 - }  
211 -  
212 - //create a new route with the remaining tree branch  
213 - final res = await _popHistory();  
214 - await _pushHistory(  
215 - GetNavConfig(  
216 - currentTreeBranch: remaining.toList(),  
217 - location: remaining.last.name,  
218 - state: null, //TOOD: persist state??  
219 - ),  
220 - );  
221 - return res;  
222 - } else {  
223 - //remove entire entry  
224 - return await _popHistory();  
225 - }  
226 - }  
227 -  
228 - Future<GetNavConfig?> popHistory() async {  
229 - return await _popHistory();  
230 - }  
231 -  
232 - bool _canPopHistory() {  
233 - return history.length > 1;  
234 - }  
235 -  
236 - Future<bool> canPopHistory() {  
237 - return SynchronousFuture(_canPopHistory());  
238 - }  
239 -  
240 - bool _canPopPage() {  
241 - final currentTreeBranch = currentConfiguration?.currentTreeBranch;  
242 - if (currentTreeBranch == null) return false;  
243 - return currentTreeBranch.length > 1 ? true : _canPopHistory();  
244 - }  
245 -  
246 - Future<bool> canPopPage() {  
247 - return SynchronousFuture(_canPopPage());  
248 - }  
249 -  
250 - bool _canPop(PopMode mode) {  
251 - switch (mode) {  
252 - case PopMode.History:  
253 - return _canPopHistory();  
254 - case PopMode.Page:  
255 - default:  
256 - return _canPopPage();  
257 - }  
258 - }  
259 -  
260 - /// gets the visual pages from the current history entry  
261 - ///  
262 - /// visual pages must have [GetPage.participatesInRootNavigator] set to true  
263 - Iterable<GetPage> getVisualPages(GetNavConfig currentHistory) {  
264 - final res = currentHistory.currentTreeBranch  
265 - .where((r) => r.participatesInRootNavigator != null);  
266 - if (res.length == 0) {  
267 - //default behavoir, all routes participate in root navigator  
268 - return history.map((e) => e.currentPage!);  
269 - } else {  
270 - //user specified at least one participatesInRootNavigator  
271 - return res  
272 - .where((element) => element.participatesInRootNavigator == true);  
273 - }  
274 - }  
275 -  
276 - @override  
277 - Widget build(BuildContext context) {  
278 - final currentHistory = currentConfiguration;  
279 - final pages = currentHistory == null  
280 - ? <GetPage>[]  
281 - : pickPagesForRootNavigator?.call(currentHistory) ??  
282 - getVisualPages(currentHistory);  
283 - if (pages.length == 0) return SizedBox.shrink();  
284 - return GetNavigator(  
285 - key: navigatorKey,  
286 - onPopPage: _onPopVisualRoute,  
287 - pages: pages.toList(),  
288 - observers: [  
289 - GetObserver(),  
290 - ...?navigatorObservers,  
291 - ],  
292 - transitionDelegate:  
293 - transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),  
294 - );  
295 - }  
296 -  
297 - @override  
298 - Future<void> setNewRoutePath(GetNavConfig configuration) async {  
299 - await pushHistory(configuration);  
300 - }  
301 -  
302 - @override  
303 - GetNavConfig? get currentConfiguration {  
304 - if (history.isEmpty) return null;  
305 - final route = history.last;  
306 - return route;  
307 - }  
308 -  
309 - Future<void> toNamed(  
310 - String page, {  
311 - dynamic arguments,  
312 - Map<String, String>? parameters,  
313 - }) async {  
314 - if (parameters != null) {  
315 - final uri = Uri(path: page, queryParameters: parameters);  
316 - page = uri.toString();  
317 - }  
318 -  
319 - final decoder = Get.routeTree.matchRoute(page, arguments: arguments);  
320 - decoder.replaceArguments(arguments);  
321 -  
322 - if (decoder.route != null) {  
323 - await pushHistory(  
324 - GetNavConfig(  
325 - currentTreeBranch: decoder.treeBranch,  
326 - location: page,  
327 - state: null, //TODO: persist state?  
328 - ),  
329 - );  
330 - } else {  
331 - await pushHistory(  
332 - GetNavConfig(  
333 - currentTreeBranch: [notFoundRoute],  
334 - location: notFoundRoute.name,  
335 - state: null, //TODO: persist state?  
336 - ),  
337 - );  
338 - }  
339 - }  
340 -  
341 - //pops the previous route (if there is one) and goes to new route  
342 - Future<void> offNamed(  
343 - String page, {  
344 - dynamic arguments,  
345 - Map<String, String>? parameters,  
346 - PopMode popMode = PopMode.History,  
347 - }) async {  
348 - await popRoute(popMode: popMode);  
349 - return toNamed(page, arguments: arguments, parameters: parameters);  
350 - }  
351 -  
352 - /// Removes routes according to [PopMode]  
353 - /// until it reaches the specifc [fullRoute],  
354 - /// DOES NOT remove the [fullRoute]  
355 - Future<void> backUntil(  
356 - String fullRoute, {  
357 - PopMode popMode = PopMode.History,  
358 - }) async {  
359 - // remove history or page entries until you meet route  
360 - var iterator = currentConfiguration;  
361 - while (_canPop(popMode) &&  
362 - iterator != null &&  
363 - iterator.location != fullRoute) {  
364 - await _pop(popMode);  
365 - // replace iterator  
366 - iterator = currentConfiguration;  
367 - }  
368 - refresh();  
369 - }  
370 -  
371 - Future<bool> handlePopupRoutes({  
372 - Object? result,  
373 - }) async {  
374 - Route? currentRoute;  
375 - navigatorKey.currentState!.popUntil((route) {  
376 - currentRoute = route;  
377 - return true;  
378 - });  
379 - if (currentRoute is PopupRoute) {  
380 - return await navigatorKey.currentState!.maybePop(result);  
381 - }  
382 - return false;  
383 - }  
384 -  
385 - @override  
386 - Future<bool> popRoute({  
387 - Object? result,  
388 - PopMode? popMode,  
389 - }) async {  
390 - //Returning false will cause the entire app to be popped.  
391 - final wasPopup = await handlePopupRoutes(result: result);  
392 - if (wasPopup) return true;  
393 - final _popped = await _pop(popMode ?? backButtonPopMode);  
394 - refresh();  
395 - if (_popped != null) {  
396 - //emulate the old pop with result  
397 - return true;  
398 - }  
399 - return false;  
400 - }  
401 -  
402 - bool _onPopVisualRoute(Route<dynamic> route, dynamic result) {  
403 - final didPop = route.didPop(result);  
404 - if (!didPop) {  
405 - return false;  
406 - }  
407 - final settings = route.settings;  
408 - if (settings is GetPage) {  
409 - final config = history.cast<GetNavConfig?>().firstWhere(  
410 - (element) => element?.currentPage == settings,  
411 - orElse: () => null,  
412 - );  
413 - if (config != null) {  
414 - _removeHistoryEntry(config);  
415 - }  
416 - }  
417 - refresh();  
418 -  
419 - return true;  
420 - }  
421 -}  
@@ -62,7 +62,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -62,7 +62,7 @@ class GetCupertinoApp extends StatelessWidget {
62 final BackButtonDispatcher? backButtonDispatcher; 62 final BackButtonDispatcher? backButtonDispatcher;
63 final CupertinoThemeData? theme; 63 final CupertinoThemeData? theme;
64 final bool useInheritedMediaQuery; 64 final bool useInheritedMediaQuery;
65 - const GetCupertinoApp({ 65 + GetCupertinoApp({
66 Key? key, 66 Key? key,
67 this.theme, 67 this.theme,
68 this.navigatorKey, 68 this.navigatorKey,
@@ -115,17 +115,28 @@ class GetCupertinoApp extends StatelessWidget { @@ -115,17 +115,28 @@ class GetCupertinoApp extends StatelessWidget {
115 this.highContrastDarkTheme, 115 this.highContrastDarkTheme,
116 this.actions, 116 this.actions,
117 }) : routeInformationProvider = null, 117 }) : routeInformationProvider = null,
  118 + backButtonDispatcher = null,
118 routeInformationParser = null, 119 routeInformationParser = null,
119 routerDelegate = null, 120 routerDelegate = null,
120 - backButtonDispatcher = null,  
121 super(key: key); 121 super(key: key);
122 122
  123 + static String _cleanRouteName(String name) {
  124 + name = name.replaceAll('() => ', '');
  125 +
  126 + /// uncommonent for URL styling.
  127 + // name = name.paramCase!;
  128 + if (!name.startsWith('/')) {
  129 + name = '/$name';
  130 + }
  131 + return Uri.tryParse(name)?.toString() ?? name;
  132 + }
  133 +
123 GetCupertinoApp.router({ 134 GetCupertinoApp.router({
124 Key? key, 135 Key? key,
125 this.theme, 136 this.theme,
126 this.routeInformationProvider, 137 this.routeInformationProvider,
127 - RouteInformationParser<Object>? routeInformationParser,  
128 - RouterDelegate<Object>? routerDelegate, 138 + this.routeInformationParser,
  139 + this.routerDelegate,
129 this.backButtonDispatcher, 140 this.backButtonDispatcher,
130 this.builder, 141 this.builder,
131 this.title = '', 142 this.title = '',
@@ -165,32 +176,27 @@ class GetCupertinoApp extends StatelessWidget { @@ -165,32 +176,27 @@ class GetCupertinoApp extends StatelessWidget {
165 this.transitionDuration, 176 this.transitionDuration,
166 this.defaultGlobalState, 177 this.defaultGlobalState,
167 this.getPages, 178 this.getPages,
  179 + this.navigatorObservers,
168 this.unknownRoute, 180 this.unknownRoute,
169 - }) : routerDelegate = routerDelegate ??= Get.createDelegate(  
170 - notFoundRoute: unknownRoute,  
171 - ),  
172 - routeInformationParser =  
173 - routeInformationParser ??= Get.createInformationParser(  
174 - initialRoute: getPages?.first.name ?? '/',  
175 - ),  
176 - navigatorObservers = null,  
177 - navigatorKey = null, 181 + }) : navigatorKey = null,
178 onGenerateRoute = null, 182 onGenerateRoute = null,
179 home = null, 183 home = null,
180 onGenerateInitialRoutes = null, 184 onGenerateInitialRoutes = null,
181 onUnknownRoute = null, 185 onUnknownRoute = null,
182 routes = null, 186 routes = null,
183 initialRoute = null, 187 initialRoute = null,
184 - super(key: key) {  
185 - Get.routerDelegate = routerDelegate;  
186 - Get.routeInformationParser = routeInformationParser;  
187 - } 188 + super(key: key);
188 189
189 @override 190 @override
190 Widget build(BuildContext context) => GetBuilder<GetMaterialController>( 191 Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
191 init: Get.rootController, 192 init: Get.rootController,
192 dispose: (d) { 193 dispose: (d) {
193 onDispose?.call(); 194 onDispose?.call();
  195 + Get.clearRouteTree();
  196 + Get.clearTranslations();
  197 + Get.resetRootNavigator();
  198 + Get.routerDelegate = null;
  199 + Get.routeInformationParser = null;
194 }, 200 },
195 initState: (i) { 201 initState: (i) {
196 Get.engine!.addPostFrameCallback((timeStamp) { 202 Get.engine!.addPostFrameCallback((timeStamp) {
@@ -211,6 +217,13 @@ class GetCupertinoApp extends StatelessWidget { @@ -211,6 +217,13 @@ class GetCupertinoApp extends StatelessWidget {
211 initialBinding?.dependencies(); 217 initialBinding?.dependencies();
212 if (getPages != null) { 218 if (getPages != null) {
213 Get.addPages(getPages!); 219 Get.addPages(getPages!);
  220 + } else {
  221 + Get.addPage(
  222 + GetPage(
  223 + name: _cleanRouteName("/${home.runtimeType}"),
  224 + page: () => home!,
  225 + ),
  226 + );
214 } 227 }
215 228
216 Get.smartManagement = smartManagement; 229 Get.smartManagement = smartManagement;
@@ -226,72 +239,50 @@ class GetCupertinoApp extends StatelessWidget { @@ -226,72 +239,50 @@ class GetCupertinoApp extends StatelessWidget {
226 transitionDuration ?? Get.defaultTransitionDuration, 239 transitionDuration ?? Get.defaultTransitionDuration,
227 ); 240 );
228 }, 241 },
229 - builder: (_) => routerDelegate != null  
230 - ? CupertinoApp.router(  
231 - routerDelegate: routerDelegate!,  
232 - routeInformationParser: routeInformationParser!,  
233 - backButtonDispatcher: backButtonDispatcher,  
234 - routeInformationProvider: routeInformationProvider,  
235 - key: _.unikey,  
236 - theme: theme,  
237 - builder: defaultBuilder,  
238 - title: title,  
239 - onGenerateTitle: onGenerateTitle,  
240 - color: color,  
241 - locale: Get.locale ?? locale,  
242 - localizationsDelegates: localizationsDelegates,  
243 - localeListResolutionCallback: localeListResolutionCallback,  
244 - localeResolutionCallback: localeResolutionCallback,  
245 - supportedLocales: supportedLocales,  
246 - showPerformanceOverlay: showPerformanceOverlay,  
247 - checkerboardRasterCacheImages: checkerboardRasterCacheImages,  
248 - checkerboardOffscreenLayers: checkerboardOffscreenLayers,  
249 - showSemanticsDebugger: showSemanticsDebugger,  
250 - debugShowCheckedModeBanner: debugShowCheckedModeBanner,  
251 - shortcuts: shortcuts,  
252 - useInheritedMediaQuery: useInheritedMediaQuery,  
253 - )  
254 - : CupertinoApp(  
255 - key: _.unikey,  
256 - theme: theme,  
257 - navigatorKey: (navigatorKey == null  
258 - ? Get.key  
259 - : Get.addKey(navigatorKey!)),  
260 - home: home,  
261 - routes: routes ?? const <String, WidgetBuilder>{},  
262 - initialRoute: initialRoute,  
263 - onGenerateRoute:  
264 - (getPages != null ? generator : onGenerateRoute),  
265 - onGenerateInitialRoutes: (getPages == null || home != null)  
266 - ? onGenerateInitialRoutes  
267 - : initialRoutesGenerate,  
268 - onUnknownRoute: onUnknownRoute,  
269 - navigatorObservers: (navigatorObservers == null  
270 - ? <NavigatorObserver>[  
271 - GetObserver(routingCallback, Get.routing)  
272 - ]  
273 - : <NavigatorObserver>[  
274 - GetObserver(routingCallback, Get.routing)  
275 - ]  
276 - ..addAll(navigatorObservers!)),  
277 - builder: defaultBuilder,  
278 - title: title,  
279 - onGenerateTitle: onGenerateTitle,  
280 - color: color,  
281 - locale: Get.locale ?? locale,  
282 - localizationsDelegates: localizationsDelegates,  
283 - localeListResolutionCallback: localeListResolutionCallback,  
284 - localeResolutionCallback: localeResolutionCallback,  
285 - supportedLocales: supportedLocales,  
286 - showPerformanceOverlay: showPerformanceOverlay,  
287 - checkerboardRasterCacheImages: checkerboardRasterCacheImages,  
288 - checkerboardOffscreenLayers: checkerboardOffscreenLayers,  
289 - showSemanticsDebugger: showSemanticsDebugger,  
290 - debugShowCheckedModeBanner: debugShowCheckedModeBanner,  
291 - shortcuts: shortcuts,  
292 - useInheritedMediaQuery: useInheritedMediaQuery,  
293 - // actions: actions,  
294 - ), 242 + builder: (_) {
  243 + final routerDelegate = Get.createDelegate(
  244 + pages: getPages ?? [],
  245 + notFoundRoute: unknownRoute,
  246 + navigatorKey: navigatorKey,
  247 + navigatorObservers: (navigatorObservers == null
  248 + ? <NavigatorObserver>[
  249 + GetObserver(routingCallback, Get.routing)
  250 + ]
  251 + : <NavigatorObserver>[
  252 + GetObserver(routingCallback, Get.routing)
  253 + ]
  254 + ..addAll(navigatorObservers!)));
  255 + final routeInformationParser = Get.createInformationParser(
  256 + initialRoute: initialRoute ??
  257 + getPages?.first.name ??
  258 + _cleanRouteName("/${home.runtimeType}"),
  259 + );
  260 +
  261 + return CupertinoApp.router(
  262 + routerDelegate: routerDelegate,
  263 + routeInformationParser: routeInformationParser,
  264 + backButtonDispatcher: backButtonDispatcher,
  265 + routeInformationProvider: routeInformationProvider,
  266 + key: _.unikey,
  267 + theme: theme,
  268 + builder: defaultBuilder,
  269 + title: title,
  270 + onGenerateTitle: onGenerateTitle,
  271 + color: color,
  272 + locale: Get.locale ?? locale,
  273 + localizationsDelegates: localizationsDelegates,
  274 + localeListResolutionCallback: localeListResolutionCallback,
  275 + localeResolutionCallback: localeResolutionCallback,
  276 + supportedLocales: supportedLocales,
  277 + showPerformanceOverlay: showPerformanceOverlay,
  278 + checkerboardRasterCacheImages: checkerboardRasterCacheImages,
  279 + checkerboardOffscreenLayers: checkerboardOffscreenLayers,
  280 + showSemanticsDebugger: showSemanticsDebugger,
  281 + debugShowCheckedModeBanner: debugShowCheckedModeBanner,
  282 + shortcuts: shortcuts,
  283 + useInheritedMediaQuery: useInheritedMediaQuery,
  284 + );
  285 + },
295 ); 286 );
296 287
297 Widget defaultBuilder(BuildContext context, Widget? child) { 288 Widget defaultBuilder(BuildContext context, Widget? child) {
@@ -66,7 +66,7 @@ class GetMaterialApp extends StatelessWidget { @@ -66,7 +66,7 @@ class GetMaterialApp extends StatelessWidget {
66 final RouterDelegate<Object>? routerDelegate; 66 final RouterDelegate<Object>? routerDelegate;
67 final BackButtonDispatcher? backButtonDispatcher; 67 final BackButtonDispatcher? backButtonDispatcher;
68 final bool useInheritedMediaQuery; 68 final bool useInheritedMediaQuery;
69 - const GetMaterialApp({ 69 + GetMaterialApp({
70 Key? key, 70 Key? key,
71 this.navigatorKey, 71 this.navigatorKey,
72 this.scaffoldMessengerKey, 72 this.scaffoldMessengerKey,
@@ -124,17 +124,28 @@ class GetMaterialApp extends StatelessWidget { @@ -124,17 +124,28 @@ class GetMaterialApp extends StatelessWidget {
124 this.highContrastDarkTheme, 124 this.highContrastDarkTheme,
125 this.actions, 125 this.actions,
126 }) : routeInformationProvider = null, 126 }) : routeInformationProvider = null,
  127 + backButtonDispatcher = null,
127 routeInformationParser = null, 128 routeInformationParser = null,
128 routerDelegate = null, 129 routerDelegate = null,
129 - backButtonDispatcher = null,  
130 super(key: key); 130 super(key: key);
131 131
  132 + static String _cleanRouteName(String name) {
  133 + name = name.replaceAll('() => ', '');
  134 +
  135 + /// uncommonent for URL styling.
  136 + // name = name.paramCase!;
  137 + if (!name.startsWith('/')) {
  138 + name = '/$name';
  139 + }
  140 + return Uri.tryParse(name)?.toString() ?? name;
  141 + }
  142 +
132 GetMaterialApp.router({ 143 GetMaterialApp.router({
133 Key? key, 144 Key? key,
134 this.routeInformationProvider, 145 this.routeInformationProvider,
135 this.scaffoldMessengerKey, 146 this.scaffoldMessengerKey,
136 - RouteInformationParser<Object>? routeInformationParser,  
137 - RouterDelegate<Object>? routerDelegate, 147 + this.routeInformationParser,
  148 + this.routerDelegate,
138 this.backButtonDispatcher, 149 this.backButtonDispatcher,
139 this.builder, 150 this.builder,
140 this.title = '', 151 this.title = '',
@@ -181,148 +192,114 @@ class GetMaterialApp extends StatelessWidget { @@ -181,148 +192,114 @@ class GetMaterialApp extends StatelessWidget {
181 this.getPages, 192 this.getPages,
182 this.navigatorObservers, 193 this.navigatorObservers,
183 this.unknownRoute, 194 this.unknownRoute,
184 - }) : routerDelegate = routerDelegate ??= Get.createDelegate(  
185 - notFoundRoute: unknownRoute,  
186 - ),  
187 - routeInformationParser =  
188 - routeInformationParser ??= Get.createInformationParser(  
189 - initialRoute: getPages?.first.name ?? '/',  
190 - ),  
191 - //navigatorObservers = null,  
192 - navigatorKey = null, 195 + }) : navigatorKey = null,
193 onGenerateRoute = null, 196 onGenerateRoute = null,
194 home = null, 197 home = null,
195 onGenerateInitialRoutes = null, 198 onGenerateInitialRoutes = null,
196 onUnknownRoute = null, 199 onUnknownRoute = null,
197 routes = null, 200 routes = null,
198 initialRoute = null, 201 initialRoute = null,
199 - super(key: key) {  
200 - Get.routerDelegate = routerDelegate;  
201 - Get.routeInformationParser = routeInformationParser;  
202 - } 202 + super(key: key);
203 203
204 @override 204 @override
205 Widget build(BuildContext context) => GetBuilder<GetMaterialController>( 205 Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
206 - init: Get.rootController,  
207 - dispose: (d) {  
208 - onDispose?.call();  
209 - },  
210 - initState: (i) {  
211 - Get.engine!.addPostFrameCallback((timeStamp) {  
212 - onReady?.call();  
213 - });  
214 - if (locale != null) Get.locale = locale; 206 + init: Get.rootController,
  207 + dispose: (d) {
  208 + onDispose?.call();
  209 + Get.clearRouteTree();
  210 + Get.clearTranslations();
  211 + Get.resetRootNavigator();
  212 + Get.routerDelegate = null;
  213 + Get.routeInformationParser = null;
  214 + },
  215 + initState: (i) {
  216 + // Get.routerDelegate = routerDelegate;
  217 + // Get.routeInformationParser = routeInformationParser;
  218 + Get.engine!.addPostFrameCallback((timeStamp) {
  219 + onReady?.call();
  220 + });
  221 + if (locale != null) Get.locale = locale;
215 222
216 - if (fallbackLocale != null) Get.fallbackLocale = fallbackLocale; 223 + if (fallbackLocale != null) Get.fallbackLocale = fallbackLocale;
217 224
218 - if (translations != null) {  
219 - Get.addTranslations(translations!.keys);  
220 - } else if (translationsKeys != null) {  
221 - Get.addTranslations(translationsKeys!);  
222 - } 225 + if (translations != null) {
  226 + Get.addTranslations(translations!.keys);
  227 + } else if (translationsKeys != null) {
  228 + Get.addTranslations(translationsKeys!);
  229 + }
223 230
224 - Get.customTransition = customTransition; 231 + Get.customTransition = customTransition;
225 232
226 - initialBinding?.dependencies();  
227 - if (getPages != null) {  
228 - Get.addPages(getPages!);  
229 - } 233 + initialBinding?.dependencies();
  234 + if (getPages != null) {
  235 + Get.addPages(getPages!);
  236 + } else {
  237 + Get.addPage(
  238 + GetPage(
  239 + name: _cleanRouteName("/${home.runtimeType}"),
  240 + page: () => home!,
  241 + ),
  242 + );
  243 + }
230 244
231 - //Get.setDefaultDelegate(routerDelegate);  
232 - Get.smartManagement = smartManagement;  
233 - onInit?.call(); 245 + //Get.setDefaultDelegate(routerDelegate);
  246 + Get.smartManagement = smartManagement;
  247 + onInit?.call();
234 248
235 - Get.config(  
236 - enableLog: enableLog ?? Get.isLogEnable,  
237 - logWriterCallback: logWriterCallback,  
238 - defaultTransition: defaultTransition ?? Get.defaultTransition,  
239 - defaultOpaqueRoute: opaqueRoute ?? Get.isOpaqueRouteDefault,  
240 - defaultPopGesture: popGesture ?? Get.isPopGestureEnable,  
241 - defaultDurationTransition:  
242 - transitionDuration ?? Get.defaultTransitionDuration,  
243 - );  
244 - },  
245 - builder: (_) => routerDelegate != null  
246 - ? MaterialApp.router(  
247 - routerDelegate: routerDelegate!,  
248 - routeInformationParser: routeInformationParser!,  
249 - backButtonDispatcher: backButtonDispatcher,  
250 - routeInformationProvider: routeInformationProvider,  
251 - key: _.unikey,  
252 - builder: defaultBuilder,  
253 - title: title,  
254 - onGenerateTitle: onGenerateTitle,  
255 - color: color,  
256 - theme: _.theme ?? theme ?? ThemeData.fallback(),  
257 - darkTheme:  
258 - _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(),  
259 - themeMode: _.themeMode ?? themeMode,  
260 - locale: Get.locale ?? locale,  
261 - scaffoldMessengerKey:  
262 - scaffoldMessengerKey ?? _.scaffoldMessengerKey,  
263 - localizationsDelegates: localizationsDelegates,  
264 - localeListResolutionCallback: localeListResolutionCallback,  
265 - localeResolutionCallback: localeResolutionCallback,  
266 - supportedLocales: supportedLocales,  
267 - debugShowMaterialGrid: debugShowMaterialGrid,  
268 - showPerformanceOverlay: showPerformanceOverlay,  
269 - checkerboardRasterCacheImages: checkerboardRasterCacheImages,  
270 - checkerboardOffscreenLayers: checkerboardOffscreenLayers,  
271 - showSemanticsDebugger: showSemanticsDebugger,  
272 - debugShowCheckedModeBanner: debugShowCheckedModeBanner,  
273 - shortcuts: shortcuts,  
274 - scrollBehavior: scrollBehavior,  
275 - useInheritedMediaQuery: useInheritedMediaQuery,  
276 - )  
277 - : MaterialApp(  
278 - key: _.unikey,  
279 - navigatorKey: (navigatorKey == null  
280 - ? Get.key  
281 - : Get.addKey(navigatorKey!)),  
282 - scaffoldMessengerKey:  
283 - scaffoldMessengerKey ?? _.scaffoldMessengerKey,  
284 - home: home,  
285 - routes: routes ?? const <String, WidgetBuilder>{},  
286 - initialRoute: initialRoute,  
287 - onGenerateRoute:  
288 - (getPages != null ? generator : onGenerateRoute),  
289 - onGenerateInitialRoutes: (getPages == null || home != null)  
290 - ? onGenerateInitialRoutes  
291 - : initialRoutesGenerate,  
292 - onUnknownRoute: onUnknownRoute,  
293 - navigatorObservers: (navigatorObservers == null  
294 - ? <NavigatorObserver>[  
295 - GetObserver(routingCallback, Get.routing)  
296 - ]  
297 - : <NavigatorObserver>[  
298 - GetObserver(routingCallback, Get.routing)  
299 - ]  
300 - ..addAll(navigatorObservers!)),  
301 - builder: defaultBuilder,  
302 - title: title,  
303 - onGenerateTitle: onGenerateTitle,  
304 - color: color,  
305 - theme: _.theme ?? theme ?? ThemeData.fallback(),  
306 - darkTheme:  
307 - _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(),  
308 - themeMode: _.themeMode ?? themeMode,  
309 - locale: Get.locale ?? locale,  
310 - localizationsDelegates: localizationsDelegates,  
311 - localeListResolutionCallback: localeListResolutionCallback,  
312 - localeResolutionCallback: localeResolutionCallback,  
313 - supportedLocales: supportedLocales,  
314 - debugShowMaterialGrid: debugShowMaterialGrid,  
315 - showPerformanceOverlay: showPerformanceOverlay,  
316 - checkerboardRasterCacheImages: checkerboardRasterCacheImages,  
317 - checkerboardOffscreenLayers: checkerboardOffscreenLayers,  
318 - showSemanticsDebugger: showSemanticsDebugger,  
319 - debugShowCheckedModeBanner: debugShowCheckedModeBanner,  
320 - shortcuts: shortcuts,  
321 - scrollBehavior: scrollBehavior,  
322 - useInheritedMediaQuery: useInheritedMediaQuery,  
323 - // actions: actions,  
324 - ),  
325 - ); 249 + Get.config(
  250 + enableLog: enableLog ?? Get.isLogEnable,
  251 + logWriterCallback: logWriterCallback,
  252 + defaultTransition: defaultTransition ?? Get.defaultTransition,
  253 + defaultOpaqueRoute: opaqueRoute ?? Get.isOpaqueRouteDefault,
  254 + defaultPopGesture: popGesture ?? Get.isPopGestureEnable,
  255 + defaultDurationTransition:
  256 + transitionDuration ?? Get.defaultTransitionDuration,
  257 + );
  258 + },
  259 + builder: (_) {
  260 + final routerDelegate = Get.createDelegate(
  261 + pages: getPages ?? [],
  262 + notFoundRoute: unknownRoute,
  263 + navigatorKey: navigatorKey,
  264 + navigatorObservers: (navigatorObservers == null
  265 + ? <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]
  266 + : <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]
  267 + ..addAll(navigatorObservers!)));
  268 + final routeInformationParser = Get.createInformationParser(
  269 + initialRoute: initialRoute ??
  270 + getPages?.first.name ??
  271 + _cleanRouteName("/${home.runtimeType}"),
  272 + );
  273 + return MaterialApp.router(
  274 + routerDelegate: routerDelegate,
  275 + routeInformationParser: routeInformationParser,
  276 + backButtonDispatcher: backButtonDispatcher,
  277 + routeInformationProvider: routeInformationProvider,
  278 + key: _.unikey,
  279 + builder: defaultBuilder,
  280 + title: title,
  281 + onGenerateTitle: onGenerateTitle,
  282 + color: color,
  283 + theme: _.theme ?? theme ?? ThemeData.fallback(),
  284 + darkTheme: _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(),
  285 + themeMode: _.themeMode ?? themeMode,
  286 + locale: Get.locale ?? locale,
  287 + scaffoldMessengerKey: scaffoldMessengerKey ?? _.scaffoldMessengerKey,
  288 + localizationsDelegates: localizationsDelegates,
  289 + localeListResolutionCallback: localeListResolutionCallback,
  290 + localeResolutionCallback: localeResolutionCallback,
  291 + supportedLocales: supportedLocales,
  292 + debugShowMaterialGrid: debugShowMaterialGrid,
  293 + showPerformanceOverlay: showPerformanceOverlay,
  294 + checkerboardRasterCacheImages: checkerboardRasterCacheImages,
  295 + checkerboardOffscreenLayers: checkerboardOffscreenLayers,
  296 + showSemanticsDebugger: showSemanticsDebugger,
  297 + debugShowCheckedModeBanner: debugShowCheckedModeBanner,
  298 + shortcuts: shortcuts,
  299 + scrollBehavior: scrollBehavior,
  300 + useInheritedMediaQuery: useInheritedMediaQuery,
  301 + );
  302 + });
326 303
327 Widget defaultBuilder(BuildContext context, Widget? child) { 304 Widget defaultBuilder(BuildContext context, Widget? child) {
328 return Directionality( 305 return Directionality(
@@ -340,12 +317,12 @@ class GetMaterialApp extends StatelessWidget { @@ -340,12 +317,12 @@ class GetMaterialApp extends StatelessWidget {
340 return PageRedirect(settings: settings, unknownRoute: unknownRoute).page(); 317 return PageRedirect(settings: settings, unknownRoute: unknownRoute).page();
341 } 318 }
342 319
343 - List<Route<dynamic>> initialRoutesGenerate(String name) {  
344 - return [  
345 - PageRedirect(  
346 - settings: RouteSettings(name: name),  
347 - unknownRoute: unknownRoute,  
348 - ).page()  
349 - ];  
350 - } 320 + // List<Route<dynamic>> initialRoutesGenerate(String name) {
  321 + // return [
  322 + // PageRedirect(
  323 + // settings: RouteSettings(name: name),
  324 + // unknownRoute: unknownRoute,
  325 + // ).page()
  326 + // ];
  327 + // }
351 } 328 }
@@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; @@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
2 2
3 import '../../../get.dart'; 3 import '../../../get.dart';
4 4
5 -class GetMaterialController extends SuperController { 5 +class GetMaterialController extends FullLifeCycleController {
  6 + static GetMaterialController get to => Get.find();
  7 +
6 bool testMode = false; 8 bool testMode = false;
7 Key? unikey; 9 Key? unikey;
8 ThemeData? theme; 10 ThemeData? theme;
@@ -28,14 +30,14 @@ class GetMaterialController extends SuperController { @@ -28,14 +30,14 @@ class GetMaterialController extends SuperController {
28 30
29 CustomTransition? customTransition; 31 CustomTransition? customTransition;
30 32
31 - var _key = GlobalKey<NavigatorState>(debugLabel: 'Key Created by default'); 33 + Map<dynamic, GetDelegate> keys = {};
32 34
33 - Map<dynamic, GlobalKey<NavigatorState>> keys = {}; 35 + GlobalKey<NavigatorState> get key => rootDelegate.navigatorKey;
34 36
35 - GlobalKey<NavigatorState> get key => _key; 37 + GetDelegate get rootDelegate => Get.createDelegate();
36 38
37 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) { 39 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
38 - _key = newKey; 40 + rootDelegate.navigatorKey = newKey;
39 return key; 41 return key;
40 } 42 }
41 43
@@ -49,18 +51,6 @@ class GetMaterialController extends SuperController { @@ -49,18 +51,6 @@ class GetMaterialController extends SuperController {
49 }); 51 });
50 } 52 }
51 53
52 - @override  
53 - void onDetached() {}  
54 -  
55 - @override  
56 - void onInactive() {}  
57 -  
58 - @override  
59 - void onPaused() {}  
60 -  
61 - @override  
62 - void onResumed() {}  
63 -  
64 void restartApp() { 54 void restartApp() {
65 unikey = UniqueKey(); 55 unikey = UniqueKey();
66 update(); 56 update();
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; @@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
2 2
3 import '../../../get.dart'; 3 import '../../../get.dart';
4 import '../router_report.dart'; 4 import '../router_report.dart';
5 -import 'get_transition_mixin.dart';  
6 5
7 @optionalTypeArgs 6 @optionalTypeArgs
8 mixin RouteReportMixin<T extends StatefulWidget> on State<T> { 7 mixin RouteReportMixin<T extends StatefulWidget> on State<T> {
@@ -33,10 +32,8 @@ mixin PageRouteReportMixin<T> on Route<T> { @@ -33,10 +32,8 @@ mixin PageRouteReportMixin<T> on Route<T> {
33 } 32 }
34 } 33 }
35 34
36 -class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T>  
37 - with  
38 - GetPageRouteTransitionMixin<T>,  
39 - PageRouteReportMixin { 35 +class GetPageRoute<T> extends PageRoute<T>
  36 + with GetPageRouteTransitionMixin<T>, PageRouteReportMixin {
40 /// Creates a page route for use in an iOS designed app. 37 /// Creates a page route for use in an iOS designed app.
41 /// 38 ///
42 /// The [builder], [maintainState], and [fullscreenDialog] arguments must not 39 /// The [builder], [maintainState], and [fullscreenDialog] arguments must not
@@ -54,7 +51,7 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T> @@ -54,7 +51,7 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T>
54 this.customTransition, 51 this.customTransition,
55 this.barrierDismissible = false, 52 this.barrierDismissible = false,
56 this.barrierColor, 53 this.barrierColor,
57 - this.binding, 54 + this.bindings,
58 this.binds, 55 this.binds,
59 this.routeName, 56 this.routeName,
60 this.page, 57 this.page,
@@ -76,7 +73,7 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T> @@ -76,7 +73,7 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T>
76 final String? routeName; 73 final String? routeName;
77 //final String reference; 74 //final String reference;
78 final CustomTransition? customTransition; 75 final CustomTransition? customTransition;
79 - final BindingsInterface? binding; 76 + final List<BindingsInterface>? bindings;
80 final Map<String, String>? parameter; 77 final Map<String, String>? parameter;
81 final List<Bind>? binds; 78 final List<Bind>? binds;
82 79
@@ -121,11 +118,11 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T> @@ -121,11 +118,11 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T>
121 ]; 118 ];
122 119
123 final localbindings = [ 120 final localbindings = [
124 - if (binding != null) ...<BindingsInterface>[binding!], 121 + if (bindings != null) ...bindings!,
125 ]; 122 ];
126 123
127 final bindingsToBind = middlewareRunner 124 final bindingsToBind = middlewareRunner
128 - .runOnBindingsStart(binding != null ? localbindings : localbinds); 125 + .runOnBindingsStart(bindings != null ? localbindings : localbinds);
129 126
130 /// Retrocompatibility workaround, remove this when Bindings api 127 /// Retrocompatibility workaround, remove this when Bindings api
131 /// have been removed 128 /// have been removed
@@ -2,17 +2,18 @@ import 'package:flutter/foundation.dart'; @@ -2,17 +2,18 @@ import 'package:flutter/foundation.dart';
2 import 'package:flutter/widgets.dart'; 2 import 'package:flutter/widgets.dart';
3 3
4 import '../../../get.dart'; 4 import '../../../get.dart';
  5 +import 'parse_route.dart';
5 6
6 -class GetInformationParser extends RouteInformationParser<GetNavConfig> { 7 +class GetInformationParser extends RouteInformationParser<RouteDecoder> {
7 final String initialRoute; 8 final String initialRoute;
8 9
9 GetInformationParser({ 10 GetInformationParser({
10 - this.initialRoute = '/', 11 + required this.initialRoute,
11 }) { 12 }) {
12 Get.log('GetInformationParser is created !'); 13 Get.log('GetInformationParser is created !');
13 } 14 }
14 @override 15 @override
15 - SynchronousFuture<GetNavConfig> parseRouteInformation( 16 + SynchronousFuture<RouteDecoder> parseRouteInformation(
16 RouteInformation routeInformation, 17 RouteInformation routeInformation,
17 ) { 18 ) {
18 var location = routeInformation.location; 19 var location = routeInformation.location;
@@ -26,22 +27,16 @@ class GetInformationParser extends RouteInformationParser<GetNavConfig> { @@ -26,22 +27,16 @@ class GetInformationParser extends RouteInformationParser<GetNavConfig> {
26 27
27 Get.log('GetInformationParser: route location: $location'); 28 Get.log('GetInformationParser: route location: $location');
28 29
29 - final matchResult = Get.routeTree.matchRoute(location ?? initialRoute); 30 + final routeName = location ?? initialRoute;
30 31
31 - return SynchronousFuture(  
32 - GetNavConfig(  
33 - currentTreeBranch: matchResult.treeBranch,  
34 - location: location,  
35 - state: routeInformation.state,  
36 - ),  
37 - ); 32 + return SynchronousFuture(RouteDecoder.fromRoute(routeName));
38 } 33 }
39 34
40 @override 35 @override
41 - RouteInformation restoreRouteInformation(GetNavConfig config) { 36 + RouteInformation restoreRouteInformation(RouteDecoder config) {
42 return RouteInformation( 37 return RouteInformation(
43 - location: config.location,  
44 - state: config.state, 38 + location: config.pageSettings?.name,
  39 + state: null,
45 ); 40 );
46 } 41 }
47 } 42 }
  1 +import 'package:flutter/widgets.dart';
  2 +
  3 +import '../../../get_instance/src/bindings_interface.dart';
  4 +import '../routes/get_route.dart';
  5 +import '../routes/transitions_type.dart';
  6 +
  7 +mixin IGetNavigation {
  8 + Future<T?> to<T>(
  9 + Widget Function() page, {
  10 + bool? opaque,
  11 + Transition? transition,
  12 + Curve? curve,
  13 + Duration? duration,
  14 + int? id,
  15 + String? routeName,
  16 + bool fullscreenDialog = false,
  17 + dynamic arguments,
  18 + List<BindingsInterface>? bindings,
  19 + bool preventDuplicates = true,
  20 + bool? popGesture,
  21 + bool showCupertinoParallax = true,
  22 + double Function(BuildContext context)? gestureWidth,
  23 + });
  24 +
  25 + Future<T?> off<T>(
  26 + Widget Function() page, {
  27 + bool? opaque,
  28 + Transition? transition,
  29 + Curve? curve,
  30 + Duration? duration,
  31 + int? id,
  32 + String? routeName,
  33 + bool fullscreenDialog = false,
  34 + dynamic arguments,
  35 + List<BindingsInterface>? bindings,
  36 + bool preventDuplicates = true,
  37 + bool? popGesture,
  38 + bool showCupertinoParallax = true,
  39 + double Function(BuildContext context)? gestureWidth,
  40 + });
  41 +
  42 + Future<T?>? offAll<T>(
  43 + Widget Function() page, {
  44 + bool Function(GetPage route)? predicate,
  45 + bool opaque = true,
  46 + bool? popGesture,
  47 + int? id,
  48 + String? routeName,
  49 + dynamic arguments,
  50 + List<BindingsInterface>? bindings,
  51 + bool fullscreenDialog = false,
  52 + Transition? transition,
  53 + Curve? curve,
  54 + Duration? duration,
  55 + bool showCupertinoParallax = true,
  56 + double Function(BuildContext context)? gestureWidth,
  57 + });
  58 +
  59 + Future<T?> toNamed<T>(
  60 + String page, {
  61 + dynamic arguments,
  62 + int? id,
  63 + bool preventDuplicates = true,
  64 + Map<String, String>? parameters,
  65 + });
  66 +
  67 + Future<T?> offNamed<T>(
  68 + String page, {
  69 + dynamic arguments,
  70 + int? id,
  71 + Map<String, String>? parameters,
  72 + });
  73 +
  74 + Future<T?>? offAllNamed<T>(
  75 + String newRouteName, {
  76 + // bool Function(GetPage route)? predicate,
  77 + dynamic arguments,
  78 + int? id,
  79 + Map<String, String>? parameters,
  80 + });
  81 +
  82 + Future<T?>? offNamedUntil<T>(
  83 + String page, {
  84 + bool Function(GetPage route)? predicate,
  85 + dynamic arguments,
  86 + int? id,
  87 + Map<String, String>? parameters,
  88 + });
  89 +
  90 + Future<T?> toNamedAndOffUntil<T>(
  91 + String page,
  92 + bool Function(GetPage) predicate, [
  93 + Object? data,
  94 + ]);
  95 +
  96 + Future<T?> offUntil<T>(
  97 + Widget Function() page,
  98 + bool Function(GetPage) predicate, [
  99 + Object? arguments,
  100 + ]);
  101 +
  102 + void back<T>([T? result]);
  103 +
  104 + Future<R?> backAndtoNamed<T, R>(String page, {T? result, Object? arguments});
  105 +
  106 + void backUntil(bool Function(GetPage) predicate);
  107 +
  108 + void goToUnknownPage([bool clearPages = true]);
  109 +}
1 import 'package:flutter/widgets.dart'; 1 import 'package:flutter/widgets.dart';
  2 +
2 import '../routes/default_route.dart'; 3 import '../routes/default_route.dart';
3 import '../routes/get_route.dart'; 4 import '../routes/get_route.dart';
4 5
@@ -11,6 +12,7 @@ class GetNavigator extends Navigator { @@ -11,6 +12,7 @@ class GetNavigator extends Navigator {
11 bool reportsRouteUpdateToEngine = false, 12 bool reportsRouteUpdateToEngine = false,
12 TransitionDelegate? transitionDelegate, 13 TransitionDelegate? transitionDelegate,
13 String? initialRoute, 14 String? initialRoute,
  15 + String? restorationScopeId,
14 }) : super( 16 }) : super(
15 //keys should be optional 17 //keys should be optional
16 key: key, 18 key: key,
@@ -35,6 +37,7 @@ class GetNavigator extends Navigator { @@ -35,6 +37,7 @@ class GetNavigator extends Navigator {
35 } 37 }
36 }, 38 },
37 reportsRouteUpdateToEngine: reportsRouteUpdateToEngine, 39 reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,
  40 + restorationScopeId: restorationScopeId,
38 pages: pages, 41 pages: pages,
39 observers: [ 42 observers: [
40 // GetObserver(), 43 // GetObserver(),
@@ -52,6 +55,7 @@ class GetNavigator extends Navigator { @@ -52,6 +55,7 @@ class GetNavigator extends Navigator {
52 bool reportsRouteUpdateToEngine = false, 55 bool reportsRouteUpdateToEngine = false,
53 TransitionDelegate? transitionDelegate, 56 TransitionDelegate? transitionDelegate,
54 String? initialRoute, 57 String? initialRoute,
  58 + String? restorationScopeId,
55 }) : super( 59 }) : super(
56 //keys should be optional 60 //keys should be optional
57 key: key, 61 key: key,
@@ -65,6 +69,7 @@ class GetNavigator extends Navigator { @@ -65,6 +69,7 @@ class GetNavigator extends Navigator {
65 return true; 69 return true;
66 }, 70 },
67 reportsRouteUpdateToEngine: reportsRouteUpdateToEngine, 71 reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,
  72 + restorationScopeId: restorationScopeId,
68 pages: pages, 73 pages: pages,
69 observers: [ 74 observers: [
70 // GetObserver(), 75 // GetObserver(),
  1 +import 'dart:async';
  2 +
1 import 'package:flutter/cupertino.dart'; 3 import 'package:flutter/cupertino.dart';
2 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
3 5
4 -import '../../../get_core/src/get_main.dart';  
5 import '../../../get_instance/src/bindings_interface.dart'; 6 import '../../../get_instance/src/bindings_interface.dart';
6 import '../../../get_state_manager/src/simple/get_state.dart'; 7 import '../../../get_state_manager/src/simple/get_state.dart';
7 import '../../get_navigation.dart'; 8 import '../../get_navigation.dart';
@@ -18,12 +19,14 @@ class GetPage<T> extends Page<T> { @@ -18,12 +19,14 @@ class GetPage<T> extends Page<T> {
18 final bool maintainState; 19 final bool maintainState;
19 final bool opaque; 20 final bool opaque;
20 final double Function(BuildContext context)? gestureWidth; 21 final double Function(BuildContext context)? gestureWidth;
21 - final BindingsInterface? binding; 22 + //final BindingsInterface? binding;
  23 + final List<BindingsInterface>? bindings;
22 final List<Bind> binds; 24 final List<Bind> binds;
23 final CustomTransition? customTransition; 25 final CustomTransition? customTransition;
24 final Duration? transitionDuration; 26 final Duration? transitionDuration;
25 final bool fullscreenDialog; 27 final bool fullscreenDialog;
26 final bool preventDuplicates; 28 final bool preventDuplicates;
  29 + final Completer<T?>? completer;
27 // @override 30 // @override
28 // final LocalKey? key; 31 // final LocalKey? key;
29 32
@@ -42,6 +45,8 @@ class GetPage<T> extends Page<T> { @@ -42,6 +45,8 @@ class GetPage<T> extends Page<T> {
42 final GetPage? unknownRoute; 45 final GetPage? unknownRoute;
43 final bool showCupertinoParallax; 46 final bool showCupertinoParallax;
44 47
  48 + final PreventDuplicateHandlingMode preventDuplicateHandlingMode;
  49 +
45 GetPage({ 50 GetPage({
46 required this.name, 51 required this.name,
47 required this.page, 52 required this.page,
@@ -56,7 +61,7 @@ class GetPage<T> extends Page<T> { @@ -56,7 +61,7 @@ class GetPage<T> extends Page<T> {
56 this.opaque = true, 61 this.opaque = true,
57 this.transitionDuration, 62 this.transitionDuration,
58 this.popGesture, 63 this.popGesture,
59 - this.binding, 64 + this.bindings = const [],
60 this.binds = const [], 65 this.binds = const [],
61 this.transition, 66 this.transition,
62 this.customTransition, 67 this.customTransition,
@@ -67,13 +72,16 @@ class GetPage<T> extends Page<T> { @@ -67,13 +72,16 @@ class GetPage<T> extends Page<T> {
67 this.arguments, 72 this.arguments,
68 this.showCupertinoParallax = true, 73 this.showCupertinoParallax = true,
69 this.preventDuplicates = true, 74 this.preventDuplicates = true,
  75 + this.preventDuplicateHandlingMode =
  76 + PreventDuplicateHandlingMode.ReorderRoutes,
  77 + this.completer,
70 }) : path = _nameToRegex(name), 78 }) : path = _nameToRegex(name),
71 assert(name.startsWith('/'), 79 assert(name.startsWith('/'),
72 'It is necessary to start route name [$name] with a slash: /$name'), 80 'It is necessary to start route name [$name] with a slash: /$name'),
73 super( 81 super(
74 key: ValueKey(name), 82 key: ValueKey(name),
75 name: name, 83 name: name,
76 - arguments: Get.arguments, 84 + // arguments: Get.arguments,
77 ); 85 );
78 // settings = RouteSettings(name: name, arguments: Get.arguments); 86 // settings = RouteSettings(name: name, arguments: Get.arguments);
79 87
@@ -88,13 +96,14 @@ class GetPage<T> extends Page<T> { @@ -88,13 +96,14 @@ class GetPage<T> extends Page<T> {
88 Alignment? alignment, 96 Alignment? alignment,
89 bool? maintainState, 97 bool? maintainState,
90 bool? opaque, 98 bool? opaque,
91 - BindingsInterface? binding, 99 + List<BindingsInterface>? bindings,
  100 + // BindingsInterface? binding,
92 List<Bind>? binds, 101 List<Bind>? binds,
93 CustomTransition? customTransition, 102 CustomTransition? customTransition,
94 Duration? transitionDuration, 103 Duration? transitionDuration,
95 bool? fullscreenDialog, 104 bool? fullscreenDialog,
96 RouteSettings? settings, 105 RouteSettings? settings,
97 - List<GetPage>? children, 106 + List<GetPage<T>>? children,
98 GetPage? unknownRoute, 107 GetPage? unknownRoute,
99 List<GetMiddleware>? middlewares, 108 List<GetMiddleware>? middlewares,
100 bool? preventDuplicates, 109 bool? preventDuplicates,
@@ -102,6 +111,7 @@ class GetPage<T> extends Page<T> { @@ -102,6 +111,7 @@ class GetPage<T> extends Page<T> {
102 bool? participatesInRootNavigator, 111 bool? participatesInRootNavigator,
103 Object? arguments, 112 Object? arguments,
104 bool? showCupertinoParallax, 113 bool? showCupertinoParallax,
  114 + Completer<T?>? completer,
105 }) { 115 }) {
106 return GetPage( 116 return GetPage(
107 participatesInRootNavigator: 117 participatesInRootNavigator:
@@ -117,7 +127,7 @@ class GetPage<T> extends Page<T> { @@ -117,7 +127,7 @@ class GetPage<T> extends Page<T> {
117 alignment: alignment ?? this.alignment, 127 alignment: alignment ?? this.alignment,
118 maintainState: maintainState ?? this.maintainState, 128 maintainState: maintainState ?? this.maintainState,
119 opaque: opaque ?? this.opaque, 129 opaque: opaque ?? this.opaque,
120 - binding: binding ?? this.binding, 130 + bindings: bindings ?? this.bindings,
121 binds: binds ?? this.binds, 131 binds: binds ?? this.binds,
122 customTransition: customTransition ?? this.customTransition, 132 customTransition: customTransition ?? this.customTransition,
123 transitionDuration: transitionDuration ?? this.transitionDuration, 133 transitionDuration: transitionDuration ?? this.transitionDuration,
@@ -129,6 +139,7 @@ class GetPage<T> extends Page<T> { @@ -129,6 +139,7 @@ class GetPage<T> extends Page<T> {
129 arguments: arguments ?? this.arguments, 139 arguments: arguments ?? this.arguments,
130 showCupertinoParallax: 140 showCupertinoParallax:
131 showCupertinoParallax ?? this.showCupertinoParallax, 141 showCupertinoParallax ?? this.showCupertinoParallax,
  142 + completer: completer ?? this.completer,
132 ); 143 );
133 } 144 }
134 145
@@ -164,6 +175,17 @@ class GetPage<T> extends Page<T> { @@ -164,6 +175,17 @@ class GetPage<T> extends Page<T> {
164 175
165 return PathDecoded(RegExp('^$stringPath\$'), keys); 176 return PathDecoded(RegExp('^$stringPath\$'), keys);
166 } 177 }
  178 +
  179 + @override
  180 + bool operator ==(Object other) {
  181 + if (identical(this, other)) return true;
  182 + return other is GetPage<T> && other.key == key;
  183 + }
  184 +
  185 + @override
  186 + int get hashCode {
  187 + return key.hashCode;
  188 + }
167 } 189 }
168 190
169 @immutable 191 @immutable
  1 +import 'dart:async';
  2 +
  3 +import 'package:flutter/foundation.dart';
  4 +import 'package:flutter/material.dart';
  5 +
  6 +import '../../../get_instance/src/bindings_interface.dart';
  7 +import '../../../get_state_manager/src/simple/list_notifier.dart';
  8 +import '../../../get_utils/src/platform/platform.dart';
  9 +import '../../../route_manager.dart';
  10 +
  11 +/// Enables the user to customize the intended pop behavior
  12 +///
  13 +/// Goes to either the previous _activePages entry or the previous page entry
  14 +///
  15 +/// e.g. if the user navigates to these pages
  16 +/// 1) /home
  17 +/// 2) /home/products/1234
  18 +///
  19 +/// when popping on [History] mode, it will emulate a browser back button.
  20 +///
  21 +/// so the new _activePages stack will be:
  22 +/// 1) /home
  23 +///
  24 +/// when popping on [Page] mode, it will only remove the last part of the route
  25 +/// so the new _activePages stack will be:
  26 +/// 1) /home
  27 +/// 2) /home/products
  28 +///
  29 +/// another pop will change the _activePages stack to:
  30 +/// 1) /home
  31 +enum PopMode {
  32 + History,
  33 + Page,
  34 +}
  35 +
  36 +/// Enables the user to customize the behavior when pushing multiple routes that
  37 +/// shouldn't be duplicates
  38 +enum PreventDuplicateHandlingMode {
  39 + /// Removes the _activePages entries until it reaches the old route
  40 + PopUntilOriginalRoute,
  41 +
  42 + /// Simply don't push the new route
  43 + DoNothing,
  44 +
  45 + /// Recommended - Moves the old route entry to the front
  46 + ///
  47 + /// With this mode, you guarantee there will be only one
  48 + /// route entry for each location
  49 + ReorderRoutes,
  50 +
  51 + Recreate,
  52 +}
  53 +
  54 +class GetDelegate extends RouterDelegate<RouteDecoder>
  55 + with
  56 + ListNotifierSingleMixin,
  57 + PopNavigatorRouterDelegateMixin<RouteDecoder>,
  58 + IGetNavigation {
  59 + final List<RouteDecoder> _activePages = <RouteDecoder>[];
  60 + final PopMode backButtonPopMode;
  61 + final PreventDuplicateHandlingMode preventDuplicateHandlingMode;
  62 +
  63 + final GetPage notFoundRoute;
  64 +
  65 + final List<NavigatorObserver>? navigatorObservers;
  66 + final TransitionDelegate<dynamic>? transitionDelegate;
  67 +
  68 + final Iterable<GetPage> Function(RouteDecoder currentNavStack)?
  69 + pickPagesForRootNavigator;
  70 +
  71 + // GlobalKey<NavigatorState> get navigatorKey => Get.key;
  72 +
  73 + @override
  74 + GlobalKey<NavigatorState> navigatorKey;
  75 +
  76 + final String? restorationScopeId;
  77 +
  78 + GetDelegate({
  79 + GetPage? notFoundRoute,
  80 + this.navigatorObservers,
  81 + this.transitionDelegate,
  82 + this.backButtonPopMode = PopMode.History,
  83 + this.preventDuplicateHandlingMode =
  84 + PreventDuplicateHandlingMode.ReorderRoutes,
  85 + this.pickPagesForRootNavigator,
  86 + this.restorationScopeId,
  87 + bool showHashOnUrl = false,
  88 + GlobalKey<NavigatorState>? navigatorKey,
  89 + required List<GetPage> pages,
  90 + }) : navigatorKey = navigatorKey ?? GlobalKey<NavigatorState>(),
  91 + notFoundRoute = notFoundRoute ??= GetPage(
  92 + name: '/404',
  93 + page: () => Scaffold(
  94 + body: Center(child: Text('Route not found')),
  95 + ),
  96 + ) {
  97 + if (!showHashOnUrl && GetPlatform.isWeb) setUrlStrategy();
  98 + Get.addPages(pages);
  99 + Get.addPage(notFoundRoute);
  100 + Get.log('GetDelegate is created !');
  101 + }
  102 +
  103 + Future<RouteDecoder?> runMiddleware(RouteDecoder config) async {
  104 + final middlewares = config.currentTreeBranch.last.middlewares;
  105 + if (middlewares == null) {
  106 + return config;
  107 + }
  108 + var iterator = config;
  109 + for (var item in middlewares) {
  110 + var redirectRes = await item.redirect(iterator);
  111 + if (redirectRes == null) return null;
  112 + iterator = redirectRes;
  113 + }
  114 + return iterator;
  115 + }
  116 +
  117 + Future<void> _unsafeHistoryAdd(RouteDecoder config) async {
  118 + final res = await runMiddleware(config);
  119 + if (res == null) return;
  120 + _activePages.add(res);
  121 + }
  122 +
  123 + Future<T?> _unsafeHistoryRemove<T>(RouteDecoder config, T result) async {
  124 + var index = _activePages.indexOf(config);
  125 + if (index >= 0) return _unsafeHistoryRemoveAt(index, result);
  126 + }
  127 +
  128 + Future<T?> _unsafeHistoryRemoveAt<T>(int index, T result) async {
  129 + if (index == _activePages.length - 1 && _activePages.length > 1) {
  130 + //removing WILL update the current route
  131 + final toCheck = _activePages[_activePages.length - 2];
  132 + final resMiddleware = await runMiddleware(toCheck);
  133 + if (resMiddleware == null) return null;
  134 + _activePages[_activePages.length - 2] = resMiddleware;
  135 + }
  136 +
  137 + final completer = _activePages.removeAt(index).route?.completer;
  138 + if (completer?.isCompleted == false) completer!.complete(result);
  139 +
  140 + return completer?.future as T?;
  141 + }
  142 +
  143 + T arguments<T>() {
  144 + return currentConfiguration?.pageSettings?.arguments as T;
  145 + }
  146 +
  147 + Map<String, String> get parameters {
  148 + return currentConfiguration?.pageSettings?.params ?? {};
  149 + }
  150 +
  151 + PageSettings? get pageSettings {
  152 + return currentConfiguration?.pageSettings;
  153 + }
  154 +
  155 + Future<T?> _removeHistoryEntry<T>(RouteDecoder entry, T result) async {
  156 + return _unsafeHistoryRemove<T>(entry, result);
  157 + }
  158 +
  159 + Future<void> _pushHistory(RouteDecoder config) async {
  160 + if (config.route!.preventDuplicates) {
  161 + final originalEntryIndex = _activePages.indexWhere(
  162 + (element) => element.pageSettings?.name == config.pageSettings?.name);
  163 + if (originalEntryIndex >= 0) {
  164 + switch (preventDuplicateHandlingMode) {
  165 + case PreventDuplicateHandlingMode.PopUntilOriginalRoute:
  166 + popModeUntil(config.pageSettings!.name, popMode: PopMode.Page);
  167 + break;
  168 + case PreventDuplicateHandlingMode.ReorderRoutes:
  169 + await _unsafeHistoryRemoveAt(originalEntryIndex, null);
  170 + await _unsafeHistoryAdd(config);
  171 + break;
  172 + case PreventDuplicateHandlingMode.DoNothing:
  173 + default:
  174 + break;
  175 + }
  176 + return;
  177 + }
  178 + }
  179 + await _unsafeHistoryAdd(config);
  180 + }
  181 +
  182 + Future<T?> _popHistory<T>(T result) async {
  183 + if (!_canPopHistory()) return null;
  184 + return await _doPopHistory(result);
  185 + }
  186 +
  187 + Future<T?> _doPopHistory<T>(T result) async {
  188 + return _unsafeHistoryRemoveAt<T>(_activePages.length - 1, result);
  189 + }
  190 +
  191 + Future<T?> _popPage<T>(T result) async {
  192 + if (!_canPopPage()) return null;
  193 + return await _doPopPage(result);
  194 + }
  195 +
  196 + // returns the popped page
  197 + Future<T?> _doPopPage<T>(T result) async {
  198 + final currentBranch = currentConfiguration?.currentTreeBranch;
  199 + if (currentBranch != null && currentBranch.length > 1) {
  200 + //remove last part only
  201 + final remaining = currentBranch.take(currentBranch.length - 1);
  202 + final prevHistoryEntry = _activePages.length > 1
  203 + ? _activePages[_activePages.length - 2]
  204 + : null;
  205 +
  206 + //check if current route is the same as the previous route
  207 + if (prevHistoryEntry != null) {
  208 + //if so, pop the entire _activePages entry
  209 + final newLocation = remaining.last.name;
  210 + final prevLocation = prevHistoryEntry.pageSettings?.name;
  211 + if (newLocation == prevLocation) {
  212 + //pop the entire _activePages entry
  213 + return await _popHistory(result);
  214 + }
  215 + }
  216 +
  217 + //create a new route with the remaining tree branch
  218 + final res = await _popHistory<T>(result);
  219 + await _pushHistory(
  220 + RouteDecoder(
  221 + remaining.toList(),
  222 + null,
  223 + //TOOD: persist state??
  224 + ),
  225 + );
  226 + return res;
  227 + } else {
  228 + //remove entire entry
  229 + return await _popHistory(result);
  230 + }
  231 + }
  232 +
  233 + Future<T?> _pop<T>(PopMode mode, T result) async {
  234 + switch (mode) {
  235 + case PopMode.History:
  236 + return await _popHistory<T>(result);
  237 + case PopMode.Page:
  238 + return await _popPage<T>(result);
  239 + default:
  240 + return null;
  241 + }
  242 + }
  243 +
  244 + Future<T?> popHistory<T>(T result) async {
  245 + return await _popHistory<T>(result);
  246 + }
  247 +
  248 + bool _canPopHistory() {
  249 + return _activePages.length > 1;
  250 + }
  251 +
  252 + Future<bool> canPopHistory() {
  253 + return SynchronousFuture(_canPopHistory());
  254 + }
  255 +
  256 + bool _canPopPage() {
  257 + final currentTreeBranch = currentConfiguration?.currentTreeBranch;
  258 + if (currentTreeBranch == null) return false;
  259 + return currentTreeBranch.length > 1 ? true : _canPopHistory();
  260 + }
  261 +
  262 + Future<bool> canPopPage() {
  263 + return SynchronousFuture(_canPopPage());
  264 + }
  265 +
  266 + bool _canPop(mode) {
  267 + switch (mode) {
  268 + case PopMode.History:
  269 + return _canPopHistory();
  270 + case PopMode.Page:
  271 + default:
  272 + return _canPopPage();
  273 + }
  274 + }
  275 +
  276 + /// gets the visual pages from the current _activePages entry
  277 + ///
  278 + /// visual pages must have [GetPage.participatesInRootNavigator] set to true
  279 + Iterable<GetPage> getVisualPages(RouteDecoder? currentHistory) {
  280 + final res = currentHistory!.currentTreeBranch
  281 + .where((r) => r.participatesInRootNavigator != null);
  282 + if (res.length == 0) {
  283 + //default behavoir, all routes participate in root navigator
  284 + return _activePages.map((e) => e.route!);
  285 + } else {
  286 + //user specified at least one participatesInRootNavigator
  287 + return res
  288 + .where((element) => element.participatesInRootNavigator == true);
  289 + }
  290 + }
  291 +
  292 + @override
  293 + Widget build(BuildContext context) {
  294 + final currentHistory = currentConfiguration;
  295 + final pages = currentHistory == null
  296 + ? <GetPage>[]
  297 + : pickPagesForRootNavigator?.call(currentHistory) ??
  298 + getVisualPages(currentHistory);
  299 + if (pages.length == 0) return SizedBox.shrink();
  300 + return GetNavigator(
  301 + key: navigatorKey,
  302 + onPopPage: _onPopVisualRoute,
  303 + pages: pages.toList(),
  304 + observers: navigatorObservers,
  305 + transitionDelegate:
  306 + transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
  307 + );
  308 + }
  309 +
  310 + @override
  311 + void goToUnknownPage([bool clearPages = false]) {
  312 + if (clearPages) _activePages.clear();
  313 +
  314 + final pageSettings = _buildPageSettings(notFoundRoute.name);
  315 + final routeDecoder = _getRouteDecoder(pageSettings);
  316 +
  317 + _push(routeDecoder!);
  318 + }
  319 +
  320 + @protected
  321 + void _popWithResult<T>([T? result]) {
  322 + final completer = _activePages.removeLast().route?.completer;
  323 + if (completer?.isCompleted == false) completer!.complete(result);
  324 + }
  325 +
  326 + @override
  327 + Future<T?> toNamed<T>(
  328 + String page, {
  329 + dynamic arguments,
  330 + int? id,
  331 + bool preventDuplicates = true,
  332 + Map<String, String>? parameters,
  333 + }) async {
  334 + final args = _buildPageSettings(page, arguments);
  335 + final route = _getRouteDecoder<T>(args);
  336 + if (route != null) {
  337 + return _push<T>(route);
  338 + } else {
  339 + goToUnknownPage();
  340 + }
  341 + }
  342 +
  343 + @override
  344 + Future<T?> to<T>(Widget Function() page,
  345 + {bool? opaque,
  346 + Transition? transition,
  347 + Curve? curve,
  348 + Duration? duration,
  349 + int? id,
  350 + String? routeName,
  351 + bool fullscreenDialog = false,
  352 + dynamic arguments,
  353 + List<BindingsInterface>? bindings,
  354 + bool preventDuplicates = true,
  355 + bool? popGesture,
  356 + bool showCupertinoParallax = true,
  357 + double Function(BuildContext context)? gestureWidth,
  358 + bool rebuildStack = true,
  359 + PreventDuplicateHandlingMode preventDuplicateHandlingMode =
  360 + PreventDuplicateHandlingMode.ReorderRoutes}) async {
  361 + routeName = _cleanRouteName("/${page.runtimeType}");
  362 + if (preventDuplicateHandlingMode == PreventDuplicateHandlingMode.Recreate) {
  363 + routeName = routeName + page.hashCode.toString();
  364 + }
  365 +
  366 + final getPage = GetPage<T>(
  367 + name: routeName,
  368 + opaque: opaque ?? true,
  369 + page: page,
  370 + gestureWidth: gestureWidth,
  371 + showCupertinoParallax: showCupertinoParallax,
  372 + popGesture: popGesture ?? Get.defaultPopGesture,
  373 + transition: transition ?? Get.defaultTransition,
  374 + curve: curve ?? Get.defaultTransitionCurve,
  375 + fullscreenDialog: fullscreenDialog,
  376 + bindings: bindings,
  377 + transitionDuration: duration ?? Get.defaultTransitionDuration,
  378 + preventDuplicateHandlingMode: preventDuplicateHandlingMode,
  379 + );
  380 +
  381 + Get.addPage(getPage);
  382 + final args = _buildPageSettings(routeName, arguments);
  383 + final route = _getRouteDecoder<T>(args);
  384 + final result = await _push<T>(
  385 + route!,
  386 + rebuildStack: rebuildStack,
  387 + preventDuplicateHandlingMode: preventDuplicateHandlingMode,
  388 + );
  389 + Get.removePage(getPage);
  390 + return result;
  391 + }
  392 +
  393 + @override
  394 + Future<T?> off<T>(
  395 + Widget Function() page, {
  396 + bool? opaque,
  397 + Transition? transition,
  398 + Curve? curve,
  399 + Duration? duration,
  400 + int? id,
  401 + String? routeName,
  402 + bool fullscreenDialog = false,
  403 + dynamic arguments,
  404 + List<BindingsInterface>? bindings,
  405 + bool preventDuplicates = true,
  406 + bool? popGesture,
  407 + bool showCupertinoParallax = true,
  408 + double Function(BuildContext context)? gestureWidth,
  409 + }) async {
  410 + routeName = _cleanRouteName("/${page.runtimeType}");
  411 + final route = GetPage<T>(
  412 + name: routeName,
  413 + opaque: opaque ?? true,
  414 + page: page,
  415 + gestureWidth: gestureWidth,
  416 + showCupertinoParallax: showCupertinoParallax,
  417 + popGesture: popGesture ?? Get.defaultPopGesture,
  418 + transition: transition ?? Get.defaultTransition,
  419 + curve: curve ?? Get.defaultTransitionCurve,
  420 + fullscreenDialog: fullscreenDialog,
  421 + bindings: bindings,
  422 + transitionDuration: duration ?? Get.defaultTransitionDuration,
  423 + );
  424 +
  425 + final args = _buildPageSettings(routeName, arguments);
  426 + return _replace(args, route);
  427 + }
  428 +
  429 + @override
  430 + Future<T?>? offAll<T>(
  431 + Widget Function() page, {
  432 + bool Function(GetPage route)? predicate,
  433 + bool opaque = true,
  434 + bool? popGesture,
  435 + int? id,
  436 + String? routeName,
  437 + dynamic arguments,
  438 + List<BindingsInterface>? bindings,
  439 + bool fullscreenDialog = false,
  440 + Transition? transition,
  441 + Curve? curve,
  442 + Duration? duration,
  443 + bool showCupertinoParallax = true,
  444 + double Function(BuildContext context)? gestureWidth,
  445 + }) async {
  446 + routeName = _cleanRouteName("/${page.runtimeType}");
  447 + final route = GetPage<T>(
  448 + name: routeName,
  449 + opaque: opaque,
  450 + page: page,
  451 + gestureWidth: gestureWidth,
  452 + showCupertinoParallax: showCupertinoParallax,
  453 + popGesture: popGesture ?? Get.defaultPopGesture,
  454 + transition: transition ?? Get.defaultTransition,
  455 + curve: curve ?? Get.defaultTransitionCurve,
  456 + fullscreenDialog: fullscreenDialog,
  457 + bindings: bindings,
  458 + transitionDuration: duration ?? Get.defaultTransitionDuration,
  459 + );
  460 +
  461 + final args = _buildPageSettings(routeName, arguments);
  462 +
  463 + final newPredicate = predicate ?? (route) => false;
  464 +
  465 + while (_activePages.length > 1 && !newPredicate(_activePages.last.route!)) {
  466 + _popWithResult();
  467 + }
  468 +
  469 + return _replace(args, route);
  470 + }
  471 +
  472 + @override
  473 + Future<T?>? offAllNamed<T>(
  474 + String page, {
  475 + // bool Function(GetPage route)? predicate,
  476 + dynamic arguments,
  477 + int? id,
  478 + Map<String, String>? parameters,
  479 + }) async {
  480 + final args = _buildPageSettings(page, arguments);
  481 + final route = _getRouteDecoder<T>(args);
  482 + if (route == null) return null;
  483 +
  484 + while (_activePages.length > 1) {
  485 + _activePages.removeLast();
  486 + }
  487 +
  488 + return _replaceNamed(route);
  489 + }
  490 +
  491 + @override
  492 + Future<T?>? offNamedUntil<T>(
  493 + String page, {
  494 + bool Function(GetPage route)? predicate,
  495 + dynamic arguments,
  496 + int? id,
  497 + Map<String, String>? parameters,
  498 + }) async {
  499 + final args = _buildPageSettings(page, arguments);
  500 + final route = _getRouteDecoder<T>(args);
  501 + if (route == null) return null;
  502 +
  503 + final newPredicate = predicate ?? (route) => false;
  504 +
  505 + while (_activePages.length > 1 && newPredicate(_activePages.last.route!)) {
  506 + _activePages.removeLast();
  507 + }
  508 +
  509 + return _replaceNamed(route);
  510 + }
  511 +
  512 + @override
  513 + Future<T?> offNamed<T>(
  514 + String page, {
  515 + dynamic arguments,
  516 + int? id,
  517 + Map<String, String>? parameters,
  518 + }) async {
  519 + final args = _buildPageSettings(page, arguments);
  520 + final route = _getRouteDecoder<T>(args);
  521 + if (route == null) return null;
  522 + _popWithResult();
  523 + return _push<T>(route);
  524 + }
  525 +
  526 + @override
  527 + Future<T?> toNamedAndOffUntil<T>(
  528 + String page,
  529 + bool Function(GetPage) predicate, [
  530 + Object? data,
  531 + ]) async {
  532 + final arguments = _buildPageSettings(page, data);
  533 +
  534 + final route = _getRouteDecoder<T>(arguments);
  535 +
  536 + if (route == null) return null;
  537 +
  538 + while (_activePages.isNotEmpty && !predicate(_activePages.last.route!)) {
  539 + _popWithResult();
  540 + }
  541 +
  542 + return _push<T>(route);
  543 + }
  544 +
  545 + @override
  546 + Future<T?> offUntil<T>(
  547 + Widget Function() page,
  548 + bool Function(GetPage) predicate, [
  549 + Object? arguments,
  550 + ]) async {
  551 + while (_activePages.isNotEmpty && !predicate(_activePages.last.route!)) {
  552 + _popWithResult();
  553 + }
  554 +
  555 + return to<T>(page, arguments: arguments);
  556 + }
  557 +
  558 + @override
  559 + void removeRoute<T>(String name) {
  560 + _activePages.remove(RouteDecoder.fromRoute(name));
  561 + }
  562 +
  563 + @override
  564 + void back<T>([T? result]) {
  565 + _checkIfCanBack();
  566 + _popWithResult<T>(result);
  567 + refresh();
  568 + }
  569 +
  570 + bool get canBack {
  571 + return _activePages.length > 1;
  572 + }
  573 +
  574 + void _checkIfCanBack() {
  575 + assert(() {
  576 + if (!canBack) {
  577 + final last = _activePages.last;
  578 + final name = last.route?.name;
  579 + throw 'The page $name cannot be popped';
  580 + }
  581 + return true;
  582 + }());
  583 + }
  584 +
  585 + @override
  586 + Future<R?> backAndtoNamed<T, R>(String page,
  587 + {T? result, Object? arguments}) async {
  588 + final args = _buildPageSettings(page, arguments);
  589 + final route = _getRouteDecoder<R>(args);
  590 + if (route == null) return null;
  591 + _popWithResult<T>(result);
  592 + return _push<R>(route);
  593 + }
  594 +
  595 + /// Removes routes according to [PopMode]
  596 + /// until it reaches the specifc [fullRoute],
  597 + /// DOES NOT remove the [fullRoute]
  598 + @override
  599 + Future<void> popModeUntil(
  600 + String fullRoute, {
  601 + PopMode popMode = PopMode.History,
  602 + }) async {
  603 + // remove history or page entries until you meet route
  604 + var iterator = currentConfiguration;
  605 + while (_canPop(popMode) &&
  606 + iterator != null &&
  607 + iterator.pageSettings?.name != fullRoute) {
  608 + await _pop(popMode, null);
  609 + // replace iterator
  610 + iterator = currentConfiguration;
  611 + }
  612 + refresh();
  613 + }
  614 +
  615 + @override
  616 + void backUntil(bool Function(GetPage) predicate) {
  617 + while (_activePages.length <= 1 && !predicate(_activePages.last.route!)) {
  618 + _popWithResult();
  619 + }
  620 +
  621 + refresh();
  622 + }
  623 +
  624 + Future<T?> _replace<T>(PageSettings arguments, GetPage<T> page) async {
  625 + final index = _activePages.length > 1 ? _activePages.length - 1 : 0;
  626 + Get.addPage(page);
  627 +
  628 + final route = _getRouteDecoder(arguments);
  629 +
  630 + final activePage = _configureRouterDecoder<T>(route!, arguments);
  631 +
  632 + _activePages[index] = activePage;
  633 +
  634 + refresh();
  635 + final result = await activePage.route?.completer?.future as Future<T?>?;
  636 + Get.removePage(page);
  637 +
  638 + return result;
  639 + }
  640 +
  641 + Future<T?> _replaceNamed<T>(RouteDecoder activePage) async {
  642 + final index = _activePages.length > 1 ? _activePages.length - 1 : 0;
  643 + // final activePage = _configureRouterDecoder<T>(page, arguments);
  644 + _activePages[index] = activePage;
  645 +
  646 + refresh();
  647 + final result = await activePage.route?.completer?.future as Future<T?>?;
  648 + return result;
  649 + }
  650 +
  651 + /// Takes a route [name] String generated by [to], [off], [offAll]
  652 + /// (and similar context navigation methods), cleans the extra chars and
  653 + /// accommodates the format.
  654 + /// TODO: check for a more "appealing" URL naming convention.
  655 + /// `() => MyHomeScreenView` becomes `/my-home-screen-view`.
  656 + String _cleanRouteName(String name) {
  657 + name = name.replaceAll('() => ', '');
  658 +
  659 + /// uncommonent for URL styling.
  660 + // name = name.paramCase!;
  661 + if (!name.startsWith('/')) {
  662 + name = '/$name';
  663 + }
  664 + return Uri.tryParse(name)?.toString() ?? name;
  665 + }
  666 +
  667 + PageSettings _buildPageSettings(String page, [Object? data]) {
  668 + var uri = Uri.parse(page);
  669 + return PageSettings(uri, data);
  670 + }
  671 +
  672 + @protected
  673 + RouteDecoder? _getRouteDecoder<T>(PageSettings arguments) {
  674 + var page = arguments.uri.path;
  675 + final parameters = arguments.params;
  676 + if (parameters.isNotEmpty) {
  677 + final uri = Uri(path: page, queryParameters: parameters);
  678 + page = uri.toString();
  679 + }
  680 +
  681 + final decoder = Get.routeTree.matchRoute(page, arguments: arguments);
  682 + final route = decoder.route;
  683 + if (route == null) return null;
  684 + return _configureRouterDecoder(decoder, arguments);
  685 + }
  686 +
  687 + @protected
  688 + RouteDecoder _configureRouterDecoder<T>(
  689 + RouteDecoder decoder, PageSettings arguments) {
  690 + final parameters =
  691 + arguments.params.isEmpty ? arguments.query : arguments.params;
  692 + if (arguments.params.isEmpty) {
  693 + arguments.params.addAll(arguments.query);
  694 + }
  695 + if (decoder.parameters.isEmpty) {
  696 + decoder.parameters.addAll(parameters);
  697 + }
  698 +
  699 + decoder.route = decoder.route?.copy(
  700 + completer: _activePages.isEmpty ? null : Completer(),
  701 + arguments: arguments,
  702 + parameters: parameters,
  703 + );
  704 + return decoder;
  705 + }
  706 +
  707 + Future<T?> _push<T>(RouteDecoder activePage,
  708 + {bool rebuildStack = true,
  709 + PreventDuplicateHandlingMode preventDuplicateHandlingMode =
  710 + PreventDuplicateHandlingMode.ReorderRoutes}) async {
  711 + final onStackPage = _activePages.firstWhereOrNull(
  712 + (element) => element.route?.key == activePage.route?.key);
  713 +
  714 + /// There are no duplicate routes in the stack
  715 + if (onStackPage == null) {
  716 + final res = await runMiddleware(activePage);
  717 + _activePages.add(res!);
  718 + } else {
  719 + /// There are duplicate routes, reorder
  720 + switch (preventDuplicateHandlingMode) {
  721 + case PreventDuplicateHandlingMode.DoNothing:
  722 + break;
  723 + case PreventDuplicateHandlingMode.ReorderRoutes:
  724 + _activePages.remove(onStackPage);
  725 + final res = await runMiddleware(onStackPage);
  726 + _activePages.add(res!);
  727 + break;
  728 + case PreventDuplicateHandlingMode.PopUntilOriginalRoute:
  729 + while (_activePages.last == onStackPage) {
  730 + _popWithResult();
  731 + }
  732 + break;
  733 + case PreventDuplicateHandlingMode.Recreate:
  734 + _activePages.remove(onStackPage);
  735 + final res = await runMiddleware(activePage);
  736 + _activePages.add(res!);
  737 + break;
  738 + default:
  739 + }
  740 + }
  741 + if (rebuildStack) {
  742 + refresh();
  743 + }
  744 +
  745 + return activePage.route?.completer?.future as Future<T?>?;
  746 + }
  747 +
  748 + @override
  749 + Future<void> setNewRoutePath(RouteDecoder configuration) async {
  750 + final page = configuration.route;
  751 + if (page == null) {
  752 + goToUnknownPage();
  753 + return;
  754 + } else {
  755 + _push(configuration);
  756 + }
  757 + }
  758 +
  759 + @override
  760 + RouteDecoder? get currentConfiguration {
  761 + if (_activePages.isEmpty) return null;
  762 + final route = _activePages.last;
  763 + return route;
  764 + }
  765 +
  766 + Future<bool> handlePopupRoutes({
  767 + Object? result,
  768 + }) async {
  769 + Route? currentRoute;
  770 + navigatorKey.currentState!.popUntil((route) {
  771 + currentRoute = route;
  772 + return true;
  773 + });
  774 + if (currentRoute is PopupRoute) {
  775 + return await navigatorKey.currentState!.maybePop(result);
  776 + }
  777 + return false;
  778 + }
  779 +
  780 + @override
  781 + Future<bool> popRoute({
  782 + Object? result,
  783 + PopMode? popMode,
  784 + }) async {
  785 + //Returning false will cause the entire app to be popped.
  786 + final wasPopup = await handlePopupRoutes(result: result);
  787 + if (wasPopup) return true;
  788 + final _popped = await _pop(popMode ?? backButtonPopMode, result);
  789 + refresh();
  790 + if (_popped != null) {
  791 + //emulate the old pop with result
  792 + return true;
  793 + }
  794 + return false;
  795 + }
  796 +
  797 + bool _onPopVisualRoute(Route<dynamic> route, dynamic result) {
  798 + final didPop = route.didPop(result);
  799 + if (!didPop) {
  800 + return false;
  801 + }
  802 + final settings = route.settings;
  803 + if (settings is GetPage) {
  804 + final config = _activePages.cast<RouteDecoder?>().firstWhere(
  805 + (element) => element?.route == settings,
  806 + orElse: () => null,
  807 + );
  808 + if (config != null) {
  809 + _removeHistoryEntry(config, result);
  810 + }
  811 + }
  812 + refresh();
  813 +
  814 + return true;
  815 + }
  816 +}
  1 +export 'circular_reveal_clipper.dart';
  2 +export 'custom_transition.dart';
  3 +export 'default_route.dart';
  4 +export 'default_transitions.dart';
  5 +export 'get_information_parser.dart';
  6 +export 'get_navigation_interface.dart';
  7 +export 'get_navigator.dart';
  8 +export 'get_route.dart';
  9 +export 'get_router_delegate.dart';
  10 +export 'get_transition_mixin.dart';
  11 +export 'modules.dart';
  12 +export 'observers/route_observer.dart';
  13 +export 'page_settings.dart';
  14 +export 'parse_route.dart';
  15 +export 'route_middleware.dart';
  16 +export 'route_report.dart';
  17 +export 'router_outlet.dart';
  18 +export 'transitions_type.dart';
  19 +export 'url_strategy/url_strategy.dart';
@@ -98,7 +98,7 @@ class GetObserver extends NavigatorObserver { @@ -98,7 +98,7 @@ class GetObserver extends NavigatorObserver {
98 } 98 }
99 99
100 RouterReportManager.instance.reportCurrentRoute(route); 100 RouterReportManager.instance.reportCurrentRoute(route);
101 - _routeSend?.update((value) { 101 + _routeSend!.update((value) {
102 // Only PageRoute is allowed to change current value 102 // Only PageRoute is allowed to change current value
103 if (route is PageRoute) { 103 if (route is PageRoute) {
104 value.current = newRoute.name ?? ''; 104 value.current = newRoute.name ?? '';
@@ -216,7 +216,6 @@ class Routing { @@ -216,7 +216,6 @@ class Routing {
216 /// This is basically a util for rules about 'what a route is' 216 /// This is basically a util for rules about 'what a route is'
217 class _RouteData { 217 class _RouteData {
218 final bool isGetPageRoute; 218 final bool isGetPageRoute;
219 - //final bool isSnackbar;  
220 final bool isBottomSheet; 219 final bool isBottomSheet;
221 final bool isDialog; 220 final bool isDialog;
222 final String? name; 221 final String? name;
@@ -224,7 +223,6 @@ class _RouteData { @@ -224,7 +223,6 @@ class _RouteData {
224 _RouteData({ 223 _RouteData({
225 required this.name, 224 required this.name,
226 required this.isGetPageRoute, 225 required this.isGetPageRoute,
227 - // required this.isSnackbar,  
228 required this.isBottomSheet, 226 required this.isBottomSheet,
229 required this.isDialog, 227 required this.isDialog,
230 }); 228 });
@@ -233,7 +231,6 @@ class _RouteData { @@ -233,7 +231,6 @@ class _RouteData {
233 return _RouteData( 231 return _RouteData(
234 name: _extractRouteName(route), 232 name: _extractRouteName(route),
235 isGetPageRoute: route is GetPageRoute, 233 isGetPageRoute: route is GetPageRoute,
236 - // isSnackbar: route is SnackRoute,  
237 isDialog: route is GetDialogRoute, 234 isDialog: route is GetDialogRoute,
238 isBottomSheet: route is GetModalBottomSheetRoute, 235 isBottomSheet: route is GetModalBottomSheetRoute,
239 ); 236 );
  1 +import 'package:flutter/widgets.dart';
  2 +
  3 +import '../../../route_manager.dart';
  4 +
  5 +extension PageArgExt on BuildContext {
  6 + RouteSettings? get settings {
  7 + return ModalRoute.of(this)!.settings;
  8 + }
  9 +
  10 + PageSettings? get pageSettings {
  11 + final args = ModalRoute.of(this)?.settings.arguments;
  12 + if (args is PageSettings) {
  13 + return args;
  14 + }
  15 + return null;
  16 + }
  17 +
  18 + dynamic get arguments {
  19 + final args = settings?.arguments;
  20 + if (args is PageSettings) {
  21 + return args.arguments;
  22 + } else {
  23 + return args;
  24 + }
  25 + }
  26 +
  27 + Map<String, String> get params {
  28 + final args = settings?.arguments;
  29 + if (args is PageSettings) {
  30 + return args.params;
  31 + } else {
  32 + return {};
  33 + }
  34 + }
  35 +
  36 + Router get router {
  37 + return Router.of(this);
  38 + }
  39 +
  40 + String get location {
  41 + final parser = router.routeInformationParser;
  42 + final config = delegate.currentConfiguration;
  43 + return parser?.restoreRouteInformation(config)?.location ?? '/';
  44 + }
  45 +
  46 + RouterDelegate get delegate {
  47 + return router.routerDelegate;
  48 + }
  49 +
  50 + GetDelegate get navigation {
  51 + return router.routerDelegate as GetDelegate;
  52 + }
  53 +}
  54 +
  55 +class PageSettings extends RouteSettings {
  56 + PageSettings(
  57 + this.uri, [
  58 + this.arguments,
  59 + ]);
  60 +
  61 + @override
  62 + String get name => '$uri';
  63 +
  64 + @override
  65 + late final Object? arguments;
  66 +
  67 + final Uri uri;
  68 +
  69 + final params = <String, String>{};
  70 +
  71 + String get path => uri.path;
  72 +
  73 + List<String> get paths => uri.pathSegments;
  74 +
  75 + Map<String, String> get query => uri.queryParameters;
  76 +
  77 + Map<String, List<String>> get queries => uri.queryParametersAll;
  78 +
  79 + @override
  80 + String toString() => name;
  81 +
  82 + PageSettings copy({
  83 + Uri? uri,
  84 + Object? arguments,
  85 + }) {
  86 + return PageSettings(
  87 + uri ?? this.uri,
  88 + arguments ?? this.arguments,
  89 + );
  90 + }
  91 +
  92 + @override
  93 + bool operator ==(Object other) {
  94 + if (identical(this, other)) return true;
  95 +
  96 + return other is PageSettings &&
  97 + other.uri == uri &&
  98 + other.arguments == arguments;
  99 + }
  100 +
  101 + @override
  102 + int get hashCode => uri.hashCode ^ arguments.hashCode;
  103 +}
1 -import '../../get_navigation.dart'; 1 +import '../../../route_manager.dart';
2 2
3 class RouteDecoder { 3 class RouteDecoder {
4 - final List<GetPage> treeBranch;  
5 - GetPage? get route => treeBranch.isEmpty ? null : treeBranch.last;  
6 - final Map<String, String> parameters;  
7 - final Object? arguments;  
8 const RouteDecoder( 4 const RouteDecoder(
9 - this.treeBranch,  
10 - this.parameters,  
11 - this.arguments, 5 + this.currentTreeBranch,
  6 + this.pageSettings,
12 ); 7 );
13 - void replaceArguments(Object? arguments) {  
14 - final _route = route;  
15 - if (_route != null) {  
16 - final index = treeBranch.indexOf(_route);  
17 - treeBranch[index] = _route.copy(arguments: arguments); 8 + final List<GetPage> currentTreeBranch;
  9 + final PageSettings? pageSettings;
  10 +
  11 + factory RouteDecoder.fromRoute(String location) {
  12 + var uri = Uri.parse(location);
  13 + final args = PageSettings(uri);
  14 + final decoder = Get.routeTree.matchRoute(location, arguments: args);
  15 + decoder.route = decoder.route?.copy(
  16 + completer: null,
  17 + arguments: args,
  18 + parameters: args.params,
  19 + );
  20 + return decoder;
  21 + }
  22 +
  23 + GetPage? get route =>
  24 + currentTreeBranch.isEmpty ? null : currentTreeBranch.last;
  25 +
  26 + GetPage routeOrUnknown(GetPage onUnknow) =>
  27 + currentTreeBranch.isEmpty ? onUnknow : currentTreeBranch.last;
  28 +
  29 + set route(GetPage? getPage) {
  30 + if (getPage == null) return;
  31 + if (currentTreeBranch.isEmpty) {
  32 + currentTreeBranch.add(getPage);
  33 + } else {
  34 + currentTreeBranch[currentTreeBranch.length - 1] = getPage;
  35 + }
  36 + }
  37 +
  38 + List<GetPage>? get currentChildrens => route?.children;
  39 +
  40 + Map<String, String> get parameters => pageSettings?.params ?? {};
  41 +
  42 + dynamic get args {
  43 + return pageSettings?.arguments;
  44 + }
  45 +
  46 + T? arguments<T>() {
  47 + final args = pageSettings?.arguments;
  48 + if (args is T) {
  49 + return pageSettings?.arguments as T;
  50 + } else {
  51 + return null;
18 } 52 }
19 } 53 }
20 54
21 - void replaceParameters(Object? arguments) { 55 + void replaceArguments(Object? arguments) {
22 final _route = route; 56 final _route = route;
23 if (_route != null) { 57 if (_route != null) {
24 - final index = treeBranch.indexOf(_route);  
25 - treeBranch[index] = _route.copy(parameters: parameters); 58 + final index = currentTreeBranch.indexOf(_route);
  59 + currentTreeBranch[index] = _route.copy(arguments: arguments);
26 } 60 }
27 } 61 }
28 } 62 }
@@ -34,7 +68,7 @@ class ParseRouteTree { @@ -34,7 +68,7 @@ class ParseRouteTree {
34 68
35 final List<GetPage> routes; 69 final List<GetPage> routes;
36 70
37 - RouteDecoder matchRoute(String name, {Object? arguments}) { 71 + RouteDecoder matchRoute(String name, {PageSettings? arguments}) {
38 final uri = Uri.parse(name); 72 final uri = Uri.parse(name);
39 // /home/profile/123 => home,profile,123 => /,/home,/home/profile,/home/profile/123 73 // /home/profile/123 => home,profile,123 => /,/home,/home/profile,/home/profile/123
40 final split = uri.path.split('/').where((element) => element.isNotEmpty); 74 final split = uri.path.split('/').where((element) => element.isNotEmpty);
@@ -77,28 +111,44 @@ class ParseRouteTree { @@ -77,28 +111,44 @@ class ParseRouteTree {
77 ), 111 ),
78 ) 112 )
79 .toList(); 113 .toList();
  114 + arguments?.params.clear();
  115 + arguments?.params.addAll(params);
80 return RouteDecoder( 116 return RouteDecoder(
81 mappedTreeBranch, 117 mappedTreeBranch,
82 - params,  
83 arguments, 118 arguments,
84 ); 119 );
85 } 120 }
86 121
  122 + arguments?.params.clear();
  123 + arguments?.params.addAll(params);
  124 +
87 //route not found 125 //route not found
88 return RouteDecoder( 126 return RouteDecoder(
89 treeBranch.map((e) => e.value).toList(), 127 treeBranch.map((e) => e.value).toList(),
90 - params,  
91 arguments, 128 arguments,
92 ); 129 );
93 } 130 }
94 131
95 - void addRoutes(List<GetPage> getPages) { 132 + void addRoutes<T>(List<GetPage<T>> getPages) {
96 for (final route in getPages) { 133 for (final route in getPages) {
97 addRoute(route); 134 addRoute(route);
98 } 135 }
99 } 136 }
100 137
101 - void addRoute(GetPage route) { 138 + void removeRoutes<T>(List<GetPage<T>> getPages) {
  139 + for (final route in getPages) {
  140 + removeRoute(route);
  141 + }
  142 + }
  143 +
  144 + void removeRoute<T>(GetPage<T> route) {
  145 + routes.remove(route);
  146 + for (var page in _flattenPage(route)) {
  147 + removeRoute(page);
  148 + }
  149 + }
  150 +
  151 + void addRoute<T>(GetPage<T> route) {
102 routes.add(route); 152 routes.add(route);
103 153
104 // Add Page children. 154 // Add Page children.
@@ -152,9 +202,11 @@ class ParseRouteTree { @@ -152,9 +202,11 @@ class ParseRouteTree {
152 ); 202 );
153 203
154 GetPage? _findRoute(String name) { 204 GetPage? _findRoute(String name) {
155 - return routes.firstWhereOrNull( 205 + final value = routes.firstWhereOrNull(
156 (route) => route.path.regex.hasMatch(name), 206 (route) => route.path.regex.hasMatch(name),
157 ); 207 );
  208 +
  209 + return value;
158 } 210 }
159 211
160 Map<String, String> _parseParams(String path, PathDecoded routePath) { 212 Map<String, String> _parseParams(String path, PathDecoded routePath) {
@@ -177,7 +229,7 @@ class ParseRouteTree { @@ -177,7 +229,7 @@ class ParseRouteTree {
177 } 229 }
178 } 230 }
179 231
180 -extension FirstWhereExt<T> on List<T> { 232 +extension FirstWhereOrNullExt<T> on List<T> {
181 /// The first element satisfying [test], or `null` if there are none. 233 /// The first element satisfying [test], or `null` if there are none.
182 T? firstWhereOrNull(bool Function(T element) test) { 234 T? firstWhereOrNull(bool Function(T element) test) {
183 for (var element in this) { 235 for (var element in this) {
@@ -20,21 +20,6 @@ abstract class _RouteMiddleware { @@ -20,21 +20,6 @@ abstract class _RouteMiddleware {
20 /// {@end-tool} 20 /// {@end-tool}
21 int? priority; 21 int? priority;
22 22
23 - /// This function will be called when the page of  
24 - /// the called route is being searched for.  
25 - /// It take RouteSettings as a result an redirect to the new settings or  
26 - /// give it null and there will be no redirecting.  
27 - /// {@tool snippet}  
28 - /// ```dart  
29 - /// GetPage redirect(String route) {  
30 - /// final authService = Get.find<AuthService>();  
31 - /// return authService.authed.value ? null : RouteSettings(name: '/login');  
32 - /// }  
33 - /// ```  
34 - /// {@end-tool}  
35 - RouteSettings? redirect(String route);  
36 -  
37 - /// Similar to [redirect],  
38 /// This function will be called when the router delegate changes the 23 /// This function will be called when the router delegate changes the
39 /// current route. 24 /// current route.
40 /// 25 ///
@@ -45,13 +30,13 @@ abstract class _RouteMiddleware { @@ -45,13 +30,13 @@ abstract class _RouteMiddleware {
45 /// and no new routes are pushed. 30 /// and no new routes are pushed.
46 /// {@tool snippet} 31 /// {@tool snippet}
47 /// ```dart 32 /// ```dart
48 - /// GetNavConfig? redirect(GetNavConfig route) { 33 + /// RouteDecoder? redirect(RouteDecoder route) {
49 /// final authService = Get.find<AuthService>(); 34 /// final authService = Get.find<AuthService>();
50 - /// return authService.authed.value ? null : RouteSettings(name: '/login'); 35 + /// return authService.authed.value ? null : RouteDecoder.fromRoute('/login');
51 /// } 36 /// }
52 /// ``` 37 /// ```
53 /// {@end-tool} 38 /// {@end-tool}
54 - Future<GetNavConfig?> redirectDelegate(GetNavConfig route); 39 + Future<RouteDecoder?> redirect(RouteDecoder route);
55 40
56 /// This function will be called when this Page is called 41 /// This function will be called when this Page is called
57 /// you can use it to change something about the page or give it new page 42 /// you can use it to change something about the page or give it new page
@@ -101,8 +86,8 @@ class GetMiddleware implements _RouteMiddleware { @@ -101,8 +86,8 @@ class GetMiddleware implements _RouteMiddleware {
101 86
102 GetMiddleware({this.priority}); 87 GetMiddleware({this.priority});
103 88
104 - @override  
105 - RouteSettings? redirect(String? route) => null; 89 + // @override
  90 + // RouteSettings? redirect(String? route) => null;
106 91
107 @override 92 @override
108 GetPage? onPageCalled(GetPage? page) => page; 93 GetPage? onPageCalled(GetPage? page) => page;
@@ -120,7 +105,7 @@ class GetMiddleware implements _RouteMiddleware { @@ -120,7 +105,7 @@ class GetMiddleware implements _RouteMiddleware {
120 void onPageDispose() {} 105 void onPageDispose() {}
121 106
122 @override 107 @override
123 - Future<GetNavConfig?> redirectDelegate(GetNavConfig route) => 108 + Future<RouteDecoder?> redirect(RouteDecoder route) =>
124 SynchronousFuture(route); 109 SynchronousFuture(route);
125 } 110 }
126 111
@@ -144,17 +129,17 @@ class MiddlewareRunner { @@ -144,17 +129,17 @@ class MiddlewareRunner {
144 return page; 129 return page;
145 } 130 }
146 131
147 - RouteSettings? runRedirect(String? route) {  
148 - RouteSettings? to;  
149 - for (final element in _getMiddlewares()) {  
150 - to = element.redirect(route);  
151 - if (to != null) {  
152 - break;  
153 - }  
154 - }  
155 - Get.log('Redirect to $to');  
156 - return to;  
157 - } 132 + // RouteSettings? runRedirect(String? route) {
  133 + // RouteSettings? to;
  134 + // for (final element in _getMiddlewares()) {
  135 + // to = element.redirect(route);
  136 + // if (to != null) {
  137 + // break;
  138 + // }
  139 + // }
  140 + // Get.log('Redirect to $to');
  141 + // return to;
  142 + // }
158 143
159 List<R>? runOnBindingsStart<R>(List<R>? bindings) { 144 List<R>? runOnBindingsStart<R>(List<R>? bindings) {
160 _getMiddlewares().forEach((element) { 145 _getMiddlewares().forEach((element) {
@@ -212,7 +197,7 @@ class PageRedirect { @@ -212,7 +197,7 @@ class PageRedirect {
212 showCupertinoParallax: _r.showCupertinoParallax, 197 showCupertinoParallax: _r.showCupertinoParallax,
213 gestureWidth: _r.gestureWidth, 198 gestureWidth: _r.gestureWidth,
214 customTransition: _r.customTransition, 199 customTransition: _r.customTransition,
215 - binding: _r.binding, 200 + bindings: _r.bindings,
216 binds: _r.binds, 201 binds: _r.binds,
217 transitionDuration: 202 transitionDuration:
218 _r.transitionDuration ?? Get.defaultTransitionDuration, 203 _r.transitionDuration ?? Get.defaultTransitionDuration,
@@ -235,13 +220,13 @@ class PageRedirect { @@ -235,13 +220,13 @@ class PageRedirect {
235 title: _r.title, 220 title: _r.title,
236 maintainState: _r.maintainState, 221 maintainState: _r.maintainState,
237 routeName: _r.name, 222 routeName: _r.name,
238 - settings: _r, 223 + settings: settings,
239 curve: _r.curve, 224 curve: _r.curve,
240 showCupertinoParallax: _r.showCupertinoParallax, 225 showCupertinoParallax: _r.showCupertinoParallax,
241 gestureWidth: _r.gestureWidth, 226 gestureWidth: _r.gestureWidth,
242 opaque: _r.opaque, 227 opaque: _r.opaque,
243 customTransition: _r.customTransition, 228 customTransition: _r.customTransition,
244 - binding: _r.binding, 229 + bindings: _r.bindings,
245 binds: _r.binds, 230 binds: _r.binds,
246 transitionDuration: 231 transitionDuration:
247 _r.transitionDuration ?? Get.defaultTransitionDuration, 232 _r.transitionDuration ?? Get.defaultTransitionDuration,
@@ -274,19 +259,19 @@ class PageRedirect { @@ -274,19 +259,19 @@ class PageRedirect {
274 if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) { 259 if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) {
275 return false; 260 return false;
276 } 261 }
277 - final newSettings = runner.runRedirect(settings!.name);  
278 - if (newSettings == null) {  
279 - return false;  
280 - }  
281 - settings = newSettings; 262 + // final newSettings = runner.runRedirect(settings!.name);
  263 + // if (newSettings == null) {
  264 + // return false;
  265 + // }
  266 + // settings = newSettings;
282 return true; 267 return true;
283 } 268 }
284 269
285 void addPageParameter(GetPage route) { 270 void addPageParameter(GetPage route) {
286 if (route.parameters == null) return; 271 if (route.parameters == null) return;
287 272
288 - final parameters = Get.parameters; 273 + final parameters = Map<String, String?>.from(Get.parameters);
289 parameters.addEntries(route.parameters!.entries); 274 parameters.addEntries(route.parameters!.entries);
290 - Get.parameters = parameters; 275 + // Get.parameters = parameters;
291 } 276 }
292 } 277 }
@@ -74,12 +74,12 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> @@ -74,12 +74,12 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
74 } 74 }
75 } 75 }
76 76
77 -class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { 77 +class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
78 GetRouterOutlet({ 78 GetRouterOutlet({
79 String? anchorRoute, 79 String? anchorRoute,
80 required String initialRoute, 80 required String initialRoute,
81 Iterable<GetPage> Function(Iterable<GetPage> afterAnchor)? filterPages, 81 Iterable<GetPage> Function(Iterable<GetPage> afterAnchor)? filterPages,
82 - GlobalKey<NavigatorState>? key, 82 + // GlobalKey<NavigatorState>? key,
83 GetDelegate? delegate, 83 GetDelegate? delegate,
84 }) : this.pickPages( 84 }) : this.pickPages(
85 pickPages: (config) { 85 pickPages: (config) {
@@ -102,13 +102,13 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { @@ -102,13 +102,13 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
102 emptyPage: (delegate) => 102 emptyPage: (delegate) =>
103 Get.routeTree.matchRoute(initialRoute).route ?? 103 Get.routeTree.matchRoute(initialRoute).route ??
104 delegate.notFoundRoute, 104 delegate.notFoundRoute,
105 - key: key, 105 + key: Get.nestedKey(anchorRoute)?.navigatorKey,
106 delegate: delegate, 106 delegate: delegate,
107 ); 107 );
108 GetRouterOutlet.pickPages({ 108 GetRouterOutlet.pickPages({
109 Widget Function(GetDelegate delegate)? emptyWidget, 109 Widget Function(GetDelegate delegate)? emptyWidget,
110 GetPage Function(GetDelegate delegate)? emptyPage, 110 GetPage Function(GetDelegate delegate)? emptyPage,
111 - required Iterable<GetPage> Function(GetNavConfig currentNavStack) pickPages, 111 + required Iterable<GetPage> Function(RouteDecoder currentNavStack) pickPages,
112 bool Function(Route<dynamic>, dynamic)? onPopPage, 112 bool Function(Route<dynamic>, dynamic)? onPopPage,
113 GlobalKey<NavigatorState>? key, 113 GlobalKey<NavigatorState>? key,
114 GetDelegate? delegate, 114 GetDelegate? delegate,
@@ -137,14 +137,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { @@ -137,14 +137,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
137 return (emptyWidget?.call(rDelegate) ?? SizedBox.shrink()); 137 return (emptyWidget?.call(rDelegate) ?? SizedBox.shrink());
138 }, 138 },
139 pickPages: pickPages, 139 pickPages: pickPages,
140 - delegate: delegate ?? Get.rootDelegate, 140 + delegate: delegate ?? GetMaterialController.to.rootDelegate,
141 ); 141 );
142 142
143 GetRouterOutlet.builder({ 143 GetRouterOutlet.builder({
144 required Widget Function( 144 required Widget Function(
145 BuildContext context, 145 BuildContext context,
146 GetDelegate delegate, 146 GetDelegate delegate,
147 - GetNavConfig? currentRoute, 147 + RouteDecoder? currentRoute,
148 ) 148 )
149 builder, 149 builder,
150 GetDelegate? routerDelegate, 150 GetDelegate? routerDelegate,
  1 +void removeHash() {}
  2 +
  3 +void removeLastHistory(String? url) {}
  1 +import 'web/web_url.dart' if (dart.library.io) 'io/io_url.dart';
  2 +
  3 +void setUrlStrategy() {
  4 + removeHash();
  5 +}
  6 +
  7 +void removeLastHistory(String? url) {
  8 + removeLastHistory(url);
  9 +}
  1 +import 'dart:html';
  2 +
  3 +import 'package:flutter_web_plugins/flutter_web_plugins.dart';
  4 +
  5 +void removeHash() {
  6 + setUrlStrategy(PathUrlStrategy());
  7 +}
  8 +
  9 +void removeLastHistory(String? url) {
  10 + window.location.replace(null);
  11 +}
@@ -154,16 +154,18 @@ extension ListExtension<E> on List<E> { @@ -154,16 +154,18 @@ extension ListExtension<E> on List<E> {
154 // (this as RxList)._value; 154 // (this as RxList)._value;
155 // } 155 // }
156 156
157 - clear(); 157 + if (this is RxList) {
  158 + (this as RxList).value.clear();
  159 + }
158 add(item); 160 add(item);
159 } 161 }
160 162
161 /// Replaces all existing items of this list with [items] 163 /// Replaces all existing items of this list with [items]
162 void assignAll(Iterable<E> items) { 164 void assignAll(Iterable<E> items) {
163 - // if (this is RxList) {  
164 - // (this as RxList)._value;  
165 - // }  
166 - clear(); 165 + if (this is RxList) {
  166 + (this as RxList).value.clear();
  167 + }
  168 + //clear();
167 addAll(items); 169 addAll(items);
168 } 170 }
169 } 171 }
@@ -26,25 +26,25 @@ extension _Empty on Object { @@ -26,25 +26,25 @@ extension _Empty on Object {
26 26
27 mixin StateMixin<T> on ListNotifier { 27 mixin StateMixin<T> on ListNotifier {
28 late T _value; 28 late T _value;
29 - GetState<T>? _status; 29 + GetStatus<T>? _status;
30 30
31 void _fillInitialStatus() { 31 void _fillInitialStatus() {
32 _status = (value == null || value!._isEmpty()) 32 _status = (value == null || value!._isEmpty())
33 - ? GetState<T>.loading()  
34 - : GetState<T>.success(_value); 33 + ? GetStatus<T>.loading()
  34 + : GetStatus<T>.success(_value);
35 } 35 }
36 36
37 - GetState<T> get status { 37 + GetStatus<T> get status {
38 reportRead(); 38 reportRead();
39 - return _status ??= _status = GetState.loading(); 39 + return _status ??= _status = GetStatus.loading();
40 } 40 }
41 41
42 T get state => value; 42 T get state => value;
43 43
44 - set status(GetState<T> newStatus) { 44 + set status(GetStatus<T> newStatus) {
45 if (newStatus == status) return; 45 if (newStatus == status) return;
46 _status = newStatus; 46 _status = newStatus;
47 - if (newStatus is SuccessState<T>) { 47 + if (newStatus is SuccessStatus<T>) {
48 _value = newStatus.data!; 48 _value = newStatus.data!;
49 return; 49 return;
50 } 50 }
@@ -69,12 +69,15 @@ mixin StateMixin<T> on ListNotifier { @@ -69,12 +69,15 @@ mixin StateMixin<T> on ListNotifier {
69 final compute = body(); 69 final compute = body();
70 compute().then((newValue) { 70 compute().then((newValue) {
71 if ((newValue == null || newValue._isEmpty()) && useEmpty) { 71 if ((newValue == null || newValue._isEmpty()) && useEmpty) {
72 - status = GetState<T>.loading(); 72 + status = GetStatus<T>.loading();
73 } else { 73 } else {
74 - status = GetState<T>.success(newValue); 74 + status = GetStatus<T>.success(newValue);
75 } 75 }
  76 +
  77 + refresh();
76 }, onError: (err) { 78 }, onError: (err) {
77 - status = GetState.error(errorMessage ?? err.toString()); 79 + status = GetStatus.error(errorMessage ?? err.toString());
  80 + refresh();
78 }); 81 });
79 } 82 }
80 } 83 }
@@ -88,6 +91,8 @@ class GetListenable<T> extends ListNotifierSingle implements RxInterface<T> { @@ -88,6 +91,8 @@ class GetListenable<T> extends ListNotifierSingle implements RxInterface<T> {
88 if (_controller == null) { 91 if (_controller == null) {
89 _controller = StreamController<T>.broadcast(); 92 _controller = StreamController<T>.broadcast();
90 addListener(_streamListener); 93 addListener(_streamListener);
  94 +
  95 + ///TODO: report to controller dispose
91 } 96 }
92 return _controller!; 97 return _controller!;
93 } 98 }
@@ -228,39 +233,39 @@ extension StateExt<T> on StateMixin<T> { @@ -228,39 +233,39 @@ extension StateExt<T> on StateMixin<T> {
228 233
229 typedef NotifierBuilder<T> = Widget Function(T state); 234 typedef NotifierBuilder<T> = Widget Function(T state);
230 235
231 -abstract class GetState<T> {  
232 - const GetState();  
233 - factory GetState.loading() => LoadingState();  
234 - factory GetState.error(String message) => ErrorState(message);  
235 - factory GetState.empty() => EmptyState();  
236 - factory GetState.success(T data) => SuccessState(data); 236 +abstract class GetStatus<T> {
  237 + const GetStatus();
  238 + factory GetStatus.loading() => LoadingStatus();
  239 + factory GetStatus.error(String message) => ErrorStatus(message);
  240 + factory GetStatus.empty() => EmptyStatus();
  241 + factory GetStatus.success(T data) => SuccessStatus(data);
237 } 242 }
238 243
239 -class LoadingState<T> extends GetState<T> {} 244 +class LoadingStatus<T> extends GetStatus<T> {}
240 245
241 -class SuccessState<T> extends GetState<T> { 246 +class SuccessStatus<T> extends GetStatus<T> {
242 final T data; 247 final T data;
243 248
244 - SuccessState(this.data); 249 + SuccessStatus(this.data);
245 } 250 }
246 251
247 -class ErrorState<T, S> extends GetState<T> { 252 +class ErrorStatus<T, S> extends GetStatus<T> {
248 final S? error; 253 final S? error;
249 - ErrorState([this.error]); 254 + ErrorStatus([this.error]);
250 } 255 }
251 256
252 -class EmptyState<T> extends GetState<T> {} 257 +class EmptyStatus<T> extends GetStatus<T> {}
253 258
254 -extension StatusDataExt<T> on GetState<T> {  
255 - bool get isLoading => this is LoadingState;  
256 - bool get isSuccess => this is SuccessState;  
257 - bool get isError => this is ErrorState;  
258 - bool get isEmpty => this is EmptyState; 259 +extension StatusDataExt<T> on GetStatus<T> {
  260 + bool get isLoading => this is LoadingStatus;
  261 + bool get isSuccess => this is SuccessStatus;
  262 + bool get isError => this is ErrorStatus;
  263 + bool get isEmpty => this is EmptyStatus;
259 bool get isCustom => !isLoading && !isSuccess && !isError && !isEmpty; 264 bool get isCustom => !isLoading && !isSuccess && !isError && !isEmpty;
260 String get errorMessage { 265 String get errorMessage {
261 - final isError = this is ErrorState; 266 + final isError = this is ErrorStatus;
262 if (isError) { 267 if (isError) {
263 - final err = this as ErrorState; 268 + final err = this as ErrorStatus;
264 if (err.error != null && err.error is String) { 269 if (err.error != null && err.error is String) {
265 return err.error as String; 270 return err.error as String;
266 } 271 }
@@ -270,8 +275,8 @@ extension StatusDataExt<T> on GetState<T> { @@ -270,8 +275,8 @@ extension StatusDataExt<T> on GetState<T> {
270 } 275 }
271 276
272 T? get data { 277 T? get data {
273 - if (this is SuccessState<T>) {  
274 - final success = this as SuccessState<T>; 278 + if (this is SuccessStatus<T>) {
  279 + final success = this as SuccessStatus<T>;
275 return success.data; 280 return success.data;
276 } 281 }
277 return null; 282 return null;
@@ -10,13 +10,13 @@ typedef GetControllerBuilder<T extends GetLifeCycleMixin> = Widget Function( @@ -10,13 +10,13 @@ typedef GetControllerBuilder<T extends GetLifeCycleMixin> = Widget Function(
10 T controller); 10 T controller);
11 11
12 extension WatchExt on BuildContext { 12 extension WatchExt on BuildContext {
13 - T listen<T extends GetxController>() { 13 + T listen<T>() {
14 return Bind.of(this, rebuild: true); 14 return Bind.of(this, rebuild: true);
15 } 15 }
16 } 16 }
17 17
18 extension ReadExt on BuildContext { 18 extension ReadExt on BuildContext {
19 - T get<T extends GetxController>() { 19 + T get<T>() {
20 return Bind.of(this); 20 return Bind.of(this);
21 } 21 }
22 } 22 }
@@ -212,7 +212,7 @@ abstract class Bind<T> extends StatelessWidget { @@ -212,7 +212,7 @@ abstract class Bind<T> extends StatelessWidget {
212 child: child, 212 child: child,
213 ); 213 );
214 214
215 - static T of<T extends GetxController>( 215 + static T of<T>(
216 BuildContext context, { 216 BuildContext context, {
217 bool rebuild = false, 217 bool rebuild = false,
218 // Object Function(T value)? filter, 218 // Object Function(T value)? filter,
@@ -21,7 +21,7 @@ class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin; @@ -21,7 +21,7 @@ class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin;
21 /// This mixin add to Listenable the addListener, removerListener and 21 /// This mixin add to Listenable the addListener, removerListener and
22 /// containsListener implementation 22 /// containsListener implementation
23 mixin ListNotifierSingleMixin on Listenable { 23 mixin ListNotifierSingleMixin on Listenable {
24 - List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[]; 24 + List<GetStateUpdate>? _updaters = <GetStateUpdate>[];
25 25
26 @override 26 @override
27 Disposer addListener(GetStateUpdate listener) { 27 Disposer addListener(GetStateUpdate listener) {
@@ -57,8 +57,9 @@ mixin ListNotifierSingleMixin on Listenable { @@ -57,8 +57,9 @@ mixin ListNotifierSingleMixin on Listenable {
57 } 57 }
58 58
59 void _notifyUpdate() { 59 void _notifyUpdate() {
60 - for (var element in _updaters!) {  
61 - element!(); 60 + final list = _updaters?.toList() ?? [];
  61 + for (var element in list) {
  62 + element();
62 } 63 }
63 } 64 }
64 65
1 import 'dart:async'; 1 import 'dart:async';
2 2
  3 +import 'package:flutter/scheduler.dart';
3 import 'package:flutter/widgets.dart'; 4 import 'package:flutter/widgets.dart';
4 5
5 import 'list_notifier.dart'; 6 import 'list_notifier.dart';
@@ -95,8 +96,26 @@ mixin ObserverComponent on ComponentElement { @@ -95,8 +96,26 @@ mixin ObserverComponent on ComponentElement {
95 96
96 void getUpdate() { 97 void getUpdate() {
97 if (disposers != null) { 98 if (disposers != null) {
  99 + _safeRebuild();
  100 + }
  101 + }
  102 +
  103 + Future<bool> _safeRebuild() async {
  104 + if (dirty) return false;
  105 + if (SchedulerBinding.instance == null) {
  106 + markNeedsBuild();
  107 + } else {
  108 + // refresh was called during the building
  109 + if (SchedulerBinding.instance!.schedulerPhase != SchedulerPhase.idle) {
  110 + // Await for the end of build
  111 + await SchedulerBinding.instance!.endOfFrame;
  112 + if (dirty) return false;
  113 + }
  114 +
98 markNeedsBuild(); 115 markNeedsBuild();
99 } 116 }
  117 +
  118 + return true;
100 } 119 }
101 120
102 @override 121 @override
1 -import 'package:collection/collection.dart';  
2 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
3 2
4 extension ContextExt on BuildContext { 3 extension ContextExt on BuildContext {
@@ -170,3 +169,12 @@ extension ContextExt on BuildContext { @@ -170,3 +169,12 @@ extension ContextExt on BuildContext {
170 return strictValues.firstOrNull ?? looseValues.first; 169 return strictValues.firstOrNull ?? looseValues.first;
171 } 170 }
172 } 171 }
  172 +
  173 +extension IterableExt<T> on Iterable<T> {
  174 + /// The first element, or `null` if the iterable is empty.
  175 + T? get firstOrNull {
  176 + var iterator = this.iterator;
  177 + if (iterator.moveNext()) return iterator.current;
  178 + return null;
  179 + }
  180 +}
1 name: get 1 name: get
2 description: Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX. 2 description: Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX.
3 -version: 4.6.1 3 +version: 5.0.0-beta.14
4 homepage: https://github.com/jonataslaw/getx 4 homepage: https://github.com/jonataslaw/getx
5 5
6 environment: 6 environment:
7 - sdk: '>=2.12.0 <3.0.0' 7 + sdk: '>=2.13.0 <3.0.0'
8 8
9 dependencies: 9 dependencies:
10 flutter: 10 flutter:
11 sdk: flutter 11 sdk: flutter
  12 + flutter_web_plugins:
  13 + sdk: flutter
12 14
13 dev_dependencies: 15 dev_dependencies:
14 flutter_test: 16 flutter_test:
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:flutter_test/flutter_test.dart'; 2 import 'package:flutter_test/flutter_test.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
  4 +
4 import 'utils/wrapper.dart'; 5 import 'utils/wrapper.dart';
5 6
6 void main() { 7 void main() {
@@ -9,6 +10,8 @@ void main() { @@ -9,6 +10,8 @@ void main() {
9 Wrapper(child: Container()), 10 Wrapper(child: Container()),
10 ); 11 );
11 12
  13 + await tester.pump();
  14 +
12 Get.bottomSheet(Container( 15 Get.bottomSheet(Container(
13 child: Wrap( 16 child: Wrap(
14 children: <Widget>[ 17 children: <Widget>[
@@ -31,6 +34,8 @@ void main() { @@ -31,6 +34,8 @@ void main() {
31 Wrapper(child: Container()), 34 Wrapper(child: Container()),
32 ); 35 );
33 36
  37 + await tester.pump();
  38 +
34 Get.bottomSheet(Container( 39 Get.bottomSheet(Container(
35 child: Wrap( 40 child: Wrap(
36 children: <Widget>[ 41 children: <Widget>[
@@ -43,9 +48,13 @@ void main() { @@ -43,9 +48,13 @@ void main() {
43 ), 48 ),
44 )); 49 ));
45 50
  51 + await tester.pumpAndSettle();
  52 +
46 expect(Get.isBottomSheetOpen, true); 53 expect(Get.isBottomSheetOpen, true);
47 54
48 Get.back(); 55 Get.back();
  56 + await tester.pumpAndSettle();
  57 +
49 expect(Get.isBottomSheetOpen, false); 58 expect(Get.isBottomSheetOpen, false);
50 59
51 // expect(() => Get.bottomSheet(Container(), isScrollControlled: null), 60 // expect(() => Get.bottomSheet(Container(), isScrollControlled: null),
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:flutter_test/flutter_test.dart'; 2 import 'package:flutter_test/flutter_test.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
  4 +
4 import 'utils/wrapper.dart'; 5 import 'utils/wrapper.dart';
5 6
6 void main() { 7 void main() {
@@ -9,6 +10,8 @@ void main() { @@ -9,6 +10,8 @@ void main() {
9 Wrapper(child: Container()), 10 Wrapper(child: Container()),
10 ); 11 );
11 12
  13 + await tester.pump();
  14 +
12 Get.defaultDialog( 15 Get.defaultDialog(
13 onConfirm: () => print("Ok"), 16 onConfirm: () => print("Ok"),
14 middleText: "Dialog made in 3 lines of code"); 17 middleText: "Dialog made in 3 lines of code");
@@ -23,6 +26,8 @@ void main() { @@ -23,6 +26,8 @@ void main() {
23 Wrapper(child: Container()), 26 Wrapper(child: Container()),
24 ); 27 );
25 28
  29 + await tester.pump();
  30 +
26 Get.dialog(YourDialogWidget()); 31 Get.dialog(YourDialogWidget());
27 32
28 await tester.pumpAndSettle(); 33 await tester.pumpAndSettle();
@@ -35,11 +40,20 @@ void main() { @@ -35,11 +40,20 @@ void main() {
35 Wrapper(child: Container()), 40 Wrapper(child: Container()),
36 ); 41 );
37 42
  43 + await tester.pump();
  44 +
38 Get.dialog(YourDialogWidget()); 45 Get.dialog(YourDialogWidget());
39 - expect(Get.isDialogOpen, true); 46 + await tester.pumpAndSettle();
  47 +
  48 + expect(find.byType(YourDialogWidget), findsOneWidget);
  49 + // expect(Get.isDialogOpen, true);
  50 +
40 Get.back(); 51 Get.back();
41 - expect(Get.isDialogOpen, false);  
42 await tester.pumpAndSettle(); 52 await tester.pumpAndSettle();
  53 +
  54 + expect(find.byType(YourDialogWidget), findsNothing);
  55 + // expect(Get.isDialogOpen, false);
  56 + // await tester.pumpAndSettle();
43 }); 57 });
44 } 58 }
45 59
@@ -13,7 +13,7 @@ void main() { @@ -13,7 +13,7 @@ void main() {
13 expect(Get.isRegistered<Controller2>(), false); 13 expect(Get.isRegistered<Controller2>(), false);
14 expect(Get.isRegistered<Controller>(), false); 14 expect(Get.isRegistered<Controller>(), false);
15 15
16 - Get.to(First()); 16 + Get.to(() => First());
17 17
18 await tester.pumpAndSettle(); 18 await tester.pumpAndSettle();
19 19
@@ -21,7 +21,7 @@ void main() { @@ -21,7 +21,7 @@ void main() {
21 21
22 expect(Get.isRegistered<Controller>(), true); 22 expect(Get.isRegistered<Controller>(), true);
23 23
24 - Get.to(Second()); 24 + Get.to(() => Second());
25 25
26 await tester.pumpAndSettle(); 26 await tester.pumpAndSettle();
27 27
@@ -8,7 +8,7 @@ void main() { @@ -8,7 +8,7 @@ void main() {
8 testWidgets("Get.to navigates to provided route", (tester) async { 8 testWidgets("Get.to navigates to provided route", (tester) async {
9 await tester.pumpWidget(Wrapper(child: Container())); 9 await tester.pumpWidget(Wrapper(child: Container()));
10 10
11 - Get.to(FirstScreen()); 11 + Get.to(() => FirstScreen());
12 12
13 await tester.pumpAndSettle(); 13 await tester.pumpAndSettle();
14 14
@@ -47,13 +47,16 @@ void main() { @@ -47,13 +47,16 @@ void main() {
47 47
48 await tester.pumpAndSettle(); 48 await tester.pumpAndSettle();
49 49
50 - expect(Get.currentRoute, '/404'); 50 + expect(
  51 + GetMaterialController.to.rootDelegate.currentConfiguration?.route?.name,
  52 + '/404');
51 }); 53 });
52 54
53 testWidgets("Get.off navigates to provided route", (tester) async { 55 testWidgets("Get.off navigates to provided route", (tester) async {
54 await tester.pumpWidget(Wrapper(child: FirstScreen())); 56 await tester.pumpWidget(Wrapper(child: FirstScreen()));
  57 + // await tester.pump();
55 58
56 - Get.off(SecondScreen()); 59 + Get.off(() => SecondScreen());
57 60
58 await tester.pumpAndSettle(); 61 await tester.pumpAndSettle();
59 62
@@ -62,8 +65,9 @@ void main() { @@ -62,8 +65,9 @@ void main() {
62 65
63 testWidgets("Get.off removes current route", (tester) async { 66 testWidgets("Get.off removes current route", (tester) async {
64 await tester.pumpWidget(Wrapper(child: FirstScreen())); 67 await tester.pumpWidget(Wrapper(child: FirstScreen()));
  68 + await tester.pump();
65 69
66 - Get.off(SecondScreen()); 70 + Get.off(() => SecondScreen());
67 Get.back(); 71 Get.back();
68 72
69 await tester.pumpAndSettle(); 73 await tester.pumpAndSettle();
@@ -81,6 +85,8 @@ void main() { @@ -81,6 +85,8 @@ void main() {
81 ], 85 ],
82 )); 86 ));
83 87
  88 + await tester.pump();
  89 +
84 Get.offNamed('/second'); 90 Get.offNamed('/second');
85 91
86 await tester.pumpAndSettle(); 92 await tester.pumpAndSettle();
@@ -98,7 +104,10 @@ void main() { @@ -98,7 +104,10 @@ void main() {
98 ], 104 ],
99 )); 105 ));
100 106
  107 + await tester.pump();
  108 +
101 Get.offNamed('/second'); 109 Get.offNamed('/second');
  110 + await tester.pumpAndSettle();
102 Get.back(); 111 Get.back();
103 112
104 await tester.pumpAndSettle(); 113 await tester.pumpAndSettle();
@@ -116,19 +125,24 @@ void main() { @@ -116,19 +125,24 @@ void main() {
116 ], 125 ],
117 )); 126 ));
118 127
  128 + // await tester.pump();
  129 +
119 Get.toNamed('/second'); 130 Get.toNamed('/second');
  131 + await tester.pumpAndSettle();
120 Get.offNamed('/third'); 132 Get.offNamed('/third');
  133 + await tester.pumpAndSettle();
121 Get.back(); 134 Get.back();
122 -  
123 await tester.pumpAndSettle(); 135 await tester.pumpAndSettle();
124 136
125 expect(find.byType(FirstScreen), findsOneWidget); 137 expect(find.byType(FirstScreen), findsOneWidget);
  138 + await tester.pumpAndSettle();
126 }); 139 });
127 140
128 testWidgets("Get.offAll navigates to provided route", (tester) async { 141 testWidgets("Get.offAll navigates to provided route", (tester) async {
129 await tester.pumpWidget(Wrapper(child: FirstScreen())); 142 await tester.pumpWidget(Wrapper(child: FirstScreen()));
  143 + await tester.pump();
130 144
131 - Get.offAll(SecondScreen()); 145 + Get.offAll(() => SecondScreen());
132 146
133 await tester.pumpAndSettle(); 147 await tester.pumpAndSettle();
134 148
@@ -137,11 +151,13 @@ void main() { @@ -137,11 +151,13 @@ void main() {
137 151
138 testWidgets("Get.offAll removes all previous routes", (tester) async { 152 testWidgets("Get.offAll removes all previous routes", (tester) async {
139 await tester.pumpWidget(Wrapper(child: FirstScreen())); 153 await tester.pumpWidget(Wrapper(child: FirstScreen()));
  154 + await tester.pump();
140 155
141 - Get.to(SecondScreen());  
142 - Get.offAll(ThirdScreen()); 156 + Get.to(() => SecondScreen());
  157 + await tester.pumpAndSettle();
  158 + Get.offAll(() => ThirdScreen());
  159 + await tester.pumpAndSettle();
143 Get.back(); 160 Get.back();
144 -  
145 await tester.pumpAndSettle(); 161 await tester.pumpAndSettle();
146 162
147 expect(find.byType(SecondScreen), findsNothing); 163 expect(find.byType(SecondScreen), findsNothing);
@@ -164,6 +180,8 @@ void main() { @@ -164,6 +180,8 @@ void main() {
164 ], 180 ],
165 )); 181 ));
166 182
  183 + await tester.pump();
  184 +
167 Get.toNamed('/second'); 185 Get.toNamed('/second');
168 186
169 await tester.pumpAndSettle(); 187 await tester.pumpAndSettle();
@@ -181,10 +199,13 @@ void main() { @@ -181,10 +199,13 @@ void main() {
181 ], 199 ],
182 )); 200 ));
183 201
  202 + await tester.pump();
  203 +
184 Get.toNamed('/second'); 204 Get.toNamed('/second');
  205 + await tester.pumpAndSettle();
185 Get.offAllNamed('/third'); 206 Get.offAllNamed('/third');
  207 + await tester.pumpAndSettle();
186 Get.back(); 208 Get.back();
187 -  
188 await tester.pumpAndSettle(); 209 await tester.pumpAndSettle();
189 210
190 expect(find.byType(SecondScreen), findsNothing); 211 expect(find.byType(SecondScreen), findsNothing);
@@ -224,6 +245,8 @@ void main() { @@ -224,6 +245,8 @@ void main() {
224 )); 245 ));
225 246
226 Get.offAndToNamed('/second'); 247 Get.offAndToNamed('/second');
  248 +
  249 + await tester.pumpAndSettle();
227 Get.back(); 250 Get.back();
228 251
229 await tester.pumpAndSettle(); 252 await tester.pumpAndSettle();
@@ -234,10 +257,11 @@ void main() { @@ -234,10 +257,11 @@ void main() {
234 testWidgets("Get.offUntil navigates to provided route", (tester) async { 257 testWidgets("Get.offUntil navigates to provided route", (tester) async {
235 await tester.pumpWidget(Wrapper(child: Container())); 258 await tester.pumpWidget(Wrapper(child: Container()));
236 259
237 - Get.to(FirstScreen()); 260 + Get.to(() => FirstScreen());
  261 +
  262 + await tester.pumpAndSettle();
238 263
239 - Get.offUntil(GetPageRoute(page: () => ThirdScreen()),  
240 - (route) => (route as GetPageRoute).routeName == '/FirstScreen'); 264 + Get.offUntil(() => ThirdScreen(), (route) => route.name == '/FirstScreen');
241 265
242 await tester.pumpAndSettle(); 266 await tester.pumpAndSettle();
243 267
@@ -249,10 +273,12 @@ void main() { @@ -249,10 +273,12 @@ void main() {
249 (tester) async { 273 (tester) async {
250 await tester.pumpWidget(Wrapper(child: Container())); 274 await tester.pumpWidget(Wrapper(child: Container()));
251 275
252 - Get.to(FirstScreen());  
253 - Get.to(SecondScreen());  
254 - Get.offUntil(GetPageRoute(page: () => ThirdScreen()),  
255 - (route) => (route as GetPageRoute).routeName == '/FirstScreen'); 276 + Get.to(() => FirstScreen());
  277 + await tester.pumpAndSettle();
  278 + Get.to(() => SecondScreen());
  279 + await tester.pumpAndSettle();
  280 + Get.offUntil(() => ThirdScreen(), (route) => route.name == '/FirstScreen');
  281 + await tester.pumpAndSettle();
256 Get.back(); 282 Get.back();
257 283
258 await tester.pumpAndSettle(); 284 await tester.pumpAndSettle();
@@ -265,10 +291,12 @@ void main() { @@ -265,10 +291,12 @@ void main() {
265 (tester) async { 291 (tester) async {
266 await tester.pumpWidget(Wrapper(child: Container())); 292 await tester.pumpWidget(Wrapper(child: Container()));
267 293
268 - Get.to(FirstScreen());  
269 - Get.to(SecondScreen());  
270 - Get.offUntil(GetPageRoute(page: () => ThirdScreen()),  
271 - (route) => (route as GetPageRoute).routeName == '/FirstScreen'); 294 + Get.to(() => FirstScreen());
  295 + await tester.pumpAndSettle();
  296 + Get.to(() => SecondScreen());
  297 + await tester.pumpAndSettle();
  298 + Get.offUntil(() => ThirdScreen(), (route) => route.name == '/FirstScreen');
  299 + await tester.pumpAndSettle();
272 Get.back(); 300 Get.back();
273 301
274 await tester.pumpAndSettle(); 302 await tester.pumpAndSettle();
@@ -286,7 +314,7 @@ void main() { @@ -286,7 +314,7 @@ void main() {
286 ], 314 ],
287 )); 315 ));
288 316
289 - Get.offNamedUntil('/second', ModalRoute.withName('/first')); 317 + Get.offNamedUntil('/second', (route) => route.name == '/first');
290 318
291 await tester.pumpAndSettle(); 319 await tester.pumpAndSettle();
292 320
@@ -306,43 +334,52 @@ void main() { @@ -306,43 +334,52 @@ void main() {
306 )); 334 ));
307 335
308 Get.toNamed('/second'); 336 Get.toNamed('/second');
309 - Get.offNamedUntil('/third', ModalRoute.withName('/first')); 337 + await tester.pumpAndSettle();
  338 + Get.offNamedUntil('/third', (route) => route.name == '/first');
310 339
311 await tester.pumpAndSettle(); 340 await tester.pumpAndSettle();
312 341
313 expect(find.byType(SecondScreen), findsNothing); 342 expect(find.byType(SecondScreen), findsNothing);
314 }); 343 });
315 344
316 - testWidgets(  
317 - "Get.offNamedUntil leaves previous routes that match provided predicate",  
318 - (tester) async {  
319 - await tester.pumpWidget(WrapperNamed(  
320 - initialRoute: '/first',  
321 - namedRoutes: [  
322 - GetPage(page: () => FirstScreen(), name: '/first'),  
323 - GetPage(page: () => SecondScreen(), name: '/second'),  
324 - GetPage(page: () => ThirdScreen(), name: '/third'),  
325 - ],  
326 - ));  
327 -  
328 - Get.toNamed('/second');  
329 - Get.offNamedUntil('/third', ModalRoute.withName('/first'));  
330 - Get.back();  
331 -  
332 - await tester.pumpAndSettle();  
333 -  
334 - expect(find.byType(FirstScreen), findsOneWidget);  
335 - }); 345 + // testWidgets(
  346 + // "Get.offNamedUntil leaves previous routes that match provided predicate",
  347 + // (tester) async {
  348 + // await tester.pumpWidget(WrapperNamed(
  349 + // initialRoute: '/first',
  350 + // namedRoutes: [
  351 + // GetPage(page: () => FirstScreen(), name: '/first'),
  352 + // GetPage(page: () => SecondScreen(), name: '/second'),
  353 + // GetPage(page: () => ThirdScreen(), name: '/third'),
  354 + // ],
  355 + // ));
  356 +
  357 + // Get.toNamed('/second');
  358 + // await tester.pumpAndSettle();
  359 + // Get.offNamedUntil('/third', (route) => route.name == '/first');
  360 + // await tester.pumpAndSettle();
  361 + // Get.back();
  362 +
  363 + // await tester.pumpAndSettle();
  364 +
  365 + // expect(find.byType(FirstScreen), findsOneWidget);
  366 + // });
336 367
337 testWidgets("Get.back navigates back", (tester) async { 368 testWidgets("Get.back navigates back", (tester) async {
338 await tester.pumpWidget( 369 await tester.pumpWidget(
339 Wrapper( 370 Wrapper(
340 - child: FirstScreen(), 371 + child: Container(),
341 defaultTransition: Transition.circularReveal, 372 defaultTransition: Transition.circularReveal,
342 ), 373 ),
343 ); 374 );
344 375
345 - Get.to(SecondScreen()); 376 + // await tester.pump();
  377 +
  378 + Get.to(() => FirstScreen());
  379 + await tester.pumpAndSettle();
  380 +
  381 + Get.to(() => SecondScreen());
  382 + await tester.pumpAndSettle();
346 Get.back(); 383 Get.back();
347 384
348 await tester.pumpAndSettle(); 385 await tester.pumpAndSettle();
@@ -353,135 +390,180 @@ void main() { @@ -353,135 +390,180 @@ void main() {
353 testWidgets( 390 testWidgets(
354 "Get.back with closeOverlays pops both snackbar and current route", 391 "Get.back with closeOverlays pops both snackbar and current route",
355 (tester) async { 392 (tester) async {
356 - await tester.pumpWidget(Wrapper(child: FirstScreen())); 393 + await tester.pumpWidget(
  394 + Wrapper(
  395 + child: Container(),
  396 + defaultTransition: Transition.circularReveal,
  397 + ),
  398 + );
357 399
358 - Get.to(SecondScreen()); 400 + // await tester.pump();
  401 +
  402 + Get.to(() => FirstScreen());
  403 + await tester.pumpAndSettle();
  404 + Get.to(() => SecondScreen());
  405 + await tester.pumpAndSettle();
359 Get.snackbar('title', "message"); 406 Get.snackbar('title', "message");
  407 + await tester.pumpAndSettle();
360 Get.back(closeOverlays: true); 408 Get.back(closeOverlays: true);
361 409
362 await tester.pumpAndSettle(); 410 await tester.pumpAndSettle();
363 411
364 expect(Get.isSnackbarOpen, false); 412 expect(Get.isSnackbarOpen, false);
  413 +
365 expect(find.byType(FirstScreen), findsOneWidget); 414 expect(find.byType(FirstScreen), findsOneWidget);
366 }); 415 });
367 416
368 - testWidgets("Get.defaultTransition smoke test", (tester) async {  
369 - await tester.pumpWidget(  
370 - Wrapper(  
371 - child: Container(),  
372 - defaultTransition: Transition.fadeIn,  
373 - ),  
374 - ); 417 + group("Get.defaultTransition smoke test", () {
  418 + testWidgets("fadeIn", (tester) async {
  419 + await tester.pumpWidget(
  420 + Wrapper(
  421 + child: Container(),
  422 + defaultTransition: Transition.fadeIn,
  423 + ),
  424 + );
375 425
376 - Get.to(FirstScreen()); 426 + Get.to(() => FirstScreen());
377 427
378 - await tester.pumpAndSettle(); 428 + await tester.pumpAndSettle();
379 429
380 - expect(find.byType(FirstScreen), findsOneWidget); 430 + expect(find.byType(FirstScreen), findsOneWidget);
  431 + });
381 432
382 - await tester.pumpWidget(  
383 - Wrapper(  
384 - child: Container(),  
385 - defaultTransition: Transition.downToUp,  
386 - ),  
387 - ); 433 + testWidgets("downToUp", (tester) async {
  434 + await tester.pumpWidget(
  435 + Wrapper(
  436 + child: Container(),
  437 + defaultTransition: Transition.downToUp,
  438 + ),
  439 + );
388 440
389 - Get.to(FirstScreen()); 441 + Get.to(() => FirstScreen());
390 442
391 - await tester.pumpAndSettle(); 443 + await tester.pumpAndSettle();
392 444
393 - expect(find.byType(FirstScreen), findsOneWidget); 445 + expect(find.byType(FirstScreen), findsOneWidget);
  446 + });
394 447
395 - await tester.pumpWidget(  
396 - Wrapper(  
397 - child: Container(),  
398 - defaultTransition: Transition.fade,  
399 - ),  
400 - ); 448 + testWidgets("fade", (tester) async {
  449 + await tester.pumpWidget(
  450 + Wrapper(
  451 + child: Container(),
  452 + defaultTransition: Transition.fade,
  453 + ),
  454 + );
401 455
402 - Get.to(FirstScreen()); 456 + Get.to(() => FirstScreen());
403 457
404 - await tester.pumpAndSettle(); 458 + await tester.pumpAndSettle();
405 459
406 - expect(find.byType(FirstScreen), findsOneWidget); 460 + expect(find.byType(FirstScreen), findsOneWidget);
  461 + });
407 462
408 - await tester.pumpWidget(  
409 - Wrapper(  
410 - child: Container(),  
411 - defaultTransition: Transition.leftToRight,  
412 - ),  
413 - ); 463 + testWidgets("leftToRight", (tester) async {
  464 + await tester.pumpWidget(
  465 + Wrapper(
  466 + child: Container(),
  467 + defaultTransition: Transition.leftToRight,
  468 + ),
  469 + );
414 470
415 - Get.to(FirstScreen()); 471 + Get.to(() => FirstScreen());
416 472
417 - await tester.pumpAndSettle(); 473 + await tester.pumpAndSettle();
418 474
419 - expect(find.byType(FirstScreen), findsOneWidget); 475 + expect(find.byType(FirstScreen), findsOneWidget);
  476 + });
420 477
421 - await tester.pumpWidget(  
422 - Wrapper(  
423 - child: Container(),  
424 - defaultTransition: Transition.leftToRightWithFade,  
425 - ),  
426 - ); 478 + testWidgets("leftToRightWithFade", (tester) async {
  479 + await tester.pumpWidget(
  480 + Wrapper(
  481 + child: Container(),
  482 + defaultTransition: Transition.leftToRightWithFade,
  483 + ),
  484 + );
427 485
428 - Get.to(FirstScreen()); 486 + Get.to(() => FirstScreen());
429 487
430 - await tester.pumpAndSettle(); 488 + await tester.pumpAndSettle();
431 489
432 - expect(find.byType(FirstScreen), findsOneWidget); 490 + expect(find.byType(FirstScreen), findsOneWidget);
  491 + });
433 492
434 - await tester.pumpWidget(  
435 - Wrapper(  
436 - child: Container(),  
437 - defaultTransition: Transition.rightToLeft,  
438 - ),  
439 - ); 493 + testWidgets("leftToRightWithFade", (tester) async {
  494 + await tester.pumpWidget(
  495 + Wrapper(
  496 + child: Container(),
  497 + defaultTransition: Transition.rightToLeft,
  498 + ),
  499 + );
440 500
441 - Get.to(FirstScreen()); 501 + Get.to(() => FirstScreen());
442 502
443 - await tester.pumpAndSettle(); 503 + await tester.pumpAndSettle();
444 504
445 - expect(find.byType(FirstScreen), findsOneWidget); 505 + expect(find.byType(FirstScreen), findsOneWidget);
  506 + });
446 507
447 - await tester.pumpWidget(  
448 - Wrapper(  
449 - child: Container(),  
450 - defaultTransition: Transition.rightToLeftWithFade,  
451 - ),  
452 - ); 508 + testWidgets("defaultTransition", (tester) async {
  509 + await tester.pumpWidget(
  510 + Wrapper(
  511 + child: Container(),
  512 + defaultTransition: Transition.rightToLeft,
  513 + ),
  514 + );
453 515
454 - Get.to(FirstScreen()); 516 + Get.to(() => FirstScreen());
455 517
456 - await tester.pumpAndSettle(); 518 + await tester.pumpAndSettle();
457 519
458 - expect(find.byType(FirstScreen), findsOneWidget); 520 + expect(find.byType(FirstScreen), findsOneWidget);
  521 + });
459 522
460 - await tester.pumpWidget(  
461 - Wrapper(  
462 - child: Container(),  
463 - defaultTransition: Transition.cupertino,  
464 - ),  
465 - ); 523 + testWidgets("rightToLeftWithFade", (tester) async {
  524 + await tester.pumpWidget(
  525 + Wrapper(
  526 + child: Container(),
  527 + defaultTransition: Transition.rightToLeftWithFade,
  528 + ),
  529 + );
466 530
467 - Get.to(FirstScreen()); 531 + Get.to(() => FirstScreen());
468 532
469 - await tester.pumpAndSettle(); 533 + await tester.pumpAndSettle();
470 534
471 - expect(find.byType(FirstScreen), findsOneWidget); 535 + expect(find.byType(FirstScreen), findsOneWidget);
  536 + });
472 537
473 - await tester.pumpWidget(  
474 - Wrapper(  
475 - child: Container(),  
476 - defaultTransition: Transition.size,  
477 - ),  
478 - ); 538 + testWidgets("cupertino", (tester) async {
  539 + await tester.pumpWidget(
  540 + Wrapper(
  541 + child: Container(),
  542 + defaultTransition: Transition.cupertino,
  543 + ),
  544 + );
479 545
480 - Get.to(FirstScreen()); 546 + Get.to(() => FirstScreen());
481 547
482 - await tester.pumpAndSettle(); 548 + await tester.pumpAndSettle();
483 549
484 - expect(find.byType(FirstScreen), findsOneWidget); 550 + expect(find.byType(FirstScreen), findsOneWidget);
  551 + });
  552 +
  553 + testWidgets("size", (tester) async {
  554 + await tester.pumpWidget(
  555 + Wrapper(
  556 + child: Container(),
  557 + defaultTransition: Transition.size,
  558 + ),
  559 + );
  560 +
  561 + Get.to(() => FirstScreen());
  562 +
  563 + await tester.pumpAndSettle();
  564 +
  565 + expect(find.byType(FirstScreen), findsOneWidget);
  566 + });
485 }); 567 });
486 } 568 }
487 569
@@ -5,8 +5,15 @@ import 'package:get/get.dart'; @@ -5,8 +5,15 @@ import 'package:get/get.dart';
5 import 'get_main_test.dart'; 5 import 'get_main_test.dart';
6 6
7 class RedirectMiddleware extends GetMiddleware { 7 class RedirectMiddleware extends GetMiddleware {
  8 + // @override
  9 + // RouteSettings redirect(String? route) {
  10 + // return RouteSettings(name: '/second');
  11 + // }
  12 +
8 @override 13 @override
9 - RouteSettings redirect(String? route) => RouteSettings(name: '/second'); 14 + Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
  15 + return RouteDecoder.fromRoute('/second');
  16 + }
10 } 17 }
11 18
12 void main() { 19 void main() {
@@ -16,10 +23,9 @@ void main() { @@ -16,10 +23,9 @@ void main() {
16 initialRoute: '/', 23 initialRoute: '/',
17 getPages: [ 24 getPages: [
18 GetPage(name: '/', page: () => Container()), 25 GetPage(name: '/', page: () => Container()),
19 - GetPage(  
20 - name: '/first',  
21 - page: () => FirstScreen(),  
22 - middlewares: [RedirectMiddleware()]), 26 + GetPage(name: '/first', page: () => FirstScreen(), middlewares: [
  27 + RedirectMiddleware(),
  28 + ]),
23 GetPage(name: '/second', page: () => SecondScreen()), 29 GetPage(name: '/second', page: () => SecondScreen()),
24 GetPage(name: '/third', page: () => ThirdScreen()), 30 GetPage(name: '/third', page: () => ThirdScreen()),
25 ], 31 ],
@@ -29,7 +35,7 @@ void main() { @@ -29,7 +35,7 @@ void main() {
29 Get.toNamed('/first'); 35 Get.toNamed('/first');
30 36
31 await tester.pumpAndSettle(); 37 await tester.pumpAndSettle();
32 - print(Get.routing.current); 38 + print(Get.rootController.rootDelegate.currentConfiguration?.route?.name);
33 expect(find.byType(SecondScreen), findsOneWidget); 39 expect(find.byType(SecondScreen), findsOneWidget);
34 }); 40 });
35 } 41 }
1 import 'package:flutter/cupertino.dart'; 1 import 'package:flutter/cupertino.dart';
2 import 'package:flutter_test/flutter_test.dart'; 2 import 'package:flutter_test/flutter_test.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
4 -import 'package:get/get_navigation/src/root/parse_route.dart';  
5 4
6 void main() { 5 void main() {
7 test('Parse Page with children', () { 6 test('Parse Page with children', () {
@@ -14,9 +14,12 @@ void main() { @@ -14,9 +14,12 @@ void main() {
14 child: Center( 14 child: Center(
15 child: CupertinoButton( 15 child: CupertinoButton(
16 onPressed: () { 16 onPressed: () {
17 - Get.to(() => CupertinoPageScaffold(  
18 - child: Center(child: Text('route')),  
19 - )); 17 + Get.to(
  18 + () => CupertinoPageScaffold(
  19 + child: Center(child: Text('route')),
  20 + ),
  21 + preventDuplicateHandlingMode:
  22 + PreventDuplicateHandlingMode.Recreate);
20 }, 23 },
21 child: const Text('push'), 24 child: const Text('push'),
22 ), 25 ),
@@ -25,6 +28,8 @@ void main() { @@ -25,6 +28,8 @@ void main() {
25 ), 28 ),
26 ); 29 );
27 30
  31 + await tester.pumpAndSettle();
  32 +
28 // Check the basic iOS back-swipe dismiss transition. Dragging the pushed 33 // Check the basic iOS back-swipe dismiss transition. Dragging the pushed
29 // route halfway across the screen will trigger the iOS dismiss animation 34 // route halfway across the screen will trigger the iOS dismiss animation
30 35
@@ -52,7 +57,7 @@ void main() { @@ -52,7 +57,7 @@ void main() {
52 of: find.text('push'), 57 of: find.text('push'),
53 matching: find.byType(CupertinoPageScaffold))) 58 matching: find.byType(CupertinoPageScaffold)))
54 .dx, 59 .dx,
55 - 0, 60 + moreOrLessEquals(-(400 / 3), epsilon: 1),
56 ); 61 );
57 await tester.pumpAndSettle(); 62 await tester.pumpAndSettle();
58 expect(find.text('push'), findsOneWidget); 63 expect(find.text('push'), findsOneWidget);
@@ -99,22 +104,5 @@ void main() { @@ -99,22 +104,5 @@ void main() {
99 .dx, 104 .dx,
100 moreOrLessEquals(798, epsilon: 1), 105 moreOrLessEquals(798, epsilon: 1),
101 ); 106 );
102 -  
103 - // Use the navigator to push a route instead of tapping the 'push' button.  
104 - // The topmost route (the one that's animating away), ignores input while  
105 - // the pop is underway because route.navigator.userGestureInProgress.  
106 - Get.to(() => const CupertinoPageScaffold(  
107 - child: Center(child: Text('route')),  
108 - ));  
109 -  
110 - await tester.pumpAndSettle();  
111 - expect(find.text('route'), findsOneWidget);  
112 - expect(find.text('push'), findsNothing);  
113 - expect(  
114 - tester  
115 - .state<NavigatorState>(find.byType(Navigator))  
116 - .userGestureInProgress,  
117 - false,  
118 - );  
119 }); 107 });
120 } 108 }