pull/1649/head
kunfei 3 years ago
parent c47190b30b
commit 6e3b74f3b0
  1. 20
      app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverDialog.kt
  2. 83
      app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt

@ -13,6 +13,9 @@ import io.legado.app.lib.theme.primaryColor
import io.legado.app.utils.applyTint import io.legado.app.utils.applyTint
import io.legado.app.utils.setLayout import io.legado.app.utils.setLayout
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.launch
class ChangeCoverDialog() : BaseDialogFragment(R.layout.dialog_change_cover), class ChangeCoverDialog() : BaseDialogFragment(R.layout.dialog_change_cover),
@ -45,6 +48,7 @@ class ChangeCoverDialog() : BaseDialogFragment(R.layout.dialog_change_cover),
viewModel.initData(arguments) viewModel.initData(arguments)
initMenu() initMenu()
initView() initView()
initData()
} }
private fun initMenu() { private fun initMenu() {
@ -56,7 +60,17 @@ class ChangeCoverDialog() : BaseDialogFragment(R.layout.dialog_change_cover),
private fun initView() { private fun initView() {
binding.recyclerView.layoutManager = GridLayoutManager(requireContext(), 3) binding.recyclerView.layoutManager = GridLayoutManager(requireContext(), 3)
binding.recyclerView.adapter = adapter binding.recyclerView.adapter = adapter
viewModel.loadDbSearchBook() }
private fun initData() {
launch {
viewModel.dataFlow
.conflate()
.collect {
adapter.setItems(it)
delay(1000)
}
}
} }
override fun observeLiveBus() { override fun observeLiveBus() {
@ -76,9 +90,7 @@ class ChangeCoverDialog() : BaseDialogFragment(R.layout.dialog_change_cover),
} }
binding.toolBar.menu.applyTint(requireContext()) binding.toolBar.menu.applyTint(requireContext())
} }
viewModel.searchBooksLiveData.observe(viewLifecycleOwner) {
adapter.setItems(it)
}
} }
override fun onMenuItemClick(item: MenuItem?): Boolean { override fun onMenuItemClick(item: MenuItem?): Boolean {

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

Loading…
Cancel
Save