mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化
This commit is contained in:
@@ -30,7 +30,7 @@ interface SearchBookDao {
|
||||
t1.wordCount, t2.customOrder as originOrder
|
||||
from searchBooks as t1 inner join book_sources as t2
|
||||
on t1.origin = t2.bookSourceUrl
|
||||
where t1.name = :name and t1.author = :author
|
||||
where t1.name = :name and t1.author like '%'||:author||'%'
|
||||
and originName like '%'||:key||'%' and t2.enabled = 1
|
||||
and t2.bookSourceGroup like '%'||:sourceGroup||'%'
|
||||
order by t2.customOrder"""
|
||||
|
||||
@@ -14,7 +14,6 @@ import io.legado.app.utils.applyTint
|
||||
import io.legado.app.utils.setLayout
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
@@ -67,7 +66,6 @@ class ChangeCoverDialog() : BaseDialogFragment(R.layout.dialog_change_cover),
|
||||
private fun initData() {
|
||||
launch {
|
||||
viewModel.dataFlow
|
||||
.conflate()
|
||||
.collect {
|
||||
adapter.setItems(it)
|
||||
delay(1000)
|
||||
|
||||
@@ -18,6 +18,7 @@ import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.math.min
|
||||
@@ -54,7 +55,8 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application
|
||||
searchBooks.clear()
|
||||
searchSuccess = null
|
||||
}
|
||||
}.flowOn(IO)
|
||||
}.conflate()
|
||||
.flowOn(IO)
|
||||
|
||||
@Volatile
|
||||
private var searchIndex = -1
|
||||
|
||||
@@ -51,7 +51,6 @@ class ChangeSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
||||
viewModel.startSearch()
|
||||
}
|
||||
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setLayout(0.9f, 0.9f)
|
||||
@@ -65,7 +64,6 @@ class ChangeSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
||||
initRecyclerView()
|
||||
initSearchView()
|
||||
initLiveData()
|
||||
viewModel.loadDbSearchBook()
|
||||
}
|
||||
|
||||
private fun showTitle() {
|
||||
@@ -143,10 +141,11 @@ class ChangeSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
||||
}
|
||||
binding.toolBar.menu.applyTint(requireContext())
|
||||
}
|
||||
viewModel.searchBooksLiveData.observe(viewLifecycleOwner) {
|
||||
adapter.setItems(it)
|
||||
}
|
||||
launch {
|
||||
viewModel.searchDataFlow
|
||||
.collect {
|
||||
adapter.setItems(it)
|
||||
}
|
||||
appDb.bookSourceDao.flowGroupEnabled().collect {
|
||||
groups.clear()
|
||||
it.map { group ->
|
||||
@@ -165,7 +164,7 @@ class ChangeSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
||||
R.id.menu_check_author -> {
|
||||
AppConfig.changeSourceCheckAuthor = !item.isChecked
|
||||
item.isChecked = !item.isChecked
|
||||
viewModel.loadDbSearchBook()
|
||||
viewModel.refresh()
|
||||
}
|
||||
R.id.menu_load_toc -> {
|
||||
putPrefBoolean(PreferKey.changeSourceLoadToc, !item.isChecked)
|
||||
@@ -186,7 +185,7 @@ class ChangeSourceDialog() : BaseDialogFragment(R.layout.dialog_change_source),
|
||||
putPrefString("searchGroup", item.title.toString())
|
||||
}
|
||||
viewModel.startOrStopSearch()
|
||||
viewModel.loadDbSearchBook()
|
||||
viewModel.refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,18 @@ import io.legado.app.help.coroutine.CompositeCoroutine
|
||||
import io.legado.app.model.webBook.WebBook
|
||||
import io.legado.app.utils.getPrefBoolean
|
||||
import io.legado.app.utils.getPrefString
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.ExecutorCoroutineDispatcher
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import splitties.init.appCtx
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -30,17 +36,56 @@ import kotlin.math.min
|
||||
class ChangeSourceViewModel(application: Application) : BaseViewModel(application) {
|
||||
private val threadCount = AppConfig.threadCount
|
||||
private var searchPool: ExecutorCoroutineDispatcher? = null
|
||||
private var upAdapterJob: Job? = null
|
||||
val searchStateData = MutableLiveData<Boolean>()
|
||||
val searchBooksLiveData = MutableLiveData<List<SearchBook>>()
|
||||
var name: String = ""
|
||||
var author: String = ""
|
||||
private var tasks = CompositeCoroutine()
|
||||
private var screenKey: String = ""
|
||||
private var bookSourceList = arrayListOf<BookSource>()
|
||||
private val searchBooks = CopyOnWriteArraySet<SearchBook>()
|
||||
private var postTime = 0L
|
||||
private val searchBooks = CopyOnWriteArrayList<SearchBook>()
|
||||
private val searchGroup get() = appCtx.getPrefString("searchGroup") ?: ""
|
||||
private var searchCallback: SourceCallback? = null
|
||||
val searchDataFlow = callbackFlow {
|
||||
|
||||
searchCallback = object : SourceCallback {
|
||||
|
||||
override fun searchSuccess(searchBook: SearchBook) {
|
||||
appDb.searchBookDao.insert(searchBook)
|
||||
val index = searchBooks.indexOf(searchBook)
|
||||
when {
|
||||
index >= 0 -> searchBooks[index] = searchBook
|
||||
screenKey.isEmpty() -> searchBooks.add(searchBook)
|
||||
searchBook.name.contains(screenKey) -> searchBooks.add(searchBook)
|
||||
else -> return
|
||||
}
|
||||
trySend(searchBooks)
|
||||
}
|
||||
|
||||
override fun upAdapter() {
|
||||
trySend(searchBooks)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getDbSearchBooks().let {
|
||||
searchBooks.clear()
|
||||
searchBooks.addAll(it)
|
||||
trySend(searchBooks)
|
||||
}
|
||||
|
||||
if (searchBooks.size <= 1) {
|
||||
startSearch()
|
||||
}
|
||||
|
||||
awaitClose {
|
||||
searchCallback = null
|
||||
}
|
||||
}.conflate()
|
||||
.map {
|
||||
val data = searchBooks.sortedBy { it.originOrder }
|
||||
delay(1000)
|
||||
data
|
||||
}.flowOn(IO)
|
||||
|
||||
@Volatile
|
||||
private var searchIndex = -1
|
||||
@@ -62,56 +107,19 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
searchIndex = -1
|
||||
}
|
||||
|
||||
fun loadDbSearchBook() {
|
||||
execute {
|
||||
fun refresh() {
|
||||
getDbSearchBooks().let {
|
||||
searchBooks.clear()
|
||||
upAdapter()
|
||||
val sbs = if (AppConfig.changeSourceCheckAuthor) {
|
||||
appDb.searchBookDao.getChangeSourceSearch(name, author, searchGroup)
|
||||
} else {
|
||||
appDb.searchBookDao.getChangeSourceSearch(name, "", searchGroup)
|
||||
}
|
||||
searchBooks.addAll(sbs)
|
||||
searchBooksLiveData.postValue(searchBooks.toList())
|
||||
if (sbs.size <= 1) {
|
||||
startSearch()
|
||||
}
|
||||
searchBooks.addAll(it)
|
||||
searchCallback?.upAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
@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 searchFinish(searchBook: SearchBook) {
|
||||
if (searchBooks.contains(searchBook)) return
|
||||
appDb.searchBookDao.insert(searchBook)
|
||||
if (screenKey.isEmpty()) {
|
||||
searchBooks.add(searchBook)
|
||||
} else if (searchBook.name.contains(screenKey)) {
|
||||
searchBooks.add(searchBook)
|
||||
}
|
||||
upAdapter()
|
||||
}
|
||||
|
||||
fun startSearch() {
|
||||
execute {
|
||||
stopSearch()
|
||||
appDb.searchBookDao.clear(name, author)
|
||||
searchBooks.clear()
|
||||
upAdapter()
|
||||
bookSourceList.clear()
|
||||
if (searchGroup.isBlank()) {
|
||||
bookSourceList.addAll(appDb.bookSourceDao.allEnabled)
|
||||
@@ -152,10 +160,10 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
if (AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) {
|
||||
loadBookInfo(source, searchBook.toBook())
|
||||
} else {
|
||||
searchFinish(searchBook)
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
} else {
|
||||
searchFinish(searchBook)
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,7 +198,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
//从详情页里获取最新章节
|
||||
book.latestChapterTitle = it.latestChapterTitle
|
||||
val searchBook = book.toSearchBook()
|
||||
searchFinish(searchBook)
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}
|
||||
}.onError {
|
||||
Timber.e(it)
|
||||
@@ -202,26 +210,38 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
.onSuccess(IO) { chapters ->
|
||||
book.latestChapterTitle = chapters.last().title
|
||||
val searchBook: SearchBook = book.toSearchBook()
|
||||
searchFinish(searchBook)
|
||||
searchCallback?.searchSuccess(searchBook)
|
||||
}.onError {
|
||||
Timber.e(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDbSearchBooks(): List<SearchBook> {
|
||||
return if (screenKey.isEmpty()) {
|
||||
if (AppConfig.changeSourceCheckAuthor) {
|
||||
appDb.searchBookDao.getChangeSourceSearch(name, author, searchGroup)
|
||||
} else {
|
||||
appDb.searchBookDao.getChangeSourceSearch(name, "", searchGroup)
|
||||
}
|
||||
} else {
|
||||
if (AppConfig.changeSourceCheckAuthor) {
|
||||
appDb.searchBookDao.getChangeSourceSearch(name, author, screenKey, searchGroup)
|
||||
} else {
|
||||
appDb.searchBookDao.getChangeSourceSearch(name, "", screenKey, searchGroup)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选
|
||||
*/
|
||||
fun screen(key: String?) {
|
||||
screenKey = key?.trim() ?: ""
|
||||
execute {
|
||||
screenKey = key ?: ""
|
||||
if (key.isNullOrEmpty()) {
|
||||
loadDbSearchBook()
|
||||
} else {
|
||||
val items =
|
||||
appDb.searchBookDao.getChangeSourceSearch(name, author, screenKey, searchGroup)
|
||||
getDbSearchBooks().let {
|
||||
searchBooks.clear()
|
||||
searchBooks.addAll(items)
|
||||
upAdapter()
|
||||
searchBooks.addAll(it)
|
||||
searchCallback?.upAdapter()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,7 +272,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
appDb.bookSourceDao.update(source)
|
||||
}
|
||||
searchBooks.remove(searchBook)
|
||||
upAdapter()
|
||||
searchCallback?.upAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +285,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
appDb.bookSourceDao.update(source)
|
||||
updateSource(searchBook)
|
||||
}
|
||||
upAdapter()
|
||||
searchCallback?.upAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +298,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
appDb.bookSourceDao.update(source)
|
||||
updateSource(searchBook)
|
||||
}
|
||||
upAdapter()
|
||||
searchCallback?.upAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,11 +314,19 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
|
||||
}
|
||||
}
|
||||
searchBooks.remove(searchBook)
|
||||
upAdapter()
|
||||
searchCallback?.upAdapter()
|
||||
}
|
||||
|
||||
fun firstSourceOrNull(searchBook: SearchBook): SearchBook? {
|
||||
return searchBooks.firstOrNull { it.bookUrl != searchBook.bookUrl }
|
||||
}
|
||||
|
||||
interface SourceCallback {
|
||||
|
||||
fun searchSuccess(searchBook: SearchBook)
|
||||
|
||||
fun upAdapter()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user