From bc88696004cca15a5d56e782ba96b65577c43e4c Mon Sep 17 00:00:00 2001 From: gedoor Date: Tue, 8 Sep 2020 11:53:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BB=E9=A2=98=E5=AF=BC=E5=85=A5=E5=AF=BC?= =?UTF-8?q?=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/themeConfig.json | 46 +++------ app/src/main/assets/updateLog.md | 4 + .../java/io/legado/app/help/ReadBookConfig.kt | 7 +- .../java/io/legado/app/help/ThemeConfig.kt | 93 +++++++++++++++++- .../java/io/legado/app/help/storage/Backup.kt | 4 +- .../io/legado/app/help/storage/Restore.kt | 19 +++- .../app/ui/config/ThemeConfigFragment.kt | 41 ++++++-- .../legado/app/ui/config/ThemeListDialog.kt | 98 +++++++++++++++++++ app/src/main/res/layout/item_theme_config.xml | 42 ++++++++ 9 files changed, 298 insertions(+), 56 deletions(-) create mode 100644 app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt create mode 100644 app/src/main/res/layout/item_theme_config.xml diff --git a/app/src/main/assets/themeConfig.json b/app/src/main/assets/themeConfig.json index 712cff4fb..d785fd22e 100644 --- a/app/src/main/assets/themeConfig.json +++ b/app/src/main/assets/themeConfig.json @@ -1,6 +1,6 @@ [ { - "configName": "典雅蓝", + "themeName": "典雅蓝", "isNightTheme": false, "primaryColor": "#03A9F4", "accentColor": "#AD1457", @@ -8,43 +8,19 @@ "bottomBackground": "#EEEEEE" }, { - "configName": "极简", + "themeName": "黑白", "isNightTheme": false, - "primaryColor": "#03A9F4", - "accentColor": "#AD1457", - "backgroundColor": "#F5F5F5", - "bottomBackground": "#EEEEEE" + "primaryColor": "#303030", + "accentColor": "#E0E0E0", + "backgroundColor": "#424242", + "bottomBackground": "#424242" }, { - "configName": "黑白", + "themeName": "A屏黑", "isNightTheme": false, - "primaryColor": "#03A9F4", - "accentColor": "#AD1457", - "backgroundColor": "#F5F5F5", - "bottomBackground": "#EEEEEE" - }, - { - "configName": "曜夜", - "isNightTheme": false, - "primaryColor": "#03A9F4", - "accentColor": "#AD1457", - "backgroundColor": "#F5F5F5", - "bottomBackground": "#EEEEEE" - }, - { - "configName": "黑白", - "isNightTheme": false, - "primaryColor": "#03A9F4", - "accentColor": "#AD1457", - "backgroundColor": "#F5F5F5", - "bottomBackground": "#EEEEEE" - }, - { - "configName": "A屏黑", - "isNightTheme": false, - "primaryColor": "#03A9F4", - "accentColor": "#AD1457", - "backgroundColor": "#F5F5F5", - "bottomBackground": "#EEEEEE" + "primaryColor": "#000000", + "accentColor": "#FFFFFF", + "backgroundColor": "#000000", + "bottomBackground": "#000000" } ] \ No newline at end of file diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index fedb7ce3a..a279010b1 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -3,6 +3,10 @@ * 关注合作公众号 **[小说拾遗]()** 获取好看的小说。 - 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 +**2020/09/08** +* 页眉页脚跟随背景 +* 主题导入导出 + **2020/09/07** * 订阅源和替换规则添加滑动选择 * 修复排版配置导入导出 diff --git a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt index fa6b30aae..9d249fe2a 100644 --- a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt +++ b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt @@ -20,11 +20,11 @@ import java.io.File */ @Keep object ReadBookConfig { - const val readConfigFileName = "readConfig.json" - private val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, readConfigFileName) + const val configFileName = "readConfig.json" + val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, configFileName) val configList: ArrayList = arrayListOf() private val defaultConfigs by lazy { - val json = String(App.INSTANCE.assets.open(readConfigFileName).readBytes()) + val json = String(App.INSTANCE.assets.open(configFileName).readBytes()) GSON.fromJsonArray(json)!! } var durConfig @@ -95,6 +95,7 @@ object ReadBookConfig { Coroutine.async { synchronized(this) { val json = GSON.toJson(configList) + FileUtils.deleteFile(configFilePath) FileUtils.createFileIfNotExist(configFilePath).writeText(json) } } diff --git a/app/src/main/java/io/legado/app/help/ThemeConfig.kt b/app/src/main/java/io/legado/app/help/ThemeConfig.kt index cb41e41d6..6a2402485 100644 --- a/app/src/main/java/io/legado/app/help/ThemeConfig.kt +++ b/app/src/main/java/io/legado/app/help/ThemeConfig.kt @@ -6,17 +6,62 @@ import io.legado.app.App import io.legado.app.R import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.help.coroutine.Coroutine import io.legado.app.utils.* +import java.io.File object ThemeConfig { - val configFileName = "themeConfigs.json" - private val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, configFileName) - val configList = arrayListOf() + const val configFileName = "themeConfig.json" + val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, configFileName) private val defaultConfigs by lazy { val json = String(App.INSTANCE.assets.open(configFileName).readBytes()) GSON.fromJsonArray(json)!! } + val configList = arrayListOf() + + init { + upConfig() + } + + fun upConfig() { + (getConfigs() ?: defaultConfigs).let { + configList.clear() + configList.addAll(it) + } + } + fun save() { + Coroutine.async { + synchronized(this) { + val json = GSON.toJson(configList) + FileUtils.deleteFile(configFilePath) + FileUtils.createFileIfNotExist(configFilePath).writeText(json) + } + } + } + + fun addConfig(newConfig: Config) { + configList.forEachIndexed { index, config -> + if (newConfig.themeName == config.themeName) { + configList[index] = newConfig + return + } + } + configList.add(newConfig) + } + + private fun getConfigs(): List? { + val configFile = File(configFilePath) + if (configFile.exists()) { + try { + val json = configFile.readText() + return GSON.fromJsonArray(json) + } catch (e: Exception) { + e.printStackTrace() + } + } + return null + } fun applyConfig(context: Context, config: Config) { val primary = Color.parseColor(config.primaryColor) @@ -42,8 +87,48 @@ object ThemeConfig { postEvent(EventBus.RECREATE, "") } + fun saveDayTheme(context: Context, name: String) { + val primary = + context.getPrefInt(PreferKey.cPrimary, context.getCompatColor(R.color.md_brown_500)) + val accent = + context.getPrefInt(PreferKey.cAccent, context.getCompatColor(R.color.md_red_600)) + val background = + context.getPrefInt(PreferKey.cBackground, context.getCompatColor(R.color.md_grey_100)) + val bBackground = + context.getPrefInt(PreferKey.cBBackground, context.getCompatColor(R.color.md_grey_200)) + val config = Config( + themeName = name, + isNightTheme = false, + primaryColor = "#${primary.hexString}", + accentColor = "#${accent.hexString}", + backgroundColor = "#${background.hexString}", + bottomBackground = "#${bBackground.hexString}" + ) + addConfig(config) + } + + fun saveNightTheme(context: Context, name: String) { + val primary = + context.getPrefInt(PreferKey.cNPrimary, context.getCompatColor(R.color.md_blue_grey_600)) + val accent = + context.getPrefInt(PreferKey.cNAccent, context.getCompatColor(R.color.md_deep_orange_800)) + val background = + context.getPrefInt(PreferKey.cNBackground, context.getCompatColor(R.color.md_grey_900)) + val bBackground = + context.getPrefInt(PreferKey.cNBBackground, context.getCompatColor(R.color.md_grey_850)) + val config = Config( + themeName = name, + isNightTheme = true, + primaryColor = "#${primary.hexString}", + accentColor = "#${accent.hexString}", + backgroundColor = "#${background.hexString}", + bottomBackground = "#${bBackground.hexString}" + ) + addConfig(config) + } + class Config( - var configName: String = "典雅蓝", + var themeName: String = "典雅蓝", var isNightTheme: Boolean = false, var primaryColor: String = "#03A9F4", var accentColor: String = "#AD1457", diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt index 1c6b8dcd6..7efc5a723 100644 --- a/app/src/main/java/io/legado/app/help/storage/Backup.kt +++ b/app/src/main/java/io/legado/app/help/storage/Backup.kt @@ -33,7 +33,7 @@ object Backup { "txtTocRule.json", "readRecord.json", "httpTTS.json", - ReadBookConfig.readConfigFileName, + ReadBookConfig.configFileName, "config.xml" ) } @@ -62,7 +62,7 @@ object Backup { writeListToJson(App.db.readRecordDao().all, "readRecord.json", backupPath) writeListToJson(App.db.httpTTSDao().all, "httpTTS.json", backupPath) GSON.toJson(ReadBookConfig.configList)?.let { - FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.readConfigFileName) + FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.configFileName) .writeText(it) } Preferences.getSharedPreferences(App.INSTANCE, backupPath, "config")?.let { sp -> diff --git a/app/src/main/java/io/legado/app/help/storage/Restore.kt b/app/src/main/java/io/legado/app/help/storage/Restore.kt index 5deeac5dd..8f89a45fe 100644 --- a/app/src/main/java/io/legado/app/help/storage/Restore.kt +++ b/app/src/main/java/io/legado/app/help/storage/Restore.kt @@ -16,6 +16,7 @@ import io.legado.app.data.entities.* import io.legado.app.help.AppConfig import io.legado.app.help.LauncherIconHelp import io.legado.app.help.ReadBookConfig +import io.legado.app.help.ThemeConfig import io.legado.app.service.help.ReadBook import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.utils.* @@ -158,14 +159,24 @@ object Restore { suspend fun restoreConfig(path: String = Backup.backupPath) { withContext(IO) { + try { + val file = + FileUtils.createFileIfNotExist(path + File.separator + ThemeConfig.configFileName) + if (file.exists()) { + FileUtils.deleteFile(ThemeConfig.configFilePath) + file.copyTo(File(ThemeConfig.configFilePath)) + ThemeConfig.upConfig() + } + } catch (e: Exception) { + e.printStackTrace() + } if (!ignoreReadConfig) { try { val file = - FileUtils.createFileIfNotExist(path + File.separator + ReadBookConfig.readConfigFileName) - val configFile = - FileUtils.getFile(App.INSTANCE.filesDir, ReadBookConfig.readConfigFileName) + FileUtils.createFileIfNotExist(path + File.separator + ReadBookConfig.configFileName) if (file.exists()) { - file.copyTo(configFile, true) + FileUtils.deleteFile(ReadBookConfig.configFilePath) + file.copyTo(File(ReadBookConfig.configFilePath)) ReadBookConfig.upConfig() } } catch (e: Exception) { diff --git a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt index e43a3019f..4b76ebc3e 100644 --- a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt +++ b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt @@ -16,11 +16,18 @@ import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey import io.legado.app.help.AppConfig import io.legado.app.help.LauncherIconHelp +import io.legado.app.help.ThemeConfig +import io.legado.app.lib.dialogs.alert +import io.legado.app.lib.dialogs.customView +import io.legado.app.lib.dialogs.noButton +import io.legado.app.lib.dialogs.okButton import io.legado.app.lib.theme.ATH import io.legado.app.ui.widget.number.NumberPickerDialog import io.legado.app.ui.widget.prefs.ColorPreference import io.legado.app.ui.widget.prefs.IconListPreference +import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.utils.* +import kotlinx.android.synthetic.main.dialog_edit_text.view.* @Suppress("SameParameterValue") @@ -147,7 +154,7 @@ class ThemeConfigFragment : BasePreferenceFragment(), @SuppressLint("PrivateResource") override fun onPreferenceTreeClick(preference: Preference?): Boolean { - when (preference?.key) { + when (val key = preference?.key) { PreferKey.barElevation -> NumberPickerDialog(requireContext()) .setTitle(getString(R.string.bar_elevation)) .setMaxValue(32) @@ -162,17 +169,35 @@ class ThemeConfigFragment : BasePreferenceFragment(), AppConfig.elevation = it recreateActivities() } - "themeList" -> themeListAlert() - "saveDayTheme" -> { - } - "saveNightTheme" -> { - } + "themeList" -> ThemeListDialog().show(childFragmentManager, "themeList") + "saveDayTheme", "saveNightTheme" -> saveThemeAlert(key) } return super.onPreferenceTreeClick(preference) } - private fun themeListAlert() { - + @SuppressLint("InflateParams") + private fun saveThemeAlert(key: String) { + alert("主题名称") { + var editText: AutoCompleteTextView? = null + customView { + layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { + editText = edit_view + } + } + okButton { + editText?.text?.toString()?.let { themeName -> + when (key) { + "saveDayTheme" -> { + ThemeConfig.saveDayTheme(requireContext(), themeName) + } + "saveNightTheme" -> { + ThemeConfig.saveNightTheme(requireContext(), themeName) + } + } + } + } + noButton { } + }.show().applyTint() } private fun upTheme(isNightTheme: Boolean) { diff --git a/app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt b/app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt new file mode 100644 index 000000000..16d6d68b9 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt @@ -0,0 +1,98 @@ +package io.legado.app.ui.config + +import android.os.Bundle +import android.util.DisplayMetrics +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import io.legado.app.R +import io.legado.app.base.BaseDialogFragment +import io.legado.app.base.adapter.ItemViewHolder +import io.legado.app.base.adapter.SimpleRecyclerAdapter +import io.legado.app.help.ThemeConfig +import io.legado.app.lib.dialogs.alert +import io.legado.app.lib.dialogs.noButton +import io.legado.app.lib.dialogs.okButton +import io.legado.app.lib.theme.primaryColor +import io.legado.app.ui.widget.recycler.VerticalDivider +import io.legado.app.utils.GSON +import io.legado.app.utils.applyTint +import kotlinx.android.synthetic.main.dialog_recycler_view.* +import kotlinx.android.synthetic.main.item_theme_config.view.* +import org.jetbrains.anko.sdk27.listeners.onClick +import org.jetbrains.anko.share + +class ThemeListDialog : BaseDialogFragment() { + + private lateinit var adapter: Adapter + + override fun onStart() { + super.onStart() + val dm = DisplayMetrics() + activity?.windowManager?.defaultDisplay?.getMetrics(dm) + dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.dialog_recycler_view, container) + } + + override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { + tool_bar.setBackgroundColor(primaryColor) + tool_bar.setTitle(R.string.theme_list) + initView() + initData() + } + + private fun initView() { + adapter = Adapter() + recycler_view.layoutManager = LinearLayoutManager(requireContext()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) + recycler_view.adapter = adapter + } + + fun initData() { + adapter.setItems(ThemeConfig.configList) + } + + fun delete(index: Int) { + alert(R.string.delete, R.string.sure_del) { + okButton { + ThemeConfig.configList.removeAt(index) + initData() + } + noButton() + }.show().applyTint() + } + + fun share(index: Int) { + val json = GSON.toJson(ThemeConfig.configList[index]) + requireContext().share(json, "主题分享") + } + + inner class Adapter : SimpleRecyclerAdapter(requireContext(), R.layout.item_theme_config) { + + override fun convert(holder: ItemViewHolder, item: ThemeConfig.Config, payloads: MutableList) { + holder.itemView.apply { + tv_name.text = item.themeName + } + } + + override fun registerListener(holder: ItemViewHolder) { + holder.itemView.apply { + iv_share.onClick { + share(holder.layoutPosition) + } + iv_delete.onClick { + delete(holder.layoutPosition) + } + } + } + + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/item_theme_config.xml b/app/src/main/res/layout/item_theme_config.xml new file mode 100644 index 000000000..008f70d15 --- /dev/null +++ b/app/src/main/res/layout/item_theme_config.xml @@ -0,0 +1,42 @@ + + + + + + + + + + \ No newline at end of file