增加漫画单独配置

更新界面
This commit is contained in:
HapeLee committed 2025-08-02 12:44:25 +08:00
1 parent 22f34161ab
commit 3c5df88027
44 files changed
+798 -1059

No files matched your search

@@ -1,14 +1,15 @@
package io.legato.kazusa.ui.book.group
//import io.legado.app.lib.theme.primaryColor
import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.viewModels
import io.legato.kazusa.R
import io.legato.kazusa.base.BaseBottomSheetDialogFragment
import io.legato.kazusa.data.entities.BookGroup
import io.legato.kazusa.databinding.DialogBookGroupEditBinding
import io.legato.kazusa.lib.dialogs.alert
//import io.legado.app.lib.theme.primaryColor
import io.legato.kazusa.utils.FileUtils
import io.legato.kazusa.utils.MD5Utils
import io.legato.kazusa.utils.SelectImageContract
@@ -19,7 +20,6 @@ import io.legato.kazusa.utils.launch
import io.legato.kazusa.utils.readUri
import io.legato.kazusa.utils.toastOnUi
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import io.legato.kazusa.utils.visible
import splitties.init.appCtx
import splitties.views.onClick
import java.io.FileOutputStream
@@ -32,6 +32,9 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
}
}
private var selectedSortIndex = -1
private lateinit var sortOptions: List<String>
private val binding by viewBinding(DialogBookGroupEditBinding::bind)
private val viewModel by viewModels<GroupViewModel>()
private var bookGroup: BookGroup? = null
@@ -62,21 +65,40 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
//binding.toolBar.setBackgroundColor(primaryColor)
sortOptions = resources.getStringArray(R.array.book_sort).toList()
@Suppress("DEPRECATION")
bookGroup = arguments?.getParcelable("group")
bookGroup?.let {
binding.btnDelete.visible(it.groupId > 0 || it.groupId == Long.MIN_VALUE)
binding.btnDelete.isEnabled = (it.groupId > 0 || it.groupId == Long.MIN_VALUE)
binding.tieGroupName.setText(it.groupName)
if (bookGroup?.cover != null)
binding.ivCover.load(it.cover)
binding.spSort.setSelection(it.bookSort + 1)
binding.cbEnableRefresh.isChecked = it.enableRefresh
if (it.bookSort in sortOptions.indices) {
selectedSortIndex = it.bookSort
binding.chipSortMenu.text = sortOptions[selectedSortIndex]
}
} ?: let {
binding.toolBar.title = getString(R.string.add_group)
binding.btnDelete.gone()
binding.ivCover.load()
}
binding.run {
chipSortMenu.setOnClickListener { chip ->
PopupMenu(requireContext(), chip).apply {
sortOptions.forEachIndexed { index, title ->
menu.add(0, index, index, title)
}
setOnMenuItemClickListener { item ->
selectedSortIndex = item.itemId
chipSortMenu.text = sortOptions[selectedSortIndex]
true
}
show()
}
}
ivCover.onClick {
selectImage.launch()
}
@@ -88,15 +110,17 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
}
}
}
btnCancel.onClick {
dismiss()
}
btnOk.onClick {
val groupName = tieGroupName.text?.toString()
if (groupName.isNullOrEmpty()) {
toastOnUi("分组名称不能为空")
} else {
val bookSort = binding.spSort.selectedItemPosition - 1
val bookSort = selectedSortIndex
val coverPath = binding.ivCover.bitmapPath
val enableRefresh = binding.cbEnableRefresh.isChecked
bookGroup?.let {
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Looper
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
@@ -202,8 +201,12 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
enableMangaEInk(AppConfig.enableMangaEInk, AppConfig.mangaEInkThreshold)
enableGray(AppConfig.enableMangaGray)
}
//setHorizontalScroll(AppConfig.enableMangaHorizontalScroll)
setScrollMode(AppConfig.mangaScrollMode)
viewModel.initData(intent) {
setScrollMode(viewModel.getEffectiveScrollMode())
updateWebtoonSidePadding(viewModel.getEffectiveWebtoonSidePadding())
}
binding.recyclerView.run {
adapter = mAdapter
itemAnimator = null
@@ -212,7 +215,6 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
setDisableClickScroll(AppConfig.disableClickScroll)
setDisableMangaScale(AppConfig.disableMangaScale)
setRecyclerViewPreloader(AppConfig.mangaPreDownloadNum)
updateWebtoonSidePadding(AppConfig.webtoonSidePaddingDp)
setPreScrollListener { _, _, _, position ->
if (mAdapter.isNotEmpty()) {
val item = mAdapter.getItem(position)
@@ -267,10 +269,10 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
Looper.myQueue().addIdleHandler {
viewModel.initData(intent)
false
}
// Looper.myQueue().addIdleHandler {
// viewModel.initData(intent)
// false
// }
justInitData = true
}
@@ -563,6 +565,8 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
override fun showScrollModeDialog() {
showDialogFragment(MangaScrollModeDialog().apply {
initialScrollMode = viewModel.getEffectiveScrollMode()
initialWebtoonSidePadding = viewModel.getEffectiveWebtoonSidePadding()
initialAutoPageEnabled = enableScroll
callback = this@ReadMangaActivity
})
@@ -570,7 +574,10 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
//漫画模式
override fun onScrollModeChanged(mode: Int) {
AppConfig.mangaScrollMode = mode
//AppConfig.mangaScrollMode = mode
viewModel.updateReadConfig {
mangaScrollMode = mode
}
setScrollMode(mode)
updateWebtoonSidePadding(AppConfig.webtoonSidePaddingDp)
setAutoReadEnabled(false)
@@ -590,7 +597,9 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
//侧边留白
override fun upSidePadding(paddingDp: Int) {
AppConfig.webtoonSidePaddingDp = paddingDp
viewModel.updateReadConfig {
webtoonSidePaddingDp = paddingDp
}
updateWebtoonSidePadding(paddingDp)
}
@@ -626,6 +635,10 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
// }
}
override fun onVolumeKeyPageChanged(enable: Boolean) {
AppConfig.MangaVolumeKeyPage = enable
}
override fun onHideMangaTitleChanged(hide: Boolean) {
AppConfig.hideMangaTitle = hide
ReadManga.loadContent()
@@ -907,17 +920,20 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_VOLUME_UP -> {
scrollToPrev()
return true
}
if (AppConfig.MangaVolumeKeyPage) {
when (keyCode) {
KeyEvent.KEYCODE_VOLUME_UP -> {
scrollToPrev()
return true
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
scrollToNext()
return true
KeyEvent.KEYCODE_VOLUME_DOWN -> {
scrollToNext()
return true
}
}
}
return super.onKeyDown(keyCode, event)
}
@@ -9,6 +9,7 @@ import io.legato.kazusa.constant.BookType
import io.legato.kazusa.constant.EventBus
import io.legato.kazusa.data.appDb
import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.Book.ReadConfig
import io.legato.kazusa.data.entities.BookChapter
import io.legato.kazusa.data.entities.BookProgress
import io.legato.kazusa.exception.NoStackTraceException
@@ -273,6 +274,29 @@ class ReadMangaViewModel(application: Application) : BaseViewModel(application)
}
}
fun getEffectiveScrollMode(): Int {
return ReadManga.book?.readConfig?.mangaScrollMode ?: AppConfig.mangaScrollMode
}
fun getEffectiveWebtoonSidePadding(): Int {
return ReadManga.book?.readConfig?.webtoonSidePaddingDp ?: AppConfig.webtoonSidePaddingDp
}
fun updateReadConfig(update: ReadConfig.() -> Unit) {
val book = ReadManga.book ?: return
val config = book.readConfig ?: ReadConfig()
config.update()
book.readConfig = config
execute {
appDb.bookDao.update(book)
}.onError {
AppLog.put("更新阅读配置失败\n${it.localizedMessage}", it)
}
}
override fun onCleared() {
super.onCleared()
changeSourceCoroutine?.cancel()
@@ -14,6 +14,9 @@ class MangaScrollModeDialog : BaseBottomSheetDialogFragment(R.layout.dialog_mang
private val binding by viewBinding(DialogMangaScrollModeBinding::bind)
var initialAutoPageEnabled: Boolean = false
var initialWebtoonSidePadding: Int = 0
var initialScrollMode: Int = MangaScrollMode.PAGE_RIGHT_TO_LEFT
var callback: Callback? = null
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
@@ -27,7 +30,7 @@ class MangaScrollModeDialog : BaseBottomSheetDialogFragment(R.layout.dialog_mang
binding.chipGroupScrollMode.addView(Chip(requireContext()).apply {
text = MangaScrollMode.labelOf(mode)
isCheckable = true
isChecked = (mode == AppConfig.mangaScrollMode)
isChecked = (mode == initialScrollMode)
setOnClickListener {
callback?.onScrollModeChanged(mode)
@@ -65,9 +68,16 @@ class MangaScrollModeDialog : BaseBottomSheetDialogFragment(R.layout.dialog_mang
}
}
binding.checkboxVolumeKeyPage.apply {
isChecked = AppConfig.MangaVolumeKeyPage
setOnCheckedChangeListener { _, isChecked ->
callback?.onVolumeKeyPageChanged(isChecked)
}
}
binding.scvPadding.apply {
valueFormat = { "$it %" }
progress = AppConfig.webtoonSidePaddingDp
progress = initialWebtoonSidePadding
onChanged = { newValue ->
callback?.upSidePadding(newValue)
}
@@ -96,6 +106,7 @@ class MangaScrollModeDialog : BaseBottomSheetDialogFragment(R.layout.dialog_mang
fun onMangaScaleDisabledChanged(disabled: Boolean)
fun upSidePadding(padding: Int)
fun onHideMangaTitleChanged(hide: Boolean)
fun onVolumeKeyPageChanged(enable: Boolean)
}
}
@@ -2,6 +2,7 @@ package io.legato.kazusa.ui.book.read.config
import android.content.DialogInterface
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import androidx.core.view.get
@@ -15,6 +16,7 @@ import io.legato.kazusa.databinding.DialogReadBookStyleBinding
import io.legato.kazusa.databinding.ItemReadStyleBinding
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.help.config.ReadBookConfig
import io.legato.kazusa.help.config.ThemeConfig
import io.legato.kazusa.lib.dialogs.selector
import io.legato.kazusa.model.ReadBook
import io.legato.kazusa.ui.book.read.ReadBookActivity
@@ -22,9 +24,8 @@ import io.legato.kazusa.ui.font.FontSelectDialog
import io.legato.kazusa.utils.ChineseUtils
import io.legato.kazusa.utils.postEvent
import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.themeColor
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import splitties.views.onLongClick
import io.legato.kazusa.help.config.ThemeConfig
class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_style),
FontSelectDialog.CallBack {
@@ -229,32 +230,35 @@ class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_
payloads: MutableList<Any>
) {
binding.apply {
ivStyle.setText(item.name.ifBlank { "文字" })
ivStyle.setTextColor(item.curTextColor())
tvStyle.text = item.name.ifBlank { "文字" }
tvStyle.setTextColor(item.curTextColor())
ivStyle.setImageDrawable(item.curBgDrawable(100, 150))
if (ReadBookConfig.styleSelect == holder.layoutPosition) {
//ivStyle.borderColor = accentColor
ivStyle.setTextBold(true)
llStyle.gravity = Gravity.TOP
cdStyle.strokeColor =
context.themeColor(com.google.android.material.R.attr.colorTertiary)
rvStyle.setCardBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorTertiary))
//tvStyle.setTextBold(true)
} else {
ivStyle.borderColor = item.curTextColor()
ivStyle.setTextBold(false)
cdStyle.strokeColor = item.curTextColor()
//tvStyle.setTextBold(false)
}
}
}
override fun registerListener(holder: ItemViewHolder, binding: ItemReadStyleBinding) {
binding.apply {
ivStyle.setOnClickListener {
if (ivStyle.isInView) {
changeBgTextConfig(holder.layoutPosition)
}
// ivStyle 现在是 MaterialCardView
cdStyle.setOnClickListener {
changeBgTextConfig(holder.layoutPosition)
}
ivStyle.onLongClick(ivStyle.isInView) {
if (ivStyle.isInView) {
showBgTextConfig(holder.layoutPosition)
}
cdStyle.setOnLongClickListener {
showBgTextConfig(holder.layoutPosition)
true // 表示事件已消费
}
}
}
}
}
@@ -1,22 +1,21 @@
package io.legato.kazusa.ui.book.source.manage
//import io.legado.app.lib.theme.backgroundColor
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.PopupMenu
import androidx.core.os.bundleOf
import androidx.core.view.doOnLayout
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.card.MaterialCardView
import io.legato.kazusa.R
import io.legato.kazusa.base.adapter.ItemViewHolder
import io.legato.kazusa.base.adapter.RecyclerAdapter
import io.legato.kazusa.data.entities.BookSourcePart
import io.legato.kazusa.databinding.ItemBookSourceBinding
//import io.legado.app.lib.theme.backgroundColor
import io.legato.kazusa.model.Debug
import io.legato.kazusa.ui.login.SourceLoginActivity
import io.legato.kazusa.ui.widget.recycler.DragSelectTouchHelper
@@ -25,6 +24,7 @@ import io.legato.kazusa.utils.buildMainHandler
import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.invisible
import io.legato.kazusa.utils.startActivity
import io.legato.kazusa.utils.themeColor
import io.legato.kazusa.utils.visible
import java.util.Collections
@@ -208,20 +208,20 @@ class BookSourceAdapter(
popupMenu.show()
}
private fun upShowExplore(iv: ImageView, source: BookSourcePart) {
private fun upShowExplore(iv: MaterialCardView, source: BookSourcePart) {
when {
!source.hasExploreUrl -> {
iv.invisible()
}
source.enabledExplore -> {
iv.setColorFilter(Color.GREEN)
iv.setCardBackgroundColor(context.themeColor(androidx.appcompat.R.attr.colorPrimary))
iv.visible()
iv.contentDescription = context.getString(R.string.tag_explore_enabled)
}
else -> {
iv.setColorFilter(Color.RED)
iv.setCardBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorOnError))
iv.visible()
iv.contentDescription = context.getString(R.string.tag_explore_disabled)
}