mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-23 18:15:30 +00:00
Cleanup more databinding implementation
This commit is contained in:
parent
1620e15f99
commit
0b987dd0b0
@ -1,31 +1,26 @@
|
||||
package com.topjohnwu.magisk.databinding
|
||||
|
||||
import androidx.annotation.MainThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.databinding.ListChangeRegistry
|
||||
import androidx.databinding.ObservableList
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListUpdateCallback
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.AbstractList
|
||||
|
||||
open class DiffObservableList<T>(
|
||||
private val callback: Callback<T>
|
||||
) : AbstractList<T>(), ObservableList<T> {
|
||||
open class DiffObservableList<T : DiffItem<*>>
|
||||
: AbstractList<T>(), ObservableList<T>, ListUpdateCallback {
|
||||
|
||||
protected var list: List<T> = emptyList()
|
||||
private set
|
||||
private val listeners = ListChangeRegistry()
|
||||
protected val listCallback = ObservableListUpdateCallback()
|
||||
|
||||
override val size: Int get() = list.size
|
||||
|
||||
override fun get(index: Int) = list[index]
|
||||
|
||||
/**
|
||||
* Calculates the list of update operations that can convert this list into the given one.
|
||||
*
|
||||
* @param newItems The items that this list will be set to.
|
||||
* @return A DiffResult that contains the information about the edit sequence to covert this
|
||||
* list into the given one.
|
||||
*/
|
||||
fun calculateDiff(newItems: List<T>): DiffUtil.DiffResult {
|
||||
return doCalculateDiff(list, newItems)
|
||||
}
|
||||
@ -36,31 +31,34 @@ open class DiffObservableList<T>(
|
||||
|
||||
override fun getNewListSize() = newItems.size
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
val oldItem = oldItems[oldItemPosition]
|
||||
val newItem = newItems[newItemPosition]
|
||||
return callback.areItemsTheSame(oldItem, newItem)
|
||||
return (oldItem as DiffItem<Any>).itemSameAs(newItem)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
val oldItem = oldItems[oldItemPosition]
|
||||
val newItem = newItems[newItemPosition]
|
||||
return callback.areContentsTheSame(oldItem, newItem)
|
||||
return (oldItem as DiffItem<Any>).contentSameAs(newItem)
|
||||
}
|
||||
}, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the contents of this list to the given one using the DiffResults to dispatch change
|
||||
* notifications.
|
||||
*
|
||||
* @param newItems The items to set this list to.
|
||||
* @param diffResult The diff results to dispatch change notifications.
|
||||
*/
|
||||
@MainThread
|
||||
fun update(newItems: List<T>, diffResult: DiffUtil.DiffResult) {
|
||||
list = ArrayList(newItems)
|
||||
diffResult.dispatchUpdatesTo(listCallback)
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
suspend fun update(newItems: List<T>) {
|
||||
val diffResult = calculateDiff(newItems)
|
||||
withContext(Dispatchers.Main) {
|
||||
update(newItems, diffResult)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addOnListChangedCallback(listener: ObservableList.OnListChangedCallback<out ObservableList<T>>) {
|
||||
@ -71,36 +69,21 @@ open class DiffObservableList<T>(
|
||||
listeners.remove(listener)
|
||||
}
|
||||
|
||||
private fun notifyAdd(start: Int, count: Int) {
|
||||
listeners.notifyInserted(this, start, count)
|
||||
override fun onChanged(position: Int, count: Int, payload: Any?) {
|
||||
listeners.notifyChanged(this, position, count)
|
||||
}
|
||||
|
||||
private fun notifyRemove(start: Int, count: Int) {
|
||||
listeners.notifyRemoved(this, start, count)
|
||||
override fun onMoved(fromPosition: Int, toPosition: Int) {
|
||||
listeners.notifyMoved(this, fromPosition, toPosition, 1)
|
||||
}
|
||||
|
||||
interface Callback<T> {
|
||||
fun areItemsTheSame(oldItem: T, newItem: T): Boolean
|
||||
fun areContentsTheSame(oldItem: T, newItem: T): Boolean
|
||||
override fun onInserted(position: Int, count: Int) {
|
||||
modCount += 1
|
||||
listeners.notifyInserted(this, position, count)
|
||||
}
|
||||
|
||||
inner class ObservableListUpdateCallback : ListUpdateCallback {
|
||||
override fun onChanged(position: Int, count: Int, payload: Any?) {
|
||||
listeners.notifyChanged(this@DiffObservableList, position, count)
|
||||
}
|
||||
|
||||
override fun onMoved(fromPosition: Int, toPosition: Int) {
|
||||
listeners.notifyMoved(this@DiffObservableList, fromPosition, toPosition, 1)
|
||||
}
|
||||
|
||||
override fun onInserted(position: Int, count: Int) {
|
||||
modCount += 1
|
||||
listeners.notifyInserted(this@DiffObservableList, position, count)
|
||||
}
|
||||
|
||||
override fun onRemoved(position: Int, count: Int) {
|
||||
modCount += 1
|
||||
listeners.notifyRemoved(this@DiffObservableList, position, count)
|
||||
}
|
||||
override fun onRemoved(position: Int, count: Int) {
|
||||
modCount += 1
|
||||
listeners.notifyRemoved(this, position, count)
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,9 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
open class FilterableDiffObservableList<T>(
|
||||
callback: Callback<T>,
|
||||
open class FilterableDiffObservableList<T : DiffItem<*>>(
|
||||
private val scope: CoroutineScope
|
||||
) : DiffObservableList<T>(callback) {
|
||||
) : DiffObservableList<T>() {
|
||||
|
||||
private var sublist: List<T> = emptyList()
|
||||
private var job: Job? = null
|
||||
@ -24,7 +23,7 @@ open class FilterableDiffObservableList<T>(
|
||||
val diff = doCalculateDiff(oldList, newList)
|
||||
withContext(Dispatchers.Main) {
|
||||
sublist = newList
|
||||
diff.dispatchUpdatesTo(listCallback)
|
||||
diff.dispatchUpdatesTo(this@FilterableDiffObservableList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,69 +3,33 @@ package com.topjohnwu.magisk.databinding
|
||||
import androidx.databinding.PropertyChangeRegistry
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
abstract class RvItem {
|
||||
abstract val layoutRes: Int
|
||||
}
|
||||
|
||||
interface RvContainer<E> {
|
||||
val item: E
|
||||
}
|
||||
|
||||
interface ViewAwareRvItem {
|
||||
fun onBind(binding: ViewDataBinding, recyclerView: RecyclerView)
|
||||
}
|
||||
|
||||
interface ComparableRv<T> : Comparable<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun comparableEqual(o: Any?) =
|
||||
o != null && o::class == this::class && compareTo(o as T) == 0
|
||||
}
|
||||
|
||||
abstract class DiffRvItem<T> : RvItem() {
|
||||
|
||||
// Defer to contentSameAs by default
|
||||
open fun itemSameAs(other: T) = true
|
||||
|
||||
open fun contentSameAs(other: T) =
|
||||
when (this) {
|
||||
is RvContainer<*> -> item == (other as RvContainer<*>).item
|
||||
is ComparableRv<*> -> comparableEqual(other)
|
||||
else -> this == other
|
||||
}
|
||||
}
|
||||
|
||||
typealias AnyDiffRvItem = DiffRvItem<*>
|
||||
|
||||
abstract class ObservableDiffRvItem<T> : DiffRvItem<T>(), ObservableHost {
|
||||
override var callbacks: PropertyChangeRegistry? = null
|
||||
}
|
||||
|
||||
abstract class ObservableRvItem : RvItem(), ObservableHost {
|
||||
override var callbacks: PropertyChangeRegistry? = null
|
||||
}
|
||||
|
||||
private object DiffRvItemCallback : DiffObservableList.Callback<DiffRvItem<Any>> {
|
||||
override fun areItemsTheSame(
|
||||
oldItem: DiffRvItem<Any>,
|
||||
newItem: DiffRvItem<Any>
|
||||
): Boolean {
|
||||
return oldItem::class == newItem::class && oldItem.itemSameAs(newItem)
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: DiffRvItem<Any>,
|
||||
newItem: DiffRvItem<Any>
|
||||
): Boolean {
|
||||
return oldItem.contentSameAs(newItem)
|
||||
}
|
||||
interface ItemWrapper<E> {
|
||||
val item: E
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class DiffRvItemList<T: AnyDiffRvItem> : DiffObservableList<T>(DiffRvItemCallback as Callback<T>)
|
||||
interface ViewAwareItem {
|
||||
fun onBind(binding: ViewDataBinding, recyclerView: RecyclerView)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class DiffRvItemFilterList<T: AnyDiffRvItem>(
|
||||
scope: CoroutineScope
|
||||
) : FilterableDiffObservableList<T>(DiffRvItemCallback as Callback<T>, scope)
|
||||
interface DiffItem<T : Any> {
|
||||
|
||||
fun itemSameAs(other: T): Boolean {
|
||||
if (this === other) return true
|
||||
return when (this) {
|
||||
is ItemWrapper<*> -> item == (other as ItemWrapper<*>).item
|
||||
is Comparable<*> -> compareValues(this, other as Comparable<*>) == 0
|
||||
else -> this == other
|
||||
}
|
||||
}
|
||||
|
||||
fun contentSameAs(other: T) = true
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class RvItemAdapter<T: RvItem>(
|
||||
holder.binding.lifecycleOwner = lifecycleOwner
|
||||
holder.binding.executePendingBindings()
|
||||
recyclerView?.let {
|
||||
if (item is ViewAwareRvItem)
|
||||
if (item is ViewAwareItem)
|
||||
item.onBind(holder.binding, it)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import android.view.ViewGroup
|
||||
import androidx.databinding.Bindable
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.ComparableRv
|
||||
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||
import com.topjohnwu.magisk.databinding.addOnPropertyChangedCallback
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.ktx.startAnimations
|
||||
@ -15,7 +15,7 @@ import kotlin.math.roundToInt
|
||||
|
||||
class DenyListRvItem(
|
||||
val info: AppProcessInfo
|
||||
) : ObservableDiffRvItem<DenyListRvItem>(), ComparableRv<DenyListRvItem> {
|
||||
) : ObservableRvItem(), DiffItem<DenyListRvItem>, Comparable<DenyListRvItem> {
|
||||
|
||||
override val layoutRes get() = R.layout.item_hide_md2
|
||||
|
||||
@ -100,7 +100,7 @@ class DenyListRvItem(
|
||||
|
||||
class ProcessRvItem(
|
||||
val process: ProcessInfo
|
||||
) : ObservableDiffRvItem<ProcessRvItem>() {
|
||||
) : ObservableRvItem(), DiffItem<ProcessRvItem> {
|
||||
|
||||
override val layoutRes get() = R.layout.item_hide_process_md2
|
||||
|
||||
@ -122,10 +122,9 @@ class ProcessRvItem(
|
||||
val defaultSelection get() =
|
||||
process.isIsolated || process.isAppZygote || process.name == process.packageName
|
||||
|
||||
override fun contentSameAs(other: ProcessRvItem) =
|
||||
process.isEnabled == other.process.isEnabled
|
||||
|
||||
override fun itemSameAs(other: ProcessRvItem) =
|
||||
process.name == other.process.name && process.packageName == other.process.packageName
|
||||
|
||||
override fun contentSameAs(other: ProcessRvItem) =
|
||||
process.isEnabled == other.process.isEnabled
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||
import com.topjohnwu.magisk.core.di.AppContext
|
||||
import com.topjohnwu.magisk.databinding.DiffRvItemFilterList
|
||||
import com.topjohnwu.magisk.databinding.FilterableDiffObservableList
|
||||
import com.topjohnwu.magisk.databinding.bindExtra
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.ktx.concurrentMap
|
||||
@ -38,7 +38,7 @@ class DenyListViewModel : AsyncLoadViewModel() {
|
||||
query()
|
||||
}
|
||||
|
||||
val items = DiffRvItemFilterList<DenyListRvItem>(viewModelScope)
|
||||
val items = FilterableDiffObservableList<DenyListRvItem>(viewModelScope)
|
||||
val extraBindings = bindExtra {
|
||||
it.put(BR.viewModel, this)
|
||||
}
|
||||
@ -50,7 +50,7 @@ class DenyListViewModel : AsyncLoadViewModel() {
|
||||
@SuppressLint("InlinedApi")
|
||||
override suspend fun doLoadWork() {
|
||||
loading = true
|
||||
val (apps, diff) = withContext(Dispatchers.Default) {
|
||||
withContext(Dispatchers.Default) {
|
||||
val pm = AppContext.packageManager
|
||||
val denyList = Shell.cmd("magisk --denylist ls").exec().out
|
||||
.map { CmdlineListItem(it) }
|
||||
@ -63,9 +63,8 @@ class DenyListViewModel : AsyncLoadViewModel() {
|
||||
.toCollection(ArrayList(size))
|
||||
}
|
||||
apps.sort()
|
||||
apps to items.calculateDiff(apps)
|
||||
items.update(apps)
|
||||
}
|
||||
items.update(apps, diff)
|
||||
query()
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,15 @@ import androidx.core.view.updateLayoutParams
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.DiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.RvContainer
|
||||
import com.topjohnwu.magisk.databinding.ViewAwareRvItem
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
import com.topjohnwu.magisk.databinding.ViewAwareItem
|
||||
import kotlin.math.max
|
||||
|
||||
class ConsoleItem(
|
||||
override val item: String
|
||||
) : DiffRvItem<ConsoleItem>(), ViewAwareRvItem, RvContainer<String> {
|
||||
) : RvItem(), ViewAwareItem, DiffItem<ConsoleItem>, ItemWrapper<String> {
|
||||
override val layoutRes = R.layout.item_console_md2
|
||||
|
||||
private var parentWidth = -1
|
||||
|
@ -4,18 +4,17 @@ import androidx.databinding.ViewDataBinding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.textview.MaterialTextView
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.RvContainer
|
||||
import com.topjohnwu.magisk.databinding.ViewAwareRvItem
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||
import com.topjohnwu.magisk.databinding.ViewAwareItem
|
||||
|
||||
class LogRvItem(
|
||||
override val item: String
|
||||
) : ObservableDiffRvItem<LogRvItem>(), RvContainer<String>, ViewAwareRvItem {
|
||||
) : ObservableRvItem(), DiffItem<LogRvItem>, ItemWrapper<String>, ViewAwareItem {
|
||||
|
||||
override val layoutRes = R.layout.item_log_textview
|
||||
|
||||
override fun itemSameAs(other: LogRvItem) = item == other.item
|
||||
|
||||
override fun onBind(binding: ViewDataBinding, recyclerView: RecyclerView) {
|
||||
val view = binding.root as MaterialTextView
|
||||
view.measure(0, 0)
|
||||
|
@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.Info
|
||||
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.DiffRvItemList
|
||||
import com.topjohnwu.magisk.databinding.DiffObservableList
|
||||
import com.topjohnwu.magisk.databinding.bindExtra
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||
@ -37,28 +37,26 @@ class LogViewModel(
|
||||
|
||||
// --- su log
|
||||
|
||||
val items = DiffRvItemList<SuLogRvItem>()
|
||||
val items = DiffObservableList<SuLogRvItem>()
|
||||
val extraBindings = bindExtra {
|
||||
it.put(BR.viewModel, this)
|
||||
}
|
||||
|
||||
// --- magisk log
|
||||
val logs = DiffRvItemList<LogRvItem>()
|
||||
val logs = DiffObservableList<LogRvItem>()
|
||||
var magiskLogRaw = " "
|
||||
|
||||
override suspend fun doLoadWork() {
|
||||
loading = true
|
||||
val (logs, logDiff) = withContext(Dispatchers.Default) {
|
||||
magiskLogRaw = repo.fetchMagiskLogs()
|
||||
val logs = magiskLogRaw.split('\n').map { LogRvItem(it) }
|
||||
logs to this@LogViewModel.logs.calculateDiff(logs)
|
||||
}
|
||||
this.logs.update(logs, logDiff)
|
||||
|
||||
val (suLogs, suDiff) = withContext(Dispatchers.Default) {
|
||||
magiskLogRaw = repo.fetchMagiskLogs()
|
||||
val newLogs = magiskLogRaw.split('\n').map { LogRvItem(it) }
|
||||
logs.update(newLogs)
|
||||
val suLogs = repo.fetchSuLogs().map { SuLogRvItem(it) }
|
||||
suLogs to items.calculateDiff(suLogs)
|
||||
}
|
||||
|
||||
items.firstOrNull()?.isTop = false
|
||||
items.lastOrNull()?.isBottom = false
|
||||
items.update(suLogs, suDiff)
|
||||
|
@ -4,19 +4,17 @@ import androidx.databinding.Bindable
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.model.su.SuLog
|
||||
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.RvContainer
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.ktx.timeDateFormat
|
||||
import com.topjohnwu.magisk.ktx.toTime
|
||||
|
||||
class SuLogRvItem(
|
||||
override val item: SuLog
|
||||
) : ObservableDiffRvItem<SuLogRvItem>(), RvContainer<SuLog> {
|
||||
class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem<SuLogRvItem> {
|
||||
|
||||
override val layoutRes = R.layout.item_log_access_md2
|
||||
|
||||
val date = item.time.toTime(timeDateFormat)
|
||||
val date = log.time.toTime(timeDateFormat)
|
||||
|
||||
@get:Bindable
|
||||
var isTop = false
|
||||
@ -26,5 +24,5 @@ class SuLogRvItem(
|
||||
var isBottom = false
|
||||
set(value) = set(value, field, { field = it }, BR.bottom)
|
||||
|
||||
override fun itemSameAs(other: SuLogRvItem) = item.appName == other.item.appName
|
||||
override fun itemSameAs(other: SuLogRvItem) = log.appName == other.log.appName
|
||||
}
|
||||
|
@ -5,20 +5,21 @@ import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||
import com.topjohnwu.magisk.databinding.DiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.RvContainer
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.utils.TextHolder
|
||||
import com.topjohnwu.magisk.utils.asText
|
||||
|
||||
object InstallModule : DiffRvItem<InstallModule>() {
|
||||
object InstallModule : RvItem(), DiffItem<InstallModule> {
|
||||
override val layoutRes = R.layout.item_module_download
|
||||
}
|
||||
|
||||
class LocalModuleRvItem(
|
||||
override val item: LocalModule
|
||||
) : ObservableDiffRvItem<LocalModuleRvItem>(), RvContainer<LocalModule> {
|
||||
) : ObservableRvItem(), DiffItem<LocalModuleRvItem>, ItemWrapper<LocalModule> {
|
||||
|
||||
override val layoutRes = R.layout.item_module_md2
|
||||
|
||||
|
@ -10,7 +10,7 @@ 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.DiffRvItemList
|
||||
import com.topjohnwu.magisk.databinding.DiffObservableList
|
||||
import com.topjohnwu.magisk.databinding.MergeObservableList
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
import com.topjohnwu.magisk.databinding.bindExtra
|
||||
@ -26,7 +26,7 @@ class ModuleViewModel : AsyncLoadViewModel() {
|
||||
|
||||
val bottomBarBarrierIds = intArrayOf(R.id.module_update, R.id.module_remove)
|
||||
|
||||
private val itemsInstalled = DiffRvItemList<LocalModuleRvItem>()
|
||||
private val itemsInstalled = DiffObservableList<LocalModuleRvItem>()
|
||||
|
||||
val items = MergeObservableList<RvItem>()
|
||||
val extraBindings = bindExtra {
|
||||
@ -57,11 +57,10 @@ class ModuleViewModel : AsyncLoadViewModel() {
|
||||
override fun onNetworkChanged(network: Boolean) = startLoading()
|
||||
|
||||
private suspend fun loadInstalled() {
|
||||
val installed = LocalModule.installed().map { LocalModuleRvItem(it) }
|
||||
val diff = withContext(Dispatchers.Default) {
|
||||
itemsInstalled.calculateDiff(installed)
|
||||
withContext(Dispatchers.Default) {
|
||||
val installed = LocalModule.installed().map { LocalModuleRvItem(it) }
|
||||
itemsInstalled.update(installed)
|
||||
}
|
||||
itemsInstalled.update(installed, diff)
|
||||
}
|
||||
|
||||
private suspend fun loadUpdateInfo() {
|
||||
|
@ -5,8 +5,9 @@ import androidx.databinding.Bindable
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.RvContainer
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
|
||||
class PolicyRvItem(
|
||||
@ -16,7 +17,7 @@ class PolicyRvItem(
|
||||
private val isSharedUid: Boolean,
|
||||
val icon: Drawable,
|
||||
val appName: String
|
||||
) : ObservableDiffRvItem<PolicyRvItem>(), RvContainer<SuPolicy> {
|
||||
) : ObservableRvItem(), DiffItem<PolicyRvItem>, ItemWrapper<SuPolicy> {
|
||||
|
||||
override val layoutRes = R.layout.item_policy_md2
|
||||
|
||||
|
@ -34,9 +34,9 @@ class SuperuserViewModel(
|
||||
private val itemNoData = TextItem(R.string.superuser_policy_none)
|
||||
|
||||
private val itemsHelpers = ObservableArrayList<TextItem>()
|
||||
private val itemsPolicies = DiffRvItemList<PolicyRvItem>()
|
||||
private val itemsPolicies = DiffObservableList<PolicyRvItem>()
|
||||
|
||||
val items = MergeObservableList<AnyDiffRvItem>()
|
||||
val items = MergeObservableList<RvItem>()
|
||||
.insertList(itemsHelpers)
|
||||
.insertList(itemsPolicies)
|
||||
val extraBindings = bindExtra {
|
||||
@ -54,7 +54,7 @@ class SuperuserViewModel(
|
||||
return
|
||||
}
|
||||
loading = true
|
||||
val (policies, diff) = withContext(Dispatchers.IO) {
|
||||
withContext(Dispatchers.IO) {
|
||||
db.deleteOutdated()
|
||||
db.delete(AppContext.applicationInfo.uid)
|
||||
val policies = ArrayList<PolicyRvItem>()
|
||||
@ -91,9 +91,8 @@ class SuperuserViewModel(
|
||||
{ it.appName.lowercase(currentLocale) },
|
||||
{ it.packageName }
|
||||
))
|
||||
policies to itemsPolicies.calculateDiff(policies)
|
||||
itemsPolicies.update(policies)
|
||||
}
|
||||
itemsPolicies.update(policies, diff)
|
||||
if (itemsPolicies.isNotEmpty())
|
||||
itemsHelpers.clear()
|
||||
else if (itemsHelpers.isEmpty())
|
||||
|
@ -22,7 +22,14 @@ import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.databinding.*
|
||||
import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||
import com.topjohnwu.magisk.databinding.ObservableHost
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
import com.topjohnwu.magisk.databinding.bindExtra
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.databinding.setAdapter
|
||||
import com.topjohnwu.magisk.view.MagiskDialog.DialogClickListener
|
||||
|
||||
typealias DialogButtonClickListener = (DialogInterface) -> Unit
|
||||
@ -166,7 +173,7 @@ class MagiskDialog(
|
||||
class DialogItem(
|
||||
override val item: CharSequence,
|
||||
val position: Int
|
||||
) : DiffRvItem<DialogItem>(), RvContainer<CharSequence> {
|
||||
) : RvItem(), DiffItem<DialogItem>, ItemWrapper<CharSequence> {
|
||||
override val layoutRes = R.layout.item_list_single_line
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
package com.topjohnwu.magisk.view
|
||||
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.DiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
|
||||
sealed class TappableHeadlineItem : DiffRvItem<TappableHeadlineItem>() {
|
||||
sealed class TappableHeadlineItem : RvItem(), DiffItem<TappableHeadlineItem> {
|
||||
|
||||
abstract val title: Int
|
||||
abstract val icon: Int
|
||||
|
@ -1,10 +1,10 @@
|
||||
package com.topjohnwu.magisk.view
|
||||
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.DiffRvItem
|
||||
import com.topjohnwu.magisk.databinding.DiffItem
|
||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
|
||||
class TextItem(val text: Int) : DiffRvItem<TextItem>() {
|
||||
class TextItem(override val item: Int) : RvItem(), DiffItem<TextItem>, ItemWrapper<Int> {
|
||||
override val layoutRes = R.layout.item_text
|
||||
|
||||
override fun contentSameAs(other: TextItem) = text == other.text
|
||||
}
|
||||
|
@ -25,9 +25,9 @@
|
||||
|
||||
<include
|
||||
android:id="@+id/log_track_container"
|
||||
bullet="@{item.item.action ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}"
|
||||
bullet="@{item.log.action ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}"
|
||||
isBottom="@{item.isBottom}"
|
||||
isSelected="@{!item.item.action}"
|
||||
isSelected="@{!item.log.action}"
|
||||
isTop="@{item.isTop}"
|
||||
layout="@layout/item_log_track_md2"
|
||||
android:layout_width="wrap_content"
|
||||
@ -51,7 +51,7 @@
|
||||
android:id="@+id/log_app_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{item.item.appName}"
|
||||
android:text="@{item.log.appName}"
|
||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/log_date"
|
||||
@ -76,7 +76,7 @@
|
||||
android:id="@+id/log_app_details"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{String.format(`%s %s`, @string/pid(item.item.fromPid), @string/target_uid(item.item.toUid))}"
|
||||
android:text="@{String.format(`%s %s`, @string/pid(item.log.fromPid), @string/target_uid(item.log.toUid))}"
|
||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
||||
app:layout_constraintBottom_toTopOf="@id/log_command"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -89,7 +89,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="monospace"
|
||||
android:text="@{item.item.command}"
|
||||
android:text="@{item.log.command}"
|
||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -15,7 +15,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/l1"
|
||||
android:text="@{item.text}"
|
||||
android:text="@{item.item}"
|
||||
android:textAppearance="@style/AppearanceFoundation.Tiny.Variant"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user