mirror of
https://github.com/nini22P/iris.git
synced 2026-05-31 08:31:29 +08:00
feat: add theme color option
This commit is contained in:
@@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
27
lib/pages/settings/general.dart
Normal file
27
lib/pages/settings/general.dart
Normal 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),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
78
lib/widgets/show_theme_color_dialog.dart
Normal file
78
lib/widgets/show_theme_color_dialog.dart
Normal 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'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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});
|
||||
|
||||
@@ -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});
|
||||
|
||||
Reference in New Issue
Block a user