Last active
July 28, 2022 01:10
-
-
Save HansMuller/289f54e867e2f9296ed375044a1f6ffd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2013 The Flutter Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
// Copied from | |
// https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/redirection.dart | |
// https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/shared/data.dart | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:go_router/go_router.dart'; | |
void main() => runApp(App()); | |
class App extends StatelessWidget { | |
App({Key? key}) : super(key: key); | |
final LoginInfo _loginInfo = LoginInfo(); | |
static const String title = 'GoRouter Example: Redirection'; | |
// add the login info into the tree as app state that can change over time | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp.router( | |
routeInformationProvider: _router.routeInformationProvider, | |
routeInformationParser: _router.routeInformationParser, | |
routerDelegate: _router.routerDelegate, | |
title: title, | |
debugShowCheckedModeBanner: false, | |
); | |
} | |
late final GoRouter _router = GoRouter( | |
routes: <GoRoute>[ | |
GoRoute( | |
path: '/', | |
builder: (BuildContext context, GoRouterState state) { | |
return HomeScreen(loginInfo: _loginInfo, families: Families.data); | |
}, | |
routes: <GoRoute>[ | |
GoRoute( | |
path: 'family/:fid', | |
builder: (BuildContext context, GoRouterState state) { | |
return FamilyScreen( | |
family: Families.family(state.params['fid']!), | |
); | |
}, | |
routes: <GoRoute>[ | |
GoRoute( | |
path: 'person/:pid', | |
builder: (BuildContext context, GoRouterState state) { | |
final Family family = Families.family(state.params['fid']!); | |
final Person person = family.person(state.params['pid']!); | |
return PersonScreen(family: family, person: person); | |
}, | |
), | |
], | |
), | |
], | |
), | |
GoRoute( | |
path: '/login', | |
builder: (BuildContext context, GoRouterState state) { | |
return LoginScreen(loginInfo: _loginInfo); | |
}, | |
), | |
], | |
// redirect to the login page if the user is not logged in | |
redirect: (GoRouterState state) { | |
final bool loggedIn = _loginInfo.loggedIn; | |
final bool loggingIn = state.subloc == '/login'; | |
if (!loggedIn) { | |
return loggingIn ? null : '/login'; | |
} | |
// if the user is logged in but still on the login page, send them to | |
// the home page | |
if (loggingIn) { | |
return '/'; | |
} | |
// no need to redirect at all | |
return null; | |
}, | |
// changes on the listenable will cause the router to refresh it's route | |
refreshListenable: _loginInfo, | |
); | |
} | |
class LoginScreen extends StatelessWidget { | |
LoginScreen({ required this.loginInfo, super.key }); | |
final LoginInfo loginInfo; | |
@override | |
Widget build(BuildContext context) => Scaffold( | |
appBar: AppBar(title: const Text(App.title)), | |
body: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
ElevatedButton( | |
onPressed: () { | |
// log a user in, letting all the listeners know | |
loginInfo.login('test-user'); | |
// router will automatically redirect from /login to / using | |
// refreshListenable | |
//context.go('/'); | |
}, | |
child: const Text('Login'), | |
), | |
], | |
), | |
), | |
); | |
} | |
/// The home screen that shows a list of families. | |
class HomeScreen extends StatelessWidget { | |
HomeScreen({ required this.loginInfo, required this.families, super.key }); | |
final LoginInfo loginInfo; | |
final List<Family> families; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text(App.title), | |
actions: <Widget>[ | |
IconButton( | |
onPressed: loginInfo.logout, | |
tooltip: 'Logout: ${loginInfo.userName}', | |
icon: const Icon(Icons.logout), | |
) | |
], | |
), | |
body: ListView( | |
children: <Widget>[ | |
for (final Family f in families) | |
ListTile( | |
title: Text(f.name), | |
onTap: () => context.go('/family/${f.id}'), | |
) | |
], | |
), | |
); | |
} | |
} | |
/// The screen that shows a list of persons in a family. | |
class FamilyScreen extends StatelessWidget { | |
/// Creates a [FamilyScreen]. | |
const FamilyScreen({required this.family, Key? key}) : super(key: key); | |
/// The family to display. | |
final Family family; | |
@override | |
Widget build(BuildContext context) => Scaffold( | |
appBar: AppBar(title: Text(family.name)), | |
body: ListView( | |
children: <Widget>[ | |
for (final Person p in family.people) | |
ListTile( | |
title: Text(p.name), | |
onTap: () => context.go('/family/${family.id}/person/${p.id}'), | |
), | |
], | |
), | |
); | |
} | |
/// The person screen. | |
class PersonScreen extends StatelessWidget { | |
/// Creates a [PersonScreen]. | |
const PersonScreen({required this.family, required this.person, Key? key}) | |
: super(key: key); | |
/// The family this person belong to. | |
final Family family; | |
/// The person to be displayed. | |
final Person person; | |
@override | |
Widget build(BuildContext context) => Scaffold( | |
appBar: AppBar(title: Text(person.name)), | |
body: Text('${person.name} ${family.name} is ${person.age} years old'), | |
); | |
} | |
class LoginInfo extends ChangeNotifier { | |
String get userName => _userName; | |
String _userName = ''; | |
bool get loggedIn => _userName.isNotEmpty; | |
void login(String userName) { | |
_userName = userName; | |
notifyListeners(); | |
} | |
void logout() { | |
_userName = ''; | |
notifyListeners(); | |
} | |
} | |
/// Person data class. | |
class Person { | |
/// Creates a [Person]. | |
Person({required this.id, required this.name, required this.age}); | |
/// The id of the person. | |
final String id; | |
/// The name of the person. | |
final String name; | |
/// The age of the person. | |
final int age; | |
} | |
/// Family data class. | |
class Family { | |
/// Creates a [Family]. | |
Family({required this.id, required this.name, required this.people}); | |
/// The id of the family. | |
final String id; | |
/// The name of the family. | |
final String name; | |
/// The list of [Person]s in the family. | |
final List<Person> people; | |
/// Gets the [Person] with the given id in this family. | |
Person person(String pid) => people.singleWhere( | |
(Person p) => p.id == pid, | |
orElse: () => throw Exception('unknown person $pid for family $id'), | |
); | |
} | |
/// The mock of families data. | |
class Families { | |
Families._(); | |
/// The data. | |
static final List<Family> data = <Family>[ | |
Family( | |
id: 'f1', | |
name: 'Sells', | |
people: <Person>[ | |
Person(id: 'p1', name: 'Chris', age: 52), | |
Person(id: 'p2', name: 'John', age: 27), | |
Person(id: 'p3', name: 'Tom', age: 26), | |
], | |
), | |
Family( | |
id: 'f2', | |
name: 'Addams', | |
people: <Person>[ | |
Person(id: 'p1', name: 'Gomez', age: 55), | |
Person(id: 'p2', name: 'Morticia', age: 50), | |
Person(id: 'p3', name: 'Pugsley', age: 10), | |
Person(id: 'p4', name: 'Wednesday', age: 17), | |
], | |
), | |
Family( | |
id: 'f3', | |
name: 'Hunting', | |
people: <Person>[ | |
Person(id: 'p1', name: 'Mom', age: 54), | |
Person(id: 'p2', name: 'Dad', age: 55), | |
Person(id: 'p3', name: 'Will', age: 20), | |
Person(id: 'p4', name: 'Marky', age: 21), | |
Person(id: 'p5', name: 'Ricky', age: 22), | |
Person(id: 'p6', name: 'Danny', age: 23), | |
Person(id: 'p7', name: 'Terry', age: 24), | |
Person(id: 'p8', name: 'Mikey', age: 25), | |
Person(id: 'p9', name: 'Davey', age: 26), | |
Person(id: 'p10', name: 'Timmy', age: 27), | |
Person(id: 'p11', name: 'Tommy', age: 28), | |
Person(id: 'p12', name: 'Joey', age: 29), | |
Person(id: 'p13', name: 'Robby', age: 30), | |
Person(id: 'p14', name: 'Johnny', age: 31), | |
Person(id: 'p15', name: 'Brian', age: 32), | |
], | |
), | |
]; | |
/// Looks up a family in the data. | |
static Family family(String fid) { | |
return data.singleWhere( | |
(Family f) => f.id == fid, | |
orElse: () => throw Exception('unknown family $fid'), | |
); | |
} | |
} | |
/// The relation of a person in a family. | |
class FamilyPerson { | |
/// Creates a [FamilyPerson]. | |
FamilyPerson({required this.family, required this.person}); | |
/// The family. | |
final Family family; | |
/// the person. | |
final Person person; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment