feat: add theme color option

This commit is contained in:
22
2024-12-10 20:51:51 +08:00
parent 96031089d8
commit cf082ac6ff
7 changed files with 140 additions and 18 deletions

View File

@@ -3,6 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_zustand/flutter_zustand.dart';
import 'package:iris/info.dart';
import 'package:iris/pages/home_page.dart';
import 'package:iris/store/use_app_store.dart';
import 'package:iris/utils/is_desktop.dart';
import 'package:media_kit/media_kit.dart';
import 'package:window_manager/window_manager.dart';
@@ -37,6 +38,18 @@ class MyApp extends HookWidget {
@override
Widget build(BuildContext context) {
String theme = useAppStore().select(context, (state) => state.theme);
ThemeMode themeMode = useMemoized(
() =>
{
'auto': ThemeMode.system,
'light': ThemeMode.light,
'dark': ThemeMode.dark,
}[theme] ??
ThemeMode.system,
[theme]);
return MaterialApp(
title: INFO.title,
theme: ThemeData(
@@ -44,7 +57,7 @@ class MyApp extends HookWidget {
useMaterial3: true,
),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.system,
themeMode: themeMode,
home: const HomePage(),
);
}

View File

@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_zustand/flutter_zustand.dart';
import 'package:iris/store/use_app_store.dart';
import 'package:iris/widgets/show_theme_color_dialog.dart';
class General extends HookWidget {
const General({super.key});
@override
Widget build(BuildContext context) {
final theme = useAppStore().select(context, (state) => state.theme);
return Column(children: [
ListTile(
leading: Icon(theme == 'light'
? Icons.light_mode_rounded
: theme == 'dark'
? Icons.dark_mode_rounded
: Icons.contrast_rounded),
title: const Text('Theme color'),
subtitle: Text(theme),
onTap: () => showThemeColorDialog(context),
),
]);
}
}

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:iris/pages/settings/about.dart';
import 'package:iris/pages/settings/general.dart';
import 'package:iris/pages/settings/libraries.dart';
class Settings extends HookWidget {
@@ -18,7 +19,9 @@ class Settings extends HookWidget {
child: TabBarView(
controller: tabController,
children: const [
Center(child: Text('General')),
SingleChildScrollView(
child: General(),
),
SingleChildScrollView(
child: About(),
),

View File

@@ -18,6 +18,11 @@ class AppStore extends PersistentStore<AppState> {
Future<void> toggleFullScreen() async =>
set(state.copyWith(isFullScreen: !state.isFullScreen));
Future<void> updateTheme(String theme) async {
set(state.copyWith(theme: theme));
save(state);
}
@override
Future<AppState?> load() async {
try {

View File

@@ -0,0 +1,78 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_zustand/flutter_zustand.dart';
import 'package:iris/store/use_app_store.dart';
Future<void> showThemeColorDialog(BuildContext context) async =>
await showDialog<void>(
context: context,
builder: (context) => const ThemeColorDialog(),
);
class ThemeColorDialog extends HookWidget {
const ThemeColorDialog({super.key});
@override
Widget build(BuildContext context) {
final theme = useAppStore().select(context, (state) => state.theme);
return AlertDialog(
title: const Text('Theme color'),
content: SingleChildScrollView(
child: Column(
children: [
ListTile(
title: const Text('Auto'),
leading: Radio(
value: 'auto',
groupValue: theme,
onChanged: (_) {
useAppStore().updateTheme('auto');
Navigator.pop(context);
},
),
onTap: () {
useAppStore().updateTheme('auto');
Navigator.pop(context);
},
),
ListTile(
title: const Text('Light'),
leading: Radio(
value: 'light',
groupValue: theme,
onChanged: (_) {
useAppStore().updateTheme('light');
Navigator.pop(context);
},
),
onTap: () {
useAppStore().updateTheme('light');
Navigator.pop(context);
},
),
ListTile(
title: const Text('Dark'),
leading: Radio(
value: 'dark',
groupValue: theme,
onChanged: (_) {
useAppStore().updateTheme('dark');
Navigator.pop(context);
},
),
onTap: () {
useAppStore().updateTheme('dark');
Navigator.pop(context);
},
),
],
)),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
],
);
}
}

View File

@@ -4,14 +4,11 @@ import 'package:iris/models/storages/local_storage.dart';
import 'package:iris/store/use_storage_store.dart';
Future<void> showLocalAlertDialog(BuildContext context,
{LocalStorage? localStorage}) async {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return LocalDialog(localStorage: localStorage);
},
);
}
{LocalStorage? localStorage}) async =>
await showDialog<void>(
context: context,
builder: (BuildContext context) =>
LocalDialog(localStorage: localStorage));
class LocalDialog extends HookWidget {
const LocalDialog({super.key, this.localStorage});

View File

@@ -4,14 +4,13 @@ import 'package:iris/models/storages/webdav_storage.dart';
import 'package:iris/store/use_storage_store.dart';
Future<void> showWebDAVAlertDialog(BuildContext context,
{WebdavStorage? webdavStorage}) async {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return WebDAVDialog(webdavStorage: webdavStorage);
},
);
}
{WebdavStorage? webdavStorage}) async =>
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return WebDAVDialog(webdavStorage: webdavStorage);
},
);
class WebDAVDialog extends HookWidget {
const WebDAVDialog({super.key, this.webdavStorage});