mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-07 19:44:27 +00:00
Cleanup RvItems
This commit is contained in:
parent
f5c982355a
commit
067248da75
@ -1,7 +1,8 @@
|
|||||||
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
|
|||||||
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
|
|||||||
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 {
|
|||||||
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
|
interface ComparableRv<T> : Comparable<T> {
|
||||||
open fun itemSameAs(other: T) = this == other
|
|
||||||
|
|
||||||
// Use compareTo if this is Comparable or assume not same
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@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) =
|
open fun contentSameAs(other: T) =
|
||||||
(this as? Comparable<T>)?.run { compareTo(other) == 0 } ?: false
|
when (this) {
|
||||||
|
is RvContainer<*> -> item == (other as RvContainer<*>).item
|
||||||
@Suppress("UNCHECKED_CAST")
|
is ComparableRv<*> -> comparableEqual(other)
|
||||||
open fun genericItemSameAs(other: Any): Boolean = other::class == this::class && itemSameAs(other as T)
|
else -> this == other
|
||||||
|
}
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
open fun genericContentSameAs(other: Any): Boolean = other::class == this::class && contentSameAs(other as T)
|
|
||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
|
|
||||||
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(
|
|||||||
|
|
||||||
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
|
|||||||
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>() {
|
|||||||
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
|
|||||||
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(
|
|||||||
@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
|
|||||||
|
|
||||||
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
|
|||||||
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.*
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
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
|
|||||||
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>() {
|
|||||||
|
|
||||||
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
|
|||||||
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(
|
|||||||
|
|
||||||
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
|
|||||||
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(
|
|||||||
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
|
|||||||
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(
|
|||||||
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(
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,10 @@ import kotlin.collections.ArrayList
|
|||||||
* @param detectMoves True if DiffUtil should try to detect moved items, false otherwise.
|
* @param detectMoves True if DiffUtil should try to detect moved items, false otherwise.
|
||||||
*/
|
*/
|
||||||
open class DiffObservableList<T>(
|
open class DiffObservableList<T>(
|
||||||
private val callback: Callback<T>,
|
private val callback: Callback<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>(
|
|||||||
* 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>(
|
|||||||
*/
|
*/
|
||||||
@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>(
|
|||||||
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>(
|
|||||||
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>(
|
|||||||
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
|
|||||||
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(
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
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 {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
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)
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user