Make FilterList more accurate

This commit is contained in:
topjohnwu 2023-04-08 18:30:39 -07:00 committed by John Wu
parent c3f9533ddc
commit 56707b8119
2 changed files with 22 additions and 15 deletions

View File

@ -24,8 +24,11 @@ interface DiffList<T : DiffItem<*>> : List<T> {
suspend fun update(newItems: List<T>) suspend fun update(newItems: List<T>)
} }
interface FilterList<T : DiffItem<*>> : DiffList<T> { interface FilterList<T : DiffItem<*>> : List<T> {
fun filter(filter: (T) -> Boolean) fun filter(filter: (T) -> Boolean)
@MainThread
fun set(newItems: List<T>)
} }
fun <T : DiffItem<*>> diffList(): DiffList<T> = DiffObservableList() fun <T : DiffItem<*>> diffList(): DiffList<T> = DiffObservableList()
@ -37,7 +40,6 @@ private open class DiffObservableList<T : DiffItem<*>>
: AbstractList<T>(), ObservableList<T>, DiffList<T>, ListUpdateCallback { : AbstractList<T>(), ObservableList<T>, DiffList<T>, ListUpdateCallback {
protected var list: List<T> = emptyList() protected var list: List<T> = emptyList()
private set
private val listeners = ListChangeRegistry() private val listeners = ListChangeRegistry()
override val size: Int get() = list.size override val size: Int get() = list.size
@ -117,10 +119,12 @@ private class FilterableDiffObservableList<T : DiffItem<*>>(
private var sublist: List<T> = emptyList() private var sublist: List<T> = emptyList()
private var job: Job? = null private var job: Job? = null
private var lastFilter: ((T) -> Boolean)? = null
// --- // ---
override fun filter(filter: (T) -> Boolean) { override fun filter(filter: (T) -> Boolean) {
lastFilter = filter
job?.cancel() job?.cancel()
job = scope.launch(Dispatchers.Default) { job = scope.launch(Dispatchers.Default) {
val oldList = sublist val oldList = sublist
@ -143,8 +147,10 @@ private class FilterableDiffObservableList<T : DiffItem<*>>(
get() = sublist.size get() = sublist.size
@MainThread @MainThread
override fun update(newItems: List<T>, diffResult: DiffUtil.DiffResult) { override fun set(newItems: List<T>) {
super.update(newItems, diffResult) onRemoved(0, sublist.size)
sublist = list list = newItems
sublist = emptyList()
lastFilter?.let { filter(it) }
} }
} }

View File

@ -23,19 +23,19 @@ class DenyListViewModel : AsyncLoadViewModel() {
var isShowSystem = false var isShowSystem = false
set(value) { set(value) {
field = value field = value
query() doQuery(query)
} }
var isShowOS = false var isShowOS = false
set(value) { set(value) {
field = value field = value
query() doQuery(query)
} }
var query = "" var query = ""
set(value) { set(value) {
field = value field = value
query() doQuery(value)
} }
val items = filterList<DenyListRvItem>(viewModelScope) val items = filterList<DenyListRvItem>(viewModelScope)
@ -50,7 +50,7 @@ class DenyListViewModel : AsyncLoadViewModel() {
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
override suspend fun doLoadWork() { override suspend fun doLoadWork() {
loading = true loading = true
withContext(Dispatchers.Default) { val apps = withContext(Dispatchers.Default) {
val pm = AppContext.packageManager val pm = AppContext.packageManager
val denyList = Shell.cmd("magisk --denylist ls").exec().out val denyList = Shell.cmd("magisk --denylist ls").exec().out
.map { CmdlineListItem(it) } .map { CmdlineListItem(it) }
@ -63,21 +63,22 @@ class DenyListViewModel : AsyncLoadViewModel() {
.toCollection(ArrayList(size)) .toCollection(ArrayList(size))
} }
apps.sort() apps.sort()
items.update(apps) apps
} }
query() items.set(apps)
doQuery(query)
} }
private fun query() { private fun doQuery(s: String) {
items.filter { items.filter {
fun filterSystem() = isShowSystem || !it.info.isSystemApp() fun filterSystem() = isShowSystem || !it.info.isSystemApp()
fun filterOS() = (isShowSystem && isShowOS) || it.info.isApp() fun filterOS() = (isShowSystem && isShowOS) || it.info.isApp()
fun filterQuery(): Boolean { fun filterQuery(): Boolean {
fun inName() = it.info.label.contains(query, true) fun inName() = it.info.label.contains(s, true)
fun inPackage() = it.info.packageName.contains(query, true) fun inPackage() = it.info.packageName.contains(s, true)
fun inProcesses() = it.processes.any { p -> p.process.name.contains(query, true) } fun inProcesses() = it.processes.any { p -> p.process.name.contains(s, true) }
return inName() || inPackage() || inProcesses() return inName() || inPackage() || inProcesses()
} }