parse_route.dart
3.5 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
import '../../../get_core/src/get_main.dart';
import '../../get_navigation.dart';
import '../routes/get_route.dart';
class RouteDecoder {
final GetPage? route;
final Map<String, String?> parameters;
const RouteDecoder(this.route, this.parameters);
}
class ParseRouteTree {
final _routes = <GetPage>[];
RouteDecoder matchRoute(String name) {
final uri = Uri.parse(name);
final route = _findRoute(uri.path);
final params = Map<String, String?>.from(uri.queryParameters);
if (route != null) {
final parsedParams = _parseParams(name, route.path);
if (parsedParams.isNotEmpty) {
params.addAll(parsedParams);
}
} else {
Get.log('Route "${uri.path}" not found');
}
return RouteDecoder(route, params);
}
void addRoutes(List<GetPage> getPages) {
for (final route in getPages) {
addRoute(route);
}
}
void addRoute(GetPage route) {
_routes.add(route);
// Add Page children.
for (var page in _flattenPage(route)) {
addRoute(page);
}
}
List<GetPage> _flattenPage(GetPage route) {
final result = <GetPage>[];
if (route.children == null || route.children!.isEmpty) {
return result;
}
final parentPath = route.name;
for (var page in route.children!) {
// Add Parent middlewares to children
final pageMiddlewares = page.middlewares ?? <GetMiddleware>[];
pageMiddlewares.addAll(route.middlewares ?? <GetMiddleware>[]);
result.add(_addChild(page, parentPath, pageMiddlewares));
final children = _flattenPage(page);
for (var child in children) {
pageMiddlewares.addAll(child.middlewares ?? <GetMiddleware>[]);
result.add(_addChild(child, parentPath, pageMiddlewares));
}
}
return result;
}
/// Change the Path for a [GetPage]
GetPage _addChild(
GetPage origin, String parentPath, List<GetMiddleware> middlewares) =>
GetPage(
name: parentPath + origin.name,
page: origin.page,
title: origin.title,
alignment: origin.alignment,
transition: origin.transition,
binding: origin.binding,
bindings: origin.bindings,
curve: origin.curve,
customTransition: origin.customTransition,
fullscreenDialog: origin.fullscreenDialog,
maintainState: origin.maintainState,
opaque: origin.opaque,
parameter: origin.parameter,
popGesture: origin.popGesture,
settings: origin.settings,
transitionDuration: origin.transitionDuration,
middlewares: middlewares,
);
GetPage? _findRoute(String name) {
return _routes.firstWhereOrNull(
(route) => route.path.regex.hasMatch(name),
);
}
Map<String, String?> _parseParams(String path, PathDecoded routePath) {
final params = <String, String?>{};
var idx = path.indexOf('?');
if (idx > -1) {
path = path.substring(0, idx);
final uri = Uri.tryParse(path);
if (uri != null) {
params.addAll(uri.queryParameters);
}
}
var paramsMatch = routePath.regex.firstMatch(path);
for (var i = 0; i < routePath.keys.length; i++) {
var param = Uri.decodeQueryComponent(paramsMatch![i + 1]!);
params[routePath.keys[i]!] = param;
}
return params;
}
}
extension FirstWhereExt<T> on List<T> {
/// The first element satisfying [test], or `null` if there are none.
T? firstWhereOrNull(bool Function(T element) test) {
for (var element in this) {
if (test(element)) return element;
}
return null;
}
}