Showing
49 changed files
with
1540 additions
and
1455 deletions
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | -import 'package:get/route_manager.dart'; | 2 | +import 'package:get/get.dart'; |
| 3 | 3 | ||
| 4 | import 'lang/translation_service.dart'; | 4 | import 'lang/translation_service.dart'; |
| 5 | import 'routes/app_pages.dart'; | 5 | import 'routes/app_pages.dart'; |
| @@ -9,31 +9,16 @@ void main() { | @@ -9,31 +9,16 @@ void main() { | ||
| 9 | runApp(MyApp()); | 9 | runApp(MyApp()); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | -class MyApp extends StatefulWidget { | ||
| 13 | - MyApp({Key? key}) : super(key: key); | 12 | +class MyApp extends StatelessWidget { |
| 13 | + const MyApp({Key? key}) : super(key: key); | ||
| 14 | 14 | ||
| 15 | @override | 15 | @override |
| 16 | - State<MyApp> createState() => _MyAppState(); | ||
| 17 | -} | ||
| 18 | - | ||
| 19 | -class _MyAppState extends State<MyApp> { | ||
| 20 | - late final routerDelegate = GetNavigation.instance = GetNavigation( | ||
| 21 | - pages: AppPages.routes, | ||
| 22 | - navigatorObservers: [GetObserver()], | ||
| 23 | - ); | ||
| 24 | - | ||
| 25 | - final routeInformationParser = | ||
| 26 | - NewGetInformationParser(initialRoute: AppPages.INITIAL); | ||
| 27 | - @override | ||
| 28 | Widget build(BuildContext context) { | 16 | Widget build(BuildContext context) { |
| 29 | - return GetMaterialApp.router( | ||
| 30 | - routeInformationParser: routeInformationParser, | ||
| 31 | - routerDelegate: routerDelegate, | ||
| 32 | - // title: 'Router Management Example', | 17 | + return GetMaterialApp( |
| 33 | debugShowCheckedModeBanner: false, | 18 | debugShowCheckedModeBanner: false, |
| 34 | enableLog: true, | 19 | enableLog: true, |
| 35 | logWriterCallback: Logger.write, | 20 | logWriterCallback: Logger.write, |
| 36 | - // initialRoute: AppPages.INITIAL, | 21 | + initialRoute: AppPages.INITIAL, |
| 37 | getPages: AppPages.routes, | 22 | getPages: AppPages.routes, |
| 38 | locale: TranslationService.locale, | 23 | locale: TranslationService.locale, |
| 39 | fallbackLocale: TranslationService.fallbackLocale, | 24 | fallbackLocale: TranslationService.fallbackLocale, |
| @@ -42,8 +27,6 @@ class _MyAppState extends State<MyApp> { | @@ -42,8 +27,6 @@ class _MyAppState extends State<MyApp> { | ||
| 42 | } | 27 | } |
| 43 | } | 28 | } |
| 44 | 29 | ||
| 45 | - | ||
| 46 | - | ||
| 47 | /// Nav 2 snippet | 30 | /// Nav 2 snippet |
| 48 | // void main() { | 31 | // void main() { |
| 49 | // runApp(MyApp()); | 32 | // runApp(MyApp()); |
| @@ -6,8 +6,11 @@ import 'package:get/get.dart'; | @@ -6,8 +6,11 @@ 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) { |
| 12 | + print('BUILD CONTRY'); | ||
| 13 | + print(context.params); | ||
| 11 | return Container( | 14 | return Container( |
| 12 | decoration: BoxDecoration( | 15 | decoration: BoxDecoration( |
| 13 | image: DecorationImage( | 16 | image: DecorationImage( |
| @@ -34,8 +37,8 @@ class CountryView extends GetView<HomeController> { | @@ -34,8 +37,8 @@ class CountryView extends GetView<HomeController> { | ||
| 34 | return ListTile( | 37 | return ListTile( |
| 35 | onTap: () async { | 38 | onTap: () async { |
| 36 | //Get.rootDelegate.toNamed('/home/country'); | 39 | //Get.rootDelegate.toNamed('/home/country'); |
| 37 | - final data = await GetNavigation.instance | ||
| 38 | - .toNamed('/home/country/details?id=$index'); | 40 | + final data = await Get.toNamed( |
| 41 | + '/home/country/details?id=$index'); | ||
| 39 | print(data); | 42 | print(data); |
| 40 | }, | 43 | }, |
| 41 | trailing: CircleAvatar( | 44 | trailing: CircleAvatar( |
| @@ -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 DetailsView extends GetView<HomeController> { | 8 | class DetailsView extends GetView<HomeController> { |
| 9 | + const DetailsView({Key? key}) : super(key: key); | ||
| 9 | @override | 10 | @override |
| 10 | Widget build(BuildContext context) { | 11 | Widget build(BuildContext context) { |
| 11 | final args = ModalRoute.of(context)!.settings.arguments as PageSettings; | 12 | final args = ModalRoute.of(context)!.settings.arguments as PageSettings; |
| @@ -80,7 +81,7 @@ class DetailsView extends GetView<HomeController> { | @@ -80,7 +81,7 @@ class DetailsView extends GetView<HomeController> { | ||
| 80 | ), | 81 | ), |
| 81 | TextButton( | 82 | TextButton( |
| 82 | onPressed: () { | 83 | onPressed: () { |
| 83 | - GetNavigation.instance.back('djsoidjsoidj'); | 84 | + Get.back(result: 'djsoidjsoidj'); |
| 84 | }, | 85 | }, |
| 85 | child: Text('back')) | 86 | child: Text('back')) |
| 86 | ], | 87 | ], |
| @@ -4,8 +4,12 @@ import 'package:get/get.dart'; | @@ -4,8 +4,12 @@ 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) { |
| 11 | + print('REBUILD HOME'); | ||
| 12 | + // print(Get.parameters); | ||
| 9 | return Container( | 13 | return Container( |
| 10 | decoration: BoxDecoration( | 14 | decoration: BoxDecoration( |
| 11 | color: Colors.white, | 15 | color: Colors.white, |
| @@ -76,7 +80,7 @@ class HomeView extends GetView<HomeController> { | @@ -76,7 +80,7 @@ class HomeView extends GetView<HomeController> { | ||
| 76 | ), | 80 | ), |
| 77 | onPressed: () async { | 81 | onPressed: () async { |
| 78 | //await Navigation Get.rootDelegate.toNamed('/home/country'); | 82 | //await Navigation Get.rootDelegate.toNamed('/home/country'); |
| 79 | - GetNavigation.instance.toNamed('/home/country'); | 83 | + Get.toNamed('/countrdhia'); |
| 80 | }, | 84 | }, |
| 81 | child: Text( | 85 | child: Text( |
| 82 | 'fetch_country'.tr, | 86 | 'fetch_country'.tr, |
| @@ -2,31 +2,30 @@ import 'package:get/get.dart'; | @@ -2,31 +2,30 @@ import 'package:get/get.dart'; | ||
| 2 | 2 | ||
| 3 | import '../pages/home/bindings/home_binding.dart'; | 3 | import '../pages/home/bindings/home_binding.dart'; |
| 4 | import '../pages/home/presentation/views/country_view.dart'; | 4 | import '../pages/home/presentation/views/country_view.dart'; |
| 5 | -import '../pages/home/presentation/views/details_view.dart'; | ||
| 6 | import '../pages/home/presentation/views/home_view.dart'; | 5 | import '../pages/home/presentation/views/home_view.dart'; |
| 7 | 6 | ||
| 8 | part 'app_routes.dart'; | 7 | part 'app_routes.dart'; |
| 9 | 8 | ||
| 10 | // ignore: avoid_classes_with_only_static_members | 9 | // ignore: avoid_classes_with_only_static_members |
| 11 | class AppPages { | 10 | class AppPages { |
| 12 | - static const INITIAL = Routes.HOME; | 11 | + static const INITIAL = '${Routes.HOME}?schineider=uuu'; |
| 13 | 12 | ||
| 14 | static final routes = [ | 13 | static final routes = [ |
| 15 | GetPage( | 14 | 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 | - ]), | 15 | + name: '${Routes.HOME}', |
| 16 | + page: () => const HomeView(), | ||
| 17 | + binding: HomeBinding(), | ||
| 18 | + children: [], | ||
| 19 | + ), | ||
| 20 | + GetPage( | ||
| 21 | + name: '${Routes.COUNTRY}/:xasa', | ||
| 22 | + page: () => const CountryView(), | ||
| 23 | + // children: [ | ||
| 24 | + // GetPage( | ||
| 25 | + // name: Routes.DETAILS, | ||
| 26 | + // page: () => DetailsView(), | ||
| 27 | + // ), | ||
| 28 | + // ], | ||
| 29 | + ), | ||
| 31 | ]; | 30 | ]; |
| 32 | } | 31 | } |
| @@ -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,14 +5,15 @@ import '../routes/app_pages.dart'; | @@ -5,14 +5,15 @@ 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?> redirectDelegate(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 newRoute = Routes.LOGIN_THEN(route.arguments!.name); |
| 15 | + | ||
| 16 | + return RouteDecoder.fromRoute(newRoute); | ||
| 16 | } | 17 | } |
| 17 | return await super.redirectDelegate(route); | 18 | return await super.redirectDelegate(route); |
| 18 | } | 19 | } |
| @@ -20,13 +21,13 @@ class EnsureAuthMiddleware extends GetMiddleware { | @@ -20,13 +21,13 @@ class EnsureAuthMiddleware extends GetMiddleware { | ||
| 20 | 21 | ||
| 21 | class EnsureNotAuthedMiddleware extends GetMiddleware { | 22 | class EnsureNotAuthedMiddleware extends GetMiddleware { |
| 22 | @override | 23 | @override |
| 23 | - Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async { | 24 | + Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async { |
| 24 | if (AuthService.to.isLoggedInValue) { | 25 | if (AuthService.to.isLoggedInValue) { |
| 25 | //NEVER navigate to auth screen, when user is already authed | 26 | //NEVER navigate to auth screen, when user is already authed |
| 26 | return null; | 27 | return null; |
| 27 | 28 | ||
| 28 | //OR redirect user to another screen | 29 | //OR redirect user to another screen |
| 29 | - //return GetNavConfig.fromRoute(Routes.PROFILE); | 30 | + //return RouteDecoder.fromRoute(Routes.PROFILE); |
| 30 | } | 31 | } |
| 31 | return await super.redirectDelegate(route); | 32 | return await super.redirectDelegate(route); |
| 32 | } | 33 | } |
| @@ -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,7 +31,7 @@ class ProductsView extends GetView<ProductsController> { | @@ -31,7 +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 | 34 | + Get |
| 35 | .toNamed(Routes.PRODUCT_DETAILS(item.id)); | 35 | .toNamed(Routes.PRODUCT_DETAILS(item.id)); |
| 36 | }, | 36 | }, |
| 37 | title: Text(item.name), | 37 | title: Text(item.name), |
| @@ -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( |
| @@ -2,12 +2,6 @@ library get_navigation; | @@ -2,12 +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/nav3/get_navigation/index.dart'; | ||
| 11 | export 'src/root/get_cupertino_app.dart'; | 5 | export 'src/root/get_cupertino_app.dart'; |
| 12 | export 'src/root/get_material_app.dart'; | 6 | export 'src/root/get_material_app.dart'; |
| 13 | export 'src/root/internacionalization.dart'; | 7 | export 'src/root/internacionalization.dart'; |
| @@ -15,6 +9,7 @@ export 'src/root/root_controller.dart'; | @@ -15,6 +9,7 @@ export 'src/root/root_controller.dart'; | ||
| 15 | export 'src/routes/custom_transition.dart'; | 9 | export 'src/routes/custom_transition.dart'; |
| 16 | export 'src/routes/default_route.dart'; | 10 | export 'src/routes/default_route.dart'; |
| 17 | export 'src/routes/get_route.dart'; | 11 | export 'src/routes/get_route.dart'; |
| 12 | +export 'src/routes/index.dart'; | ||
| 18 | export 'src/routes/observers/route_observer.dart'; | 13 | export 'src/routes/observers/route_observer.dart'; |
| 19 | export 'src/routes/route_middleware.dart'; | 14 | export 'src/routes/route_middleware.dart'; |
| 20 | export 'src/routes/transitions_type.dart'; | 15 | export 'src/routes/transitions_type.dart'; |
| @@ -9,7 +9,6 @@ import '../../get_state_manager/src/simple/get_state.dart'; | @@ -9,7 +9,6 @@ import '../../get_state_manager/src/simple/get_state.dart'; | ||
| 9 | import '../../get_utils/get_utils.dart'; | 9 | import '../../get_utils/get_utils.dart'; |
| 10 | import '../get_navigation.dart'; | 10 | import '../get_navigation.dart'; |
| 11 | import 'dialog/dialog_route.dart'; | 11 | import 'dialog/dialog_route.dart'; |
| 12 | -import 'root/parse_route.dart'; | ||
| 13 | 12 | ||
| 14 | /// It replaces the Flutter Navigator, but needs no context. | 13 | /// It replaces the Flutter Navigator, but needs no context. |
| 15 | /// You can to use navigator.push(YourRoute()) rather | 14 | /// You can to use navigator.push(YourRoute()) rather |
| @@ -78,6 +77,7 @@ extension ExtensionDialog on GetInterface { | @@ -78,6 +77,7 @@ extension ExtensionDialog on GetInterface { | ||
| 78 | Curve? transitionCurve, | 77 | Curve? transitionCurve, |
| 79 | String? name, | 78 | String? name, |
| 80 | RouteSettings? routeSettings, | 79 | RouteSettings? routeSettings, |
| 80 | + dynamic id, | ||
| 81 | }) { | 81 | }) { |
| 82 | assert(debugCheckHasMaterialLocalizations(context!)); | 82 | assert(debugCheckHasMaterialLocalizations(context!)); |
| 83 | 83 | ||
| @@ -110,22 +110,24 @@ extension ExtensionDialog on GetInterface { | @@ -110,22 +110,24 @@ extension ExtensionDialog on GetInterface { | ||
| 110 | navigatorKey: navigatorKey, | 110 | navigatorKey: navigatorKey, |
| 111 | routeSettings: | 111 | routeSettings: |
| 112 | routeSettings ?? RouteSettings(arguments: arguments, name: name), | 112 | routeSettings ?? RouteSettings(arguments: arguments, name: name), |
| 113 | + id: id, | ||
| 113 | ); | 114 | ); |
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | /// Api from showGeneralDialog with no context | 117 | /// 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 | - }) { | 118 | + Future<T?> generalDialog<T>( |
| 119 | + {required RoutePageBuilder pageBuilder, | ||
| 120 | + bool barrierDismissible = false, | ||
| 121 | + String? barrierLabel, | ||
| 122 | + Color barrierColor = const Color(0x80000000), | ||
| 123 | + Duration transitionDuration = const Duration(milliseconds: 200), | ||
| 124 | + RouteTransitionsBuilder? transitionBuilder, | ||
| 125 | + GlobalKey<NavigatorState>? navigatorKey, | ||
| 126 | + RouteSettings? routeSettings, | ||
| 127 | + dynamic id}) { | ||
| 127 | assert(!barrierDismissible || barrierLabel != null); | 128 | assert(!barrierDismissible || barrierLabel != null); |
| 128 | - final nav = navigatorKey?.currentState ?? | 129 | + final key = navigatorKey ?? Get.nestedKey(id)?.navigatorKey; |
| 130 | + final nav = key?.currentState ?? | ||
| 129 | Navigator.of(overlayContext!, | 131 | Navigator.of(overlayContext!, |
| 130 | rootNavigator: | 132 | rootNavigator: |
| 131 | true); //overlay context will always return the root navigator | 133 | true); //overlay context will always return the root navigator |
| @@ -148,6 +150,7 @@ extension ExtensionDialog on GetInterface { | @@ -148,6 +150,7 @@ extension ExtensionDialog on GetInterface { | ||
| 148 | EdgeInsetsGeometry? titlePadding, | 150 | EdgeInsetsGeometry? titlePadding, |
| 149 | TextStyle? titleStyle, | 151 | TextStyle? titleStyle, |
| 150 | Widget? content, | 152 | Widget? content, |
| 153 | + dynamic id, | ||
| 151 | EdgeInsetsGeometry? contentPadding, | 154 | EdgeInsetsGeometry? contentPadding, |
| 152 | VoidCallback? onConfirm, | 155 | VoidCallback? onConfirm, |
| 153 | VoidCallback? onCancel, | 156 | VoidCallback? onCancel, |
| @@ -269,6 +272,7 @@ extension ExtensionDialog on GetInterface { | @@ -269,6 +272,7 @@ extension ExtensionDialog on GetInterface { | ||
| 269 | : baseAlertDialog, | 272 | : baseAlertDialog, |
| 270 | barrierDismissible: barrierDismissible, | 273 | barrierDismissible: barrierDismissible, |
| 271 | navigatorKey: navigatorKey, | 274 | navigatorKey: navigatorKey, |
| 275 | + id: id, | ||
| 272 | ); | 276 | ); |
| 273 | } | 277 | } |
| 274 | } | 278 | } |
| @@ -499,66 +503,60 @@ extension GetNavigationExt on GetInterface { | @@ -499,66 +503,60 @@ extension GetNavigationExt on GetInterface { | ||
| 499 | /// | 503 | /// |
| 500 | /// By default, GetX will prevent you from push a route that you already in, | 504 | /// 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 | 505 | /// 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 | - ); | 506 | + Future<T?>? to<T>(Widget Function() page, |
| 507 | + {bool? opaque, | ||
| 508 | + Transition? transition, | ||
| 509 | + Curve? curve, | ||
| 510 | + Duration? duration, | ||
| 511 | + int? id, | ||
| 512 | + String? routeName, | ||
| 513 | + bool fullscreenDialog = false, | ||
| 514 | + dynamic arguments, | ||
| 515 | + Binding? binding, | ||
| 516 | + bool preventDuplicates = true, | ||
| 517 | + bool? popGesture, | ||
| 518 | + bool showCupertinoParallax = true, | ||
| 519 | + double Function(BuildContext context)? gestureWidth, | ||
| 520 | + bool rebuildStack = true, | ||
| 521 | + PreventDuplicateHandlingMode preventDuplicateHandlingMode = | ||
| 522 | + PreventDuplicateHandlingMode.ReorderRoutes}) { | ||
| 523 | + searchDelegate(id).to( | ||
| 524 | + page, | ||
| 525 | + opaque: opaque, | ||
| 526 | + transition: transition, | ||
| 527 | + curve: curve, | ||
| 528 | + duration: duration, | ||
| 529 | + id: id, | ||
| 530 | + routeName: routeName, | ||
| 531 | + fullscreenDialog: fullscreenDialog, | ||
| 532 | + arguments: arguments, | ||
| 533 | + binding: binding, | ||
| 534 | + preventDuplicates: preventDuplicates, | ||
| 535 | + popGesture: popGesture, | ||
| 536 | + showCupertinoParallax: showCupertinoParallax, | ||
| 537 | + gestureWidth: gestureWidth, | ||
| 538 | + rebuildStack: rebuildStack, | ||
| 539 | + preventDuplicateHandlingMode: preventDuplicateHandlingMode, | ||
| 540 | + ); | ||
| 543 | } | 541 | } |
| 544 | 542 | ||
| 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 | - } | 543 | +// GetPageBuilder _resolvePage(dynamic page, String method) { |
| 544 | +// if (page is GetPageBuilder) { | ||
| 545 | +// return page; | ||
| 546 | +// } else if (page is Widget) { | ||
| 547 | +// Get.log( | ||
| 548 | +// '''WARNING, consider using: "Get.$method(() => Page())" instead of "Get.$method(Page())". | ||
| 549 | +// 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. | ||
| 550 | +// '''); | ||
| 551 | +// return () => page; | ||
| 552 | +// } else if (page is String) { | ||
| 553 | +// throw '''Unexpected String, | ||
| 554 | +// use toNamed() instead'''; | ||
| 555 | +// } else { | ||
| 556 | +// throw '''Unexpected format, | ||
| 557 | +// you can only use widgets and widget functions here'''; | ||
| 558 | +// } | ||
| 559 | +// } | ||
| 562 | 560 | ||
| 563 | /// **Navigation.pushNamed()** shortcut.<br><br> | 561 | /// **Navigation.pushNamed()** shortcut.<br><br> |
| 564 | /// | 562 | /// |
| @@ -592,10 +590,13 @@ you can only use widgets and widget functions here'''; | @@ -592,10 +590,13 @@ you can only use widgets and widget functions here'''; | ||
| 592 | page = uri.toString(); | 590 | page = uri.toString(); |
| 593 | } | 591 | } |
| 594 | 592 | ||
| 595 | - return global(id).currentState?.pushNamed<T>( | ||
| 596 | - page, | ||
| 597 | - arguments: arguments, | ||
| 598 | - ); | 593 | + return searchDelegate(id).toNamed( |
| 594 | + page, | ||
| 595 | + arguments: arguments, | ||
| 596 | + id: id, | ||
| 597 | + preventDuplicates: preventDuplicates, | ||
| 598 | + parameters: parameters, | ||
| 599 | + ); | ||
| 599 | } | 600 | } |
| 600 | 601 | ||
| 601 | /// **Navigation.pushReplacementNamed()** shortcut.<br><br> | 602 | /// **Navigation.pushReplacementNamed()** shortcut.<br><br> |
| @@ -618,21 +619,23 @@ you can only use widgets and widget functions here'''; | @@ -618,21 +619,23 @@ you can only use widgets and widget functions here'''; | ||
| 618 | String page, { | 619 | String page, { |
| 619 | dynamic arguments, | 620 | dynamic arguments, |
| 620 | int? id, | 621 | int? id, |
| 621 | - bool preventDuplicates = true, | ||
| 622 | Map<String, String>? parameters, | 622 | Map<String, String>? parameters, |
| 623 | }) { | 623 | }) { |
| 624 | - if (preventDuplicates && page == currentRoute) { | ||
| 625 | - return null; | ||
| 626 | - } | 624 | + // if (preventDuplicates && page == currentRoute) { |
| 625 | + // return null; | ||
| 626 | + // } | ||
| 627 | 627 | ||
| 628 | if (parameters != null) { | 628 | if (parameters != null) { |
| 629 | final uri = Uri(path: page, queryParameters: parameters); | 629 | final uri = Uri(path: page, queryParameters: parameters); |
| 630 | page = uri.toString(); | 630 | page = uri.toString(); |
| 631 | } | 631 | } |
| 632 | - return global(id).currentState?.pushReplacementNamed( | ||
| 633 | - page, | ||
| 634 | - arguments: arguments, | ||
| 635 | - ); | 632 | + return searchDelegate(id).offNamed( |
| 633 | + page, | ||
| 634 | + arguments: arguments, | ||
| 635 | + id: id, | ||
| 636 | + // preventDuplicates: preventDuplicates, | ||
| 637 | + parameters: parameters, | ||
| 638 | + ); | ||
| 636 | } | 639 | } |
| 637 | 640 | ||
| 638 | /// **Navigation.popUntil()** shortcut.<br><br> | 641 | /// **Navigation.popUntil()** shortcut.<br><br> |
| @@ -648,34 +651,10 @@ you can only use widgets and widget functions here'''; | @@ -648,34 +651,10 @@ you can only use widgets and widget functions here'''; | ||
| 648 | /// or also like this: | 651 | /// or also like this: |
| 649 | /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the | 652 | /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the |
| 650 | /// dialog is closed | 653 | /// dialog is closed |
| 651 | - void until(RoutePredicate predicate, {int? id}) { | ||
| 652 | - // if (key.currentState.mounted) // add this if appear problems on future with route navigate | ||
| 653 | - // 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}) { | 654 | + void until(bool Function(GetPage<dynamic>) predicate, {int? id}) { |
| 676 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate | 655 | // if (key.currentState.mounted) // add this if appear problems on future with route navigate |
| 677 | // when widget don't mounted | 656 | // when widget don't mounted |
| 678 | - return global(id).currentState?.pushAndRemoveUntil<T>(page, predicate); | 657 | + return searchDelegate(id).backUntil(predicate); |
| 679 | } | 658 | } |
| 680 | 659 | ||
| 681 | /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> | 660 | /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> |
| @@ -698,7 +677,7 @@ you can only use widgets and widget functions here'''; | @@ -698,7 +677,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 | 677 | /// Note: Always put a slash on the route name ('/page1'), to avoid unexpected errors |
| 699 | Future<T?>? offNamedUntil<T>( | 678 | Future<T?>? offNamedUntil<T>( |
| 700 | String page, | 679 | String page, |
| 701 | - RoutePredicate predicate, { | 680 | + bool Function(GetPage<dynamic>)? predicate, { |
| 702 | int? id, | 681 | int? id, |
| 703 | dynamic arguments, | 682 | dynamic arguments, |
| 704 | Map<String, String>? parameters, | 683 | Map<String, String>? parameters, |
| @@ -708,11 +687,13 @@ you can only use widgets and widget functions here'''; | @@ -708,11 +687,13 @@ you can only use widgets and widget functions here'''; | ||
| 708 | page = uri.toString(); | 687 | page = uri.toString(); |
| 709 | } | 688 | } |
| 710 | 689 | ||
| 711 | - return global(id).currentState?.pushNamedAndRemoveUntil<T>( | ||
| 712 | - page, | ||
| 713 | - predicate, | ||
| 714 | - arguments: arguments, | ||
| 715 | - ); | 690 | + return searchDelegate(id).offNamedUntil<T>( |
| 691 | + page, | ||
| 692 | + predicate: predicate, | ||
| 693 | + id: id, | ||
| 694 | + arguments: arguments, | ||
| 695 | + parameters: parameters, | ||
| 696 | + ); | ||
| 716 | } | 697 | } |
| 717 | 698 | ||
| 718 | /// **Navigation.popAndPushNamed()** shortcut.<br><br> | 699 | /// **Navigation.popAndPushNamed()** shortcut.<br><br> |
| @@ -737,11 +718,11 @@ you can only use widgets and widget functions here'''; | @@ -737,11 +718,11 @@ you can only use widgets and widget functions here'''; | ||
| 737 | final uri = Uri(path: page, queryParameters: parameters); | 718 | final uri = Uri(path: page, queryParameters: parameters); |
| 738 | page = uri.toString(); | 719 | page = uri.toString(); |
| 739 | } | 720 | } |
| 740 | - return global(id).currentState?.popAndPushNamed( | ||
| 741 | - page, | ||
| 742 | - arguments: arguments, | ||
| 743 | - result: result, | ||
| 744 | - ); | 721 | + return searchDelegate(id).backAndtoNamed( |
| 722 | + page, | ||
| 723 | + arguments: arguments, | ||
| 724 | + result: result, | ||
| 725 | + ); | ||
| 745 | } | 726 | } |
| 746 | 727 | ||
| 747 | /// **Navigation.removeRoute()** shortcut.<br><br> | 728 | /// **Navigation.removeRoute()** shortcut.<br><br> |
| @@ -750,8 +731,8 @@ you can only use widgets and widget functions here'''; | @@ -750,8 +731,8 @@ you can only use widgets and widget functions here'''; | ||
| 750 | /// | 731 | /// |
| 751 | /// [id] is for when you are using nested navigation, | 732 | /// [id] is for when you are using nested navigation, |
| 752 | /// as explained in documentation | 733 | /// as explained in documentation |
| 753 | - void removeRoute(Route<dynamic> route, {int? id}) { | ||
| 754 | - return global(id).currentState?.removeRoute(route); | 734 | + void removeRoute(String name, {int? id}) { |
| 735 | + return searchDelegate(id).removeRoute(name); | ||
| 755 | } | 736 | } |
| 756 | 737 | ||
| 757 | /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> | 738 | /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> |
| @@ -776,7 +757,7 @@ you can only use widgets and widget functions here'''; | @@ -776,7 +757,7 @@ you can only use widgets and widget functions here'''; | ||
| 776 | /// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors | 757 | /// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors |
| 777 | Future<T?>? offAllNamed<T>( | 758 | Future<T?>? offAllNamed<T>( |
| 778 | String newRouteName, { | 759 | String newRouteName, { |
| 779 | - RoutePredicate? predicate, | 760 | + // bool Function(GetPage<dynamic>)? predicate, |
| 780 | dynamic arguments, | 761 | dynamic arguments, |
| 781 | int? id, | 762 | int? id, |
| 782 | Map<String, String>? parameters, | 763 | Map<String, String>? parameters, |
| @@ -786,11 +767,13 @@ you can only use widgets and widget functions here'''; | @@ -786,11 +767,13 @@ you can only use widgets and widget functions here'''; | ||
| 786 | newRouteName = uri.toString(); | 767 | newRouteName = uri.toString(); |
| 787 | } | 768 | } |
| 788 | 769 | ||
| 789 | - return global(id).currentState?.pushNamedAndRemoveUntil<T>( | ||
| 790 | - newRouteName, | ||
| 791 | - predicate ?? (_) => false, | ||
| 792 | - arguments: arguments, | ||
| 793 | - ); | 770 | + return searchDelegate(id).offAllNamed<T>( |
| 771 | + newRouteName, | ||
| 772 | + //predicate: predicate ?? (_) => false, | ||
| 773 | + arguments: arguments, | ||
| 774 | + id: id, | ||
| 775 | + parameters: parameters, | ||
| 776 | + ); | ||
| 794 | } | 777 | } |
| 795 | 778 | ||
| 796 | /// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN | 779 | /// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN |
| @@ -832,16 +815,19 @@ you can only use widgets and widget functions here'''; | @@ -832,16 +815,19 @@ you can only use widgets and widget functions here'''; | ||
| 832 | if (isSnackbarOpen) { | 815 | if (isSnackbarOpen) { |
| 833 | closeAllSnackbars(); | 816 | closeAllSnackbars(); |
| 834 | } | 817 | } |
| 835 | - navigator?.popUntil((route) { | ||
| 836 | - return (!isDialogOpen! && !isBottomSheetOpen!); | ||
| 837 | - }); | 818 | + |
| 819 | + searchDelegate(id) | ||
| 820 | + .backUntil((route) => (!isDialogOpen! && !isBottomSheetOpen!)); | ||
| 821 | + // navigator?.popUntil((route) { | ||
| 822 | + // return; | ||
| 823 | + // }); | ||
| 838 | } | 824 | } |
| 839 | if (canPop) { | 825 | if (canPop) { |
| 840 | - if (global(id).currentState?.canPop() == true) { | ||
| 841 | - global(id).currentState?.pop<T>(result); | 826 | + if (searchDelegate(id).canBack == true) { |
| 827 | + searchDelegate(id).back<T>(result); | ||
| 842 | } | 828 | } |
| 843 | } else { | 829 | } else { |
| 844 | - global(id).currentState?.pop<T>(result); | 830 | + searchDelegate(id).back<T>(result); |
| 845 | } | 831 | } |
| 846 | } | 832 | } |
| 847 | 833 | ||
| @@ -856,7 +842,7 @@ you can only use widgets and widget functions here'''; | @@ -856,7 +842,7 @@ you can only use widgets and widget functions here'''; | ||
| 856 | times = 1; | 842 | times = 1; |
| 857 | } | 843 | } |
| 858 | var count = 0; | 844 | var count = 0; |
| 859 | - var back = global(id).currentState?.popUntil((route) => count++ == times); | 845 | + var back = searchDelegate(id).backUntil((route) => count++ == times); |
| 860 | 846 | ||
| 861 | return back; | 847 | return back; |
| 862 | } | 848 | } |
| @@ -887,8 +873,8 @@ you can only use widgets and widget functions here'''; | @@ -887,8 +873,8 @@ you can only use widgets and widget functions here'''; | ||
| 887 | /// By default, GetX will prevent you from push a route that you already in, | 873 | /// 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 | 874 | /// if you want to push anyway, set [preventDuplicates] to false |
| 889 | Future<T?>? off<T>( | 875 | Future<T?>? off<T>( |
| 890 | - dynamic page, { | ||
| 891 | - bool opaque = false, | 876 | + Widget Function() page, { |
| 877 | + bool? opaque, | ||
| 892 | Transition? transition, | 878 | Transition? transition, |
| 893 | Curve? curve, | 879 | Curve? curve, |
| 894 | bool? popGesture, | 880 | bool? popGesture, |
| @@ -906,21 +892,34 @@ you can only use widgets and widget functions here'''; | @@ -906,21 +892,34 @@ you can only use widgets and widget functions here'''; | ||
| 906 | if (preventDuplicates && routeName == currentRoute) { | 892 | if (preventDuplicates && routeName == currentRoute) { |
| 907 | return null; | 893 | return null; |
| 908 | } | 894 | } |
| 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)); | 895 | + return searchDelegate(id).off( |
| 896 | + page, | ||
| 897 | + opaque: opaque ?? true, | ||
| 898 | + transition: transition, | ||
| 899 | + curve: curve, | ||
| 900 | + popGesture: popGesture, | ||
| 901 | + id: id, | ||
| 902 | + routeName: routeName, | ||
| 903 | + arguments: arguments, | ||
| 904 | + binding: binding, | ||
| 905 | + fullscreenDialog: fullscreenDialog, | ||
| 906 | + preventDuplicates: preventDuplicates, | ||
| 907 | + duration: duration, | ||
| 908 | + gestureWidth: gestureWidth, | ||
| 909 | + ); | ||
| 910 | + } | ||
| 911 | + | ||
| 912 | + Future<T?> offUntil<T>( | ||
| 913 | + Widget Function() page, | ||
| 914 | + bool Function(GetPage) predicate, [ | ||
| 915 | + Object? arguments, | ||
| 916 | + int? id, | ||
| 917 | + ]) { | ||
| 918 | + return searchDelegate(id).offUntil( | ||
| 919 | + page, | ||
| 920 | + predicate, | ||
| 921 | + arguments, | ||
| 922 | + ); | ||
| 924 | } | 923 | } |
| 925 | 924 | ||
| 926 | /// | 925 | /// |
| @@ -954,9 +953,9 @@ you can only use widgets and widget functions here'''; | @@ -954,9 +953,9 @@ you can only use widgets and widget functions here'''; | ||
| 954 | /// By default, GetX will prevent you from push a route that you already in, | 953 | /// 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 | 954 | /// if you want to push anyway, set [preventDuplicates] to false |
| 956 | Future<T?>? offAll<T>( | 955 | Future<T?>? offAll<T>( |
| 957 | - dynamic page, { | ||
| 958 | - RoutePredicate? predicate, | ||
| 959 | - bool opaque = false, | 956 | + Widget Function() page, { |
| 957 | + bool Function(GetPage<dynamic>)? predicate, | ||
| 958 | + bool? opaque, | ||
| 960 | bool? popGesture, | 959 | bool? popGesture, |
| 961 | int? id, | 960 | int? id, |
| 962 | String? routeName, | 961 | String? routeName, |
| @@ -970,24 +969,21 @@ you can only use widgets and widget functions here'''; | @@ -970,24 +969,21 @@ you can only use widgets and widget functions here'''; | ||
| 970 | }) { | 969 | }) { |
| 971 | routeName ??= "/${page.runtimeType.toString()}"; | 970 | routeName ??= "/${page.runtimeType.toString()}"; |
| 972 | routeName = _cleanRouteName(routeName); | 971 | 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); | 972 | + return searchDelegate(id).offAll<T>( |
| 973 | + page, | ||
| 974 | + predicate: predicate, | ||
| 975 | + opaque: opaque ?? true, | ||
| 976 | + popGesture: popGesture, | ||
| 977 | + id: id, | ||
| 978 | + // routeName routeName, | ||
| 979 | + arguments: arguments, | ||
| 980 | + binding: binding, | ||
| 981 | + fullscreenDialog: fullscreenDialog, | ||
| 982 | + transition: transition, | ||
| 983 | + curve: curve, | ||
| 984 | + duration: duration, | ||
| 985 | + gestureWidth: gestureWidth, | ||
| 986 | + ); | ||
| 991 | } | 987 | } |
| 992 | 988 | ||
| 993 | /// Takes a route [name] String generated by [to], [off], [offAll] | 989 | /// Takes a route [name] String generated by [to], [off], [offAll] |
| @@ -1072,20 +1068,22 @@ you can only use widgets and widget functions here'''; | @@ -1072,20 +1068,22 @@ you can only use widgets and widget functions here'''; | ||
| 1072 | return _getxController.addKey(newKey); | 1068 | return _getxController.addKey(newKey); |
| 1073 | } | 1069 | } |
| 1074 | 1070 | ||
| 1075 | - GlobalKey<NavigatorState>? nestedKey(dynamic key) { | 1071 | + GetDelegate? nestedKey(dynamic key) { |
| 1076 | keys.putIfAbsent( | 1072 | keys.putIfAbsent( |
| 1077 | key, | 1073 | key, |
| 1078 | - () => GlobalKey<NavigatorState>( | ||
| 1079 | - debugLabel: 'Getx nested key: ${key.toString()}', | 1074 | + () => GetDelegate( |
| 1075 | + //debugLabel: 'Getx nested key: ${key.toString()}', | ||
| 1076 | + pages: [], | ||
| 1080 | ), | 1077 | ), |
| 1081 | ); | 1078 | ); |
| 1082 | return keys[key]; | 1079 | return keys[key]; |
| 1083 | } | 1080 | } |
| 1084 | 1081 | ||
| 1085 | - GlobalKey<NavigatorState> global(int? k) { | ||
| 1086 | - GlobalKey<NavigatorState> _key; | 1082 | + GetDelegate searchDelegate(int? k) { |
| 1083 | + GetDelegate _key; | ||
| 1087 | if (k == null) { | 1084 | if (k == null) { |
| 1088 | - _key = key; | 1085 | + _key = Get.rootController.rootDelegate; |
| 1086 | + print(_key.navigatorKey); | ||
| 1089 | } else { | 1087 | } else { |
| 1090 | if (!keys.containsKey(k)) { | 1088 | if (!keys.containsKey(k)) { |
| 1091 | throw 'Route id ($k) not found'; | 1089 | throw 'Route id ($k) not found'; |
| @@ -1093,15 +1091,15 @@ you can only use widgets and widget functions here'''; | @@ -1093,15 +1091,15 @@ you can only use widgets and widget functions here'''; | ||
| 1093 | _key = keys[k]!; | 1091 | _key = keys[k]!; |
| 1094 | } | 1092 | } |
| 1095 | 1093 | ||
| 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 | - } | 1094 | + // if (_key.listenersLength == 0 && !testMode) { |
| 1095 | + // throw """You are trying to use contextless navigation without | ||
| 1096 | + // a GetMaterialApp or Get.key. | ||
| 1097 | + // If you are testing your app, you can use: | ||
| 1098 | + // [Get.testMode = true], or if you are running your app on | ||
| 1099 | + // a physical device or emulator, you must exchange your [MaterialApp] | ||
| 1100 | + // for a [GetMaterialApp]. | ||
| 1101 | + // """; | ||
| 1102 | + // } | ||
| 1105 | 1103 | ||
| 1106 | return _key; | 1104 | return _key; |
| 1107 | } | 1105 | } |
| @@ -1225,7 +1223,7 @@ you can only use widgets and widget functions here'''; | @@ -1225,7 +1223,7 @@ you can only use widgets and widget functions here'''; | ||
| 1225 | 1223 | ||
| 1226 | GlobalKey<NavigatorState> get key => _getxController.key; | 1224 | GlobalKey<NavigatorState> get key => _getxController.key; |
| 1227 | 1225 | ||
| 1228 | - Map<dynamic, GlobalKey<NavigatorState>> get keys => _getxController.keys; | 1226 | + Map<dynamic, GetDelegate> get keys => _getxController.keys; |
| 1229 | 1227 | ||
| 1230 | GetMaterialController get rootController => _getxController; | 1228 | GetMaterialController get rootController => _getxController; |
| 1231 | 1229 | ||
| @@ -1250,7 +1248,8 @@ you can only use widgets and widget functions here'''; | @@ -1250,7 +1248,8 @@ you can only use widgets and widget functions here'''; | ||
| 1250 | 1248 | ||
| 1251 | Routing get routing => _getxController.routing; | 1249 | Routing get routing => _getxController.routing; |
| 1252 | 1250 | ||
| 1253 | - Map<String, String?> get parameters => _getxController.parameters; | 1251 | + Map<String, String?> get parameters => |
| 1252 | + _getxController.rootDelegate.parameters; | ||
| 1254 | set parameters(Map<String, String?> newParameters) => | 1253 | set parameters(Map<String, String?> newParameters) => |
| 1255 | _getxController.parameters = newParameters; | 1254 | _getxController.parameters = newParameters; |
| 1256 | 1255 | ||
| @@ -1312,15 +1311,15 @@ extension NavTwoExt on GetInterface { | @@ -1312,15 +1311,15 @@ extension NavTwoExt on GetInterface { | ||
| 1312 | 1311 | ||
| 1313 | // static GetDelegate? _delegate; | 1312 | // static GetDelegate? _delegate; |
| 1314 | 1313 | ||
| 1315 | - GetDelegate get rootDelegate => createDelegate(); | ||
| 1316 | - | ||
| 1317 | GetDelegate createDelegate({ | 1314 | GetDelegate createDelegate({ |
| 1318 | GetPage<dynamic>? notFoundRoute, | 1315 | GetPage<dynamic>? notFoundRoute, |
| 1316 | + List<GetPage> pages = const [], | ||
| 1319 | List<NavigatorObserver>? navigatorObservers, | 1317 | List<NavigatorObserver>? navigatorObservers, |
| 1320 | TransitionDelegate<dynamic>? transitionDelegate, | 1318 | TransitionDelegate<dynamic>? transitionDelegate, |
| 1321 | PopMode backButtonPopMode = PopMode.History, | 1319 | PopMode backButtonPopMode = PopMode.History, |
| 1322 | PreventDuplicateHandlingMode preventDuplicateHandlingMode = | 1320 | PreventDuplicateHandlingMode preventDuplicateHandlingMode = |
| 1323 | PreventDuplicateHandlingMode.ReorderRoutes, | 1321 | PreventDuplicateHandlingMode.ReorderRoutes, |
| 1322 | + GlobalKey<NavigatorState>? navigatorKey, | ||
| 1324 | }) { | 1323 | }) { |
| 1325 | if (routerDelegate == null) { | 1324 | if (routerDelegate == null) { |
| 1326 | return routerDelegate = GetDelegate( | 1325 | return routerDelegate = GetDelegate( |
| @@ -1329,6 +1328,8 @@ extension NavTwoExt on GetInterface { | @@ -1329,6 +1328,8 @@ extension NavTwoExt on GetInterface { | ||
| 1329 | transitionDelegate: transitionDelegate, | 1328 | transitionDelegate: transitionDelegate, |
| 1330 | backButtonPopMode: backButtonPopMode, | 1329 | backButtonPopMode: backButtonPopMode, |
| 1331 | preventDuplicateHandlingMode: preventDuplicateHandlingMode, | 1330 | preventDuplicateHandlingMode: preventDuplicateHandlingMode, |
| 1331 | + pages: pages, | ||
| 1332 | + navigatorKey: navigatorKey, | ||
| 1332 | ); | 1333 | ); |
| 1333 | } else { | 1334 | } else { |
| 1334 | return routerDelegate as GetDelegate; | 1335 | return routerDelegate as GetDelegate; |
| 1 | -import 'package:flutter/foundation.dart'; | ||
| 2 | -import 'package:flutter/widgets.dart'; | ||
| 3 | - | ||
| 4 | -import '../../../get.dart'; | ||
| 5 | - | ||
| 6 | -class GetInformationParser extends RouteInformationParser<GetNavConfig> { | ||
| 7 | - final String initialRoute; | ||
| 8 | - | ||
| 9 | - GetInformationParser({ | ||
| 10 | - this.initialRoute = '/', | ||
| 11 | - }) { | ||
| 12 | - Get.log('GetInformationParser is created !'); | ||
| 13 | - } | ||
| 14 | - @override | ||
| 15 | - SynchronousFuture<GetNavConfig> parseRouteInformation( | ||
| 16 | - RouteInformation routeInformation, | ||
| 17 | - ) { | ||
| 18 | - var location = routeInformation.location; | ||
| 19 | - if (location == '/') { | ||
| 20 | - //check if there is a corresponding page | ||
| 21 | - //if not, relocate to initialRoute | ||
| 22 | - if (!Get.routeTree.routes.any((element) => element.name == '/')) { | ||
| 23 | - location = initialRoute; | ||
| 24 | - } | ||
| 25 | - } | ||
| 26 | - | ||
| 27 | - Get.log('GetInformationParser: route location: $location'); | ||
| 28 | - | ||
| 29 | - final matchResult = Get.routeTree.matchRoute(location ?? initialRoute); | ||
| 30 | - | ||
| 31 | - return SynchronousFuture( | ||
| 32 | - GetNavConfig( | ||
| 33 | - currentTreeBranch: matchResult.currentTreeBranch, | ||
| 34 | - location: location, | ||
| 35 | - state: routeInformation.state, | ||
| 36 | - ), | ||
| 37 | - ); | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | - @override | ||
| 41 | - RouteInformation restoreRouteInformation(GetNavConfig config) { | ||
| 42 | - return RouteInformation( | ||
| 43 | - location: config.location, | ||
| 44 | - state: config.state, | ||
| 45 | - ); | ||
| 46 | - } | ||
| 47 | -} |
| 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.currentTreeBranch.isEmpty) return null; | ||
| 50 | - return GetNavConfig( | ||
| 51 | - currentTreeBranch: res.currentTreeBranch, | ||
| 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 | - PageSettings? 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.currentTreeBranch, | ||
| 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 | - PageSettings? 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 | -} |
| 1 | -import 'dart:async'; | ||
| 2 | - | ||
| 3 | -import 'package:flutter/material.dart'; | ||
| 4 | - | ||
| 5 | -import '../../../../get_state_manager/src/simple/get_state.dart'; | ||
| 6 | -import '../../../../get_state_manager/src/simple/list_notifier.dart'; | ||
| 7 | -import '../../../../get_utils/src/platform/platform.dart'; | ||
| 8 | -import '../../../../route_manager.dart'; | ||
| 9 | -import '../../root/parse_route.dart'; | ||
| 10 | -import '../url_strategy/url_strategy.dart'; | ||
| 11 | - | ||
| 12 | -class GetNavigation extends RouterDelegate<RouteDecoder> | ||
| 13 | - with | ||
| 14 | - ListNotifierSingleMixin, | ||
| 15 | - PopNavigatorRouterDelegateMixin<RouteDecoder>, | ||
| 16 | - IGetNavigation { | ||
| 17 | - final _activePages = <RouteDecoder>[]; | ||
| 18 | - final GetPage _unknownPage; | ||
| 19 | - final List<NavigatorObserver>? navigatorObservers; | ||
| 20 | - final String? restorationScopeId; | ||
| 21 | - @override | ||
| 22 | - final navigatorKey = GlobalKey<NavigatorState>(); | ||
| 23 | - | ||
| 24 | - static late final GetNavigation instance; | ||
| 25 | - | ||
| 26 | - @override | ||
| 27 | - Future<void> setInitialRoutePath(RouteDecoder configuration) async { | ||
| 28 | - setNewRoutePath(configuration); | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - GetNavigation({ | ||
| 32 | - String? initialPage, | ||
| 33 | - required List<GetPage> pages, | ||
| 34 | - GetPage? unknownPage, | ||
| 35 | - this.navigatorObservers, | ||
| 36 | - this.restorationScopeId, | ||
| 37 | - bool showHashOnUrl = false, | ||
| 38 | - }) : _unknownPage = unknownPage ?? | ||
| 39 | - GetPage( | ||
| 40 | - name: '/404', | ||
| 41 | - page: () => | ||
| 42 | - Scaffold(body: Center(child: Text('Route not found'))), | ||
| 43 | - ) { | ||
| 44 | - if (!showHashOnUrl && GetPlatform.isWeb) setUrlStrategy(); | ||
| 45 | - Get.addPages(pages); | ||
| 46 | - Get.addPage(_unknownPage); | ||
| 47 | - // setNewRoutePath(_buildPageSettings(_initialPage)); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - PageSettings _buildPageSettings(String page, [Object? data]) { | ||
| 51 | - var uri = Uri.parse(page); | ||
| 52 | - return PageSettings(uri, data); | ||
| 53 | - } | ||
| 54 | - | ||
| 55 | - @protected | ||
| 56 | - RouteDecoder? _getRouteDecoder<T>(PageSettings arguments) { | ||
| 57 | - var page = arguments.uri.path; | ||
| 58 | - final parameters = arguments.params; | ||
| 59 | - if (parameters.isNotEmpty) { | ||
| 60 | - final uri = Uri(path: page, queryParameters: parameters); | ||
| 61 | - page = uri.toString(); | ||
| 62 | - } | ||
| 63 | - | ||
| 64 | - final decoder = Get.routeTree.matchRoute(page, arguments: arguments); | ||
| 65 | - final route = decoder.route; | ||
| 66 | - if (route == null) return null; | ||
| 67 | - return _configureRouterDecoder(decoder, arguments); | ||
| 68 | - // decoder.replaceArguments(arguments); | ||
| 69 | - //decoder.replaceParameters(arguments) | ||
| 70 | - | ||
| 71 | - // return decoder; | ||
| 72 | - } | ||
| 73 | - | ||
| 74 | - @protected | ||
| 75 | - RouteDecoder _configureRouterDecoder<T>( | ||
| 76 | - RouteDecoder decoder, PageSettings arguments) { | ||
| 77 | - // final decoder = Get.routeTree.matchRoute(page.name, arguments: arguments); | ||
| 78 | - | ||
| 79 | - decoder.route = decoder.route?.copy( | ||
| 80 | - completer: _activePages.isEmpty ? null : Completer(), | ||
| 81 | - arguments: arguments, | ||
| 82 | - parameters: arguments.params, | ||
| 83 | - ); | ||
| 84 | - return decoder; | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - Future<T?> _push<T>(RouteDecoder activePage) async { | ||
| 88 | - // final activePage = _configureRouterDecoder<T>(page, arguments); | ||
| 89 | - final onStackPage = _activePages.firstWhereOrNull( | ||
| 90 | - (element) => element.route?.key == activePage.route?.key); | ||
| 91 | - | ||
| 92 | - /// There are no duplicate routes in the stack | ||
| 93 | - if (onStackPage == null) { | ||
| 94 | - _activePages.add(activePage); | ||
| 95 | - } else { | ||
| 96 | - /// There are duplicate routes, reorder | ||
| 97 | - _activePages.remove(onStackPage); | ||
| 98 | - _activePages.add(onStackPage); | ||
| 99 | - } | ||
| 100 | - refresh(); | ||
| 101 | - return activePage.route?.completer?.future as Future<T?>?; | ||
| 102 | - } | ||
| 103 | - | ||
| 104 | - Future<T?> _replace<T>(PageSettings arguments, GetPage<T> page) async { | ||
| 105 | - final index = _activePages.length > 1 ? _activePages.length - 1 : 0; | ||
| 106 | - Get.addPage(page); | ||
| 107 | - | ||
| 108 | - final route = _getRouteDecoder(arguments); | ||
| 109 | - | ||
| 110 | - final activePage = _configureRouterDecoder<T>(route!, arguments); | ||
| 111 | - | ||
| 112 | - _activePages[index] = activePage; | ||
| 113 | - | ||
| 114 | - refresh(); | ||
| 115 | - final result = await activePage.route?.completer?.future as Future<T?>; | ||
| 116 | - Get.removePage(page); | ||
| 117 | - | ||
| 118 | - return result; | ||
| 119 | - } | ||
| 120 | - | ||
| 121 | - Future<T?> _replaceNamed<T>(RouteDecoder activePage) async { | ||
| 122 | - final index = _activePages.length > 1 ? _activePages.length - 1 : 0; | ||
| 123 | - // final activePage = _configureRouterDecoder<T>(page, arguments); | ||
| 124 | - _activePages[index] = activePage; | ||
| 125 | - | ||
| 126 | - refresh(); | ||
| 127 | - final result = await activePage.route?.completer?.future as Future<T?>; | ||
| 128 | - return result; | ||
| 129 | - } | ||
| 130 | - | ||
| 131 | - /// Takes a route [name] String generated by [to], [off], [offAll] | ||
| 132 | - /// (and similar context navigation methods), cleans the extra chars and | ||
| 133 | - /// accommodates the format. | ||
| 134 | - /// TODO: check for a more "appealing" URL naming convention. | ||
| 135 | - /// `() => MyHomeScreenView` becomes `/my-home-screen-view`. | ||
| 136 | - String _cleanRouteName(String name) { | ||
| 137 | - name = name.replaceAll('() => ', ''); | ||
| 138 | - | ||
| 139 | - /// uncommonent for URL styling. | ||
| 140 | - // name = name.paramCase!; | ||
| 141 | - if (!name.startsWith('/')) { | ||
| 142 | - name = '/$name'; | ||
| 143 | - } | ||
| 144 | - return Uri.tryParse(name)?.toString() ?? name; | ||
| 145 | - } | ||
| 146 | - | ||
| 147 | - @protected | ||
| 148 | - void _popWithResult<T>([T? result]) { | ||
| 149 | - final completer = _activePages.removeLast().route?.completer; | ||
| 150 | - if (completer?.isCompleted == false) completer!.complete(result); | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - @override | ||
| 154 | - Future<T?> toNamed<T>(String page, [Object? data]) async { | ||
| 155 | - final arguments = _buildPageSettings(page, data); | ||
| 156 | - final route = _getRouteDecoder<T>(arguments); | ||
| 157 | - if (route != null) { | ||
| 158 | - return _push<T>(route); | ||
| 159 | - } | ||
| 160 | - throw 'Route $page not registered'; | ||
| 161 | - } | ||
| 162 | - | ||
| 163 | - @override | ||
| 164 | - Future<T?> to<T>( | ||
| 165 | - Widget Function() page, { | ||
| 166 | - bool? opaque, | ||
| 167 | - Transition? transition, | ||
| 168 | - Curve? curve, | ||
| 169 | - Duration? duration, | ||
| 170 | - int? id, | ||
| 171 | - String? routeName, | ||
| 172 | - bool fullscreenDialog = false, | ||
| 173 | - dynamic arguments, | ||
| 174 | - Binding? binding, | ||
| 175 | - bool preventDuplicates = true, | ||
| 176 | - bool? popGesture, | ||
| 177 | - bool showCupertinoParallax = true, | ||
| 178 | - double Function(BuildContext context)? gestureWidth, | ||
| 179 | - }) async { | ||
| 180 | - routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 181 | - final getPage = GetPage<T>( | ||
| 182 | - name: routeName, | ||
| 183 | - opaque: opaque ?? true, | ||
| 184 | - page: page, | ||
| 185 | - gestureWidth: gestureWidth, | ||
| 186 | - showCupertinoParallax: showCupertinoParallax, | ||
| 187 | - popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 188 | - transition: transition ?? Get.defaultTransition, | ||
| 189 | - curve: curve ?? Get.defaultTransitionCurve, | ||
| 190 | - fullscreenDialog: fullscreenDialog, | ||
| 191 | - binding: binding, | ||
| 192 | - transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 193 | - ); | ||
| 194 | - Get.addPage(getPage); | ||
| 195 | - final args = _buildPageSettings(routeName, arguments); | ||
| 196 | - final route = _getRouteDecoder<T>(args); | ||
| 197 | - final result = await _push<T>(route!); | ||
| 198 | - Get.removePage(getPage); | ||
| 199 | - return result; | ||
| 200 | - } | ||
| 201 | - | ||
| 202 | - @override | ||
| 203 | - Future<T?> off<T>( | ||
| 204 | - Widget Function() page, { | ||
| 205 | - bool? opaque, | ||
| 206 | - Transition? transition, | ||
| 207 | - Curve? curve, | ||
| 208 | - Duration? duration, | ||
| 209 | - int? id, | ||
| 210 | - String? routeName, | ||
| 211 | - bool fullscreenDialog = false, | ||
| 212 | - dynamic arguments, | ||
| 213 | - Binding? binding, | ||
| 214 | - bool preventDuplicates = true, | ||
| 215 | - bool? popGesture, | ||
| 216 | - bool showCupertinoParallax = true, | ||
| 217 | - double Function(BuildContext context)? gestureWidth, | ||
| 218 | - }) async { | ||
| 219 | - routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 220 | - final route = GetPage<T>( | ||
| 221 | - name: routeName, | ||
| 222 | - opaque: opaque ?? true, | ||
| 223 | - page: page, | ||
| 224 | - gestureWidth: gestureWidth, | ||
| 225 | - showCupertinoParallax: showCupertinoParallax, | ||
| 226 | - popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 227 | - transition: transition ?? Get.defaultTransition, | ||
| 228 | - curve: curve ?? Get.defaultTransitionCurve, | ||
| 229 | - fullscreenDialog: fullscreenDialog, | ||
| 230 | - binding: binding, | ||
| 231 | - transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 232 | - ); | ||
| 233 | - | ||
| 234 | - final args = _buildPageSettings(routeName, arguments); | ||
| 235 | - return _replace(args, route); | ||
| 236 | - } | ||
| 237 | - | ||
| 238 | - @override | ||
| 239 | - Future<T?>? offAll<T>( | ||
| 240 | - Widget Function() page, { | ||
| 241 | - bool Function(GetPage route)? predicate, | ||
| 242 | - bool opaque = true, | ||
| 243 | - bool? popGesture, | ||
| 244 | - int? id, | ||
| 245 | - String? routeName, | ||
| 246 | - dynamic arguments, | ||
| 247 | - Binding? binding, | ||
| 248 | - bool fullscreenDialog = false, | ||
| 249 | - Transition? transition, | ||
| 250 | - Curve? curve, | ||
| 251 | - Duration? duration, | ||
| 252 | - bool showCupertinoParallax = true, | ||
| 253 | - double Function(BuildContext context)? gestureWidth, | ||
| 254 | - }) async { | ||
| 255 | - routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 256 | - final route = GetPage<T>( | ||
| 257 | - name: routeName, | ||
| 258 | - opaque: opaque, | ||
| 259 | - page: page, | ||
| 260 | - gestureWidth: gestureWidth, | ||
| 261 | - showCupertinoParallax: showCupertinoParallax, | ||
| 262 | - popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 263 | - transition: transition ?? Get.defaultTransition, | ||
| 264 | - curve: curve ?? Get.defaultTransitionCurve, | ||
| 265 | - fullscreenDialog: fullscreenDialog, | ||
| 266 | - binding: binding, | ||
| 267 | - transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 268 | - ); | ||
| 269 | - | ||
| 270 | - final args = _buildPageSettings(routeName, arguments); | ||
| 271 | - | ||
| 272 | - final newPredicate = predicate ?? (route) => false; | ||
| 273 | - | ||
| 274 | - while (_activePages.length > 1 && !newPredicate(_activePages.last.route!)) { | ||
| 275 | - _popWithResult(); | ||
| 276 | - } | ||
| 277 | - | ||
| 278 | - return _replace(args, route); | ||
| 279 | - } | ||
| 280 | - | ||
| 281 | - @override | ||
| 282 | - Future<T?>? offAllNamed<T>( | ||
| 283 | - String page, { | ||
| 284 | - bool Function(GetPage route)? predicate, | ||
| 285 | - dynamic arguments, | ||
| 286 | - int? id, | ||
| 287 | - Map<String, String>? parameters, | ||
| 288 | - }) async { | ||
| 289 | - final args = _buildPageSettings(page, arguments); | ||
| 290 | - final route = _getRouteDecoder<T>(args); | ||
| 291 | - if (route == null) return null; | ||
| 292 | - | ||
| 293 | - // final newPredicate = predicate ?? (route) => false; | ||
| 294 | - | ||
| 295 | - while (_activePages.length > 1) { | ||
| 296 | - _activePages.removeLast(); | ||
| 297 | - } | ||
| 298 | - | ||
| 299 | - return _replaceNamed(route); | ||
| 300 | - } | ||
| 301 | - | ||
| 302 | - @override | ||
| 303 | - Future<T?> offNamed<T>(String page, [Object? data]) async { | ||
| 304 | - final arguments = _buildPageSettings(page, data); | ||
| 305 | - final route = _getRouteDecoder<T>(arguments); | ||
| 306 | - if (route == null) return null; | ||
| 307 | - _popWithResult(); | ||
| 308 | - return _push<T>(route); | ||
| 309 | - } | ||
| 310 | - | ||
| 311 | - @override | ||
| 312 | - Future<T?> toAndOffUntil<T>( | ||
| 313 | - String page, | ||
| 314 | - bool Function(GetPage) predicate, [ | ||
| 315 | - Object? data, | ||
| 316 | - ]) async { | ||
| 317 | - final arguments = _buildPageSettings(page, data); | ||
| 318 | - | ||
| 319 | - final route = _getRouteDecoder<T>(arguments); | ||
| 320 | - | ||
| 321 | - if (route == null) return null; | ||
| 322 | - | ||
| 323 | - while (_activePages.isNotEmpty && !predicate(_activePages.last.route!)) { | ||
| 324 | - _popWithResult(); | ||
| 325 | - } | ||
| 326 | - | ||
| 327 | - return _push<T>(route); | ||
| 328 | - } | ||
| 329 | - | ||
| 330 | - @override | ||
| 331 | - void back<T>([T? result]) { | ||
| 332 | - _checkIfCanBack(); | ||
| 333 | - _popWithResult<T>(result); | ||
| 334 | - refresh(); | ||
| 335 | - } | ||
| 336 | - | ||
| 337 | - void _checkIfCanBack() { | ||
| 338 | - assert(() { | ||
| 339 | - if (!canBack) { | ||
| 340 | - final last = _activePages.last; | ||
| 341 | - final name = last.route?.name; | ||
| 342 | - throw 'The page $name cannot be popped'; | ||
| 343 | - } | ||
| 344 | - return true; | ||
| 345 | - }()); | ||
| 346 | - } | ||
| 347 | - | ||
| 348 | - @override | ||
| 349 | - Future<R?> backAndtoNamed<T, R>(String page, | ||
| 350 | - {T? result, Object? data}) async { | ||
| 351 | - final arguments = _buildPageSettings(page, data); | ||
| 352 | - final route = _getRouteDecoder<R>(arguments); | ||
| 353 | - if (route == null) return null; | ||
| 354 | - _popWithResult<T>(result); | ||
| 355 | - return _push<R>(route); | ||
| 356 | - } | ||
| 357 | - | ||
| 358 | - @override | ||
| 359 | - void backUntil(bool Function(GetPage) predicate) { | ||
| 360 | - while (canBack && !predicate(_activePages.last.route!)) { | ||
| 361 | - _popWithResult(); | ||
| 362 | - } | ||
| 363 | - | ||
| 364 | - refresh(); | ||
| 365 | - } | ||
| 366 | - | ||
| 367 | - @override | ||
| 368 | - void goToUnknownPage([bool clearPages = false]) { | ||
| 369 | - if (clearPages) _activePages.clear(); | ||
| 370 | - | ||
| 371 | - final pageSettings = _buildPageSettings(_unknownPage.name); | ||
| 372 | - final routeDecoder = _getRouteDecoder(pageSettings); | ||
| 373 | - | ||
| 374 | - _push(routeDecoder!); | ||
| 375 | - } | ||
| 376 | - | ||
| 377 | - @override | ||
| 378 | - bool get canBack => _activePages.length > 1; | ||
| 379 | - | ||
| 380 | - bool _onPopPage(Route route, result) { | ||
| 381 | - if (!route.didPop(result)) return false; | ||
| 382 | - _popWithResult(result); | ||
| 383 | - refresh(); | ||
| 384 | - return true; | ||
| 385 | - } | ||
| 386 | - | ||
| 387 | - @override | ||
| 388 | - Widget build(BuildContext context) { | ||
| 389 | - if (_activePages.isEmpty) return SizedBox.shrink(); | ||
| 390 | - return GetNavigator( | ||
| 391 | - key: navigatorKey, | ||
| 392 | - restorationScopeId: restorationScopeId, | ||
| 393 | - observers: navigatorObservers, | ||
| 394 | - pages: _activePages.map((decoder) => decoder.route!).toList(), | ||
| 395 | - onPopPage: _onPopPage, | ||
| 396 | - ); | ||
| 397 | - } | ||
| 398 | - | ||
| 399 | - @override | ||
| 400 | - Future<void> setNewRoutePath(RouteDecoder configuration) async { | ||
| 401 | - // if (_activePages.isEmpty) return; | ||
| 402 | - final page = configuration.route; | ||
| 403 | - if (page == null) { | ||
| 404 | - goToUnknownPage(); | ||
| 405 | - return; | ||
| 406 | - } else { | ||
| 407 | - _push(configuration); | ||
| 408 | - } | ||
| 409 | - } | ||
| 410 | - | ||
| 411 | - @override | ||
| 412 | - RouteDecoder? get currentConfiguration { | ||
| 413 | - if (_activePages.isEmpty) { | ||
| 414 | - return null; | ||
| 415 | - } | ||
| 416 | - return _activePages.last; | ||
| 417 | - } | ||
| 418 | -} |
| @@ -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, |
| @@ -114,12 +114,37 @@ class GetCupertinoApp extends StatelessWidget { | @@ -114,12 +114,37 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 114 | this.highContrastTheme, | 114 | this.highContrastTheme, |
| 115 | this.highContrastDarkTheme, | 115 | this.highContrastDarkTheme, |
| 116 | this.actions, | 116 | this.actions, |
| 117 | - }) : routeInformationProvider = null, | ||
| 118 | - routeInformationParser = null, | ||
| 119 | - routerDelegate = null, | 117 | + }) : routerDelegate = Get.createDelegate( |
| 118 | + pages: getPages ?? | ||
| 119 | + [ | ||
| 120 | + GetPage( | ||
| 121 | + name: _cleanRouteName("/${home.runtimeType}"), | ||
| 122 | + page: () => home!, | ||
| 123 | + ), | ||
| 124 | + ], | ||
| 125 | + notFoundRoute: unknownRoute, | ||
| 126 | + navigatorKey: navigatorKey, | ||
| 127 | + ), | ||
| 128 | + routeInformationParser = Get.createInformationParser( | ||
| 129 | + initialRoute: initialRoute ?? | ||
| 130 | + getPages?.first.name ?? | ||
| 131 | + _cleanRouteName("/${home.runtimeType}"), | ||
| 132 | + ), | ||
| 133 | + routeInformationProvider = null, | ||
| 120 | backButtonDispatcher = null, | 134 | backButtonDispatcher = null, |
| 121 | super(key: key); | 135 | super(key: key); |
| 122 | 136 | ||
| 137 | + static String _cleanRouteName(String name) { | ||
| 138 | + name = name.replaceAll('() => ', ''); | ||
| 139 | + | ||
| 140 | + /// uncommonent for URL styling. | ||
| 141 | + // name = name.paramCase!; | ||
| 142 | + if (!name.startsWith('/')) { | ||
| 143 | + name = '/$name'; | ||
| 144 | + } | ||
| 145 | + return Uri.tryParse(name)?.toString() ?? name; | ||
| 146 | + } | ||
| 147 | + | ||
| 123 | GetCupertinoApp.router({ | 148 | GetCupertinoApp.router({ |
| 124 | Key? key, | 149 | Key? key, |
| 125 | this.theme, | 150 | this.theme, |
| @@ -167,6 +192,7 @@ class GetCupertinoApp extends StatelessWidget { | @@ -167,6 +192,7 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 167 | this.getPages, | 192 | this.getPages, |
| 168 | this.unknownRoute, | 193 | this.unknownRoute, |
| 169 | }) : routerDelegate = routerDelegate ??= Get.createDelegate( | 194 | }) : routerDelegate = routerDelegate ??= Get.createDelegate( |
| 195 | + pages: getPages ?? [], | ||
| 170 | notFoundRoute: unknownRoute, | 196 | notFoundRoute: unknownRoute, |
| 171 | ), | 197 | ), |
| 172 | routeInformationParser = | 198 | routeInformationParser = |
| @@ -7,6 +7,64 @@ import '../../../get_state_manager/get_state_manager.dart'; | @@ -7,6 +7,64 @@ import '../../../get_state_manager/get_state_manager.dart'; | ||
| 7 | import '../../../get_utils/get_utils.dart'; | 7 | import '../../../get_utils/get_utils.dart'; |
| 8 | import '../../get_navigation.dart'; | 8 | import '../../get_navigation.dart'; |
| 9 | 9 | ||
| 10 | +// extension GetMaterialExt on MaterialApp{ | ||
| 11 | +// MaterialApp get(){ | ||
| 12 | +// final app = MaterialApp.router( | ||
| 13 | +// key: key, | ||
| 14 | +// routeInformationProvider:routeInformationProvider, | ||
| 15 | +// scaffoldMessengerKey:scaffoldMessengerKey, | ||
| 16 | +// // RouteInformationParser<Object>? routeInformationParser, | ||
| 17 | +// // RouterDelegate<Object>? routerDelegate, | ||
| 18 | +// backButtonDispatcher:backButtonDispatcher, | ||
| 19 | +// builder:builder, | ||
| 20 | +// title:title, | ||
| 21 | +// onGenerateTitle:onGenerateTitle, | ||
| 22 | +// color:color, | ||
| 23 | +// theme:theme, | ||
| 24 | +// darkTheme:darkTheme, | ||
| 25 | +// useInheritedMediaQuery:useInheritedMediaQuery, | ||
| 26 | +// highContrastTheme:highContrastTheme, | ||
| 27 | +// highContrastDarkTheme:highContrastDarkTheme, | ||
| 28 | +// themeMode :themeMode, | ||
| 29 | +// locale:locale, | ||
| 30 | +// localizationsDelegates:localizationsDelegates, | ||
| 31 | +// localeListResolutionCallback: localeListResolutionCallback, | ||
| 32 | +// localeResolutionCallback: localeResolutionCallback, | ||
| 33 | +// supportedLocales: supportedLocales, | ||
| 34 | +// debugShowMaterialGrid :debugShowMaterialGrid, | ||
| 35 | +// showPerformanceOverlay :showPerformanceOverlay, | ||
| 36 | +// checkerboardRasterCacheImages :checkerboardRasterCacheImages, | ||
| 37 | +// checkerboardOffscreenLayers :checkerboardOffscreenLayers, | ||
| 38 | +// showSemanticsDebugger :showSemanticsDebugger, | ||
| 39 | +// debugShowCheckedModeBanner :debugShowCheckedModeBanner, | ||
| 40 | +// shortcuts: shortcuts, | ||
| 41 | +// scrollBehavior:scrollBehavior, | ||
| 42 | +// actions:actions, | ||
| 43 | +// customTransition:customTransition, | ||
| 44 | +// translationsKeys:translationsKeys, | ||
| 45 | +// translations:translations, | ||
| 46 | +// textDirection:textDirection, | ||
| 47 | +// fallbackLocale:fallbackLocale, | ||
| 48 | +// routingCallback:routingCallback, | ||
| 49 | +// defaultTransition:defaultTransition, | ||
| 50 | +// opaqueRoute:opaqueRoute, | ||
| 51 | +// onInit:onInit, | ||
| 52 | +// onReady:onReady, | ||
| 53 | +// onDispose:onDispose, | ||
| 54 | +// enableLog:enableLog, | ||
| 55 | +// logWriterCallback:logWriterCallback, | ||
| 56 | +// popGesture:popGesture, | ||
| 57 | +// smartManagement:smartManagement | ||
| 58 | +// initialBinding:initialBinding, | ||
| 59 | +// transitionDuration:transitionDuration, | ||
| 60 | +// defaultGlobalState:defaultGlobalState, | ||
| 61 | +// getPages:getPages, | ||
| 62 | +// navigatorObservers: navigatorObservers, | ||
| 63 | +// unknownRoute:unknownRoute, | ||
| 64 | +// ); | ||
| 65 | +// } | ||
| 66 | +// } | ||
| 67 | + | ||
| 10 | class GetMaterialApp extends StatelessWidget { | 68 | class GetMaterialApp extends StatelessWidget { |
| 11 | final GlobalKey<NavigatorState>? navigatorKey; | 69 | final GlobalKey<NavigatorState>? navigatorKey; |
| 12 | 70 | ||
| @@ -66,7 +124,7 @@ class GetMaterialApp extends StatelessWidget { | @@ -66,7 +124,7 @@ class GetMaterialApp extends StatelessWidget { | ||
| 66 | final RouterDelegate<Object>? routerDelegate; | 124 | final RouterDelegate<Object>? routerDelegate; |
| 67 | final BackButtonDispatcher? backButtonDispatcher; | 125 | final BackButtonDispatcher? backButtonDispatcher; |
| 68 | final bool useInheritedMediaQuery; | 126 | final bool useInheritedMediaQuery; |
| 69 | - const GetMaterialApp({ | 127 | + GetMaterialApp({ |
| 70 | Key? key, | 128 | Key? key, |
| 71 | this.navigatorKey, | 129 | this.navigatorKey, |
| 72 | this.scaffoldMessengerKey, | 130 | this.scaffoldMessengerKey, |
| @@ -123,12 +181,37 @@ class GetMaterialApp extends StatelessWidget { | @@ -123,12 +181,37 @@ class GetMaterialApp extends StatelessWidget { | ||
| 123 | this.highContrastTheme, | 181 | this.highContrastTheme, |
| 124 | this.highContrastDarkTheme, | 182 | this.highContrastDarkTheme, |
| 125 | this.actions, | 183 | this.actions, |
| 126 | - }) : routeInformationProvider = null, | ||
| 127 | - routeInformationParser = null, | ||
| 128 | - routerDelegate = null, | 184 | + }) : routerDelegate = Get.createDelegate( |
| 185 | + pages: getPages ?? | ||
| 186 | + [ | ||
| 187 | + GetPage( | ||
| 188 | + name: _cleanRouteName("/${home.runtimeType}"), | ||
| 189 | + page: () => home!, | ||
| 190 | + ), | ||
| 191 | + ], | ||
| 192 | + notFoundRoute: unknownRoute, | ||
| 193 | + navigatorKey: navigatorKey, | ||
| 194 | + ), | ||
| 195 | + routeInformationParser = Get.createInformationParser( | ||
| 196 | + initialRoute: initialRoute ?? | ||
| 197 | + getPages?.first.name ?? | ||
| 198 | + _cleanRouteName("/${home.runtimeType}"), | ||
| 199 | + ), | ||
| 200 | + routeInformationProvider = null, | ||
| 129 | backButtonDispatcher = null, | 201 | backButtonDispatcher = null, |
| 130 | super(key: key); | 202 | super(key: key); |
| 131 | 203 | ||
| 204 | + static String _cleanRouteName(String name) { | ||
| 205 | + name = name.replaceAll('() => ', ''); | ||
| 206 | + | ||
| 207 | + /// uncommonent for URL styling. | ||
| 208 | + // name = name.paramCase!; | ||
| 209 | + if (!name.startsWith('/')) { | ||
| 210 | + name = '/$name'; | ||
| 211 | + } | ||
| 212 | + return Uri.tryParse(name)?.toString() ?? name; | ||
| 213 | + } | ||
| 214 | + | ||
| 132 | GetMaterialApp.router({ | 215 | GetMaterialApp.router({ |
| 133 | Key? key, | 216 | Key? key, |
| 134 | this.routeInformationProvider, | 217 | this.routeInformationProvider, |
| @@ -182,13 +265,13 @@ class GetMaterialApp extends StatelessWidget { | @@ -182,13 +265,13 @@ class GetMaterialApp extends StatelessWidget { | ||
| 182 | this.navigatorObservers, | 265 | this.navigatorObservers, |
| 183 | this.unknownRoute, | 266 | this.unknownRoute, |
| 184 | }) : routerDelegate = routerDelegate ??= Get.createDelegate( | 267 | }) : routerDelegate = routerDelegate ??= Get.createDelegate( |
| 268 | + pages: getPages ?? [], | ||
| 185 | notFoundRoute: unknownRoute, | 269 | notFoundRoute: unknownRoute, |
| 186 | ), | 270 | ), |
| 187 | routeInformationParser = | 271 | routeInformationParser = |
| 188 | routeInformationParser ??= Get.createInformationParser( | 272 | routeInformationParser ??= Get.createInformationParser( |
| 189 | initialRoute: getPages?.first.name ?? '/', | 273 | initialRoute: getPages?.first.name ?? '/', |
| 190 | ), | 274 | ), |
| 191 | - //navigatorObservers = null, | ||
| 192 | navigatorKey = null, | 275 | navigatorKey = null, |
| 193 | onGenerateRoute = null, | 276 | onGenerateRoute = null, |
| 194 | home = null, | 277 | home = null, |
| @@ -28,14 +28,14 @@ class GetMaterialController extends SuperController { | @@ -28,14 +28,14 @@ class GetMaterialController extends SuperController { | ||
| 28 | 28 | ||
| 29 | CustomTransition? customTransition; | 29 | CustomTransition? customTransition; |
| 30 | 30 | ||
| 31 | - var _key = GlobalKey<NavigatorState>(debugLabel: 'Key Created by default'); | 31 | + Map<dynamic, GetDelegate> keys = {}; |
| 32 | 32 | ||
| 33 | - Map<dynamic, GlobalKey<NavigatorState>> keys = {}; | 33 | + GlobalKey<NavigatorState> get key => rootDelegate.navigatorKey; |
| 34 | 34 | ||
| 35 | - GlobalKey<NavigatorState> get key => _key; | 35 | + GetDelegate get rootDelegate => Get.createDelegate(); |
| 36 | 36 | ||
| 37 | GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) { | 37 | GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) { |
| 38 | - _key = newKey; | 38 | + rootDelegate.navigatorKey = newKey; |
| 39 | return key; | 39 | return key; |
| 40 | } | 40 | } |
| 41 | 41 |
| @@ -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 MaterialPageRoute<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 |
| @@ -67,7 +64,7 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T> | @@ -67,7 +64,7 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T> | ||
| 67 | }) : super( | 64 | }) : super( |
| 68 | settings: settings, | 65 | settings: settings, |
| 69 | fullscreenDialog: fullscreenDialog, | 66 | fullscreenDialog: fullscreenDialog, |
| 70 | - // builder: (context) => Container(), | 67 | + builder: (context) => Container(), |
| 71 | ); | 68 | ); |
| 72 | 69 | ||
| 73 | @override | 70 | @override |
| 1 | import 'package:flutter/foundation.dart'; | 1 | import 'package:flutter/foundation.dart'; |
| 2 | import 'package:flutter/widgets.dart'; | 2 | import 'package:flutter/widgets.dart'; |
| 3 | 3 | ||
| 4 | -import '../../../../get.dart'; | ||
| 5 | -import '../../root/parse_route.dart'; | 4 | +import '../../../get.dart'; |
| 5 | +import 'parse_route.dart'; | ||
| 6 | 6 | ||
| 7 | -class NewGetInformationParser extends RouteInformationParser<RouteDecoder> { | 7 | +class GetInformationParser extends RouteInformationParser<RouteDecoder> { |
| 8 | final String initialRoute; | 8 | final String initialRoute; |
| 9 | 9 | ||
| 10 | - NewGetInformationParser({ | 10 | + GetInformationParser({ |
| 11 | required this.initialRoute, | 11 | required this.initialRoute, |
| 12 | }) { | 12 | }) { |
| 13 | Get.log('GetInformationParser is created !'); | 13 | Get.log('GetInformationParser is created !'); |
| @@ -29,19 +29,7 @@ class NewGetInformationParser extends RouteInformationParser<RouteDecoder> { | @@ -29,19 +29,7 @@ class NewGetInformationParser extends RouteInformationParser<RouteDecoder> { | ||
| 29 | 29 | ||
| 30 | final routeName = location ?? initialRoute; | 30 | final routeName = location ?? initialRoute; |
| 31 | 31 | ||
| 32 | - return SynchronousFuture(_locationToRouteDecoder(routeName)); | ||
| 33 | - } | ||
| 34 | - | ||
| 35 | - RouteDecoder _locationToRouteDecoder(String location) { | ||
| 36 | - var uri = Uri.parse(location); | ||
| 37 | - final args = PageSettings(uri); | ||
| 38 | - final decoder = Get.routeTree.matchRoute(location, arguments: args); | ||
| 39 | - decoder.route = decoder.route?.copy( | ||
| 40 | - completer: null, | ||
| 41 | - arguments: args, | ||
| 42 | - parameters: args.params, | ||
| 43 | - ); | ||
| 44 | - return decoder; | 32 | + return SynchronousFuture(RouteDecoder.fromRoute(routeName)); |
| 45 | } | 33 | } |
| 46 | 34 | ||
| 47 | @override | 35 | @override |
| 1 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; |
| 2 | 2 | ||
| 3 | -import '../../../../get_state_manager/src/simple/get_state.dart'; | ||
| 4 | -import '../../routes/get_route.dart'; | ||
| 5 | -import '../../routes/transitions_type.dart'; | 3 | +import '../../../get_state_manager/src/simple/get_state.dart'; |
| 4 | +import '../routes/get_route.dart'; | ||
| 5 | +import '../routes/transitions_type.dart'; | ||
| 6 | 6 | ||
| 7 | mixin IGetNavigation { | 7 | mixin IGetNavigation { |
| 8 | Future<T?> to<T>( | 8 | Future<T?> to<T>( |
| @@ -56,31 +56,54 @@ mixin IGetNavigation { | @@ -56,31 +56,54 @@ mixin IGetNavigation { | ||
| 56 | double Function(BuildContext context)? gestureWidth, | 56 | double Function(BuildContext context)? gestureWidth, |
| 57 | }); | 57 | }); |
| 58 | 58 | ||
| 59 | - Future<T?> toNamed<T>(String page, [Object? data]); | 59 | + Future<T?> toNamed<T>( |
| 60 | + String page, { | ||
| 61 | + dynamic arguments, | ||
| 62 | + int? id, | ||
| 63 | + bool preventDuplicates = true, | ||
| 64 | + Map<String, String>? parameters, | ||
| 65 | + }); | ||
| 60 | 66 | ||
| 61 | - Future<T?> offNamed<T>(String page, [Object? data]); | 67 | + Future<T?> offNamed<T>( |
| 68 | + String page, { | ||
| 69 | + dynamic arguments, | ||
| 70 | + int? id, | ||
| 71 | + Map<String, String>? parameters, | ||
| 72 | + }); | ||
| 62 | 73 | ||
| 63 | Future<T?>? offAllNamed<T>( | 74 | Future<T?>? offAllNamed<T>( |
| 64 | String newRouteName, { | 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, { | ||
| 65 | bool Function(GetPage route)? predicate, | 84 | bool Function(GetPage route)? predicate, |
| 66 | dynamic arguments, | 85 | dynamic arguments, |
| 67 | int? id, | 86 | int? id, |
| 68 | Map<String, String>? parameters, | 87 | Map<String, String>? parameters, |
| 69 | }); | 88 | }); |
| 70 | 89 | ||
| 71 | - Future<T?> toAndOffUntil<T>( | 90 | + Future<T?> toNamedAndOffUntil<T>( |
| 72 | String page, | 91 | String page, |
| 73 | bool Function(GetPage) predicate, [ | 92 | bool Function(GetPage) predicate, [ |
| 74 | Object? data, | 93 | Object? data, |
| 75 | ]); | 94 | ]); |
| 76 | 95 | ||
| 96 | + Future<T?> offUntil<T>( | ||
| 97 | + Widget Function() page, | ||
| 98 | + bool Function(GetPage) predicate, [ | ||
| 99 | + Object? arguments, | ||
| 100 | + ]); | ||
| 101 | + | ||
| 77 | void back<T>([T? result]); | 102 | void back<T>([T? result]); |
| 78 | 103 | ||
| 79 | - Future<R?> backAndtoNamed<T, R>(String page, {T? result, Object? data}); | 104 | + Future<R?> backAndtoNamed<T, R>(String page, {T? result, Object? arguments}); |
| 80 | 105 | ||
| 81 | void backUntil(bool Function(GetPage) predicate); | 106 | void backUntil(bool Function(GetPage) predicate); |
| 82 | 107 | ||
| 83 | void goToUnknownPage([bool clearPages = true]); | 108 | void goToUnknownPage([bool clearPages = true]); |
| 84 | - | ||
| 85 | - bool get canBack; | ||
| 86 | } | 109 | } |
| @@ -45,6 +45,8 @@ class GetPage<T> extends Page<T> { | @@ -45,6 +45,8 @@ class GetPage<T> extends Page<T> { | ||
| 45 | final GetPage? unknownRoute; | 45 | final GetPage? unknownRoute; |
| 46 | final bool showCupertinoParallax; | 46 | final bool showCupertinoParallax; |
| 47 | 47 | ||
| 48 | + final PreventDuplicateHandlingMode preventDuplicateHandlingMode; | ||
| 49 | + | ||
| 48 | GetPage({ | 50 | GetPage({ |
| 49 | required this.name, | 51 | required this.name, |
| 50 | required this.page, | 52 | required this.page, |
| @@ -70,6 +72,8 @@ class GetPage<T> extends Page<T> { | @@ -70,6 +72,8 @@ class GetPage<T> extends Page<T> { | ||
| 70 | this.arguments, | 72 | this.arguments, |
| 71 | this.showCupertinoParallax = true, | 73 | this.showCupertinoParallax = true, |
| 72 | this.preventDuplicates = true, | 74 | this.preventDuplicates = true, |
| 75 | + this.preventDuplicateHandlingMode = | ||
| 76 | + PreventDuplicateHandlingMode.ReorderRoutes, | ||
| 73 | this.completer, | 77 | this.completer, |
| 74 | }) : path = _nameToRegex(name), | 78 | }) : path = _nameToRegex(name), |
| 75 | assert(name.startsWith('/'), | 79 | assert(name.startsWith('/'), |
| 1 | +import 'dart:async'; | ||
| 2 | + | ||
| 3 | +import 'package:flutter/foundation.dart'; | ||
| 4 | +import 'package:flutter/material.dart'; | ||
| 5 | + | ||
| 6 | +import '../../../get_state_manager/src/simple/get_state.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.redirectDelegate(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?.arguments?.arguments as T; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + Map<String, String> get parameters { | ||
| 148 | + return currentConfiguration?.arguments?.params ?? {}; | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + PageSettings? get pageSettings { | ||
| 152 | + return currentConfiguration?.arguments; | ||
| 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.arguments?.name == config.arguments?.name); | ||
| 163 | + if (originalEntryIndex >= 0) { | ||
| 164 | + switch (preventDuplicateHandlingMode) { | ||
| 165 | + case PreventDuplicateHandlingMode.PopUntilOriginalRoute: | ||
| 166 | + popModeUntil(config.arguments!.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.arguments?.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: [ | ||
| 305 | + GetObserver(), | ||
| 306 | + ...?navigatorObservers, | ||
| 307 | + ], | ||
| 308 | + transitionDelegate: | ||
| 309 | + transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(), | ||
| 310 | + ); | ||
| 311 | + } | ||
| 312 | + | ||
| 313 | + @override | ||
| 314 | + void goToUnknownPage([bool clearPages = false]) { | ||
| 315 | + if (clearPages) _activePages.clear(); | ||
| 316 | + | ||
| 317 | + final pageSettings = _buildPageSettings(notFoundRoute.name); | ||
| 318 | + final routeDecoder = _getRouteDecoder(pageSettings); | ||
| 319 | + | ||
| 320 | + _push(routeDecoder!); | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + @protected | ||
| 324 | + void _popWithResult<T>([T? result]) { | ||
| 325 | + final completer = _activePages.removeLast().route?.completer; | ||
| 326 | + if (completer?.isCompleted == false) completer!.complete(result); | ||
| 327 | + } | ||
| 328 | + | ||
| 329 | + @override | ||
| 330 | + Future<T?> toNamed<T>( | ||
| 331 | + String page, { | ||
| 332 | + dynamic arguments, | ||
| 333 | + int? id, | ||
| 334 | + bool preventDuplicates = true, | ||
| 335 | + Map<String, String>? parameters, | ||
| 336 | + }) async { | ||
| 337 | + final args = _buildPageSettings(page, arguments); | ||
| 338 | + final route = _getRouteDecoder<T>(args); | ||
| 339 | + if (route != null) { | ||
| 340 | + return _push<T>(route); | ||
| 341 | + } else { | ||
| 342 | + goToUnknownPage(); | ||
| 343 | + } | ||
| 344 | + } | ||
| 345 | + | ||
| 346 | + @override | ||
| 347 | + Future<T?> to<T>(Widget Function() page, | ||
| 348 | + {bool? opaque, | ||
| 349 | + Transition? transition, | ||
| 350 | + Curve? curve, | ||
| 351 | + Duration? duration, | ||
| 352 | + int? id, | ||
| 353 | + String? routeName, | ||
| 354 | + bool fullscreenDialog = false, | ||
| 355 | + dynamic arguments, | ||
| 356 | + Binding? binding, | ||
| 357 | + bool preventDuplicates = true, | ||
| 358 | + bool? popGesture, | ||
| 359 | + bool showCupertinoParallax = true, | ||
| 360 | + double Function(BuildContext context)? gestureWidth, | ||
| 361 | + bool rebuildStack = true, | ||
| 362 | + PreventDuplicateHandlingMode preventDuplicateHandlingMode = | ||
| 363 | + PreventDuplicateHandlingMode.ReorderRoutes}) async { | ||
| 364 | + routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 365 | + if (preventDuplicateHandlingMode == PreventDuplicateHandlingMode.Recreate) { | ||
| 366 | + routeName = routeName + page.hashCode.toString(); | ||
| 367 | + } | ||
| 368 | + | ||
| 369 | + final getPage = GetPage<T>( | ||
| 370 | + name: routeName, | ||
| 371 | + opaque: opaque ?? true, | ||
| 372 | + page: page, | ||
| 373 | + gestureWidth: gestureWidth, | ||
| 374 | + showCupertinoParallax: showCupertinoParallax, | ||
| 375 | + popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 376 | + transition: transition ?? Get.defaultTransition, | ||
| 377 | + curve: curve ?? Get.defaultTransitionCurve, | ||
| 378 | + fullscreenDialog: fullscreenDialog, | ||
| 379 | + binding: binding, | ||
| 380 | + transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 381 | + preventDuplicateHandlingMode: preventDuplicateHandlingMode, | ||
| 382 | + ); | ||
| 383 | + | ||
| 384 | + Get.addPage(getPage); | ||
| 385 | + final args = _buildPageSettings(routeName, arguments); | ||
| 386 | + final route = _getRouteDecoder<T>(args); | ||
| 387 | + final result = await _push<T>( | ||
| 388 | + route!, | ||
| 389 | + rebuildStack: rebuildStack, | ||
| 390 | + preventDuplicateHandlingMode: preventDuplicateHandlingMode, | ||
| 391 | + ); | ||
| 392 | + Get.removePage(getPage); | ||
| 393 | + return result; | ||
| 394 | + } | ||
| 395 | + | ||
| 396 | + @override | ||
| 397 | + Future<T?> off<T>( | ||
| 398 | + Widget Function() page, { | ||
| 399 | + bool? opaque, | ||
| 400 | + Transition? transition, | ||
| 401 | + Curve? curve, | ||
| 402 | + Duration? duration, | ||
| 403 | + int? id, | ||
| 404 | + String? routeName, | ||
| 405 | + bool fullscreenDialog = false, | ||
| 406 | + dynamic arguments, | ||
| 407 | + Binding? binding, | ||
| 408 | + bool preventDuplicates = true, | ||
| 409 | + bool? popGesture, | ||
| 410 | + bool showCupertinoParallax = true, | ||
| 411 | + double Function(BuildContext context)? gestureWidth, | ||
| 412 | + }) async { | ||
| 413 | + routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 414 | + final route = GetPage<T>( | ||
| 415 | + name: routeName, | ||
| 416 | + opaque: opaque ?? true, | ||
| 417 | + page: page, | ||
| 418 | + gestureWidth: gestureWidth, | ||
| 419 | + showCupertinoParallax: showCupertinoParallax, | ||
| 420 | + popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 421 | + transition: transition ?? Get.defaultTransition, | ||
| 422 | + curve: curve ?? Get.defaultTransitionCurve, | ||
| 423 | + fullscreenDialog: fullscreenDialog, | ||
| 424 | + binding: binding, | ||
| 425 | + transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 426 | + ); | ||
| 427 | + | ||
| 428 | + final args = _buildPageSettings(routeName, arguments); | ||
| 429 | + return _replace(args, route); | ||
| 430 | + } | ||
| 431 | + | ||
| 432 | + @override | ||
| 433 | + Future<T?>? offAll<T>( | ||
| 434 | + Widget Function() page, { | ||
| 435 | + bool Function(GetPage route)? predicate, | ||
| 436 | + bool opaque = true, | ||
| 437 | + bool? popGesture, | ||
| 438 | + int? id, | ||
| 439 | + String? routeName, | ||
| 440 | + dynamic arguments, | ||
| 441 | + Binding? binding, | ||
| 442 | + bool fullscreenDialog = false, | ||
| 443 | + Transition? transition, | ||
| 444 | + Curve? curve, | ||
| 445 | + Duration? duration, | ||
| 446 | + bool showCupertinoParallax = true, | ||
| 447 | + double Function(BuildContext context)? gestureWidth, | ||
| 448 | + }) async { | ||
| 449 | + routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 450 | + final route = GetPage<T>( | ||
| 451 | + name: routeName, | ||
| 452 | + opaque: opaque, | ||
| 453 | + page: page, | ||
| 454 | + gestureWidth: gestureWidth, | ||
| 455 | + showCupertinoParallax: showCupertinoParallax, | ||
| 456 | + popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 457 | + transition: transition ?? Get.defaultTransition, | ||
| 458 | + curve: curve ?? Get.defaultTransitionCurve, | ||
| 459 | + fullscreenDialog: fullscreenDialog, | ||
| 460 | + binding: binding, | ||
| 461 | + transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 462 | + ); | ||
| 463 | + | ||
| 464 | + final args = _buildPageSettings(routeName, arguments); | ||
| 465 | + | ||
| 466 | + final newPredicate = predicate ?? (route) => false; | ||
| 467 | + | ||
| 468 | + while (_activePages.length > 1 && !newPredicate(_activePages.last.route!)) { | ||
| 469 | + _popWithResult(); | ||
| 470 | + } | ||
| 471 | + | ||
| 472 | + return _replace(args, route); | ||
| 473 | + } | ||
| 474 | + | ||
| 475 | + @override | ||
| 476 | + Future<T?>? offAllNamed<T>( | ||
| 477 | + String page, { | ||
| 478 | + // bool Function(GetPage route)? predicate, | ||
| 479 | + dynamic arguments, | ||
| 480 | + int? id, | ||
| 481 | + Map<String, String>? parameters, | ||
| 482 | + }) async { | ||
| 483 | + final args = _buildPageSettings(page, arguments); | ||
| 484 | + final route = _getRouteDecoder<T>(args); | ||
| 485 | + if (route == null) return null; | ||
| 486 | + | ||
| 487 | + while (_activePages.length > 1) { | ||
| 488 | + _activePages.removeLast(); | ||
| 489 | + } | ||
| 490 | + | ||
| 491 | + return _replaceNamed(route); | ||
| 492 | + } | ||
| 493 | + | ||
| 494 | + @override | ||
| 495 | + Future<T?>? offNamedUntil<T>( | ||
| 496 | + String page, { | ||
| 497 | + bool Function(GetPage route)? predicate, | ||
| 498 | + dynamic arguments, | ||
| 499 | + int? id, | ||
| 500 | + Map<String, String>? parameters, | ||
| 501 | + }) async { | ||
| 502 | + final args = _buildPageSettings(page, arguments); | ||
| 503 | + final route = _getRouteDecoder<T>(args); | ||
| 504 | + if (route == null) return null; | ||
| 505 | + | ||
| 506 | + final newPredicate = predicate ?? (route) => false; | ||
| 507 | + | ||
| 508 | + while (_activePages.length > 1 && newPredicate(_activePages.last.route!)) { | ||
| 509 | + _activePages.removeLast(); | ||
| 510 | + } | ||
| 511 | + | ||
| 512 | + return _replaceNamed(route); | ||
| 513 | + } | ||
| 514 | + | ||
| 515 | + @override | ||
| 516 | + Future<T?> offNamed<T>( | ||
| 517 | + String page, { | ||
| 518 | + dynamic arguments, | ||
| 519 | + int? id, | ||
| 520 | + Map<String, String>? parameters, | ||
| 521 | + }) async { | ||
| 522 | + final args = _buildPageSettings(page, arguments); | ||
| 523 | + final route = _getRouteDecoder<T>(args); | ||
| 524 | + if (route == null) return null; | ||
| 525 | + _popWithResult(); | ||
| 526 | + return _push<T>(route); | ||
| 527 | + } | ||
| 528 | + | ||
| 529 | + @override | ||
| 530 | + Future<T?> toNamedAndOffUntil<T>( | ||
| 531 | + String page, | ||
| 532 | + bool Function(GetPage) predicate, [ | ||
| 533 | + Object? data, | ||
| 534 | + ]) async { | ||
| 535 | + final arguments = _buildPageSettings(page, data); | ||
| 536 | + | ||
| 537 | + final route = _getRouteDecoder<T>(arguments); | ||
| 538 | + | ||
| 539 | + if (route == null) return null; | ||
| 540 | + | ||
| 541 | + while (_activePages.isNotEmpty && !predicate(_activePages.last.route!)) { | ||
| 542 | + _popWithResult(); | ||
| 543 | + } | ||
| 544 | + | ||
| 545 | + return _push<T>(route); | ||
| 546 | + } | ||
| 547 | + | ||
| 548 | + @override | ||
| 549 | + Future<T?> offUntil<T>( | ||
| 550 | + Widget Function() page, | ||
| 551 | + bool Function(GetPage) predicate, [ | ||
| 552 | + Object? arguments, | ||
| 553 | + ]) async { | ||
| 554 | + while (_activePages.isNotEmpty && !predicate(_activePages.last.route!)) { | ||
| 555 | + _popWithResult(); | ||
| 556 | + } | ||
| 557 | + | ||
| 558 | + return to<T>(page, arguments: arguments); | ||
| 559 | + } | ||
| 560 | + | ||
| 561 | + @override | ||
| 562 | + void removeRoute<T>(String name) { | ||
| 563 | + _activePages.remove(RouteDecoder.fromRoute(name)); | ||
| 564 | + } | ||
| 565 | + | ||
| 566 | + @override | ||
| 567 | + void back<T>([T? result]) { | ||
| 568 | + _checkIfCanBack(); | ||
| 569 | + _popWithResult<T>(result); | ||
| 570 | + refresh(); | ||
| 571 | + } | ||
| 572 | + | ||
| 573 | + bool get canBack { | ||
| 574 | + return _activePages.length > 1; | ||
| 575 | + } | ||
| 576 | + | ||
| 577 | + void _checkIfCanBack() { | ||
| 578 | + assert(() { | ||
| 579 | + if (!canBack) { | ||
| 580 | + final last = _activePages.last; | ||
| 581 | + final name = last.route?.name; | ||
| 582 | + throw 'The page $name cannot be popped'; | ||
| 583 | + } | ||
| 584 | + return true; | ||
| 585 | + }()); | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + @override | ||
| 589 | + Future<R?> backAndtoNamed<T, R>(String page, | ||
| 590 | + {T? result, Object? arguments}) async { | ||
| 591 | + final args = _buildPageSettings(page, arguments); | ||
| 592 | + final route = _getRouteDecoder<R>(args); | ||
| 593 | + if (route == null) return null; | ||
| 594 | + _popWithResult<T>(result); | ||
| 595 | + return _push<R>(route); | ||
| 596 | + } | ||
| 597 | + | ||
| 598 | + /// Removes routes according to [PopMode] | ||
| 599 | + /// until it reaches the specifc [fullRoute], | ||
| 600 | + /// DOES NOT remove the [fullRoute] | ||
| 601 | + @override | ||
| 602 | + Future<void> popModeUntil( | ||
| 603 | + String fullRoute, { | ||
| 604 | + PopMode popMode = PopMode.History, | ||
| 605 | + }) async { | ||
| 606 | + // remove history or page entries until you meet route | ||
| 607 | + var iterator = currentConfiguration; | ||
| 608 | + while (_canPop(popMode) && | ||
| 609 | + iterator != null && | ||
| 610 | + iterator.arguments?.name != fullRoute) { | ||
| 611 | + await _pop(popMode, null); | ||
| 612 | + // replace iterator | ||
| 613 | + iterator = currentConfiguration; | ||
| 614 | + } | ||
| 615 | + refresh(); | ||
| 616 | + } | ||
| 617 | + | ||
| 618 | + @override | ||
| 619 | + void backUntil(bool Function(GetPage) predicate) { | ||
| 620 | + while (_activePages.length <= 1 && !predicate(_activePages.last.route!)) { | ||
| 621 | + _popWithResult(); | ||
| 622 | + } | ||
| 623 | + | ||
| 624 | + refresh(); | ||
| 625 | + } | ||
| 626 | + | ||
| 627 | + Future<T?> _replace<T>(PageSettings arguments, GetPage<T> page) async { | ||
| 628 | + final index = _activePages.length > 1 ? _activePages.length - 1 : 0; | ||
| 629 | + Get.addPage(page); | ||
| 630 | + | ||
| 631 | + final route = _getRouteDecoder(arguments); | ||
| 632 | + | ||
| 633 | + final activePage = _configureRouterDecoder<T>(route!, arguments); | ||
| 634 | + | ||
| 635 | + _activePages[index] = activePage; | ||
| 636 | + | ||
| 637 | + refresh(); | ||
| 638 | + final result = await activePage.route?.completer?.future as Future<T?>?; | ||
| 639 | + Get.removePage(page); | ||
| 640 | + | ||
| 641 | + return result; | ||
| 642 | + } | ||
| 643 | + | ||
| 644 | + Future<T?> _replaceNamed<T>(RouteDecoder activePage) async { | ||
| 645 | + final index = _activePages.length > 1 ? _activePages.length - 1 : 0; | ||
| 646 | + // final activePage = _configureRouterDecoder<T>(page, arguments); | ||
| 647 | + _activePages[index] = activePage; | ||
| 648 | + | ||
| 649 | + refresh(); | ||
| 650 | + final result = await activePage.route?.completer?.future as Future<T?>?; | ||
| 651 | + return result; | ||
| 652 | + } | ||
| 653 | + | ||
| 654 | + /// Takes a route [name] String generated by [to], [off], [offAll] | ||
| 655 | + /// (and similar context navigation methods), cleans the extra chars and | ||
| 656 | + /// accommodates the format. | ||
| 657 | + /// TODO: check for a more "appealing" URL naming convention. | ||
| 658 | + /// `() => MyHomeScreenView` becomes `/my-home-screen-view`. | ||
| 659 | + String _cleanRouteName(String name) { | ||
| 660 | + name = name.replaceAll('() => ', ''); | ||
| 661 | + | ||
| 662 | + /// uncommonent for URL styling. | ||
| 663 | + // name = name.paramCase!; | ||
| 664 | + if (!name.startsWith('/')) { | ||
| 665 | + name = '/$name'; | ||
| 666 | + } | ||
| 667 | + return Uri.tryParse(name)?.toString() ?? name; | ||
| 668 | + } | ||
| 669 | + | ||
| 670 | + PageSettings _buildPageSettings(String page, [Object? data]) { | ||
| 671 | + var uri = Uri.parse(page); | ||
| 672 | + return PageSettings(uri, data); | ||
| 673 | + } | ||
| 674 | + | ||
| 675 | + @protected | ||
| 676 | + RouteDecoder? _getRouteDecoder<T>(PageSettings arguments) { | ||
| 677 | + var page = arguments.uri.path; | ||
| 678 | + final parameters = arguments.params; | ||
| 679 | + if (parameters.isNotEmpty) { | ||
| 680 | + final uri = Uri(path: page, queryParameters: parameters); | ||
| 681 | + page = uri.toString(); | ||
| 682 | + } | ||
| 683 | + | ||
| 684 | + final decoder = Get.routeTree.matchRoute(page, arguments: arguments); | ||
| 685 | + final route = decoder.route; | ||
| 686 | + if (route == null) return null; | ||
| 687 | + return _configureRouterDecoder(decoder, arguments); | ||
| 688 | + } | ||
| 689 | + | ||
| 690 | + @protected | ||
| 691 | + RouteDecoder _configureRouterDecoder<T>( | ||
| 692 | + RouteDecoder decoder, PageSettings arguments) { | ||
| 693 | + final parameters = | ||
| 694 | + arguments.params.isEmpty ? arguments.query : arguments.params; | ||
| 695 | + if (arguments.params.isEmpty) { | ||
| 696 | + arguments.params.addAll(arguments.query); | ||
| 697 | + } | ||
| 698 | + if (decoder.parameters.isEmpty) { | ||
| 699 | + decoder.parameters.addAll(parameters); | ||
| 700 | + } | ||
| 701 | + | ||
| 702 | + decoder.route = decoder.route?.copy( | ||
| 703 | + completer: _activePages.isEmpty ? null : Completer(), | ||
| 704 | + arguments: arguments, | ||
| 705 | + parameters: parameters, | ||
| 706 | + ); | ||
| 707 | + return decoder; | ||
| 708 | + } | ||
| 709 | + | ||
| 710 | + Future<T?> _push<T>(RouteDecoder activePage, | ||
| 711 | + {bool rebuildStack = true, | ||
| 712 | + PreventDuplicateHandlingMode preventDuplicateHandlingMode = | ||
| 713 | + PreventDuplicateHandlingMode.ReorderRoutes}) async { | ||
| 714 | + final onStackPage = _activePages.firstWhereOrNull( | ||
| 715 | + (element) => element.route?.key == activePage.route?.key); | ||
| 716 | + | ||
| 717 | + /// There are no duplicate routes in the stack | ||
| 718 | + if (onStackPage == null) { | ||
| 719 | + final res = await runMiddleware(activePage); | ||
| 720 | + _activePages.add(res!); | ||
| 721 | + } else { | ||
| 722 | + /// There are duplicate routes, reorder | ||
| 723 | + switch (preventDuplicateHandlingMode) { | ||
| 724 | + case PreventDuplicateHandlingMode.DoNothing: | ||
| 725 | + break; | ||
| 726 | + case PreventDuplicateHandlingMode.ReorderRoutes: | ||
| 727 | + _activePages.remove(onStackPage); | ||
| 728 | + final res = await runMiddleware(onStackPage); | ||
| 729 | + _activePages.add(res!); | ||
| 730 | + break; | ||
| 731 | + case PreventDuplicateHandlingMode.PopUntilOriginalRoute: | ||
| 732 | + while (_activePages.last == onStackPage) { | ||
| 733 | + _popWithResult(); | ||
| 734 | + } | ||
| 735 | + break; | ||
| 736 | + case PreventDuplicateHandlingMode.Recreate: | ||
| 737 | + _activePages.remove(onStackPage); | ||
| 738 | + final res = await runMiddleware(activePage); | ||
| 739 | + _activePages.add(res!); | ||
| 740 | + break; | ||
| 741 | + default: | ||
| 742 | + } | ||
| 743 | + } | ||
| 744 | + if (rebuildStack) { | ||
| 745 | + refresh(); | ||
| 746 | + } | ||
| 747 | + | ||
| 748 | + return activePage.route?.completer?.future as Future<T?>?; | ||
| 749 | + } | ||
| 750 | + | ||
| 751 | + @override | ||
| 752 | + Future<void> setNewRoutePath(RouteDecoder configuration) async { | ||
| 753 | + final page = configuration.route; | ||
| 754 | + if (page == null) { | ||
| 755 | + goToUnknownPage(); | ||
| 756 | + return; | ||
| 757 | + } else { | ||
| 758 | + _push(configuration); | ||
| 759 | + } | ||
| 760 | + } | ||
| 761 | + | ||
| 762 | + @override | ||
| 763 | + RouteDecoder? get currentConfiguration { | ||
| 764 | + if (_activePages.isEmpty) return null; | ||
| 765 | + final route = _activePages.last; | ||
| 766 | + return route; | ||
| 767 | + } | ||
| 768 | + | ||
| 769 | + Future<bool> handlePopupRoutes({ | ||
| 770 | + Object? result, | ||
| 771 | + }) async { | ||
| 772 | + Route? currentRoute; | ||
| 773 | + navigatorKey.currentState!.popUntil((route) { | ||
| 774 | + currentRoute = route; | ||
| 775 | + return true; | ||
| 776 | + }); | ||
| 777 | + if (currentRoute is PopupRoute) { | ||
| 778 | + return await navigatorKey.currentState!.maybePop(result); | ||
| 779 | + } | ||
| 780 | + return false; | ||
| 781 | + } | ||
| 782 | + | ||
| 783 | + @override | ||
| 784 | + Future<bool> popRoute({ | ||
| 785 | + Object? result, | ||
| 786 | + PopMode? popMode, | ||
| 787 | + }) async { | ||
| 788 | + //Returning false will cause the entire app to be popped. | ||
| 789 | + final wasPopup = await handlePopupRoutes(result: result); | ||
| 790 | + if (wasPopup) return true; | ||
| 791 | + final _popped = await _pop(popMode ?? backButtonPopMode, result); | ||
| 792 | + refresh(); | ||
| 793 | + if (_popped != null) { | ||
| 794 | + //emulate the old pop with result | ||
| 795 | + return true; | ||
| 796 | + } | ||
| 797 | + return false; | ||
| 798 | + } | ||
| 799 | + | ||
| 800 | + bool _onPopVisualRoute(Route<dynamic> route, dynamic result) { | ||
| 801 | + final didPop = route.didPop(result); | ||
| 802 | + if (!didPop) { | ||
| 803 | + return false; | ||
| 804 | + } | ||
| 805 | + final settings = route.settings; | ||
| 806 | + if (settings is GetPage) { | ||
| 807 | + final config = _activePages.cast<RouteDecoder?>().firstWhere( | ||
| 808 | + (element) => element?.route == settings, | ||
| 809 | + orElse: () => null, | ||
| 810 | + ); | ||
| 811 | + if (config != null) { | ||
| 812 | + _removeHistoryEntry(config, result); | ||
| 813 | + } | ||
| 814 | + } | ||
| 815 | + refresh(); | ||
| 816 | + | ||
| 817 | + return true; | ||
| 818 | + } | ||
| 819 | +} |
lib/get_navigation/src/routes/index.dart
0 → 100644
| 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'; |
| @@ -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'; | 1 | import 'package:flutter/widgets.dart'; |
| 2 | 2 | ||
| 3 | +import '../../../route_manager.dart'; | ||
| 4 | + | ||
| 3 | extension PageArgExt on BuildContext { | 5 | extension PageArgExt on BuildContext { |
| 4 | RouteSettings? get settings { | 6 | RouteSettings? get settings { |
| 5 | return ModalRoute.of(this)!.settings; | 7 | return ModalRoute.of(this)!.settings; |
| @@ -44,6 +46,10 @@ extension PageArgExt on BuildContext { | @@ -44,6 +46,10 @@ extension PageArgExt on BuildContext { | ||
| 44 | RouterDelegate get delegate { | 46 | RouterDelegate get delegate { |
| 45 | return router.routerDelegate; | 47 | return router.routerDelegate; |
| 46 | } | 48 | } |
| 49 | + | ||
| 50 | + GetDelegate get navigation { | ||
| 51 | + return router.routerDelegate as GetDelegate; | ||
| 52 | + } | ||
| 47 | } | 53 | } |
| 48 | 54 | ||
| 49 | class PageSettings extends RouteSettings { | 55 | class PageSettings extends RouteSettings { |
| 1 | -import '../../get_navigation.dart'; | 1 | +import '../../../route_manager.dart'; |
| 2 | +import 'page_settings.dart'; | ||
| 2 | 3 | ||
| 3 | class RouteDecoder { | 4 | class RouteDecoder { |
| 4 | const RouteDecoder( | 5 | const RouteDecoder( |
| @@ -8,6 +9,18 @@ class RouteDecoder { | @@ -8,6 +9,18 @@ class RouteDecoder { | ||
| 8 | final List<GetPage> currentTreeBranch; | 9 | final List<GetPage> currentTreeBranch; |
| 9 | final PageSettings? arguments; | 10 | final PageSettings? arguments; |
| 10 | 11 | ||
| 12 | + factory RouteDecoder.fromRoute(String location) { | ||
| 13 | + var uri = Uri.parse(location); | ||
| 14 | + final args = PageSettings(uri); | ||
| 15 | + final decoder = Get.routeTree.matchRoute(location, arguments: args); | ||
| 16 | + decoder.route = decoder.route?.copy( | ||
| 17 | + completer: null, | ||
| 18 | + arguments: args, | ||
| 19 | + parameters: args.params, | ||
| 20 | + ); | ||
| 21 | + return decoder; | ||
| 22 | + } | ||
| 23 | + | ||
| 11 | GetPage? get route => | 24 | GetPage? get route => |
| 12 | currentTreeBranch.isEmpty ? null : currentTreeBranch.last; | 25 | currentTreeBranch.isEmpty ? null : currentTreeBranch.last; |
| 13 | 26 | ||
| @@ -204,7 +217,7 @@ class ParseRouteTree { | @@ -204,7 +217,7 @@ class ParseRouteTree { | ||
| 204 | } | 217 | } |
| 205 | } | 218 | } |
| 206 | 219 | ||
| 207 | -extension FirstWhereExt<T> on List<T> { | 220 | +extension FirstWhereOrNullExt<T> on List<T> { |
| 208 | /// The first element satisfying [test], or `null` if there are none. | 221 | /// The first element satisfying [test], or `null` if there are none. |
| 209 | T? firstWhereOrNull(bool Function(T element) test) { | 222 | T? firstWhereOrNull(bool Function(T element) test) { |
| 210 | for (var element in this) { | 223 | for (var element in this) { |
| @@ -51,7 +51,7 @@ abstract class _RouteMiddleware { | @@ -51,7 +51,7 @@ abstract class _RouteMiddleware { | ||
| 51 | /// } | 51 | /// } |
| 52 | /// ``` | 52 | /// ``` |
| 53 | /// {@end-tool} | 53 | /// {@end-tool} |
| 54 | - Future<GetNavConfig?> redirectDelegate(GetNavConfig route); | 54 | + Future<RouteDecoder?> redirectDelegate(RouteDecoder route); |
| 55 | 55 | ||
| 56 | /// This function will be called when this Page is called | 56 | /// 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 | 57 | /// you can use it to change something about the page or give it new page |
| @@ -120,7 +120,7 @@ class GetMiddleware implements _RouteMiddleware { | @@ -120,7 +120,7 @@ class GetMiddleware implements _RouteMiddleware { | ||
| 120 | void onPageDispose() {} | 120 | void onPageDispose() {} |
| 121 | 121 | ||
| 122 | @override | 122 | @override |
| 123 | - Future<GetNavConfig?> redirectDelegate(GetNavConfig route) => | 123 | + Future<RouteDecoder?> redirectDelegate(RouteDecoder route) => |
| 124 | SynchronousFuture(route); | 124 | SynchronousFuture(route); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| @@ -285,8 +285,8 @@ class PageRedirect { | @@ -285,8 +285,8 @@ class PageRedirect { | ||
| 285 | void addPageParameter(GetPage route) { | 285 | void addPageParameter(GetPage route) { |
| 286 | if (route.parameters == null) return; | 286 | if (route.parameters == null) return; |
| 287 | 287 | ||
| 288 | - final parameters = Get.parameters; | 288 | + final parameters = Map<String, String?>.from(Get.parameters); |
| 289 | parameters.addEntries(route.parameters!.entries); | 289 | parameters.addEntries(route.parameters!.entries); |
| 290 | - Get.parameters = parameters; | 290 | + // Get.parameters = parameters; |
| 291 | } | 291 | } |
| 292 | } | 292 | } |
| @@ -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 ?? Get.rootController.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, |
| @@ -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, |
| 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>[ |
| 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,10 +40,18 @@ void main() { | @@ -35,10 +40,18 @@ 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); | ||
| 40 | Get.back(); | 50 | Get.back(); |
| 41 | - expect(Get.isDialogOpen, false); | 51 | + await tester.pumpAndSettle(); |
| 52 | + | ||
| 53 | + expect(find.byType(YourDialogWidget), findsNothing); | ||
| 54 | + // expect(Get.isDialogOpen, false); | ||
| 42 | await tester.pumpAndSettle(); | 55 | await tester.pumpAndSettle(); |
| 43 | }); | 56 | }); |
| 44 | } | 57 | } |
| @@ -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,15 @@ void main() { | @@ -47,13 +47,15 @@ void main() { | ||
| 47 | 47 | ||
| 48 | await tester.pumpAndSettle(); | 48 | await tester.pumpAndSettle(); |
| 49 | 49 | ||
| 50 | - expect(Get.currentRoute, '/404'); | 50 | + expect(Get.rootController.rootDelegate.currentConfiguration?.route?.name, |
| 51 | + '/404'); | ||
| 51 | }); | 52 | }); |
| 52 | 53 | ||
| 53 | testWidgets("Get.off navigates to provided route", (tester) async { | 54 | testWidgets("Get.off navigates to provided route", (tester) async { |
| 54 | await tester.pumpWidget(Wrapper(child: FirstScreen())); | 55 | await tester.pumpWidget(Wrapper(child: FirstScreen())); |
| 56 | + // await tester.pump(); | ||
| 55 | 57 | ||
| 56 | - Get.off(SecondScreen()); | 58 | + Get.off(() => SecondScreen()); |
| 57 | 59 | ||
| 58 | await tester.pumpAndSettle(); | 60 | await tester.pumpAndSettle(); |
| 59 | 61 | ||
| @@ -62,8 +64,9 @@ void main() { | @@ -62,8 +64,9 @@ void main() { | ||
| 62 | 64 | ||
| 63 | testWidgets("Get.off removes current route", (tester) async { | 65 | testWidgets("Get.off removes current route", (tester) async { |
| 64 | await tester.pumpWidget(Wrapper(child: FirstScreen())); | 66 | await tester.pumpWidget(Wrapper(child: FirstScreen())); |
| 67 | + await tester.pump(); | ||
| 65 | 68 | ||
| 66 | - Get.off(SecondScreen()); | 69 | + Get.off(() => SecondScreen()); |
| 67 | Get.back(); | 70 | Get.back(); |
| 68 | 71 | ||
| 69 | await tester.pumpAndSettle(); | 72 | await tester.pumpAndSettle(); |
| @@ -81,6 +84,8 @@ void main() { | @@ -81,6 +84,8 @@ void main() { | ||
| 81 | ], | 84 | ], |
| 82 | )); | 85 | )); |
| 83 | 86 | ||
| 87 | + await tester.pump(); | ||
| 88 | + | ||
| 84 | Get.offNamed('/second'); | 89 | Get.offNamed('/second'); |
| 85 | 90 | ||
| 86 | await tester.pumpAndSettle(); | 91 | await tester.pumpAndSettle(); |
| @@ -98,7 +103,10 @@ void main() { | @@ -98,7 +103,10 @@ void main() { | ||
| 98 | ], | 103 | ], |
| 99 | )); | 104 | )); |
| 100 | 105 | ||
| 106 | + await tester.pump(); | ||
| 107 | + | ||
| 101 | Get.offNamed('/second'); | 108 | Get.offNamed('/second'); |
| 109 | + await tester.pumpAndSettle(); | ||
| 102 | Get.back(); | 110 | Get.back(); |
| 103 | 111 | ||
| 104 | await tester.pumpAndSettle(); | 112 | await tester.pumpAndSettle(); |
| @@ -116,19 +124,24 @@ void main() { | @@ -116,19 +124,24 @@ void main() { | ||
| 116 | ], | 124 | ], |
| 117 | )); | 125 | )); |
| 118 | 126 | ||
| 127 | + await tester.pump(); | ||
| 128 | + | ||
| 119 | Get.toNamed('/second'); | 129 | Get.toNamed('/second'); |
| 130 | + await tester.pumpAndSettle(); | ||
| 120 | Get.offNamed('/third'); | 131 | Get.offNamed('/third'); |
| 132 | + await tester.pumpAndSettle(); | ||
| 121 | Get.back(); | 133 | Get.back(); |
| 122 | - | ||
| 123 | await tester.pumpAndSettle(); | 134 | await tester.pumpAndSettle(); |
| 135 | + print(Get.rootController.rootDelegate.currentConfiguration?.route?.name); | ||
| 124 | 136 | ||
| 125 | expect(find.byType(FirstScreen), findsOneWidget); | 137 | expect(find.byType(FirstScreen), findsOneWidget); |
| 126 | }); | 138 | }); |
| 127 | 139 | ||
| 128 | testWidgets("Get.offAll navigates to provided route", (tester) async { | 140 | testWidgets("Get.offAll navigates to provided route", (tester) async { |
| 129 | await tester.pumpWidget(Wrapper(child: FirstScreen())); | 141 | await tester.pumpWidget(Wrapper(child: FirstScreen())); |
| 142 | + await tester.pump(); | ||
| 130 | 143 | ||
| 131 | - Get.offAll(SecondScreen()); | 144 | + Get.offAll(() => SecondScreen()); |
| 132 | 145 | ||
| 133 | await tester.pumpAndSettle(); | 146 | await tester.pumpAndSettle(); |
| 134 | 147 | ||
| @@ -137,11 +150,13 @@ void main() { | @@ -137,11 +150,13 @@ void main() { | ||
| 137 | 150 | ||
| 138 | testWidgets("Get.offAll removes all previous routes", (tester) async { | 151 | testWidgets("Get.offAll removes all previous routes", (tester) async { |
| 139 | await tester.pumpWidget(Wrapper(child: FirstScreen())); | 152 | await tester.pumpWidget(Wrapper(child: FirstScreen())); |
| 153 | + await tester.pump(); | ||
| 140 | 154 | ||
| 141 | - Get.to(SecondScreen()); | ||
| 142 | - Get.offAll(ThirdScreen()); | 155 | + Get.to(() => SecondScreen()); |
| 156 | + await tester.pumpAndSettle(); | ||
| 157 | + Get.offAll(() => ThirdScreen()); | ||
| 158 | + await tester.pumpAndSettle(); | ||
| 143 | Get.back(); | 159 | Get.back(); |
| 144 | - | ||
| 145 | await tester.pumpAndSettle(); | 160 | await tester.pumpAndSettle(); |
| 146 | 161 | ||
| 147 | expect(find.byType(SecondScreen), findsNothing); | 162 | expect(find.byType(SecondScreen), findsNothing); |
| @@ -164,6 +179,8 @@ void main() { | @@ -164,6 +179,8 @@ void main() { | ||
| 164 | ], | 179 | ], |
| 165 | )); | 180 | )); |
| 166 | 181 | ||
| 182 | + await tester.pump(); | ||
| 183 | + | ||
| 167 | Get.toNamed('/second'); | 184 | Get.toNamed('/second'); |
| 168 | 185 | ||
| 169 | await tester.pumpAndSettle(); | 186 | await tester.pumpAndSettle(); |
| @@ -181,10 +198,13 @@ void main() { | @@ -181,10 +198,13 @@ void main() { | ||
| 181 | ], | 198 | ], |
| 182 | )); | 199 | )); |
| 183 | 200 | ||
| 201 | + await tester.pump(); | ||
| 202 | + | ||
| 184 | Get.toNamed('/second'); | 203 | Get.toNamed('/second'); |
| 204 | + await tester.pumpAndSettle(); | ||
| 185 | Get.offAllNamed('/third'); | 205 | Get.offAllNamed('/third'); |
| 206 | + await tester.pumpAndSettle(); | ||
| 186 | Get.back(); | 207 | Get.back(); |
| 187 | - | ||
| 188 | await tester.pumpAndSettle(); | 208 | await tester.pumpAndSettle(); |
| 189 | 209 | ||
| 190 | expect(find.byType(SecondScreen), findsNothing); | 210 | expect(find.byType(SecondScreen), findsNothing); |
| @@ -234,10 +254,9 @@ void main() { | @@ -234,10 +254,9 @@ void main() { | ||
| 234 | testWidgets("Get.offUntil navigates to provided route", (tester) async { | 254 | testWidgets("Get.offUntil navigates to provided route", (tester) async { |
| 235 | await tester.pumpWidget(Wrapper(child: Container())); | 255 | await tester.pumpWidget(Wrapper(child: Container())); |
| 236 | 256 | ||
| 237 | - Get.to(FirstScreen()); | 257 | + Get.to(() => FirstScreen()); |
| 238 | 258 | ||
| 239 | - Get.offUntil(GetPageRoute(page: () => ThirdScreen()), | ||
| 240 | - (route) => (route as GetPageRoute).routeName == '/FirstScreen'); | 259 | + Get.offUntil(() => ThirdScreen(), (route) => route.name == '/FirstScreen'); |
| 241 | 260 | ||
| 242 | await tester.pumpAndSettle(); | 261 | await tester.pumpAndSettle(); |
| 243 | 262 | ||
| @@ -249,10 +268,10 @@ void main() { | @@ -249,10 +268,10 @@ void main() { | ||
| 249 | (tester) async { | 268 | (tester) async { |
| 250 | await tester.pumpWidget(Wrapper(child: Container())); | 269 | await tester.pumpWidget(Wrapper(child: Container())); |
| 251 | 270 | ||
| 252 | - Get.to(FirstScreen()); | ||
| 253 | - Get.to(SecondScreen()); | ||
| 254 | - Get.offUntil(GetPageRoute(page: () => ThirdScreen()), | ||
| 255 | - (route) => (route as GetPageRoute).routeName == '/FirstScreen'); | 271 | + Get.to(() => FirstScreen()); |
| 272 | + Get.to(() => SecondScreen()); | ||
| 273 | + Get.rootController.rootDelegate | ||
| 274 | + .offUntil(() => ThirdScreen(), (route) => route.name == '/FirstScreen'); | ||
| 256 | Get.back(); | 275 | Get.back(); |
| 257 | 276 | ||
| 258 | await tester.pumpAndSettle(); | 277 | await tester.pumpAndSettle(); |
| @@ -265,10 +284,12 @@ void main() { | @@ -265,10 +284,12 @@ void main() { | ||
| 265 | (tester) async { | 284 | (tester) async { |
| 266 | await tester.pumpWidget(Wrapper(child: Container())); | 285 | await tester.pumpWidget(Wrapper(child: Container())); |
| 267 | 286 | ||
| 268 | - Get.to(FirstScreen()); | ||
| 269 | - Get.to(SecondScreen()); | ||
| 270 | - Get.offUntil(GetPageRoute(page: () => ThirdScreen()), | ||
| 271 | - (route) => (route as GetPageRoute).routeName == '/FirstScreen'); | 287 | + Get.to(() => FirstScreen()); |
| 288 | + await tester.pumpAndSettle(); | ||
| 289 | + Get.to(() => SecondScreen()); | ||
| 290 | + await tester.pumpAndSettle(); | ||
| 291 | + Get.offUntil(() => ThirdScreen(), (route) => route.name == '/FirstScreen'); | ||
| 292 | + await tester.pumpAndSettle(); | ||
| 272 | Get.back(); | 293 | Get.back(); |
| 273 | 294 | ||
| 274 | await tester.pumpAndSettle(); | 295 | await tester.pumpAndSettle(); |
| @@ -286,7 +307,7 @@ void main() { | @@ -286,7 +307,7 @@ void main() { | ||
| 286 | ], | 307 | ], |
| 287 | )); | 308 | )); |
| 288 | 309 | ||
| 289 | - Get.offNamedUntil('/second', ModalRoute.withName('/first')); | 310 | + Get.offNamedUntil('/second', (route) => route.name == '/first'); |
| 290 | 311 | ||
| 291 | await tester.pumpAndSettle(); | 312 | await tester.pumpAndSettle(); |
| 292 | 313 | ||
| @@ -306,7 +327,8 @@ void main() { | @@ -306,7 +327,8 @@ void main() { | ||
| 306 | )); | 327 | )); |
| 307 | 328 | ||
| 308 | Get.toNamed('/second'); | 329 | Get.toNamed('/second'); |
| 309 | - Get.offNamedUntil('/third', ModalRoute.withName('/first')); | 330 | + await tester.pumpAndSettle(); |
| 331 | + Get.offNamedUntil('/third', (route) => route.name == '/first'); | ||
| 310 | 332 | ||
| 311 | await tester.pumpAndSettle(); | 333 | await tester.pumpAndSettle(); |
| 312 | 334 | ||
| @@ -326,7 +348,9 @@ void main() { | @@ -326,7 +348,9 @@ void main() { | ||
| 326 | )); | 348 | )); |
| 327 | 349 | ||
| 328 | Get.toNamed('/second'); | 350 | Get.toNamed('/second'); |
| 329 | - Get.offNamedUntil('/third', ModalRoute.withName('/first')); | 351 | + await tester.pumpAndSettle(); |
| 352 | + Get.offNamedUntil('/third', (route) => route.name == '/first'); | ||
| 353 | + await tester.pumpAndSettle(); | ||
| 330 | Get.back(); | 354 | Get.back(); |
| 331 | 355 | ||
| 332 | await tester.pumpAndSettle(); | 356 | await tester.pumpAndSettle(); |
| @@ -342,7 +366,8 @@ void main() { | @@ -342,7 +366,8 @@ void main() { | ||
| 342 | ), | 366 | ), |
| 343 | ); | 367 | ); |
| 344 | 368 | ||
| 345 | - Get.to(SecondScreen()); | 369 | + Get.to(() => SecondScreen()); |
| 370 | + await tester.pumpAndSettle(); | ||
| 346 | Get.back(); | 371 | Get.back(); |
| 347 | 372 | ||
| 348 | await tester.pumpAndSettle(); | 373 | await tester.pumpAndSettle(); |
| @@ -355,8 +380,10 @@ void main() { | @@ -355,8 +380,10 @@ void main() { | ||
| 355 | (tester) async { | 380 | (tester) async { |
| 356 | await tester.pumpWidget(Wrapper(child: FirstScreen())); | 381 | await tester.pumpWidget(Wrapper(child: FirstScreen())); |
| 357 | 382 | ||
| 358 | - Get.to(SecondScreen()); | 383 | + Get.to(() => SecondScreen()); |
| 384 | + await tester.pumpAndSettle(); | ||
| 359 | Get.snackbar('title', "message"); | 385 | Get.snackbar('title', "message"); |
| 386 | + await tester.pumpAndSettle(); | ||
| 360 | Get.back(closeOverlays: true); | 387 | Get.back(closeOverlays: true); |
| 361 | 388 | ||
| 362 | await tester.pumpAndSettle(); | 389 | await tester.pumpAndSettle(); |
| @@ -373,7 +400,7 @@ void main() { | @@ -373,7 +400,7 @@ void main() { | ||
| 373 | ), | 400 | ), |
| 374 | ); | 401 | ); |
| 375 | 402 | ||
| 376 | - Get.to(FirstScreen()); | 403 | + Get.to(() => FirstScreen()); |
| 377 | 404 | ||
| 378 | await tester.pumpAndSettle(); | 405 | await tester.pumpAndSettle(); |
| 379 | 406 | ||
| @@ -386,7 +413,7 @@ void main() { | @@ -386,7 +413,7 @@ void main() { | ||
| 386 | ), | 413 | ), |
| 387 | ); | 414 | ); |
| 388 | 415 | ||
| 389 | - Get.to(FirstScreen()); | 416 | + Get.to(() => FirstScreen()); |
| 390 | 417 | ||
| 391 | await tester.pumpAndSettle(); | 418 | await tester.pumpAndSettle(); |
| 392 | 419 | ||
| @@ -399,7 +426,7 @@ void main() { | @@ -399,7 +426,7 @@ void main() { | ||
| 399 | ), | 426 | ), |
| 400 | ); | 427 | ); |
| 401 | 428 | ||
| 402 | - Get.to(FirstScreen()); | 429 | + Get.to(() => FirstScreen()); |
| 403 | 430 | ||
| 404 | await tester.pumpAndSettle(); | 431 | await tester.pumpAndSettle(); |
| 405 | 432 | ||
| @@ -412,7 +439,7 @@ void main() { | @@ -412,7 +439,7 @@ void main() { | ||
| 412 | ), | 439 | ), |
| 413 | ); | 440 | ); |
| 414 | 441 | ||
| 415 | - Get.to(FirstScreen()); | 442 | + Get.to(() => FirstScreen()); |
| 416 | 443 | ||
| 417 | await tester.pumpAndSettle(); | 444 | await tester.pumpAndSettle(); |
| 418 | 445 | ||
| @@ -425,7 +452,7 @@ void main() { | @@ -425,7 +452,7 @@ void main() { | ||
| 425 | ), | 452 | ), |
| 426 | ); | 453 | ); |
| 427 | 454 | ||
| 428 | - Get.to(FirstScreen()); | 455 | + Get.to(() => FirstScreen()); |
| 429 | 456 | ||
| 430 | await tester.pumpAndSettle(); | 457 | await tester.pumpAndSettle(); |
| 431 | 458 | ||
| @@ -438,7 +465,7 @@ void main() { | @@ -438,7 +465,7 @@ void main() { | ||
| 438 | ), | 465 | ), |
| 439 | ); | 466 | ); |
| 440 | 467 | ||
| 441 | - Get.to(FirstScreen()); | 468 | + Get.to(() => FirstScreen()); |
| 442 | 469 | ||
| 443 | await tester.pumpAndSettle(); | 470 | await tester.pumpAndSettle(); |
| 444 | 471 | ||
| @@ -451,7 +478,7 @@ void main() { | @@ -451,7 +478,7 @@ void main() { | ||
| 451 | ), | 478 | ), |
| 452 | ); | 479 | ); |
| 453 | 480 | ||
| 454 | - Get.to(FirstScreen()); | 481 | + Get.to(() => FirstScreen()); |
| 455 | 482 | ||
| 456 | await tester.pumpAndSettle(); | 483 | await tester.pumpAndSettle(); |
| 457 | 484 | ||
| @@ -464,7 +491,7 @@ void main() { | @@ -464,7 +491,7 @@ void main() { | ||
| 464 | ), | 491 | ), |
| 465 | ); | 492 | ); |
| 466 | 493 | ||
| 467 | - Get.to(FirstScreen()); | 494 | + Get.to(() => FirstScreen()); |
| 468 | 495 | ||
| 469 | await tester.pumpAndSettle(); | 496 | await tester.pumpAndSettle(); |
| 470 | 497 | ||
| @@ -477,7 +504,7 @@ void main() { | @@ -477,7 +504,7 @@ void main() { | ||
| 477 | ), | 504 | ), |
| 478 | ); | 505 | ); |
| 479 | 506 | ||
| 480 | - Get.to(FirstScreen()); | 507 | + Get.to(() => FirstScreen()); |
| 481 | 508 | ||
| 482 | await tester.pumpAndSettle(); | 509 | await tester.pumpAndSettle(); |
| 483 | 510 |
| 1 | -import 'package:flutter/cupertino.dart'; | ||
| 2 | -import 'package:flutter_test/flutter_test.dart'; | ||
| 3 | -import 'package:get/get.dart'; | 1 | +// import 'package:flutter/cupertino.dart'; |
| 2 | +// import 'package:flutter_test/flutter_test.dart'; | ||
| 3 | +// import 'package:get/get.dart'; | ||
| 4 | 4 | ||
| 5 | -import 'get_main_test.dart'; | 5 | +// import 'get_main_test.dart'; |
| 6 | 6 | ||
| 7 | -class RedirectMiddleware extends GetMiddleware { | ||
| 8 | - @override | ||
| 9 | - RouteSettings redirect(String? route) => RouteSettings(name: '/second'); | ||
| 10 | -} | 7 | +// class RedirectMiddleware extends GetMiddleware { |
| 8 | +// @override | ||
| 9 | +// RouteSettings redirect(String? route) { | ||
| 10 | +// return RouteSettings(name: '/second'); | ||
| 11 | +// } | ||
| 12 | +// } | ||
| 11 | 13 | ||
| 12 | -void main() { | ||
| 13 | - testWidgets("Middleware redirect smoke test", (tester) async { | ||
| 14 | - await tester.pumpWidget( | ||
| 15 | - GetMaterialApp( | ||
| 16 | - initialRoute: '/', | ||
| 17 | - getPages: [ | ||
| 18 | - GetPage(name: '/', page: () => Container()), | ||
| 19 | - GetPage( | ||
| 20 | - name: '/first', | ||
| 21 | - page: () => FirstScreen(), | ||
| 22 | - middlewares: [RedirectMiddleware()]), | ||
| 23 | - GetPage(name: '/second', page: () => SecondScreen()), | ||
| 24 | - GetPage(name: '/third', page: () => ThirdScreen()), | ||
| 25 | - ], | ||
| 26 | - ), | ||
| 27 | - ); | 14 | +// void main() { |
| 15 | +// testWidgets("Middleware redirect smoke test", (tester) async { | ||
| 16 | +// await tester.pumpWidget( | ||
| 17 | +// GetMaterialApp( | ||
| 18 | +// initialRoute: '/', | ||
| 19 | +// getPages: [ | ||
| 20 | +// GetPage(name: '/', page: () => Container()), | ||
| 21 | +// GetPage(name: '/first', page: () => FirstScreen(), middlewares: [ | ||
| 22 | +// RedirectMiddleware(), | ||
| 23 | +// ]), | ||
| 24 | +// GetPage(name: '/second', page: () => SecondScreen()), | ||
| 25 | +// GetPage(name: '/third', page: () => ThirdScreen()), | ||
| 26 | +// ], | ||
| 27 | +// ), | ||
| 28 | +// ); | ||
| 28 | 29 | ||
| 29 | - Get.toNamed('/first'); | 30 | +// Get.toNamed('/first'); |
| 30 | 31 | ||
| 31 | - await tester.pumpAndSettle(); | ||
| 32 | - print(Get.routing.current); | ||
| 33 | - expect(find.byType(SecondScreen), findsOneWidget); | ||
| 34 | - }); | ||
| 35 | -} | 32 | +// await tester.pumpAndSettle(); |
| 33 | +// print(Get.rootController.rootDelegate.currentConfiguration?.route?.name); | ||
| 34 | +// expect(find.byType(SecondScreen), findsOneWidget); | ||
| 35 | +// }); | ||
| 36 | +// } |
| 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', () { |
| @@ -146,12 +145,16 @@ void main() { | @@ -146,12 +145,16 @@ void main() { | ||
| 146 | 145 | ||
| 147 | await tester.pumpAndSettle(); | 146 | await tester.pumpAndSettle(); |
| 148 | 147 | ||
| 148 | + print(Get.rootController.rootDelegate.pageSettings?.params); | ||
| 149 | + | ||
| 149 | expect(Get.parameters['id'], '1234'); | 150 | expect(Get.parameters['id'], '1234'); |
| 150 | 151 | ||
| 151 | Get.toNamed('/third?name=jonny&job=dev'); | 152 | Get.toNamed('/third?name=jonny&job=dev'); |
| 152 | 153 | ||
| 153 | await tester.pumpAndSettle(); | 154 | await tester.pumpAndSettle(); |
| 154 | 155 | ||
| 156 | + print(Get.parameters); | ||
| 157 | + | ||
| 155 | expect(Get.parameters['name'], 'jonny'); | 158 | expect(Get.parameters['name'], 'jonny'); |
| 156 | expect(Get.parameters['job'], 'dev'); | 159 | expect(Get.parameters['job'], 'dev'); |
| 157 | 160 |
| 1 | -import 'package:flutter/cupertino.dart'; | ||
| 2 | -import 'package:flutter_test/flutter_test.dart'; | ||
| 3 | -import 'package:get/get.dart'; | 1 | +// import 'package:flutter/cupertino.dart'; |
| 2 | +// import 'package:flutter_test/flutter_test.dart'; | ||
| 3 | +// import 'package:get/get.dart'; | ||
| 4 | 4 | ||
| 5 | -void main() { | ||
| 6 | - testWidgets('Back swipe dismiss interrupted by route push', (tester) async { | ||
| 7 | - // final scaffoldKey = GlobalKey(); | 5 | +void main() {} |
| 8 | 6 | ||
| 9 | - await tester.pumpWidget( | ||
| 10 | - GetCupertinoApp( | ||
| 11 | - popGesture: true, | ||
| 12 | - home: CupertinoPageScaffold( | ||
| 13 | - // key: scaffoldKey, | ||
| 14 | - child: Center( | ||
| 15 | - child: CupertinoButton( | ||
| 16 | - onPressed: () { | ||
| 17 | - Get.to(() => CupertinoPageScaffold( | ||
| 18 | - child: Center(child: Text('route')), | ||
| 19 | - )); | ||
| 20 | - }, | ||
| 21 | - child: const Text('push'), | ||
| 22 | - ), | ||
| 23 | - ), | ||
| 24 | - ), | ||
| 25 | - ), | ||
| 26 | - ); | 7 | +// void main() { |
| 8 | +// testWidgets('Back swipe dismiss interrupted by route push', (tester) async { | ||
| 9 | +// // final scaffoldKey = GlobalKey(); | ||
| 27 | 10 | ||
| 28 | - // Check the basic iOS back-swipe dismiss transition. Dragging the pushed | ||
| 29 | - // route halfway across the screen will trigger the iOS dismiss animation | 11 | +// await tester.pumpWidget( |
| 12 | +// GetCupertinoApp( | ||
| 13 | +// popGesture: true, | ||
| 14 | +// home: CupertinoPageScaffold( | ||
| 15 | +// // key: scaffoldKey, | ||
| 16 | +// child: Center( | ||
| 17 | +// child: CupertinoButton( | ||
| 18 | +// onPressed: () { | ||
| 19 | +// Get.to( | ||
| 20 | +// () => CupertinoPageScaffold( | ||
| 21 | +// child: Center(child: Text('route')), | ||
| 22 | +// ), | ||
| 23 | +// preventDuplicateHandlingMode: | ||
| 24 | +// PreventDuplicateHandlingMode.Recreate); | ||
| 25 | +// }, | ||
| 26 | +// child: const Text('push'), | ||
| 27 | +// ), | ||
| 28 | +// ), | ||
| 29 | +// ), | ||
| 30 | +// ), | ||
| 31 | +// ); | ||
| 30 | 32 | ||
| 31 | - await tester.tap(find.text('push')); | ||
| 32 | - await tester.pumpAndSettle(); | ||
| 33 | - expect(find.text('route'), findsOneWidget); | ||
| 34 | - expect(find.text('push'), findsNothing); | 33 | +// await tester.pumpAndSettle(); |
| 35 | 34 | ||
| 36 | - var gesture = await tester.startGesture(const Offset(5, 300)); | ||
| 37 | - await gesture.moveBy(const Offset(400, 0)); | ||
| 38 | - await gesture.up(); | ||
| 39 | - await tester.pump(); | ||
| 40 | - expect( | ||
| 41 | - // The 'route' route has been dragged to the right, halfway across | ||
| 42 | - // the screen | ||
| 43 | - tester.getTopLeft(find.ancestor( | ||
| 44 | - of: find.text('route'), | ||
| 45 | - matching: find.byType(CupertinoPageScaffold))), | ||
| 46 | - const Offset(400, 0), | ||
| 47 | - ); | ||
| 48 | - expect( | ||
| 49 | - // The 'push' route is sliding in from the left. | ||
| 50 | - tester | ||
| 51 | - .getTopLeft(find.ancestor( | ||
| 52 | - of: find.text('push'), | ||
| 53 | - matching: find.byType(CupertinoPageScaffold))) | ||
| 54 | - .dx, | ||
| 55 | - 0, | ||
| 56 | - ); | ||
| 57 | - await tester.pumpAndSettle(); | ||
| 58 | - expect(find.text('push'), findsOneWidget); | ||
| 59 | - expect( | ||
| 60 | - tester.getTopLeft(find.ancestor( | ||
| 61 | - of: find.text('push'), matching: find.byType(CupertinoPageScaffold))), | ||
| 62 | - Offset.zero, | ||
| 63 | - ); | ||
| 64 | - expect(find.text('route'), findsNothing); | 35 | +// // Check the basic iOS back-swipe dismiss transition. Dragging the pushed |
| 36 | +// // route halfway across the screen will trigger the iOS dismiss animation | ||
| 65 | 37 | ||
| 66 | - // Run the dismiss animation 60%, which exposes the route "push" button, | ||
| 67 | - // and then press the button. | 38 | +// await tester.tap(find.text('push')); |
| 39 | +// await tester.pumpAndSettle(); | ||
| 40 | +// expect(find.text('route'), findsOneWidget); | ||
| 41 | +// expect(find.text('push'), findsNothing); | ||
| 68 | 42 | ||
| 69 | - await tester.tap(find.text('push')); | ||
| 70 | - await tester.pumpAndSettle(); | ||
| 71 | - expect(find.text('route'), findsOneWidget); | ||
| 72 | - expect(find.text('push'), findsNothing); | 43 | +// var gesture = await tester.startGesture(const Offset(5, 300)); |
| 44 | +// await gesture.moveBy(const Offset(400, 0)); | ||
| 45 | +// await gesture.up(); | ||
| 46 | +// await tester.pump(); | ||
| 47 | +// expect( | ||
| 48 | +// // The 'route' route has been dragged to the right, halfway across | ||
| 49 | +// // the screen | ||
| 50 | +// tester.getTopLeft(find.ancestor( | ||
| 51 | +// of: find.text('route'), | ||
| 52 | +// matching: find.byType(CupertinoPageScaffold))), | ||
| 53 | +// const Offset(400, 0), | ||
| 54 | +// ); | ||
| 55 | +// expect( | ||
| 56 | +// // The 'push' route is sliding in from the left. | ||
| 57 | +// tester | ||
| 58 | +// .getTopLeft(find.ancestor( | ||
| 59 | +// of: find.text('push'), | ||
| 60 | +// matching: find.byType(CupertinoPageScaffold))) | ||
| 61 | +// .dx, | ||
| 62 | +// 400 / 3, | ||
| 63 | +// ); | ||
| 64 | +// await tester.pumpAndSettle(); | ||
| 65 | +// expect(find.text('push'), findsOneWidget); | ||
| 66 | +// expect( | ||
| 67 | +// tester.getTopLeft(find.ancestor( | ||
| 68 | +// of: find.text('push'), matching: find.byType(CupertinoPageScaffold))), | ||
| 69 | +// Offset.zero, | ||
| 70 | +// ); | ||
| 71 | +// expect(find.text('route'), findsNothing); | ||
| 73 | 72 | ||
| 74 | - gesture = await tester.startGesture(const Offset(5, 300)); | ||
| 75 | - await gesture.moveBy(const Offset(400, 0)); // Drag halfway. | ||
| 76 | - await gesture.up(); | ||
| 77 | - // Trigger the snapping animation. | ||
| 78 | - // Since the back swipe drag was brought to >=50% of the screen, it will | ||
| 79 | - // self snap to finish the pop transition as the gesture is lifted. | ||
| 80 | - // | ||
| 81 | - // This drag drop animation is 400ms when dropped exactly halfway | ||
| 82 | - // (800 / [pixel distance remaining], see | ||
| 83 | - // _CupertinoBackGestureController.dragEnd). It follows a curve that is very | ||
| 84 | - // steep initially. | ||
| 85 | - await tester.pump(); | ||
| 86 | - expect( | ||
| 87 | - tester.getTopLeft(find.ancestor( | ||
| 88 | - of: find.text('route'), | ||
| 89 | - matching: find.byType(CupertinoPageScaffold))), | ||
| 90 | - const Offset(400, 0), | ||
| 91 | - ); | ||
| 92 | - // Let the dismissing snapping animation go 60%. | ||
| 93 | - await tester.pump(const Duration(milliseconds: 240)); | ||
| 94 | - expect( | ||
| 95 | - tester | ||
| 96 | - .getTopLeft(find.ancestor( | ||
| 97 | - of: find.text('route'), | ||
| 98 | - matching: find.byType(CupertinoPageScaffold))) | ||
| 99 | - .dx, | ||
| 100 | - moreOrLessEquals(798, epsilon: 1), | ||
| 101 | - ); | 73 | +// // Run the dismiss animation 60%, which exposes the route "push" button, |
| 74 | +// // and then press the button. | ||
| 102 | 75 | ||
| 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 | - )); | 76 | +// await tester.tap(find.text('push')); |
| 77 | +// await tester.pumpAndSettle(); | ||
| 78 | +// expect(find.text('route'), findsOneWidget); | ||
| 79 | +// expect(find.text('push'), findsNothing); | ||
| 109 | 80 | ||
| 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 | - }); | ||
| 120 | -} | 81 | +// gesture = await tester.startGesture(const Offset(5, 300)); |
| 82 | +// await gesture.moveBy(const Offset(400, 0)); // Drag halfway. | ||
| 83 | +// await gesture.up(); | ||
| 84 | +// // Trigger the snapping animation. | ||
| 85 | +// // Since the back swipe drag was brought to >=50% of the screen, it will | ||
| 86 | +// // self snap to finish the pop transition as the gesture is lifted. | ||
| 87 | +// // | ||
| 88 | +// // This drag drop animation is 400ms when dropped exactly halfway | ||
| 89 | +// // (800 / [pixel distance remaining], see | ||
| 90 | +// // _CupertinoBackGestureController.dragEnd). It follows a curve that is very | ||
| 91 | +// // steep initially. | ||
| 92 | +// await tester.pump(); | ||
| 93 | +// expect( | ||
| 94 | +// tester.getTopLeft(find.ancestor( | ||
| 95 | +// of: find.text('route'), | ||
| 96 | +// matching: find.byType(CupertinoPageScaffold))), | ||
| 97 | +// const Offset(400, 0), | ||
| 98 | +// ); | ||
| 99 | +// // Let the dismissing snapping animation go 60%. | ||
| 100 | +// await tester.pump(const Duration(milliseconds: 240)); | ||
| 101 | +// expect( | ||
| 102 | +// tester | ||
| 103 | +// .getTopLeft(find.ancestor( | ||
| 104 | +// of: find.text('route'), | ||
| 105 | +// matching: find.byType(CupertinoPageScaffold))) | ||
| 106 | +// .dx, | ||
| 107 | +// moreOrLessEquals(798, epsilon: 1), | ||
| 108 | +// ); | ||
| 109 | + | ||
| 110 | +// // Use the navigator to push a route instead of tapping the 'push' button. | ||
| 111 | +// // The topmost route (the one that's animating away), ignores input while | ||
| 112 | +// // the pop is underway because route.navigator.userGestureInProgress. | ||
| 113 | +// Get.to(() => const CupertinoPageScaffold( | ||
| 114 | +// child: Center(child: Text('route')), | ||
| 115 | +// )); | ||
| 116 | + | ||
| 117 | +// await tester.pumpAndSettle(); | ||
| 118 | +// expect(find.text('route'), findsOneWidget); | ||
| 119 | +// expect(find.text('push'), findsNothing); | ||
| 120 | +// expect( | ||
| 121 | +// tester | ||
| 122 | +// .state<NavigatorState>(find.byType(Navigator)) | ||
| 123 | +// .userGestureInProgress, | ||
| 124 | +// false, | ||
| 125 | +// ); | ||
| 126 | +// }); | ||
| 127 | +// } |
| @@ -23,6 +23,8 @@ void main() { | @@ -23,6 +23,8 @@ void main() { | ||
| 23 | ), | 23 | ), |
| 24 | ); | 24 | ); |
| 25 | 25 | ||
| 26 | + await tester.pump(); | ||
| 27 | + | ||
| 26 | expect(Get.isSnackbarOpen, false); | 28 | expect(Get.isSnackbarOpen, false); |
| 27 | await tester.tap(find.text('Open Snackbar')); | 29 | await tester.tap(find.text('Open Snackbar')); |
| 28 | 30 | ||
| @@ -57,8 +59,12 @@ void main() { | @@ -57,8 +59,12 @@ void main() { | ||
| 57 | ), | 59 | ), |
| 58 | ); | 60 | ); |
| 59 | 61 | ||
| 62 | + await tester.pump(); | ||
| 63 | + | ||
| 60 | expect(Get.isSnackbarOpen, false); | 64 | expect(Get.isSnackbarOpen, false); |
| 61 | - await tester.tap(find.text('Open Snackbar')); | 65 | + await tester.tap( |
| 66 | + find.text('Open Snackbar'), | ||
| 67 | + ); | ||
| 62 | 68 | ||
| 63 | expect(Get.isSnackbarOpen, true); | 69 | expect(Get.isSnackbarOpen, true); |
| 64 | await tester.pump(const Duration(seconds: 1)); | 70 | await tester.pump(const Duration(seconds: 1)); |
| @@ -85,6 +91,8 @@ void main() { | @@ -85,6 +91,8 @@ void main() { | ||
| 85 | ), | 91 | ), |
| 86 | ); | 92 | ); |
| 87 | 93 | ||
| 94 | + await tester.pump(); | ||
| 95 | + | ||
| 88 | expect(Get.isSnackbarOpen, false); | 96 | expect(Get.isSnackbarOpen, false); |
| 89 | await tester.tap(find.text('Open Snackbar')); | 97 | await tester.tap(find.text('Open Snackbar')); |
| 90 | expect(Get.isSnackbarOpen, true); | 98 | expect(Get.isSnackbarOpen, true); |
| @@ -134,6 +142,8 @@ void main() { | @@ -134,6 +142,8 @@ void main() { | ||
| 134 | ), | 142 | ), |
| 135 | )); | 143 | )); |
| 136 | 144 | ||
| 145 | + await tester.pump(); | ||
| 146 | + | ||
| 137 | expect(Get.isSnackbarOpen, false); | 147 | expect(Get.isSnackbarOpen, false); |
| 138 | expect(find.text('bar1'), findsNothing); | 148 | expect(find.text('bar1'), findsNothing); |
| 139 | 149 | ||
| @@ -218,6 +228,8 @@ void main() { | @@ -218,6 +228,8 @@ void main() { | ||
| 218 | 228 | ||
| 219 | await tester.pumpWidget(GetMaterialApp(home: Scaffold())); | 229 | await tester.pumpWidget(GetMaterialApp(home: Scaffold())); |
| 220 | 230 | ||
| 231 | + await tester.pump(); | ||
| 232 | + | ||
| 221 | expect(Get.isSnackbarOpen, false); | 233 | expect(Get.isSnackbarOpen, false); |
| 222 | expect(find.text('bar1'), findsNothing); | 234 | expect(find.text('bar1'), findsNothing); |
| 223 | 235 |
| @@ -7,6 +7,8 @@ import '../../navigation/utils/wrapper.dart'; | @@ -7,6 +7,8 @@ import '../../navigation/utils/wrapper.dart'; | ||
| 7 | void main() { | 7 | void main() { |
| 8 | testWidgets("Get.defaultDialog smoke test", (tester) async { | 8 | testWidgets("Get.defaultDialog smoke test", (tester) async { |
| 9 | await tester.pumpWidget(Wrapper(child: Container())); | 9 | await tester.pumpWidget(Wrapper(child: Container())); |
| 10 | + await tester.pump(); | ||
| 11 | + | ||
| 10 | final BuildContext context = tester.element(find.byType(Container)); | 12 | final BuildContext context = tester.element(find.byType(Container)); |
| 11 | 13 | ||
| 12 | var mediaQuery = MediaQuery.of(context); | 14 | var mediaQuery = MediaQuery.of(context); |
-
Please register or login to post a comment