Line data Source code
1 : import 'package:flutter/material.dart'; 2 : 3 : class ParseRoute { 4 : final List<ParseRouteSplit> _routeSplits = <ParseRouteSplit>[]; 5 : 6 1 : void addRoute(String routePath) { 7 : String path = routePath; 8 : 9 1 : if (path == Navigator.defaultRouteName) { 10 1 : var routeSplit = ParseRouteSplit(path, ParseRouteSplitType.component); 11 2 : routeSplit.routes = [routePath]; 12 2 : _routeSplits.add(routeSplit); 13 : return; 14 : } 15 1 : if (path.startsWith("/")) { 16 1 : path = path.substring(1); 17 : } 18 1 : List<String> pathComponents = path.split('/'); 19 : ParseRouteSplit parent; 20 3 : for (int i = 0; i < pathComponents.length; i++) { 21 1 : String component = pathComponents[i]; 22 1 : ParseRouteSplit routeSplit = _routeSplitForComponent(component, parent); 23 : if (routeSplit == null) { 24 1 : ParseRouteSplitType type = _typeForComponent(component); 25 1 : routeSplit = ParseRouteSplit(component, type); 26 1 : routeSplit.parent = parent; 27 : if (parent == null) { 28 2 : _routeSplits.add(routeSplit); 29 : } else { 30 0 : parent.routeSplits.add(routeSplit); 31 : } 32 : } 33 3 : if (i == pathComponents.length - 1) { 34 1 : if (routeSplit.routes == null) { 35 0 : routeSplit.routes = [routePath]; 36 : } else { 37 2 : routeSplit.routes.add(routePath); 38 : } 39 : } 40 : parent = routeSplit; 41 : } 42 : } 43 : 44 1 : AppRouteMatch split(String path) { 45 : String usePath = path; 46 1 : if (usePath.startsWith("/")) { 47 1 : usePath = path.substring(1); 48 : } 49 1 : List<String> components = usePath.split("/"); 50 1 : if (path == Navigator.defaultRouteName) { 51 1 : components = ["/"]; 52 : } 53 : 54 : Map<ParseRouteSplit, ParseRouteSplitMatch> routeSplitMatches = 55 1 : <ParseRouteSplit, ParseRouteSplitMatch>{}; 56 1 : List<ParseRouteSplit> routeSplitsToCheck = _routeSplits; 57 2 : for (String checkComponent in components) { 58 : Map<ParseRouteSplit, ParseRouteSplitMatch> currentMatches = 59 1 : <ParseRouteSplit, ParseRouteSplitMatch>{}; 60 1 : List<ParseRouteSplit> nextrouteSplits = <ParseRouteSplit>[]; 61 2 : for (ParseRouteSplit routeSplit in routeSplitsToCheck) { 62 : String pathPart = checkComponent; 63 1 : Map<String, String> queryMap = {}; 64 1 : if (checkComponent.contains("?") && !checkComponent.contains("=")) { 65 0 : var splitParam = checkComponent.split("?"); 66 0 : pathPart = splitParam[0]; 67 0 : queryMap = {pathPart: splitParam[1]}; 68 1 : } else if (checkComponent.contains("?")) { 69 0 : var splitParam = checkComponent.split("?"); 70 0 : var splitParam2 = splitParam[1].split("="); 71 0 : if (!splitParam2[1].contains("&")) { 72 0 : pathPart = splitParam[0]; 73 0 : queryMap = {splitParam2[0]: splitParam2[1]}; 74 : } else { 75 0 : pathPart = splitParam[0]; 76 0 : final segunda = splitParam[1]; 77 0 : var other = segunda.split(RegExp(r"[&,=]")); 78 0 : for (var i = 0; i < (other.length - 1); i++) { 79 0 : bool impar = (i % 2 == 0); 80 : if (impar) { 81 0 : queryMap.addAll({other[0 + i]: other[1 + i]}); 82 : } 83 : } 84 : } 85 : } 86 : bool isMatch = 87 3 : (routeSplit.part == pathPart || routeSplit.isParameter()); 88 : if (isMatch) { 89 : ParseRouteSplitMatch parentMatch = 90 2 : routeSplitMatches[routeSplit.parent]; 91 : ParseRouteSplitMatch match = 92 1 : ParseRouteSplitMatch.fromMatch(parentMatch, routeSplit); 93 1 : if (routeSplit.isParameter()) { 94 0 : String paramKey = routeSplit.part.substring(1); 95 0 : match.parameters[paramKey] = pathPart; 96 : } 97 : if (queryMap != null) { 98 2 : match.parameters.addAll(queryMap); 99 : } 100 : 101 1 : currentMatches[routeSplit] = match; 102 1 : if (routeSplit.routeSplits != null) { 103 2 : nextrouteSplits.addAll(routeSplit.routeSplits); 104 : } 105 : } 106 : } 107 : routeSplitMatches = currentMatches; 108 : routeSplitsToCheck = nextrouteSplits; 109 3 : if (currentMatches.values.length == 0) { 110 : return null; 111 : } 112 : } 113 2 : List<ParseRouteSplitMatch> matches = routeSplitMatches.values.toList(); 114 2 : if (matches.length > 0) { 115 1 : ParseRouteSplitMatch match = matches.first; 116 1 : ParseRouteSplit routeSplitToUse = match.routeSplit; 117 : 118 : if (routeSplitToUse != null && 119 1 : routeSplitToUse.routes != null && 120 3 : routeSplitToUse.routes.length > 0) { 121 1 : AppRouteMatch routeMatch = AppRouteMatch(); 122 2 : routeMatch.parameters = match.parameters; 123 1 : if (routeSplitToUse.isParameter()) { 124 0 : routeMatch.route = match.routeSplit.parent.part; 125 : } else { 126 3 : routeMatch.route = match.routeSplit.part; 127 : } 128 : return routeMatch; 129 : } 130 : } 131 : return null; 132 : } 133 : 134 1 : ParseRouteSplit _routeSplitForComponent( 135 : String component, ParseRouteSplit parent) { 136 1 : List<ParseRouteSplit> routeSplits = _routeSplits; 137 : if (parent != null) { 138 0 : routeSplits = parent.routeSplits; 139 : } 140 2 : for (ParseRouteSplit routeSplit in routeSplits) { 141 2 : if (routeSplit.part == component) { 142 : return routeSplit; 143 : } 144 : } 145 : return null; 146 : } 147 : 148 1 : ParseRouteSplitType _typeForComponent(String component) { 149 : ParseRouteSplitType type = ParseRouteSplitType.component; 150 1 : if (_isParameterComponent(component)) { 151 : type = ParseRouteSplitType.parameter; 152 : } 153 : return type; 154 : } 155 : 156 1 : bool _isParameterComponent(String component) { 157 1 : return component.startsWith(":"); 158 : } 159 : } 160 : 161 12 : enum ParseRouteSplitType { 162 12 : component, 163 12 : parameter, 164 : } 165 : 166 : class AppRouteMatch { 167 : Map<String, String> parameters = <String, String>{}; 168 : String route = '/'; 169 : } 170 : 171 : class ParseRouteSplitMatch { 172 0 : ParseRouteSplitMatch(this.routeSplit); 173 : 174 1 : ParseRouteSplitMatch.fromMatch(ParseRouteSplitMatch match, this.routeSplit) { 175 2 : parameters = <String, String>{}; 176 : if (match != null) { 177 0 : parameters.addAll(match.parameters); 178 : } 179 : } 180 : 181 : ParseRouteSplit routeSplit; 182 : Map<String, String> parameters = <String, String>{}; 183 : } 184 : 185 : class ParseRouteSplit { 186 1 : ParseRouteSplit(this.part, this.type); 187 : 188 : String part; 189 : ParseRouteSplitType type; 190 : List<String> routes = []; 191 : List<ParseRouteSplit> routeSplits = <ParseRouteSplit>[]; 192 : ParseRouteSplit parent; 193 : 194 1 : bool isParameter() { 195 2 : return type == ParseRouteSplitType.parameter; 196 : } 197 : }