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