route_middleware.dart
7.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import '../../../get.dart';
abstract class _RouteMiddleware {
/// The Order of the Middlewares to run.
///
/// {@tool snippet}
/// This Middewares will be called in this order.
/// ```dart
/// final middlewares = [
/// GetMiddleware(priority: 2),
/// GetMiddleware(priority: 5),
/// GetMiddleware(priority: 4),
/// GetMiddleware(priority: -8),
/// ];
/// ```
/// -8 => 2 => 4 => 5
/// {@end-tool}
int? priority;
/// This function will be called when the page of
/// the called route is being searched for.
/// It take RouteSettings as a result an redirect to the new settings or
/// give it null and there will be no redirecting.
/// {@tool snippet}
/// ```dart
/// GetPage redirect(String route) {
/// final authService = Get.find<AuthService>();
/// return authService.authed.value ? null : RouteSettings(name: '/login');
/// }
/// ```
/// {@end-tool}
RouteSettings? redirect(String route);
/// Similar to [redirect],
/// This function will be called when the router delegate changes the
/// current route.
///
/// The default implmentation is to navigate to
/// the input route, with no redirection.
///
/// if this returns null, the navigation is stopped,
/// and no new routes are pushed.
/// {@tool snippet}
/// ```dart
/// GetNavConfig? redirect(GetNavConfig route) {
/// final authService = Get.find<AuthService>();
/// return authService.authed.value ? null : RouteSettings(name: '/login');
/// }
/// ```
/// {@end-tool}
Future<GetNavConfig?> redirectDelegate(GetNavConfig route);
/// This function will be called when this Page is called
/// you can use it to change something about the page or give it new page
/// {@tool snippet}
/// ```dart
/// GetPage onPageCalled(GetPage page) {
/// final authService = Get.find<AuthService>();
/// return page.copyWith(title: 'Welcome ${authService.UserName}');
/// }
/// ```
/// {@end-tool}
GetPage? onPageCalled(GetPage page);
/// This function will be called right before the [Bindings] are initialize.
/// Here you can change [Bindings] for this page
/// {@tool snippet}
/// ```dart
/// List<Bindings> onBindingsStart(List<Bindings> bindings) {
/// final authService = Get.find<AuthService>();
/// if (authService.isAdmin) {
/// bindings.add(AdminBinding());
/// }
/// return bindings;
/// }
/// ```
/// {@end-tool}
List<Bindings>? onBindingsStart(List<Bindings> bindings);
/// This function will be called right after the [Bindings] are initialize.
GetPageBuilder? onPageBuildStart(GetPageBuilder page);
/// This function will be called right after the
/// GetPage.page function is called and will give you the result
/// of the function. and take the widget that will be showed.
Widget onPageBuilt(Widget page);
void onPageDispose();
}
/// The Page Middlewares.
/// The Functions will be called in this order
/// (( [redirect] -> [onPageCalled] -> [onBindingsStart] ->
/// [onPageBuildStart] -> [onPageBuilt] -> [onPageDispose] ))
class GetMiddleware implements _RouteMiddleware {
@override
int? priority = 0;
GetMiddleware({this.priority});
@override
RouteSettings? redirect(String? route) => null;
@override
GetPage? onPageCalled(GetPage? page) => page;
@override
List<Bindings>? onBindingsStart(List<Bindings>? bindings) => bindings;
@override
GetPageBuilder? onPageBuildStart(GetPageBuilder? page) => page;
@override
Widget onPageBuilt(Widget page) => page;
@override
void onPageDispose() {}
@override
Future<GetNavConfig?> redirectDelegate(GetNavConfig route) =>
SynchronousFuture(route);
}
class MiddlewareRunner {
MiddlewareRunner(this._middlewares);
final List<GetMiddleware>? _middlewares;
List<GetMiddleware> _getMiddlewares() {
final _m = _middlewares ?? <GetMiddleware>[];
return _m
..sort(
(a, b) => (a.priority ?? 0).compareTo(b.priority ?? 0),
);
}
GetPage? runOnPageCalled(GetPage? page) {
_getMiddlewares().forEach((element) {
page = element.onPageCalled(page);
});
return page;
}
RouteSettings? runRedirect(String? route) {
RouteSettings? to;
for (final element in _getMiddlewares()) {
to = element.redirect(route);
if (to != null) {
break;
}
}
Get.log('Redirect to $to');
return to;
}
List<Bindings>? runOnBindingsStart(List<Bindings>? bindings) {
_getMiddlewares().forEach((element) {
bindings = element.onBindingsStart(bindings);
});
return bindings;
}
GetPageBuilder? runOnPageBuildStart(GetPageBuilder? page) {
_getMiddlewares().forEach((element) {
page = element.onPageBuildStart(page);
});
return page;
}
Widget runOnPageBuilt(Widget page) {
_getMiddlewares().forEach((element) {
page = element.onPageBuilt(page);
});
return page;
}
void runOnPageDispose() =>
_getMiddlewares().forEach((element) => element.onPageDispose());
}
class PageRedirect {
GetPage? route;
GetPage? unknownRoute;
RouteSettings? settings;
bool isUnknown;
PageRedirect({
this.route,
this.unknownRoute,
this.isUnknown = false,
this.settings,
});
// redirect all pages that needes redirecting
GetPageRoute<T> page<T>() {
while (needRecheck()) {}
final _r = (isUnknown ? unknownRoute : route)!;
return GetPageRoute<T>(
page: _r.page,
parameter: _r.parameters,
settings: isUnknown
? RouteSettings(
name: _r.name,
arguments: settings!.arguments,
)
: settings,
curve: _r.curve,
opaque: _r.opaque,
showCupertinoParallax: _r.showCupertinoParallax,
gestureWidth: _r.gestureWidth,
customTransition: _r.customTransition,
binding: _r.binding,
bindings: _r.bindings,
transitionDuration:
_r.transitionDuration ?? Get.defaultTransitionDuration,
transition: _r.transition,
popGesture: _r.popGesture,
fullscreenDialog: _r.fullscreenDialog,
middlewares: _r.middlewares,
);
}
// redirect all pages that needes redirecting
GetPageRoute<T> getPageToRoute<T>(GetPage rou, GetPage? unk) {
while (needRecheck()) {}
final _r = (isUnknown ? unk : rou)!;
return GetPageRoute<T>(
page: _r.page,
parameter: _r.parameters,
alignment: _r.alignment,
title: _r.title,
maintainState: _r.maintainState,
routeName: _r.name,
settings: _r,
curve: _r.curve,
showCupertinoParallax: _r.showCupertinoParallax,
gestureWidth: _r.gestureWidth,
opaque: _r.opaque,
customTransition: _r.customTransition,
binding: _r.binding,
bindings: _r.bindings,
transitionDuration:
_r.transitionDuration ?? Get.defaultTransitionDuration,
transition: _r.transition,
popGesture: _r.popGesture,
fullscreenDialog: _r.fullscreenDialog,
middlewares: _r.middlewares,
);
}
/// check if redirect is needed
bool needRecheck() {
if (settings == null && route != null) {
settings = route;
}
final match = Get.routeTree.matchRoute(settings!.name!);
Get.parameters = match.parameters;
// No Match found
if (match.route == null) {
isUnknown = true;
return false;
}
final runner = MiddlewareRunner(match.route!.middlewares);
route = runner.runOnPageCalled(match.route);
addPageParameter(route!);
// No middlewares found return match.
if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) {
return false;
}
final newSettings = runner.runRedirect(settings!.name);
if (newSettings == null) {
return false;
}
settings = newSettings;
return true;
}
void addPageParameter(GetPage route) {
if (route.parameters == null) return;
final parameters = Get.parameters;
parameters.addEntries(route.parameters!.entries);
Get.parameters = parameters;
}
}