Line data Source code
1 : part of '../../routemaster.dart'; 2 : 3 : /// A page that can create a state. 4 : abstract class StatefulPage<T> extends Page<T> { 5 : PageState createState(Routemaster delegate, RouteInfo info); 6 : 7 1 : @override 8 : Route<T> createRoute(BuildContext context) { 9 1 : throw UnimplementedError( 10 : 'Stateful pages do not directly create routes. Do not call createRoute on them directly.'); 11 : } 12 : } 13 : 14 : /// A wrapper around a page object. 15 : abstract class PageWrapper { 16 : /// Information about the current route. 17 : RouteInfo get routeInfo; 18 : 19 : /// Called when popping a route stack. Returns `true` if this page wrapper 20 : /// has been able to pop a page, otherwise `false`. 21 : Future<bool> maybePop(); 22 : 23 : /// Returns this page, and any descendant pages below it in the navigation 24 : /// hierarchy. 25 : Iterable<PageWrapper> getCurrentPages(); 26 : 27 : /// See if this page can consume the list of [pages] as children. For instance 28 : /// a tab page could accept the pages and put them in one of its tab's stacks. 29 : bool maybeSetChildPages(Iterable<PageWrapper> pages); 30 : 31 : /// Gets the actual Flutter [Page] object for passing to a [Navigator]. 32 : Page createPage(); 33 : } 34 : 35 : /// A page's state, similar to [State] for a [StatefulWidget]. For instance, 36 : /// maintains the current index for a tabbed page. 37 : abstract class PageState extends PageWrapper {} 38 : 39 : /// A page that wraps other pages in order to provide more functionality. 40 : /// 41 : /// For example, [Guarded] adds validation functionality for routes. 42 : abstract class ProxyPage<T> extends Page<T> { 43 : final Page<T> child; 44 : 45 3 : ProxyPage({required this.child}); 46 : 47 1 : @override 48 : Route<T> createRoute(BuildContext context) { 49 2 : return child.createRoute(context); 50 : } 51 : } 52 : 53 : /// A wrapper for normal, non-stateless pages that allows us to treat them like 54 : /// stateful ones. 55 : class StatelessPage extends PageWrapper { 56 10 : StatelessPage({ 57 : required this.routeInfo, 58 : required this.page, 59 10 : }) : assert(page is! Redirect); 60 : 61 : final Page page; 62 : 63 : @override 64 : final RouteInfo routeInfo; 65 : 66 : @override 67 : Iterable<PageWrapper> getCurrentPages() sync* { 68 : yield this; 69 : } 70 : 71 2 : @override 72 2 : Future<bool> maybePop() => SynchronousFuture(false); 73 : 74 5 : @override 75 : bool maybeSetChildPages(Iterable<PageWrapper> pages) => false; 76 : 77 10 : @override 78 10 : Page createPage() => page; 79 : } 80 : 81 : /// A fake page state to wrap redirects 82 : class _RedirectWrapper extends PageWrapper { 83 : final Redirect redirectPage; 84 : 85 2 : _RedirectWrapper(this.redirectPage); 86 : 87 0 : @override 88 : Iterable<PageWrapper> getCurrentPages() { 89 0 : throw UnimplementedError(); 90 : } 91 : 92 0 : @override 93 : Future<bool> maybePop() { 94 0 : throw UnimplementedError(); 95 : } 96 : 97 0 : @override 98 : bool maybeSetChildPages(Iterable<PageWrapper> pages) { 99 0 : throw UnimplementedError(); 100 : } 101 : 102 0 : @override 103 0 : RouteInfo get routeInfo => throw UnimplementedError(); 104 : 105 0 : @override 106 : Page createPage() { 107 0 : throw UnimplementedError(); 108 : } 109 : }