修复发现页书源互相污染的问题
This commit is contained in:
@@ -5,8 +5,10 @@ import io.legado.app.data.entities.BookSource
|
|||||||
import io.legado.app.data.entities.BookSourcePart
|
import io.legado.app.data.entities.BookSourcePart
|
||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.data.entities.rule.ExploreKind
|
import io.legado.app.data.entities.rule.ExploreKind
|
||||||
|
import io.legado.app.domain.gateway.ExploreBooksGateway
|
||||||
import io.legado.app.help.source.SourceHelp
|
import io.legado.app.help.source.SourceHelp
|
||||||
import io.legado.app.help.source.exploreKinds
|
import io.legado.app.help.source.exploreKinds
|
||||||
|
import io.legado.app.model.webBook.WebBook
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@@ -16,7 +18,7 @@ interface ExploreRepository {
|
|||||||
fun getBookshelfItems(): Flow<List<SearchBook>>
|
fun getBookshelfItems(): Flow<List<SearchBook>>
|
||||||
fun getExploreGroups(): Flow<List<String>>
|
fun getExploreGroups(): Flow<List<String>>
|
||||||
fun getExploreSources(query: String, selectedGroup: String): Flow<List<BookSourcePart>>
|
fun getExploreSources(query: String, selectedGroup: String): Flow<List<BookSourcePart>>
|
||||||
suspend fun getBookSource(url: String): BookSource?
|
suspend fun getBookSource(sourceUrl: String): BookSource?
|
||||||
suspend fun saveSearchBooks(books: List<SearchBook>)
|
suspend fun saveSearchBooks(books: List<SearchBook>)
|
||||||
suspend fun getSourceExploreKinds(sourceUrl: String): List<ExploreKind>
|
suspend fun getSourceExploreKinds(sourceUrl: String): List<ExploreKind>
|
||||||
suspend fun topSource(bookSource: BookSourcePart)
|
suspend fun topSource(bookSource: BookSourcePart)
|
||||||
@@ -25,7 +27,7 @@ interface ExploreRepository {
|
|||||||
|
|
||||||
class ExploreRepositoryImpl(
|
class ExploreRepositoryImpl(
|
||||||
private val appDb: AppDatabase
|
private val appDb: AppDatabase
|
||||||
) : ExploreRepository {
|
) : ExploreRepository, ExploreBooksGateway {
|
||||||
|
|
||||||
override fun getBookshelfItems(): Flow<List<SearchBook>> {
|
override fun getBookshelfItems(): Flow<List<SearchBook>> {
|
||||||
return appDb.bookDao.flowBookShelf().map { books ->
|
return appDb.bookDao.flowBookShelf().map { books ->
|
||||||
@@ -71,8 +73,16 @@ class ExploreRepositoryImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getBookSource(url: String): BookSource? {
|
override suspend fun getBookSource(sourceUrl: String): BookSource? {
|
||||||
return appDb.bookSourceDao.getBookSource(url)
|
return appDb.bookSourceDao.getBookSource(sourceUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun exploreBooks(
|
||||||
|
bookSource: BookSource,
|
||||||
|
url: String,
|
||||||
|
page: Int
|
||||||
|
): List<SearchBook> {
|
||||||
|
return WebBook.exploreBookSuspend(bookSource, url, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getSourceExploreKinds(sourceUrl: String): List<ExploreKind> = withContext(IO) {
|
override suspend fun getSourceExploreKinds(sourceUrl: String): List<ExploreKind> = withContext(IO) {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import io.legado.app.domain.gateway.BookCacheDownloadGateway
|
|||||||
import io.legado.app.domain.gateway.BookSearchGateway
|
import io.legado.app.domain.gateway.BookSearchGateway
|
||||||
import io.legado.app.domain.gateway.BookSourceCallbackGateway
|
import io.legado.app.domain.gateway.BookSourceCallbackGateway
|
||||||
import io.legado.app.domain.gateway.DatabaseMaintenanceGateway
|
import io.legado.app.domain.gateway.DatabaseMaintenanceGateway
|
||||||
|
import io.legado.app.domain.gateway.ExploreBooksGateway
|
||||||
import io.legado.app.domain.gateway.HomepageModulesGateway
|
import io.legado.app.domain.gateway.HomepageModulesGateway
|
||||||
import io.legado.app.domain.gateway.LocalBookGateway
|
import io.legado.app.domain.gateway.LocalBookGateway
|
||||||
import io.legado.app.domain.gateway.ReadingProgressGateway
|
import io.legado.app.domain.gateway.ReadingProgressGateway
|
||||||
@@ -173,7 +174,9 @@ val appModule = module {
|
|||||||
single<ReadingProgressGateway> { WebDavReadingProgressRepository() }
|
single<ReadingProgressGateway> { WebDavReadingProgressRepository() }
|
||||||
single<HomepageModulesGateway> { HomepageModulesRepository(get(), get()) }
|
single<HomepageModulesGateway> { HomepageModulesRepository(get(), get()) }
|
||||||
single<BookDomainRepository> { BookDomainRepositoryImpl(get(), get()) }
|
single<BookDomainRepository> { BookDomainRepositoryImpl(get(), get()) }
|
||||||
single<ExploreRepository> { ExploreRepositoryImpl(get()) }
|
single { ExploreRepositoryImpl(get()) }
|
||||||
|
single<ExploreRepository> { get<ExploreRepositoryImpl>() }
|
||||||
|
single<ExploreBooksGateway> { get<ExploreRepositoryImpl>() }
|
||||||
singleOf(::RssRepository)
|
singleOf(::RssRepository)
|
||||||
single {
|
single {
|
||||||
SearchRepositoryImpl(get())
|
SearchRepositoryImpl(get())
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package io.legado.app.domain.gateway
|
||||||
|
|
||||||
|
import io.legado.app.data.entities.BookSource
|
||||||
|
import io.legado.app.data.entities.SearchBook
|
||||||
|
|
||||||
|
interface ExploreBooksGateway {
|
||||||
|
suspend fun getBookSource(sourceUrl: String): BookSource?
|
||||||
|
suspend fun exploreBooks(bookSource: BookSource, url: String, page: Int): List<SearchBook>
|
||||||
|
}
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
package io.legado.app.domain.usecase
|
package io.legado.app.domain.usecase
|
||||||
|
|
||||||
import io.legado.app.data.entities.SearchBook
|
import io.legado.app.data.entities.SearchBook
|
||||||
import io.legado.app.data.repository.BookSourceRepository
|
import io.legado.app.domain.gateway.ExploreBooksGateway
|
||||||
import io.legado.app.model.webBook.WebBook
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class ExploreBooksUseCase(
|
class ExploreBooksUseCase(
|
||||||
private val bookSourceRepository: BookSourceRepository,
|
private val gateway: ExploreBooksGateway,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
/** 排名类模块自动加载的最大书本数 */
|
/** 排名类模块自动加载的最大书本数 */
|
||||||
@@ -23,18 +22,12 @@ class ExploreBooksUseCase(
|
|||||||
args: String?,
|
args: String?,
|
||||||
page: Int = 1
|
page: Int = 1
|
||||||
): ExploreResult = withContext(Dispatchers.IO) {
|
): ExploreResult = withContext(Dispatchers.IO) {
|
||||||
val base = bookSourceRepository.getBookSource(sourceUrl)
|
val base = gateway.getBookSource(sourceUrl)
|
||||||
?: throw SourceNotFound(sourceUrl)
|
?: throw SourceNotFound(sourceUrl)
|
||||||
val source = args?.let { base.copy().also { s -> s.setVariable(it) } } ?: base
|
val source = args?.let { base.copy().also { s -> s.setVariable(it) } } ?: base
|
||||||
val resolvedUrl = moduleUrl ?: source.exploreUrl
|
val resolvedUrl = moduleUrl ?: source.exploreUrl
|
||||||
?: throw NoExploreUrl(sourceUrl)
|
?: throw NoExploreUrl(sourceUrl)
|
||||||
if (!resolvedUrl.startsWith("http", ignoreCase = true)
|
val books = gateway.exploreBooks(source, resolvedUrl, page)
|
||||||
&& !resolvedUrl.startsWith("data:", ignoreCase = true)
|
|
||||||
&& !resolvedUrl.startsWith("{{")
|
|
||||||
) {
|
|
||||||
throw InvalidUrl(resolvedUrl)
|
|
||||||
}
|
|
||||||
val books = WebBook.exploreBookSuspend(source, resolvedUrl, page)
|
|
||||||
ExploreResult(resolvedUrl, books)
|
ExploreResult(resolvedUrl, books)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,13 +42,10 @@ class ExploreBooksUseCase(
|
|||||||
while (books.size < MAX_RANKING_BOOKS && page < MAX_RANKING_PAGES) {
|
while (books.size < MAX_RANKING_BOOKS && page < MAX_RANKING_PAGES) {
|
||||||
page++
|
page++
|
||||||
val next = try {
|
val next = try {
|
||||||
WebBook.exploreBookSuspend(
|
val source = gateway.getBookSource(sourceUrl)
|
||||||
bookSourceRepository.getBookSource(sourceUrl)
|
?.let { s -> args?.let { s.copy().also { x -> x.setVariable(it) } } ?: s }
|
||||||
?.let { s -> args?.let { s.copy().also { x -> x.setVariable(it) } } ?: s }
|
?: return@withContext books.take(MAX_RANKING_BOOKS)
|
||||||
?: return@withContext books.take(MAX_RANKING_BOOKS),
|
gateway.exploreBooks(source, result.resolvedUrl, page)
|
||||||
result.resolvedUrl,
|
|
||||||
page,
|
|
||||||
)
|
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
@@ -69,5 +59,4 @@ class ExploreBooksUseCase(
|
|||||||
|
|
||||||
class SourceNotFound(url: String) : Exception("Source not found: ${url.take(60)}")
|
class SourceNotFound(url: String) : Exception("Source not found: ${url.take(60)}")
|
||||||
class NoExploreUrl(url: String) : Exception("No explore URL for source: ${url.take(60)}")
|
class NoExploreUrl(url: String) : Exception("No explore URL for source: ${url.take(60)}")
|
||||||
class InvalidUrl(url: String) : Exception("Invalid explore URL: ${url.take(80)}")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ class ExploreShowViewModel(
|
|||||||
sourceUrl = incomingSourceUrl
|
sourceUrl = incomingSourceUrl
|
||||||
exploreUrl = incomingExploreUrl
|
exploreUrl = incomingExploreUrl
|
||||||
page = 1
|
page = 1
|
||||||
|
bookSource = null
|
||||||
_rawBooks.value = emptyList()
|
_rawBooks.value = emptyList()
|
||||||
_isEndStateFlow.value = false
|
_isEndStateFlow.value = false
|
||||||
_errorMsg.value = null
|
_errorMsg.value = null
|
||||||
|
|||||||
Reference in New Issue
Block a user