Global theme color

This commit is contained in:
LittleSheep 2024-07-31 02:44:49 +08:00
parent b70d3795d1
commit cc9c99f375
8 changed files with 148 additions and 22 deletions

View File

@ -1,12 +1,14 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:solian/exts.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/providers/content/channel.dart';
import 'package:solian/providers/relation.dart';
import 'package:solian/providers/websocket.dart';
import 'package:solian/services.dart';
import 'package:solian/theme.dart';
import 'package:solian/widgets/sized_container.dart';
class BootstrapperShell extends StatefulWidget {
@ -29,6 +31,18 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
int _periodCursor = 0;
late final List<({String label, Future<void> Function() action})> _periods = [
(
label: 'bsLoadingTheme',
action: () async {
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey('global_theme_color')) {
final value = prefs.getInt('global_theme_color')!;
final color = Color(value);
currentLightTheme = SolianTheme.build(Brightness.light, seedColor: color);
currentDarkTheme = SolianTheme.build(Brightness.dark, seedColor: color);
}
}
),
(
label: 'bsCheckingServer',
action: () async {

View File

@ -78,8 +78,8 @@ class SolianApp extends StatelessWidget {
Widget build(BuildContext context) {
return GetMaterialApp.router(
title: 'Solian',
theme: SolianTheme.build(Brightness.light),
darkTheme: SolianTheme.build(Brightness.dark),
theme: currentLightTheme,
darkTheme: currentDarkTheme,
themeMode: ThemeMode.system,
routerDelegate: AppRouter.instance.routerDelegate,
routeInformationParser: AppRouter.instance.routeInformationParser,

View File

@ -18,6 +18,7 @@ import 'package:solian/screens/realms/realm_organize.dart';
import 'package:solian/screens/realms/realm_view.dart';
import 'package:solian/screens/home.dart';
import 'package:solian/screens/posts/post_editor.dart';
import 'package:solian/screens/settings.dart';
import 'package:solian/shells/root_shell.dart';
import 'package:solian/shells/title_shell.dart';
@ -34,6 +35,22 @@ abstract class AppRouter {
_chatRoute,
_realmRoute,
_accountRoute,
GoRoute(
path: '/about',
name: 'about',
builder: (context, state) => TitleShell(
state: state,
child: const AboutScreen(),
),
),
GoRoute(
path: '/settings',
name: 'settings',
builder: (context, state) => TitleShell(
state: state,
child: const SettingScreen(),
),
),
],
),
],
@ -210,14 +227,6 @@ abstract class AppRouter {
name: state.pathParameters['name']!,
),
),
GoRoute(
path: '/about',
name: 'about',
builder: (context, state) => TitleShell(
state: state,
child: const AboutScreen(),
),
),
],
);
}

81
lib/screens/settings.dart Normal file
View File

@ -0,0 +1,81 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:solian/exts.dart';
import 'package:solian/theme.dart';
class SettingScreen extends StatefulWidget {
const SettingScreen({super.key});
@override
State<SettingScreen> createState() => _SettingScreenState();
}
class _SettingScreenState extends State<SettingScreen> {
late final SharedPreferences _prefs;
Widget _buildCaptionHeader(String title) {
return Container(
width: MediaQuery.of(context).size.width,
color: Theme.of(context).colorScheme.surfaceContainer,
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
child: Text(title),
);
}
Widget _buildThemeColorButton(String label, Color color) {
return IconButton(
icon: Icon(Icons.circle, color: color),
tooltip: label,
onPressed: () {
currentLightTheme =
SolianTheme.build(Brightness.light, seedColor: color);
currentDarkTheme = SolianTheme.build(Brightness.dark, seedColor: color);
_prefs.setInt('global_theme_color', color.value);
context.showSnackbar('themeColorApplied'.tr);
},
);
}
@override
void initState() {
super.initState();
SharedPreferences.getInstance().then((inst) {
_prefs = inst;
});
}
@override
Widget build(BuildContext context) {
return Material(
color: Theme.of(context).colorScheme.surface,
child: ListView(
children: [
_buildCaptionHeader('themeColor'.tr),
SizedBox(
height: 56,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
_buildThemeColorButton(
'themeColorRed'.tr,
const Color.fromRGBO(154, 98, 91, 1),
),
_buildThemeColorButton(
'themeColorBlue'.tr,
const Color.fromRGBO(103, 96, 193, 1),
),
_buildThemeColorButton(
'themeColorMiku'.tr,
const Color.fromRGBO(56, 120, 126, 1),
),
],
).paddingSymmetric(horizontal: 12, vertical: 8),
),
],
),
);
}
}

View File

@ -1,6 +1,9 @@
import 'package:flutter/material.dart';
import 'package:solian/platform.dart';
ThemeData? currentLightTheme = SolianTheme.build(Brightness.light);
ThemeData? currentDarkTheme = SolianTheme.build(Brightness.dark);
abstract class SolianTheme {
static bool isLargeScreen(BuildContext context) =>
MediaQuery.of(context).size.width > 640;
@ -27,13 +30,13 @@ abstract class SolianTheme {
}
}
static ThemeData build(Brightness brightness) {
static ThemeData build(Brightness brightness, {Color? seedColor}) {
return ThemeData(
brightness: brightness,
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
brightness: brightness,
seedColor: const Color.fromRGBO(154, 98, 91, 1),
seedColor: seedColor ?? const Color.fromRGBO(154, 98, 91, 1),
),
);
}

View File

@ -27,6 +27,7 @@ const i18nEnglish = {
'about': 'About',
'edit': 'Edit',
'delete': 'Delete',
'settings': 'Settings',
'search': 'Search',
'post': 'Post',
'article': 'Article',
@ -293,6 +294,7 @@ const i18nEnglish = {
'accountStatusNegative': 'Negative',
'accountStatusNeutral': 'Neutral',
'accountStatusPositive': 'Positive',
'bsLoadingTheme': 'Loading Theme',
'bsCheckingServer': 'Checking Server Status',
'bsCheckingServerFail':
'Unable connect to server, check your network connection',
@ -304,4 +306,9 @@ const i18nEnglish = {
'postShareContent':
'@content\n\n@username on the Solar Network\nCheck it out: @link',
'postShareSubject': '@username posted a post on the Solar Network',
'themeColor': 'Global Theme Color',
'themeColorRed': 'Modern Red',
'themeColorBlue': 'Classic Blue',
'themeColorMiku': 'Miku Blue',
'themeColorApplied': 'Global theme color has been saved, restart to get applied.',
};

View File

@ -13,6 +13,7 @@ const i18nSimplifiedChinese = {
'about': '关于',
'edit': '编辑',
'delete': '删除',
'settings': '设置',
'page': '页面',
'draft': '草稿',
'draftSave': '存为草稿',
@ -272,6 +273,7 @@ const i18nSimplifiedChinese = {
'accountStatusNegative': '负面',
'accountStatusNeutral': '中性',
'accountStatusPositive': '积极',
'bsLoadingTheme': '正在装载主题',
'bsCheckingServer': '检查服务器状态中',
'bsCheckingServerFail': '无法连接至服务器,请检查你的网络连接状态',
'bsCheckingServerDown': '当前服务器不可用,请稍后重试',
@ -281,4 +283,9 @@ const i18nSimplifiedChinese = {
'bsRegisteringPushNotify': '正在启用推送通知',
'postShareContent': '@content\n\n@username 在 Solar Network\n原帖地址:@link',
'postShareSubject': '@username 在 Solar Network 上发布了一篇帖子',
'themeColor': '全局主题色',
'themeColorRed': '现代红',
'themeColorBlue': '经典蓝',
'themeColorMiku': '未来色',
'themeColorApplied': '全局主题颜色已保存,重启后生效。',
};

View File

@ -138,17 +138,11 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
);
}),
trailing: IconButton(
icon: const Icon(Icons.face_retouching_natural),
icon: const Icon(Icons.settings),
onPressed: () {
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) => AccountStatusAction(
currentStatus: _accountStatus!.status,
),
).then((val) {
if (val == true) getStatus();
});
AppRouter.instance.pushNamed('settings');
setState(() => _selectedIndex = null);
closeDrawer();
},
),
onTap: () {
@ -156,6 +150,17 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
setState(() => _selectedIndex = null);
closeDrawer();
},
onLongPress: () {
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) => AccountStatusAction(
currentStatus: _accountStatus!.status,
),
).then((val) {
if (val == true) getStatus();
});
},
);
}).paddingOnly(top: 8),
const Divider(thickness: 0.3, height: 1).paddingOnly(