替换规则排序
This commit is contained in:
@@ -72,8 +72,6 @@ class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRu
|
||||
}
|
||||
private var groups = arrayListOf<String>()
|
||||
private var groupMenu: SubMenu? = null
|
||||
|
||||
private var sortMode = "desc"
|
||||
private var searchKey: String? = null
|
||||
private val qrCodeResult = registerForActivityResult(QrCodeResult()) {
|
||||
it ?: return@registerForActivityResult
|
||||
|
||||
@@ -16,6 +16,10 @@ import io.legado.app.databinding.ItemReplaceRuleBinding
|
||||
//import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
||||
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
||||
import io.legado.app.utils.gone
|
||||
import io.legado.app.utils.themeColor
|
||||
import io.legado.app.utils.visible
|
||||
import splitties.views.backgroundColor
|
||||
|
||||
|
||||
class ReplaceRuleAdapter(context: Context, var callBack: CallBack) :
|
||||
@@ -38,28 +42,24 @@ class ReplaceRuleAdapter(context: Context, var callBack: CallBack) :
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: ReplaceRule, newItem: ReplaceRule): Boolean {
|
||||
if (oldItem.name != newItem.name) {
|
||||
return false
|
||||
}
|
||||
if (oldItem.group != newItem.group) {
|
||||
return false
|
||||
}
|
||||
if (oldItem.isEnabled != newItem.isEnabled) {
|
||||
return false
|
||||
}
|
||||
if (oldItem.name != newItem.name) return false
|
||||
if (oldItem.group != newItem.group) return false
|
||||
if (oldItem.isEnabled != newItem.isEnabled) return false
|
||||
if (oldItem.order != newItem.order) return false // 添加 order 检查
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getChangePayload(oldItem: ReplaceRule, newItem: ReplaceRule): Any? {
|
||||
val payload = Bundle()
|
||||
if (oldItem.name != newItem.name
|
||||
|| oldItem.group != newItem.group
|
||||
) {
|
||||
if (oldItem.name != newItem.name || oldItem.group != newItem.group) {
|
||||
payload.putBoolean("upName", true)
|
||||
}
|
||||
if (oldItem.isEnabled != newItem.isEnabled) {
|
||||
payload.putBoolean("enabled", newItem.isEnabled)
|
||||
}
|
||||
if (oldItem.order != newItem.order) {
|
||||
payload.putBoolean("orderChanged", true)
|
||||
}
|
||||
if (payload.isEmpty) {
|
||||
return null
|
||||
}
|
||||
@@ -102,12 +102,9 @@ class ReplaceRuleAdapter(context: Context, var callBack: CallBack) :
|
||||
payloads: MutableList<Any>
|
||||
) {
|
||||
binding.run {
|
||||
if (payloads.isEmpty()) {
|
||||
//root.setBackgroundColor(ColorUtils.withAlpha(context.backgroundColor, 0.5f))
|
||||
cbName.text = item.getDisplayNameGroup()
|
||||
swtEnabled.isChecked = item.isEnabled
|
||||
cbName.isChecked = selected.contains(item)
|
||||
} else {
|
||||
var needUpdatePin = payloads.isEmpty()
|
||||
|
||||
if (payloads.isNotEmpty()) {
|
||||
for (i in payloads.indices) {
|
||||
val bundle = payloads[i] as Bundle
|
||||
bundle.keySet().forEach {
|
||||
@@ -115,10 +112,35 @@ class ReplaceRuleAdapter(context: Context, var callBack: CallBack) :
|
||||
"selected" -> cbName.isChecked = selected.contains(item)
|
||||
"upName" -> cbName.text = item.getDisplayNameGroup()
|
||||
"enabled" -> swtEnabled.isChecked = item.isEnabled
|
||||
"orderChanged" -> needUpdatePin = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (payloads.isEmpty() || needUpdatePin) {
|
||||
when (item.order) {
|
||||
-1 -> {
|
||||
ivPin.visible()
|
||||
ivPin.setImageResource(R.drawable.ic_praise_filled)
|
||||
ivPin.rotation = 0f
|
||||
ivPin.setColorFilter(context.themeColor(com.google.android.material.R.attr.colorSecondary))
|
||||
}
|
||||
-2 -> {
|
||||
ivPin.visible()
|
||||
ivPin.setImageResource(R.drawable.ic_praise_filled)
|
||||
ivPin.rotation = 180f
|
||||
ivPin.setColorFilter(context.themeColor(com.google.android.material.R.attr.colorSecondary))
|
||||
}
|
||||
else -> ivPin.gone()
|
||||
}
|
||||
}
|
||||
|
||||
if (payloads.isEmpty()) {
|
||||
cbName.text = item.getDisplayNameGroup()
|
||||
swtEnabled.isChecked = item.isEnabled
|
||||
cbName.isChecked = selected.contains(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +243,7 @@ class ReplaceRuleAdapter(context: Context, var callBack: CallBack) :
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface CallBack {
|
||||
|
||||
@@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import splitties.init.appCtx
|
||||
|
||||
/**
|
||||
@@ -43,39 +44,64 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application
|
||||
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()
|
||||
}
|
||||
|
||||
// 先获取基础数据
|
||||
val baseFlow = when {
|
||||
searchKey.isNullOrEmpty() -> appDb.replaceRuleDao.flowAll()
|
||||
searchKey == appCtx.getString(R.string.no_group) -> appDb.replaceRuleDao.flowNoGroup()
|
||||
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%")
|
||||
appDb.replaceRuleDao.flowGroupSearch("%$key%")
|
||||
}
|
||||
else -> appDb.replaceRuleDao.flowSearch("%$searchKey%")
|
||||
}
|
||||
|
||||
baseFlow.map { rules ->
|
||||
val comparator = when (sortMode) {
|
||||
"asc" -> Comparator<ReplaceRule> { a, b ->
|
||||
when {
|
||||
// 置顶优先
|
||||
a.order == -1 && b.order != -1 -> -1
|
||||
a.order != -1 && b.order == -1 -> 1
|
||||
// 置底最后
|
||||
a.order == -2 && b.order != -2 -> 1
|
||||
a.order != -2 && b.order == -2 -> -1
|
||||
// 普通规则按order排序
|
||||
else -> a.order.compareTo(b.order)
|
||||
}
|
||||
}
|
||||
"desc" -> Comparator<ReplaceRule> { a, b ->
|
||||
when {
|
||||
a.order == -1 && b.order != -1 -> -1
|
||||
a.order != -1 && b.order == -1 -> 1
|
||||
a.order == -2 && b.order != -2 -> 1
|
||||
a.order != -2 && b.order == -2 -> -1
|
||||
else -> b.order.compareTo(a.order)
|
||||
}
|
||||
}
|
||||
"name_asc" -> Comparator<ReplaceRule> { a, b ->
|
||||
when {
|
||||
a.order == -1 && b.order != -1 -> -1
|
||||
a.order != -1 && b.order == -1 -> 1
|
||||
a.order == -2 && b.order != -2 -> 1
|
||||
a.order != -2 && b.order == -2 -> -1
|
||||
else -> a.name.lowercase().compareTo(b.name.lowercase())
|
||||
}
|
||||
}
|
||||
"name_desc" -> Comparator<ReplaceRule> { a, b ->
|
||||
when {
|
||||
a.order == -1 && b.order != -1 -> -1
|
||||
a.order != -1 && b.order == -1 -> 1
|
||||
a.order == -2 && b.order != -2 -> 1
|
||||
a.order != -2 && b.order == -2 -> -1
|
||||
else -> b.name.lowercase().compareTo(a.name.lowercase())
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
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%")
|
||||
}
|
||||
if (comparator != null) rules.sortedWith(comparator) else rules
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
}.flowOn(Dispatchers.Default)
|
||||
|
||||
fun update(vararg rule: ReplaceRule) {
|
||||
execute {
|
||||
@@ -91,16 +117,15 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application
|
||||
|
||||
fun toTop(rule: ReplaceRule) {
|
||||
execute {
|
||||
rule.order = appDb.replaceRuleDao.minOrder - 1
|
||||
rule.order = -1
|
||||
appDb.replaceRuleDao.update(rule)
|
||||
}
|
||||
}
|
||||
|
||||
fun topSelect(rules: List<ReplaceRule>) {
|
||||
execute {
|
||||
var minOrder = appDb.replaceRuleDao.minOrder - rules.size
|
||||
rules.forEach {
|
||||
it.order = ++minOrder
|
||||
it.order = -1
|
||||
}
|
||||
appDb.replaceRuleDao.update(*rules.toTypedArray())
|
||||
}
|
||||
@@ -108,16 +133,15 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application
|
||||
|
||||
fun toBottom(rule: ReplaceRule) {
|
||||
execute {
|
||||
rule.order = appDb.replaceRuleDao.maxOrder + 1
|
||||
rule.order = -2
|
||||
appDb.replaceRuleDao.update(rule)
|
||||
}
|
||||
}
|
||||
|
||||
fun bottomSelect(rules: List<ReplaceRule>) {
|
||||
execute {
|
||||
var maxOrder = appDb.replaceRuleDao.maxOrder
|
||||
rules.forEach {
|
||||
it.order = maxOrder++
|
||||
it.order = -2
|
||||
}
|
||||
appDb.replaceRuleDao.update(*rules.toTypedArray())
|
||||
}
|
||||
@@ -125,9 +149,13 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application
|
||||
|
||||
fun upOrder() {
|
||||
execute {
|
||||
// 重置所有非特殊排序的规则
|
||||
val rules = appDb.replaceRuleDao.all
|
||||
for ((index, rule) in rules.withIndex()) {
|
||||
rule.order = index + 1
|
||||
var normalOrder = 1
|
||||
rules.forEach { rule ->
|
||||
if (rule.order >= 0) { // 只重置普通排序的规则
|
||||
rule.order = normalOrder++
|
||||
}
|
||||
}
|
||||
appDb.replaceRuleDao.update(*rules.toTypedArray())
|
||||
}
|
||||
|
||||
@@ -211,8 +211,7 @@ class ReplaceEditActivity :
|
||||
|
||||
private fun upReplaceView(rule: ReplaceRule) = binding.run {
|
||||
etName.setText(rule.name)
|
||||
val group = rule.group.takeUnless { it.isNullOrBlank() }
|
||||
?: GroupManager.getLastSelectedGroup(this@ReplaceEditActivity)
|
||||
val group = rule.group.takeUnless { it.isNullOrBlank() } ?: "默认"
|
||||
etGroup.setText(group, false)
|
||||
etReplaceRule.setText(rule.pattern)
|
||||
cbUseRegex.isChecked = rule.isRegex
|
||||
@@ -229,8 +228,11 @@ class ReplaceEditActivity :
|
||||
val rule = viewModel.replaceRule ?: ReplaceRule()
|
||||
|
||||
rule.name = etName.text.toString()
|
||||
rule.group = etGroup.text.toString().trim().ifBlank {
|
||||
GroupManager.getLastSelectedGroup(this@ReplaceEditActivity)
|
||||
val groupText = etGroup.text.toString().trim()
|
||||
rule.group = if (groupText == "默认") {
|
||||
null
|
||||
} else {
|
||||
groupText.ifBlank { null }
|
||||
}
|
||||
rule.pattern = etReplaceRule.text.toString()
|
||||
rule.isRegex = cbUseRegex.isChecked
|
||||
|
||||
@@ -39,26 +39,35 @@
|
||||
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_group"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:hint="@string/group">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/et_group"
|
||||
android:layout_width="match_parent"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_group"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/text_default"
|
||||
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
android:layout_weight="1"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:hint="@string/group">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/iv_manage_groups"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/group_manage"/>
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/et_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/text_default"
|
||||
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/iv_manage_groups"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Material3Expressive.Button.TextButton"
|
||||
android:text="@string/group_manage"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_replace_rule"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/cb_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
@@ -20,10 +20,19 @@
|
||||
android:maxLines="2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/swt_enabled"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_pin"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:src="@drawable/ic_praise"
|
||||
app:layout_constraintStart_toEndOf="@id/cb_name"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/swt_enabled"
|
||||
android:name="@string/enable"
|
||||
|
||||
Reference in New Issue
Block a user