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