From 50abb9b55299bc58b75a5c09b1391e4a94223c91 Mon Sep 17 00:00:00 2001
From: HapeLee <1321903405@qq.com>
Date: Wed, 27 Aug 2025 03:03:18 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=95=8C=E9=9D=A2=20?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A6=96=E6=AC=A1=E8=BF=9B=E5=85=A5=E5=BC=95?=
=?UTF-8?q?=E5=AF=BC=E7=95=8C=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/src/main/AndroidManifest.xml | 4 +-
app/src/main/assets/disclaimer.md | 2 -
.../io/legato/kazusa/constant/PreferKey.kt | 2 +-
.../io/legato/kazusa/help/config/AppConfig.kt | 6 +
.../kazusa/lib/prefs/ThemeCardPreference.kt | 2 +-
.../kazusa/lib/prefs/ThemeModePreference.kt | 27 ++-
.../ui/book/read/config/BgTextConfigDialog.kt | 26 +--
.../ui/book/read/config/ReadStyleDialog.kt | 6 +-
.../kazusa/ui/config/ThemeConfigFragment.kt | 9 +-
.../io/legato/kazusa/ui/main/MainActivity.kt | 56 +----
.../kazusa/ui/welcome/PrivacyFragment.kt | 23 ++
.../legato/kazusa/ui/welcome/ThemeFragment.kt | 27 +++
.../kazusa/ui/welcome/WebDavFragment.kt | 204 ++++++++++++++++++
.../kazusa/ui/welcome/WelcomeActivity.kt | 141 ++++++------
.../res/color/chip_background_selector.xml | 5 +
.../main/res/color/chip_stroke_selector.xml | 5 +
.../main/res/layout/activity_book_search.xml | 2 +
app/src/main/res/layout/activity_welcome.xml | 114 +++++-----
.../main/res/layout/dialog_read_bg_text.xml | 114 +++++-----
.../res/layout/dialog_read_book_style.xml | 18 +-
app/src/main/res/layout/fragment_privacy.xml | 45 ++++
.../main/res/layout/fragment_webdav_auth.xml | 97 +++++++++
app/src/main/res/layout/item_bg_image.xml | 1 +
app/src/main/res/layout/item_download.xml | 2 +
app/src/main/res/layout/item_read_style.xml | 3 +
app/src/main/res/layout/view_pref.xml | 1 +
app/src/main/res/layout/view_theme_mode.xml | 10 +-
app/src/main/res/values-night/themes.xml | 1 +
app/src/main/res/values/dimens.xml | 2 +-
app/src/main/res/values/styles.xml | 5 +
app/src/main/res/values/themes.xml | 1 +
app/src/main/res/xml/pref_strat_theme.xml | 14 ++
gradle/libs.versions.toml | 16 +-
33 files changed, 684 insertions(+), 307 deletions(-)
create mode 100644 app/src/main/java/io/legato/kazusa/ui/welcome/PrivacyFragment.kt
create mode 100644 app/src/main/java/io/legato/kazusa/ui/welcome/ThemeFragment.kt
create mode 100644 app/src/main/java/io/legato/kazusa/ui/welcome/WebDavFragment.kt
create mode 100644 app/src/main/res/color/chip_background_selector.xml
create mode 100644 app/src/main/res/color/chip_stroke_selector.xml
create mode 100644 app/src/main/res/layout/fragment_privacy.xml
create mode 100644 app/src/main/res/layout/fragment_webdav_auth.xml
create mode 100644 app/src/main/res/xml/pref_strat_theme.xml
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 16643b883..0071c1b67 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -133,10 +133,12 @@
+
diff --git a/app/src/main/assets/disclaimer.md b/app/src/main/assets/disclaimer.md
index 5511655f5..f6870b2c3 100644
--- a/app/src/main/assets/disclaimer.md
+++ b/app/src/main/assets/disclaimer.md
@@ -1,5 +1,3 @@
-# 免责声明(Disclaimer)
-
* 阅读是一款解析指定规则并获取内容的工具,为广大网络文学爱好者提供一种方便、快捷舒适的试读体验。
* 当您搜索一本书的时,阅读会您所使用的规则将该书的书名以关键词的形式提交到各个第三方网络文学网站。
各第三方网站返回的内容与阅读无关,阅读对其概不负责,亦不承担任何法律责任。
diff --git a/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt b/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt
index 52fbbf037..df20ed725 100644
--- a/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt
+++ b/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt
@@ -204,7 +204,7 @@ object PreferKey {
const val mangaClickActionBL = "mangaClickActionBottomLeft"
const val mangaClickActionBC = "mangaClickActionBottomCenter"
const val mangaClickActionBR = "mangaClickActionBottomRight"
-
+ const val isFirstLaunch = "isFirstLaunch"
const val permissionChecked = "permissionChecked"
const val notificationsPost = "notificationsPost"
const val ignoreBatteryPermission = "ignoreBatteryPermission"
diff --git a/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt b/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt
index e9baa00f5..dcd67400c 100644
--- a/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt
+++ b/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt
@@ -149,6 +149,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
}
}
+ var isFirstLaunch: Boolean
+ get() = appCtx.getPrefBoolean(PreferKey.isFirstLaunch, true)
+ set(value) {
+ appCtx.putPrefBoolean(PreferKey.isFirstLaunch, value)
+ }
+
var showUnread: Boolean
get() = appCtx.getPrefBoolean(PreferKey.showUnread, true)
set(value) {
diff --git a/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeCardPreference.kt b/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeCardPreference.kt
index 8cdd4798c..849cf6527 100644
--- a/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeCardPreference.kt
+++ b/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeCardPreference.kt
@@ -24,7 +24,7 @@ class ThemeCardPreference(context: Context, attrs: AttributeSet) : Preference(co
private var entries: Array = context.resources.getTextArray(R.array.themes_item)
private var entryValues: Array = context.resources.getTextArray(R.array.themes_value).takeIf { it.isNotEmpty() }
?: arrayOf("0")
- private var currentValue: String? = null
+ private var currentValue = "0"
init {
layoutResource = R.layout.preference_theme_card
diff --git a/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeModePreference.kt b/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeModePreference.kt
index 680cd5c81..96892f295 100644
--- a/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeModePreference.kt
+++ b/app/src/main/java/io/legato/kazusa/lib/prefs/ThemeModePreference.kt
@@ -2,9 +2,6 @@ package io.legato.kazusa.lib.prefs
import android.content.Context
import android.util.AttributeSet
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
import androidx.preference.PreferenceViewHolder
import com.google.android.material.button.MaterialButtonToggleGroup
import io.legato.kazusa.R
@@ -13,7 +10,7 @@ import io.legato.kazusa.help.config.ThemeConfig
class ThemeModePreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
- private var currentValue: String? = null
+ private var currentValue: String = "0"
init {
layoutResource = R.layout.view_pref
@@ -23,17 +20,21 @@ class ThemeModePreference(context: Context, attrs: AttributeSet) : Preference(co
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
- val toggleGroup = holder.itemView.findViewById(R.id.theme_toggle_group)
- if (toggleGroup == null) {
- val rootView = holder.itemView as ViewGroup
- val inflater = LayoutInflater.from(context)
- val themeToggleView = inflater.inflate(R.layout.view_theme_mode, rootView, false)
- rootView.addView(themeToggleView)
+ val toggleGroup =
+ holder.itemView.findViewById(R.id.theme_toggle_group)
+ ?: return
- setupToggleGroup(themeToggleView.findViewById(R.id.theme_toggle_group))
+ // 根据 currentValue 设置选中
+ when (currentValue) {
+ "0" -> toggleGroup.check(R.id.btn_system)
+ "1" -> toggleGroup.check(R.id.btn_light)
+ "2" -> toggleGroup.check(R.id.btn_dark)
}
+
+ setupToggleGroup(toggleGroup)
}
+
private fun setupToggleGroup(toggleGroup: MaterialButtonToggleGroup) {
when (currentValue) {
@@ -65,8 +66,4 @@ class ThemeModePreference(context: Context, attrs: AttributeSet) : Preference(co
currentValue = getPersistedString(defaultValue as? String ?: "0")
}
- override fun shouldDisableDependents(): Boolean {
- return currentValue == null || super.shouldDisableDependents()
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legato/kazusa/ui/book/read/config/BgTextConfigDialog.kt b/app/src/main/java/io/legato/kazusa/ui/book/read/config/BgTextConfigDialog.kt
index 15d6bcab8..607b652a2 100644
--- a/app/src/main/java/io/legato/kazusa/ui/book/read/config/BgTextConfigDialog.kt
+++ b/app/src/main/java/io/legato/kazusa/ui/book/read/config/BgTextConfigDialog.kt
@@ -1,22 +1,21 @@
package io.legato.kazusa.ui.book.read.config
+//import io.legado.app.lib.theme.bottomBackground
+//import io.legado.app.lib.theme.getPrimaryTextColor
+//import io.legado.app.lib.theme.getSecondaryTextColor
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.PorterDuff
import android.net.Uri
import android.os.Bundle
-import android.view.Gravity
import android.view.View
-import android.view.ViewGroup
-import android.view.WindowManager
import androidx.appcompat.widget.TooltipCompat
import androidx.documentfile.provider.DocumentFile
import com.google.android.material.slider.Slider
import com.jaredrummler.android.colorpicker.ColorPickerDialog
import io.legato.kazusa.R
import io.legato.kazusa.base.BaseBottomSheetDialogFragment
-import io.legato.kazusa.base.BaseDialogFragment
import io.legato.kazusa.constant.AppLog
import io.legato.kazusa.constant.EventBus
import io.legato.kazusa.databinding.DialogEditTextBinding
@@ -29,9 +28,6 @@ import io.legato.kazusa.help.http.okHttpClient
import io.legato.kazusa.lib.dialogs.SelectItem
import io.legato.kazusa.lib.dialogs.alert
import io.legato.kazusa.lib.dialogs.selector
-//import io.legado.app.lib.theme.bottomBackground
-//import io.legado.app.lib.theme.getPrimaryTextColor
-//import io.legado.app.lib.theme.getSecondaryTextColor
import io.legato.kazusa.ui.book.read.ReadBookActivity
import io.legato.kazusa.ui.file.HandleFileContract
import io.legato.kazusa.utils.FileUtils
@@ -116,22 +112,6 @@ class BgTextConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_bg
}
private fun initView() = binding.run {
-// val bg = requireContext().bottomBackground
-// val isLight = ColorUtils.isColorLight(bg)
-// primaryTextColor = requireContext().getPrimaryTextColor(isLight)
-// secondaryTextColor = requireContext().getSecondaryTextColor(isLight)
-// rootView.setBackgroundColor(bg)
-// tvNameTitle.setTextColor(primaryTextColor)
-// tvName.setTextColor(secondaryTextColor)
-// ivEdit.setColorFilter(secondaryTextColor, PorterDuff.Mode.SRC_IN)
-// tvRestore.setTextColor(primaryTextColor)
-// swDarkStatusIcon.setTextColor(primaryTextColor)
-// swUnderline.setTextColor(primaryTextColor)
-// ivImport.setColorFilter(primaryTextColor, PorterDuff.Mode.SRC_IN)
-// ivExport.setColorFilter(primaryTextColor, PorterDuff.Mode.SRC_IN)
-// ivDelete.setColorFilter(primaryTextColor, PorterDuff.Mode.SRC_IN)
-// tvBgAlpha.setTextColor(primaryTextColor)
-// tvBgImage.setTextColor(primaryTextColor)
recyclerView.adapter = adapter
adapter.addHeaderView {
ItemBgImageBinding.inflate(layoutInflater, it, false).apply {
diff --git a/app/src/main/java/io/legato/kazusa/ui/book/read/config/ReadStyleDialog.kt b/app/src/main/java/io/legato/kazusa/ui/book/read/config/ReadStyleDialog.kt
index e5f563cb7..d5642ec77 100644
--- a/app/src/main/java/io/legato/kazusa/ui/book/read/config/ReadStyleDialog.kt
+++ b/app/src/main/java/io/legato/kazusa/ui/book/read/config/ReadStyleDialog.kt
@@ -230,14 +230,14 @@ class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_
llStyle.gravity = Gravity.TOP
cdStyle.cardElevation = 1f.dpToPx()
cdStyle.radius = 16f.dpToPx()
- cdStyle.strokeWidth = 2
- cdStyle.strokeColor = item.curTextColor()
+ cdStyle.strokeWidth = 1.dpToPx()
+ //cdStyle.strokeColor = item.curTextColor()
//tvStyle.setTextBold(true)
} else {
cdStyle.cardElevation = 2f.dpToPx()
cdStyle.radius = 32f.dpToPx()
cdStyle.strokeWidth = 0
- cdStyle.strokeColor = item.curTextColor()
+ //cdStyle.strokeColor = item.curTextColor()
//tvStyle.setTextBold(false)
}
}
diff --git a/app/src/main/java/io/legato/kazusa/ui/config/ThemeConfigFragment.kt b/app/src/main/java/io/legato/kazusa/ui/config/ThemeConfigFragment.kt
index 1c9d34614..2e032b238 100644
--- a/app/src/main/java/io/legato/kazusa/ui/config/ThemeConfigFragment.kt
+++ b/app/src/main/java/io/legato/kazusa/ui/config/ThemeConfigFragment.kt
@@ -1,14 +1,12 @@
package io.legato.kazusa.ui.config
+//import io.legado.app.lib.theme.primaryColor
import android.annotation.SuppressLint
-import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
-import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.SeekBar
-import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import io.legato.kazusa.R
@@ -23,10 +21,8 @@ import io.legato.kazusa.help.config.ThemeConfig
import io.legato.kazusa.lib.dialogs.alert
import io.legato.kazusa.lib.dialogs.selector
import io.legato.kazusa.lib.prefs.ColorPreference
-import io.legato.kazusa.lib.prefs.NameListPreference
import io.legato.kazusa.lib.prefs.ThemeCardPreference
import io.legato.kazusa.lib.prefs.ThemeModePreference
-//import io.legado.app.lib.theme.primaryColor
import io.legato.kazusa.ui.widget.number.NumberPickerDialog
import io.legato.kazusa.ui.widget.seekbar.SeekBarChangeListener
import io.legato.kazusa.utils.ColorUtils
@@ -72,9 +68,6 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_config_theme)
- if (Build.VERSION.SDK_INT < 26) {
- preferenceScreen.removePreferenceRecursively(PreferKey.launcherIcon)
- }
upPreferenceSummary(PreferKey.bgImage, getPrefString(PreferKey.bgImage))
upPreferenceSummary(PreferKey.bgImageN, getPrefString(PreferKey.bgImageN))
diff --git a/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt b/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt
index 7f53d4b3c..cde53ffb1 100644
--- a/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt
+++ b/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt
@@ -26,7 +26,6 @@ import io.legato.kazusa.constant.AppConst.appInfo
import io.legato.kazusa.constant.EventBus
import io.legato.kazusa.constant.PreferKey
import io.legato.kazusa.databinding.ActivityMainBinding
-import io.legato.kazusa.databinding.DialogEditTextBinding
import io.legato.kazusa.help.AppWebDav
import io.legato.kazusa.help.book.BookHelp
import io.legato.kazusa.help.config.AppConfig
@@ -43,6 +42,7 @@ import io.legato.kazusa.ui.main.bookshelf.books.BookshelfFragment3
import io.legato.kazusa.ui.main.explore.ExploreFragment
import io.legato.kazusa.ui.main.my.MyFragment
import io.legato.kazusa.ui.main.rss.RssFragment
+import io.legato.kazusa.ui.welcome.WelcomeActivity
import io.legato.kazusa.ui.widget.dialog.TextDialog
import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.hideSoftInput
@@ -51,6 +51,7 @@ import io.legato.kazusa.utils.observeEvent
import io.legato.kazusa.utils.setNavigationBarColorAuto
import io.legato.kazusa.utils.shouldHideSoftInput
import io.legato.kazusa.utils.showDialogFragment
+import io.legato.kazusa.utils.startActivity
import io.legato.kazusa.utils.themeColor
import io.legato.kazusa.utils.toastOnUi
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
@@ -100,6 +101,12 @@ class MainActivity : VMBaseActivity(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ if (AppConfig.isFirstLaunch) {
+ startActivity()
+ finish()
+ return
+ }
+
onBackPressedDispatcher.addCallback(this) {
if (pagePosition != 0) {
binding.viewPagerMain.currentItem = 0
@@ -145,12 +152,9 @@ class MainActivity : VMBaseActivity(),
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
lifecycleScope.launch {
- //隐私协议
- if (!privacyPolicy()) return@launch
//版本更新
upVersion()
//设置本地密码
- setLocalPassword()
notifyAppCrash()
//备份同步
backupSync()
@@ -217,27 +221,6 @@ class MainActivity : VMBaseActivity(),
window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurfaceContainer))
}
- /**
- * 用户隐私与协议
- */
- private suspend fun privacyPolicy(): Boolean = suspendCoroutine { block ->
- if (LocalConfig.privacyPolicyOk) {
- block.resume(true)
- return@suspendCoroutine
- }
- val privacyPolicy = String(assets.open("privacyPolicy.md").readBytes())
- alert(getString(R.string.privacy_policy), privacyPolicy) {
- positiveButton(R.string.agree) {
- LocalConfig.privacyPolicyOk = true
- block.resume(true)
- }
- negativeButton(R.string.refuse) {
- finish()
- block.resume(false)
- }
- }
- }
-
/**
* 版本更新日志
*/
@@ -269,29 +252,6 @@ class MainActivity : VMBaseActivity(),
/**
* 设置本地密码
*/
- private suspend fun setLocalPassword() = suspendCoroutine { block ->
- if (LocalConfig.password != null) {
- block.resume(null)
- return@suspendCoroutine
- }
- alert(R.string.set_local_password, R.string.set_local_password_summary) {
- val editTextBinding = DialogEditTextBinding.inflate(layoutInflater).apply {
- editView.hint = "password"
- }
- customView {
- editTextBinding.root
- }
- onDismiss {
- block.resume(null)
- }
- okButton {
- LocalConfig.password = editTextBinding.editView.text.toString()
- }
- cancelButton {
- LocalConfig.password = ""
- }
- }
- }
private fun notifyAppCrash() {
if (!LocalConfig.appCrash || BuildConfig.DEBUG) {
diff --git a/app/src/main/java/io/legato/kazusa/ui/welcome/PrivacyFragment.kt b/app/src/main/java/io/legato/kazusa/ui/welcome/PrivacyFragment.kt
new file mode 100644
index 000000000..1bcbd08e2
--- /dev/null
+++ b/app/src/main/java/io/legato/kazusa/ui/welcome/PrivacyFragment.kt
@@ -0,0 +1,23 @@
+package io.legato.kazusa.ui.welcome
+
+import android.os.Bundle
+import android.view.View
+import io.legato.kazusa.R
+import io.legato.kazusa.base.BaseFragment
+import io.legato.kazusa.databinding.FragmentPrivacyBinding
+import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
+
+class PrivacyFragment : BaseFragment(R.layout.fragment_privacy) {
+
+ private val binding by viewBinding(FragmentPrivacyBinding::bind)
+
+ override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
+
+ binding.tvPrivacy.text =
+ String(requireContext().assets.open("privacyPolicy.md").readBytes())
+ binding.tvDisclaimer.text =
+ String(requireContext().assets.open("disclaimer.md").readBytes())
+
+ }
+
+}
diff --git a/app/src/main/java/io/legato/kazusa/ui/welcome/ThemeFragment.kt b/app/src/main/java/io/legato/kazusa/ui/welcome/ThemeFragment.kt
new file mode 100644
index 000000000..432ce689d
--- /dev/null
+++ b/app/src/main/java/io/legato/kazusa/ui/welcome/ThemeFragment.kt
@@ -0,0 +1,27 @@
+package io.legato.kazusa.ui.welcome
+
+import android.os.Bundle
+import androidx.preference.PreferenceFragmentCompat
+import io.legato.kazusa.R
+import io.legato.kazusa.constant.PreferKey
+import io.legato.kazusa.lib.prefs.ThemeCardPreference
+import io.legato.kazusa.lib.prefs.ThemeModePreference
+
+class ThemeFragment : PreferenceFragmentCompat() {
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.pref_strat_theme, rootKey)
+
+ findPreference(PreferKey.themeMode)?.let {
+ it.setOnPreferenceChangeListener { _, _ ->
+ true
+ }
+ }
+
+ findPreference(PreferKey.themePref)?.let {
+ it.setOnPreferenceChangeListener { _, _ ->
+ true
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/io/legato/kazusa/ui/welcome/WebDavFragment.kt b/app/src/main/java/io/legato/kazusa/ui/welcome/WebDavFragment.kt
new file mode 100644
index 000000000..1d0b363d4
--- /dev/null
+++ b/app/src/main/java/io/legato/kazusa/ui/welcome/WebDavFragment.kt
@@ -0,0 +1,204 @@
+package io.legato.kazusa.ui.welcome
+
+import android.content.Context
+import android.os.Bundle
+import android.text.InputType
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import androidx.core.content.edit
+import androidx.core.widget.doAfterTextChanged
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.PreferenceManager
+import io.legato.kazusa.R
+import io.legato.kazusa.base.BaseFragment
+import io.legato.kazusa.constant.AppLog
+import io.legato.kazusa.constant.PreferKey
+import io.legato.kazusa.databinding.FragmentWebdavAuthBinding
+import io.legato.kazusa.exception.NoStackTraceException
+import io.legato.kazusa.help.AppWebDav
+import io.legato.kazusa.help.AppWebDav.testWebDav
+import io.legato.kazusa.help.config.LocalConfig
+import io.legato.kazusa.help.coroutine.Coroutine
+import io.legato.kazusa.help.storage.Restore
+import io.legato.kazusa.lib.dialogs.alert
+import io.legato.kazusa.lib.dialogs.selector
+import io.legato.kazusa.ui.file.HandleFileContract
+import io.legato.kazusa.ui.widget.dialog.WaitDialog
+import io.legato.kazusa.utils.toastOnUi
+import kotlinx.coroutines.Dispatchers.IO
+import kotlinx.coroutines.Dispatchers.Main
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.ensureActive
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import splitties.init.appCtx
+import kotlin.coroutines.coroutineContext
+
+class WebDavFragment : BaseFragment(R.layout.fragment_webdav_auth) {
+
+ private var _binding: FragmentWebdavAuthBinding? = null
+ private val binding get() = _binding!!
+ private var restoreJob: Job? = null
+ private val waitDialog by lazy { WaitDialog(requireContext()) }
+
+ private val restoreDoc = registerForActivityResult(HandleFileContract()) {
+ it.uri?.let { uri ->
+ waitDialog.setText("恢复中…")
+ waitDialog.show()
+ val task = Coroutine.async {
+ Restore.restore(appCtx, uri)
+ }.onFinally {
+ waitDialog.dismiss()
+ }
+ waitDialog.setOnCancelListener {
+ task.cancel()
+ }
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = FragmentWebdavAuthBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
+
+ val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
+
+ val urls = listOf(
+ "https://dav.jianguoyun.com/dav/",
+ "https://webdav.aliyundrive.com/",
+ "https://dav.example.com/"
+ )
+
+ val adapter = ArrayAdapter(
+ requireContext(),
+ android.R.layout.simple_dropdown_item_1line,
+ urls
+ )
+
+ binding.editUrl.setAdapter(adapter)
+
+ binding.editAccount.setText(prefs.getString(PreferKey.webDavAccount, ""))
+ binding.editPassword.setText(prefs.getString(PreferKey.webDavPassword, ""))
+ binding.editPassword.inputType =
+ InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
+
+ binding.etPassword.setText(LocalConfig.password ?: "")
+
+ binding.etPassword.doAfterTextChanged {
+ LocalConfig.password = it.toString()
+ }
+
+ binding.btnCheck.setOnClickListener {
+ saveWebDavConfig()
+
+ lifecycleScope.launch {
+ testWebDav()
+ }
+ }
+
+ binding.btnRestore.setOnClickListener {
+ restore()
+ }
+
+ }
+
+ fun saveWebDavConfig(onSaved: (() -> Unit)? = null) {
+ val url = binding.editUrl.text.toString()
+ val account = binding.editAccount.text.toString()
+ val password = binding.editPassword.text.toString()
+
+ PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
+ putString(PreferKey.webDavUrl, url)
+ putString(PreferKey.webDavAccount, account)
+ putString(PreferKey.webDavPassword, password)
+ }
+
+ onSaved?.invoke()
+ }
+
+ fun restore() {
+ waitDialog.setText(R.string.loading)
+ waitDialog.setOnCancelListener {
+ restoreJob?.cancel()
+ }
+ waitDialog.show()
+ Coroutine.async {
+ restoreJob = coroutineContext[Job]
+ showRestoreDialog(requireContext())
+ }.onError {
+ AppLog.put("恢复备份出错WebDavError\n${it.localizedMessage}", it)
+ if (context == null) {
+ return@onError
+ }
+ alert {
+ setTitle(R.string.restore)
+ setMessage("WebDavError\n${it.localizedMessage}\n将从本地备份恢复。")
+ okButton {
+ restoreFromLocal()
+ }
+ cancelButton()
+ }
+ }.onFinally {
+ waitDialog.dismiss()
+ }
+ }
+
+ private suspend fun showRestoreDialog(context: Context) {
+ val names = withContext(IO) { AppWebDav.getBackupNames() }
+ if (AppWebDav.isJianGuoYun && names.size > 700) {
+ context.toastOnUi("由于坚果云限制列出文件数量,部分备份可能未显示,请及时清理旧备份")
+ }
+ if (names.isNotEmpty()) {
+ coroutineContext.ensureActive()
+ withContext(Main) {
+ context.selector(
+ title = context.getString(R.string.select_restore_file),
+ items = names
+ ) { _, index ->
+ if (index in names.indices) {
+ restoreWebDav(names[index])
+ }
+ }
+ }
+ } else {
+ throw NoStackTraceException("Web dav no back up file")
+ }
+ }
+
+ private fun restoreWebDav(name: String) {
+ waitDialog.setText("恢复中…")
+ waitDialog.show()
+ val task = Coroutine.async {
+ AppWebDav.restoreWebDav(name)
+ }.onError {
+ AppLog.put("WebDav恢复出错\n${it.localizedMessage}", it)
+ appCtx.toastOnUi("WebDav恢复出错\n${it.localizedMessage}")
+ }.onFinally {
+ waitDialog.dismiss()
+ }
+ waitDialog.setOnCancelListener {
+ task.cancel()
+ }
+ }
+
+ private fun restoreFromLocal() {
+ restoreDoc.launch {
+ title = getString(R.string.select_restore_file)
+ mode = HandleFileContract.FILE
+ allowExtensions = arrayOf("zip")
+ }
+ }
+
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+}
diff --git a/app/src/main/java/io/legato/kazusa/ui/welcome/WelcomeActivity.kt b/app/src/main/java/io/legato/kazusa/ui/welcome/WelcomeActivity.kt
index 5227b349d..780c8fb8f 100644
--- a/app/src/main/java/io/legato/kazusa/ui/welcome/WelcomeActivity.kt
+++ b/app/src/main/java/io/legato/kazusa/ui/welcome/WelcomeActivity.kt
@@ -1,86 +1,101 @@
package io.legato.kazusa.ui.welcome
-import android.content.Intent
-import android.graphics.drawable.BitmapDrawable
+
import android.os.Bundle
-import androidx.core.view.postDelayed
+import androidx.activity.addCallback
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import androidx.viewpager2.widget.ViewPager2
import io.legato.kazusa.base.BaseActivity
-import io.legato.kazusa.constant.PreferKey
-import io.legato.kazusa.constant.Theme
import io.legato.kazusa.databinding.ActivityWelcomeBinding
-import io.legato.kazusa.help.config.ThemeConfig
-//import io.legado.app.lib.theme.accentColor
-//import io.legado.app.lib.theme.backgroundColor
-import io.legato.kazusa.ui.book.read.ReadBookActivity
+import io.legato.kazusa.help.config.AppConfig
+import io.legato.kazusa.help.config.LocalConfig
import io.legato.kazusa.ui.main.MainActivity
-import io.legato.kazusa.utils.*
+import io.legato.kazusa.utils.startActivity
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
-open class WelcomeActivity : BaseActivity() {
+class WelcomeActivity : BaseActivity() {
override val binding by viewBinding(ActivityWelcomeBinding::inflate)
+ private val pages = listOf(
+ PrivacyFragment(),
+ WebDavFragment(),
+ ThemeFragment()
+ )
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-// binding.ivBook.setColorFilter(accentColor)
-// binding.vwTitleLine.setBackgroundColor(accentColor)
- // 避免从桌面启动程序后,会重新实例化入口类的activity
- if (intent.flags and Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT != 0) {
- finish()
- } else {
- binding.root.postDelayed(100) { startMainActivity() }
- }
- }
-// override fun setupSystemBar() {
-// fullScreen()
-// //setStatusBarColorAuto(backgroundColor, true, fullScreen)
-// upNavigationBarColor()
-// }
-
- override fun upBackgroundImage() {
- if (getPrefBoolean(PreferKey.customWelcome)) {
- kotlin.runCatching {
- when (ThemeConfig.getTheme()) {
- Theme.Dark -> getPrefString(PreferKey.welcomeImageDark)?.let { path ->
- val size = windowManager.windowSize
- BitmapUtils.decodeBitmap(path, size.widthPixels, size.heightPixels).let {
- binding.tvLegado.visible(getPrefBoolean(PreferKey.welcomeShowTextDark))
- binding.ivBook.visible(getPrefBoolean(PreferKey.welcomeShowIconDark))
- binding.tvGzh.visible(getPrefBoolean(PreferKey.welcomeShowTextDark))
- window.decorView.background = BitmapDrawable(resources, it)
- return
- }
- }
- else -> getPrefString(PreferKey.welcomeImage)?.let { path ->
- val size = windowManager.windowSize
- BitmapUtils.decodeBitmap(path, size.widthPixels, size.heightPixels).let {
- binding.tvLegado.visible(getPrefBoolean(PreferKey.welcomeShowText))
- binding.ivBook.visible(getPrefBoolean(PreferKey.welcomeShowIcon))
- binding.tvGzh.visible(getPrefBoolean(PreferKey.welcomeShowText))
- window.decorView.background = BitmapDrawable(resources, it)
- return
- }
- }
+ onBackPressedDispatcher.addCallback(this) {
+ val current = binding.viewPager.currentItem
+ if (current > 0) {
+ binding.viewPager.currentItem = current - 1
+ } else {
+ finish()
+ }
+ }
+
+ updateProgress(0)
+
+ binding.viewPager.adapter = object : FragmentStateAdapter(this) {
+ override fun getItemCount() = pages.size
+ override fun createFragment(position: Int) = pages[position]
+ }
+
+ binding.viewPager.isUserInputEnabled = false
+
+ binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
+ override fun onPageSelected(position: Int) {
+ super.onPageSelected(position)
+ binding.btnNext.text = when (position) {
+ 0 -> "阅读并同意" // PrivacyFragment
+ pages.lastIndex -> "完成"
+ else -> "下一步"
+ }
+ binding.tvTitle.text = when (position) {
+ 0 -> "欢迎!" // PrivacyFragment
+ 1 -> "备份与恢复"
+ else -> "主题样式"
+ }
+ binding.tvSummary.text = when (position) {
+ 0 -> "请先阅读应用的服务条款与用户协议。"
+ 1 -> "此处可设置云同步与恢复应用备份。"
+ else -> "在这里设置您喜爱的样式。"
}
+ updateProgress(position)
+ }
+ })
+
+ // 初始化按钮文字
+ binding.btnNext.text = "阅读并同意"
+
+ binding.btnNext.setOnClickListener {
+ val current = binding.viewPager.currentItem
+ when (current) {
+ 0 -> {
+ LocalConfig.privacyPolicyOk = true
+ binding.viewPager.currentItem = 1
+ }
+
+ pages.lastIndex -> {
+ updateProgress(2)
+ finishSetup()
+ }
+
+ else -> binding.viewPager.currentItem = current + 1
}
}
- super.upBackgroundImage()
}
- private fun startMainActivity() {
+ private fun updateProgress(position: Int) {
+ val progressMax = pages.size
+ val progress = (position * 100 / progressMax)
+ binding.progressBar.setProgress(progress, true)
+ }
+
+ private fun finishSetup() {
+ AppConfig.isFirstLaunch = false
startActivity()
- if (getPrefBoolean(PreferKey.defaultToRead)) {
- startActivity()
- }
finish()
}
-
}
-
-class Launcher1 : WelcomeActivity()
-class Launcher2 : WelcomeActivity()
-class Launcher3 : WelcomeActivity()
-class Launcher4 : WelcomeActivity()
-class Launcher5 : WelcomeActivity()
-class Launcher6 : WelcomeActivity()
\ No newline at end of file
diff --git a/app/src/main/res/color/chip_background_selector.xml b/app/src/main/res/color/chip_background_selector.xml
new file mode 100644
index 000000000..c3ad46f6c
--- /dev/null
+++ b/app/src/main/res/color/chip_background_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/color/chip_stroke_selector.xml b/app/src/main/res/color/chip_stroke_selector.xml
new file mode 100644
index 000000000..73f16062d
--- /dev/null
+++ b/app/src/main/res/color/chip_stroke_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_book_search.xml b/app/src/main/res/layout/activity_book_search.xml
index c930a94da..c123f5f09 100644
--- a/app/src/main/res/layout/activity_book_search.xml
+++ b/app/src/main/res/layout/activity_book_search.xml
@@ -33,6 +33,8 @@
android:id="@+id/refresh_progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ app:waveAmplitude="8dp"
+ app:wavelength="80dp"
android:indeterminate="true"
android:visibility="gone">
diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml
index b437c516a..e0352757d 100644
--- a/app/src/main/res/layout/activity_welcome.xml
+++ b/app/src/main/res/layout/activity_welcome.xml
@@ -1,82 +1,76 @@
+ android:animateLayoutChanges="true"
+ android:fitsSystemWindows="true">
-
+ android:orientation="vertical"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
-
+
-
+ android:layout_marginHorizontal="16dp"
+ android:text="欢迎!"
+ android:textSize="36sp"
+ android:textStyle="bold" />
-
+ android:layout_marginHorizontal="16dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="16dp"
+ android:text="请先阅读应用的服务条款与用户协议。"
+ android:textStyle="bold" />
+
+
-
+
-
-
-
+ app:layout_constraintEnd_toEndOf="parent" />
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/dialog_read_bg_text.xml b/app/src/main/res/layout/dialog_read_bg_text.xml
index 1120c642e..0852dd774 100644
--- a/app/src/main/res/layout/dialog_read_bg_text.xml
+++ b/app/src/main/res/layout/dialog_read_bg_text.xml
@@ -50,66 +50,70 @@
app:layout_constraintTop_toBottomOf="@id/tv_name_title"
tools:text="文字" />
-
-
-
+ app:layout_constraintTop_toTopOf="@id/tv_name">
-
+
-
+
+
+
+
+
-
-
+ app:layout_constraintTop_toBottomOf="@id/mbg_1">
+
+
+
+
+
+
+
+
+
@@ -129,7 +133,7 @@
android:text="@string/text_underline"
tools:ignore="TouchTargetSizeCheck" />
-
-
+
diff --git a/app/src/main/res/layout/dialog_read_book_style.xml b/app/src/main/res/layout/dialog_read_book_style.xml
index 1b8a8226f..9aa1e69a1 100644
--- a/app/src/main/res/layout/dialog_read_book_style.xml
+++ b/app/src/main/res/layout/dialog_read_book_style.xml
@@ -272,45 +272,37 @@
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_privacy.xml b/app/src/main/res/layout/fragment_privacy.xml
new file mode 100644
index 000000000..b9bc6e778
--- /dev/null
+++ b/app/src/main/res/layout/fragment_privacy.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_webdav_auth.xml b/app/src/main/res/layout/fragment_webdav_auth.xml
new file mode 100644
index 000000000..da44664fd
--- /dev/null
+++ b/app/src/main/res/layout/fragment_webdav_auth.xml
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_bg_image.xml b/app/src/main/res/layout/item_bg_image.xml
index b22ed8cc2..f3b86a871 100644
--- a/app/src/main/res/layout/item_bg_image.xml
+++ b/app/src/main/res/layout/item_bg_image.xml
@@ -7,6 +7,7 @@
android:orientation="vertical">
diff --git a/app/src/main/res/layout/item_download.xml b/app/src/main/res/layout/item_download.xml
index 7574e1c10..803f1eafd 100644
--- a/app/src/main/res/layout/item_download.xml
+++ b/app/src/main/res/layout/item_download.xml
@@ -104,6 +104,8 @@
style="@style/Widget.Material3.LinearProgressIndicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ app:waveAmplitude="8dp"
+ app:wavelength="80dp"
android:layout_marginTop="2dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/iv_download" />
diff --git a/app/src/main/res/layout/item_read_style.xml b/app/src/main/res/layout/item_read_style.xml
index 8cc6a8328..aa3902e57 100644
--- a/app/src/main/res/layout/item_read_style.xml
+++ b/app/src/main/res/layout/item_read_style.xml
@@ -1,5 +1,6 @@
diff --git a/app/src/main/res/layout/view_pref.xml b/app/src/main/res/layout/view_pref.xml
index 22373aef8..0b299992d 100644
--- a/app/src/main/res/layout/view_pref.xml
+++ b/app/src/main/res/layout/view_pref.xml
@@ -1,6 +1,7 @@
diff --git a/app/src/main/res/layout/view_theme_mode.xml b/app/src/main/res/layout/view_theme_mode.xml
index 28faa6e0b..aee5936bf 100644
--- a/app/src/main/res/layout/view_theme_mode.xml
+++ b/app/src/main/res/layout/view_theme_mode.xml
@@ -4,16 +4,16 @@
android:id="@+id/theme_toggle_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
+ android:spacing="2dp"
+ app:innerCornerSize="8dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
- android:gravity="center"
app:singleSelection="true"
app:selectionRequired="true">
true
- false
- @style/Widget.App.TabLayout
+ - @style/Widget.MyApp.Chip.Assist
- @drawable/popup_background
- @style/AppTheme.AlertDialog
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 91c5c825d..8f0874873 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -25,7 +25,7 @@
16dp
48dp
- 16dp
+ 12dp
8dp
8dp
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index fc6b9c24e..ce8154e24 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -32,6 +32,11 @@
- @layout/m3_alert_dialog
+
+
diff --git a/app/src/main/res/xml/pref_strat_theme.xml b/app/src/main/res/xml/pref_strat_theme.xml
new file mode 100644
index 000000000..0d0a8f07e
--- /dev/null
+++ b/app/src/main/res/xml/pref_strat_theme.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a54fb6629..da6916e28 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,17 +1,17 @@
[versions]
datastorePreferences = "1.1.7"
-kotlin = "2.1.21"
+kotlin = "2.2.10"
ksp = "2.1.21-2.0.1"
-agp = "8.12.0"
+agp = "8.12.1"
appcompat = "1.7.1"
colorpicker = "1.1.0"
-commonsText = "1.13.1"
+commonsText = "1.14.0"
constraintlayout = "2.2.1"
-core = "1.16.0"
-firebaseBom = "34.0.0"
+core = "1.17.0"
+firebaseBom = "34.1.0"
flexbox = "3.0.0"
-fragment = "1.8.8"
+fragment = "1.8.9"
#不要更新版本
hutool = "5.8.22"
@@ -28,7 +28,7 @@ jsoupxpath = "2.5.3"
coroutines = "1.10.2"
liveeventbus = "1.8.14"
markwon = "4.6.2"
-material = "1.14.0-alpha03"
+material = "1.14.0-alpha04"
media = "1.7.0"
media3 = "1.7.1"
nanoHttpd = "2.3.1"
@@ -52,7 +52,7 @@ viewpager2 = "1.0.0"
webkit = "1.14.0"
collection = "1.5.0"
-zxingLite = "3.2.0"
+zxingLite = "3.3.0"
[libraries]