Showing
19 changed files
with
692 additions
and
12 deletions
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | -import 'package:get/get.dart'; | 2 | +import 'package:get/route_manager.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,12 +9,27 @@ void main() { | @@ -9,12 +9,27 @@ void main() { | ||
| 9 | runApp(MyApp()); | 9 | runApp(MyApp()); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | -class MyApp extends StatelessWidget { | ||
| 13 | - const MyApp({Key? key}) : super(key: key); | 12 | +class MyApp extends StatefulWidget { |
| 13 | + 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 | ||
| 16 | Widget build(BuildContext context) { | 28 | Widget build(BuildContext context) { |
| 17 | return GetMaterialApp.router( | 29 | return GetMaterialApp.router( |
| 30 | + routeInformationParser: routeInformationParser, | ||
| 31 | + routerDelegate: routerDelegate, | ||
| 32 | + // title: 'Router Management Example', | ||
| 18 | debugShowCheckedModeBanner: false, | 33 | debugShowCheckedModeBanner: false, |
| 19 | enableLog: true, | 34 | enableLog: true, |
| 20 | logWriterCallback: Logger.write, | 35 | logWriterCallback: Logger.write, |
| @@ -27,6 +42,8 @@ class MyApp extends StatelessWidget { | @@ -27,6 +42,8 @@ class MyApp extends StatelessWidget { | ||
| 27 | } | 42 | } |
| 28 | } | 43 | } |
| 29 | 44 | ||
| 45 | + | ||
| 46 | + | ||
| 30 | /// Nav 2 snippet | 47 | /// Nav 2 snippet |
| 31 | // void main() { | 48 | // void main() { |
| 32 | // runApp(MyApp()); | 49 | // runApp(MyApp()); |
| @@ -32,10 +32,11 @@ class CountryView extends GetView<HomeController> { | @@ -32,10 +32,11 @@ class CountryView extends GetView<HomeController> { | ||
| 32 | itemBuilder: (context, index) { | 32 | itemBuilder: (context, index) { |
| 33 | final country = controller.state.countries[index]; | 33 | final country = controller.state.countries[index]; |
| 34 | return ListTile( | 34 | return ListTile( |
| 35 | - onTap: () { | 35 | + onTap: () async { |
| 36 | //Get.rootDelegate.toNamed('/home/country'); | 36 | //Get.rootDelegate.toNamed('/home/country'); |
| 37 | - Get.rootDelegate | 37 | + final data = await GetNavigation.instance |
| 38 | .toNamed('/home/country/details?id=$index'); | 38 | .toNamed('/home/country/details?id=$index'); |
| 39 | + print(data); | ||
| 39 | }, | 40 | }, |
| 40 | trailing: CircleAvatar( | 41 | trailing: CircleAvatar( |
| 41 | backgroundImage: NetworkImage( | 42 | backgroundImage: NetworkImage( |
| @@ -2,12 +2,14 @@ import 'dart:ui'; | @@ -2,12 +2,14 @@ import 'dart:ui'; | ||
| 2 | 2 | ||
| 3 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
| 4 | import 'package:get/get.dart'; | 4 | import 'package:get/get.dart'; |
| 5 | + | ||
| 5 | import '../controllers/home_controller.dart'; | 6 | import '../controllers/home_controller.dart'; |
| 6 | 7 | ||
| 7 | class DetailsView extends GetView<HomeController> { | 8 | class DetailsView extends GetView<HomeController> { |
| 8 | @override | 9 | @override |
| 9 | Widget build(BuildContext context) { | 10 | Widget build(BuildContext context) { |
| 10 | - final parameter = Get.rootDelegate.parameters; | 11 | + final args = ModalRoute.of(context)!.settings.arguments as PageSettings; |
| 12 | + final parameter = args.params; //Get.rootDelegate.parameters; | ||
| 11 | final country = controller.getCountryById(parameter['id'] ?? ''); | 13 | final country = controller.getCountryById(parameter['id'] ?? ''); |
| 12 | return Container( | 14 | return Container( |
| 13 | decoration: BoxDecoration( | 15 | decoration: BoxDecoration( |
| @@ -76,6 +78,11 @@ class DetailsView extends GetView<HomeController> { | @@ -76,6 +78,11 @@ class DetailsView extends GetView<HomeController> { | ||
| 76 | '${country.totalRecovered}', | 78 | '${country.totalRecovered}', |
| 77 | style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold), | 79 | style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold), |
| 78 | ), | 80 | ), |
| 81 | + TextButton( | ||
| 82 | + onPressed: () { | ||
| 83 | + GetNavigation.instance.back('djsoidjsoidj'); | ||
| 84 | + }, | ||
| 85 | + child: Text('back')) | ||
| 79 | ], | 86 | ], |
| 80 | )), | 87 | )), |
| 81 | ), | 88 | ), |
| @@ -75,7 +75,8 @@ class HomeView extends GetView<HomeController> { | @@ -75,7 +75,8 @@ class HomeView extends GetView<HomeController> { | ||
| 75 | shape: StadiumBorder(), | 75 | shape: StadiumBorder(), |
| 76 | ), | 76 | ), |
| 77 | onPressed: () async { | 77 | onPressed: () async { |
| 78 | - await Get.rootDelegate.toNamed('/home/country'); | 78 | + //await Navigation Get.rootDelegate.toNamed('/home/country'); |
| 79 | + GetNavigation.instance.toNamed('/home/country'); | ||
| 79 | }, | 80 | }, |
| 80 | child: Text( | 81 | child: Text( |
| 81 | 'fetch_country'.tr, | 82 | 'fetch_country'.tr, |
| @@ -7,6 +7,7 @@ export 'src/nav2/get_nav_config.dart'; | @@ -7,6 +7,7 @@ export 'src/nav2/get_nav_config.dart'; | ||
| 7 | export 'src/nav2/get_navigator.dart'; | 7 | export 'src/nav2/get_navigator.dart'; |
| 8 | export 'src/nav2/get_router_delegate.dart'; | 8 | export 'src/nav2/get_router_delegate.dart'; |
| 9 | export 'src/nav2/router_outlet.dart'; | 9 | export 'src/nav2/router_outlet.dart'; |
| 10 | +export 'src/nav3/get_navigation/index.dart'; | ||
| 10 | export 'src/root/get_cupertino_app.dart'; | 11 | export 'src/root/get_cupertino_app.dart'; |
| 11 | export 'src/root/get_material_app.dart'; | 12 | export 'src/root/get_material_app.dart'; |
| 12 | export 'src/root/internacionalization.dart'; | 13 | export 'src/root/internacionalization.dart'; |
| @@ -14,7 +14,7 @@ import 'root/parse_route.dart'; | @@ -14,7 +14,7 @@ import 'root/parse_route.dart'; | ||
| 14 | /// It replaces the Flutter Navigator, but needs no context. | 14 | /// It replaces the Flutter Navigator, but needs no context. |
| 15 | /// You can to use navigator.push(YourRoute()) rather | 15 | /// You can to use navigator.push(YourRoute()) rather |
| 16 | /// Navigator.push(context, YourRoute()); | 16 | /// Navigator.push(context, YourRoute()); |
| 17 | -NavigatorState? get navigator => GetNavigation(Get).key.currentState; | 17 | +NavigatorState? get navigator => GetNavigationExt(Get).key.currentState; |
| 18 | 18 | ||
| 19 | extension ExtensionBottomSheet on GetInterface { | 19 | extension ExtensionBottomSheet on GetInterface { |
| 20 | Future<T?> bottomSheet<T>( | 20 | Future<T?> bottomSheet<T>( |
| @@ -474,7 +474,7 @@ extension ExtensionSnackbar on GetInterface { | @@ -474,7 +474,7 @@ extension ExtensionSnackbar on GetInterface { | ||
| 474 | } | 474 | } |
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | -extension GetNavigation on GetInterface { | 477 | +extension GetNavigationExt on GetInterface { |
| 478 | /// **Navigation.push()** shortcut.<br><br> | 478 | /// **Navigation.push()** shortcut.<br><br> |
| 479 | /// | 479 | /// |
| 480 | /// Pushes a new `page` to the stack | 480 | /// Pushes a new `page` to the stack |
| @@ -1280,10 +1280,15 @@ extension NavTwoExt on GetInterface { | @@ -1280,10 +1280,15 @@ extension NavTwoExt on GetInterface { | ||
| 1280 | static late final _routeTree = ParseRouteTree(routes: []); | 1280 | static late final _routeTree = ParseRouteTree(routes: []); |
| 1281 | 1281 | ||
| 1282 | ParseRouteTree get routeTree => _routeTree; | 1282 | ParseRouteTree get routeTree => _routeTree; |
| 1283 | + | ||
| 1283 | void addPage(GetPage getPage) { | 1284 | void addPage(GetPage getPage) { |
| 1284 | routeTree.addRoute(getPage); | 1285 | routeTree.addRoute(getPage); |
| 1285 | } | 1286 | } |
| 1286 | 1287 | ||
| 1288 | + void removePage(GetPage getPage) { | ||
| 1289 | + routeTree.removeRoute(getPage); | ||
| 1290 | + } | ||
| 1291 | + | ||
| 1287 | /// Casts the stored router delegate to a desired type | 1292 | /// Casts the stored router delegate to a desired type |
| 1288 | TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => | 1293 | TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => |
| 1289 | routerDelegate as TDelegate?; | 1294 | routerDelegate as TDelegate?; |
| 1 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; |
| 2 | + | ||
| 2 | import '../routes/default_route.dart'; | 3 | import '../routes/default_route.dart'; |
| 3 | import '../routes/get_route.dart'; | 4 | import '../routes/get_route.dart'; |
| 4 | 5 | ||
| @@ -11,6 +12,7 @@ class GetNavigator extends Navigator { | @@ -11,6 +12,7 @@ class GetNavigator extends Navigator { | ||
| 11 | bool reportsRouteUpdateToEngine = false, | 12 | bool reportsRouteUpdateToEngine = false, |
| 12 | TransitionDelegate? transitionDelegate, | 13 | TransitionDelegate? transitionDelegate, |
| 13 | String? initialRoute, | 14 | String? initialRoute, |
| 15 | + String? restorationScopeId, | ||
| 14 | }) : super( | 16 | }) : super( |
| 15 | //keys should be optional | 17 | //keys should be optional |
| 16 | key: key, | 18 | key: key, |
| @@ -35,6 +37,7 @@ class GetNavigator extends Navigator { | @@ -35,6 +37,7 @@ class GetNavigator extends Navigator { | ||
| 35 | } | 37 | } |
| 36 | }, | 38 | }, |
| 37 | reportsRouteUpdateToEngine: reportsRouteUpdateToEngine, | 39 | reportsRouteUpdateToEngine: reportsRouteUpdateToEngine, |
| 40 | + restorationScopeId: restorationScopeId, | ||
| 38 | pages: pages, | 41 | pages: pages, |
| 39 | observers: [ | 42 | observers: [ |
| 40 | // GetObserver(), | 43 | // GetObserver(), |
| @@ -52,6 +55,7 @@ class GetNavigator extends Navigator { | @@ -52,6 +55,7 @@ class GetNavigator extends Navigator { | ||
| 52 | bool reportsRouteUpdateToEngine = false, | 55 | bool reportsRouteUpdateToEngine = false, |
| 53 | TransitionDelegate? transitionDelegate, | 56 | TransitionDelegate? transitionDelegate, |
| 54 | String? initialRoute, | 57 | String? initialRoute, |
| 58 | + String? restorationScopeId, | ||
| 55 | }) : super( | 59 | }) : super( |
| 56 | //keys should be optional | 60 | //keys should be optional |
| 57 | key: key, | 61 | key: key, |
| @@ -65,6 +69,7 @@ class GetNavigator extends Navigator { | @@ -65,6 +69,7 @@ class GetNavigator extends Navigator { | ||
| 65 | return true; | 69 | return true; |
| 66 | }, | 70 | }, |
| 67 | reportsRouteUpdateToEngine: reportsRouteUpdateToEngine, | 71 | reportsRouteUpdateToEngine: reportsRouteUpdateToEngine, |
| 72 | + restorationScopeId: restorationScopeId, | ||
| 68 | pages: pages, | 73 | pages: pages, |
| 69 | observers: [ | 74 | observers: [ |
| 70 | // GetObserver(), | 75 | // GetObserver(), |
| 1 | +import 'dart:async'; | ||
| 2 | + | ||
| 3 | +import 'package:flutter/material.dart'; | ||
| 4 | + | ||
| 5 | +import '../../../../get.dart'; | ||
| 6 | +import '../../../../get_state_manager/src/simple/list_notifier.dart'; | ||
| 7 | +import '../url_strategy/url_strategy.dart'; | ||
| 8 | + | ||
| 9 | +class GetNavigation extends RouterDelegate<PageSettings> | ||
| 10 | + with | ||
| 11 | + ListNotifierSingleMixin, | ||
| 12 | + PopNavigatorRouterDelegateMixin<PageSettings>, | ||
| 13 | + IGetNavigation { | ||
| 14 | + final _activePages = <GetPage>[]; | ||
| 15 | + final GetPage _unknownPage; | ||
| 16 | + final List<NavigatorObserver>? navigatorObservers; | ||
| 17 | + final String? restorationScopeId; | ||
| 18 | + @override | ||
| 19 | + final navigatorKey = GlobalKey<NavigatorState>(); | ||
| 20 | + | ||
| 21 | + static late final GetNavigation instance; | ||
| 22 | + | ||
| 23 | + @override | ||
| 24 | + Future<void> setInitialRoutePath(PageSettings configuration) async { | ||
| 25 | + setNewRoutePath(configuration); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + GetNavigation({ | ||
| 29 | + String? initialPage, | ||
| 30 | + required List<GetPage> pages, | ||
| 31 | + GetPage? unknownPage, | ||
| 32 | + this.navigatorObservers, | ||
| 33 | + this.restorationScopeId, | ||
| 34 | + bool showHashOnUrl = false, | ||
| 35 | + }) : _unknownPage = unknownPage ?? | ||
| 36 | + GetPage( | ||
| 37 | + name: '/404', | ||
| 38 | + page: () => | ||
| 39 | + Scaffold(body: Center(child: Text('Route not found'))), | ||
| 40 | + ) { | ||
| 41 | + if (!showHashOnUrl && GetPlatform.isWeb) setUrlStrategy(); | ||
| 42 | + Get.addPages(pages); | ||
| 43 | + Get.addPage(_unknownPage); | ||
| 44 | + // setNewRoutePath(_buildPageSettings(_initialPage)); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + PageSettings _buildPageSettings(String page, [Object? data]) { | ||
| 48 | + var uri = Uri.parse(page); | ||
| 49 | + return PageSettings(uri, data); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @protected | ||
| 53 | + GetPage<T>? _getPage<T>(PageSettings arguments) { | ||
| 54 | + var page = arguments.uri.path; | ||
| 55 | + final parameters = arguments.params; | ||
| 56 | + if (parameters.isNotEmpty) { | ||
| 57 | + final uri = Uri(path: page, queryParameters: parameters); | ||
| 58 | + page = uri.toString(); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + final decoder = Get.routeTree.matchRoute(page, arguments: arguments); | ||
| 62 | + decoder.replaceArguments(arguments); | ||
| 63 | + //decoder.replaceParameters(arguments) | ||
| 64 | + | ||
| 65 | + return decoder.route as GetPage<T>?; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @protected | ||
| 69 | + GetPage<T> _buildSettings<T>(GetPage<T> page, PageSettings arguments) { | ||
| 70 | + return page.copy( | ||
| 71 | + completer: _activePages.isEmpty ? null : Completer(), | ||
| 72 | + arguments: arguments); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + Future<T?> _push<T>(PageSettings arguments, GetPage<T> page) async { | ||
| 76 | + final activePage = _buildSettings<T>(page, arguments); | ||
| 77 | + final onStackPage = _activePages | ||
| 78 | + .firstWhereOrNull((element) => element.key == activePage.key); | ||
| 79 | + | ||
| 80 | + /// There are no duplicate routes in the stack | ||
| 81 | + if (onStackPage == null) { | ||
| 82 | + _activePages.add(activePage); | ||
| 83 | + } else { | ||
| 84 | + /// There are duplicate routes, reorder | ||
| 85 | + _activePages.remove(onStackPage); | ||
| 86 | + _activePages.add(onStackPage); | ||
| 87 | + } | ||
| 88 | + refresh(); | ||
| 89 | + return activePage.completer?.future; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + Future<T?> _replace<T>(PageSettings arguments, GetPage<T> page) async { | ||
| 93 | + final index = _activePages.length > 1 ? _activePages.length - 1 : 0; | ||
| 94 | + final activePage = _buildSettings<T>(page, arguments); | ||
| 95 | + Get.addPage(activePage); | ||
| 96 | + _activePages[index] = activePage; | ||
| 97 | + | ||
| 98 | + refresh(); | ||
| 99 | + final result = await activePage.completer?.future; | ||
| 100 | + Get.removePage(activePage); | ||
| 101 | + | ||
| 102 | + return result; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + /// Takes a route [name] String generated by [to], [off], [offAll] | ||
| 106 | + /// (and similar context navigation methods), cleans the extra chars and | ||
| 107 | + /// accommodates the format. | ||
| 108 | + /// TODO: check for a more "appealing" URL naming convention. | ||
| 109 | + /// `() => MyHomeScreenView` becomes `/my-home-screen-view`. | ||
| 110 | + String _cleanRouteName(String name) { | ||
| 111 | + name = name.replaceAll('() => ', ''); | ||
| 112 | + | ||
| 113 | + /// uncommonent for URL styling. | ||
| 114 | + // name = name.paramCase!; | ||
| 115 | + if (!name.startsWith('/')) { | ||
| 116 | + name = '/$name'; | ||
| 117 | + } | ||
| 118 | + return Uri.tryParse(name)?.toString() ?? name; | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + @protected | ||
| 122 | + void _popWithResult<T>([T? result]) { | ||
| 123 | + final completer = _activePages.removeLast().completer; | ||
| 124 | + if (completer?.isCompleted == false) completer!.complete(result); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + @override | ||
| 128 | + Future<T?> toNamed<T>(String page, [Object? data]) async { | ||
| 129 | + final arguments = _buildPageSettings(page, data); | ||
| 130 | + final route = _getPage<T>(arguments); | ||
| 131 | + if (route != null) { | ||
| 132 | + return _push<T>(arguments, route); | ||
| 133 | + } | ||
| 134 | + throw 'Route $page not registered'; | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + @override | ||
| 138 | + Future<T?> to<T>( | ||
| 139 | + Widget Function() page, { | ||
| 140 | + bool? opaque, | ||
| 141 | + Transition? transition, | ||
| 142 | + Curve? curve, | ||
| 143 | + Duration? duration, | ||
| 144 | + int? id, | ||
| 145 | + String? routeName, | ||
| 146 | + bool fullscreenDialog = false, | ||
| 147 | + dynamic arguments, | ||
| 148 | + Binding? binding, | ||
| 149 | + bool preventDuplicates = true, | ||
| 150 | + bool? popGesture, | ||
| 151 | + bool showCupertinoParallax = true, | ||
| 152 | + double Function(BuildContext context)? gestureWidth, | ||
| 153 | + }) async { | ||
| 154 | + routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 155 | + final route = GetPage<T>( | ||
| 156 | + name: routeName, | ||
| 157 | + opaque: opaque ?? true, | ||
| 158 | + page: page, | ||
| 159 | + gestureWidth: gestureWidth, | ||
| 160 | + showCupertinoParallax: showCupertinoParallax, | ||
| 161 | + popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 162 | + transition: transition ?? Get.defaultTransition, | ||
| 163 | + curve: curve ?? Get.defaultTransitionCurve, | ||
| 164 | + fullscreenDialog: fullscreenDialog, | ||
| 165 | + binding: binding, | ||
| 166 | + transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 167 | + ); | ||
| 168 | + Get.addPage(route); | ||
| 169 | + final args = _buildPageSettings(routeName, arguments); | ||
| 170 | + final result = await _push<T>(args, route); | ||
| 171 | + Get.removePage(route); | ||
| 172 | + return result; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + @override | ||
| 176 | + Future<T?> off<T>( | ||
| 177 | + Widget Function() page, { | ||
| 178 | + bool? opaque, | ||
| 179 | + Transition? transition, | ||
| 180 | + Curve? curve, | ||
| 181 | + Duration? duration, | ||
| 182 | + int? id, | ||
| 183 | + String? routeName, | ||
| 184 | + bool fullscreenDialog = false, | ||
| 185 | + dynamic arguments, | ||
| 186 | + Binding? binding, | ||
| 187 | + bool preventDuplicates = true, | ||
| 188 | + bool? popGesture, | ||
| 189 | + bool showCupertinoParallax = true, | ||
| 190 | + double Function(BuildContext context)? gestureWidth, | ||
| 191 | + }) async { | ||
| 192 | + routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 193 | + final route = GetPage<T>( | ||
| 194 | + name: routeName, | ||
| 195 | + opaque: opaque ?? true, | ||
| 196 | + page: page, | ||
| 197 | + gestureWidth: gestureWidth, | ||
| 198 | + showCupertinoParallax: showCupertinoParallax, | ||
| 199 | + popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 200 | + transition: transition ?? Get.defaultTransition, | ||
| 201 | + curve: curve ?? Get.defaultTransitionCurve, | ||
| 202 | + fullscreenDialog: fullscreenDialog, | ||
| 203 | + binding: binding, | ||
| 204 | + transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 205 | + ); | ||
| 206 | + | ||
| 207 | + final args = _buildPageSettings(routeName, arguments); | ||
| 208 | + return _replace(args, route); | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + @override | ||
| 212 | + Future<T?>? offAll<T>( | ||
| 213 | + Widget Function() page, { | ||
| 214 | + bool Function(GetPage route)? predicate, | ||
| 215 | + bool opaque = true, | ||
| 216 | + bool? popGesture, | ||
| 217 | + int? id, | ||
| 218 | + String? routeName, | ||
| 219 | + dynamic arguments, | ||
| 220 | + Binding? binding, | ||
| 221 | + bool fullscreenDialog = false, | ||
| 222 | + Transition? transition, | ||
| 223 | + Curve? curve, | ||
| 224 | + Duration? duration, | ||
| 225 | + bool showCupertinoParallax = true, | ||
| 226 | + double Function(BuildContext context)? gestureWidth, | ||
| 227 | + }) async { | ||
| 228 | + routeName = _cleanRouteName("/${page.runtimeType}"); | ||
| 229 | + final route = GetPage<T>( | ||
| 230 | + name: routeName, | ||
| 231 | + opaque: opaque, | ||
| 232 | + page: page, | ||
| 233 | + gestureWidth: gestureWidth, | ||
| 234 | + showCupertinoParallax: showCupertinoParallax, | ||
| 235 | + popGesture: popGesture ?? Get.defaultPopGesture, | ||
| 236 | + transition: transition ?? Get.defaultTransition, | ||
| 237 | + curve: curve ?? Get.defaultTransitionCurve, | ||
| 238 | + fullscreenDialog: fullscreenDialog, | ||
| 239 | + binding: binding, | ||
| 240 | + transitionDuration: duration ?? Get.defaultTransitionDuration, | ||
| 241 | + ); | ||
| 242 | + | ||
| 243 | + final args = _buildPageSettings(routeName, arguments); | ||
| 244 | + | ||
| 245 | + final newPredicate = predicate ?? (route) => false; | ||
| 246 | + | ||
| 247 | + while (_activePages.length > 1 && !newPredicate(_activePages.last)) { | ||
| 248 | + _popWithResult(); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + return _push(args, route); | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + @override | ||
| 255 | + Future<T?>? offAllNamed<T>( | ||
| 256 | + String page, { | ||
| 257 | + bool Function(GetPage route)? predicate, | ||
| 258 | + dynamic arguments, | ||
| 259 | + int? id, | ||
| 260 | + Map<String, String>? parameters, | ||
| 261 | + }) async { | ||
| 262 | + final args = _buildPageSettings(page, arguments); | ||
| 263 | + final route = _getPage<T>(args); | ||
| 264 | + if (route == null) return null; | ||
| 265 | + | ||
| 266 | + // final newPredicate = predicate ?? (route) => false; | ||
| 267 | + | ||
| 268 | + while (_activePages.length > 1) { | ||
| 269 | + _activePages.removeLast(); | ||
| 270 | + removeLastHistory(null); | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + return _replace(args, route); | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + @override | ||
| 277 | + Future<T?> offNamed<T>(String page, [Object? data]) async { | ||
| 278 | + final arguments = _buildPageSettings(page, data); | ||
| 279 | + final route = _getPage<T>(arguments); | ||
| 280 | + if (route == null) return null; | ||
| 281 | + _popWithResult(); | ||
| 282 | + return _push<T>(arguments, route); | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + @override | ||
| 286 | + Future<T?> toAndOffUntil<T>( | ||
| 287 | + String page, | ||
| 288 | + bool Function(GetPage) predicate, [ | ||
| 289 | + Object? data, | ||
| 290 | + ]) async { | ||
| 291 | + final arguments = _buildPageSettings(page, data); | ||
| 292 | + | ||
| 293 | + final route = _getPage<T>(arguments); | ||
| 294 | + | ||
| 295 | + if (route == null) return null; | ||
| 296 | + | ||
| 297 | + while (_activePages.isNotEmpty && !predicate(_activePages.last)) { | ||
| 298 | + _popWithResult(); | ||
| 299 | + } | ||
| 300 | + | ||
| 301 | + return _push<T>(arguments, route); | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + @override | ||
| 305 | + void back<T>([T? result]) { | ||
| 306 | + _checkIfCanBack(); | ||
| 307 | + _popWithResult<T>(result); | ||
| 308 | + refresh(); | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + void _checkIfCanBack() { | ||
| 312 | + assert(() { | ||
| 313 | + if (!canBack) { | ||
| 314 | + final last = _activePages.last; | ||
| 315 | + final name = last.name; | ||
| 316 | + throw 'The page $name cannot be popped'; | ||
| 317 | + } | ||
| 318 | + return true; | ||
| 319 | + }()); | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + @override | ||
| 323 | + Future<R?> backAndtoNamed<T, R>(String page, | ||
| 324 | + {T? result, Object? data}) async { | ||
| 325 | + final arguments = _buildPageSettings(page, data); | ||
| 326 | + final route = _getPage<R>(arguments); | ||
| 327 | + if (route == null) return null; | ||
| 328 | + _popWithResult<T>(result); | ||
| 329 | + return _push<R>(arguments, route); | ||
| 330 | + } | ||
| 331 | + | ||
| 332 | + @override | ||
| 333 | + void backUntil(bool Function(GetPage) predicate) { | ||
| 334 | + while (canBack && !predicate(_activePages.last)) { | ||
| 335 | + _popWithResult(); | ||
| 336 | + } | ||
| 337 | + | ||
| 338 | + refresh(); | ||
| 339 | + } | ||
| 340 | + | ||
| 341 | + @override | ||
| 342 | + void goToUnknownPage([bool clearPages = false]) { | ||
| 343 | + if (clearPages) _activePages.clear(); | ||
| 344 | + final page = | ||
| 345 | + _buildSettings(_unknownPage, _buildPageSettings(_unknownPage.name)); | ||
| 346 | + _activePages.add(page); | ||
| 347 | + refresh(); | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + @override | ||
| 351 | + bool get canBack => _activePages.length > 1; | ||
| 352 | + | ||
| 353 | + bool _onPopPage(Route route, result) { | ||
| 354 | + if (!route.didPop(result)) return false; | ||
| 355 | + _popWithResult(result); | ||
| 356 | + refresh(); | ||
| 357 | + return true; | ||
| 358 | + } | ||
| 359 | + | ||
| 360 | + @override | ||
| 361 | + Widget build(BuildContext context) { | ||
| 362 | + if (_activePages.isEmpty) return SizedBox.shrink(); | ||
| 363 | + return GetNavigator( | ||
| 364 | + key: navigatorKey, | ||
| 365 | + restorationScopeId: restorationScopeId, | ||
| 366 | + observers: navigatorObservers, | ||
| 367 | + pages: List.unmodifiable(_activePages), | ||
| 368 | + onPopPage: _onPopPage, | ||
| 369 | + ); | ||
| 370 | + } | ||
| 371 | + | ||
| 372 | + @override | ||
| 373 | + Future<void> setNewRoutePath(PageSettings configuration) async { | ||
| 374 | + // if (_activePages.isEmpty) return; | ||
| 375 | + final page = _getPage(configuration); | ||
| 376 | + if (page == null) { | ||
| 377 | + goToUnknownPage(); | ||
| 378 | + return; | ||
| 379 | + } else { | ||
| 380 | + _push(configuration, page); | ||
| 381 | + } | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + @override | ||
| 385 | + PageSettings? get currentConfiguration { | ||
| 386 | + if (_activePages.isEmpty) { | ||
| 387 | + return null; | ||
| 388 | + } | ||
| 389 | + return _activePages.last.arguments as PageSettings; | ||
| 390 | + } | ||
| 391 | +} |
| 1 | +import 'package:flutter/widgets.dart'; | ||
| 2 | + | ||
| 3 | +import '../../../../get_state_manager/src/simple/get_state.dart'; | ||
| 4 | +import '../../routes/get_route.dart'; | ||
| 5 | +import '../../routes/transitions_type.dart'; | ||
| 6 | + | ||
| 7 | +mixin IGetNavigation { | ||
| 8 | + Future<T?> to<T>( | ||
| 9 | + Widget Function() page, { | ||
| 10 | + bool? opaque, | ||
| 11 | + Transition? transition, | ||
| 12 | + Curve? curve, | ||
| 13 | + Duration? duration, | ||
| 14 | + int? id, | ||
| 15 | + String? routeName, | ||
| 16 | + bool fullscreenDialog = false, | ||
| 17 | + dynamic arguments, | ||
| 18 | + Binding? binding, | ||
| 19 | + bool preventDuplicates = true, | ||
| 20 | + bool? popGesture, | ||
| 21 | + bool showCupertinoParallax = true, | ||
| 22 | + double Function(BuildContext context)? gestureWidth, | ||
| 23 | + }); | ||
| 24 | + | ||
| 25 | + Future<T?> off<T>( | ||
| 26 | + Widget Function() page, { | ||
| 27 | + bool? opaque, | ||
| 28 | + Transition? transition, | ||
| 29 | + Curve? curve, | ||
| 30 | + Duration? duration, | ||
| 31 | + int? id, | ||
| 32 | + String? routeName, | ||
| 33 | + bool fullscreenDialog = false, | ||
| 34 | + dynamic arguments, | ||
| 35 | + Binding? binding, | ||
| 36 | + bool preventDuplicates = true, | ||
| 37 | + bool? popGesture, | ||
| 38 | + bool showCupertinoParallax = true, | ||
| 39 | + double Function(BuildContext context)? gestureWidth, | ||
| 40 | + }); | ||
| 41 | + | ||
| 42 | + Future<T?>? offAll<T>( | ||
| 43 | + Widget Function() page, { | ||
| 44 | + bool Function(GetPage route)? predicate, | ||
| 45 | + bool opaque = true, | ||
| 46 | + bool? popGesture, | ||
| 47 | + int? id, | ||
| 48 | + String? routeName, | ||
| 49 | + dynamic arguments, | ||
| 50 | + Binding? binding, | ||
| 51 | + bool fullscreenDialog = false, | ||
| 52 | + Transition? transition, | ||
| 53 | + Curve? curve, | ||
| 54 | + Duration? duration, | ||
| 55 | + bool showCupertinoParallax = true, | ||
| 56 | + double Function(BuildContext context)? gestureWidth, | ||
| 57 | + }); | ||
| 58 | + | ||
| 59 | + Future<T?> toNamed<T>(String page, [Object? data]); | ||
| 60 | + | ||
| 61 | + Future<T?> offNamed<T>(String page, [Object? data]); | ||
| 62 | + | ||
| 63 | + Future<T?>? offAllNamed<T>( | ||
| 64 | + String newRouteName, { | ||
| 65 | + bool Function(GetPage route)? predicate, | ||
| 66 | + dynamic arguments, | ||
| 67 | + int? id, | ||
| 68 | + Map<String, String>? parameters, | ||
| 69 | + }); | ||
| 70 | + | ||
| 71 | + Future<T?> toAndOffUntil<T>( | ||
| 72 | + String page, | ||
| 73 | + bool Function(GetPage) predicate, [ | ||
| 74 | + Object? data, | ||
| 75 | + ]); | ||
| 76 | + | ||
| 77 | + void back<T>([T? result]); | ||
| 78 | + | ||
| 79 | + Future<R?> backAndtoNamed<T, R>(String page, {T? result, Object? data}); | ||
| 80 | + | ||
| 81 | + void backUntil(bool Function(GetPage) predicate); | ||
| 82 | + | ||
| 83 | + void goToUnknownPage([bool clearPages = true]); | ||
| 84 | + | ||
| 85 | + bool get canBack; | ||
| 86 | +} |
| 1 | +import 'package:flutter/foundation.dart'; | ||
| 2 | +import 'package:flutter/widgets.dart'; | ||
| 3 | + | ||
| 4 | +import '../../../../get.dart'; | ||
| 5 | + | ||
| 6 | +class NewGetInformationParser extends RouteInformationParser<PageSettings> { | ||
| 7 | + final String initialRoute; | ||
| 8 | + | ||
| 9 | + NewGetInformationParser({ | ||
| 10 | + required this.initialRoute, | ||
| 11 | + }) { | ||
| 12 | + Get.log('GetInformationParser is created !'); | ||
| 13 | + } | ||
| 14 | + @override | ||
| 15 | + SynchronousFuture<PageSettings> 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 | + PageSettings( | ||
| 33 | + Uri.parse(location!), | ||
| 34 | + ), | ||
| 35 | + ); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @override | ||
| 39 | + RouteInformation restoreRouteInformation(PageSettings config) { | ||
| 40 | + return RouteInformation( | ||
| 41 | + location: config.name, | ||
| 42 | + state: null, | ||
| 43 | + ); | ||
| 44 | + } | ||
| 45 | +} |
| 1 | +import 'package:flutter/widgets.dart'; | ||
| 2 | + | ||
| 3 | +extension PageArgExt on BuildContext { | ||
| 4 | + PageSettings get arguments { | ||
| 5 | + return ModalRoute.of(this)!.settings.arguments as PageSettings; | ||
| 6 | + } | ||
| 7 | +} | ||
| 8 | + | ||
| 9 | +class PageSettings extends RouteSettings { | ||
| 10 | + PageSettings( | ||
| 11 | + this.uri, [ | ||
| 12 | + this.arguments, | ||
| 13 | + ]); | ||
| 14 | + | ||
| 15 | + @override | ||
| 16 | + String get name => '$uri'; | ||
| 17 | + | ||
| 18 | + @override | ||
| 19 | + late final Object? arguments; | ||
| 20 | + | ||
| 21 | + final Uri uri; | ||
| 22 | + | ||
| 23 | + final params = <String, String>{}; | ||
| 24 | + | ||
| 25 | + String get path => uri.path; | ||
| 26 | + | ||
| 27 | + List<String> get paths => uri.pathSegments; | ||
| 28 | + | ||
| 29 | + Map<String, String> get query => uri.queryParameters; | ||
| 30 | + | ||
| 31 | + Map<String, List<String>> get queries => uri.queryParametersAll; | ||
| 32 | + | ||
| 33 | + @override | ||
| 34 | + String toString() => name; | ||
| 35 | + | ||
| 36 | + PageSettings copy({ | ||
| 37 | + Uri? uri, | ||
| 38 | + Object? arguments, | ||
| 39 | + }) { | ||
| 40 | + return PageSettings( | ||
| 41 | + uri ?? this.uri, | ||
| 42 | + arguments ?? this.arguments, | ||
| 43 | + ); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + @override | ||
| 47 | + bool operator ==(Object other) { | ||
| 48 | + if (identical(this, other)) return true; | ||
| 49 | + | ||
| 50 | + return other is PageSettings && | ||
| 51 | + other.uri == uri && | ||
| 52 | + other.arguments == arguments; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @override | ||
| 56 | + int get hashCode => uri.hashCode ^ arguments.hashCode; | ||
| 57 | +} |
| 1 | import '../../get_navigation.dart'; | 1 | import '../../get_navigation.dart'; |
| 2 | 2 | ||
| 3 | -class RouteDecoder { | ||
| 4 | - final List<GetPage> treeBranch; | ||
| 5 | - GetPage? get route => treeBranch.isEmpty ? null : treeBranch.last; | 3 | +class RouteDecoder<T> { |
| 4 | + final List<GetPage<T>> treeBranch; | ||
| 5 | + GetPage<T>? get route => treeBranch.isEmpty ? null : treeBranch.last; | ||
| 6 | final Map<String, String> parameters; | 6 | final Map<String, String> parameters; |
| 7 | final Object? arguments; | 7 | final Object? arguments; |
| 8 | const RouteDecoder( | 8 | const RouteDecoder( |
| @@ -98,6 +98,19 @@ class ParseRouteTree { | @@ -98,6 +98,19 @@ class ParseRouteTree { | ||
| 98 | } | 98 | } |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | + void removeRoutes(List<GetPage> getPages) { | ||
| 102 | + for (final route in getPages) { | ||
| 103 | + removeRoute(route); | ||
| 104 | + } | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + void removeRoute(GetPage route) { | ||
| 108 | + routes.remove(route); | ||
| 109 | + for (var page in _flattenPage(route)) { | ||
| 110 | + removeRoute(page); | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + | ||
| 101 | void addRoute(GetPage route) { | 114 | void addRoute(GetPage route) { |
| 102 | routes.add(route); | 115 | routes.add(route); |
| 103 | 116 |
| 1 | +import 'dart:async'; | ||
| 2 | + | ||
| 1 | import 'package:flutter/cupertino.dart'; | 3 | import 'package:flutter/cupertino.dart'; |
| 2 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
| 3 | 5 | ||
| @@ -24,6 +26,7 @@ class GetPage<T> extends Page<T> { | @@ -24,6 +26,7 @@ class GetPage<T> extends Page<T> { | ||
| 24 | final Duration? transitionDuration; | 26 | final Duration? transitionDuration; |
| 25 | final bool fullscreenDialog; | 27 | final bool fullscreenDialog; |
| 26 | final bool preventDuplicates; | 28 | final bool preventDuplicates; |
| 29 | + final Completer<T?>? completer; | ||
| 27 | // @override | 30 | // @override |
| 28 | // final LocalKey? key; | 31 | // final LocalKey? key; |
| 29 | 32 | ||
| @@ -67,6 +70,7 @@ class GetPage<T> extends Page<T> { | @@ -67,6 +70,7 @@ class GetPage<T> extends Page<T> { | ||
| 67 | this.arguments, | 70 | this.arguments, |
| 68 | this.showCupertinoParallax = true, | 71 | this.showCupertinoParallax = true, |
| 69 | this.preventDuplicates = true, | 72 | this.preventDuplicates = true, |
| 73 | + this.completer, | ||
| 70 | }) : path = _nameToRegex(name), | 74 | }) : path = _nameToRegex(name), |
| 71 | assert(name.startsWith('/'), | 75 | assert(name.startsWith('/'), |
| 72 | 'It is necessary to start route name [$name] with a slash: /$name'), | 76 | 'It is necessary to start route name [$name] with a slash: /$name'), |
| @@ -102,6 +106,7 @@ class GetPage<T> extends Page<T> { | @@ -102,6 +106,7 @@ class GetPage<T> extends Page<T> { | ||
| 102 | bool? participatesInRootNavigator, | 106 | bool? participatesInRootNavigator, |
| 103 | Object? arguments, | 107 | Object? arguments, |
| 104 | bool? showCupertinoParallax, | 108 | bool? showCupertinoParallax, |
| 109 | + Completer<T?>? completer, | ||
| 105 | }) { | 110 | }) { |
| 106 | return GetPage( | 111 | return GetPage( |
| 107 | participatesInRootNavigator: | 112 | participatesInRootNavigator: |
| @@ -129,6 +134,7 @@ class GetPage<T> extends Page<T> { | @@ -129,6 +134,7 @@ class GetPage<T> extends Page<T> { | ||
| 129 | arguments: arguments ?? this.arguments, | 134 | arguments: arguments ?? this.arguments, |
| 130 | showCupertinoParallax: | 135 | showCupertinoParallax: |
| 131 | showCupertinoParallax ?? this.showCupertinoParallax, | 136 | showCupertinoParallax ?? this.showCupertinoParallax, |
| 137 | + completer: completer ?? this.completer, | ||
| 132 | ); | 138 | ); |
| 133 | } | 139 | } |
| 134 | 140 | ||
| @@ -164,6 +170,17 @@ class GetPage<T> extends Page<T> { | @@ -164,6 +170,17 @@ class GetPage<T> extends Page<T> { | ||
| 164 | 170 | ||
| 165 | return PathDecoded(RegExp('^$stringPath\$'), keys); | 171 | return PathDecoded(RegExp('^$stringPath\$'), keys); |
| 166 | } | 172 | } |
| 173 | + | ||
| 174 | + @override | ||
| 175 | + bool operator ==(Object other) { | ||
| 176 | + if (identical(this, other)) return true; | ||
| 177 | + return other is GetPage<T> && other.key == key; | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + @override | ||
| 181 | + int get hashCode { | ||
| 182 | + return key.hashCode; | ||
| 183 | + } | ||
| 167 | } | 184 | } |
| 168 | 185 | ||
| 169 | @immutable | 186 | @immutable |
| @@ -73,8 +73,11 @@ mixin StateMixin<T> on ListNotifier { | @@ -73,8 +73,11 @@ mixin StateMixin<T> on ListNotifier { | ||
| 73 | } else { | 73 | } else { |
| 74 | status = GetState<T>.success(newValue); | 74 | status = GetState<T>.success(newValue); |
| 75 | } | 75 | } |
| 76 | + | ||
| 77 | + refresh(); | ||
| 76 | }, onError: (err) { | 78 | }, onError: (err) { |
| 77 | status = GetState.error(errorMessage ?? err.toString()); | 79 | status = GetState.error(errorMessage ?? err.toString()); |
| 80 | + refresh(); | ||
| 78 | }); | 81 | }); |
| 79 | } | 82 | } |
| 80 | } | 83 | } |
-
Please register or login to post a comment