mirror of
https://github.com/flutter/samples.git
synced 2025-11-10 06:48:26 +00:00
This is a new PR to update the navigation_and_routing sample to the latest version of go_router. It is a based on https://github.com/flutter/samples/pull/1437 --------- Co-authored-by: Brett Morgan <brettmorgan@google.com>
273 lines
10 KiB
Dart
273 lines
10 KiB
Dart
// Copyright 2021, the Flutter project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import 'auth.dart';
|
|
import 'data.dart';
|
|
import 'screens/author_details.dart';
|
|
import 'screens/authors.dart';
|
|
import 'screens/book_details.dart';
|
|
import 'screens/books.dart';
|
|
import 'screens/scaffold.dart';
|
|
import 'screens/settings.dart';
|
|
import 'screens/sign_in.dart';
|
|
import 'widgets/book_list.dart';
|
|
import 'widgets/fade_transition_page.dart';
|
|
|
|
final appShellNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'app shell');
|
|
final booksNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'books shell');
|
|
|
|
class Bookstore extends StatefulWidget {
|
|
const Bookstore({super.key});
|
|
|
|
@override
|
|
State<Bookstore> createState() => _BookstoreState();
|
|
}
|
|
|
|
class _BookstoreState extends State<Bookstore> {
|
|
final BookstoreAuth auth = BookstoreAuth();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp.router(
|
|
builder: (context, child) {
|
|
if (child == null) {
|
|
throw ('No child in .router constructor builder');
|
|
}
|
|
return BookstoreAuthScope(
|
|
notifier: auth,
|
|
child: child,
|
|
);
|
|
},
|
|
routerConfig: GoRouter(
|
|
refreshListenable: auth,
|
|
debugLogDiagnostics: true,
|
|
initialLocation: '/books/popular',
|
|
redirect: (context, state) {
|
|
final signedIn = BookstoreAuth.of(context).signedIn;
|
|
if (state.uri.toString() != '/sign-in' && !signedIn) {
|
|
return '/sign-in';
|
|
}
|
|
return null;
|
|
},
|
|
routes: [
|
|
ShellRoute(
|
|
navigatorKey: appShellNavigatorKey,
|
|
builder: (context, state, child) {
|
|
return BookstoreScaffold(
|
|
selectedIndex: switch (state.uri.path) {
|
|
var p when p.startsWith('/books') => 0,
|
|
var p when p.startsWith('/authors') => 1,
|
|
var p when p.startsWith('/settings') => 2,
|
|
_ => 0,
|
|
},
|
|
child: child,
|
|
);
|
|
},
|
|
routes: [
|
|
ShellRoute(
|
|
pageBuilder: (context, state, child) {
|
|
return FadeTransitionPage<dynamic>(
|
|
key: state.pageKey,
|
|
// Use a builder to get the correct BuildContext
|
|
// TODO (johnpryan): remove when https://github.com/flutter/flutter/issues/108177 lands
|
|
child: Builder(builder: (context) {
|
|
return BooksScreen(
|
|
onTap: (idx) {
|
|
GoRouter.of(context).go(switch (idx) {
|
|
0 => '/books/popular',
|
|
1 => '/books/new',
|
|
2 => '/books/all',
|
|
_ => '/books/popular',
|
|
});
|
|
},
|
|
selectedIndex: switch (state.uri.path) {
|
|
var p when p.startsWith('/books/popular') => 0,
|
|
var p when p.startsWith('/books/new') => 1,
|
|
var p when p.startsWith('/books/all') => 2,
|
|
_ => 0,
|
|
},
|
|
child: child,
|
|
);
|
|
}),
|
|
);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: '/books/popular',
|
|
pageBuilder: (context, state) {
|
|
return FadeTransitionPage<dynamic>(
|
|
// Use a builder to get the correct BuildContext
|
|
// TODO (johnpryan): remove when https://github.com/flutter/flutter/issues/108177 lands
|
|
key: state.pageKey,
|
|
child: Builder(
|
|
builder: (context) {
|
|
return BookList(
|
|
books: libraryInstance.popularBooks,
|
|
onTap: (book) {
|
|
GoRouter.of(context)
|
|
.go('/books/popular/book/${book.id}');
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: 'book/:bookId',
|
|
parentNavigatorKey: appShellNavigatorKey,
|
|
builder: (context, state) {
|
|
return BookDetailsScreen(
|
|
book: libraryInstance
|
|
.getBook(state.pathParameters['bookId'] ?? ''),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: '/books/new',
|
|
pageBuilder: (context, state) {
|
|
return FadeTransitionPage<dynamic>(
|
|
key: state.pageKey,
|
|
// Use a builder to get the correct BuildContext
|
|
// TODO (johnpryan): remove when https://github.com/flutter/flutter/issues/108177 lands
|
|
child: Builder(
|
|
builder: (context) {
|
|
return BookList(
|
|
books: libraryInstance.newBooks,
|
|
onTap: (book) {
|
|
GoRouter.of(context)
|
|
.go('/books/new/book/${book.id}');
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: 'book/:bookId',
|
|
parentNavigatorKey: appShellNavigatorKey,
|
|
builder: (context, state) {
|
|
return BookDetailsScreen(
|
|
book: libraryInstance
|
|
.getBook(state.pathParameters['bookId'] ?? ''),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: '/books/all',
|
|
pageBuilder: (context, state) {
|
|
return FadeTransitionPage<dynamic>(
|
|
key: state.pageKey,
|
|
// Use a builder to get the correct BuildContext
|
|
// TODO (johnpryan): remove when https://github.com/flutter/flutter/issues/108177 lands
|
|
child: Builder(
|
|
builder: (context) {
|
|
return BookList(
|
|
books: libraryInstance.allBooks,
|
|
onTap: (book) {
|
|
GoRouter.of(context)
|
|
.go('/books/all/book/${book.id}');
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: 'book/:bookId',
|
|
parentNavigatorKey: appShellNavigatorKey,
|
|
builder: (context, state) {
|
|
return BookDetailsScreen(
|
|
book: libraryInstance
|
|
.getBook(state.pathParameters['bookId'] ?? ''),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: '/authors',
|
|
pageBuilder: (context, state) {
|
|
return FadeTransitionPage<dynamic>(
|
|
key: state.pageKey,
|
|
child: Builder(builder: (context) {
|
|
return AuthorsScreen(
|
|
onTap: (author) {
|
|
GoRouter.of(context)
|
|
.go('/authors/author/${author.id}');
|
|
},
|
|
);
|
|
}),
|
|
);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: 'author/:authorId',
|
|
builder: (context, state) {
|
|
final author = libraryInstance.allAuthors.firstWhere(
|
|
(author) =>
|
|
author.id ==
|
|
int.parse(state.pathParameters['authorId']!));
|
|
// Use a builder to get the correct BuildContext
|
|
// TODO (johnpryan): remove when https://github.com/flutter/flutter/issues/108177 lands
|
|
return Builder(builder: (context) {
|
|
return AuthorDetailsScreen(
|
|
author: author,
|
|
onBookTapped: (book) {
|
|
GoRouter.of(context)
|
|
.go('/books/all/book/${book.id}');
|
|
},
|
|
);
|
|
});
|
|
},
|
|
)
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: '/settings',
|
|
pageBuilder: (context, state) {
|
|
return FadeTransitionPage<dynamic>(
|
|
key: state.pageKey,
|
|
child: const SettingsScreen(),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
GoRoute(
|
|
path: '/sign-in',
|
|
builder: (context, state) {
|
|
// Use a builder to get the correct BuildContext
|
|
// TODO (johnpryan): remove when https://github.com/flutter/flutter/issues/108177 lands
|
|
return Builder(
|
|
builder: (context) {
|
|
return SignInScreen(
|
|
onSignIn: (value) async {
|
|
final router = GoRouter.of(context);
|
|
await BookstoreAuth.of(context)
|
|
.signIn(value.username, value.password);
|
|
router.go('/books/popular');
|
|
},
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|