Line data Source code
1 : import 'package:flutter/material.dart'; 2 : 3 : import '../destination.dart'; 4 : import '../navigation_controller.dart'; 5 : import '../utils/log/log.dart'; 6 : 7 : /// Builds a navigation widget. 8 : /// 9 : /// It is used by [NavigationController] to build a navigation widget sub-tree 10 : /// around a content of destinations, managed by this navigation controller. 11 : /// 12 : /// See also: 13 : /// - [DefaultNavigatorBuilder] 14 : /// - [BottomNavigationBuilder] 15 : /// 16 : abstract class NavigatorBuilder { 17 : /// Creates an instance of [NavigatorBuilder]. 18 : /// 19 : /// Does not keep upward destination by default. 20 : /// 21 17 : const NavigatorBuilder({ 22 : KeepingStateInParameters? keepStateInParameters, 23 : }) : keepStateInParameters = 24 : keepStateInParameters ?? KeepingStateInParameters.auto; 25 : 26 : /// Automatic persisting of upward destination. 27 : /// 28 : final KeepingStateInParameters keepStateInParameters; 29 : 30 : /// Returns a widget that wraps a content of navigator's destinations. 31 : /// 32 : Widget build(BuildContext context, NavigationController navigator); 33 : } 34 : 35 : /// Implementation of [NavigatorBuilder] that manages a stack of destinations using 36 : /// Flutter's [Navigator] widget. 37 : /// 38 : class DefaultNavigatorBuilder extends NavigatorBuilder { 39 : /// Creates an instance of [DefaultNavigatorBuilder]. 40 : /// 41 : /// Set [NavigatorBuilder.keepStateInParameters] to [KeepingStateInParameters.auto] 42 : /// by default to allow persisting navigation stack in the web browser history. 43 : /// 44 17 : const DefaultNavigatorBuilder({ 45 : KeepingStateInParameters? keepStateInParameters, 46 0 : }) : super(keepStateInParameters: keepStateInParameters); 47 : 48 3 : @override 49 : Widget build(BuildContext context, NavigationController navigator) { 50 3 : final pages = <_TheseusPage>[]; 51 12 : for (int i = 0; i < navigator.stack.length; i++) { 52 6 : final destination = navigator.stack[i]; 53 6 : pages.add(_TheseusPage( 54 : // TODO: Remove reference to 'i' in the key 55 9 : key: ValueKey('${destination.uri}-$i'), 56 : destination: destination, 57 : )); 58 : } 59 3 : return Navigator( 60 3 : key: navigator.key, 61 : pages: pages, 62 0 : onPopPage: (route, result) { 63 0 : Log.d(runtimeType, 'onPopPage()'); 64 0 : navigator.goBack(); 65 0 : route.didPop(result); 66 : return true; 67 : }, 68 : ); 69 : } 70 : } 71 : 72 : class _TheseusPage extends Page { 73 3 : const _TheseusPage({ 74 : required this.destination, 75 : required LocalKey key, 76 3 : }) : super(key: key); 77 : 78 : final Destination destination; 79 : 80 3 : @override 81 : Route createRoute(BuildContext context) { 82 9 : switch (destination.settings.transition) { 83 3 : case DestinationTransition.material: 84 3 : return MaterialPageRoute( 85 : settings: this, 86 9 : builder: (context) => destination.build(context), 87 : ); 88 0 : case DestinationTransition.materialDialog: 89 0 : return DialogRoute( 90 : context: context, 91 : settings: this, 92 0 : builder: (context) => destination.build(context), 93 : ); 94 0 : case DestinationTransition.custom: 95 0 : return PageRouteBuilder( 96 : settings: this, 97 0 : pageBuilder: (context, animation, secondaryAnimation) => 98 0 : destination.build(context), 99 0 : transitionsBuilder: destination.settings.transitionBuilder!, 100 : ); 101 : case DestinationTransition.none: 102 : default: 103 0 : return PageRouteBuilder( 104 : settings: this, 105 0 : pageBuilder: (context, animation, secondaryAnimation) => 106 0 : destination.build(context), 107 0 : transitionsBuilder: (context, animation, secondaryAnimation, child) => 108 : child, 109 : ); 110 : } 111 : } 112 : }