diff --git a/app/src/main/java/com/topjohnwu/magisk/databinding/DiffObservableList.kt b/app/src/main/java/com/topjohnwu/magisk/databinding/DiffObservableList.kt index a1b22eff6..96262122e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/databinding/DiffObservableList.kt +++ b/app/src/main/java/com/topjohnwu/magisk/databinding/DiffObservableList.kt @@ -24,8 +24,11 @@ interface DiffList> : List { suspend fun update(newItems: List) } -interface FilterList> : DiffList { +interface FilterList> : List { fun filter(filter: (T) -> Boolean) + + @MainThread + fun set(newItems: List) } fun > diffList(): DiffList = DiffObservableList() @@ -37,7 +40,6 @@ private open class DiffObservableList> : AbstractList(), ObservableList, DiffList, ListUpdateCallback { protected var list: List = emptyList() - private set private val listeners = ListChangeRegistry() override val size: Int get() = list.size @@ -117,10 +119,12 @@ private class FilterableDiffObservableList>( private var sublist: List = emptyList() private var job: Job? = null + private var lastFilter: ((T) -> Boolean)? = null // --- override fun filter(filter: (T) -> Boolean) { + lastFilter = filter job?.cancel() job = scope.launch(Dispatchers.Default) { val oldList = sublist @@ -143,8 +147,10 @@ private class FilterableDiffObservableList>( get() = sublist.size @MainThread - override fun update(newItems: List, diffResult: DiffUtil.DiffResult) { - super.update(newItems, diffResult) - sublist = list + override fun set(newItems: List) { + onRemoved(0, sublist.size) + list = newItems + sublist = emptyList() + lastFilter?.let { filter(it) } } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListViewModel.kt index 127769c5d..767c19c41 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListViewModel.kt @@ -23,19 +23,19 @@ class DenyListViewModel : AsyncLoadViewModel() { var isShowSystem = false set(value) { field = value - query() + doQuery(query) } var isShowOS = false set(value) { field = value - query() + doQuery(query) } var query = "" set(value) { field = value - query() + doQuery(value) } val items = filterList(viewModelScope) @@ -50,7 +50,7 @@ class DenyListViewModel : AsyncLoadViewModel() { @SuppressLint("InlinedApi") override suspend fun doLoadWork() { loading = true - withContext(Dispatchers.Default) { + val apps = withContext(Dispatchers.Default) { val pm = AppContext.packageManager val denyList = Shell.cmd("magisk --denylist ls").exec().out .map { CmdlineListItem(it) } @@ -63,21 +63,22 @@ class DenyListViewModel : AsyncLoadViewModel() { .toCollection(ArrayList(size)) } apps.sort() - items.update(apps) + apps } - query() + items.set(apps) + doQuery(query) } - private fun query() { + private fun doQuery(s: String) { items.filter { fun filterSystem() = isShowSystem || !it.info.isSystemApp() fun filterOS() = (isShowSystem && isShowOS) || it.info.isApp() fun filterQuery(): Boolean { - fun inName() = it.info.label.contains(query, true) - fun inPackage() = it.info.packageName.contains(query, true) - fun inProcesses() = it.processes.any { p -> p.process.name.contains(query, true) } + fun inName() = it.info.label.contains(s, true) + fun inPackage() = it.info.packageName.contains(s, true) + fun inProcesses() = it.processes.any { p -> p.process.name.contains(s, true) } return inName() || inPackage() || inProcesses() }