替换规则界面排序功能

This commit is contained in:
HapeLee
2025-11-01 16:12:03 +08:00
parent fecf52f211
commit 7c151e1b86
6 changed files with 155 additions and 32 deletions
@@ -22,6 +22,55 @@ interface ReplaceRuleDao {
@Query("SELECT * FROM replace_rules ORDER BY sortOrder ASC")
fun flowAll(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules ORDER BY sortOrder ASC")
fun flowAllAsc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules ORDER BY sortOrder DESC")
fun flowAllDesc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules ORDER BY name COLLATE NOCASE ASC")
fun flowAllNameAsc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules ORDER BY name COLLATE NOCASE DESC")
fun flowAllNameDesc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key OR name LIKE :key ORDER BY sortOrder ASC")
fun flowSearchAsc(key: String): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key OR name LIKE :key ORDER BY sortOrder DESC")
fun flowSearchDesc(key: String): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key OR name LIKE :key ORDER BY name COLLATE NOCASE ASC")
fun flowSearchNameAsc(key: String): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key OR name LIKE :key ORDER BY name COLLATE NOCASE DESC")
fun flowSearchNameDesc(key: String): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key ORDER BY sortOrder ASC")
fun flowGroupSearchAsc(key: String): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key ORDER BY sortOrder DESC")
fun flowGroupSearchDesc(key: String): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key ORDER BY name COLLATE NOCASE ASC")
fun flowGroupSearchNameAsc(key: String): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` LIKE :key ORDER BY name COLLATE NOCASE DESC")
fun flowGroupSearchNameDesc(key: String): Flow<List<ReplaceRule>>
// === 未分组 ===
@Query("SELECT * FROM replace_rules WHERE `group` IS NULL OR trim(`group`) = '' OR trim(`group`) LIKE '%未分组%' ORDER BY sortOrder ASC")
fun flowNoGroupAsc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` IS NULL OR trim(`group`) = '' OR trim(`group`) LIKE '%未分组%' ORDER BY sortOrder DESC")
fun flowNoGroupDesc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` IS NULL OR trim(`group`) = '' OR trim(`group`) LIKE '%未分组%' ORDER BY name COLLATE NOCASE ASC")
fun flowNoGroupNameAsc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules WHERE `group` IS NULL OR trim(`group`) = '' OR trim(`group`) LIKE '%未分组%' ORDER BY name COLLATE NOCASE DESC")
fun flowNoGroupNameDesc(): Flow<List<ReplaceRule>>
@Query("SELECT * FROM replace_rules where `group` like :key or name like :key ORDER BY sortOrder ASC")
fun flowSearch(key: String): Flow<List<ReplaceRule>>
@@ -50,6 +50,7 @@ import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
@@ -71,8 +72,9 @@ class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRu
}
private var groups = arrayListOf<String>()
private var groupMenu: SubMenu? = null
private var replaceRuleFlowJob: Job? = null
private var dataInit = false
private var sortMode = "desc"
private var searchKey: String? = null
private val qrCodeResult = registerForActivityResult(QrCodeResult()) {
it ?: return@registerForActivityResult
showDialogFragment(
@@ -197,35 +199,10 @@ class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRu
binding.selectActionBar.setCallBack(this)
}
private fun observeReplaceRuleData(searchKey: String? = null) {
dataInit = false
replaceRuleFlowJob?.cancel()
replaceRuleFlowJob = lifecycleScope.launch {
when {
searchKey.isNullOrEmpty() -> {
appDb.replaceRuleDao.flowAll()
}
searchKey == getString(R.string.no_group) -> {
appDb.replaceRuleDao.flowNoGroup()
}
searchKey.startsWith("group:") -> {
val key = searchKey.substringAfter("group:")
appDb.replaceRuleDao.flowGroupSearch("%$key%")
}
else -> {
appDb.replaceRuleDao.flowSearch("%$searchKey%")
}
}.catch {
AppLog.put("替换规则管理界面更新数据出错", it)
}.flowOn(IO).conflate().collect {
if (dataInit) {
setResult(RESULT_OK)
}
adapter.setItems(it, adapter.diffItemCallBack)
dataInit = true
delay(100)
private fun observeReplaceRuleData() {
lifecycleScope.launch {
viewModel.rulesFlow.collectLatest { rules ->
adapter.setItems(rules, adapter.diffItemCallBack)
}
}
}
@@ -256,10 +233,16 @@ class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRu
R.id.menu_group_null -> {
searchView.setQuery(getString(R.string.no_group), true)
}
R.id.sort_order_asc -> viewModel.setSortMode("asc")
R.id.sort_order_desc -> viewModel.setSortMode("desc")
R.id.sort_name_asc -> viewModel.setSortMode("name_asc")
R.id.sort_name_desc -> viewModel.setSortMode("name_desc")
else -> if (item.groupId == R.id.replace_group) {
searchView.setQuery("group:${item.title}", true)
viewModel.setSearchKey("group:${item.title}")
}
}
observeReplaceRuleData()
return super.onCompatOptionsItemSelected(item)
}
@@ -322,7 +305,8 @@ class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRu
}
override fun onQueryTextChange(newText: String?): Boolean {
observeReplaceRuleData(newText)
searchKey = newText
viewModel.setSearchKey(newText)
return false
}
@@ -2,10 +2,22 @@ package io.legado.app.ui.replace
import android.app.Application
import android.text.TextUtils
import io.legado.app.R
import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppLog
import io.legado.app.data.appDb
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.utils.splitNotBlank
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import splitties.init.appCtx
/**
* 替换规则数据修改
@@ -13,6 +25,58 @@ import io.legado.app.utils.splitNotBlank
*/
class ReplaceRuleViewModel(application: Application) : BaseViewModel(application) {
private val _sortMode = MutableStateFlow("desc")
private val _searchKey = MutableStateFlow<String?>(null)
val sortMode: StateFlow<String> = _sortMode
val searchKey: StateFlow<String?> = _searchKey
fun setSortMode(mode: String) {
_sortMode.value = mode
}
fun setSearchKey(key: String?) {
_searchKey.value = key
}
@OptIn(ExperimentalCoroutinesApi::class)
val rulesFlow = combine(_searchKey, _sortMode) { search, sort ->
Pair(search, sort)
}.flatMapLatest { (searchKey, sortMode) ->
when {
searchKey.isNullOrEmpty() -> when (sortMode) {
"asc" -> appDb.replaceRuleDao.flowAllAsc()
"name_asc" -> appDb.replaceRuleDao.flowAllNameAsc()
"name_desc" -> appDb.replaceRuleDao.flowAllNameDesc()
else -> appDb.replaceRuleDao.flowAllDesc()
}
searchKey == appCtx.getString(R.string.no_group) -> when (sortMode) {
"asc" -> appDb.replaceRuleDao.flowNoGroupAsc()
"name_asc" -> appDb.replaceRuleDao.flowNoGroupNameAsc()
"name_desc" -> appDb.replaceRuleDao.flowNoGroupNameDesc()
else -> appDb.replaceRuleDao.flowNoGroupDesc()
}
searchKey.startsWith("group:") -> {
val key = searchKey.substringAfter("group:")
when (sortMode) {
"asc" -> appDb.replaceRuleDao.flowGroupSearchAsc("%$key%")
"name_asc" -> appDb.replaceRuleDao.flowGroupSearchNameAsc("%$key%")
"name_desc" -> appDb.replaceRuleDao.flowGroupSearchNameDesc("%$key%")
else -> appDb.replaceRuleDao.flowGroupSearchDesc("%$key%")
}
}
else -> when (sortMode) {
"asc" -> appDb.replaceRuleDao.flowSearchAsc("%$searchKey%")
"name_asc" -> appDb.replaceRuleDao.flowSearchNameAsc("%$searchKey%")
"name_desc" -> appDb.replaceRuleDao.flowSearchNameDesc("%$searchKey%")
else -> appDb.replaceRuleDao.flowSearchDesc("%$searchKey%")
}
}
}.flowOn(Dispatchers.IO)
fun update(vararg rule: ReplaceRule) {
execute {
appDb.replaceRuleDao.update(*rule)