Skip to content

Commit b34e3a6

Browse files
authored
Merge pull request #13 from dhafinrayhan/settings-in-profile-screen
Move logout button
2 parents 7706c75 + b0eceb5 commit b34e3a6

File tree

4 files changed

+114
-16
lines changed

4 files changed

+114
-16
lines changed
Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import 'package:flutter/material.dart';
22
import 'package:hooks_riverpod/hooks_riverpod.dart';
33

4+
import '../../../services/theme_mode.dart';
5+
import '../../../utils/theme_mode_helper.dart';
46
import '../../auth/providers/auth_state.dart';
57
import '../providers/profile.dart';
68

@@ -10,34 +12,89 @@ class ProfileScreen extends ConsumerWidget {
1012
@override
1113
Widget build(BuildContext context, WidgetRef ref) {
1214
final profile = ref.watch(currentProfileProvider);
15+
final themeMode = ref.watch(currentThemeModeProvider);
16+
1317
final profileRecords = [
1418
(label: 'Name', text: profile?.fullName),
1519
(label: 'Username', text: profile?.username),
1620
(label: 'Email', text: profile?.email),
1721
];
1822

23+
void showThemeModeDialog() {
24+
showDialog(
25+
context: context,
26+
builder: (_) => const _ThemeModeDialog(),
27+
);
28+
}
29+
30+
void logout() {
31+
ref.read(currentAuthStateProvider.notifier).logout();
32+
}
33+
1934
return Scaffold(
2035
appBar: AppBar(
2136
title: const Text('Profile'),
22-
actions: [
23-
IconButton(
24-
onPressed: () =>
25-
ref.read(currentAuthStateProvider.notifier).logout(),
26-
icon: const Icon(Icons.logout),
27-
tooltip: 'Logout',
37+
),
38+
body: ListView(
39+
children: [
40+
for (final record in profileRecords)
41+
ListTile(
42+
title: Text(record.label),
43+
subtitle: Text(record.text ?? ''),
44+
),
45+
const Divider(),
46+
ListTile(
47+
leading: const Icon(Icons.brightness_6),
48+
title: const Text('Theme mode'),
49+
trailing: Text(themeMode.label),
50+
onTap: showThemeModeDialog,
51+
),
52+
const Divider(),
53+
ListTile(
54+
leading: const Icon(Icons.logout),
55+
title: const Text('Logout'),
56+
onTap: logout,
2857
),
2958
],
3059
),
31-
body: ListView.builder(
32-
itemCount: profileRecords.length,
33-
itemBuilder: (_, index) {
34-
final record = profileRecords[index];
35-
return ListTile(
36-
title: Text(record.label),
37-
subtitle: Text(record.text ?? ''),
38-
);
39-
},
40-
),
60+
);
61+
}
62+
}
63+
64+
class _ThemeModeDialog extends ConsumerWidget {
65+
const _ThemeModeDialog();
66+
67+
@override
68+
Widget build(BuildContext context, WidgetRef ref) {
69+
void setThemeMode(ThemeMode themeMode) {
70+
ref.read(currentThemeModeProvider.notifier).set(themeMode);
71+
Navigator.of(context).pop();
72+
}
73+
74+
return SimpleDialog(
75+
clipBehavior: Clip.antiAlias,
76+
children: [
77+
for (final themeMode in ThemeMode.values)
78+
_ThemeModeDialogOption(
79+
value: themeMode,
80+
onTap: () => setThemeMode(themeMode),
81+
)
82+
],
83+
);
84+
}
85+
}
86+
87+
class _ThemeModeDialogOption extends StatelessWidget {
88+
const _ThemeModeDialogOption({required this.value, required this.onTap});
89+
90+
final ThemeMode value;
91+
final GestureTapCallback? onTap;
92+
93+
@override
94+
Widget build(BuildContext context) {
95+
return ListTile(
96+
onTap: onTap,
97+
title: Text(value.label),
4198
);
4299
}
43100
}

lib/main.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
66

77
import 'features/profile/models/profile.dart';
88
import 'services/router.dart';
9+
import 'services/theme_mode.dart';
910

1011
Future<void> main() async {
1112
HttpOverrides.global = _HttpOverrides();
@@ -22,6 +23,7 @@ Future<void> main() async {
2223
await [
2324
Hive.openBox<Profile>('profile'),
2425
Hive.openBox<String>('token'),
26+
Hive.openBox<String>('settings'),
2527
].wait;
2628
});
2729

@@ -37,9 +39,11 @@ class DummyMartApp extends ConsumerWidget {
3739
@override
3840
Widget build(BuildContext context, WidgetRef ref) {
3941
final router = ref.watch(routerProvider);
42+
final themeMode = ref.watch(currentThemeModeProvider);
4043

4144
return MaterialApp.router(
4245
title: 'DummyMart',
46+
themeMode: themeMode,
4347
theme: ThemeData(
4448
useMaterial3: true,
4549
colorSchemeSeed: Colors.blue,

lib/services/theme_mode.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:hive_flutter/hive_flutter.dart';
3+
import 'package:riverpod_annotation/riverpod_annotation.dart';
4+
5+
part 'theme_mode.g.dart';
6+
7+
@Riverpod(keepAlive: true)
8+
class CurrentThemeMode extends _$CurrentThemeMode {
9+
@override
10+
ThemeMode build() {
11+
// Load the saved theme mode setting from Hive box.
12+
final themeModeName = Hive.box<String>('settings').get('themeMode');
13+
14+
// Return [ThemeMode] based on the saved setting, or [ThemeMode.system]
15+
// if there's no saved setting yet.
16+
return ThemeMode.values.singleWhere(
17+
(themeMode) => themeMode.name == themeModeName,
18+
orElse: () => ThemeMode.system,
19+
);
20+
}
21+
22+
void set(ThemeMode themeMode) {
23+
state = themeMode;
24+
25+
// Save the new theme mode to Hive box.
26+
Hive.box<String>('settings').put('themeMode', themeMode.name);
27+
}
28+
}

lib/utils/theme_mode_helper.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import 'package:flutter/material.dart';
2+
3+
extension ThemeModeHelper on ThemeMode {
4+
String get label => switch (this) {
5+
ThemeMode.system => 'System',
6+
ThemeMode.light => 'Light',
7+
ThemeMode.dark => 'Dark',
8+
};
9+
}

0 commit comments

Comments
 (0)