|
|
@@ -13,23 +13,48 @@ import io.legado.app.data.entities.SearchBook
|
|
|
import io.legado.app.help.AppConfig
|
|
|
import io.legado.app.help.coroutine.CompositeCoroutine
|
|
|
import io.legado.app.model.webBook.WebBook
|
|
|
-import kotlinx.coroutines.*
|
|
|
-import java.util.concurrent.CopyOnWriteArraySet
|
|
|
+import kotlinx.coroutines.Dispatchers.IO
|
|
|
+import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
|
|
+import kotlinx.coroutines.asCoroutineDispatcher
|
|
|
+import kotlinx.coroutines.channels.awaitClose
|
|
|
+import kotlinx.coroutines.channels.trySendBlocking
|
|
|
+import kotlinx.coroutines.flow.callbackFlow
|
|
|
import java.util.concurrent.Executors
|
|
|
import kotlin.math.min
|
|
|
|
|
|
class ChangeCoverViewModel(application: Application) : BaseViewModel(application) {
|
|
|
private val threadCount = AppConfig.threadCount
|
|
|
private var searchPool: ExecutorCoroutineDispatcher? = null
|
|
|
- private var upAdapterJob: Job? = null
|
|
|
- var name: String = ""
|
|
|
- var author: String = ""
|
|
|
- private var tasks = CompositeCoroutine()
|
|
|
+ private val tasks = CompositeCoroutine()
|
|
|
+ private var searchSuccess: ((SearchBook) -> Unit)? = null
|
|
|
private var bookSourceList = arrayListOf<BookSource>()
|
|
|
val searchStateData = MutableLiveData<Boolean>()
|
|
|
- val searchBooksLiveData = MutableLiveData<List<SearchBook>>()
|
|
|
- private val searchBooks = CopyOnWriteArraySet<SearchBook>()
|
|
|
- private var postTime = 0L
|
|
|
+ var name: String = ""
|
|
|
+ var author: String = ""
|
|
|
+ val dataFlow = callbackFlow<List<SearchBook>> {
|
|
|
+ val searchBooks = arrayListOf<SearchBook>()
|
|
|
+
|
|
|
+ searchSuccess = {
|
|
|
+ if (!searchBooks.contains(it)) {
|
|
|
+ searchBooks.add(it)
|
|
|
+ trySendBlocking(searchBooks)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ appDb.searchBookDao.getEnableHasCover(name, author).let {
|
|
|
+ searchBooks.addAll(it)
|
|
|
+ trySendBlocking(searchBooks)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (searchBooks.size <= 1) {
|
|
|
+ startSearch()
|
|
|
+ }
|
|
|
+
|
|
|
+ awaitClose {
|
|
|
+ searchBooks.clear()
|
|
|
+ searchSuccess = null
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
@Volatile
|
|
|
private var searchIndex = -1
|
|
|
@@ -51,34 +76,6 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application
|
|
|
searchIndex = -1
|
|
|
}
|
|
|
|
|
|
- fun loadDbSearchBook() {
|
|
|
- execute {
|
|
|
- appDb.searchBookDao.getEnableHasCover(name, author).let {
|
|
|
- searchBooks.addAll(it)
|
|
|
- searchBooksLiveData.postValue(searchBooks.toList())
|
|
|
- if (it.size <= 1) {
|
|
|
- startSearch()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Synchronized
|
|
|
- private fun upAdapter() {
|
|
|
- if (System.currentTimeMillis() >= postTime + 500) {
|
|
|
- upAdapterJob?.cancel()
|
|
|
- postTime = System.currentTimeMillis()
|
|
|
- val books = searchBooks.toList()
|
|
|
- searchBooksLiveData.postValue(books.sortedBy { it.originOrder })
|
|
|
- } else {
|
|
|
- upAdapterJob?.cancel()
|
|
|
- upAdapterJob = viewModelScope.launch {
|
|
|
- delay(500)
|
|
|
- upAdapter()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private fun startSearch() {
|
|
|
execute {
|
|
|
stopSearch()
|
|
|
@@ -106,17 +103,13 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application
|
|
|
val task = WebBook
|
|
|
.searchBook(viewModelScope, source, name, context = searchPool!!)
|
|
|
.timeout(60000L)
|
|
|
- .onSuccess(searchPool) {
|
|
|
- if (it.isNotEmpty()) {
|
|
|
- val searchBook = it[0]
|
|
|
+ .onSuccess(IO) {
|
|
|
+ it.firstOrNull()?.let { searchBook ->
|
|
|
if (searchBook.name == name && searchBook.author == author
|
|
|
&& !searchBook.coverUrl.isNullOrEmpty()
|
|
|
) {
|
|
|
appDb.searchBookDao.insert(searchBook)
|
|
|
- if (!searchBooks.contains(searchBook)) {
|
|
|
- searchBooks.add(searchBook)
|
|
|
- upAdapter()
|
|
|
- }
|
|
|
+ searchSuccess?.invoke(searchBook)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -151,7 +144,7 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fun stopSearch() {
|
|
|
+ private fun stopSearch() {
|
|
|
tasks.clear()
|
|
|
searchPool?.close()
|
|
|
searchStateData.postValue(false)
|