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