From 76feb9202af575b0524981ed96ce3ffdbc285129 Mon Sep 17 00:00:00 2001 From: HapeLee <1321903405@qq.com> Date: Tue, 11 Nov 2025 00:52:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B9=A6=E7=B1=8D=E5=8C=B9=E9=85=8DURL=20#282?= =?UTF-8?q?=E3=80=81#203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/book/explore/ExploreShowActivity.kt | 5 +-- .../app/ui/book/explore/ExploreShowAdapter.kt | 34 ++++++++++++++++--- .../ui/book/explore/ExploreShowViewModel.kt | 30 ++++++++-------- .../app/ui/book/search/SearchActivity.kt | 4 +-- .../app/ui/book/search/SearchAdapter.kt | 34 ++++++++++++++++--- .../app/ui/book/search/SearchViewModel.kt | 34 +++++++++++-------- app/src/main/res/layout/item_search.xml | 3 +- 7 files changed, 99 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt index a8a16ad3a..38d25078d 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt @@ -11,6 +11,7 @@ import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.ActivityExploreShowBinding import io.legado.app.databinding.ViewLoadMoreBinding import io.legado.app.ui.book.info.BookInfoActivity +import io.legado.app.ui.book.search.BookShelfState import io.legado.app.ui.widget.recycler.LoadMoreView import io.legado.app.utils.applyNavigationBarPadding import io.legado.app.utils.startActivity @@ -81,8 +82,8 @@ class ExploreShowActivity : VMBaseActivity { + 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 + } + } if (item.latestChapterTitle.isNullOrEmpty()) { tvLasted.gone() } else { @@ -90,8 +103,21 @@ class ExploreShowAdapter(context: Context, val callBack: CallBack) : binding.run { bundle.keySet().forEach { when (it) { - "isInBookshelf" -> ivInBookshelf.isVisible = - callBack.isInBookshelf(item.name, item.author) + "isInBookshelf" -> { + when (callBack.getBookShelfState(item.name, item.author, item.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 + } + } + } } } } @@ -109,7 +135,7 @@ class ExploreShowAdapter(context: Context, val callBack: CallBack) : /** * 是否已经加入书架 */ - fun isInBookshelf(name: String, author: String): Boolean + fun getBookShelfState(name: String, author: String, url: String?): BookShelfState fun showBookInfo(book: Book) } diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt index 1fc24f296..80cfe342e 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt @@ -12,6 +12,8 @@ import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.help.book.isNotShelf import io.legado.app.model.webBook.WebBook +import io.legado.app.ui.book.search.BookKey +import io.legado.app.ui.book.search.BookShelfState import io.legado.app.utils.printOnDebug import io.legado.app.utils.stackTraceStr import kotlinx.coroutines.Dispatchers.IO @@ -23,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap @OptIn(ExperimentalCoroutinesApi::class) class ExploreShowViewModel(application: Application) : BaseViewModel(application) { - val bookshelf: MutableSet = ConcurrentHashMap.newKeySet() + val bookshelf: MutableSet = ConcurrentHashMap.newKeySet() val upAdapterLiveData = MutableLiveData() val booksData = MutableLiveData>() val errorLiveData = MutableLiveData() @@ -35,18 +37,12 @@ class ExploreShowViewModel(application: Application) : BaseViewModel(application init { execute { appDb.bookDao.flowAll().mapLatest { books -> - val keys = arrayListOf() books.filterNot { it.isNotShelf } - .forEach { - keys.add("${it.name}-${it.author}") - keys.add(it.name) - } - keys }.catch { - AppLog.put("发现列表界面获取书籍数据失败\n${it.localizedMessage}", it) - }.collect { + AppLog.put("搜索界面获取书籍列表失败\n${it.localizedMessage}", it) + }.collect { books -> bookshelf.clear() - bookshelf.addAll(it) + bookshelf.addAll(books.map { BookKey(it.name, it.author, it.bookUrl) }) upAdapterLiveData.postValue("isInBookshelf") } }.onError { @@ -82,12 +78,14 @@ class ExploreShowViewModel(application: Application) : BaseViewModel(application } } - fun isInBookShelf(name: String, author: String): Boolean { - return if (author.isNotBlank()) { - bookshelf.contains("$name-$author") - } else { - bookshelf.contains(name) - } + fun isInBookShelf(name: String, author: String, url: String?): BookShelfState { + val exactMatch = bookshelf.any { it.name == name && it.author == author && it.url == url } + if (exactMatch) return BookShelfState.IN_SHELF + + val sameNameAuthor = bookshelf.any { it.name == name && it.author == author && it.url != url } + if (sameNameAuthor) return BookShelfState.SAME_NAME_AUTHOR + + return BookShelfState.NOT_IN_SHELF } } diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt index 554575481..06d4b2293 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt @@ -576,8 +576,8 @@ class SearchActivity : VMBaseActivity { + 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) @@ -110,8 +121,21 @@ class SearchAdapter(context: Context, val callBack: CallBack) : "last" -> upLasted(binding, searchBook.latestChapterTitle) "intro" -> tvIntroduce.text = searchBook.trimIntro(context) "kind" -> upKind(binding, searchBook.getKindList()) - "isInBookshelf" -> ivInBookshelf.isVisible = - callBack.isInBookshelf(searchBook.name, searchBook.author) + "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, @@ -165,7 +189,7 @@ class SearchAdapter(context: Context, val callBack: CallBack) : /** * 是否已经加入书架 */ - fun isInBookshelf(name: String, author: String): Boolean + fun getBookShelfState(name: String, author: String, url: String?): BookShelfState /** * 显示书籍详情 diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt index 0be104149..14369decb 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt @@ -20,10 +20,18 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.mapLatest import java.util.concurrent.ConcurrentHashMap +enum class BookShelfState { + IN_SHELF, + SAME_NAME_AUTHOR, + NOT_IN_SHELF +} + +data class BookKey(val name: String, val author: String, val url: String?) + @OptIn(ExperimentalCoroutinesApi::class) class SearchViewModel(application: Application) : BaseViewModel(application) { val handler = Handler(Looper.getMainLooper()) - val bookshelf: MutableSet = ConcurrentHashMap.newKeySet() + val bookshelf: MutableSet = ConcurrentHashMap.newKeySet() val upAdapterLiveData = MutableLiveData() var searchBookLiveData = ConflateLiveData>(1000) val searchScope: SearchScope = SearchScope(AppConfig.searchScope) @@ -70,18 +78,12 @@ class SearchViewModel(application: Application) : BaseViewModel(application) { init { execute { appDb.bookDao.flowAll().mapLatest { books -> - val keys = arrayListOf() books.filterNot { it.isNotShelf } - .forEach { - keys.add("${it.name}-${it.author}") - keys.add(it.name) - } - keys }.catch { AppLog.put("搜索界面获取书籍列表失败\n${it.localizedMessage}", it) - }.collect { + }.collect { books -> bookshelf.clear() - bookshelf.addAll(it) + bookshelf.addAll(books.map { BookKey(it.name, it.author, it.bookUrl) }) upAdapterLiveData.postValue("isInBookshelf") } }.onError { @@ -89,12 +91,14 @@ class SearchViewModel(application: Application) : BaseViewModel(application) { } } - fun isInBookShelf(name: String, author: String): Boolean { - return if (author.isNotBlank()) { - bookshelf.contains("$name-$author") - } else { - bookshelf.contains(name) - } + fun isInBookShelf(name: String, author: String, url: String?): BookShelfState { + val exactMatch = bookshelf.any { it.name == name && it.author == author && it.url == url } + if (exactMatch) return BookShelfState.IN_SHELF + + val sameNameAuthor = bookshelf.any { it.name == name && it.author == author && it.url != url } + if (sameNameAuthor) return BookShelfState.SAME_NAME_AUTHOR + + return BookShelfState.NOT_IN_SHELF } /** diff --git a/app/src/main/res/layout/item_search.xml b/app/src/main/res/layout/item_search.xml index d7711ab75..55fd36401 100644 --- a/app/src/main/res/layout/item_search.xml +++ b/app/src/main/res/layout/item_search.xml @@ -49,6 +49,7 @@ app:strokeWidth="0dp">