Commit 067248da authored by topjohnwu's avatar topjohnwu

Cleanup RvItems

parent f5c98235
package com.topjohnwu.magisk.arch package com.topjohnwu.magisk.arch
import androidx.databinding.ViewDataBinding import androidx.databinding.ViewDataBinding
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.AnyDiffRvItem
import com.topjohnwu.magisk.databinding.DiffRvItem
import com.topjohnwu.magisk.databinding.RvItem import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.utils.DiffObservableList import com.topjohnwu.magisk.utils.DiffObservableList
import com.topjohnwu.magisk.utils.FilterableDiffObservableList import com.topjohnwu.magisk.utils.FilterableDiffObservableList
...@@ -9,23 +10,14 @@ import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter ...@@ -9,23 +10,14 @@ import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
import me.tatarka.bindingcollectionadapter2.ItemBinding import me.tatarka.bindingcollectionadapter2.ItemBinding
import me.tatarka.bindingcollectionadapter2.OnItemBind import me.tatarka.bindingcollectionadapter2.OnItemBind
fun <T : ComparableRvItem<*>> diffListOf( fun <T : AnyDiffRvItem> diffListOf() =
vararg newItems: T DiffObservableList(DiffRvItem.callback<T>())
) = diffListOf(newItems.toList())
fun <T : ComparableRvItem<*>> diffListOf( fun <T : AnyDiffRvItem> diffListOf(newItems: List<T>) =
newItems: List<T> DiffObservableList(DiffRvItem.callback<T>()).also { it.update(newItems) }
) = DiffObservableList(object : DiffObservableList.Callback<T> {
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
override fun areContentsTheSame(oldItem: T, newItem: T) = oldItem.genericContentSameAs(newItem)
}).also { it.update(newItems) }
fun <T : ComparableRvItem<*>> filterableListOf( fun <T : AnyDiffRvItem> filterableListOf() =
vararg newItems: T FilterableDiffObservableList(DiffRvItem.callback<T>())
) = FilterableDiffObservableList(object : DiffObservableList.Callback<T> {
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
override fun areContentsTheSame(oldItem: T, newItem: T) = oldItem.genericContentSameAs(newItem)
}).also { it.update(newItems.toList()) }
fun <T : RvItem> adapterOf() = object : BindingRecyclerViewAdapter<T>() { fun <T : RvItem> adapterOf() = object : BindingRecyclerViewAdapter<T>() {
override fun onBindBinding( override fun onBindBinding(
......
...@@ -7,13 +7,15 @@ import kotlinx.coroutines.Dispatchers ...@@ -7,13 +7,15 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.* import java.util.*
class LocalModule(path: String) : Module() { data class LocalModule(
override var id: String = "" private val path: String,
override var name: String = "" override var id: String = "",
override var author: String = "" override var name: String = "",
override var version: String = "" override var author: String = "",
override var versionCode: Int = -1 override var version: String = "",
override var description: String = "" override var versionCode: Int = -1,
override var description: String = "",
) : Module() {
private val removeFile = SuFile(path, "remove") private val removeFile = SuFile(path, "remove")
private val disableFile = SuFile(path, "disable") private val disableFile = SuFile(path, "disable")
......
...@@ -26,38 +26,57 @@ abstract class RvItem { ...@@ -26,38 +26,57 @@ abstract class RvItem {
open fun onBindingBound(binding: ViewDataBinding) {} open fun onBindingBound(binding: ViewDataBinding) {}
} }
abstract class ComparableRvItem<in T> : RvItem() { interface RvContainer<E> {
val item: E
// Use Any.equals by default }
open fun itemSameAs(other: T) = this == other
// Use compareTo if this is Comparable or assume not same interface ComparableRv<T> : Comparable<T> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
open fun contentSameAs(other: T) = fun comparableEqual(o: Any?) =
(this as? Comparable<T>)?.run { compareTo(other) == 0 } ?: false o != null && o::class == this::class && compareTo(o as T) == 0
}
@Suppress("UNCHECKED_CAST") abstract class DiffRvItem<T> : RvItem() {
open fun genericItemSameAs(other: Any): Boolean = other::class == this::class && itemSameAs(other as T)
@Suppress("UNCHECKED_CAST") // Defer to contentSameAs by default
open fun genericContentSameAs(other: Any): Boolean = other::class == this::class && contentSameAs(other as T) 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
}
companion object { companion object {
val callback = object : DiffObservableList.Callback<ComparableRvItem<*>> { private val callback = object : DiffObservableList.Callback<DiffRvItem<Any>> {
override fun areItemsTheSame( override fun areItemsTheSame(
oldItem: ComparableRvItem<*>, oldItem: DiffRvItem<Any>,
newItem: ComparableRvItem<*> newItem: DiffRvItem<Any>
) = oldItem.genericItemSameAs(newItem) ): Boolean {
return oldItem::class == newItem::class && oldItem.itemSameAs(newItem)
}
override fun areContentsTheSame( override fun areContentsTheSame(
oldItem: ComparableRvItem<*>, oldItem: DiffRvItem<Any>,
newItem: ComparableRvItem<*> newItem: DiffRvItem<Any>
) = oldItem.genericContentSameAs(newItem) ): Boolean {
return oldItem.contentSameAs(newItem)
}
} }
@Suppress("UNCHECKED_CAST")
fun <T : AnyDiffRvItem> callback() = callback as DiffObservableList.Callback<T>
} }
} }
abstract class ObservableItem<T> : ComparableRvItem<T>(), ObservableHost { 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 override var callbacks: PropertyChangeRegistry? = null
} }
......
...@@ -6,11 +6,15 @@ import androidx.core.view.updateLayoutParams ...@@ -6,11 +6,15 @@ import androidx.core.view.updateLayoutParams
import androidx.databinding.ViewDataBinding import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.DiffRvItem
import com.topjohnwu.magisk.databinding.LenientRvItem import com.topjohnwu.magisk.databinding.LenientRvItem
import com.topjohnwu.magisk.databinding.RvContainer
import kotlin.math.max import kotlin.math.max
class ConsoleItem(val item: String) : ComparableRvItem<ConsoleItem>(), LenientRvItem { class ConsoleItem(
override val item: String
) : DiffRvItem<ConsoleItem>(), LenientRvItem,
RvContainer<String> {
override val layoutRes = R.layout.item_console_md2 override val layoutRes = R.layout.item_console_md2
private var parentWidth = -1 private var parentWidth = -1
...@@ -31,7 +35,4 @@ class ConsoleItem(val item: String) : ComparableRvItem<ConsoleItem>(), LenientRv ...@@ -31,7 +35,4 @@ class ConsoleItem(val item: String) : ComparableRvItem<ConsoleItem>(), LenientRv
recyclerView.requestLayout() recyclerView.requestLayout()
} }
} }
override fun contentSameAs(other: ConsoleItem) = itemSameAs(other)
override fun itemSameAs(other: ConsoleItem) = item == other.item
} }
...@@ -5,7 +5,8 @@ import android.view.ViewGroup ...@@ -5,7 +5,8 @@ import android.view.ViewGroup
import androidx.databinding.Bindable import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ObservableItem import com.topjohnwu.magisk.databinding.ComparableRv
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
import com.topjohnwu.magisk.ktx.startAnimations import com.topjohnwu.magisk.ktx.startAnimations
import com.topjohnwu.magisk.utils.addOnPropertyChangedCallback import com.topjohnwu.magisk.utils.addOnPropertyChangedCallback
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
...@@ -14,7 +15,7 @@ import kotlin.math.roundToInt ...@@ -14,7 +15,7 @@ import kotlin.math.roundToInt
class HideRvItem( class HideRvItem(
val info: HideAppInfo val info: HideAppInfo
) : ObservableItem<HideRvItem>(), Comparable<HideRvItem> { ) : ObservableDiffRvItem<HideRvItem>(), ComparableRv<HideRvItem> {
override val layoutRes get() = R.layout.item_hide_md2 override val layoutRes get() = R.layout.item_hide_md2
...@@ -89,7 +90,7 @@ class HideRvItem( ...@@ -89,7 +90,7 @@ class HideRvItem(
class HideProcessRvItem( class HideProcessRvItem(
val process: HideProcessInfo val process: HideProcessInfo
) : ObservableItem<HideProcessRvItem>() { ) : ObservableDiffRvItem<HideProcessRvItem>() {
override val layoutRes get() = R.layout.item_hide_process_md2 override val layoutRes get() = R.layout.item_hide_process_md2
......
...@@ -4,12 +4,15 @@ import androidx.databinding.Bindable ...@@ -4,12 +4,15 @@ import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.model.su.SuLog import com.topjohnwu.magisk.core.model.su.SuLog
import com.topjohnwu.magisk.databinding.ObservableItem import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
import com.topjohnwu.magisk.databinding.RvContainer
import com.topjohnwu.magisk.ktx.timeDateFormat import com.topjohnwu.magisk.ktx.timeDateFormat
import com.topjohnwu.magisk.ktx.toTime import com.topjohnwu.magisk.ktx.toTime
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
class LogRvItem(val item: SuLog) : ObservableItem<LogRvItem>() { class LogRvItem(
override val item: SuLog
) : ObservableDiffRvItem<LogRvItem>(), RvContainer<SuLog> {
override val layoutRes = R.layout.item_log_access_md2 override val layoutRes = R.layout.item_log_access_md2
...@@ -24,14 +27,4 @@ class LogRvItem(val item: SuLog) : ObservableItem<LogRvItem>() { ...@@ -24,14 +27,4 @@ class LogRvItem(val item: SuLog) : ObservableItem<LogRvItem>() {
set(value) = set(value, field, { field = it }, BR.bottom) set(value) = set(value, field, { field = it }, BR.bottom)
override fun itemSameAs(other: LogRvItem) = item.appName == other.item.appName override fun itemSameAs(other: LogRvItem) = item.appName == other.item.appName
override fun contentSameAs(other: LogRvItem) = item.fromUid == other.item.fromUid &&
item.toUid == other.item.toUid &&
item.fromPid == other.item.fromPid &&
item.packageName == other.item.packageName &&
item.command == other.item.command &&
item.action == other.item.action &&
item.time == other.item.time &&
isTop == other.isTop &&
isBottom == other.isBottom
} }
...@@ -5,22 +5,20 @@ import com.topjohnwu.magisk.BR ...@@ -5,22 +5,20 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
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.ComparableRvItem import com.topjohnwu.magisk.databinding.DiffRvItem
import com.topjohnwu.magisk.databinding.ObservableItem import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
import com.topjohnwu.magisk.databinding.RvContainer
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
object InstallModule : ComparableRvItem<InstallModule>() { object InstallModule : DiffRvItem<InstallModule>() {
override val layoutRes = R.layout.item_module_download override val layoutRes = R.layout.item_module_download
override fun contentSameAs(other: InstallModule) = this == other
override fun itemSameAs(other: InstallModule) = this === other
} }
class SectionTitle( class SectionTitle(
val title: Int, val title: Int,
_button: Int = 0, _button: Int = 0,
_icon: Int = 0 _icon: Int = 0
) : ObservableItem<SectionTitle>() { ) : ObservableDiffRvItem<SectionTitle>() {
override val layoutRes = R.layout.item_section_md2 override val layoutRes = R.layout.item_section_md2
@get:Bindable @get:Bindable
...@@ -34,12 +32,11 @@ class SectionTitle( ...@@ -34,12 +32,11 @@ class SectionTitle(
@get:Bindable @get:Bindable
var hasButton = _button != 0 && _icon != 0 var hasButton = _button != 0 && _icon != 0
set(value) = set(value, field, { field = it }, BR.hasButton) set(value) = set(value, field, { field = it }, BR.hasButton)
override fun itemSameAs(other: SectionTitle): Boolean = this === other
override fun contentSameAs(other: SectionTitle): Boolean = this === other
} }
class OnlineModuleRvItem(val item: OnlineModule) : ObservableItem<OnlineModuleRvItem>() { class OnlineModuleRvItem(
override val item: OnlineModule
) : ObservableDiffRvItem<OnlineModuleRvItem>(), RvContainer<OnlineModule> {
override val layoutRes: Int = R.layout.item_repo_md2 override val layoutRes: Int = R.layout.item_repo_md2
@get:Bindable @get:Bindable
...@@ -48,12 +45,12 @@ class OnlineModuleRvItem(val item: OnlineModule) : ObservableItem<OnlineModuleRv ...@@ -48,12 +45,12 @@ class OnlineModuleRvItem(val item: OnlineModule) : ObservableItem<OnlineModuleRv
var hasUpdate = false var hasUpdate = false
override fun contentSameAs(other: OnlineModuleRvItem): Boolean = item == other.item
override fun itemSameAs(other: OnlineModuleRvItem): Boolean = item.id == other.item.id override fun itemSameAs(other: OnlineModuleRvItem): Boolean = item.id == other.item.id
} }
class LocalModuleRvItem(val item: LocalModule) : ObservableItem<LocalModuleRvItem>() { class LocalModuleRvItem(
override val item: LocalModule
) : ObservableDiffRvItem<LocalModuleRvItem>(), RvContainer<LocalModule> {
override val layoutRes = R.layout.item_module_md2 override val layoutRes = R.layout.item_module_md2
...@@ -81,10 +78,5 @@ class LocalModuleRvItem(val item: LocalModule) : ObservableItem<LocalModuleRvIte ...@@ -81,10 +78,5 @@ class LocalModuleRvItem(val item: LocalModule) : ObservableItem<LocalModuleRvIte
viewModel.updateActiveState() viewModel.updateActiveState()
} }
override fun contentSameAs(other: LocalModuleRvItem): Boolean = item.version == other.item.version
&& item.versionCode == other.item.versionCode
&& item.description == other.item.description
&& item.name == other.item.name
override fun itemSameAs(other: LocalModuleRvItem): Boolean = item.id == other.item.id override fun itemSameAs(other: LocalModuleRvItem): Boolean = item.id == other.item.id
} }
...@@ -9,7 +9,7 @@ import com.topjohnwu.magisk.arch.* ...@@ -9,7 +9,7 @@ import com.topjohnwu.magisk.arch.*
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
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.ComparableRvItem import com.topjohnwu.magisk.databinding.AnyDiffRvItem
import com.topjohnwu.magisk.databinding.RvItem import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.events.OpenReadmeEvent import com.topjohnwu.magisk.events.OpenReadmeEvent
import com.topjohnwu.magisk.events.SelectModuleEvent import com.topjohnwu.magisk.events.SelectModuleEvent
...@@ -44,8 +44,8 @@ class ModuleViewModel : BaseViewModel(), Queryable { ...@@ -44,8 +44,8 @@ class ModuleViewModel : BaseViewModel(), Queryable {
var searchLoading = false var searchLoading = false
set(value) = set(value, field, { field = it }, BR.searchLoading) set(value) = set(value, field, { field = it }, BR.searchLoading)
val itemsSearch = diffListOf<ComparableRvItem<*>>() val itemsSearch = diffListOf<AnyDiffRvItem>()
val itemSearchBinding = itemBindingOf<ComparableRvItem<*>> { val itemSearchBinding = itemBindingOf<AnyDiffRvItem> {
it.bindExtra(BR.viewModel, this) it.bindExtra(BR.viewModel, this)
} }
...@@ -110,7 +110,7 @@ class ModuleViewModel : BaseViewModel(), Queryable { ...@@ -110,7 +110,7 @@ class ModuleViewModel : BaseViewModel(), Queryable {
// --- // ---
private suspend fun queryInternal(query: String): List<ComparableRvItem<*>> { private suspend fun queryInternal(query: String): List<AnyDiffRvItem> {
return if (query.isBlank()) { return if (query.isBlank()) {
itemsSearch.clear() itemsSearch.clear()
listOf() listOf()
......
...@@ -7,12 +7,12 @@ import androidx.annotation.CallSuper ...@@ -7,12 +7,12 @@ import androidx.annotation.CallSuper
import androidx.databinding.Bindable import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ObservableItem import com.topjohnwu.magisk.databinding.ObservableRvItem
import com.topjohnwu.magisk.utils.TextHolder import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
sealed class BaseSettingsItem : ObservableItem<BaseSettingsItem>() { sealed class BaseSettingsItem : ObservableRvItem() {
override val layoutRes get() = R.layout.item_settings override val layoutRes get() = R.layout.item_settings
...@@ -42,9 +42,6 @@ sealed class BaseSettingsItem : ObservableItem<BaseSettingsItem>() { ...@@ -42,9 +42,6 @@ sealed class BaseSettingsItem : ObservableItem<BaseSettingsItem>() {
open fun refresh() {} open fun refresh() {}
override fun itemSameAs(other: BaseSettingsItem) = this === other
override fun contentSameAs(other: BaseSettingsItem) = itemSameAs(other)
// --- // ---
interface Callback { interface Callback {
......
...@@ -10,7 +10,6 @@ import com.topjohnwu.magisk.BuildConfig ...@@ -10,7 +10,6 @@ import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.adapterOf import com.topjohnwu.magisk.arch.adapterOf
import com.topjohnwu.magisk.arch.diffListOf
import com.topjohnwu.magisk.arch.itemBindingOf import com.topjohnwu.magisk.arch.itemBindingOf
import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
...@@ -32,7 +31,7 @@ class SettingsViewModel( ...@@ -32,7 +31,7 @@ class SettingsViewModel(
val adapter = adapterOf<BaseSettingsItem>() val adapter = adapterOf<BaseSettingsItem>()
val itemBinding = itemBindingOf<BaseSettingsItem> { it.bindExtra(BR.callback, this) } val itemBinding = itemBindingOf<BaseSettingsItem> { it.bindExtra(BR.callback, this) }
val items = diffListOf(createItems()) val items = createItems()
init { init {
viewModelScope.launch { viewModelScope.launch {
......
...@@ -5,14 +5,15 @@ import androidx.databinding.Bindable ...@@ -5,14 +5,15 @@ import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.model.su.SuPolicy import com.topjohnwu.magisk.core.model.su.SuPolicy
import com.topjohnwu.magisk.databinding.ObservableItem import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
import com.topjohnwu.magisk.databinding.RvContainer
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
class PolicyRvItem( class PolicyRvItem(
val item: SuPolicy, override val item: SuPolicy,
val icon: Drawable, val icon: Drawable,
val viewModel: SuperuserViewModel val viewModel: SuperuserViewModel
) : ObservableItem<PolicyRvItem>() { ) : ObservableDiffRvItem<PolicyRvItem>(), RvContainer<SuPolicy> {
override val layoutRes = R.layout.item_policy_md2 override val layoutRes = R.layout.item_policy_md2
@get:Bindable @get:Bindable
...@@ -64,7 +65,6 @@ class PolicyRvItem( ...@@ -64,7 +65,6 @@ class PolicyRvItem(
viewModel.deletePressed(this) viewModel.deletePressed(this)
} }
override fun contentSameAs(other: PolicyRvItem) = itemSameAs(other)
override fun itemSameAs(other: PolicyRvItem) = item.uid == other.item.uid override fun itemSameAs(other: PolicyRvItem) = item.uid == other.item.uid
} }
...@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.core.magiskdb.PolicyDao ...@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.core.magiskdb.PolicyDao
import com.topjohnwu.magisk.core.model.su.SuPolicy import com.topjohnwu.magisk.core.model.su.SuPolicy
import com.topjohnwu.magisk.core.utils.BiometricHelper import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.core.utils.currentLocale import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.AnyDiffRvItem
import com.topjohnwu.magisk.events.SnackbarEvent import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.events.dialog.BiometricEvent import com.topjohnwu.magisk.events.dialog.BiometricEvent
import com.topjohnwu.magisk.events.dialog.SuperuserRevokeDialog import com.topjohnwu.magisk.events.dialog.SuperuserRevokeDialog
...@@ -35,13 +35,13 @@ class SuperuserViewModel( ...@@ -35,13 +35,13 @@ class SuperuserViewModel(
private val itemsPolicies = diffListOf<PolicyRvItem>() private val itemsPolicies = diffListOf<PolicyRvItem>()
private val itemsHelpers = ObservableArrayList<TextItem>() private val itemsHelpers = ObservableArrayList<TextItem>()
val adapter = adapterOf<ComparableRvItem<*>>() val adapter = adapterOf<AnyDiffRvItem>()
val items = MergeObservableList<ComparableRvItem<*>>().apply { val items = MergeObservableList<AnyDiffRvItem>().apply {
if (Config.magiskHide) if (Config.magiskHide)
insertItem(TappableHeadlineItem.Hide) insertItem(TappableHeadlineItem.Hide)
}.insertList(itemsHelpers) }.insertList(itemsHelpers)
.insertList(itemsPolicies) .insertList(itemsPolicies)
val itemBinding = itemBindingOf<ComparableRvItem<*>> { val itemBinding = itemBindingOf<AnyDiffRvItem> {
it.bindExtra(BR.listener, this) it.bindExtra(BR.listener, this)
} }
...@@ -84,7 +84,7 @@ class SuperuserViewModel( ...@@ -84,7 +84,7 @@ 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.genericItemSameAs(item) } itemsPolicies.removeAll { it.itemSameAs(item) }
if (itemsPolicies.isEmpty() && itemsHelpers.isEmpty()) { if (itemsPolicies.isEmpty() && itemsHelpers.isEmpty()) {
itemsHelpers.add(itemNoData) itemsHelpers.add(itemNoData)
} }
......
...@@ -17,7 +17,6 @@ open class DiffObservableList<T>( ...@@ -17,7 +17,6 @@ open class DiffObservableList<T>(
private val detectMoves: Boolean = true private val detectMoves: Boolean = true
) : AbstractList<T>(), ObservableList<T> { ) : AbstractList<T>(), ObservableList<T> {
private val LIST_LOCK = Object()
protected var list: MutableList<T> = ArrayList() protected var list: MutableList<T> = ArrayList()
private val listeners = ListChangeRegistry() private val listeners = ListChangeRegistry()
protected val listCallback = ObservableListUpdateCallback() protected val listCallback = ObservableListUpdateCallback()
...@@ -32,27 +31,25 @@ open class DiffObservableList<T>( ...@@ -32,27 +31,25 @@ open class DiffObservableList<T>(
* list into the given one. * list into the given one.
*/ */
fun calculateDiff(newItems: List<T>): DiffUtil.DiffResult { fun calculateDiff(newItems: List<T>): DiffUtil.DiffResult {
val frozenList = synchronized(LIST_LOCK) { val frozenList = ArrayList(list)
ArrayList(list)
}
return doCalculateDiff(frozenList, newItems) return doCalculateDiff(frozenList, newItems)
} }
protected fun doCalculateDiff(oldItems: List<T>, newItems: List<T>?): DiffUtil.DiffResult { protected fun doCalculateDiff(oldItems: List<T>, newItems: List<T>): DiffUtil.DiffResult {
return DiffUtil.calculateDiff(object : DiffUtil.Callback() { return DiffUtil.calculateDiff(object : DiffUtil.Callback() {
override fun getOldListSize() = oldItems.size override fun getOldListSize() = oldItems.size
override fun getNewListSize() = newItems?.size ?: 0 override fun getNewListSize() = newItems.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldItems[oldItemPosition] val oldItem = oldItems[oldItemPosition]
val newItem = newItems!![newItemPosition] val newItem = newItems[newItemPosition]
return callback.areItemsTheSame(oldItem, newItem) return callback.areItemsTheSame(oldItem, newItem)
} }
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldItems[oldItemPosition] val oldItem = oldItems[oldItemPosition]
val newItem = newItems!![newItemPosition] val newItem = newItems[newItemPosition]
return callback.areContentsTheSame(oldItem, newItem) return callback.areContentsTheSame(oldItem, newItem)
} }
}, detectMoves) }, detectMoves)
...@@ -67,9 +64,7 @@ open class DiffObservableList<T>( ...@@ -67,9 +64,7 @@ open class DiffObservableList<T>(
*/ */
@MainThread @MainThread
fun update(newItems: List<T>, diffResult: DiffUtil.DiffResult) { fun update(newItems: List<T>, diffResult: DiffUtil.DiffResult) {
synchronized(LIST_LOCK) {
list = newItems.toMutableList() list = newItems.toMutableList()
}
diffResult.dispatchUpdatesTo(listCallback) diffResult.dispatchUpdatesTo(listCallback)
} }
...@@ -97,29 +92,14 @@ open class DiffObservableList<T>( ...@@ -97,29 +92,14 @@ open class DiffObservableList<T>(
listeners.remove(listener) listeners.remove(listener)
} }
override fun get(index: Int): T { override fun get(index: Int) = list[index]
return list[index]
}
override fun add(element: T): Boolean {
list.add(element)
notifyAdd(size - 1, 1)
return true
}
override fun add(index: Int, element: T) { override fun add(index: Int, element: T) {
list.add(index, element) list.add(index, element)
notifyAdd(index, 1) notifyAdd(index, 1)
} }
override fun addAll(elements: Collection<T>): Boolean { override fun addAll(elements: Collection<T>) = addAll(size, elements)
val oldSize = size
val added = list.addAll(elements)
if (added) {
notifyAdd(oldSize, size - oldSize)
}
return added
}
override fun addAll(index: Int, elements: Collection<T>): Boolean { override fun addAll(index: Int, elements: Collection<T>): Boolean {
val added = list.addAll(index, elements) val added = list.addAll(index, elements)
...@@ -153,14 +133,6 @@ open class DiffObservableList<T>( ...@@ -153,14 +133,6 @@ open class DiffObservableList<T>(
return element return element
} }
fun removeLast(): T? {
if (size > 0) {
val index = size - 1
return removeAt(index)
}
return null
}
override fun set(index: Int, element: T): T { override fun set(index: Int, element: T): T {
val old = list.set(index, element) val old = list.set(index, element)
listeners.notifyChanged(this, index, 1) listeners.notifyChanged(this, index, 1)
...@@ -228,6 +200,5 @@ open class DiffObservableList<T>( ...@@ -228,6 +200,5 @@ open class DiffObservableList<T>(
modCount += 1 modCount += 1
listeners.notifyRemoved(this@DiffObservableList, position, count) listeners.notifyRemoved(this@DiffObservableList, position, count)
} }
} }
} }
...@@ -23,8 +23,9 @@ import com.google.android.material.shape.MaterialShapeDrawable ...@@ -23,8 +23,9 @@ import com.google.android.material.shape.MaterialShapeDrawable
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.itemBindingOf import com.topjohnwu.magisk.arch.itemBindingOf
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.DiffRvItem
import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
import com.topjohnwu.magisk.databinding.RvContainer
import com.topjohnwu.magisk.utils.ObservableHost import com.topjohnwu.magisk.utils.ObservableHost
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapters import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapters
...@@ -188,12 +189,10 @@ class MagiskDialog( ...@@ -188,12 +189,10 @@ class MagiskDialog(
} }
class DialogItem( class DialogItem(
val item: CharSequence, override val item: CharSequence,
val position: Int val position: Int
) : ComparableRvItem<DialogItem>() { ) : DiffRvItem<DialogItem>(), RvContainer<CharSequence> {
override val layoutRes = R.layout.item_list_single_line override val layoutRes = R.layout.item_list_single_line
override fun itemSameAs(other: DialogItem) = item == other.item
override fun contentSameAs(other: DialogItem) = itemSameAs(other)
} }
interface ActualOnDialogClickListener { interface ActualOnDialogClickListener {
......
package com.topjohnwu.magisk.view package com.topjohnwu.magisk.view
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.DiffRvItem
sealed class TappableHeadlineItem : ComparableRvItem<TappableHeadlineItem>() { sealed class TappableHeadlineItem : DiffRvItem<TappableHeadlineItem>() {
abstract val title: Int abstract val title: Int
abstract val icon: Int abstract val icon: Int
override val layoutRes = R.layout.item_tappable_headline override val layoutRes = R.layout.item_tappable_headline
override fun itemSameAs(other: TappableHeadlineItem) =
this === other
override fun contentSameAs(other: TappableHeadlineItem) =
title == other.title && icon == other.icon
// --- listener // --- listener
interface Listener { interface Listener {
......
package com.topjohnwu.magisk.view package com.topjohnwu.magisk.view
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.DiffRvItem
class TextItem(val text: Int) : ComparableRvItem<TextItem>() { class TextItem(val text: Int) : DiffRvItem<TextItem>() {
override val layoutRes = R.layout.item_text override val layoutRes = R.layout.item_text
override fun contentSameAs(other: TextItem) = text == other.text override fun contentSameAs(other: TextItem) = text == other.text
override fun itemSameAs(other: TextItem) = contentSameAs(other)
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment