fluro/lib/src/router.dart

159 lines
6.0 KiB
Dart
Raw Normal View History

2017-05-04 15:33:40 -04:00
/*
2017-05-14 01:01:02 -04:00
* fluro
2017-05-04 15:33:40 -04:00
* A Posse Production
* http://goposse.com
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
* See LICENSE for distribution and usage details.
*/
2017-05-14 00:28:28 -04:00
part of fluro;
2017-04-25 03:24:14 -04:00
2017-05-04 15:27:32 -04:00
enum TransitionType {
native,
nativeModal,
2017-05-13 20:52:27 -04:00
inFromLeft,
inFromRight,
inFromBottom,
fadeIn,
custom, // if using custom then you must also provide a transition
2017-05-04 15:27:32 -04:00
}
2017-04-25 03:24:14 -04:00
class Router {
/// The tree structure that stores the defined routes
RouteTree _routeTree = new RouteTree();
/// Generic handler for when a route has not been defined
Handler notFoundHandler;
/// Creates a [PageRoute] definition for the passed [RouteHandler]. You can optionally provide a custom
/// transition builder for the route.
void define(String routePath, {@required Handler handler}) {
2017-05-04 15:27:32 -04:00
_routeTree.addRoute(new AppRoute(routePath, handler));
2017-04-25 03:24:14 -04:00
}
2017-05-04 15:27:32 -04:00
/// Finds a defined [AppRoute] for the path value. If no [AppRoute] definition was found
/// then function will return null.
AppRouteMatch match(String path) {
return _routeTree.matchRoute(path);
2017-04-25 03:24:14 -04:00
}
2017-05-04 15:27:32 -04:00
///
2017-05-13 20:52:27 -04:00
void navigateTo(BuildContext context, String path, {TransitionType transition = TransitionType.native,
Duration transitionDuration = const Duration(milliseconds: 250),
RouteTransitionsBuilder transitionBuilder})
{
RouteMatch routeMatch = matchRoute(context, path, transitionType: transition,
2017-05-13 20:52:27 -04:00
transitionsBuilder: transitionBuilder, transitionDuration: transitionDuration);
Route<Null> route = routeMatch.route;
if (routeMatch.matchType == RouteMatchType.nonVisual) {
return;
}
2017-05-04 15:27:32 -04:00
if (route == null && notFoundHandler != null) {
route = _notFoundRoute(context, path);
}
if (route != null) {
Navigator.push(context, route);
} else {
print("No registered route was found to handle '$path'.");
}
2017-04-25 03:24:14 -04:00
}
2017-05-04 15:27:32 -04:00
///
Route<Null> _notFoundRoute(BuildContext context, String path) {
RouteCreator creator = (RouteSettings routeSettings, Map<String, dynamic> parameters) {
2017-05-04 15:27:32 -04:00
return new MaterialPageRoute<Null>(settings: routeSettings, builder: (BuildContext context) {
return notFoundHandler.handlerFunc(context, parameters);
2017-05-04 15:27:32 -04:00
});
};
return creator(new RouteSettings(name: path), null);
2017-04-25 03:24:14 -04:00
}
2017-05-04 15:27:32 -04:00
///
RouteMatch matchRoute(BuildContext buildContext, String path, {RouteSettings routeSettings = null,
2017-05-13 20:52:27 -04:00
TransitionType transitionType, Duration transitionDuration = const Duration(milliseconds: 250),
RouteTransitionsBuilder transitionsBuilder})
{
RouteSettings settingsToUse = routeSettings;
if (routeSettings == null) {
settingsToUse = new RouteSettings(name: path);
}
AppRouteMatch match = _routeTree.matchRoute(path);
2017-05-04 15:27:32 -04:00
AppRoute route = match?.route;
Handler handler = (route != null ? route.handler : notFoundHandler);
2017-05-04 15:27:32 -04:00
if (route == null && notFoundHandler == null) {
return new RouteMatch(matchType: RouteMatchType.noMatch, errorMessage: "No matching route was found");
2017-04-25 03:24:14 -04:00
}
Map<String, String> parameters = match?.parameters ?? <String, String>{};
if (handler.type == HandlerType.function) {
handler.handlerFunc(buildContext, parameters);
return new RouteMatch(matchType: RouteMatchType.nonVisual);
}
RouteCreator creator = (RouteSettings routeSettings, Map<String, dynamic> parameters) {
2017-05-13 20:52:27 -04:00
bool isNativeTransition = (transitionType == TransitionType.native || transitionType == TransitionType.nativeModal);
if (isNativeTransition) {
return new MaterialPageRoute<Null>(settings: routeSettings, fullscreenDialog: transitionType == TransitionType.nativeModal,
builder: (BuildContext context) {
return handler.handlerFunc(context, parameters);
2017-05-13 20:52:27 -04:00
});
} else {
var routeTransitionsBuilder;
if (transitionType == TransitionType.custom) {
routeTransitionsBuilder = transitionsBuilder;
} else {
routeTransitionsBuilder = _standardTransitionsBuilder(transitionType);
}
return new PageRouteBuilder<Null>(settings: routeSettings,
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return handler.handlerFunc(context, parameters);
2017-05-13 20:52:27 -04:00
},
transitionDuration: transitionDuration,
transitionsBuilder: routeTransitionsBuilder,
);
}
2017-05-04 15:27:32 -04:00
};
return new RouteMatch(
matchType: RouteMatchType.visual,
route: creator(settingsToUse, parameters),
);
}
2017-05-13 20:52:27 -04:00
RouteTransitionsBuilder _standardTransitionsBuilder(TransitionType transitionType) {
return (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
if (transitionType == TransitionType.fadeIn) {
return new FadeTransition(opacity: animation, child: child);
} else {
FractionalOffset startOffset = FractionalOffset.bottomLeft;
FractionalOffset endOffset = FractionalOffset.topLeft;
if (transitionType == TransitionType.inFromLeft) {
startOffset = new FractionalOffset(-1.0, 0.0);
endOffset = FractionalOffset.topLeft;
} else if (transitionType == TransitionType.inFromRight) {
startOffset = FractionalOffset.topRight;
endOffset = FractionalOffset.topLeft;
}
return new SlideTransition(
position: new FractionalOffsetTween(
begin: startOffset,
end: endOffset,
).animate(animation),
child: child,
);
}
};
}
2017-05-04 15:27:32 -04:00
/// Route generation method. This function can be used as a way to create routes on-the-fly
/// if any defined handler is found. It can also be used with the [MaterialApp.onGenerateRoute]
/// property as callback to create routes that can be used with the [Navigator] class.
Route<Null> generator(RouteSettings routeSettings) {
RouteMatch match = matchRoute(null, routeSettings.name, routeSettings: routeSettings);
return match.route;
2017-04-25 03:24:14 -04:00
}
/// Prints the route tree so you can analyze it.
void printTree() {
_routeTree.printTree();
}
}