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 : 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 1 : static BeamerDelegate of(BuildContext context, {bool root = false}) {
36 : BeamerDelegate _delegate;
37 : try {
38 2 : _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 1 : parent: parent.backButtonDispatcher!,
80 1 : delegate: routerDelegate,
81 : )
82 : : null);
83 3 : return Router(
84 3 : routerDelegate: routerDelegate,
85 1 : backButtonDispatcher: backButtonDispatcher?..takePriority(),
86 : );
87 : }
88 : }
89 :
90 : extension BeamerExtensions on BuildContext {
91 : /// {@macro beamTo}
92 1 : void beamTo(
93 : BeamLocation location, {
94 : BeamLocation? popTo,
95 : TransitionDelegate? transitionDelegate,
96 : bool beamBackOnPop = false,
97 : bool popBeamLocationOnPop = false,
98 : bool stacked = true,
99 : bool replaceCurrent = false,
100 : }) {
101 2 : Beamer.of(this).beamTo(
102 : location,
103 : popTo: popTo,
104 : transitionDelegate: transitionDelegate,
105 : beamBackOnPop: beamBackOnPop,
106 : popBeamLocationOnPop: popBeamLocationOnPop,
107 : stacked: stacked,
108 : replaceCurrent: replaceCurrent,
109 : );
110 : }
111 :
112 : /// {@macro beamToNamed}
113 1 : void beamToNamed(
114 : String uri, {
115 : Map<String, dynamic>? data,
116 : String? popToNamed,
117 : TransitionDelegate? transitionDelegate,
118 : bool beamBackOnPop = false,
119 : bool popBeamLocationOnPop = false,
120 : bool stacked = true,
121 : bool replaceCurrent = false,
122 : }) {
123 2 : Beamer.of(this).beamToNamed(
124 : uri,
125 : data: data,
126 : popToNamed: popToNamed,
127 : transitionDelegate: transitionDelegate,
128 : beamBackOnPop: beamBackOnPop,
129 : popBeamLocationOnPop: popBeamLocationOnPop,
130 : stacked: stacked,
131 : replaceCurrent: replaceCurrent,
132 : );
133 : }
134 :
135 : /// {@macro popToNamed}
136 1 : void popToNamed(
137 : String uri, {
138 : Map<String, dynamic>? data,
139 : String? popToNamed,
140 : bool beamBackOnPop = false,
141 : bool popBeamLocationOnPop = false,
142 : bool stacked = true,
143 : bool replaceCurrent = false,
144 : }) {
145 2 : Beamer.of(this).popToNamed(
146 : uri,
147 : data: data,
148 : popToNamed: popToNamed,
149 : beamBackOnPop: beamBackOnPop,
150 : popBeamLocationOnPop: popBeamLocationOnPop,
151 : stacked: stacked,
152 : replaceCurrent: replaceCurrent,
153 : );
154 : }
155 :
156 : /// {@macro beamBack}
157 1 : void beamBack({Map<String, dynamic>? data}) =>
158 2 : Beamer.of(this).beamBack(data: data);
159 :
160 : /// {@macro popBeamLocation}
161 3 : void popBeamLocation() => Beamer.of(this).popBeamLocation();
162 :
163 : /// {@macro currentBeamLocation}
164 3 : BeamLocation get currentBeamLocation => Beamer.of(this).currentBeamLocation;
165 :
166 : /// {@macro currentPages}
167 3 : List<BeamPage> get currentBeamPages => Beamer.of(this).currentPages;
168 :
169 : /// {@macro beamStateHistory}
170 3 : List<BeamState> get beamStateHistory => Beamer.of(this).beamStateHistory;
171 :
172 : /// {@macro canBeamBack}
173 3 : bool get canBeamBack => Beamer.of(this).canBeamBack;
174 :
175 : /// {@macro beamLocationHistory}
176 1 : List<BeamLocation> get beamLocationHistory =>
177 2 : Beamer.of(this).beamLocationHistory;
178 :
179 : /// {@macro canPopBeamLocation}
180 3 : bool get canPopBeamLocation => Beamer.of(this).canPopBeamLocation;
181 : }
|