From 5a03bee410fed4873634a62c5f42b12be9bee8d3 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 22 Aug 2023 16:49:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BB=E9=A2=98=E9=A2=9C=E8=89=B2?= =?UTF-8?q?=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 26 +++- lib/models/common/color_type.dart | 23 +++ lib/pages/setting/pages/color_select.dart | 162 ++++++++++++++++++++++ lib/pages/setting/style_setting.dart | 5 + lib/router/app_pages.dart | 2 + lib/utils/storage.dart | 25 ++-- 6 files changed, 227 insertions(+), 16 deletions(-) create mode 100644 lib/models/common/color_type.dart create mode 100644 lib/pages/setting/pages/color_select.dart diff --git a/lib/main.dart b/lib/main.dart index d35d8399..525cfd68 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:dynamic_color/dynamic_color.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/custom_toast.dart'; import 'package:pilipala/http/init.dart'; +import 'package:pilipala/models/common/color_type.dart'; import 'package:pilipala/models/common/theme_type.dart'; import 'package:pilipala/pages/search/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; @@ -35,15 +36,24 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - Color brandColor = const Color.fromARGB(255, 92, 182, 123); Box setting = GStrorage.setting; + // 主题色 + Color defaultColor = + colorThemeTypes[setting.get(SettingBoxKey.customColor, defaultValue: 0)] + ['color']; + Color brandColor = defaultColor; + // 主题模式 ThemeType currentThemeValue = ThemeType.values[setting .get(SettingBoxKey.themeMode, defaultValue: ThemeType.system.code)]; + // 是否动态取色 + bool isDynamicColor = + setting.get(SettingBoxKey.dynamicColor, defaultValue: true); + return DynamicColorBuilder( builder: ((ColorScheme? lightDynamic, ColorScheme? darkDynamic) { ColorScheme? lightColorScheme; ColorScheme? darkColorScheme; - if (lightDynamic != null && darkDynamic != null) { + if (lightDynamic != null && darkDynamic != null && isDynamicColor) { // dynamic取色成功 lightColorScheme = lightDynamic.harmonized(); darkColorScheme = darkDynamic.harmonized(); @@ -93,9 +103,15 @@ class MyApp extends StatelessWidget { fallbackLocale: const Locale("zh", "CN"), getPages: Routes.getPages, home: const MainApp(), - builder: FlutterSmartDialog.init( - toastBuilder: (String msg) => CustomToast(msg: msg), - ), + builder: (BuildContext context, Widget? child) { + return FlutterSmartDialog( + toastBuilder: (String msg) => CustomToast(msg: msg), + child: MediaQuery( + data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), + child: child!, + ), + ); + }, navigatorObservers: [ VideoDetailPage.routeObserver, SearchPage.routeObserver, diff --git a/lib/models/common/color_type.dart b/lib/models/common/color_type.dart new file mode 100644 index 00000000..25d5caa9 --- /dev/null +++ b/lib/models/common/color_type.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +final List> colorThemeTypes = [ + {'color': const Color.fromARGB(255, 92, 182, 123), 'label': '默认绿'}, + {'color': Colors.pink, 'label': '粉红色'}, + {'color': Colors.red, 'label': '红色'}, + {'color': Colors.orange, 'label': '橙色'}, + {'color': Colors.amber, 'label': '琥珀色'}, + {'color': Colors.yellow, 'label': '黄色'}, + {'color': Colors.lime, 'label': '酸橙色'}, + {'color': Colors.lightGreen, 'label': '浅绿色'}, + {'color': Colors.green, 'label': '绿色'}, + {'color': Colors.teal, 'label': '青色'}, + {'color': Colors.cyan, 'label': '蓝绿色'}, + {'color': Colors.lightBlue, 'label': '浅蓝色'}, + {'color': Colors.blue, 'label': '蓝色'}, + {'color': Colors.indigo, 'label': '靛蓝色'}, + {'color': Colors.purple, 'label': '紫色'}, + {'color': Colors.deepPurple, 'label': '深紫色'}, + {'color': Colors.blueGrey, 'label': '蓝灰色'}, + {'color': Colors.brown, 'label': '棕色'}, + {'color': Colors.grey, 'label': '灰色'}, +]; diff --git a/lib/pages/setting/pages/color_select.dart b/lib/pages/setting/pages/color_select.dart new file mode 100644 index 00000000..d0e34bcb --- /dev/null +++ b/lib/pages/setting/pages/color_select.dart @@ -0,0 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:hive/hive.dart'; +import 'package:pilipala/models/common/color_type.dart'; +import 'package:pilipala/utils/storage.dart'; + +class ColorSelectPage extends StatefulWidget { + const ColorSelectPage({super.key}); + + @override + State createState() => _ColorSelectPageState(); +} + +class Item { + Item({ + required this.expandedValue, + required this.headerValue, + this.isExpanded = false, + }); + + String expandedValue; + String headerValue; + bool isExpanded; +} + +List generateItems(int count) { + return List.generate(count, (int index) { + return Item( + headerValue: 'Panel $index', + expandedValue: 'This is item number $index', + ); + }); +} + +class _ColorSelectPageState extends State { + final ColorSelectController ctr = Get.put(ColorSelectController()); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: false, + title: const Text('选择应用主题'), + ), + body: ListView( + children: [ + Obx( + () => RadioListTile( + value: 0, + title: const Text('动态取色'), + groupValue: ctr.type.value, + onChanged: (dynamic val) async { + ctr.type.value = 0; + ctr.setting.put(SettingBoxKey.dynamicColor, true); + }, + ), + ), + Obx( + () => RadioListTile( + value: 1, + title: const Text('指定颜色'), + groupValue: ctr.type.value, + onChanged: (dynamic val) async { + ctr.type.value = 1; + ctr.setting.put(SettingBoxKey.dynamicColor, false); + }, + ), + ), + Obx( + () { + int type = ctr.type.value; + return AnimatedOpacity( + opacity: type == 1 ? 1 : 0, + duration: const Duration(milliseconds: 200), + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 12, right: 12), + child: Wrap( + alignment: WrapAlignment.center, + spacing: 22, + runSpacing: 18, + children: [ + ...ctr.colorThemes.map( + (e) { + final index = ctr.colorThemes.indexOf(e); + return GestureDetector( + onTap: () { + ctr.currentColor.value = index; + ctr.setting.put(SettingBoxKey.customColor, index); + Get.forceAppUpdate(); + }, + child: Column( + children: [ + Container( + width: 46, + height: 46, + decoration: BoxDecoration( + color: e['color'].withOpacity(0.8), + borderRadius: BorderRadius.circular(50), + border: Border.all( + width: 2, + color: ctr.currentColor.value == index + ? Colors.black + : e['color'].withOpacity(0.8), + ), + ), + child: AnimatedOpacity( + opacity: + ctr.currentColor.value == index ? 1 : 0, + duration: const Duration(milliseconds: 200), + child: const Icon( + Icons.done, + color: Colors.black, + size: 20, + ), + ), + ), + const SizedBox(height: 3), + Text( + e['label'], + style: TextStyle( + fontSize: 12, + color: ctr.currentColor.value != index + ? Theme.of(context).colorScheme.outline + : null, + ), + ), + ], + ), + ); + }, + ) + ], + ), + ), + ); + }, + ), + ], + ), + ); + } +} + +class ColorSelectController extends GetxController { + Box setting = GStrorage.setting; + RxBool dynamicColor = true.obs; + RxInt type = 0.obs; + late final List> colorThemes; + RxInt currentColor = 0.obs; + + @override + void onInit() { + colorThemes = colorThemeTypes; + // 默认使用动态取色 + dynamicColor.value = + setting.get(SettingBoxKey.dynamicColor, defaultValue: true); + type.value = dynamicColor.value ? 0 : 1; + currentColor.value = + setting.get(SettingBoxKey.customColor, defaultValue: 0); + super.onInit(); + } +} diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 397edbbf..6dfd4031 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -184,6 +184,11 @@ class _StyleSettingState extends State { style: subTitleStyle)), trailing: const Icon(Icons.arrow_right_alt_outlined), ), + ListTile( + dense: false, + onTap: () => Get.toNamed('/colorSetting'), + title: Text('应用主题', style: titleStyle), + ), ], ), ); diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index f525e4e5..f5505b72 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -17,6 +17,7 @@ import 'package:pilipala/pages/preview/index.dart'; import 'package:pilipala/pages/search/index.dart'; import 'package:pilipala/pages/searchResult/index.dart'; import 'package:pilipala/pages/setting/extra_setting.dart'; +import 'package:pilipala/pages/setting/pages/color_select.dart'; import 'package:pilipala/pages/setting/play_setting.dart'; import 'package:pilipala/pages/setting/privacy_setting.dart'; import 'package:pilipala/pages/setting/style_setting.dart'; @@ -85,6 +86,7 @@ class Routes { GetPage(name: '/extraSetting', page: () => const ExtraSetting()), // GetPage(name: '/blackListPage', page: () => const BlackListPage()), + GetPage(name: '/colorSetting', page: () => const ColorSelectPage()), // 关于 GetPage(name: '/about', page: () => const AboutPage()), ]; diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index b70589a5..2f5c1f6d 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -82,24 +82,27 @@ class GStrorage { } class SettingBoxKey { - static const String themeMode = 'themeMode'; - static const String feedBackEnable = 'feedBackEnable'; - static const String defaultFontSize = 'fontSize'; - static const String defaultVideoQa = 'defaultVideoQa'; - static const String defaultAudioQa = 'defaultAudioQa'; - static const String defaultDecode = 'defaultDecode'; + static const String btmProgressBehavior = 'btmProgressBehavior'; static const String defaultVideoSpeed = 'defaultVideoSpeed'; static const String autoUpgradeEnable = 'autoUpgradeEnable'; + static const String feedBackEnable = 'feedBackEnable'; + static const String defaultVideoQa = 'defaultVideoQa'; + static const String defaultAudioQa = 'defaultAudioQa'; static const String autoPlayEnable = 'autoPlayEnable'; - static const String enableHA = 'enableHA'; - static const String defaultPicQa = 'defaultPicQa'; - - static const String danmakuEnable = 'danmakuEnable'; static const String fullScreenMode = 'fullScreenMode'; + static const String defaultDecode = 'defaultDecode'; + static const String danmakuEnable = 'danmakuEnable'; + static const String defaultPicQa = 'defaultPicQa'; + static const String enableHA = 'enableHA'; static const String blackMidsList = 'blackMidsList'; + static const String autoUpdate = 'autoUpdate'; - static const String btmProgressBehavior = 'btmProgressBehavior'; + + static const String themeMode = 'themeMode'; + static const String defaultFontSize = 'fontSize'; + static const String dynamicColor = 'dynamicColor'; // bool + static const String customColor = 'customColor'; // 自定义主题色 } class LocalCacheKey {