mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化
This commit is contained in:
@@ -5,6 +5,8 @@ import androidx.room.Delete
|
||||
import androidx.room.Query
|
||||
import androidx.room.Upsert
|
||||
import io.legado.app.data.entities.DictRule
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
||||
@Dao
|
||||
interface DictRuleDao {
|
||||
@@ -15,6 +17,9 @@ interface DictRuleDao {
|
||||
@get:Query("select * from dictRules where enabled = 1")
|
||||
val enabled: List<DictRule>
|
||||
|
||||
@Query("select * from dictRules where enabled = 1")
|
||||
fun flowAll(): Flow<List<DictRule>>
|
||||
|
||||
@Upsert
|
||||
fun upsert(vararg dictRule: DictRule)
|
||||
|
||||
|
||||
@@ -1,17 +1,112 @@
|
||||
package io.legado.app.ui.dict.rule
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.VMBaseActivity
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.DictRule
|
||||
import io.legado.app.databinding.ActivityDictRuleBinding
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.ui.widget.SelectActionBar
|
||||
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
||||
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||
import io.legado.app.utils.setEdgeEffectColor
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class DictRuleActivity : VMBaseActivity<ActivityDictRuleBinding, DictRuleViewModel>() {
|
||||
class DictRuleActivity : VMBaseActivity<ActivityDictRuleBinding, DictRuleViewModel>(),
|
||||
PopupMenu.OnMenuItemClickListener,
|
||||
SelectActionBar.CallBack,
|
||||
DictRuleAdapter.CallBack {
|
||||
|
||||
override val viewModel by viewModels<DictRuleViewModel>()
|
||||
override val binding by viewBinding(ActivityDictRuleBinding::inflate)
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
private val adapter by lazy { DictRuleAdapter(this, this) }
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
initRecyclerView()
|
||||
initSelectActionView()
|
||||
observeDictRuleData()
|
||||
}
|
||||
|
||||
private fun initRecyclerView() {
|
||||
binding.recyclerView.setEdgeEffectColor(primaryColor)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
binding.recyclerView.adapter = adapter
|
||||
binding.recyclerView.addItemDecoration(VerticalDivider(this))
|
||||
val itemTouchCallback = ItemTouchCallback(adapter)
|
||||
itemTouchCallback.isCanDrag = true
|
||||
val dragSelectTouchHelper: DragSelectTouchHelper =
|
||||
DragSelectTouchHelper(adapter.dragSelectCallback).setSlideArea(16, 50)
|
||||
dragSelectTouchHelper.attachToRecyclerView(binding.recyclerView)
|
||||
// When this page is opened, it is in selection mode
|
||||
dragSelectTouchHelper.activeSlideSelect()
|
||||
|
||||
// Note: need judge selection first, so add ItemTouchHelper after it.
|
||||
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
|
||||
}
|
||||
|
||||
private fun initSelectActionView() {
|
||||
binding.selectActionBar.setMainActionText(R.string.delete)
|
||||
binding.selectActionBar.inflateMenu(R.menu.replace_rule_sel)
|
||||
binding.selectActionBar.setOnMenuItemClickListener(this)
|
||||
binding.selectActionBar.setCallBack(this)
|
||||
}
|
||||
|
||||
private fun observeDictRuleData() {
|
||||
launch {
|
||||
appDb.dictRuleDao.flowAll().collect {
|
||||
adapter.setItems(it, adapter.diffItemCallBack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun selectAll(selectAll: Boolean) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun revertSelection() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun update(vararg rule: DictRule) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun delete(rule: DictRule) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun edit(rule: DictRule) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun toTop(rule: DictRule) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun toBottom(rule: DictRule) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun upOrder() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun upCountView() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
226
app/src/main/java/io/legado/app/ui/dict/rule/DictRuleAdapter.kt
Normal file
226
app/src/main/java/io/legado/app/ui/dict/rule/DictRuleAdapter.kt
Normal file
@@ -0,0 +1,226 @@
|
||||
package io.legado.app.ui.dict.rule
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.PopupMenu
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.adapter.ItemViewHolder
|
||||
import io.legado.app.base.adapter.RecyclerAdapter
|
||||
import io.legado.app.data.entities.DictRule
|
||||
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.ColorUtils
|
||||
|
||||
|
||||
class DictRuleAdapter(context: Context, var callBack: CallBack) :
|
||||
RecyclerAdapter<DictRule, ItemReplaceRuleBinding>(context),
|
||||
ItemTouchCallback.Callback {
|
||||
|
||||
private val selected = linkedSetOf<DictRule>()
|
||||
|
||||
val selection: List<DictRule>
|
||||
get() {
|
||||
return getItems().filter {
|
||||
selected.contains(it)
|
||||
}
|
||||
}
|
||||
|
||||
val diffItemCallBack = object : DiffUtil.ItemCallback<DictRule>() {
|
||||
|
||||
override fun areItemsTheSame(oldItem: DictRule, newItem: DictRule): Boolean {
|
||||
return oldItem.name == newItem.name
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: DictRule, newItem: DictRule): Boolean {
|
||||
if (oldItem.name != newItem.name) {
|
||||
return false
|
||||
}
|
||||
if (oldItem.enabled != newItem.enabled) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getChangePayload(oldItem: DictRule, newItem: DictRule): Any? {
|
||||
val payload = Bundle()
|
||||
if (oldItem.name != newItem.name) {
|
||||
payload.putBoolean("upName", true)
|
||||
}
|
||||
if (oldItem.enabled != newItem.enabled) {
|
||||
payload.putBoolean("enabled", newItem.enabled)
|
||||
}
|
||||
if (payload.isEmpty) {
|
||||
return null
|
||||
}
|
||||
return payload
|
||||
}
|
||||
}
|
||||
|
||||
fun selectAll() {
|
||||
getItems().forEach {
|
||||
selected.add(it)
|
||||
}
|
||||
notifyItemRangeChanged(0, itemCount, bundleOf(Pair("selected", null)))
|
||||
callBack.upCountView()
|
||||
}
|
||||
|
||||
fun revertSelection() {
|
||||
getItems().forEach {
|
||||
if (selected.contains(it)) {
|
||||
selected.remove(it)
|
||||
} else {
|
||||
selected.add(it)
|
||||
}
|
||||
}
|
||||
notifyItemRangeChanged(0, itemCount, bundleOf(Pair("selected", null)))
|
||||
callBack.upCountView()
|
||||
}
|
||||
|
||||
override fun getViewBinding(parent: ViewGroup): ItemReplaceRuleBinding {
|
||||
return ItemReplaceRuleBinding.inflate(inflater, parent, false)
|
||||
}
|
||||
|
||||
override fun onCurrentListChanged() {
|
||||
callBack.upCountView()
|
||||
}
|
||||
|
||||
override fun convert(
|
||||
holder: ItemViewHolder,
|
||||
binding: ItemReplaceRuleBinding,
|
||||
item: DictRule,
|
||||
payloads: MutableList<Any>
|
||||
) {
|
||||
binding.run {
|
||||
val bundle = payloads.getOrNull(0) as? Bundle
|
||||
if (bundle == null) {
|
||||
root.setBackgroundColor(ColorUtils.withAlpha(context.backgroundColor, 0.5f))
|
||||
cbName.text = item.name
|
||||
swtEnabled.isChecked = item.enabled
|
||||
cbName.isChecked = selected.contains(item)
|
||||
} else {
|
||||
bundle.keySet().map {
|
||||
when (it) {
|
||||
"selected" -> cbName.isChecked = selected.contains(item)
|
||||
"upName" -> cbName.text = item.name
|
||||
"enabled" -> swtEnabled.isChecked = item.enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerListener(holder: ItemViewHolder, binding: ItemReplaceRuleBinding) {
|
||||
binding.apply {
|
||||
swtEnabled.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
if (buttonView.isPressed) {
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
it.enabled = isChecked
|
||||
callBack.update(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
ivEdit.setOnClickListener {
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.edit(it)
|
||||
}
|
||||
}
|
||||
cbName.setOnClickListener {
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
if (cbName.isChecked) {
|
||||
selected.add(it)
|
||||
} else {
|
||||
selected.remove(it)
|
||||
}
|
||||
}
|
||||
callBack.upCountView()
|
||||
}
|
||||
ivMenuMore.setOnClickListener {
|
||||
showMenu(ivMenuMore, holder.layoutPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showMenu(view: View, position: Int) {
|
||||
val item = getItem(position) ?: return
|
||||
val popupMenu = PopupMenu(context, view)
|
||||
popupMenu.inflate(R.menu.replace_rule_item)
|
||||
popupMenu.setOnMenuItemClickListener { menuItem ->
|
||||
when (menuItem.itemId) {
|
||||
R.id.menu_top -> callBack.toTop(item)
|
||||
R.id.menu_bottom -> callBack.toBottom(item)
|
||||
R.id.menu_del -> callBack.delete(item)
|
||||
}
|
||||
true
|
||||
}
|
||||
popupMenu.show()
|
||||
}
|
||||
|
||||
override fun swap(srcPosition: Int, targetPosition: Int): Boolean {
|
||||
val srcItem = getItem(srcPosition)
|
||||
val targetItem = getItem(targetPosition)
|
||||
if (srcItem != null && targetItem != null) {
|
||||
if (srcItem.sortNumber == targetItem.sortNumber) {
|
||||
callBack.upOrder()
|
||||
} else {
|
||||
val srcOrder = srcItem.sortNumber
|
||||
srcItem.sortNumber = targetItem.sortNumber
|
||||
targetItem.sortNumber = srcOrder
|
||||
movedItems.add(srcItem)
|
||||
movedItems.add(targetItem)
|
||||
}
|
||||
}
|
||||
swapItem(srcPosition, targetPosition)
|
||||
return true
|
||||
}
|
||||
|
||||
private val movedItems = linkedSetOf<DictRule>()
|
||||
|
||||
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
|
||||
if (movedItems.isNotEmpty()) {
|
||||
callBack.update(*movedItems.toTypedArray())
|
||||
movedItems.clear()
|
||||
}
|
||||
}
|
||||
|
||||
val dragSelectCallback: DragSelectTouchHelper.Callback =
|
||||
object : DragSelectTouchHelper.AdvanceCallback<DictRule>(Mode.ToggleAndReverse) {
|
||||
override fun currentSelectedId(): MutableSet<DictRule> {
|
||||
return selected
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): DictRule {
|
||||
return getItem(position)!!
|
||||
}
|
||||
|
||||
override fun updateSelectState(position: Int, isSelected: Boolean): Boolean {
|
||||
getItem(position)?.let {
|
||||
if (isSelected) {
|
||||
selected.add(it)
|
||||
} else {
|
||||
selected.remove(it)
|
||||
}
|
||||
notifyItemChanged(position, bundleOf(Pair("selected", null)))
|
||||
callBack.upCountView()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
interface CallBack {
|
||||
fun update(vararg rule: DictRule)
|
||||
fun delete(rule: DictRule)
|
||||
fun edit(rule: DictRule)
|
||||
fun toTop(rule: DictRule)
|
||||
fun toBottom(rule: DictRule)
|
||||
fun upOrder()
|
||||
fun upCountView()
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,22 @@ package io.legado.app.ui.dict.rule
|
||||
|
||||
import android.app.Application
|
||||
import io.legado.app.base.BaseViewModel
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.DictRule
|
||||
|
||||
class DictRuleViewModel(application: Application) : BaseViewModel(application)
|
||||
class DictRuleViewModel(application: Application) : BaseViewModel(application) {
|
||||
|
||||
|
||||
fun upsert(vararg dictRule: DictRule) {
|
||||
execute {
|
||||
appDb.dictRuleDao.upsert(*dictRule)
|
||||
}
|
||||
}
|
||||
|
||||
fun delete(vararg dictRule: DictRule) {
|
||||
execute {
|
||||
appDb.dictRuleDao.delete(*dictRule)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user