Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Example] Add bottom_navigation_complex #535

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions examples/bottom_navigation_complex/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

# Remove platform specific folders
android
ios
linux
macos
web
windows
30 changes: 30 additions & 0 deletions examples/bottom_navigation_complex/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.

version:
revision: 85684f9300908116a78138ea4c6036c35c9a1236
channel: stable

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
- platform: android
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
6 changes: 6 additions & 0 deletions examples/bottom_navigation_complex/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Bottom Navigation Complex

<p align="center">
<img src="bottom_navigation_complex.png">

Run `flutter create .` to generate all necessary files, if needed.
29 changes: 29 additions & 0 deletions examples/bottom_navigation_complex/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2022-06-29T00:53:30.216Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37" etag="sMLf9MFu5jCPUWF8_uKO" version="20.0.3" type="device"><diagram id="WqRtav1gksRt4kbiOZdr" name="Page-1">7VvbcuI4EP0aqnYfoGzJ10cuSSa1ma3ZYi/Jo2ILcGIsxogE8vUr2xK2LJMhg43NVHhIrNYF63SfVqslenC83N7EaLX4Snwc9oDmb3tw0gMA6pbG/iWSXSYBrm5lknkc+JlMzwXT4A1zIe843wQ+XksNKSEhDVay0CNRhD0qyVAck1e52YyE8reu0BwrgqmHQlX6X+DTRSZ1gJ3Lv+BgvhDfrFtuVrNEojGfyXqBfPJaEMGrHhzHhNDsabkd4zBBT+CS9bs+ULt/sRhH9JgODzv39vn67/U/Nnjy3+6n3s2T3Yd8Hi8o3PAZ87elOwFBTDaRj5NRtB4cvS4Ciqcr5CW1r0zrTLagy5CVdPY4IxHlWtST5rMgDMckJHE6FvQRdmYek69pTJ5xocbyHPw4YzXqvPhUX3BM8bYg4vO8wWSJabxjTXitLTDnVtc3jKz8mqvQEm0WBfW5Jhcibjbz/dg5suyBg1sN9P2fN9+H326f/nr78seVM4Hju383fUOBFfvM0HiRxHRB5iRC4VUuHcnA523uCFlxuJ8wpTuON9pQIisDbwN6n3QfmLz0UKiZbPnIaWEnChGbbqFTUnwo1uXd0pLol80vmdRB++SiNdnEHn7HKE3OcxTPMX0HU1htBDEOEQ1e5Pc4RaHvvWSBOGNm+slcT+JPDdbv6KZk/abmDICrEABoFQSAVg0EqMTLUvCaYhR7i8uGqyl34X66i6PdhX2ku7DbdBfqOtsVd6FrVhf9haMA9nU3XSTx3GUD1hReOlAAG2G0xHHreLlGKRrTB7auFT5O27amQwW7O7Qjm/bJWRt2jUFnKND1gBVSvhWQ0LO+b4io6K/TVWjIGujaapuiJerZ0zz5PyLkeS1GY2+XDZjVdU4zEFQ6Af282mg1bhDPzUUN5d3lQT0Wg4H3wtFSAHJCdMC7fiNBavX7taJsJiYzE8fNP5Y8ZBbt8FFyaxjGMdoVmq2SBusPfK8BS9mBUge3FAWX2rOH7BVy29yD9PPmKnggOY/rA/uCRFV36BGHsvGhMJhH7NljJsAWOzhKKBx4KBzyimXg+5mdY+Zz0GM6XmI8HEM2uDnqmZMK8wqTrxsh73meckRkKyIS4Urje5eTimvZJ634O/WKeaEql6MNLNOW1dTnI/2smYomZDZbY9or+58adLxPf7WzlemOS/rhPkZkRn/ou5xGfFfjLkbXrTZ8jFjZJR9zaC9xqU5GsKwWJ2MZQHYyoOtORlezS7VFocNE0yHubCCqhhhdiESB2arbP0MGqz7HD8CRjl/sU+vz/KfpWM3RsHH4rk3r9xJPc53Tp31Xe6wzFbn9GpypBsRRYXe9J7A+uVo7V4HRLa5WHfSmXE3HHT6yp9vJJZFULPk1kBTowpXtpIFO3PwbUF6XbXmA5ggNPxff+gkNu0VoWBXyXk+ZhoJofkmrLaxxtXV17UTq7m+MmA2QtfJYUgR1vy5ZK3lTH1urUQWtrrZAIac4jMs2kY+x2D/+FkQBDVCYAsL2aszG0/2oiKR/V6zj7BtM4JYOoUxHvU915iM7oB7ZdeZA3bC6fuAJ1FO7LBTUJpiiIOzAIXttIDaFIeywBbqdt0CoWuDB2OVy4WsMvarMywfznfaBfOeUIoqTF0iSOCsW9uGYLZdHJj8ZwlTWh3zRl2e1i7eCuej4SLTKAGQTOXp38IErxbBkEkluR/rYik3sb78XbcJozCZcxSaGq1X7ZDohemjqdmXlkRDPW3YnGWLvFXD01qhCV4cvsJRO/F1oMYs2gGPaOvtrgYbAV0PjGpfNCqSOR6R8E9i1rTMuk4evuDccp7WEWVOQqRfzpVOIhN8oK/3yFNf1UiBzLo6ruamucFy5vNsBkqupeW6uHeL5Cbg1topX3h7bQ5cQfdgVomsNE93R3IFTCEaBpKu+bQ3swp1D1zyskgP50JKnaDAdqgZnnfEdtt6hbfU7ac+u+5LacPw4jKyY/+Q2s9n8l8vw6n8=</diagram></mxfile>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions examples/bottom_navigation_complex/lib/app.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:bottom_navigation_complex/routers/app.router.dart';
import 'package:bottom_navigation_complex/screens/splash.screen.dart';
import 'package:flutter/material.dart';
import 'package:beamer/beamer.dart';

class App extends StatelessWidget {
static final BeamerDelegate _router = routerDelegate;

const App({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
routerDelegate: _router,
routeInformationParser: BeamerParser(),
builder: (context, child) => SplashScreen(screen: child),
);
}
}
13 changes: 13 additions & 0 deletions examples/bottom_navigation_complex/lib/data/data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:bottom_navigation_complex/models/article.models.dart';
import 'package:bottom_navigation_complex/models/book.models.dart';

const List<Book> books = [
Book(id: '1', title: 'Stranger in a Strange Land', author: 'Robert A. Heinlein'),
Book(id: '2', title: 'Foundation', author: 'Isaac Asimov'),
Book(id: '3', title: 'Fahrenheit 451', author: 'Ray Bradbury'),
];

const List<Article> articles = [
Article(id: '1', title: 'Learning Flutter’s new navigation and routing system', seller: 'John Ryan'),
Article(id: '2', title: 'Explaining Flutter Nav 2.0 and Beamer', seller: 'Isaac Asimov'),
];
8 changes: 8 additions & 0 deletions examples/bottom_navigation_complex/lib/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:bottom_navigation_complex/app.dart';
import 'package:flutter/material.dart';
import 'package:beamer/beamer.dart';

void main() {
Beamer.setPathUrlStrategy();
runApp(const App());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Article {
final String id;
final String title;
final String seller;

const Article({required this.id, required this.title, required this.seller});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Book {
final String id;
final String title;
final String author;

const Book({required this.id, required this.title, required this.author});
}
39 changes: 39 additions & 0 deletions examples/bottom_navigation_complex/lib/routers/app.router.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/routers/locations/article.location.dart';
import 'package:bottom_navigation_complex/routers/locations/book.location.dart';
import 'package:bottom_navigation_complex/routers/locations/layout.locations.dart';
import 'package:bottom_navigation_complex/routers/locations/settings.locations.dart';

final BeamerDelegate routerDelegate = BeamerDelegate(
setBrowserTabTitle: false,
initialPath: '/Books',
routeListener: (_, delegate) {
print("${'=' * 15} History ${'=' * 15}");
for (var beamHistory in delegate.beamingHistory) {
for (var history in beamHistory.history) {
print('BeamLocation: ${beamHistory.runtimeType} \t path: ${history.routeInformation.location}');
}
}
},
locationBuilder: BeamerLocationBuilder(
beamLocations: [
LayoutLocation(),
BookLocation(),
ArticleLocation(),
SettingsLocation(),
],
),
);

String? get previousLocation {
BeamLocation lastLocation = routerDelegate.beamingHistory.last;
if (lastLocation.history.length > 1) {
return lastLocation.history[lastLocation.history.length - 2].routeInformation.location;
}

if (routerDelegate.beamingHistory.length > 1) {
return routerDelegate.beamingHistory[routerDelegate.beamingHistory.length - 2].history.last.routeInformation.location;
}

return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/screens/article_details.screen.dart';
import 'package:bottom_navigation_complex/screens/articles.screen.dart';
import 'package:flutter/foundation.dart';
import 'package:bottom_navigation_complex/routers/app.router.dart';

final BeamerDelegate articlesRouterDelegate = BeamerDelegate(
setBrowserTabTitle: false,
initialPath: '/Articles',
clearBeamingHistoryOn: {'/Articles'},
locationBuilder: RoutesLocationBuilder(
routes: {
'/Articles': (context, state, data) => const BeamPage(key: ValueKey('articles'), child: ArticlesScreen()),
'/Articles/:articleID': (context, state, data) => BeamPage(
key: ValueKey('articles-${state.pathParameters["articleID"]}'),
child: ArticleDetailsScreen(articleID: state.pathParameters["articleID"]!),
popToNamed: previousLocation,
),
},
),
);
21 changes: 21 additions & 0 deletions examples/bottom_navigation_complex/lib/routers/books.router.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/routers/app.router.dart';
import 'package:bottom_navigation_complex/screens/book_details.screen.dart';
import 'package:bottom_navigation_complex/screens/books.screen.dart';
import 'package:flutter/foundation.dart';

final BeamerDelegate booksRouterDelegate = BeamerDelegate(
setBrowserTabTitle: false,
initialPath: '/Books',
clearBeamingHistoryOn: {'/Books'},
locationBuilder: RoutesLocationBuilder(
routes: {
'/Books': (context, state, data) => const BeamPage(key: ValueKey('books'), child: Books()),
'/Books/:bookID': (context, state, data) => BeamPage(
key: ValueKey('books-${state.pathParameters["bookID"]}'),
child: BookDetailsScreen(bookID: state.pathParameters["bookID"]!),
popToNamed: previousLocation,
),
},
),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/routers/locations/layout.locations.dart';
import 'package:bottom_navigation_complex/screens/article_details.screen.dart';
import 'package:flutter/widgets.dart';
import 'package:bottom_navigation_complex/routers/app.router.dart';

class ArticleLocation extends BeamLocation<BeamState> {
@override
List<String> get pathPatterns => ['/Article/:articleID'];

@override
List<BeamPage> buildPages(BuildContext context, BeamState state) => [
...LayoutLocation().buildPages(context, state),
if (state.pathParameters.containsKey('articleID'))
BeamPage(
key: ValueKey('article-details-${state.pathParameters["articleID"]}'),
child: ArticleDetailsScreen(articleID: state.pathParameters["articleID"]!),
popToNamed: previousLocation,
)
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/routers/locations/layout.locations.dart';
import 'package:bottom_navigation_complex/screens/book_details.screen.dart';
import 'package:flutter/widgets.dart';
import 'package:bottom_navigation_complex/routers/app.router.dart';

class BookLocation extends BeamLocation<BeamState> {
@override
List<String> get pathPatterns => ['/Book/:bookID'];

@override
List<BeamPage> buildPages(BuildContext context, BeamState state) => [
...LayoutLocation().buildPages(context, state),
if (state.pathParameters.containsKey('bookID'))
BeamPage(
key: ValueKey('book-details-${state.pathParameters["bookID"]}'),
child: BookDetailsScreen(bookID: state.pathParameters["bookID"]!),
popToNamed: previousLocation,
)
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/screens/layout.screen.dart';
import 'package:flutter/widgets.dart';

class LayoutLocation extends BeamLocation<BeamState> {
@override
List<String> get pathPatterns => ['/Books', '/Books/*', '/Articles', '/Articles/*'];

@override
List<BeamPage> buildPages(BuildContext context, BeamState state) => [
const BeamPage(key: ValueKey('layout'), child: LayoutScreen()),
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/routers/app.router.dart';
import 'package:bottom_navigation_complex/routers/locations/layout.locations.dart';
import 'package:bottom_navigation_complex/screens/settings.screen.dart';
import 'package:flutter/widgets.dart';

class SettingsLocation extends BeamLocation<BeamState> {
@override
List<String> get pathPatterns => ['/Settings'];

@override
List<BeamPage> buildPages(BuildContext context, BeamState state) => [
...LayoutLocation().buildPages(context, state),
BeamPage(key: const ValueKey('settings'), child: const SettingsScreen(), popToNamed: previousLocation),
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'package:beamer/beamer.dart';
import 'package:bottom_navigation_complex/data/data.dart';
import 'package:bottom_navigation_complex/models/article.models.dart';
import 'package:flutter/material.dart';

class ArticleDetailsScreen extends StatelessWidget {
final String articleID;
late final Article article = articles.firstWhere((article) => article.id == articleID);

ArticleDetailsScreen({super.key, required this.articleID});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Article ${article.title}'),
actions: [
IconButton(
icon: const Icon(Icons.open_in_new),
onPressed: () => Beamer.of(context).root.beamToNamed('/Article/${article.id}'),
)
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 12),
child: Text('Other articles:', style: Theme.of(context).textTheme.titleLarge),
),
...articles
.where((article) => article.id != articleID)
.map(
(article) => ListTile(
leading: CircleAvatar(
backgroundColor: Theme.of(context).primaryColor,
child: Text(article.id),
),
title: Text(article.title),
subtitle: Text(article.seller),
onTap: () => context.beamToNamed('/Articles/${article.id}'),
onLongPress: () => Beamer.of(context).root.beamToNamed('/Article/${article.id}'),
),
)
.toList(),
],
),
);
}
}
Loading