From d5df963020e25aab24783ee524a985edb68614b6 Mon Sep 17 00:00:00 2001 From: niuhuan Date: Fri, 15 Oct 2021 14:18:29 +0800 Subject: [PATCH] font setting --- .gitignore | 3 + README.md | 6 ++ .../kotlin/niuhuan/pikapi/MainActivity.kt | 42 -------- go/mobile/bind-ios.sh | 2 +- ios/Runner.xcodeproj/project.pbxproj | 10 +- lib/basic/config/Themes.dart | 99 ++++++++++++++----- lib/main.dart | 1 + lib/screens/InitScreen.dart | 1 + lib/screens/SettingsScreen.dart | 2 + 9 files changed, 92 insertions(+), 74 deletions(-) diff --git a/.gitignore b/.gitignore index 43f2dec..e329e38 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,7 @@ app.*.map.json /go/mobile/lib/*.aar /go/mobile/lib/*.jar /go/mobile/lib/*.framework/ +/go/mobile/lib/*.xcframework/ /go/vendor/ + +ios/build/ diff --git a/README.md b/README.md index 8ca2351..8c7794d 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,12 @@ VPN->代理->分流, 这三个功能如果同时设置, 您会在您手机的VPN ### 移动端 (gomobile) +- 编译环境 + ```shell + # 安卓环境需要安装AndroidSDK, 并且安装platforms以及ndk, 配置 ANDROID_HOME + # IOS需要安装xcode以及CocoaPods + gem install cocoapods + ``` - [安装gomobile](https://github.com/golang/mobile) ```shell go install golang.org/x/mobile/cmd/gomobile@latest diff --git a/android/app/src/main/kotlin/niuhuan/pikapi/MainActivity.kt b/android/app/src/main/kotlin/niuhuan/pikapi/MainActivity.kt index 7e99055..e24fba2 100644 --- a/android/app/src/main/kotlin/niuhuan/pikapi/MainActivity.kt +++ b/android/app/src/main/kotlin/niuhuan/pikapi/MainActivity.kt @@ -1,8 +1,6 @@ package niuhuan.pikapi import android.content.ContentValues -import android.content.Intent -import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Build @@ -87,9 +85,6 @@ class MainActivity : FlutterActivity() { "androidSetMode" -> { setMode(call.argument("mode")!!) } - "androidGetUiMode" -> { - uiMode() - } "androidGetVersion" -> Build.VERSION.SDK_INT // "exportComicDownloadAndroidQ" -> { // exportComicDownloadAndroidQ(call.argument("comicId")!!) @@ -143,9 +138,6 @@ class MainActivity : FlutterActivity() { EventChannel(flutterEngine.dartExecutor.binaryMessenger, "volume_button") .setStreamHandler(volumeStreamHandler) - // - EventChannel(flutterEngine.dartExecutor.binaryMessenger, "ui_mode") - .setStreamHandler(uiModeStreamHandler) } // save_image @@ -257,40 +249,6 @@ class MainActivity : FlutterActivity() { return super.onKeyDown(keyCode, event) } - // ui_mode - - private var uiModeEvents: EventChannel.EventSink? = null - - private val uiModeStreamHandler = object : EventChannel.StreamHandler { - - override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { - uiModeEvents = events - } - - override fun onCancel(arguments: Any?) { - uiModeEvents = null - } - } - - override fun onConfigurationChanged(newConfig: Configuration) { - when (newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK) { - Configuration.UI_MODE_NIGHT_YES -> { - uiModeEvents?.let { it.success("NIGHT") } - } - Configuration.UI_MODE_NIGHT_NO -> { - uiModeEvents?.let { it.success("NORMAL") } - } - } - super.onConfigurationChanged(newConfig) - } - - private fun uiMode(): String { - return when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) { - Configuration.UI_MODE_NIGHT_YES -> "NIGHT" - else -> "NORMAL" - } - } - // 安卓11以上使用了 MANAGE_EXTERNAL_STORAGE 权限来管理整个外置存储 (危险权限) // private var tmpComicId: String? = null diff --git a/go/mobile/bind-ios.sh b/go/mobile/bind-ios.sh index 3442a6e..6d1711e 100644 --- a/go/mobile/bind-ios.sh +++ b/go/mobile/bind-ios.sh @@ -1 +1 @@ -gomobile bind -target=ios -o lib/Pikapi.framework ./ +gomobile bind -target=ios -o lib/Pikapi.xcframework ./ diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 36c179e..111ed7c 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ @@ -14,7 +14,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - DDEFBAAB26AAE3AA00159A13 /* Pikapi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDEFBAAA26AAE3AA00159A13 /* Pikapi.framework */; }; + DDE03DA827193C22000ABF7B /* Pikapi.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDE03DA727193C22000ABF7B /* Pikapi.xcframework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -48,7 +48,7 @@ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CA7EB5DA1FDE22BAC5B01D77 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - DDEFBAAA26AAE3AA00159A13 /* Pikapi.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pikapi.framework; path = ../go/mobile/lib/Pikapi.framework; sourceTree = ""; }; + DDE03DA727193C22000ABF7B /* Pikapi.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Pikapi.xcframework; path = ../go/mobile/lib/Pikapi.xcframework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -56,7 +56,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DDEFBAAB26AAE3AA00159A13 /* Pikapi.framework in Frameworks */, + DDE03DA827193C22000ABF7B /* Pikapi.xcframework in Frameworks */, 0E44DEFD92B805627806403C /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -88,7 +88,7 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( - DDEFBAAA26AAE3AA00159A13 /* Pikapi.framework */, + DDE03DA727193C22000ABF7B /* Pikapi.xcframework */, 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, diff --git a/lib/basic/config/Themes.dart b/lib/basic/config/Themes.dart index 2dbe5f5..7159f5c 100644 --- a/lib/basic/config/Themes.dart +++ b/lib/basic/config/Themes.dart @@ -5,16 +5,60 @@ import 'dart:io'; import 'package:event/event.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:pikapi/basic/Common.dart'; import '../Method.dart'; import 'Platform.dart'; +const _fontFamilyProperty = "fontFamily"; + +String? _fontFamily; + +Future initFont() async { + var defaultFont = ""; + _fontFamily = await method.loadProperty(_fontFamilyProperty, defaultFont); +} + +ThemeData _fontThemeData(bool dark) { + return ThemeData( + brightness: dark ? Brightness.dark : Brightness.light, + fontFamily: _fontFamily, + ); +} + +Future inputFont(BuildContext context) async { + var font = await displayTextInputDialog( + context, "字体", "请输入字体", "$_fontFamily", + "请输入字体的名称, 例如宋体/黑体, 如果您保存后没有发生变化, 说明字体无法使用或名称错误, 可以去参考C:\\Windows\\Fonts寻找您的字体。", + ); + if (font != null) { + await method.saveProperty(_fontFamilyProperty, font); + _fontFamily = font; + _changeThemeByCode(_themeCode); + } +} + +Widget fontSetting() { + return StatefulBuilder( + builder: (BuildContext context, void Function(void Function()) setState) { + return ListTile( + title: Text("字体"), + subtitle: Text("$_fontFamily"), + onTap: () async { + await inputFont(context); + setState(() {}); + }, + ); + }, + ); +} + // 主题包 abstract class _ThemePackage { String code(); String name(); - ThemeData themeData(); + ThemeData themeData(ThemeData rawData); } class _OriginTheme extends _ThemePackage { @@ -25,7 +69,7 @@ class _OriginTheme extends _ThemePackage { String name() => "原生"; @override - ThemeData themeData() => ThemeData(); + ThemeData themeData(ThemeData rawData) => rawData; } class _PinkTheme extends _ThemePackage { @@ -36,8 +80,8 @@ class _PinkTheme extends _ThemePackage { String name() => "粉色"; @override - ThemeData themeData() => - ThemeData().copyWith( + ThemeData themeData(ThemeData rawData) => + rawData.copyWith( brightness: Brightness.light, colorScheme: ColorScheme.light( secondary: Colors.pink.shade200, @@ -65,8 +109,8 @@ class _BlackTheme extends _ThemePackage { String name() => "酷黑"; @override - ThemeData themeData() => - ThemeData().copyWith( + ThemeData themeData(ThemeData rawData) => + rawData.copyWith( brightness: Brightness.light, colorScheme: ColorScheme.light( secondary: Colors.pink.shade200, @@ -95,8 +139,9 @@ class _DarkTheme extends _ThemePackage { String name() => "暗黑"; @override - ThemeData themeData() => - ThemeData.dark().copyWith( + ThemeData themeData(ThemeData rawData) => + rawData.copyWith( + brightness: Brightness.dark, colorScheme: ColorScheme.light( secondary: Colors.pink.shade200, ), @@ -127,8 +172,8 @@ var themeEvent = Event(); String? _themeCode; ThemeData? _themeData; +ThemeData? _currentDarkTheme; bool _androidNightMode = false; -bool _systemNight = false; String currentThemeName() { for (var package in _themePackages) { @@ -140,20 +185,31 @@ String currentThemeName() { } ThemeData? currentThemeData() { - return (_androidNightMode && _systemNight) - ? _themePackages[3].themeData() - : _themeData; + return _themeData; +} + +ThemeData? currentDarkTheme() { + return _currentDarkTheme; } // 根据Code选择主题, 并发送主题更换事件 -void _changeThemeByCode(String themeCode) { +void _changeThemeByCode(String? themeCode) { + _ThemePackage? _themePackage; for (var package in _themePackages) { if (themeCode == package.code()) { _themeCode = themeCode; - _themeData = package.themeData(); + _themePackage = package; break; } } + if (_themePackage != null) { + _themeData = _themePackage.themeData( + _fontThemeData(_themePackage == _themePackages[3]), + ); + } + _currentDarkTheme = _androidNightMode + ? _themePackages[3].themeData(_fontThemeData(true)) + : _themeData; themeEvent.broadcast(); } @@ -161,16 +217,8 @@ void _changeThemeByCode(String themeCode) { const _nightModePropertyName = "androidNightMode"; Future initTheme() async { - if (androidVersion >= 29) { - _androidNightMode = - (await method.loadProperty(_nightModePropertyName, "false")) == - "true"; - _systemNight = (await method.androidGetUiMode()) == "NIGHT"; - EventChannel("ui_mode").receiveBroadcastStream().listen((event) { - _systemNight = "$event" == "NIGHT"; - themeEvent.broadcast(); - }); - } + _androidNightMode = + await method.loadProperty(_nightModePropertyName, "true") == "true"; _changeThemeByCode(await method.loadTheme()); } @@ -189,8 +237,7 @@ Future chooseTheme(BuildContext buildContext) async { _nightModePropertyName, "$v"); _androidNightMode = v; } - setState(() {}); - themeEvent.broadcast(); + _changeThemeByCode(_themeCode); }; list.add( SimpleDialogOption( diff --git a/lib/main.dart b/lib/main.dart index b1644fb..2d2e0c0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,6 +37,7 @@ class _PikapiAppState extends State { Widget build(BuildContext context) { return MaterialApp( theme: currentThemeData(), + darkTheme: currentDarkTheme(), navigatorObservers: [navigatorObserver, routeObserver], home: InitScreen(), ); diff --git a/lib/screens/InitScreen.dart b/lib/screens/InitScreen.dart index 282840c..fc54d5a 100644 --- a/lib/screens/InitScreen.dart +++ b/lib/screens/InitScreen.dart @@ -43,6 +43,7 @@ class _InitScreenState extends State { await initAddress(); await initProxy(); await initQuality(); + await initFont(); await initTheme(); await initListLayout(); await initReaderType(); diff --git a/lib/screens/SettingsScreen.dart b/lib/screens/SettingsScreen.dart index 16dbf4d..15c3316 100644 --- a/lib/screens/SettingsScreen.dart +++ b/lib/screens/SettingsScreen.dart @@ -14,6 +14,7 @@ import 'package:pikapi/basic/config/ReaderDirection.dart'; import 'package:pikapi/basic/config/ReaderType.dart'; import 'package:pikapi/basic/config/Quality.dart'; import 'package:pikapi/basic/config/ShadowCategories.dart'; +import 'package:pikapi/basic/config/Themes.dart'; import 'package:pikapi/basic/config/VolumeController.dart'; import 'package:pikapi/screens/components/NetworkSetting.dart'; @@ -137,6 +138,7 @@ class _SettingsScreenState extends State { setState(() {}); }, ), + fontSetting(), Divider(), ], ),