Line data Source code
1 : part of 'main.dart'; 2 : 3 : /// Widget which allows you to handle navigation event directly in 4 : /// you widgets. 5 : /// Any [VNavigationGuard] is associated to the [VRouteElement] above it 6 : /// in the route tree. 7 : class VNavigationGuard extends StatefulWidget { 8 : /// The child of this widget 9 : final Widget child; 10 : 11 : /// Called when the route changes and the [VRouteElement] 12 : /// associated to this [VNavigationGuard] is in the previous route 13 : /// but not in the new one 14 : /// 15 : /// Use [vRedirector] if you want to redirect or stop the navigation. 16 : /// DO NOT use VRouter methods to redirect. 17 : /// [vRedirector] also has information about the route you leave and the route you go to 18 : /// 19 : /// Use [newVRouteData] if you want information on the new route but be 20 : /// careful, on the web newVRouteData is null when a user types a url manually 21 : /// 22 : /// Use [newVRouteData] if you want information on the new route but be 23 : /// careful, on the web newVRouteData is null when a user types a url manually 24 : /// 25 : /// [saveHistoryState] can be used to save a history state before leaving 26 : /// This history state will be restored if the user uses the back button 27 : /// You will find the saved history state in the [VRouteElementData] using 28 : /// [VRouteElementData.of(context).historyState] 29 : /// WARNING: Since the history state is saved in [VRouteElementData], if you have 30 : /// multiple VNavigationGuards associated to the same [VRouteElement], only one 31 : /// should use [saveHistoryState]. 32 : /// 33 : /// Note that you should consider the navigation cycle to 34 : /// handle this precisely, see [https://vrouter.dev/guide/Advanced/Navigation%20Control/The%20Navigation%20Cycle] 35 : /// 36 : /// Also see: 37 : /// * [VRouter.beforeLeave] for global level beforeLeave 38 : /// * [VRouteElement.beforeLeave] for route level beforeLeave 39 : /// * [VRedirector] to known how to redirect and have access to route information 40 : final Future<void> Function( 41 : VRedirector? vRedirector, 42 : void Function(Map<String, String> state) saveHistoryState, 43 : ) beforeLeave; 44 : 45 : /// This is called before the url is updated, if this [VRouteElement] is in the previous route 46 : /// AND in the new route 47 : /// 48 : /// Use [vRedirector] if you want to redirect or stop the navigation. 49 : /// DO NOT use VRouter methods to redirect. 50 : /// [vRedirector] also has information about the route you leave and the route you go to 51 : /// 52 : /// Note that you should consider the navigation cycle to 53 : /// handle this precisely, see [https://vrouter.dev/guide/Advanced/Navigation%20Control/The%20Navigation%20Cycle] 54 : /// 55 : /// Also see: 56 : /// * [VRouter.beforeEnter] for global level beforeEnter 57 : /// * [VRedirector] to known how to redirect and have access to route information 58 : final Future<void> Function(VRedirector vRedirector) beforeUpdate; 59 : 60 : /// Called when the url changes and this [VNavigationGuard] was NOT part 61 : /// of the previous route. 62 : /// 63 : /// This is called after the url and the state of you app has change 64 : /// so any data in [VRouteElementData] is up to date 65 : /// 66 : /// Note that you should consider the navigation cycle to 67 : /// handle this precisely, see [https://vrouter.dev/guide/Advanced/Navigation%20Control/The%20Navigation%20Cycle] 68 : /// 69 : /// Also see: 70 : /// * [VRouter.afterEnter] for global level afterEnter 71 : /// * [VRouteElement.afterEnter] for route level afterEnter 72 : final void Function(BuildContext context, String? from, String to) afterEnter; 73 : 74 : /// Called when the url changes and this [VNavigationGuard] was already part 75 : /// of the previous route. 76 : /// 77 : /// This is called after the url and the state of you app has change 78 : /// so any data in [VRouteElementData] is up to date 79 : /// 80 : /// Note that you should consider the navigation cycle to 81 : /// handle this precisely, see [https://vrouter.dev/guide/Advanced/Navigation%20Control/The%20Navigation%20Cycle] 82 : final void Function(BuildContext context, String? from, String to) 83 : afterUpdate; 84 : 85 : /// Called when a pop event occurs. 86 : /// A pop event can be called programmatically (with [VRouterData.of(context).pop()]) 87 : /// or by other widgets such as the appBar back button 88 : /// 89 : /// Use [vRedirector] if you want to redirect or stop the navigation. 90 : /// DO NOT use VRouter methods to redirect. 91 : /// [vRedirector] also has information about the route you leave and the route you go to 92 : /// 93 : /// The route you go to is calculated based on [VRouterState._defaultPop] 94 : /// 95 : /// Note that you should consider the pop cycle to 96 : /// handle this precisely, see [https://vrouter.dev/guide/Advanced/Pop%20Events/onPop] 97 : /// 98 : /// Also see: 99 : /// * [VRouter.onPop] for global level onPop 100 : /// * [VRouteElement.onPop] for route level onPop 101 : /// * [VRedirector] to known how to redirect and have access to route information 102 : final Future<void> Function(VRedirector vRedirector) onPop; 103 : 104 : /// Called when a system pop event occurs. 105 : /// This happens on android when the system back button is pressed 106 : /// 107 : /// Use [vRedirector] if you want to redirect or stop the navigation. 108 : /// DO NOT use VRouter methods to redirect. 109 : /// [vRedirector] also has information about the route you leave and the route you go to 110 : /// 111 : /// The route you go to is calculated based on [VRouterState._defaultPop] 112 : /// 113 : /// Note that you should consider the systemPop cycle to 114 : /// handle this precisely, see [https://vrouter.dev/guide/Advanced/Pop%20Events/onSystemPop] 115 : /// 116 : /// Also see: 117 : /// * [VRouter.onSystemPop] for global level onSystemPop 118 : /// * [VRouteElement.onSystemPop] for route level onSystemPop 119 : /// * [VRedirector] to known how to redirect and have access to route information 120 : final Future<void> Function(VRedirector vRedirector) onSystemPop; 121 : 122 0 : const VNavigationGuard({ 123 : Key? key, 124 : this.afterEnter = VRouteElement._voidAfterEnter, 125 : this.afterUpdate = VRouteElement._voidAfterUpdate, 126 : this.beforeUpdate = VRouteElement._voidBeforeUpdate, 127 : this.beforeLeave = VRouteElement._voidBeforeLeave, 128 : this.onPop = VRouteElement._voidOnPop, 129 : this.onSystemPop = VRouteElement._voidOnSystemPop, 130 : required this.child, 131 0 : }) : super(key: key); 132 : 133 0 : @override 134 0 : _VNavigationGuardState createState() => _VNavigationGuardState(); 135 : } 136 : 137 : class _VNavigationGuardState extends State<VNavigationGuard> { 138 0 : @override 139 : void initState() { 140 0 : VNavigationGuardMessage(vNavigationGuard: widget, localContext: context) 141 0 : .dispatch(context); 142 0 : super.initState(); 143 0 : WidgetsBinding.instance?.addPostFrameCallback((_) { 144 0 : widget.afterEnter( 145 0 : context, VRouter.of(context).previousUrl, VRouter.of(context).url!); 146 : }); 147 : } 148 : 149 : // This is used to try to support hot restart 150 : // However it seems that even with this, two hot reloads 151 : // are necessary when changes to VNavigationGuard are made 152 0 : @override 153 : void reassemble() { 154 0 : VNavigationGuardMessage(vNavigationGuard: widget, localContext: context) 155 0 : .dispatch(context); 156 0 : super.reassemble(); 157 : } 158 : 159 0 : @override 160 : Widget build(BuildContext context) { 161 0 : return widget.child; 162 : } 163 : } 164 : 165 : /// This message is a notification that each [VNavigationGuard] sends 166 : /// and received by their associated [VRouteElementWidget] which will in turn 167 : /// send a [VNavigationGuardRootMessage] for the [VRouter] 168 : class VNavigationGuardMessage extends Notification { 169 : final VNavigationGuard vNavigationGuard; 170 : final BuildContext localContext; 171 : 172 0 : VNavigationGuardMessage( 173 : {required this.vNavigationGuard, required this.localContext}); 174 : } 175 : 176 : class VNavigationGuardMessageRoot extends Notification { 177 : final VNavigationGuard vNavigationGuard; 178 : final BuildContext localContext; 179 : final VRouteElementWithPage associatedVRouteElement; 180 : 181 0 : VNavigationGuardMessageRoot( 182 : {required this.vNavigationGuard, 183 : required this.localContext, 184 : required this.associatedVRouteElement}); 185 : }