Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@HansMuller
Last active July 28, 2022 01:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HansMuller/289f54e867e2f9296ed375044a1f6ffd to your computer and use it in GitHub Desktop.
Save HansMuller/289f54e867e2f9296ed375044a1f6ffd to your computer and use it in GitHub Desktop.
// 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