Line data Source code
1 : part of '../main.dart';
2 :
3 : /// This widget handles most of the routing work
4 : /// It gives you access to the [routes] attribute where you can start
5 : /// building your routes using [VRouteElement]s
6 : ///
7 : /// Note that this widget also acts as a [CupertinoApp] so you can pass
8 : /// it every argument that you would expect in [CupertinoApp]
9 : class CupertinoVRouter extends StatefulWidget
10 : with VRouteElement, VRouteElementSingleSubRoute {
11 : /// This list holds every possible routes of your app
12 : final List<VRouteElement> routes;
13 :
14 : /// If implemented, this becomes the default transition for every route transition
15 : /// except those who implement there own buildTransition
16 : /// Also see:
17 : /// * [VRouteElement.buildTransition] for custom local transitions
18 : ///
19 : /// Note that if this is not implemented, every route which does not implement
20 : /// its own buildTransition will be given a default transition: this of a
21 : /// [MaterialPage] or a [CupertinoPage] depending on the platform
22 : final Widget Function(Animation<double> animation,
23 : Animation<double> secondaryAnimation, Widget child)? buildTransition;
24 :
25 : /// The duration of [VRouter.buildTransition]
26 : final Duration? transitionDuration;
27 :
28 : /// The reverse duration of [VRouter.buildTransition]
29 : final Duration? reverseTransitionDuration;
30 :
31 : /// Two router mode are possible:
32 : /// - "hash": This is the default, the url will be serverAddress/#/localUrl
33 : /// - "history": This will display the url in the way we are used to, without
34 : /// the #. However note that you will need to configure your server to make this work.
35 : /// Follow the instructions here: [https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations]
36 : final VRouterModes mode;
37 :
38 0 : @override
39 : Future<void> beforeEnter(VRedirector vRedirector) =>
40 0 : _beforeEnter(vRedirector);
41 : final Future<void> Function(VRedirector vRedirector) _beforeEnter;
42 :
43 0 : @override
44 : Future<void> beforeLeave(
45 : VRedirector vRedirector,
46 : void Function(Map<String, String> historyState) saveHistoryState,
47 : ) =>
48 0 : _beforeLeave(vRedirector, saveHistoryState);
49 : final Future<void> Function(
50 : VRedirector vRedirector,
51 : void Function(Map<String, String> historyState) saveHistoryState,
52 : ) _beforeLeave;
53 :
54 0 : @override
55 : void afterEnter(BuildContext context, String? from, String to) =>
56 0 : _afterEnter(context, from, to);
57 : final void Function(BuildContext context, String? from, String to)
58 : _afterEnter;
59 :
60 0 : @override
61 0 : Future<void> onPop(VRedirector vRedirector) => _onPop(vRedirector);
62 : final Future<void> Function(VRedirector vRedirector) _onPop;
63 :
64 0 : @override
65 : Future<void> onSystemPop(VRedirector vRedirector) =>
66 0 : _onSystemPop(vRedirector);
67 : final Future<void> Function(VRedirector vRedirector) _onSystemPop;
68 :
69 : /// This allows you to change the initial url
70 : ///
71 : /// The default is '/'
72 : final String initialUrl;
73 :
74 0 : CupertinoVRouter({
75 : Key? key,
76 : required this.routes,
77 : Future<void> Function(VRedirector vRedirector) beforeEnter =
78 : VGuard._voidBeforeEnter,
79 : Future<void> Function(
80 : VRedirector vRedirector,
81 : void Function(Map<String, String> historyState) saveHistoryState,
82 : )
83 : beforeLeave = VGuard._voidBeforeLeave,
84 : void Function(BuildContext context, String? from, String to) afterEnter =
85 : VGuard._voidAfterEnter,
86 : Future<void> Function(VRedirector vRedirector) onPop =
87 : VPopHandler._voidOnPop,
88 : Future<void> Function(VRedirector vRedirector) onSystemPop =
89 : VPopHandler._voidOnSystemPop,
90 : this.buildTransition,
91 : this.transitionDuration,
92 : this.reverseTransitionDuration,
93 : this.mode = VRouterModes.hash,
94 : this.initialUrl = '/',
95 : this.navigatorObservers = const [],
96 : this.builder,
97 : // Bellow are the MaterialApp parameters
98 : this.theme,
99 : this.title = '',
100 : this.onGenerateTitle,
101 : this.color,
102 : this.locale,
103 : this.localizationsDelegates,
104 : this.localeListResolutionCallback,
105 : this.localeResolutionCallback,
106 : this.supportedLocales = const <Locale>[Locale('en', 'US')],
107 : this.showPerformanceOverlay = false,
108 : this.checkerboardRasterCacheImages = false,
109 : this.checkerboardOffscreenLayers = false,
110 : this.showSemanticsDebugger = false,
111 : this.debugShowCheckedModeBanner = true,
112 : this.shortcuts,
113 : this.actions,
114 : this.restorationScopeId,
115 : }) : _beforeEnter = beforeEnter,
116 : _beforeLeave = beforeLeave,
117 : _afterEnter = afterEnter,
118 : _onPop = onPop,
119 : _onSystemPop = onSystemPop,
120 0 : super(key: key);
121 :
122 0 : @override
123 0 : CupertinoVRouterState createState() => CupertinoVRouterState();
124 :
125 : /// {@macro flutter.widgets.widgetsApp.navigatorObservers}
126 : final List<NavigatorObserver> navigatorObservers;
127 :
128 : /// {@macro flutter.widgets.widgetsApp.builder}
129 : ///
130 : /// Material specific features such as [showDialog] and [showMenu], and widgets
131 : /// such as [Tooltip], [PopupMenuButton], also require a [Navigator] to properly
132 : /// function.
133 : final TransitionBuilder? builder;
134 :
135 : /// {@macro flutter.widgets.widgetsApp.title}
136 : ///
137 : /// This value is passed unmodified to [WidgetsApp.title].
138 : final String title;
139 :
140 : /// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
141 : ///
142 : /// This value is passed unmodified to [WidgetsApp.onGenerateTitle].
143 : final GenerateAppTitle? onGenerateTitle;
144 :
145 : /// Default visual properties, like colors fonts and shapes, for this app's
146 : /// material widgets.
147 : ///
148 : /// A second [darkTheme] [ThemeData] value, which is used to provide a dark
149 : /// version of the user interface can also be specified. [themeMode] will
150 : /// control which theme will be used if a [darkTheme] is provided.
151 : ///
152 : /// The default value of this property is the value of [ThemeData.light()].
153 : ///
154 : /// See also:
155 : ///
156 : /// * [themeMode], which controls which theme to use.
157 : /// * [MediaQueryData.platformBrightness], which indicates the platform's
158 : /// desired brightness and is used to automatically toggle between [theme]
159 : /// and [darkTheme] in [MaterialApp].
160 : /// * [ThemeData.brightness], which indicates the [Brightness] of a theme's
161 : /// colors.
162 : final CupertinoThemeData? theme;
163 :
164 : /// {@macro flutter.widgets.widgetsApp.color}
165 : final Color? color;
166 :
167 : /// {@macro flutter.widgets.widgetsApp.locale}
168 : final Locale? locale;
169 :
170 : /// {@macro flutter.widgets.widgetsApp.localizationsDelegates}
171 : ///
172 : /// Internationalized apps that require translations for one of the locales
173 : /// listed in [GlobalMaterialLocalizations] should specify this parameter
174 : /// and list the [supportedLocales] that the application can handle.
175 : ///
176 : /// ```dart
177 : /// import 'package:flutter_localizations/flutter_localizations.dart';
178 : /// MaterialApp(
179 : /// localizationsDelegates: [
180 : /// // ... app-specific localization delegate[s] here
181 : /// GlobalMaterialLocalizations.delegate,
182 : /// GlobalWidgetsLocalizations.delegate,
183 : /// ],
184 : /// supportedLocales: [
185 : /// const Locale('en', 'US'), // English
186 : /// const Locale('he', 'IL'), // Hebrew
187 : /// // ... other locales the app supports
188 : /// ],
189 : /// // ...
190 : /// )
191 : /// ```
192 : ///
193 : /// ## Adding localizations for a new locale
194 : ///
195 : /// The information that follows applies to the unusual case of an app
196 : /// adding translations for a language not already supported by
197 : /// [GlobalMaterialLocalizations].
198 : ///
199 : /// Delegates that produce [WidgetsLocalizations] and [MaterialLocalizations]
200 : /// are included automatically. Apps can provide their own versions of these
201 : /// localizations by creating implementations of
202 : /// [LocalizationsDelegate<WidgetsLocalizations>] or
203 : /// [LocalizationsDelegate<MaterialLocalizations>] whose load methods return
204 : /// custom versions of [WidgetsLocalizations] or [MaterialLocalizations].
205 : ///
206 : /// For example: to add support to [MaterialLocalizations] for a
207 : /// locale it doesn't already support, say `const Locale('foo', 'BR')`,
208 : /// one could just extend [DefaultMaterialLocalizations]:
209 : ///
210 : /// ```dart
211 : /// class FooLocalizations extends DefaultMaterialLocalizations {
212 : /// FooLocalizations(Locale locale) : super(locale);
213 : /// @override
214 : /// String get okButtonLabel {
215 : /// if (locale == const Locale('foo', 'BR'))
216 : /// return 'foo';
217 : /// return super.okButtonLabel;
218 : /// }
219 : /// }
220 : ///
221 : /// ```
222 : ///
223 : /// A `FooLocalizationsDelegate` is essentially just a method that constructs
224 : /// a `FooLocalizations` object. We return a [SynchronousFuture] here because
225 : /// no asynchronous work takes place upon "loading" the localizations object.
226 : ///
227 : /// ```dart
228 : /// class FooLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
229 : /// const FooLocalizationsDelegate();
230 : /// @override
231 : /// Future<FooLocalizations> load(Locale locale) {
232 : /// return SynchronousFuture(FooLocalizations(locale));
233 : /// }
234 : /// @override
235 : /// bool shouldReload(FooLocalizationsDelegate old) => false;
236 : /// }
237 : /// ```
238 : ///
239 : /// Constructing a [MaterialApp] with a `FooLocalizationsDelegate` overrides
240 : /// the automatically included delegate for [MaterialLocalizations] because
241 : /// only the first delegate of each [LocalizationsDelegate.type] is used and
242 : /// the automatically included delegates are added to the end of the app's
243 : /// [localizationsDelegates] list.
244 : ///
245 : /// ```dart
246 : /// MaterialApp(
247 : /// localizationsDelegates: [
248 : /// const FooLocalizationsDelegate(),
249 : /// ],
250 : /// // ...
251 : /// )
252 : /// ```
253 : /// See also:
254 : ///
255 : /// * [supportedLocales], which must be specified along with
256 : /// [localizationsDelegates].
257 : /// * [GlobalMaterialLocalizations], a [localizationsDelegates] value
258 : /// which provides material localizations for many languages.
259 : /// * The Flutter Internationalization Tutorial,
260 : /// <https://flutter.dev/tutorials/internationalization/>.
261 : final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;
262 :
263 : /// {@macro flutter.widgets.widgetsApp.localeListResolutionCallback}
264 : ///
265 : /// This callback is passed along to the [WidgetsApp] built by this widget.
266 : final LocaleListResolutionCallback? localeListResolutionCallback;
267 :
268 : /// {@macro flutter.widgets.LocaleResolutionCallback}
269 : ///
270 : /// This callback is passed along to the [WidgetsApp] built by this widget.
271 : final LocaleResolutionCallback? localeResolutionCallback;
272 :
273 : /// {@macro flutter.widgets.widgetsApp.supportedLocales}
274 : ///
275 : /// It is passed along unmodified to the [WidgetsApp] built by this widget.
276 : ///
277 : /// See also:
278 : ///
279 : /// * [localizationsDelegates], which must be specified for localized
280 : /// applications.
281 : /// * [GlobalMaterialLocalizations], a [localizationsDelegates] value
282 : /// which provides material localizations for many languages.
283 : /// * The Flutter Internationalization Tutorial,
284 : /// <https://flutter.dev/tutorials/internationalization/>.
285 : final Iterable<Locale> supportedLocales;
286 :
287 : /// Turns on a performance overlay.
288 : ///
289 : /// See also:
290 : ///
291 : /// * <https://flutter.dev/debugging/#performanceoverlay>
292 : final bool showPerformanceOverlay;
293 :
294 : /// Turns on checkerboarding of raster cache images.
295 : final bool checkerboardRasterCacheImages;
296 :
297 : /// Turns on checkerboarding of layers rendered to offscreen bitmaps.
298 : final bool checkerboardOffscreenLayers;
299 :
300 : /// Turns on an overlay that shows the accessibility information
301 : /// reported by the framework.
302 : final bool showSemanticsDebugger;
303 :
304 : /// {@macro flutter.widgets.widgetsApp.debugShowCheckedModeBanner}
305 : final bool debugShowCheckedModeBanner;
306 :
307 : /// {@macro flutter.widgets.widgetsApp.shortcuts}
308 : /// {@tool snippet}
309 : /// This example shows how to add a single shortcut for
310 : /// [LogicalKeyboardKey.select] to the default shortcuts without needing to
311 : /// add your own [Shortcuts] widget.
312 : ///
313 : /// Alternatively, you could insert a [Shortcuts] widget with just the mapping
314 : /// you want to add between the [WidgetsApp] and its child and get the same
315 : /// effect.
316 : ///
317 : /// ```dart
318 : /// Widget build(BuildContext context) {
319 : /// return WidgetsApp(
320 : /// shortcuts: <LogicalKeySet, Intent>{
321 : /// ... WidgetsApp.defaultShortcuts,
322 : /// LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
323 : /// },
324 : /// color: const Color(0xFFFF0000),
325 : /// builder: (BuildContext context, Widget child) {
326 : /// return const Placeholder();
327 : /// },
328 : /// );
329 : /// }
330 : /// ```
331 : /// {@end-tool}
332 : /// {@macro flutter.widgets.widgetsApp.shortcuts.seeAlso}
333 : final Map<LogicalKeySet, Intent>? shortcuts;
334 :
335 : /// {@macro flutter.widgets.widgetsApp.actions}
336 : /// {@tool snippet}
337 : /// This example shows how to add a single action handling an
338 : /// [ActivateAction] to the default actions without needing to
339 : /// add your own [Actions] widget.
340 : ///
341 : /// Alternatively, you could insert a [Actions] widget with just the mapping
342 : /// you want to add between the [WidgetsApp] and its child and get the same
343 : /// effect.
344 : ///
345 : /// ```dart
346 : /// Widget build(BuildContext context) {
347 : /// return WidgetsApp(
348 : /// actions: <Type, Action<Intent>>{
349 : /// ... WidgetsApp.defaultActions,
350 : /// ActivateAction: CallbackAction(
351 : /// onInvoke: (Intent intent) {
352 : /// // Do something here...
353 : /// return null;
354 : /// },
355 : /// ),
356 : /// },
357 : /// color: const Color(0xFFFF0000),
358 : /// builder: (BuildContext context, Widget child) {
359 : /// return const Placeholder();
360 : /// },
361 : /// );
362 : /// }
363 : /// ```
364 : /// {@end-tool}
365 : /// {@macro flutter.widgets.widgetsApp.actions.seeAlso}
366 : final Map<Type, Action<Intent>>? actions;
367 :
368 : /// {@macro flutter.widgets.widgetsApp.restorationScopeId}
369 : final String? restorationScopeId;
370 :
371 0 : static VRouterData of(BuildContext context) {
372 : VRouterData? vRouterData;
373 :
374 : // First try to get a local MaterialVRouterData
375 : vRouterData =
376 0 : context.dependOnInheritedWidgetOfExactType<LocalVRouterData>();
377 : if (vRouterData != null) {
378 : return vRouterData;
379 : }
380 :
381 : // Else try to get the root MaterialVRouterData
382 0 : vRouterData = context.dependOnInheritedWidgetOfExactType<RootVRouterData>();
383 : if (vRouterData != null) {
384 : return vRouterData;
385 : }
386 :
387 : if (vRouterData == null) {
388 0 : throw FlutterError(
389 : 'MaterialVRouter.of(context) was called with a context which does not contain a MaterialVRouter.\n'
390 : 'The context used to retrieve MaterialVRouter must be that of a widget that '
391 : 'is a descendant of a MaterialVRouter widget.');
392 : }
393 : return vRouterData;
394 : }
395 :
396 0 : @override
397 0 : List<VRouteElement> buildRoutes() => routes;
398 :
399 0 : @override
400 : void afterUpdate(BuildContext context, String? from, String to) {}
401 :
402 : @override
403 0 : Future<void> beforeUpdate(VRedirector vRedirector) async {}
404 : }
405 :
406 : class CupertinoVRouterState extends State<CupertinoVRouter> {
407 : late final vRouterDelegate = VRouterDelegate(
408 : routes: widget.routes,
409 : builder: widget.builder,
410 : navigatorObservers: widget.navigatorObservers,
411 : beforeEnter: widget.beforeEnter,
412 : beforeLeave: widget.beforeLeave,
413 : afterEnter: widget.afterEnter,
414 : onPop: widget.onPop,
415 : onSystemPop: widget.onSystemPop,
416 : buildTransition: widget.buildTransition,
417 : transitionDuration: widget.transitionDuration,
418 : reverseTransitionDuration: widget.reverseTransitionDuration,
419 : mode: widget.mode,
420 : initialUrl: widget.initialUrl,
421 : );
422 :
423 0 : @override
424 : Widget build(BuildContext context) {
425 0 : return CupertinoApp.router(
426 0 : backButtonDispatcher: VBackButtonDispatcher(),
427 0 : routeInformationParser: VRouteInformationParser(),
428 0 : routerDelegate: vRouterDelegate,
429 0 : theme: widget.theme,
430 0 : title: widget.title,
431 0 : onGenerateTitle: widget.onGenerateTitle,
432 0 : color: widget.color,
433 0 : locale: widget.locale,
434 0 : localizationsDelegates: widget.localizationsDelegates,
435 0 : localeListResolutionCallback: widget.localeListResolutionCallback,
436 0 : localeResolutionCallback: widget.localeResolutionCallback,
437 0 : supportedLocales: widget.supportedLocales,
438 0 : showPerformanceOverlay: widget.showPerformanceOverlay,
439 0 : checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages,
440 0 : checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers,
441 0 : showSemanticsDebugger: widget.showSemanticsDebugger,
442 0 : debugShowCheckedModeBanner: widget.debugShowCheckedModeBanner,
443 0 : shortcuts: widget.shortcuts,
444 0 : actions: widget.actions,
445 0 : restorationScopeId: widget.restorationScopeId,
446 : );
447 : }
448 :
449 : /// Url currently synced with the state
450 : /// This url can differ from the once of the browser if
451 : /// the state has been yet been updated
452 0 : String? get url => vRouterDelegate.url;
453 :
454 : /// Previous url that was synced with the state
455 0 : String? get previousUrl => vRouterDelegate.previousUrl;
456 :
457 : /// This state is saved in the browser history. This means that if the user presses
458 : /// the back or forward button on the navigator, this historyState will be the same
459 : /// as the last one you saved.
460 : ///
461 : /// It can be changed by using [context.vRouter.replaceHistoryState(newState)]
462 0 : Map<String, String> get historyState => vRouterDelegate.historyState;
463 :
464 : /// Maps all route parameters (i.e. parameters of the path
465 : /// mentioned as ":someId")
466 0 : Map<String, String> get pathParameters => vRouterDelegate.pathParameters;
467 :
468 : /// Contains all query parameters (i.e. parameters after
469 : /// the "?" in the url) of the current url
470 0 : Map<String, String> get queryParameters => vRouterDelegate.queryParameters;
471 :
472 : /// Starts a pop cycle
473 : ///
474 : /// Pop cycle:
475 : /// 1. onPop is called in all [VNavigationGuard]s
476 : /// 2. onPop is called in all [VRouteElement]s of the current route
477 : /// 3. onPop is called in [VRouter]
478 : ///
479 : /// In any of the above steps, we can use [vRedirector] if you want to redirect or
480 : /// stop the navigation
481 0 : Future<void> pop({
482 : Map<String, String> pathParameters = const {},
483 : Map<String, String> queryParameters = const {},
484 : Map<String, String> newHistoryState = const {},
485 : }) async =>
486 0 : vRouterDelegate.pop(
487 : pathParameters: pathParameters,
488 : queryParameters: queryParameters,
489 : newHistoryState: newHistoryState,
490 : );
491 :
492 : /// Starts a systemPop cycle
493 : ///
494 : /// systemPop cycle:
495 : /// 1. onSystemPop (or onPop if not implemented) is called in all VNavigationGuards
496 : /// 2. onSystemPop (or onPop if not implemented) is called in the nested-most VRouteElement of the current route
497 : /// 3. onSystemPop (or onPop if not implemented) is called in MaterialVRouter
498 : ///
499 : /// In any of the above steps, we can use a [VRedirector] if you want to redirect or
500 : /// stop the navigation
501 0 : Future<void> systemPop({
502 : Map<String, String> pathParameters = const {},
503 : Map<String, String> queryParameters = const {},
504 : Map<String, String> newHistoryState = const {},
505 : }) async =>
506 0 : vRouterDelegate.systemPop(
507 : pathParameters: pathParameters,
508 : queryParameters: queryParameters,
509 : newHistoryState: newHistoryState,
510 : );
511 :
512 : /// Pushes the new route of the given url on top of the current one
513 : /// A path can be of one of two forms:
514 : /// * stating with '/', in which case we just navigate
515 : /// to the given path
516 : /// * not starting with '/', in which case we append the
517 : /// current path to the given one
518 : ///
519 : /// We can also specify queryParameters, either by directly
520 : /// putting them is the url or by providing a Map using [queryParameters]
521 : ///
522 : /// We can also put a state to the next route, this state will
523 : /// be a router state (this is the only kind of state that we can
524 : /// push) accessible with MaterialVRouter.of(context).historyState
525 0 : void push(
526 : String newUrl, {
527 : Map<String, String> queryParameters = const {},
528 : Map<String, String> historyState = const {},
529 : }) =>
530 0 : vRouterDelegate.push(
531 : newUrl,
532 : queryParameters: queryParameters,
533 : historyState: historyState,
534 : );
535 :
536 : /// Updates the url given a [VRouteElement] name
537 : ///
538 : /// We can also specify path parameters to inject into the new path
539 : ///
540 : /// We can also specify queryParameters, either by directly
541 : /// putting them is the url or by providing a Map using [queryParameters]
542 : ///
543 : /// We can also put a state to the next route, this state will
544 : /// be a router state (this is the only kind of state that we can
545 : /// push) accessible with MaterialVRouter.of(context).historyState
546 : ///
547 : /// After finding the url and taking charge of the path parameters,
548 : /// it updates the url
549 : ///
550 : /// To specify a name, see [VRouteElement.name]
551 0 : void pushNamed(
552 : String name, {
553 : Map<String, String> pathParameters = const {},
554 : Map<String, String> queryParameters = const {},
555 : Map<String, String> historyState = const {},
556 : }) =>
557 0 : vRouterDelegate.pushNamed(
558 : name,
559 : pathParameters: pathParameters,
560 : queryParameters: queryParameters,
561 : historyState: historyState,
562 : );
563 :
564 : /// Replace the current one by the new route corresponding to the given url
565 : /// The difference with [push] is that this overwrites the current browser history entry
566 : /// If you are on mobile, this is the same as push
567 : /// Path can be of one of two forms:
568 : /// * stating with '/', in which case we just navigate
569 : /// to the given path
570 : /// * not starting with '/', in which case we append the
571 : /// current path to the given one
572 : ///
573 : /// We can also specify queryParameters, either by directly
574 : /// putting them is the url or by providing a Map using [queryParameters]
575 : ///
576 : /// We can also put a state to the next route, this state will
577 : /// be a router state (this is the only kind of state that we can
578 : /// push) accessible with MaterialVRouter.of(context).historyState
579 0 : void pushReplacement(
580 : String newUrl, {
581 : Map<String, String> queryParameters = const {},
582 : Map<String, String> historyState = const {},
583 : }) =>
584 0 : vRouterDelegate.pushReplacement(
585 : newUrl,
586 : queryParameters: queryParameters,
587 : historyState: historyState,
588 : );
589 :
590 : /// Replace the url given a [VRouteElement] name
591 : /// The difference with [pushNamed] is that this overwrites the current browser history entry
592 : ///
593 : /// We can also specify path parameters to inject into the new path
594 : ///
595 : /// We can also specify queryParameters, either by directly
596 : /// putting them is the url or by providing a Map using [queryParameters]
597 : ///
598 : /// We can also put a state to the next route, this state will
599 : /// be a router state (this is the only kind of state that we can
600 : /// push) accessible with MaterialVRouter.of(context).historyState
601 : ///
602 : /// After finding the url and taking charge of the path parameters
603 : /// it updates the url
604 : ///
605 : /// To specify a name, see [VPath.name]
606 0 : void pushReplacementNamed(
607 : String name, {
608 : Map<String, String> pathParameters = const {},
609 : Map<String, String> queryParameters = const {},
610 : Map<String, String> historyState = const {},
611 : }) =>
612 0 : vRouterDelegate.pushReplacementNamed(
613 : name,
614 : pathParameters: pathParameters,
615 : queryParameters: queryParameters,
616 : historyState: historyState,
617 : );
618 :
619 : /// Goes to an url which is not in the app
620 : ///
621 : /// On the web, you can set [openNewTab] to true to open this url
622 : /// in a new tab
623 0 : void pushExternal(String newUrl, {bool openNewTab = false}) =>
624 0 : vRouterDelegate.pushExternal(
625 : newUrl,
626 : openNewTab: openNewTab,
627 : );
628 : }
|