fix: 封面设置来源统一

This commit is contained in:
HapeLee
2026-06-09 13:07:55 +08:00
parent 18dd340de1
commit 264f93389a
6 changed files with 5 additions and 623 deletions
@@ -600,8 +600,6 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val recordHeapDump get() = OtherConfig.recordHeapDump
val loadCoverOnlyWifi get() = appCtx.getPrefBoolean(PreferKey.loadCoverOnlyWifi, false)
val showAddToShelfAlert get() = OtherConfig.showAddToShelfAlert
var ignoreAudioFocus
@@ -19,7 +19,7 @@ import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.request.target.Target.SIZE_ORIGINAL
import io.legado.app.R
import io.legado.app.constant.PreferKey
import io.legado.app.ui.config.coverConfig.CoverConfig
import io.legado.app.data.entities.BaseSource
import io.legado.app.data.entities.Book
import io.legado.app.help.CacheManager
@@ -34,7 +34,6 @@ import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.BitmapUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject
import io.legado.app.utils.getPrefString
import kotlinx.coroutines.currentCoroutineContext
import splitties.init.appCtx
import java.io.File
@@ -50,8 +49,8 @@ object BookCover {
@SuppressLint("UseCompatLoadingForDrawables")
get() {
val isNightTheme = AppConfig.isNightTheme
val key = if (isNightTheme) PreferKey.defaultCoverDark else PreferKey.defaultCover
val paths = appCtx.getPrefString(key)?.split(",")?.filter { it.isNotBlank() }
val pathStr = if (isNightTheme) CoverConfig.defaultCoverDark else CoverConfig.defaultCover
val paths = pathStr.split(",").filter { it.isNotBlank() }
if (paths.isNullOrEmpty()) {
return appCtx.resources.getDrawable(R.drawable.image_cover_default, null)
@@ -67,8 +66,8 @@ object BookCover {
seed: Any? = null,
isNight: Boolean = AppConfig.isNightTheme
): String? {
val key = if (isNight) PreferKey.defaultCoverDark else PreferKey.defaultCover
val paths = appCtx.getPrefString(key)?.split(",")?.filter { it.isNotBlank() }
val pathStr = if (isNight) CoverConfig.defaultCoverDark else CoverConfig.defaultCover
val paths = pathStr.split(",").filter { it.isNotBlank() }
if (paths.isNullOrEmpty()) return null
val random = if (seed != null) Random(seed.hashCode()) else Random
return paths[random.nextInt(paths.size)]
@@ -1,200 +0,0 @@
package io.legado.app.ui.book.search
import android.content.Context
import android.os.Bundle
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil
import io.legado.app.R
import io.legado.app.base.adapter.DiffRecyclerAdapter
import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.data.entities.SearchBook
import io.legado.app.databinding.ItemSearchBinding
import io.legado.app.help.config.AppConfig
import io.legado.app.domain.model.BookShelfState
import io.legado.app.ui.widget.text.AccentBgTextView
import io.legado.app.utils.dpToPx
import io.legado.app.utils.gone
import io.legado.app.utils.visible
class SearchAdapter(context: Context, val callBack: CallBack) :
DiffRecyclerAdapter<SearchBook, ItemSearchBinding>(context) {
override val keepScrollPosition = true
override val diffItemCallback: DiffUtil.ItemCallback<SearchBook>
get() = object : DiffUtil.ItemCallback<SearchBook>() {
override fun areItemsTheSame(oldItem: SearchBook, newItem: SearchBook): Boolean {
return when {
oldItem.name != newItem.name -> false
oldItem.author != newItem.author -> false
else -> true
}
}
override fun areContentsTheSame(oldItem: SearchBook, newItem: SearchBook): Boolean {
return false
}
override fun getChangePayload(oldItem: SearchBook, newItem: SearchBook): Any {
val payload = Bundle()
payload.putInt("origins", newItem.origins.size)
if (oldItem.coverUrl != newItem.coverUrl)
payload.putString("cover", newItem.coverUrl)
if (oldItem.kind != newItem.kind)
payload.putString("kind", newItem.kind)
if (oldItem.latestChapterTitle != newItem.latestChapterTitle)
payload.putString("last", newItem.latestChapterTitle)
if (oldItem.intro != newItem.intro)
payload.putString("intro", newItem.intro)
return payload
}
}
override fun getViewBinding(parent: ViewGroup): ItemSearchBinding {
return ItemSearchBinding.inflate(inflater, parent, false)
}
override fun convert(
holder: ItemViewHolder,
binding: ItemSearchBinding,
item: SearchBook,
payloads: MutableList<Any>
) {
if (payloads.isEmpty()) {
bind(binding, item)
} else {
for (i in payloads.indices) {
val bundle = payloads[i] as Bundle
bindChange(binding, item, bundle)
}
}
}
override fun registerListener(holder: ItemViewHolder, binding: ItemSearchBinding) {
binding.llContent.setOnClickListener {
getItem(holder.layoutPosition)?.let {
callBack.showBookInfo(it.name, it.author, it.bookUrl)
}
}
}
private fun bind(binding: ItemSearchBinding, searchBook: SearchBook) {
binding.run {
tvName.text = searchBook.name
tvAuthor.text = context.getString(R.string.author_show, searchBook.author)
when (callBack.getBookShelfState(searchBook.name, searchBook.author, searchBook.bookUrl)) {
BookShelfState.IN_SHELF -> {
ivInBookshelf.isVisible = true
tvBookshelf.text = context.getString(R.string.remove_from_bookshelf)
}
BookShelfState.SAME_NAME_AUTHOR -> {
ivInBookshelf.isVisible = true
tvBookshelf.text = context.getString(R.string.same_name_book)
}
BookShelfState.NOT_IN_SHELF -> {
ivInBookshelf.isVisible = false
}
}
bvOriginCount.text = searchBook.origins.size.toString()
upLasted(binding, searchBook.latestChapterTitle)
tvIntroduce.text = searchBook.trimIntro(context)
upKind(binding, searchBook.getKindList())
ivCover.load(
searchBook.coverUrl,
searchBook.name,
searchBook.author,
AppConfig.loadCoverOnlyWifi,
searchBook.origin
)
}
}
private fun bindChange(binding: ItemSearchBinding, searchBook: SearchBook, bundle: Bundle) {
binding.run {
bundle.keySet().forEach {
when (it) {
"origins" -> bvOriginCount.text = searchBook.origins.size.toString()
"last" -> upLasted(binding, searchBook.latestChapterTitle)
"intro" -> tvIntroduce.text = searchBook.trimIntro(context)
"kind" -> upKind(binding, searchBook.getKindList())
"isInBookshelf" -> {
when (callBack.getBookShelfState(searchBook.name, searchBook.author, searchBook.bookUrl)) {
BookShelfState.IN_SHELF -> {
ivInBookshelf.isVisible = true
tvBookshelf.text = context.getString(R.string.remove_from_bookshelf)
}
BookShelfState.SAME_NAME_AUTHOR -> {
ivInBookshelf.isVisible = true
tvBookshelf.text = context.getString(R.string.same_name_book)
}
BookShelfState.NOT_IN_SHELF -> {
ivInBookshelf.isVisible = false
}
}
}
"cover" -> ivCover.load(
searchBook.coverUrl,
searchBook.name,
searchBook.author,
false,
searchBook.origin
)
}
}
}
}
private fun upLasted(binding: ItemSearchBinding, latestChapterTitle: String?) {
binding.run {
if (latestChapterTitle.isNullOrEmpty()) {
tvLasted.gone()
} else {
tvLasted.text =
context.getString(R.string.lasted_show, latestChapterTitle)
tvLasted.visible()
}
}
}
private fun upKind(binding: ItemSearchBinding, kinds: List<String>) = binding.run {
if (kinds.isEmpty()) {
kindContainer.gone()
} else {
kindContainer.visible()
kindContainer.removeAllViews()
kinds.forEach { kind ->
val kindTextView = AccentBgTextView(context).apply {
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).apply {
marginEnd = 4.dpToPx()
}
textSize = 11f
text = kind
setLines(1)
setSingleLine(true)
}
kindContainer.addView(kindTextView)
}
}
}
interface CallBack {
/**
* 是否已经加入书架
*/
fun getBookShelfState(name: String, author: String, url: String?): BookShelfState
/**
* 显示书籍详情
*/
fun showBookInfo(name: String, author: String, bookUrl: String)
}
}
@@ -1,214 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.book.search.SearchActivity">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="false"
android:fitsSystemWindows="true"
app:statusBarForeground="?attr/colorSurface">
<com.google.android.material.search.SearchBar
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/search_book_key"
app:menu="@menu/book_search"
app:navigationIcon="@drawable/ic_arrow_back"
app:navigationIconTint="?attr/colorOnSurface" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/refresh_progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
app:waveAmplitude="2dp"
app:waveSpeed="50dp"
app:wavelength="40dp" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/cd_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="4dp"
android:scaleType="centerCrop"
android:visibility="invisible"
app:cardBackgroundColor="?attr/colorTertiaryContainer"
app:cardCornerRadius="4dp"
app:strokeWidth="0dp">
<TextView
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="4dp"
android:paddingVertical="2dp"
android:text="@string/progress"
android:textColor="?attr/colorOnTertiaryContainer"
android:textSize="10sp"
android:textStyle="bold"
tools:ignore="SmallSp" />
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.appbar.AppBarLayout>
<io.legado.app.ui.widget.EmptyMessageView
android:id="@+id/tv_empty_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:messageText="@string/search_empty"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:visibility="visible"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
tools:listitem="@layout/item_search"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/>
<LinearLayout
android:id="@+id/ll_stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:gravity="end"
android:orientation="horizontal">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fb_start_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:tint="?attr/colorOnTertiaryContainer"
app:backgroundTint="?attr/colorTertiaryContainer"
android:contentDescription="@string/stop"
android:src="@drawable/ic_stop_black_24dp"
android:visibility="invisible" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.search.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:menu="@menu/book_search"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/ll_input_help"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:visibility="visible">
<com.google.android.material.chip.ChipGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:chipSpacingVertical="0dp"
android:layout_marginTop="8dp"
android:layout_marginHorizontal="16dp">
<com.google.android.material.chip.Chip
android:id="@+id/chip_precision_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="@string/precision_search"/>
<com.google.android.material.chip.Chip
android:id="@+id/chip_search_scope"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/all_source"/>
<com.google.android.material.chip.Chip
android:id="@+id/chip_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:checkable="true"
android:text="@string/search_select_group"/>
</com.google.android.material.chip.ChipGroup>
<TextView
android:id="@+id/tv_book_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
android:text="@string/bookshelf"
android:textSize="16sp"
android:textStyle="bold"
android:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_bookshelf_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tv_history"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/searchHistory"
android:textSize="16sp"
android:textStyle="bold" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_clear_history"
style="@style/Widget.Material3Expressive.Button"
android:text="@string/delete_all"
app:backgroundTint="?attr/colorSecondaryContainer"
app:iconTint="?attr/colorOnSecondaryContainer"
android:textColor="?attr/colorOnSecondaryContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/ic_clear_all"
app:strokeColor="?attr/colorSecondaryContainer"
app:iconGravity="textStart" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_history_key"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</com.google.android.material.search.SearchView>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.book.search.SearchActivity">
<io.legado.app.ui.widget.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/discovery" />
<io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout
android:id="@+id/content_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_bar">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_search" />
</io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
-166
View File
@@ -1,166 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:strokeWidth="0dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="4dp">
<LinearLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
android:scrollbars="none">
<!-- 封面图片 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:strokeWidth="0dp">
<io.legado.app.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="80dp"
android:layout_height="110dp"
android:contentDescription="@string/img_cover"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default"
android:transitionName="img_cover"
tools:ignore="UnusedAttribute" />
<!-- 书架内标记 -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/iv_in_bookshelf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_margin="4dp"
android:scaleType="centerCrop"
android:visibility="visible"
app:cardBackgroundColor="?attr/colorTertiaryContainer"
app:cardCornerRadius="4dp"
app:strokeWidth="0dp">
<TextView
android:id="@+id/tv_bookshelf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="4dp"
android:paddingVertical="2dp"
android:text="@string/remove_from_bookshelf"
android:textColor="?attr/colorOnTertiaryContainer"
android:textStyle="bold"
android:textSize="9sp"
tools:ignore="SmallSp" />
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.card.MaterialCardView>
<!-- 右侧内容区域 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:layout_gravity="center"
android:orientation="vertical">
<!-- 标题行 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/app_name"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@id/cd_count"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/cd_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginVertical="4dp"
app:cardBackgroundColor="?attr/colorSurfaceContainer"
app:cardCornerRadius="4dp"
app:layout_constraintBottom_toBottomOf="@id/tv_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_name"
app:strokeWidth="0dp">
<TextView
android:id="@+id/bv_originCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="4dp"
android:paddingVertical="2dp"
android:text="@string/text"
android:textColor="?attr/colorPrimary"
android:textSize="10sp"
android:textStyle="bold"
tools:ignore="SmallSp" />
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorSecondary"
android:lines="1"
android:singleLine="true"
android:text="@string/author"
android:textSize="12sp" />
<!-- 最后阅读 -->
<TextView
android:id="@+id/tv_lasted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:text="@string/last_read"
android:textSize="11sp" />
<!-- 简介 -->
<TextView
android:id="@+id/tv_introduce"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end"
android:text="@string/book_intro"
android:textSize="11sp" />
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:layout_marginTop="2dp">
<LinearLayout
android:id="@+id/kind_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</HorizontalScrollView>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>