Add full black theme

This commit is contained in:
niuhuan 2022-03-23 18:51:38 +08:00
parent f5dbbe4c4e
commit cae29f23bb
10 changed files with 256 additions and 140 deletions

View File

@ -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中。
- 本仓库仅作为学习交流使用, 请您遵守当地法律法规以及开源协议。

View File

@ -1 +1 @@
v1.4.2
v1.4.3

View File

@ -1 +1,2 @@
测试RELEASE
- [x] 增加纯黑主题
- [x] 设置点击屏幕一次为默认的全屏方式

View File

@ -28,7 +28,7 @@ late FullScreenAction _fullScreenAction;
Future<void> initFullScreenAction() async {
_fullScreenAction = _fullScreenActionFromString(await method.loadProperty(
_propertyName,
FullScreenAction.CONTROLLER.toString(),
FullScreenAction.TOUCH_ONCE.toString(),
));
}

View File

@ -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<void> 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<EventArgs>();
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<dynamic> 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<dynamic> chooseTheme(BuildContext buildContext) async {
String? theme = await showDialog<String>(
Future<String?> _chooseTheme(BuildContext buildContext) {
return showDialog<String>(
context: buildContext,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
var list = <SimpleDialogOption>[];
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 = <SimpleDialogOption>[];
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<dynamic> 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<dynamic> 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();
}

View File

@ -38,8 +38,8 @@ class _PikapikaAppState extends State<PikapikaApp> {
Widget build(BuildContext context) {
return MaterialApp(
scrollBehavior: mouseAndTouchScrollBehavior,
theme: currentThemeData(),
darkTheme: currentDarkTheme(),
theme: currentLightThemeData(),
darkTheme: currentDarkThemeData(),
navigatorObservers: [navigatorObserver, routeObserver],
home: const InitScreen(),
);

View File

@ -60,7 +60,7 @@ class _AccountScreenState extends State<AccountScreen> {
actions: [
IconButton(
onPressed: () {
chooseTheme(context);
// todo : chooseTheme(context);
},
icon: const Text('主题'),
),

View File

@ -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<StatefulWidget> createState() => _SpaceScreenState();
}
class _SpaceScreenState extends State<SpaceScreen> {
@override
void initState() {
versionEvent.subscribe(_onVersion);
@ -44,7 +43,7 @@ class _SpaceScreenState extends State<SpaceScreen> {
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<SpaceScreen> {
await method.setPassword("");
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => AccountScreen()),
MaterialPageRoute(
builder: (context) => const AccountScreen()),
);
}
},
@ -91,38 +91,45 @@ class _SpaceScreenState extends State<SpaceScreen> {
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('我的下载'),

View File

@ -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<StatefulWidget> createState() => _ThemeScreenState();
}
class _ThemeScreenState extends State<ThemeScreen> {
@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(),
],
),
);
}
}

View File

@ -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: