Line data Source code
1 : part of '../main.dart';
2 :
3 : class LocalVRouterData extends InheritedWidget {
4 : final VRouteElementNode _vRouteElementNode;
5 : final BuildContext _context;
6 :
7 10 : LocalVRouterData({
8 : Key? key,
9 : required Widget child,
10 : required this.url,
11 : required this.previousUrl,
12 : required this.historyState,
13 : required this.pathParameters,
14 : required this.queryParameters,
15 : required VRouteElementNode vRouteElementNode,
16 : required BuildContext context,
17 : }) : _vRouteElementNode = vRouteElementNode,
18 : _context = context,
19 10 : super(
20 : key: key,
21 : child: child,
22 : );
23 :
24 9 : @override
25 : bool updateShouldNotify(LocalVRouterData old) {
26 27 : return (old.url != url ||
27 0 : old.previousUrl != previousUrl ||
28 0 : old.historyState != historyState ||
29 0 : old.pathParameters != pathParameters ||
30 0 : old.queryParameters != queryParameters);
31 : }
32 :
33 : /// Url currently synced with the state
34 : /// This url can differ from the once of the browser if
35 : /// the state has been yet been updated
36 : final String? url;
37 :
38 : /// Previous url that was synced with the state
39 : final String? previousUrl;
40 :
41 : /// This state is saved in the browser history. This means that if the user presses
42 : /// the back or forward button on the navigator, this historyState will be the same
43 : /// as the last one you saved.
44 : ///
45 : /// It can be changed by using [VRouteElementWidgetData.of(context).replaceHistoryState(newState)]
46 : ///
47 : /// Also see:
48 : /// * [VRouteElementData.historyState] if you want to use a local level
49 : /// version of the historyState
50 : /// * [VRouterData.historyState] if you want to use a router level
51 : /// version of the historyState
52 : final Map<String, String> historyState;
53 :
54 : /// Maps all route parameters (i.e. parameters of the path
55 : /// mentioned as ":someId")
56 : /// Note that if you have multiple parameters with the same
57 : /// name, only the last one will be visible here
58 : /// However every parameters is passed locally to VRouteElementWidgetData
59 : /// so you should find them there.
60 : /// See [VRouteElementData.pathParameters]
61 : final Map<String, String> pathParameters;
62 :
63 : /// Contains all query parameters (i.e. parameters after
64 : /// the "?" in the url) of the current url
65 : final Map<String, String> queryParameters;
66 :
67 : /// Pushes the new route of the given url on top of the current one
68 : /// A path can be of one of two forms:
69 : /// * stating with '/', in which case we just navigate
70 : /// to the given path
71 : /// * not starting with '/', in which case we append the
72 : /// current path to the given one
73 : ///
74 : /// We can also specify queryParameters, either by directly
75 : /// putting them is the url or by providing a Map using [queryParameters]
76 : ///
77 : /// We can also put a state to the next route, this state will
78 : /// be a router state (this is the only kind of state that we can
79 : /// push) accessible with VRouterData.of(context).historyState
80 7 : void push(
81 : String newUrl, {
82 : Map<String, String> queryParameters = const {},
83 : Map<String, String> historyState = const {},
84 : }) =>
85 21 : RootVRouterData.of(_context).push(newUrl,
86 : queryParameters: queryParameters, historyState: historyState);
87 :
88 : /// Updates the url given a [VRouteElement] name
89 : ///
90 : /// We can also specify path parameters to inject into the new path
91 : ///
92 : /// We can also specify queryParameters, either by directly
93 : /// putting them is the url or by providing a Map using [queryParameters]
94 : ///
95 : /// We can also put a state to the next route, this state will
96 : /// be a router state (this is the only kind of state that we can
97 : /// push) accessible with VRouterData.of(context).historyState
98 : ///
99 : /// After finding the url and taking charge of the path parameters
100 : /// it updates the url
101 : ///
102 : /// To specify a name, see [VRouteElement.name]
103 2 : void pushNamed(
104 : String name, {
105 : Map<String, String> pathParameters = const {},
106 : Map<String, String> queryParameters = const {},
107 : String? routerState,
108 : }) =>
109 6 : RootVRouterData.of(_context).pushNamed(name,
110 : pathParameters: pathParameters,
111 : queryParameters: queryParameters,
112 : routerState: routerState);
113 :
114 : /// Replace the current one by the new route corresponding to the given url
115 : /// The difference with [push] is that this overwrites the current browser history entry
116 : /// If you are on mobile, this is the same as push
117 : /// Path can be of one of two forms:
118 : /// * stating with '/', in which case we just navigate
119 : /// to the given path
120 : /// * not starting with '/', in which case we append the
121 : /// current path to the given one
122 : ///
123 : /// We can also specify queryParameters, either by directly
124 : /// putting them is the url or by providing a Map using [queryParameters]
125 : ///
126 : /// We can also put a state to the next route, this state will
127 : /// be a router state (this is the only kind of state that we can
128 : /// push) accessible with VRouterData.of(context).historyState
129 0 : void pushReplacement(
130 : String newUrl, {
131 : Map<String, String> queryParameters = const {},
132 : Map<String, String> historyState = const {},
133 : }) =>
134 0 : RootVRouterData.of(_context).pushReplacement(newUrl,
135 : queryParameters: queryParameters, historyState: historyState);
136 :
137 : /// Replace the url given a [VRouteElement] name
138 : /// The difference with [pushNamed] is that this overwrites the current browser history entry
139 : ///
140 : /// We can also specify path parameters to inject into the new path
141 : ///
142 : /// We can also specify queryParameters, either by directly
143 : /// putting them is the url or by providing a Map using [queryParameters]
144 : ///
145 : /// We can also put a state to the next route, this state will
146 : /// be a router state (this is the only kind of state that we can
147 : /// push) accessible with VRouterData.of(context).historyState
148 : ///
149 : /// After finding the url and taking charge of the path parameters
150 : /// it updates the url
151 : ///
152 : /// To specify a name, see [VRouteElement.name]
153 0 : void pushReplacementNamed(
154 : String name, {
155 : Map<String, String> pathParameters = const {},
156 : Map<String, String> queryParameters = const {},
157 : Map<String, String> historyState = const {},
158 : }) =>
159 0 : RootVRouterData.of(_context).pushReplacementNamed(name,
160 : pathParameters: pathParameters,
161 : queryParameters: queryParameters,
162 : historyState: historyState);
163 :
164 : /// Goes to an url which is not in the app
165 : ///
166 : /// On the web, you can set [openNewTab] to true to open this url
167 : /// in a new tab
168 0 : void pushExternal(String newUrl, {bool openNewTab = false}) =>
169 0 : RootVRouterData.of(_context).pushExternal(newUrl, openNewTab: openNewTab);
170 :
171 : /// Starts a pop cycle
172 : ///
173 : /// Pop cycle:
174 : /// 1. onPop is called in all [VNavigationGuard]s
175 : /// 2. onPop is called in the nested-most [VRouteElement] of the current route
176 : /// 3. onPop is called in [VRouter]
177 : /// 4. Default behaviour of pop is called: [VRouterState._defaultPop]
178 : ///
179 : /// In any of the above steps, we can use [vRedirector] if you want to redirect or
180 : /// stop the navigation
181 4 : void pop({
182 : Map<String, String> pathParameters = const {},
183 : Map<String, String> queryParameters = const {},
184 : Map<String, String> newHistoryState = const {},
185 : }) =>
186 12 : RootVRouterData.of(_context).pop(
187 8 : _vRouteElementNode.getVRouteElementToPop(),
188 : pathParameters: pathParameters,
189 : queryParameters: queryParameters,
190 : newHistoryState: newHistoryState,
191 : );
192 :
193 : /// Starts a systemPop cycle
194 : ///
195 : /// systemPop cycle:
196 : /// 1. onSystemPop is called in all VNavigationGuards
197 : /// 2. onSystemPop is called in the nested-most VRouteElement of the current route
198 : /// 3. onSystemPop is called in VRouter
199 : /// 4. [pop] is called
200 : ///
201 : /// In any of the above steps, we can use [vRedirector] if you want to redirect or
202 : /// stop the navigation
203 1 : Future<void> systemPop({
204 : Map<String, String> pathParameters = const {},
205 : Map<String, String> queryParameters = const {},
206 : Map<String, String> newHistoryState = const {},
207 : }) =>
208 3 : RootVRouterData.of(_context).systemPop(
209 2 : _vRouteElementNode.getVRouteElementToPop(),
210 : pathParameters: pathParameters,
211 : queryParameters: queryParameters,
212 : newHistoryState: newHistoryState,
213 : );
214 :
215 : /// This replaces the current history state of [VRouterData] with given one
216 0 : void replaceHistoryState(Map<String, String> historyState) =>
217 0 : RootVRouterData.of(_context).replaceHistoryState(historyState);
218 :
219 0 : static LocalVRouterData of(BuildContext context) {
220 : final localVRouterData =
221 0 : context.dependOnInheritedWidgetOfExactType<LocalVRouterData>();
222 : if (localVRouterData == null) {
223 0 : throw FlutterError(
224 : 'LocalVRouterData.of(context) was called with a context which does not contain a LocalVRouterData.\n'
225 : 'The context used to retrieve LocalVRouterData must be that of a widget that '
226 : 'is a descendant of a LocalVRouterData widget.');
227 : }
228 : return localVRouterData;
229 : }
230 : }
|