Skip to content

Commit 9d4bb07

Browse files
Merge pull request flutter#1 from slovnicki/master
merge new updates
2 parents 001010a + d6cf233 commit 9d4bb07

35 files changed

+1374
-366
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
# 0.7.0
2+
3+
- **BREAKING:** `BeamerRouterDelegate.notFoundPage` is now `BeamPage` instead of `Widget`
4+
- **BREAKING:** `BeamGuard.showPage` is now `BeamPage` instead of `Widget`
5+
- **NEW FEATURE:** `beamBack` now goes back through `beamHistory`
6+
- **NEW FEATURE:** `beamTo` can take an optional `beamBackOnPop` boolean
7+
- **NEW FEATURE:** `BeamLocation.builder` can be used to provide something to the entire location
8+
- **NEW EXAMPLE:** location_builder
9+
- **NEW EXAMPLE:** animated_rail
10+
- tweaks and improvements to the documentation
11+
112
# 0.6.4+1
213

314
- **Add** logo image

README.md

+152-56
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ Handle your application routing, synchronize it with browser URL and more. `Beam
2828
- [Books](#books)
2929
- [Advanced Books](#advanced-books)
3030
- [Deep Location](#deep-location)
31+
- [Location Builder](#location-builder)
3132
- [Guards](#guards)
32-
- [Bottom Navigation (WIP)](#bottom-navigation-(wip))
33+
- [Beamer Widget](#beamer-widget)
34+
- [Integration with Navigation UI Packages](#integration-with-navigation-ui-packages)
3335
- [Usage](#usage)
34-
- [With *App.router](#with-app.router)
35-
- [As a Widget (WIP)](#as-a-widget-(wip))
36+
- [On Entire App](#on-entire-app)
37+
- [As a Widget](#as-a-widget)
3638
- [General Notes](#general-notes)
3739
- [Migrating from 0.4.x to >=0.5.x](#migrating-from-0.4.x-to->=0.5.x)
3840
- [Contributing](#contributing)
@@ -72,39 +74,163 @@ Using Beamer _can_ feel like using many of `Navigator`'s `push/pop` methods at o
7274
Here is a recreation of books example from [this article](https://medium.com/flutter/learning-flutters-new-navigation-and-routing-system-7c9068155ade) where you can learn a lot about Navigator 2.0. See [Example](https://pub.dev/packages/beamer/example) for full application code of this example.
7375

7476
<p align="center">
75-
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-books.gif" alt="example-books" style="margin-right:32px;margin-left:32px">
77+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-books.gif" alt="example-books" width="520">
7678

7779
## Advanced Books
7880

7981
For a step further, we add more flows to demonstrate the power of Beamer. The full code is available [here](https://github.com/slovnicki/beamer/tree/master/examples/advanced_books).
8082

8183
<p align="center">
82-
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-advanced-books.gif" alt="example-advanced-books" style="margin-right:32px;margin-left:32px">
84+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-advanced-books.gif" width="520">
8385

8486
## Deep Location
8587

86-
You can instantly beam to a location in your app that has many pages stacked (deep linking) and then pop them one by one or simply `beamBack` to where you came from. The full code is available [here](https://github.com/slovnicki/beamer/tree/master/examples/deep_location).
88+
You can instantly beam to a location in your app that has many pages stacked (deep linking) and then pop them one by one or simply `beamBack` to where you came from. The full code is available [here](https://github.com/slovnicki/beamer/tree/master/examples/deep_location). Note that `beamBackOnPop` parameter of `beamTo` might be useful here to override `AppBar`'s `pop` with `beamBack`.
8789

8890
<p align="center">
89-
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-deep-location.gif" alt="example-deep-location" style="margin-right:32px;margin-left:32px">
91+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-deep-location.gif" alt="example-deep-location" width="260">
92+
93+
```dart
94+
ElevatedButton(
95+
onPressed: () => context.beamTo(DeepLocation('/a/b/c/d')),
96+
// onPressed: () => context.beamTo(DeepLocation('/a/b/c/d'), beamBackOnPop: true),
97+
child: Text('Beam deep'),
98+
),
99+
```
100+
101+
## Location Builder
102+
103+
You can override `BeamLocation.builder` to provide some data to the entire location, i.e. to all of the `pages`. The full code is available [here](https://github.com/slovnicki/beamer/tree/master/examples/location_builder).
104+
105+
<p align="center">
106+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-location-builder.gif" width="260">
107+
108+
```dart
109+
// in your location implementation
110+
@override
111+
Widget builder(BuildContext context, Navigator navigator) {
112+
return MyProvider<MyObject>(
113+
create: (context) => MyObject(),
114+
child: navigator,
115+
);
116+
}
117+
```
90118

91119
## Guards
92120

93121
You can define global guards (for example, authentication guard) or location guards that keep a specific location safe. The full code is available [here](https://github.com/slovnicki/beamer/tree/master/examples/guards).
94122

95123
<p align="center">
96-
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-guards.gif" alt="example-guards" style="margin-right:32px;margin-left:32px">
124+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-guards.gif" alt="example-guards" width="520">
125+
126+
- Global Guards
127+
128+
```dart
129+
BeamerRouterDelegate(
130+
initialLocation: initialLocation,
131+
guards: [
132+
BeamGuard(
133+
pathBlueprints: ['/books*'],
134+
check: (context, location) => AuthenticationStateProvider.of(context).isAuthenticated.value,
135+
beamTo: (context) => LoginLocation(),
136+
),
137+
],
138+
),
139+
```
140+
141+
- Location (local) Guards
97142

98-
## Bottom Navigation (WIP)
143+
```dart
144+
// in your location implementation
145+
@override
146+
List<BeamGuard> get guards => [
147+
BeamGuard(
148+
pathBlueprints: ['/books/*'],
149+
check: (context, location) => location.pathParameters['bookId'] != '2',
150+
showPage: forbiddenPage,
151+
),
152+
];
153+
```
99154

100-
An example of putting `Beamer` into widget tree. **This is not yet fully functional for web usage**; setting the URL from browser doesn't update the state properly. It should work when [nested routers issue](https://github.com/slovnicki/beamer/issues/4) is done. The full code is available [here](https://github.com/slovnicki/beamer/tree/master/examples/bottom_navigation).
155+
## Beamer Widget
156+
157+
An example of putting `Beamer`(s) into the Widget tree. _This is not yet fully functional for web usage_; setting the URL from browser doesn't update the state properly. It should work when [nested routers issue](https://github.com/slovnicki/beamer/issues/4) is settled.
101158

102159
<p align="center">
103-
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-bottom-navigation-mobile.gif" alt="example-bottom-navigation" style="margin-right:32px;margin-left:32px">
160+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-bottom-navigation-mobile.gif" width="240" style="margin-right: 32px">
161+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-bottom-navigation-multiple-beamers.gif" width="240">
104162

105-
# Usage
163+
- [Bottom navigation example](https://github.com/slovnicki/beamer/tree/master/examples/bottom_navigation)
164+
```dart
165+
class MyApp extends StatelessWidget {
166+
final _beamerKey = GlobalKey<BeamerState>();
106167
107-
## With *App.router
168+
@override
169+
Widget build(BuildContext context) {
170+
return MaterialApp(
171+
home: Scaffold(
172+
body: Beamer(
173+
key: _beamerKey,
174+
beamLocations: _beamLocations,
175+
),
176+
bottomNavigationBar: BottomNavigationBarWidget(
177+
beamerKey: _beamerKey,
178+
),
179+
),
180+
);
181+
}
182+
}
183+
```
184+
185+
- [Bottom navigation example with multiple Beamers](https://github.com/slovnicki/beamer/tree/master/examples/bottom_navigation_multiple_beamers)
186+
```dart
187+
class MyAppState extends State<MyApp> {
188+
int _currentIndex = 0;
189+
190+
@override
191+
Widget build(BuildContext context) {
192+
return MaterialApp(
193+
home: Scaffold(
194+
body: IndexedStack(
195+
index: _currentIndex,
196+
children: [
197+
Beamer(
198+
beamLocations: [ArticlesLocation()],
199+
),
200+
Container(
201+
color: Colors.blueAccent,
202+
padding: const EdgeInsets.all(32.0),
203+
child: Beamer(
204+
beamLocations: [BooksLocation()],
205+
),
206+
),
207+
],
208+
),
209+
bottomNavigationBar: BottomNavigationBar(
210+
currentIndex: _currentIndex,
211+
items: [
212+
BottomNavigationBarItem(label: 'A', icon: Icon(Icons.article)),
213+
BottomNavigationBarItem(label: 'B', icon: Icon(Icons.book)),
214+
],
215+
onTap: (index) => setState(() => _currentIndex = index),
216+
),
217+
),
218+
);
219+
}
220+
}
221+
```
222+
223+
---
224+
## Integration with Navigation UI Packages
225+
226+
- [Animated Rail Example](https://github.com/slovnicki/beamer/tree/master/examples/animated_rail), with [animated_rail](https://pub.dev/packages/animated_rail) package.
227+
- ... (contributions are very welcome, add your suggestions [here](https://github.com/slovnicki/beamer/issues/79))
228+
229+
<img src="https://raw.githubusercontent.com/slovnicki/beamer/master/res/example-animated-rail.gif" alt="example-bottom-navigation" width="240">
230+
231+
---
232+
# Usage
233+
## On Entire App
108234

109235
In order to use Beamer on your entire app, you must (as per [official documentation](https://api.flutter.dev/flutter/widgets/Router-class.html)) construct your `*App` widget with `.router` constructor to which (along with all your regular `*App` attributes) you provide
110236

@@ -133,53 +259,23 @@ class MyApp extends StatelessWidget {
133259
}
134260
```
135261

136-
## As a Widget (WIP)
262+
## As a Widget
137263

138-
```dart
139-
class MyApp extends StatefulWidget {
140-
@override
141-
_MyAppState createState() => _MyAppState();
142-
}
143-
144-
class _MyAppState extends State<MyApp> {
145-
final List<BeamLocation> _beamLocations = [
146-
BooksLocation(pathBlueprint: '/books'),
147-
ArticlesLocation(pathBlueprint: '/articles'),
148-
];
149-
final _beamerKey = GlobalKey<BeamerState>();
150-
Beamer _beamer;
151-
int _currentIndex = 0;
152-
153-
@override
154-
void initState() {
155-
_beamer = Beamer(
156-
key: _beamerKey,
157-
routerDelegate: BeamerRouterDelegate(initialLocation: _beamLocations[0]),
158-
routeInformationParser: BeamerRouteInformationParser(
159-
beamLocations: _beamLocations,
160-
),
161-
);
162-
super.initState();
163-
}
264+
_(not yet fully functional on web, regarding URL parsing)_
164265

266+
```dart
267+
class MyApp extends StatelessWidget {
165268
@override
166269
Widget build(BuildContext context) {
167270
return MaterialApp(
168-
debugShowCheckedModeBanner: false,
169271
home: Scaffold(
170-
body: _beamer,
171-
bottomNavigationBar: BottomNavigationBar(
172-
currentIndex: _currentIndex,
173-
items: [
174-
BottomNavigationBarItem(label: 'Books', icon: Icon(Icons.book)),
175-
BottomNavigationBarItem(
176-
label: 'Articles', icon: Icon(Icons.article)),
177-
],
178-
onTap: (index) {
179-
setState(() => _currentIndex = index);
180-
_beamerKey.currentState.routerDelegate
181-
.beamTo(_beamLocations[index]);
182-
}),
272+
body: Beamer(
273+
beamLocations: [
274+
HomeLocation(),
275+
BooksLocation(),
276+
],
277+
),
278+
...
183279
),
184280
);
185281
}
@@ -188,8 +284,8 @@ class _MyAppState extends State<MyApp> {
188284

189285
## General Notes
190286

191-
- When extending `BeamLocation`, two getters need to be implemented; `pathBlueprints` and `pages`.
192-
- `pages` represent a stack that will be built by `Navigator` when you beam there, and `pathBlueprints` is there for Beamer to decide which `BeamLocation` corresponds to an URL coming from browser.
287+
- When extending `BeamLocation`, two methods need to be implemented; `pathBlueprints` and `pagesBuilder`.
288+
- `pagesBuilder` returns a stack of pages that will be built by `Navigator` when you beam there, and `pathBlueprints` is there for Beamer to decide which `BeamLocation` corresponds to an URL coming from browser.
193289
- `BeamLocation` takes query and path parameters from URI. The `:` is necessary in `pathBlueprints` if you _might_ get path parameter from browser.
194290

195291
- `BeamPage`'s child is an arbitrary `Widgets` that represent your app screen / page.

example/lib/main.dart

+6-10
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ class HomeScreen extends StatelessWidget {
4040
}
4141

4242
class BooksScreen extends StatelessWidget {
43-
BooksScreen({this.titleQuery = ''});
44-
45-
final String titleQuery;
46-
4743
@override
4844
Widget build(BuildContext context) {
45+
final titleQuery =
46+
Beamer.of(context).currentLocation.queryParameters['title'] ?? '';
4947
return Scaffold(
5048
appBar: AppBar(
5149
title: Text('Books'),
@@ -96,7 +94,7 @@ class HomeLocation extends BeamLocation {
9694
List<String> get pathBlueprints => ['/'];
9795

9896
@override
99-
List<BeamPage> get pages => [
97+
List<BeamPage> pagesBuilder(BuildContext context) => [
10098
BeamPage(
10199
key: ValueKey('home'),
102100
child: HomeScreen(),
@@ -117,14 +115,12 @@ class BooksLocation extends BeamLocation {
117115
List<String> get pathBlueprints => ['/books/:bookId'];
118116

119117
@override
120-
List<BeamPage> get pages => [
121-
...HomeLocation().pages,
118+
List<BeamPage> pagesBuilder(BuildContext context) => [
119+
...HomeLocation().pagesBuilder(context),
122120
if (pathSegments.contains('books'))
123121
BeamPage(
124122
key: ValueKey('books-${queryParameters['title'] ?? ''}'),
125-
child: BooksScreen(
126-
titleQuery: queryParameters['title'] ?? '',
127-
),
123+
child: BooksScreen(),
128124
),
129125
if (pathParameters.containsKey('bookId'))
130126
BeamPage(

0 commit comments

Comments
 (0)