From cae29f23bba1bd2b724a08dd4134c621854b001d Mon Sep 17 00:00:00 2001 From: niuhuan Date: Wed, 23 Mar 2022 18:51:38 +0800 Subject: [PATCH] Add full black theme --- README.md | 7 +- ci/version.code.txt | 2 +- ci/version.info.txt | 3 +- lib/basic/config/FullScreenAction.dart | 2 +- lib/basic/config/Themes.dart | 276 ++++++++++++++----------- lib/main.dart | 4 +- lib/screens/AccountScreen.dart | 2 +- lib/screens/SpaceScreen.dart | 35 ++-- lib/screens/ThemeScreen.dart | 63 ++++++ pubspec.lock | 2 +- 10 files changed, 256 insertions(+), 140 deletions(-) create mode 100644 lib/screens/ThemeScreen.dart diff --git a/README.md b/README.md index 1989c5b..8ba5204 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ PIKAPIKA - 漫画客户端 ======== -[![license](https://img.shields.io/github/license/niuhuan/pikapika)](https://raw.githubusercontent.com/niuhuan/pikapika/master/LICENSE) -[![releases](https://img.shields.io/github/v/release/niuhuan/pikapika)](https://github.com/niuhuan/pikapika/releases) -[![downloads](https://img.shields.io/github/downloads/niuhuan/pikapika/total)](https://github.com/niuhuan/pikapika/releases) +[![license](https://img.shields.io/github/license/niuhuan/pikapika)](https://raw.githubusercontent.com/niuhuan/pikapika/master/LICENSE) +[![ci-release](https://img.shields.io/github/workflow/status/niuhuan/pikapika/Release)](https://github.com/niuhuan/pikapika/releases) +[![releases](https://img.shields.io/github/v/release/niuhuan/pikapika)](https://github.com/niuhuan/pikapika/releases) +[![downloads](https://img.shields.io/github/downloads/niuhuan/pikapika/total)](https://github.com/niuhuan/pikapika/releases) - 美观易用且无广告的漫画客户端, 能运行在Windows/MacOS/Linux/Android/IOS中。 - 本仓库仅作为学习交流使用, 请您遵守当地法律法规以及开源协议。 diff --git a/ci/version.code.txt b/ci/version.code.txt index 87ff52e..5beebea 100644 --- a/ci/version.code.txt +++ b/ci/version.code.txt @@ -1 +1 @@ -v1.4.2 \ No newline at end of file +v1.4.3 \ No newline at end of file diff --git a/ci/version.info.txt b/ci/version.info.txt index c1852c6..06e9222 100644 --- a/ci/version.info.txt +++ b/ci/version.info.txt @@ -1 +1,2 @@ -测试RELEASE \ No newline at end of file +- [x] 增加纯黑主题 +- [x] 设置点击屏幕一次为默认的全屏方式 diff --git a/lib/basic/config/FullScreenAction.dart b/lib/basic/config/FullScreenAction.dart index 1eebc70..6e58363 100644 --- a/lib/basic/config/FullScreenAction.dart +++ b/lib/basic/config/FullScreenAction.dart @@ -28,7 +28,7 @@ late FullScreenAction _fullScreenAction; Future initFullScreenAction() async { _fullScreenAction = _fullScreenActionFromString(await method.loadProperty( _propertyName, - FullScreenAction.CONTROLLER.toString(), + FullScreenAction.TOUCH_ONCE.toString(), )); } diff --git a/lib/basic/config/Themes.dart b/lib/basic/config/Themes.dart index cc71f1f..7197fbf 100644 --- a/lib/basic/config/Themes.dart +++ b/lib/basic/config/Themes.dart @@ -7,7 +7,6 @@ import 'package:pikapika/basic/Common.dart'; import '../Method.dart'; import 'Platform.dart'; - // 字体相关 const _fontFamilyProperty = "fontFamily"; @@ -28,13 +27,17 @@ ThemeData _fontThemeData(bool dark) { Future inputFont(BuildContext context) async { var font = await displayTextInputDialog( - context, src: "$_fontFamily", title: "字体", hint: "请输入字体", - desc: "请输入字体的名称, 例如宋体/黑体, 如果您保存后没有发生变化, 说明字体无法使用或名称错误, 可以去参考C:\\Windows\\Fonts寻找您的字体。", + context, + src: "$_fontFamily", + title: "字体", + hint: "请输入字体", + desc: + "请输入字体的名称, 例如宋体/黑体, 如果您保存后没有发生变化, 说明字体无法使用或名称错误, 可以去参考C:\\Windows\\Fonts寻找您的字体。", ); if (font != null) { await method.saveProperty(_fontFamilyProperty, font); _fontFamily = font; - _changeThemeByCode(_themeCode); + _reloadTheme(); } } @@ -62,6 +65,8 @@ abstract class _ThemePackage { String name(); ThemeData themeData(ThemeData rawData); + + bool isDark(); } class _OriginTheme extends _ThemePackage { @@ -73,6 +78,9 @@ class _OriginTheme extends _ThemePackage { @override ThemeData themeData(ThemeData rawData) => rawData; + + @override + bool isDark() => false; } class _PinkTheme extends _ThemePackage { @@ -83,8 +91,7 @@ class _PinkTheme extends _ThemePackage { String name() => "粉色"; @override - ThemeData themeData(ThemeData rawData) => - rawData.copyWith( + ThemeData themeData(ThemeData rawData) => rawData.copyWith( brightness: Brightness.light, colorScheme: ColorScheme.light( secondary: Colors.pink.shade200, @@ -113,6 +120,9 @@ class _PinkTheme extends _ThemePackage { ), ), ); + + @override + bool isDark() => false; } class _BlackTheme extends _ThemePackage { @@ -123,8 +133,7 @@ class _BlackTheme extends _ThemePackage { String name() => "酷黑"; @override - ThemeData themeData(ThemeData rawData) => - rawData.copyWith( + ThemeData themeData(ThemeData rawData) => rawData.copyWith( brightness: Brightness.light, colorScheme: ColorScheme.light( secondary: Colors.pink.shade200, @@ -154,6 +163,9 @@ class _BlackTheme extends _ThemePackage { ), ), ); + + @override + bool isDark() => false; } class _DarkTheme extends _ThemePackage { @@ -164,8 +176,7 @@ class _DarkTheme extends _ThemePackage { String name() => "暗黑"; @override - ThemeData themeData(ThemeData rawData) => - rawData.copyWith( + ThemeData themeData(ThemeData rawData) => rawData.copyWith( brightness: Brightness.light, colorScheme: ColorScheme.light( secondary: Colors.pink.shade200, @@ -194,6 +205,9 @@ class _DarkTheme extends _ThemePackage { ), ), ); + + @override + bool isDark() => true; } class _DustyBlueTheme extends _ThemePackage { @@ -204,13 +218,14 @@ class _DustyBlueTheme extends _ThemePackage { String name() => "灰蓝"; @override - ThemeData themeData(ThemeData rawData) => - rawData.copyWith( + ThemeData themeData(ThemeData rawData) => rawData.copyWith( scaffoldBackgroundColor: Color.alphaBlend( - const Color(0x11999999), const Color(0xff20253b), + const Color(0x11999999), + const Color(0xff20253b), ), cardColor: Color.alphaBlend( - const Color(0x11AAAAAA), const Color(0xff20253b), + const Color(0x11AAAAAA), + const Color(0xff20253b), ), brightness: Brightness.light, colorScheme: ColorScheme.light( @@ -244,153 +259,182 @@ class _DustyBlueTheme extends _ThemePackage { ), ), ); + + @override + bool isDark() => true; } -var _darkTheme = _DarkTheme(); -var _dustyBlueTheme = _DustyBlueTheme(); +class _DarkBlackTheme extends _ThemePackage { + @override + String code() => "dark_black"; + + @override + String name() => "纯黑"; + + @override + ThemeData themeData(ThemeData rawData) => rawData.copyWith( + brightness: Brightness.light, + colorScheme: ColorScheme.light( + secondary: Colors.pink.shade200, + ), + scaffoldBackgroundColor: Colors.black, + appBarTheme: const AppBarTheme( + systemOverlayStyle: SystemUiOverlayStyle.light, + color: Color.fromARGB(0xff, 10, 10, 10), + iconTheme: IconThemeData( + color: Colors.white, + ), + ), + bottomNavigationBarTheme: BottomNavigationBarThemeData( + selectedItemColor: Colors.white, + unselectedItemColor: Colors.grey.shade300, + backgroundColor: const Color.fromARGB(0xff, 10, 10, 10), + ), + primaryColor: Colors.pink.shade200, + textSelectionTheme: TextSelectionThemeData( + cursorColor: Colors.pink.shade200, + selectionColor: Colors.pink.shade300.withAlpha(150), + selectionHandleColor: Colors.pink.shade300.withAlpha(200), + ), + inputDecorationTheme: InputDecorationTheme( + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide(color: Colors.pink.shade200), + ), + ), + dividerColor: const Color.fromARGB(0xff, 64, 64, 64), + ); + + @override + bool isDark() => true; +} final _themePackages = <_ThemePackage>[ _OriginTheme(), _PinkTheme(), _BlackTheme(), - _darkTheme, - _dustyBlueTheme, + _DarkTheme(), + _DustyBlueTheme(), + _DarkBlackTheme(), ]; // 主题更换事件 var themeEvent = Event(); -const _themePropertyName = "theme"; -const _defaultThemeCode = "pink"; +const _nightModePropertyName = "androidNightMode"; +const _lightThemePropertyName = "theme"; +const _darkThemePropertyName = "theme.dark"; +const _defaultLightThemeCode = "pink"; +const _defaultDarkThemeCode = "dark"; +bool androidNightModeDisplay = false; +bool androidNightMode = false; -String? _themeCode; -ThemeData? _themeData; -ThemeData? _currentDarkTheme; -bool _androidNightMode = false; +String? _lightThemeCode; +ThemeData? _lightThemeData; +String? _darkThemeCode; +ThemeData? _darkThemeData; -String currentThemeName() { +// _changeThemeByCode + +String _codeToName(String? code) { for (var package in _themePackages) { - if (_themeCode == package.code()) { + if (code == package.code()) { return package.name(); } } return ""; } -ThemeData? currentThemeData() { - return _themeData; +String currentLightThemeName() { + return _codeToName(_lightThemeCode); } -ThemeData? currentDarkTheme() { - return _currentDarkTheme; +String currentDarkThemeName() { + return _codeToName(_darkThemeCode); +} + +ThemeData? currentLightThemeData() { + return _lightThemeData; +} + +ThemeData? currentDarkThemeData() { + return _darkThemeData; } // 根据Code选择主题, 并发送主题更换事件 -void _changeThemeByCode(String? themeCode) { - _ThemePackage? _themePackage; + +ThemeData? _themeByCode(String? themeCode) { for (var package in _themePackages) { if (themeCode == package.code()) { - _themeCode = themeCode; - _themePackage = package; - break; + return package.themeData(_fontThemeData(package.isDark())); } } - if (_themePackage != null) { - _themeData = _themePackage.themeData( - _fontThemeData( - _themePackage == _darkTheme || _themePackage == _dustyBlueTheme), - ); + return null; +} + +void _reloadTheme() { + _lightThemeData = _themeByCode(_lightThemeCode); + if (androidNightMode) { + _darkThemeData = _themeByCode(_darkThemeCode); + } else { + _darkThemeData = _lightThemeData; } - _currentDarkTheme = _androidNightMode - ? _darkTheme.themeData(_fontThemeData(true)) - : _themeData; themeEvent.broadcast(); } -// 为了匹配安卓夜间模式增加的配置文件 -const _nightModePropertyName = "androidNightMode"; - Future initTheme() async { - _androidNightMode = + androidNightModeDisplay = androidVersion >= 29; + androidNightMode = await method.loadProperty(_nightModePropertyName, "true") == "true"; - _changeThemeByCode( - await method.loadProperty(_themePropertyName, _defaultThemeCode), - ); + _lightThemeCode = await method.loadProperty( + _lightThemePropertyName, _defaultLightThemeCode); + _darkThemeCode = + await method.loadProperty(_darkThemePropertyName, _defaultDarkThemeCode); + _reloadTheme(); } // 选择主题的对话框 -Future chooseTheme(BuildContext buildContext) async { - String? theme = await showDialog( +Future _chooseTheme(BuildContext buildContext) { + return showDialog( context: buildContext, builder: (BuildContext context) { return StatefulBuilder( builder: (BuildContext context, StateSetter setState) { - var list = []; - if (androidVersion >= 29) { - var onChange = (bool? v) async { - if (v != null) { - await method.saveProperty( - _nightModePropertyName, "$v"); - _androidNightMode = v; - } - _changeThemeByCode(_themeCode); - }; - list.add( - SimpleDialogOption( - child: GestureDetector( - onTap: () { - onChange(!_androidNightMode); - }, - child: Container( - margin: const EdgeInsets.only(top: 3, bottom: 3), - decoration: BoxDecoration( - border: Border( - top: BorderSide( - color: Theme - .of(context) - .dividerColor, - width: 0.5, - ), - bottom: BorderSide( - color: Theme - .of(context) - .dividerColor, - width: 0.5 - ), - ), - ), - child: Row( - children: [ - Checkbox( - value: _androidNightMode, - onChanged: onChange, - ), - const Text("随手机进入黑暗模式"), - ], - ), - ), - ), - ), - ); - } - list.addAll(_themePackages - .map((e) => - SimpleDialogOption( - child: Text(e.name()), - onPressed: () { - Navigator.of(context).pop(e.code()); - }, - ) - )); - return SimpleDialog( - title: const Text("选择主题"), - children: list, - ); - }) + var list = []; + list.addAll(_themePackages.map((e) => SimpleDialogOption( + child: Text(e.name()), + onPressed: () { + Navigator.of(context).pop(e.code()); + }, + ))); + return SimpleDialog( + title: const Text("选择主题"), + children: list, + ); + }); }, ); +} + +Future chooseLightTheme(BuildContext buildContext) async { + String? theme = await _chooseTheme(buildContext); if (theme != null) { - method.saveProperty(_themePropertyName, theme); - _changeThemeByCode(theme); + await method.saveProperty(_lightThemePropertyName, theme); + _lightThemeCode = theme; + _reloadTheme(); } } + +Future chooseDarkTheme(BuildContext buildContext) async { + String? theme = await _chooseTheme(buildContext); + if (theme != null) { + await method.saveProperty(_darkThemePropertyName, theme); + _darkThemeCode = theme; + _reloadTheme(); + } +} + +Future setAndroidNightMode(bool value) async { + await method.saveProperty(_nightModePropertyName, "$value"); + androidNightMode = value; + _reloadTheme(); +} diff --git a/lib/main.dart b/lib/main.dart index 990afc1..29095bd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,8 +38,8 @@ class _PikapikaAppState extends State { Widget build(BuildContext context) { return MaterialApp( scrollBehavior: mouseAndTouchScrollBehavior, - theme: currentThemeData(), - darkTheme: currentDarkTheme(), + theme: currentLightThemeData(), + darkTheme: currentDarkThemeData(), navigatorObservers: [navigatorObserver, routeObserver], home: const InitScreen(), ); diff --git a/lib/screens/AccountScreen.dart b/lib/screens/AccountScreen.dart index 1e22d52..461c1e1 100644 --- a/lib/screens/AccountScreen.dart +++ b/lib/screens/AccountScreen.dart @@ -60,7 +60,7 @@ class _AccountScreenState extends State { actions: [ IconButton( onPressed: () { - chooseTheme(context); + // todo : chooseTheme(context); }, icon: const Text('主题'), ), diff --git a/lib/screens/SpaceScreen.dart b/lib/screens/SpaceScreen.dart index d3afbc1..cb900ac 100644 --- a/lib/screens/SpaceScreen.dart +++ b/lib/screens/SpaceScreen.dart @@ -1,14 +1,15 @@ import 'package:flutter/material.dart'; import 'package:pikapika/basic/Common.dart'; -import 'package:pikapika/basic/config/Themes.dart'; import 'package:pikapika/basic/config/Version.dart'; import 'package:pikapika/screens/AboutScreen.dart'; import 'package:pikapika/screens/AccountScreen.dart'; import 'package:pikapika/screens/DownloadListScreen.dart'; import 'package:pikapika/screens/FavouritePaperScreen.dart'; +import 'package:pikapika/screens/ThemeScreen.dart'; import 'package:pikapika/screens/ViewLogsScreen.dart'; import 'package:pikapika/basic/Method.dart'; +import '../basic/config/Themes.dart'; import 'SettingsScreen.dart'; import 'components/Badge.dart'; import 'components/UserProfileCard.dart'; @@ -17,13 +18,11 @@ import 'components/UserProfileCard.dart'; class SpaceScreen extends StatefulWidget { const SpaceScreen({Key? key}) : super(key: key); - @override State createState() => _SpaceScreenState(); } class _SpaceScreenState extends State { - @override void initState() { versionEvent.subscribe(_onVersion); @@ -44,7 +43,7 @@ class _SpaceScreenState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('我的'), + title: const Text('我的'), actions: [ IconButton( onPressed: () async { @@ -55,7 +54,8 @@ class _SpaceScreenState extends State { await method.setPassword(""); Navigator.pushReplacement( context, - MaterialPageRoute(builder: (context) => AccountScreen()), + MaterialPageRoute( + builder: (context) => const AccountScreen()), ); } }, @@ -91,38 +91,45 @@ class _SpaceScreenState extends State { const Divider(), ListTile( onTap: () async { - await chooseTheme(context); - setState(() {}); + if (androidNightModeDisplay) { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const ThemeScreen()), + ); + } else { + chooseLightTheme(context); + } }, - title: Text('主题'), - subtitle: Text(currentThemeName()), + title: const Text('主题'), ), const Divider(), ListTile( onTap: () { Navigator.push( context, - MaterialPageRoute(builder: (context) => FavouritePaperScreen()), + MaterialPageRoute( + builder: (context) => const FavouritePaperScreen()), ); }, - title: Text('我的收藏'), + title: const Text('我的收藏'), ), const Divider(), ListTile( onTap: () { Navigator.push( context, - MaterialPageRoute(builder: (context) => ViewLogsScreen()), + MaterialPageRoute(builder: (context) => const ViewLogsScreen()), ); }, - title: Text('浏览记录'), + title: const Text('浏览记录'), ), const Divider(), ListTile( onTap: () { Navigator.push( context, - MaterialPageRoute(builder: (context) => const DownloadListScreen()), + MaterialPageRoute( + builder: (context) => const DownloadListScreen()), ); }, title: const Text('我的下载'), diff --git a/lib/screens/ThemeScreen.dart b/lib/screens/ThemeScreen.dart new file mode 100644 index 0000000..79f4224 --- /dev/null +++ b/lib/screens/ThemeScreen.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; + +import '../basic/config/Themes.dart'; +import 'components/RightClickPop.dart'; + +class ThemeScreen extends StatefulWidget { + const ThemeScreen({Key? key}) : super(key: key); + + @override + State createState() => _ThemeScreenState(); +} + +class _ThemeScreenState extends State { + @override + Widget build(BuildContext context) { + return RightClickPop(buildScreen(context)); + } + + Widget buildScreen(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text("主题设置")), + body: ListView( + children: [ + const Divider(), + ListTile( + onTap: () async { + await chooseLightTheme(context); + setState(() {}); + }, + title: const Text('主题'), + subtitle: Text(currentLightThemeName()), + ), + const Divider(), + ...androidNightModeDisplay + ? [ + SwitchListTile( + title: const Text("深色模式下使用不同的主题"), + value: androidNightMode, + onChanged: (value) async { + await setAndroidNightMode(value); + setState(() {}); + }), + ] + : [], + const Divider(), + ...androidNightModeDisplay && androidNightMode + ? [ + ListTile( + onTap: () async { + await chooseDarkTheme(context); + setState(() {}); + }, + title: const Text('主题 (深色模式)'), + subtitle: Text(currentDarkThemeName()), + ), + ] + : [], + const Divider(), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index b59b132..0e9233f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -494,7 +494,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.4.4" xml: dependency: transitive description: