mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 12:05:30 +00:00
Fix crash when revoke root permission
This commit is contained in:
parent
69b66ef637
commit
7be958e35d
@ -6,12 +6,35 @@ import androidx.databinding.ListChangeRegistry
|
||||
import androidx.databinding.ObservableList
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListUpdateCallback
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.AbstractList
|
||||
|
||||
open class DiffObservableList<T : DiffItem<*>>
|
||||
: AbstractList<T>(), ObservableList<T>, ListUpdateCallback {
|
||||
// Only expose the immutable List types
|
||||
interface DiffList<T : DiffItem<*>> : List<T> {
|
||||
fun calculateDiff(newItems: List<T>): DiffUtil.DiffResult
|
||||
|
||||
@MainThread
|
||||
fun update(newItems: List<T>, diffResult: DiffUtil.DiffResult)
|
||||
|
||||
@WorkerThread
|
||||
suspend fun update(newItems: List<T>)
|
||||
}
|
||||
|
||||
interface FilterList<T : DiffItem<*>> : DiffList<T> {
|
||||
fun filter(filter: (T) -> Boolean)
|
||||
}
|
||||
|
||||
fun <T : DiffItem<*>> diffList(): DiffList<T> = DiffObservableList()
|
||||
|
||||
fun <T : DiffItem<*>> filterList(scope: CoroutineScope): FilterList<T> =
|
||||
FilterableDiffObservableList(scope)
|
||||
|
||||
private open class DiffObservableList<T : DiffItem<*>>
|
||||
: AbstractList<T>(), ObservableList<T>, DiffList<T>, ListUpdateCallback {
|
||||
|
||||
protected var list: List<T> = emptyList()
|
||||
private set
|
||||
@ -21,7 +44,7 @@ open class DiffObservableList<T : DiffItem<*>>
|
||||
|
||||
override fun get(index: Int) = list[index]
|
||||
|
||||
fun calculateDiff(newItems: List<T>): DiffUtil.DiffResult {
|
||||
override fun calculateDiff(newItems: List<T>): DiffUtil.DiffResult {
|
||||
return doCalculateDiff(list, newItems)
|
||||
}
|
||||
|
||||
@ -48,13 +71,13 @@ open class DiffObservableList<T : DiffItem<*>>
|
||||
}
|
||||
|
||||
@MainThread
|
||||
fun update(newItems: List<T>, diffResult: DiffUtil.DiffResult) {
|
||||
override fun update(newItems: List<T>, diffResult: DiffUtil.DiffResult) {
|
||||
list = ArrayList(newItems)
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
suspend fun update(newItems: List<T>) {
|
||||
override suspend fun update(newItems: List<T>) {
|
||||
val diffResult = calculateDiff(newItems)
|
||||
withContext(Dispatchers.Main) {
|
||||
update(newItems, diffResult)
|
||||
@ -87,3 +110,35 @@ open class DiffObservableList<T : DiffItem<*>>
|
||||
listeners.notifyRemoved(this, position, count)
|
||||
}
|
||||
}
|
||||
|
||||
private class FilterableDiffObservableList<T : DiffItem<*>>(
|
||||
private val scope: CoroutineScope
|
||||
) : DiffObservableList<T>(), FilterList<T> {
|
||||
|
||||
private var sublist: List<T> = emptyList()
|
||||
private var job: Job? = null
|
||||
|
||||
// ---
|
||||
|
||||
override fun filter(filter: (T) -> Boolean) {
|
||||
job?.cancel()
|
||||
job = scope.launch(Dispatchers.Default) {
|
||||
val oldList = sublist
|
||||
val newList = list.filter(filter)
|
||||
val diff = doCalculateDiff(oldList, newList)
|
||||
withContext(Dispatchers.Main) {
|
||||
sublist = newList
|
||||
diff.dispatchUpdatesTo(this@FilterableDiffObservableList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
override fun get(index: Int): T {
|
||||
return sublist[index]
|
||||
}
|
||||
|
||||
override val size: Int
|
||||
get() = sublist.size
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
package com.topjohnwu.magisk.databinding
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
open class FilterableDiffObservableList<T : DiffItem<*>>(
|
||||
private val scope: CoroutineScope
|
||||
) : DiffObservableList<T>() {
|
||||
|
||||
private var sublist: List<T> = emptyList()
|
||||
private var job: Job? = null
|
||||
|
||||
// ---
|
||||
|
||||
fun filter(filter: (T) -> Boolean) {
|
||||
job?.cancel()
|
||||
job = scope.launch(Dispatchers.Default) {
|
||||
val oldList = sublist
|
||||
val newList = list.filter(filter)
|
||||
val diff = doCalculateDiff(oldList, newList)
|
||||
withContext(Dispatchers.Main) {
|
||||
sublist = newList
|
||||
diff.dispatchUpdatesTo(this@FilterableDiffObservableList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
override fun get(index: Int): T {
|
||||
return sublist[index]
|
||||
}
|
||||
|
||||
override val size: Int
|
||||
get() = sublist.size
|
||||
}
|
@ -46,11 +46,11 @@ class MergeObservableList<T> : AbstractList<T>(), ObservableList<T> {
|
||||
return this
|
||||
}
|
||||
|
||||
fun insertList(list: ObservableList<out T>): MergeObservableList<T> {
|
||||
fun insertList(list: List<T>): MergeObservableList<T> {
|
||||
val idx = size
|
||||
lists.add(list)
|
||||
++modCount
|
||||
(list as ObservableList<T>).addOnListChangedCallback(callback)
|
||||
(list as? ObservableList<T>)?.addOnListChangedCallback(callback)
|
||||
if (list.isNotEmpty())
|
||||
listeners.notifyInserted(this, idx, list.size)
|
||||
return this
|
||||
@ -72,11 +72,11 @@ class MergeObservableList<T> : AbstractList<T>(), ObservableList<T> {
|
||||
return false
|
||||
}
|
||||
|
||||
fun removeList(listToRemove: ObservableList<out T>): Boolean {
|
||||
fun removeList(listToRemove: List<T>): Boolean {
|
||||
var idx = 0
|
||||
for ((i, list) in lists.withIndex()) {
|
||||
if (listToRemove === list) {
|
||||
(list as ObservableList<T>).removeOnListChangedCallback(callback)
|
||||
(list as? ObservableList<T>)?.removeOnListChangedCallback(callback)
|
||||
lists.removeAt(i)
|
||||
++modCount
|
||||
listeners.notifyRemoved(this, idx, list.size)
|
||||
@ -90,8 +90,8 @@ class MergeObservableList<T> : AbstractList<T>(), ObservableList<T> {
|
||||
override fun clear() {
|
||||
val sz = size
|
||||
for (list in lists) {
|
||||
if (list is ObservableList<*>) {
|
||||
(list as ObservableList<T>).removeOnListChangedCallback(callback)
|
||||
if (list is ObservableList) {
|
||||
list.removeOnListChangedCallback(callback)
|
||||
}
|
||||
}
|
||||
++modCount
|
||||
|
@ -8,8 +8,8 @@ import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||
import com.topjohnwu.magisk.core.di.AppContext
|
||||
import com.topjohnwu.magisk.core.ktx.concurrentMap
|
||||
import com.topjohnwu.magisk.databinding.FilterableDiffObservableList
|
||||
import com.topjohnwu.magisk.databinding.bindExtra
|
||||
import com.topjohnwu.magisk.databinding.filterList
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -38,7 +38,7 @@ class DenyListViewModel : AsyncLoadViewModel() {
|
||||
query()
|
||||
}
|
||||
|
||||
val items = FilterableDiffObservableList<DenyListRvItem>(viewModelScope)
|
||||
val items = filterList<DenyListRvItem>(viewModelScope)
|
||||
val extraBindings = bindExtra {
|
||||
it.put(BR.viewModel, this)
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ import com.topjohnwu.magisk.core.ktx.toTime
|
||||
import com.topjohnwu.magisk.core.repository.LogRepository
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.databinding.DiffObservableList
|
||||
import com.topjohnwu.magisk.databinding.bindExtra
|
||||
import com.topjohnwu.magisk.databinding.diffList
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.view.TextItem
|
||||
@ -37,13 +37,13 @@ class LogViewModel(
|
||||
|
||||
// --- su log
|
||||
|
||||
val items = DiffObservableList<SuLogRvItem>()
|
||||
val items = diffList<SuLogRvItem>()
|
||||
val extraBindings = bindExtra {
|
||||
it.put(BR.viewModel, this)
|
||||
}
|
||||
|
||||
// --- magisk log
|
||||
val logs = DiffObservableList<LogRvItem>()
|
||||
val logs = diffList<LogRvItem>()
|
||||
var magiskLogRaw = " "
|
||||
|
||||
override suspend fun doLoadWork() {
|
||||
|
@ -10,10 +10,10 @@ import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.databinding.DiffObservableList
|
||||
import com.topjohnwu.magisk.databinding.MergeObservableList
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
import com.topjohnwu.magisk.databinding.bindExtra
|
||||
import com.topjohnwu.magisk.databinding.diffList
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.dialog.LocalModuleInstallDialog
|
||||
import com.topjohnwu.magisk.dialog.OnlineModuleInstallDialog
|
||||
@ -27,7 +27,7 @@ class ModuleViewModel : AsyncLoadViewModel() {
|
||||
|
||||
val bottomBarBarrierIds = intArrayOf(R.id.module_update, R.id.module_remove)
|
||||
|
||||
private val itemsInstalled = DiffObservableList<LocalModuleRvItem>()
|
||||
private val itemsInstalled = diffList<LocalModuleRvItem>()
|
||||
|
||||
val items = MergeObservableList<RvItem>()
|
||||
val extraBindings = bindExtra {
|
||||
|
@ -34,7 +34,7 @@ class SuperuserViewModel(
|
||||
private val itemNoData = TextItem(R.string.superuser_policy_none)
|
||||
|
||||
private val itemsHelpers = ObservableArrayList<TextItem>()
|
||||
private val itemsPolicies = DiffObservableList<PolicyRvItem>()
|
||||
private val itemsPolicies = diffList<PolicyRvItem>()
|
||||
|
||||
val items = MergeObservableList<RvItem>()
|
||||
.insertList(itemsHelpers)
|
||||
@ -105,8 +105,10 @@ class SuperuserViewModel(
|
||||
fun deletePressed(item: PolicyRvItem) {
|
||||
fun updateState() = viewModelScope.launch {
|
||||
db.delete(item.item.uid)
|
||||
itemsPolicies.removeAll { it.itemSameAs(item) }
|
||||
if (itemsPolicies.isEmpty() && itemsHelpers.isEmpty()) {
|
||||
val list = ArrayList(itemsPolicies)
|
||||
list.removeAll { it.itemSameAs(item) }
|
||||
itemsPolicies.update(list)
|
||||
if (list.isEmpty() && itemsHelpers.isEmpty()) {
|
||||
itemsHelpers.add(itemNoData)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user