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