Skip to content

Commit 05184ca

Browse files
Tomasz KądziołkaTomasz Kądziołka
authored andcommitted
Configured navigation with go router plus
1 parent f546b80 commit 05184ca

File tree

11 files changed

+240
-28
lines changed

11 files changed

+240
-28
lines changed

flutter_module/lib/main.dart

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_module/model/main_model.dart';
3-
import 'package:flutter_module/presentation/pages/main_page.dart';
4-
import 'package:flutter_module/presentation/widgets/snippet_list_item.dart';
5-
import 'package:flutter_module/utils/mock/mock_page.dart';
6-
import 'package:flutter_module/utils/mock/mocks.dart';
3+
import 'package:flutter_module/presentation/navigation/details/details_navigator.dart';
4+
import 'package:flutter_module/presentation/navigation/details/details_redirector.dart';
5+
import 'package:flutter_module/presentation/navigation/login/login_navigator.dart';
6+
import 'package:flutter_module/presentation/screens//main_screen.dart';
7+
import 'package:flutter_module/presentation/screens/details_screen.dart';
8+
import 'package:flutter_module/presentation/screens/login_screen.dart';
9+
import 'package:go_router_plus/go_router_plus.dart';
710

811
void main() => runApp(MyApp());
912

@@ -12,13 +15,38 @@ class MyApp extends StatelessWidget {
1215

1316
final mainModel = MainModelBridge();
1417

15-
// This widgets is the root of your application.
1618
@override
1719
Widget build(BuildContext context) {
18-
return MaterialApp(
20+
final loginNavigator = LoginNavigator();
21+
final detailsNavigator = DetailsNavigator();
22+
final router = createGoRouter(
23+
screens: [
24+
LoginScreen(loginNavigator),
25+
MainScreen(
26+
navigator: detailsNavigator,
27+
model: mainModel,
28+
),
29+
DetailsScreen(detailsNavigator)
30+
],
31+
redirectors: [
32+
ScreenRedirector(),
33+
DetailsRedirector(detailsNavigator),
34+
AuthRedirector(
35+
state: loginNavigator,
36+
guestRedirectPath: '/${LoginScreen.name}',
37+
userRedirectPath: '/${MainScreen.name}',
38+
)
39+
],
40+
refreshNotifiers: [loginNavigator, detailsNavigator],
41+
);
42+
43+
return MaterialApp.router(
1944
title: 'SnipMe',
2045
theme: ThemeData(primarySwatch: Colors.blue),
21-
home: MainPage(model: mainModel),
46+
// TODO Use theme tailor
47+
routeInformationProvider: router.routeInformationProvider,
48+
routeInformationParser: router.routeInformationParser,
49+
routerDelegate: router.routerDelegate,
2250
);
2351
}
2452
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'package:flutter/foundation.dart';
2+
3+
class DetailsNavigator with ChangeNotifier {
4+
String? _snippetId;
5+
6+
String? get snippetId => _snippetId;
7+
8+
void goToDetails(String snippetId) {
9+
_snippetId = snippetId;
10+
notifyListeners();
11+
}
12+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import 'dart:async';
2+
3+
import 'package:flutter/widgets.dart';
4+
import 'package:flutter_module/presentation/navigation/details/details_navigator.dart';
5+
import 'package:flutter_module/presentation/screens/details_screen.dart';
6+
import 'package:go_router/go_router.dart';
7+
import 'package:go_router_plus/go_router_plus.dart';
8+
9+
class DetailsRedirector extends ScreenRedirector {
10+
DetailsRedirector(this.navigator);
11+
12+
final DetailsNavigator navigator;
13+
14+
@override
15+
FutureOr<String?> redirect(
16+
Screen screen,
17+
BuildContext context,
18+
GoRouterState state,
19+
) {
20+
if (navigator.snippetId != null) {
21+
return '/${DetailsScreen.name}';
22+
}
23+
24+
return null;
25+
}
26+
27+
@override
28+
bool shouldRedirect(Screen screen) => true;
29+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:go_router_plus/go_router_plus.dart';
3+
4+
class LoginNavigator with ChangeNotifier implements LoggedInState {
5+
bool _loggedIn = false;
6+
7+
@override
8+
bool get loggedIn => _loggedIn;
9+
10+
void login() {
11+
_loggedIn = true;
12+
notifyListeners();
13+
}
14+
15+
void logout() {
16+
_loggedIn = false;
17+
notifyListeners();
18+
}
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_module/presentation/navigation/details/details_navigator.dart';
3+
import 'package:flutter_module/presentation/screens/named_screen.dart';
4+
import 'package:go_router/go_router.dart';
5+
6+
class DetailsScreen extends NamedScreen {
7+
DetailsScreen(this.navigator) : super(name);
8+
9+
static String name = 'details';
10+
11+
final DetailsNavigator navigator;
12+
13+
@override
14+
Widget builder(BuildContext context, GoRouterState state) {
15+
return const Scaffold(
16+
body: Center(
17+
child: Text("Details"),
18+
),
19+
);
20+
}
21+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_module/presentation/navigation/login/login_navigator.dart';
3+
import 'package:flutter_module/presentation/screens/named_screen.dart';
4+
import 'package:go_router/go_router.dart';
5+
import 'package:go_router_plus/go_router_plus.dart';
6+
7+
class LoginScreen extends NamedScreen implements InitialScreen, GuestScreen {
8+
LoginScreen(this.navigator) : super(name);
9+
10+
static String name = 'login';
11+
final LoginNavigator navigator;
12+
13+
@override
14+
Widget builder(BuildContext context, GoRouterState state) {
15+
return Scaffold(
16+
body: Center(
17+
child: Column(
18+
mainAxisAlignment: MainAxisAlignment.center,
19+
children: [
20+
// TODO Extract strings
21+
const Text("Login"),
22+
MaterialButton(
23+
child: const Text("Navigate to login"),
24+
onPressed: navigator.login,
25+
),
26+
],
27+
),
28+
),
29+
);
30+
}
31+
}

flutter_module/lib/presentation/pages/main_page.dart renamed to flutter_module/lib/presentation/screens/main_screen.dart

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,44 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_hooks/flutter_hooks.dart';
33
import 'package:flutter_module/model/main_model.dart';
4+
import 'package:flutter_module/presentation/navigation/details/details_navigator.dart';
5+
import 'package:flutter_module/presentation/screens/named_screen.dart';
46
import 'package:flutter_module/presentation/styles/color_styles.dart';
57
import 'package:flutter_module/presentation/styles/dimens.dart';
68
import 'package:flutter_module/presentation/widgets/snippet_list_item.dart';
79
import 'package:flutter_module/presentation/widgets/view_state_wrapper.dart';
810
import 'package:flutter_module/utils/extensions/build_context_extensions.dart';
911
import 'package:flutter_module/utils/hooks/use_observable_state_hook.dart';
12+
import 'package:go_router/src/state.dart';
13+
import 'package:go_router_plus/go_router_plus.dart';
1014

11-
class MainPage extends HookWidget {
12-
const MainPage({
15+
class MainScreen extends NamedScreen implements UserScreen {
16+
MainScreen({
17+
required this.navigator,
18+
required this.model,
19+
}) : super(name);
20+
21+
static String name = 'main';
22+
final DetailsNavigator navigator;
23+
final MainModelBridge model;
24+
25+
@override
26+
Widget builder(BuildContext context, GoRouterState state) {
27+
return _MainPage(
28+
navigator: navigator,
29+
model: model,
30+
);
31+
}
32+
}
33+
34+
class _MainPage extends HookWidget {
35+
const _MainPage({
1336
Key? key,
37+
required this.navigator,
1438
required this.model,
1539
}) : super(key: key);
1640

41+
final DetailsNavigator navigator;
1742
final MainModelBridge model;
1843

1944
@override
@@ -47,14 +72,17 @@ class MainPage extends HookWidget {
4772
error: data.error,
4873
data: data.data?.cast(),
4974
builder: (_, snippets) {
50-
return _MainPage(snippets: snippets ?? List.empty());
75+
return _MainPageData(
76+
navigator: navigator,
77+
snippets: snippets ?? List.empty(),
78+
);
5179
},
5280
),
5381
floatingActionButton: FloatingActionButton(
5482
onPressed: () => model.loadNextPage(),
5583
tooltip: 'Increment',
5684
child: const Icon(Icons.add),
57-
), // This trailing comma makes auto-formatting nicer for build methods.
85+
),
5886
);
5987
}
6088

@@ -68,27 +96,35 @@ class MainPage extends HookWidget {
6896
}
6997
}
7098

71-
class _MainPage extends StatelessWidget {
72-
const _MainPage({
99+
class _MainPageData extends StatelessWidget {
100+
const _MainPageData({
73101
Key? key,
102+
required this.navigator,
74103
required this.snippets,
75104
}) : super(key: key);
76105

106+
final DetailsNavigator navigator;
77107
final List<Snippet> snippets;
78108

79109
@override
80110
Widget build(BuildContext context) {
81111
return ListView.builder(
82112
itemCount: snippets.length,
83-
itemBuilder: (_, index) => Padding(
84-
padding: const EdgeInsets.symmetric(
85-
vertical: Dimens.s,
86-
horizontal: Dimens.m,
87-
),
88-
child: SnippetListTile(
89-
snippet: snippets[index],
90-
),
91-
),
113+
itemBuilder: (_, index) {
114+
final snippet = snippets[index];
115+
return Padding(
116+
padding: const EdgeInsets.symmetric(
117+
vertical: Dimens.s,
118+
horizontal: Dimens.m,
119+
),
120+
child: SnippetListTile(
121+
snippet: snippet,
122+
onTap: () {
123+
navigator.goToDetails(snippet.uuid!);
124+
},
125+
),
126+
);
127+
},
92128
);
93129
}
94130
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import 'package:go_router_plus/go_router_plus.dart';
2+
3+
abstract class NamedScreen extends Screen {
4+
NamedScreen(this._name);
5+
6+
final String _name;
7+
8+
@override
9+
String get routeName => _name;
10+
11+
@override
12+
String get routePath => '/$_name';
13+
}

flutter_module/lib/presentation/widgets/snippet_list_item.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@ class SnippetListTile extends HookWidget {
1212
const SnippetListTile({
1313
Key? key,
1414
required this.snippet,
15+
required this.onTap,
1516
}) : super(key: key);
1617

1718
final bool isExpanded = true;
1819
final Snippet snippet;
20+
final GestureTapCallback? onTap;
1921

2022
@override
2123
Widget build(BuildContext context) {
2224
return SurfaceStyles.snippetCard(
23-
onTap: () {},
25+
onTap: onTap,
2426
child: Expanded(
2527
child: Column(
2628
crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -62,4 +64,4 @@ class SnippetListTile extends HookWidget {
6264
),
6365
);
6466
}
65-
}
67+
}

flutter_module/pubspec.lock

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ packages:
207207
description: flutter
208208
source: sdk
209209
version: "0.0.0"
210+
flutter_web_plugins:
211+
dependency: transitive
212+
description: flutter
213+
source: sdk
214+
version: "0.0.0"
210215
frontend_server_client:
211216
dependency: transitive
212217
description:
@@ -221,6 +226,20 @@ packages:
221226
url: "https://pub.dartlang.org"
222227
source: hosted
223228
version: "2.1.0"
229+
go_router:
230+
dependency: "direct main"
231+
description:
232+
name: go_router
233+
url: "https://pub.dartlang.org"
234+
source: hosted
235+
version: "5.1.5"
236+
go_router_plus:
237+
dependency: "direct main"
238+
description:
239+
name: go_router_plus
240+
url: "https://pub.dartlang.org"
241+
source: hosted
242+
version: "2.0.0"
224243
graphs:
225244
dependency: transitive
226245
description:
@@ -255,7 +274,7 @@ packages:
255274
name: js
256275
url: "https://pub.dartlang.org"
257276
source: hosted
258-
version: "0.6.5"
277+
version: "0.6.4"
259278
json_annotation:
260279
dependency: transitive
261280
description:
@@ -522,4 +541,4 @@ packages:
522541
version: "3.1.1"
523542
sdks:
524543
dart: ">=2.18.2 <3.0.0"
525-
flutter: ">=3.0.0"
544+
flutter: ">=3.3.0"

0 commit comments

Comments
 (0)