Line data Source code
1 : import 'package:beamer/beamer.dart';
2 : import 'package:flutter/widgets.dart';
3 :
4 : import 'beam_page.dart';
5 : import 'beam_location.dart';
6 : import 'beamer_back_button_dispatcher.dart';
7 : import 'beamer_delegate.dart';
8 : import 'beamer_provider.dart';
9 : import 'path_url_strategy_nonweb.dart'
10 : if (dart.library.html) 'path_url_strategy_web.dart' as url_strategy;
11 :
12 : /// A wrapper for [Router].
13 : class Beamer extends StatefulWidget {
14 3 : const Beamer({
15 : Key? key,
16 : required this.routerDelegate,
17 : this.createBackButtonDispatcher = true,
18 : this.backButtonDispatcher,
19 3 : }) : super(key: key);
20 :
21 : /// Responsible for beaming, updating and rebuilding the page stack.
22 : final BeamerDelegate routerDelegate;
23 :
24 : /// Whether to create a [BeamerChildBackButtonDispatcher] automatically
25 : /// if the [backButtonDispatcher] is not set but parent has it.
26 : final bool createBackButtonDispatcher;
27 :
28 : /// Define how Android's back button should behave.
29 : ///
30 : /// Use [BeamerChildBackButtonDispatcher]
31 : /// instead of [BeamerBackButtonDispatcher].
32 : final BackButtonDispatcher? backButtonDispatcher;
33 :
34 : /// Access Beamer's [routerDelegate].
35 2 : static BeamerDelegate of(BuildContext context, {bool root = false}) {
36 : BeamerDelegate _delegate;
37 : try {
38 4 : _delegate = Router.of(context).routerDelegate as BeamerDelegate;
39 : } catch (e) {
40 1 : assert(BeamerProvider.of(context) != null,
41 : 'There was no Router nor BeamerProvider in current context. If using MaterialApp.builder, wrap the MaterialApp.router in BeamerProvider to which you pass the same routerDelegate as to MaterialApp.router.');
42 2 : return BeamerProvider.of(context)!.routerDelegate;
43 : }
44 : if (root) {
45 1 : return _delegate.root;
46 : }
47 : return _delegate;
48 : }
49 :
50 : /// Change the strategy to use for handling browser URL to [PathUrlStrategy].
51 : ///
52 : /// [PathUrlStrategy] uses the browser URL's pathname to represent Beamer's route name.
53 2 : static void setPathUrlStrategy() => url_strategy.setPathUrlStrategy();
54 :
55 3 : @override
56 3 : State<StatefulWidget> createState() => BeamerState();
57 : }
58 :
59 : class BeamerState extends State<Beamer> {
60 9 : BeamerDelegate get routerDelegate => widget.routerDelegate;
61 1 : BeamLocation get currentBeamLocation =>
62 3 : widget.routerDelegate.currentBeamLocation;
63 :
64 3 : @override
65 : void didChangeDependencies() {
66 3 : super.didChangeDependencies();
67 6 : routerDelegate.parent ??=
68 9 : Router.of(context).routerDelegate as BeamerDelegate;
69 : }
70 :
71 3 : @override
72 : Widget build(BuildContext context) {
73 3 : final parent = Router.of(context);
74 6 : routerDelegate.parent ??= parent.routerDelegate as BeamerDelegate;
75 6 : final backButtonDispatcher = widget.backButtonDispatcher ??
76 6 : ((parent.backButtonDispatcher is BeamerBackButtonDispatcher &&
77 2 : widget.createBackButtonDispatcher)
78 1 : ? BeamerChildBackButtonDispatcher(
79 : parent:
80 1 : parent.backButtonDispatcher! as BeamerBackButtonDispatcher,
81 1 : delegate: routerDelegate,
82 : )
83 : : null);
84 3 : return Router(
85 3 : routerDelegate: routerDelegate,
86 1 : backButtonDispatcher: backButtonDispatcher?..takePriority(),
87 : );
88 : }
89 : }
90 :
91 : extension BeamerExtensions on BuildContext {
92 : /// {@macro beamTo}
93 1 : void beamTo(
94 : BeamLocation location, {
95 : BeamLocation? popTo,
96 : TransitionDelegate? transitionDelegate,
97 : bool beamBackOnPop = false,
98 : bool popBeamLocationOnPop = false,
99 : bool stacked = true,
100 : bool replaceCurrent = false,
101 : }) {
102 2 : Beamer.of(this).beamTo(
103 : location,
104 : popTo: popTo,
105 : transitionDelegate: transitionDelegate,
106 : beamBackOnPop: beamBackOnPop,
107 : popBeamLocationOnPop: popBeamLocationOnPop,
108 : stacked: stacked,
109 : // replaceCurrent: replaceCurrent,
110 : );
111 : }
112 :
113 : /// {@macro beamToNamed}
114 1 : void beamToNamed(
115 : String uri, {
116 : Map<String, dynamic>? data,
117 : String? popToNamed,
118 : TransitionDelegate? transitionDelegate,
119 : bool beamBackOnPop = false,
120 : bool popBeamLocationOnPop = false,
121 : bool stacked = true,
122 : bool replaceCurrent = false,
123 : }) {
124 2 : Beamer.of(this).beamToNamed(
125 : uri,
126 : data: data,
127 : popToNamed: popToNamed,
128 : transitionDelegate: transitionDelegate,
129 : beamBackOnPop: beamBackOnPop,
130 : popBeamLocationOnPop: popBeamLocationOnPop,
131 : stacked: stacked,
132 : // replaceCurrent: replaceCurrent,
133 : );
134 : }
135 :
136 : /// {@macro popToNamed}
137 1 : void popToNamed(
138 : String uri, {
139 : Map<String, dynamic>? data,
140 : String? popToNamed,
141 : bool beamBackOnPop = false,
142 : bool popBeamLocationOnPop = false,
143 : bool stacked = true,
144 : bool replaceCurrent = false,
145 : }) {
146 2 : Beamer.of(this).popToNamed(
147 : uri,
148 : data: data,
149 : popToNamed: popToNamed,
150 : beamBackOnPop: beamBackOnPop,
151 : popBeamLocationOnPop: popBeamLocationOnPop,
152 : stacked: stacked,
153 : replaceCurrent: replaceCurrent,
154 : );
155 : }
156 :
157 : /// {@macro beamBack}
158 1 : void beamBack({Map<String, dynamic>? data}) =>
159 2 : Beamer.of(this).beamBack(data: data);
160 :
161 : /// {@macro popBeamLocation}
162 3 : void popBeamLocation() => Beamer.of(this).popBeamLocation();
163 :
164 : /// {@macro currentBeamLocation}
165 3 : BeamLocation get currentBeamLocation => Beamer.of(this).currentBeamLocation;
166 :
167 : /// {@macro currentPages}
168 3 : List<BeamPage> get currentBeamPages => Beamer.of(this).currentPages;
169 :
170 : /// {@macro beamingHistory}
171 3 : List<BeamLocation> get beamingHistory => Beamer.of(this).beamingHistory;
172 :
173 : /// {@macro canBeamBack}
174 3 : bool get canBeamBack => Beamer.of(this).canBeamBack;
175 :
176 : /// {@macro canPopBeamLocation}
177 3 : bool get canPopBeamLocation => Beamer.of(this).canPopBeamLocation;
178 : }
179 :
180 : extension BeamerRouteInformationExtension on RouteInformation {
181 6 : RouteInformation copyWith({
182 : String? location,
183 : Object? state,
184 : }) {
185 6 : return RouteInformation(
186 6 : location: location ?? this.location,
187 6 : state: state ?? this.state,
188 : );
189 : }
190 : }
|