Updated policy items so listeners are not indirectly set to them and kept out of the instance of the parent object

This commit is contained in:
Viktor De Pasquale 2019-04-19 19:22:18 +02:00
parent ad80804461
commit ce693aa5e9
4 changed files with 80 additions and 55 deletions

View File

@ -11,6 +11,6 @@ import org.koin.dsl.module
val viewModelModules = module { val viewModelModules = module {
viewModel { MainViewModel() } viewModel { MainViewModel() }
viewModel { HomeViewModel(get(), get()) } viewModel { HomeViewModel(get(), get()) }
viewModel { SuperuserViewModel(get(), get(), get()) } viewModel { SuperuserViewModel(get(), get(), get(), get()) }
viewModel { HideViewModel(get(), get()) } viewModel { HideViewModel(get(), get()) }
} }

View File

@ -2,9 +2,14 @@ package com.topjohnwu.magisk.model.entity.recycler
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import com.skoumal.teanity.databinding.ComparableRvItem import com.skoumal.teanity.databinding.ComparableRvItem
import com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import com.skoumal.teanity.rxbus.RxBus
import com.skoumal.teanity.util.KObservableField import com.skoumal.teanity.util.KObservableField
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.entity.Policy import com.topjohnwu.magisk.model.entity.Policy
import com.topjohnwu.magisk.model.events.PolicyEnableEvent
import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
import com.topjohnwu.magisk.utils.inject
import com.topjohnwu.magisk.utils.toggle import com.topjohnwu.magisk.utils.toggle
class PolicyRvItem(val item: Policy, val icon: Drawable) : ComparableRvItem<PolicyRvItem>() { class PolicyRvItem(val item: Policy, val icon: Drawable) : ComparableRvItem<PolicyRvItem>() {
@ -18,6 +23,25 @@ class PolicyRvItem(val item: Policy, val icon: Drawable) : ComparableRvItem<Poli
fun toggle() = isExpanded.toggle() fun toggle() = isExpanded.toggle()
private val rxBus: RxBus by inject()
init {
isEnabled.addOnPropertyChangedCallback {
it ?: return@addOnPropertyChangedCallback
rxBus.post(PolicyEnableEvent(this@PolicyRvItem, it))
}
shouldNotify.addOnPropertyChangedCallback {
it ?: return@addOnPropertyChangedCallback
item.notification = it
rxBus.post(PolicyUpdateEvent.Notification(this@PolicyRvItem))
}
shouldLog.addOnPropertyChangedCallback {
it ?: return@addOnPropertyChangedCallback
item.logging = it
rxBus.post(PolicyUpdateEvent.Log(this@PolicyRvItem))
}
}
override fun contentSameAs(other: PolicyRvItem): Boolean = itemSameAs(other) override fun contentSameAs(other: PolicyRvItem): Boolean = itemSameAs(other)
override fun itemSameAs(other: PolicyRvItem): Boolean = item.uid == other.item.uid override fun itemSameAs(other: PolicyRvItem): Boolean = item.uid == other.item.uid
} }

View File

@ -2,5 +2,12 @@ package com.topjohnwu.magisk.model.events
import com.skoumal.teanity.rxbus.RxBus import com.skoumal.teanity.rxbus.RxBus
import com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem import com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem
import com.topjohnwu.magisk.model.entity.recycler.PolicyRvItem
class HideProcessEvent(val item: HideProcessRvItem) : RxBus.Event class HideProcessEvent(val item: HideProcessRvItem) : RxBus.Event
class PolicyEnableEvent(val item: PolicyRvItem, val enable: Boolean) : RxBus.Event
sealed class PolicyUpdateEvent(val item: PolicyRvItem) : RxBus.Event {
class Notification(item: PolicyRvItem) : PolicyUpdateEvent(item)
class Log(item: PolicyRvItem) : PolicyUpdateEvent(item)
}

View File

@ -3,9 +3,9 @@ package com.topjohnwu.magisk.ui.superuser
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Resources import android.content.res.Resources
import com.skoumal.teanity.databinding.ComparableRvItem import com.skoumal.teanity.databinding.ComparableRvItem
import com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import com.skoumal.teanity.extensions.applySchedulers import com.skoumal.teanity.extensions.applySchedulers
import com.skoumal.teanity.extensions.subscribeK import com.skoumal.teanity.extensions.subscribeK
import com.skoumal.teanity.rxbus.RxBus
import com.skoumal.teanity.util.DiffObservableList import com.skoumal.teanity.util.DiffObservableList
import com.skoumal.teanity.viewevents.SnackbarEvent import com.skoumal.teanity.viewevents.SnackbarEvent
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
@ -13,6 +13,8 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.database.MagiskDB import com.topjohnwu.magisk.data.database.MagiskDB
import com.topjohnwu.magisk.model.entity.Policy import com.topjohnwu.magisk.model.entity.Policy
import com.topjohnwu.magisk.model.entity.recycler.PolicyRvItem import com.topjohnwu.magisk.model.entity.recycler.PolicyRvItem
import com.topjohnwu.magisk.model.events.PolicyEnableEvent
import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
import com.topjohnwu.magisk.ui.base.MagiskViewModel import com.topjohnwu.magisk.ui.base.MagiskViewModel
import com.topjohnwu.magisk.utils.FingerprintHelper import com.topjohnwu.magisk.utils.FingerprintHelper
import com.topjohnwu.magisk.utils.toggle import com.topjohnwu.magisk.utils.toggle
@ -24,7 +26,8 @@ import me.tatarka.bindingcollectionadapter2.ItemBinding
class SuperuserViewModel( class SuperuserViewModel(
private val database: MagiskDB, private val database: MagiskDB,
private val packageManager: PackageManager, private val packageManager: PackageManager,
private val resources: Resources private val resources: Resources,
rxBus: RxBus
) : MagiskViewModel() { ) : MagiskViewModel() {
val items = DiffObservableList(ComparableRvItem.callback) val items = DiffObservableList(ComparableRvItem.callback)
@ -36,13 +39,20 @@ class SuperuserViewModel(
private var ignoreNext: PolicyRvItem? = null private var ignoreNext: PolicyRvItem? = null
init { init {
rxBus.register<PolicyEnableEvent>()
.subscribeK { togglePolicy(it.item, it.enable) }
.add()
rxBus.register<PolicyUpdateEvent>()
.subscribeK { updatePolicy(it) }
.add()
updatePolicies() updatePolicies()
} }
fun updatePolicies() { fun updatePolicies() {
Single.fromCallable { database.policyList } Single.fromCallable { database.policyList }
.flattenAsFlowable { it } .flattenAsFlowable { it }
.map { PolicyRvItem(it, it.info.loadIcon(packageManager)).setListeners() } .map { PolicyRvItem(it, it.info.loadIcon(packageManager)) }
.toList() .toList()
.applySchedulers() .applySchedulers()
.applyViewModel(this) .applyViewModel(this)
@ -70,23 +80,34 @@ class SuperuserViewModel(
} }
} }
private fun PolicyRvItem.setListeners() = apply { private fun updatePolicy(it: PolicyUpdateEvent) = when (it) {
isEnabled.addOnPropertyChangedCallback { is PolicyUpdateEvent.Notification -> updatePolicy(it.item) {
it ?: return@addOnPropertyChangedCallback val textId = if (it.logging) R.string.su_snack_notif_on else R.string.su_snack_notif_off
val text = resources.getString(textId).format(it.appName)
if (ignoreNext == this) { SnackbarEvent(text).publish()
ignoreNext = null }
return@addOnPropertyChangedCallback is PolicyUpdateEvent.Log -> updatePolicy(it.item) {
val textId =
if (it.notification) R.string.su_snack_log_on else R.string.su_snack_log_off
val text = resources.getString(textId).format(it.appName)
SnackbarEvent(text).publish()
}
} }
fun updateState() { private fun updatePolicy(item: PolicyRvItem, onSuccess: (Policy) -> Unit) =
item.policy = if (it) Policy.ALLOW else Policy.DENY updatePolicy(item.item)
.subscribeK { onSuccess(it) }
.add()
updatePolicy(item) private fun togglePolicy(item: PolicyRvItem, enable: Boolean) {
fun updateState() {
item.item.policy = if (enable) Policy.ALLOW else Policy.DENY
updatePolicy(item.item)
.map { it.policy == Policy.ALLOW } .map { it.policy == Policy.ALLOW }
.subscribeK { .subscribeK {
val textId = if (it) R.string.su_snack_grant else R.string.su_snack_deny val textId = if (it) R.string.su_snack_grant else R.string.su_snack_deny
val text = resources.getString(textId).format(item.appName) val text = resources.getString(textId).format(item.item.appName)
SnackbarEvent(text).publish() SnackbarEvent(text).publish()
} }
.add() .add()
@ -95,41 +116,14 @@ class SuperuserViewModel(
if (FingerprintHelper.useFingerprint()) { if (FingerprintHelper.useFingerprint()) {
withView { withView {
FingerprintAuthDialog(this, { updateState() }, { FingerprintAuthDialog(this, { updateState() }, {
ignoreNext = this@setListeners ignoreNext = item
isEnabled.toggle() item.isEnabled.toggle()
}).show() }).show()
} }
} else { } else {
updateState() updateState()
} }
} }
shouldNotify.addOnPropertyChangedCallback {
it ?: return@addOnPropertyChangedCallback
item.notification = it
updatePolicy(item)
.map { it.notification }
.subscribeK {
val textId = if (it) R.string.su_snack_notif_on else R.string.su_snack_notif_off
val text = resources.getString(textId).format(item.appName)
SnackbarEvent(text).publish()
}
.add()
}
shouldLog.addOnPropertyChangedCallback {
it ?: return@addOnPropertyChangedCallback
item.logging = it
updatePolicy(item)
.map { it.logging }
.subscribeK {
val textId = if (it) R.string.su_snack_log_on else R.string.su_snack_log_off
val text = resources.getString(textId).format(item.appName)
SnackbarEvent(text).publish()
}
.add()
}
}
private fun updatePolicy(policy: Policy) = private fun updatePolicy(policy: Policy) =
Single.fromCallable { database.updatePolicy(policy); policy } Single.fromCallable { database.updatePolicy(policy); policy }