Remove usage of KObservableField

This commit is contained in:
topjohnwu 2020-07-08 06:14:32 -07:00
parent 8ffbffddb3
commit 18dab28c32
27 changed files with 93 additions and 172 deletions

View File

@ -21,8 +21,8 @@ import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.utils.refreshLocale import com.topjohnwu.magisk.core.utils.refreshLocale
import com.topjohnwu.magisk.core.utils.updateConfig import com.topjohnwu.magisk.core.utils.updateConfig
import com.topjohnwu.magisk.extensions.forceGetDeclaredField import com.topjohnwu.magisk.extensions.forceGetDeclaredField
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import com.topjohnwu.magisk.ui.MainActivity import com.topjohnwu.magisk.ui.MainActivity
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
fun AssetManager.addAssetPath(path: String) { fun AssetManager.addAssetPath(path: String) {
DynAPK.addAssetPath(this, path) DynAPK.addAssetPath(this, path)

View File

@ -1,12 +1,13 @@
package com.topjohnwu.magisk.core package com.topjohnwu.magisk.core
import androidx.databinding.ObservableField
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.topjohnwu.magisk.DynAPK import com.topjohnwu.magisk.DynAPK
import com.topjohnwu.magisk.core.model.UpdateInfo import com.topjohnwu.magisk.core.model.UpdateInfo
import com.topjohnwu.magisk.extensions.get import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.utils.CachedValue import com.topjohnwu.magisk.utils.CachedValue
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils.fastCmd import com.topjohnwu.superuser.ShellUtils.fastCmd
import java.io.FileInputStream import java.io.FileInputStream
@ -35,7 +36,7 @@ object Info {
@JvmStatic var ramdisk = false @JvmStatic var ramdisk = false
val isConnected by lazy { val isConnected by lazy {
KObservableField(false).also { field -> ObservableField(false).also { field ->
ReactiveNetwork.observeNetworkConnectivity(get()) ReactiveNetwork.observeNetworkConnectivity(get())
.subscribeK { .subscribeK {
field.value = it.available() field.value = it.available()

View File

@ -5,7 +5,6 @@ import android.content.pm.PackageManager
import android.util.Base64 import android.util.Base64
import android.util.Base64OutputStream import android.util.Base64OutputStream
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.utils.PatchAPK.ALPHANUM
import com.topjohnwu.signing.CryptoUtils.readCertificate import com.topjohnwu.signing.CryptoUtils.readCertificate
import com.topjohnwu.signing.CryptoUtils.readPrivateKey import com.topjohnwu.signing.CryptoUtils.readPrivateKey
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name

View File

@ -11,7 +11,10 @@ import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toAdaptiveIcon import androidx.core.graphics.drawable.toAdaptiveIcon
import androidx.core.graphics.drawable.toIcon import androidx.core.graphics.drawable.toIcon
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.* import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.SplashActivity
import com.topjohnwu.magisk.core.intent
import com.topjohnwu.magisk.core.utils.Utils import com.topjohnwu.magisk.core.utils.Utils
import com.topjohnwu.magisk.extensions.getBitmap import com.topjohnwu.magisk.extensions.getBitmap

View File

@ -54,4 +54,12 @@ inline fun <T> ObservableField<T>.updateNonNull(block: (T) -> Unit) {
inline fun ObservableInt.update(block: (Int) -> Unit) { inline fun ObservableInt.update(block: (Int) -> Unit) {
set(get().apply(block)) set(get().apply(block))
} }
inline var <T> ObservableField<T>.value
get() = get() as T
set(value) {
// Use Kotlin comparision (Any.equals)
if (value != get())
set(value)
}

View File

@ -1,7 +1,6 @@
package com.topjohnwu.magisk.extensions package com.topjohnwu.magisk.extensions
import androidx.databinding.ObservableField import androidx.databinding.ObservableField
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.internal.UiThreadHandler import com.topjohnwu.superuser.internal.UiThreadHandler
import io.reactivex.* import io.reactivex.*
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
@ -76,34 +75,6 @@ fun Completable.subscribeK(
) = applySchedulers() ) = applySchedulers()
.subscribe(onComplete, onError) .subscribe(onComplete, onError)
fun <T> Observable<out T>.updateBy(
field: KObservableField<T?>
) = doOnNextUi { field.value = it }
.doOnErrorUi { field.value = null }
fun <T> Single<out T>.updateBy(
field: KObservableField<T?>
) = doOnSuccessUi { field.value = it }
.doOnErrorUi { field.value = null }
fun <T> Maybe<out T>.updateBy(
field: KObservableField<T?>
) = doOnSuccessUi { field.value = it }
.doOnErrorUi { field.value = null }
.doOnComplete { field.value = field.value }
fun <T> Flowable<out T>.updateBy(
field: KObservableField<T?>
) = doOnNextUi { field.value = it }
.doOnErrorUi { field.value = null }
fun Completable.updateBy(
field: KObservableField<Boolean>
) = doOnCompleteUi { field.value = true }
.doOnErrorUi { field.value = false }
fun <T> Observable<T>.doOnSubscribeUi(body: () -> Unit) = fun <T> Observable<T>.doOnSubscribeUi(body: () -> Unit) =
doOnSubscribe { UiThreadHandler.run { body() } } doOnSubscribe { UiThreadHandler.run { body() } }
@ -202,4 +173,4 @@ inline fun <T1, T2, R> zip(
t1: Single<T1>, t1: Single<T1>,
t2: Single<T2>, t2: Single<T2>,
crossinline zipper: (T1, T2) -> R crossinline zipper: (T1, T2) -> R
) = Single.zip(t1, t2, BiFunction<T1, T2, R> { rt1, rt2 -> zipper(rt1, rt2) }) ) = Single.zip(t1, t2, BiFunction<T1, T2, R> { rt1, rt2 -> zipper(rt1, rt2) })

View File

@ -1,10 +1,10 @@
package com.topjohnwu.magisk.extensions package com.topjohnwu.magisk.extensions
import androidx.databinding.ObservableField
import androidx.databinding.ObservableList import androidx.databinding.ObservableList
import com.topjohnwu.magisk.utils.KObservableField
fun KObservableField<Boolean>.toggle() { fun ObservableField<Boolean>.toggle() {
value = !value value = !value
} }
@ -68,4 +68,4 @@ fun <T> ObservableList<T>.addOnListChangedCallback(
itemCount itemCount
) )
} }
}) })

View File

@ -2,16 +2,17 @@ package com.topjohnwu.magisk.model.entity.recycler
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.databinding.ObservableField
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback import com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import com.topjohnwu.magisk.extensions.startAnimations import com.topjohnwu.magisk.extensions.startAnimations
import com.topjohnwu.magisk.extensions.toggle import com.topjohnwu.magisk.extensions.toggle
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.entity.ProcessHideApp import com.topjohnwu.magisk.model.entity.ProcessHideApp
import com.topjohnwu.magisk.model.entity.StatefulProcess import com.topjohnwu.magisk.model.entity.StatefulProcess
import com.topjohnwu.magisk.model.observer.Observer import com.topjohnwu.magisk.model.observer.Observer
import com.topjohnwu.magisk.ui.hide.HideViewModel import com.topjohnwu.magisk.ui.hide.HideViewModel
import com.topjohnwu.magisk.utils.KObservableField
import kotlin.math.roundToInt import kotlin.math.roundToInt
class HideItem(val item: ProcessHideApp) : ComparableRvItem<HideItem>() { class HideItem(val item: ProcessHideApp) : ComparableRvItem<HideItem>() {
@ -21,8 +22,8 @@ class HideItem(val item: ProcessHideApp) : ComparableRvItem<HideItem>() {
val packageName = item.info.info.packageName.orEmpty() val packageName = item.info.info.packageName.orEmpty()
val items = item.processes.map { HideProcessItem(it) } val items = item.processes.map { HideProcessItem(it) }
val isExpanded = KObservableField(false) val isExpanded = ObservableField(false)
val itemsChecked = KObservableField(0) val itemsChecked = ObservableField(0)
val itemsCheckedPercent = Observer(itemsChecked) { val itemsCheckedPercent = Observer(itemsChecked) {
(itemsChecked.value.toFloat() / items.size * 100).roundToInt() (itemsChecked.value.toFloat() / items.size * 100).roundToInt()
} }
@ -68,7 +69,7 @@ class HideProcessItem(val item: StatefulProcess) : ComparableRvItem<HideProcessI
override val layoutRes = R.layout.item_hide_process_md2 override val layoutRes = R.layout.item_hide_process_md2
val isHidden = KObservableField(item.isHidden) val isHidden = ObservableField(item.isHidden)
fun toggle(viewModel: HideViewModel) { fun toggle(viewModel: HideViewModel) {
isHidden.toggle() isHidden.toggle()

View File

@ -1,9 +1,6 @@
package com.topjohnwu.magisk.model.entity.recycler package com.topjohnwu.magisk.model.entity.recycler
import androidx.databinding.Bindable import androidx.databinding.*
import androidx.databinding.Observable
import androidx.databinding.PropertyChangeRegistry
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.StaggeredGridLayoutManager import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
@ -11,7 +8,6 @@ import com.topjohnwu.magisk.core.model.module.Module
import com.topjohnwu.magisk.core.model.module.Repo import com.topjohnwu.magisk.core.model.module.Repo
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.ui.module.ModuleViewModel import com.topjohnwu.magisk.ui.module.ModuleViewModel
import com.topjohnwu.magisk.utils.KObservableField
object InstallModule : ComparableRvItem<InstallModule>() { object InstallModule : ComparableRvItem<InstallModule>() {
override val layoutRes = R.layout.item_module_download override val layoutRes = R.layout.item_module_download
@ -65,7 +61,7 @@ class SectionTitle(
sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() { sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() {
override val layoutRes: Int = R.layout.item_repo_md2 override val layoutRes: Int = R.layout.item_repo_md2
val progress = KObservableField(0) val progress = ObservableField(0)
var isUpdate = false var isUpdate = false
@Bindable get @Bindable get
protected set(value) { protected set(value) {

View File

@ -1,23 +1,24 @@
package com.topjohnwu.magisk.model.entity.recycler package com.topjohnwu.magisk.model.entity.recycler
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import androidx.databinding.ObservableField
import androidx.databinding.ViewDataBinding import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.StaggeredGridLayoutManager import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.model.MagiskPolicy import com.topjohnwu.magisk.core.model.MagiskPolicy
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.extensions.toggle import com.topjohnwu.magisk.extensions.toggle
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.events.PolicyUpdateEvent import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
import com.topjohnwu.magisk.ui.superuser.SuperuserViewModel import com.topjohnwu.magisk.ui.superuser.SuperuserViewModel
import com.topjohnwu.magisk.utils.KObservableField
class PolicyItem(val item: MagiskPolicy, val icon: Drawable) : ComparableRvItem<PolicyItem>() { class PolicyItem(val item: MagiskPolicy, val icon: Drawable) : ComparableRvItem<PolicyItem>() {
override val layoutRes = R.layout.item_policy_md2 override val layoutRes = R.layout.item_policy_md2
val isExpanded = KObservableField(false) val isExpanded = ObservableField(false)
val isEnabled = KObservableField(item.policy == MagiskPolicy.ALLOW) val isEnabled = ObservableField(item.policy == MagiskPolicy.ALLOW)
val shouldNotify = KObservableField(item.notification) val shouldNotify = ObservableField(item.notification)
val shouldLog = KObservableField(item.logging) val shouldLog = ObservableField(item.logging)
private val updatedPolicy private val updatedPolicy
get() = item.copy( get() = item.copy(

View File

@ -6,7 +6,6 @@ import android.view.View
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import android.view.WindowManager import android.view.WindowManager
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.graphics.Insets
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.core.view.setPadding import androidx.core.view.setPadding
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
@ -138,10 +137,6 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
return true return true
} }
override fun peekSystemWindowInsets(insets: Insets) {
viewModel.insets.value = insets
}
fun setDisplayHomeAsUpEnabled(isEnabled: Boolean) { fun setDisplayHomeAsUpEnabled(isEnabled: Boolean) {
binding.mainToolbar.startAnimations() binding.mainToolbar.startAnimations()
when { when {

View File

@ -20,6 +20,7 @@ import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.base.BaseActivity import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.extensions.snackbar import com.topjohnwu.magisk.extensions.snackbar
import com.topjohnwu.magisk.extensions.startAnimations import com.topjohnwu.magisk.extensions.startAnimations
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.events.EventHandler import com.topjohnwu.magisk.model.events.EventHandler
import com.topjohnwu.magisk.model.events.SnackbarEvent import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.model.events.ViewEvent import com.topjohnwu.magisk.model.events.ViewEvent

View File

@ -4,6 +4,7 @@ import android.Manifest
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.databinding.Bindable import androidx.databinding.Bindable
import androidx.databinding.ObservableField
import androidx.databinding.PropertyChangeRegistry import androidx.databinding.PropertyChangeRegistry
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
@ -13,10 +14,10 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.BaseActivity import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.extensions.doOnSubscribeUi import com.topjohnwu.magisk.extensions.doOnSubscribeUi
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.events.* import com.topjohnwu.magisk.model.events.*
import com.topjohnwu.magisk.model.navigation.NavigationWrapper import com.topjohnwu.magisk.model.navigation.NavigationWrapper
import com.topjohnwu.magisk.model.observer.Observer import com.topjohnwu.magisk.model.observer.Observer
import com.topjohnwu.magisk.utils.KObservableField
import io.reactivex.* import io.reactivex.*
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
@ -40,7 +41,7 @@ abstract class BaseViewModel(
val isConnected = Observer(Info.isConnected) { Info.isConnected.value } val isConnected = Observer(Info.isConnected) { Info.isConnected.value }
val viewEvents: LiveData<ViewEvent> get() = _viewEvents val viewEvents: LiveData<ViewEvent> get() = _viewEvents
val insets = KObservableField(Insets.NONE) val insets = ObservableField(Insets.NONE)
var state: State = initialState var state: State = initialState
set(value) { set(value) {

View File

@ -5,6 +5,7 @@ import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.events.ActivityExecutor import com.topjohnwu.magisk.model.events.ActivityExecutor
import com.topjohnwu.magisk.model.events.ContextExecutor import com.topjohnwu.magisk.model.events.ContextExecutor
import com.topjohnwu.magisk.model.events.FragmentExecutor import com.topjohnwu.magisk.model.events.FragmentExecutor

View File

@ -5,11 +5,7 @@ import android.content.Context
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent import android.view.*
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.navigation.NavDeepLinkBuilder import androidx.navigation.NavDeepLinkBuilder
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R

View File

@ -5,6 +5,7 @@ import android.content.res.Resources
import android.net.Uri import android.net.Uri
import android.view.MenuItem import android.view.MenuItem
import androidx.databinding.ObservableArrayList import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableField
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
@ -19,7 +20,6 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.diffListOf import com.topjohnwu.magisk.ui.base.diffListOf
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File
@ -30,8 +30,8 @@ class FlashViewModel(
private val resources: Resources private val resources: Resources
) : BaseViewModel() { ) : BaseViewModel() {
val showReboot = KObservableField(Shell.rootAccess()) val showReboot = ObservableField(Shell.rootAccess())
val behaviorText = KObservableField(resources.getString(R.string.flashing)) val behaviorText = ObservableField(resources.getString(R.string.flashing))
val adapter = BindingAdapter<ConsoleItem>() val adapter = BindingAdapter<ConsoleItem>()
val items = diffListOf<ConsoleItem>() val items = diffListOf<ConsoleItem>()

View File

@ -2,11 +2,12 @@ package com.topjohnwu.magisk.ui.hide
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import androidx.databinding.Bindable import androidx.databinding.Bindable
import androidx.databinding.ObservableField
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.core.utils.currentLocale import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.data.repository.MagiskRepository import com.topjohnwu.magisk.data.repository.MagiskRepository
import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.toggle import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.entity.HideAppInfo import com.topjohnwu.magisk.model.entity.HideAppInfo
import com.topjohnwu.magisk.model.entity.HideTarget import com.topjohnwu.magisk.model.entity.HideTarget
import com.topjohnwu.magisk.model.entity.ProcessHideApp import com.topjohnwu.magisk.model.entity.ProcessHideApp
@ -17,7 +18,6 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.Queryable import com.topjohnwu.magisk.ui.base.Queryable
import com.topjohnwu.magisk.ui.base.filterableListOf import com.topjohnwu.magisk.ui.base.filterableListOf
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.KObservableField
class HideViewModel( class HideViewModel(
private val magiskRepo: MagiskRepository private val magiskRepo: MagiskRepository
@ -48,7 +48,7 @@ class HideViewModel(
it.bindExtra(BR.viewModel, this) it.bindExtra(BR.viewModel, this)
} }
val isFilterExpanded = KObservableField(false) val isFilterExpanded = ObservableField(false)
override fun rxRefresh() = magiskRepo.fetchApps() override fun rxRefresh() = magiskRepo.fetchApps()
.map { it to magiskRepo.fetchHideTargets().blockingGet() } .map { it to magiskRepo.fetchHideTargets().blockingGet() }
@ -101,8 +101,6 @@ class HideViewModel(
fun toggleItem(item: HideProcessItem) = magiskRepo fun toggleItem(item: HideProcessItem) = magiskRepo
.toggleHide(item.isHidden.value, item.item.packageName, item.item.name) .toggleHide(item.isHidden.value, item.item.packageName, item.item.name)
fun toggle(item: KObservableField<Boolean>) = item.toggle()
fun resetQuery() { fun resetQuery() {
query = "" query = ""
} }

View File

@ -2,6 +2,7 @@ package com.topjohnwu.magisk.ui.home
import android.Manifest import android.Manifest
import android.os.Build import android.os.Build
import androidx.databinding.ObservableField
import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
@ -24,7 +25,6 @@ import com.topjohnwu.magisk.model.events.dialog.ManagerInstallDialog
import com.topjohnwu.magisk.model.events.dialog.UninstallDialog import com.topjohnwu.magisk.model.events.dialog.UninstallDialog
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import me.tatarka.bindingcollectionadapter2.BR import me.tatarka.bindingcollectionadapter2.BR
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -37,22 +37,22 @@ class HomeViewModel(
private val repoMagisk: MagiskRepository private val repoMagisk: MagiskRepository
) : BaseViewModel() { ) : BaseViewModel() {
val isNoticeVisible = KObservableField(Config.safetyNotice) val isNoticeVisible = ObservableField(Config.safetyNotice)
val stateMagisk = KObservableField(MagiskState.LOADING) val stateMagisk = ObservableField(MagiskState.LOADING)
val stateManager = KObservableField(MagiskState.LOADING) val stateManager = ObservableField(MagiskState.LOADING)
val stateMagiskRemoteVersion = KObservableField(R.string.loading.res()) val stateMagiskRemoteVersion = ObservableField(R.string.loading.res())
val stateMagiskInstalledVersion get() = val stateMagiskInstalledVersion get() =
"${Info.env.magiskVersionString} (${Info.env.magiskVersionCode})" "${Info.env.magiskVersionString} (${Info.env.magiskVersionCode})"
val stateMagiskMode get() = R.string.home_status_normal.res() val stateMagiskMode get() = R.string.home_status_normal.res()
val stateManagerRemoteVersion = KObservableField(R.string.loading.res()) val stateManagerRemoteVersion = ObservableField(R.string.loading.res())
val stateManagerInstalledVersion = Info.stub?.let { val stateManagerInstalledVersion = Info.stub?.let {
"${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) (${it.version})" "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) (${it.version})"
} ?: "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" } ?: "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
val statePackageName = packageName val statePackageName = packageName
val stateManagerProgress = KObservableField(0) val stateManagerProgress = ObservableField(0)
val items = listOf(DeveloperItem.Mainline, DeveloperItem.App, DeveloperItem.Project) val items = listOf(DeveloperItem.Mainline, DeveloperItem.App, DeveloperItem.Project)
val itemBinding = itemBindingOf<HomeItem> { val itemBinding = itemBindingOf<HomeItem> {
@ -116,8 +116,6 @@ class HomeViewModel(
.subscribeK { HomeFragmentDirections.actionHomeFragmentToInstallFragment().publish() } .subscribeK { HomeFragmentDirections.actionHomeFragmentToInstallFragment().publish() }
.add() .add()
fun toggle(kof: KObservableField<Boolean>) = kof.toggle()
fun hideNotice() { fun hideNotice() {
Config.safetyNotice = false Config.safetyNotice = false
isNoticeVisible.value = false isNoticeVisible.value = false

View File

@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.install
import android.content.Intent import android.content.Intent
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.events.RequestFileEvent import com.topjohnwu.magisk.model.events.RequestFileEvent
import com.topjohnwu.magisk.ui.base.BaseUIFragment import com.topjohnwu.magisk.ui.base.BaseUIFragment
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel

View File

@ -4,6 +4,7 @@ import android.net.Uri
import android.text.SpannableString import android.text.SpannableString
import android.text.Spanned import android.text.Spanned
import android.widget.Toast import android.widget.Toast
import androidx.databinding.ObservableField
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.download.DownloadService import com.topjohnwu.magisk.core.download.DownloadService
@ -12,12 +13,12 @@ import com.topjohnwu.magisk.core.utils.Utils
import com.topjohnwu.magisk.data.repository.StringRepository import com.topjohnwu.magisk.data.repository.StringRepository
import com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback import com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.entity.internal.Configuration import com.topjohnwu.magisk.model.entity.internal.Configuration
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.model.events.RequestFileEvent import com.topjohnwu.magisk.model.events.RequestFileEvent
import com.topjohnwu.magisk.model.events.dialog.SecondSlotWarningDialog import com.topjohnwu.magisk.model.events.dialog.SecondSlotWarningDialog
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
import org.koin.core.get import org.koin.core.get
@ -31,11 +32,11 @@ class InstallViewModel(
val isRooted get() = Shell.rootAccess() val isRooted get() = Shell.rootAccess()
val isAB get() = Info.isAB val isAB get() = Info.isAB
val step = KObservableField(0) val step = ObservableField(0)
val method = KObservableField(-1) val method = ObservableField(-1)
val progress = KObservableField(0) val progress = ObservableField(0)
val data = KObservableField<Uri?>(null) val data = ObservableField<Uri?>(null)
val notes = KObservableField<Spanned>(SpannableString("")) val notes = ObservableField<Spanned>(SpannableString(""))
init { init {
RemoteFileService.reset() RemoteFileService.reset()

View File

@ -1,18 +1,19 @@
package com.topjohnwu.magisk.ui.log package com.topjohnwu.magisk.ui.log
import androidx.databinding.ObservableField
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.Config import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.data.repository.LogRepository import com.topjohnwu.magisk.data.repository.LogRepository
import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.entity.recycler.LogItem import com.topjohnwu.magisk.model.entity.recycler.LogItem
import com.topjohnwu.magisk.model.entity.recycler.TextItem import com.topjohnwu.magisk.model.entity.recycler.TextItem
import com.topjohnwu.magisk.model.events.SnackbarEvent import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.diffListOf import com.topjohnwu.magisk.ui.base.diffListOf
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
@ -40,7 +41,7 @@ class LogViewModel(
// --- magisk log // --- magisk log
val consoleText = KObservableField(" ") val consoleText = ObservableField(" ")
override fun rxRefresh(): Disposable { override fun rxRefresh(): Disposable {
val logs = repo.fetchLogs() val logs = repo.fetchLogs()

View File

@ -2,6 +2,7 @@ package com.topjohnwu.magisk.ui.module
import androidx.databinding.Bindable import androidx.databinding.Bindable
import androidx.databinding.ObservableArrayList import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableField
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
@ -15,6 +16,7 @@ import com.topjohnwu.magisk.data.database.RepoByUpdatedDao
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.extensions.addOnListChangedCallback import com.topjohnwu.magisk.extensions.addOnListChangedCallback
import com.topjohnwu.magisk.extensions.reboot import com.topjohnwu.magisk.extensions.reboot
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.model.entity.recycler.* import com.topjohnwu.magisk.model.entity.recycler.*
import com.topjohnwu.magisk.model.events.InstallExternalModuleEvent import com.topjohnwu.magisk.model.events.InstallExternalModuleEvent
@ -23,7 +25,6 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog import com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog
import com.topjohnwu.magisk.ui.base.* import com.topjohnwu.magisk.ui.base.*
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
import com.topjohnwu.magisk.utils.KObservableField
import kotlinx.coroutines.* import kotlinx.coroutines.*
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -63,7 +64,7 @@ class ModuleViewModel(
searchLoading.value = true searchLoading.value = true
} }
val searchLoading = KObservableField(false) val searchLoading = ObservableField(false)
val itemsSearch = diffListOf<RepoItem>() val itemsSearch = diffListOf<RepoItem>()
val itemSearchBinding = itemBindingOf<RepoItem> { val itemSearchBinding = itemBindingOf<RepoItem> {
it.bindExtra(BR.viewModel, this) it.bindExtra(BR.viewModel, this)

View File

@ -1,14 +1,15 @@
package com.topjohnwu.magisk.ui.safetynet package com.topjohnwu.magisk.ui.safetynet
import androidx.databinding.Bindable import androidx.databinding.Bindable
import androidx.databinding.ObservableField
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.events.SafetyNetResult import com.topjohnwu.magisk.model.events.SafetyNetResult
import com.topjohnwu.magisk.model.events.UpdateSafetyNetEvent import com.topjohnwu.magisk.model.events.UpdateSafetyNetEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.* import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.*
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.magisk.utils.RxBus import com.topjohnwu.magisk.utils.RxBus
import org.json.JSONObject import org.json.JSONObject
@ -25,10 +26,10 @@ class SafetynetViewModel(
field = value field = value
notifyStateChanged() notifyStateChanged()
} }
val safetyNetTitle = KObservableField(R.string.empty) val safetyNetTitle = ObservableField(R.string.empty)
val ctsState = KObservableField(false) val ctsState = ObservableField(false)
val basicIntegrityState = KObservableField(false) val basicIntegrityState = ObservableField(false)
val evalType = KObservableField("") val evalType = ObservableField("")
val isChecking @Bindable get() = currentState == LOADING val isChecking @Bindable get() = currentState == LOADING
val isFailed @Bindable get() = currentState == FAILED val isFailed @Bindable get() = currentState == FAILED

View File

@ -13,11 +13,12 @@ import com.topjohnwu.magisk.core.utils.PatchAPK
import com.topjohnwu.magisk.core.utils.Utils import com.topjohnwu.magisk.core.utils.Utils
import com.topjohnwu.magisk.data.database.RepoDao import com.topjohnwu.magisk.data.database.RepoDao
import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.entity.internal.Configuration import com.topjohnwu.magisk.model.entity.internal.Configuration
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.model.entity.recycler.SettingsItem import com.topjohnwu.magisk.model.entity.recycler.SettingsItem
import com.topjohnwu.magisk.model.events.RxPermissionEvent
import com.topjohnwu.magisk.model.events.RecreateEvent import com.topjohnwu.magisk.model.events.RecreateEvent
import com.topjohnwu.magisk.model.events.RxPermissionEvent
import com.topjohnwu.magisk.model.events.dialog.BiometricDialog import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.adapterOf import com.topjohnwu.magisk.ui.base.adapterOf

View File

@ -6,6 +6,7 @@ import android.content.pm.PackageManager
import android.content.res.Resources import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.CountDownTimer import android.os.CountDownTimer
import androidx.databinding.ObservableField
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
@ -14,10 +15,10 @@ import com.topjohnwu.magisk.core.model.MagiskPolicy.Companion.ALLOW
import com.topjohnwu.magisk.core.model.MagiskPolicy.Companion.DENY import com.topjohnwu.magisk.core.model.MagiskPolicy.Companion.DENY
import com.topjohnwu.magisk.core.su.SuRequestHandler import com.topjohnwu.magisk.core.su.SuRequestHandler
import com.topjohnwu.magisk.core.utils.BiometricHelper import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem import com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem
import com.topjohnwu.magisk.model.events.DieEvent import com.topjohnwu.magisk.model.events.DieEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.internal.UiThreadHandler import com.topjohnwu.superuser.internal.UiThreadHandler
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
@ -31,16 +32,16 @@ class SuRequestViewModel(
private val res: Resources private val res: Resources
) : BaseViewModel() { ) : BaseViewModel() {
val icon = KObservableField<Drawable?>(null) val icon = ObservableField<Drawable?>(null)
val title = KObservableField("") val title = ObservableField("")
val packageName = KObservableField("") val packageName = ObservableField("")
val denyText = KObservableField(res.getString(R.string.deny)) val denyText = ObservableField(res.getString(R.string.deny))
val warningText = KObservableField<CharSequence>(res.getString(R.string.su_warning)) val warningText = ObservableField<CharSequence>(res.getString(R.string.su_warning))
val selectedItemPosition = KObservableField(0) val selectedItemPosition = ObservableField(0)
val grantEnabled = KObservableField(false) val grantEnabled = ObservableField(false)
private val items = res.getStringArray(R.array.allow_timeout).map { SpinnerRvItem(it) } private val items = res.getStringArray(R.array.allow_timeout).map { SpinnerRvItem(it) }
val adapter = BindingListViewAdapter<SpinnerRvItem>(1).apply { val adapter = BindingListViewAdapter<SpinnerRvItem>(1).apply {

View File

@ -1,57 +0,0 @@
package com.topjohnwu.magisk.utils
import androidx.databinding.Observable
import androidx.databinding.ObservableField
import com.topjohnwu.magisk.model.observer.Observer
import java.io.Serializable
/**
* Kotlin version of [ObservableField].
* You can define if wrapped type is Nullable or not.
* You can use kotlin get/set syntax for value
*
* ## Notes
* This stays final for fuck's sake. Too many things depend on it, so you just cannot go around and
* change it randomly. Even though you think you're improving the design, you might be fucking this
* up in unimaginable ways. So DON'T TOUCH THIS.
*
* In order to have value-less observer you need - you guessed it - **a fucking [Observer]**!
*/
class KObservableField<T> : ObservableField<T>, Serializable {
var value: T
set(value) {
if (field != value) {
field = value
notifyChange()
}
}
constructor(init: T) {
value = init
}
constructor(init: T, vararg dependencies: Observable) : super(*dependencies) {
value = init
}
@Deprecated(
message = "Needed for data binding, use KObservableField.value syntax from code",
replaceWith = ReplaceWith("value")
)
override fun get(): T {
return value
}
@Deprecated(
message = "Needed for data binding, use KObservableField.value = ... syntax from code",
replaceWith = ReplaceWith("value = newValue")
)
override fun set(newValue: T) {
value = newValue
}
override fun toString(): String {
return "KObservableField(value=$value)"
}
}

View File

@ -15,6 +15,7 @@ import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatDialog import androidx.appcompat.app.AppCompatDialog
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.databinding.ObservableField
import androidx.databinding.ViewDataBinding import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -22,8 +23,8 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.KObservableField
import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapters import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapters
import me.tatarka.bindingcollectionadapter2.ItemBinding import me.tatarka.bindingcollectionadapter2.ItemBinding
@ -71,10 +72,10 @@ class MagiskDialog @JvmOverloads constructor(
} }
inner class Data { inner class Data {
val icon = KObservableField(0) val icon = ObservableField(0)
val iconRaw = KObservableField<Drawable?>(null) val iconRaw = ObservableField<Drawable?>(null)
val title = KObservableField<CharSequence>("") val title = ObservableField<CharSequence>("")
val message = KObservableField<CharSequence>("") val message = ObservableField<CharSequence>("")
val buttonPositive = Button() val buttonPositive = Button()
val buttonNeutral = Button() val buttonNeutral = Button()
@ -87,9 +88,9 @@ class MagiskDialog @JvmOverloads constructor(
} }
inner class Button { inner class Button {
val icon = KObservableField(0) val icon = ObservableField(0)
val title = KObservableField<CharSequence>("") val title = ObservableField<CharSequence>("")
val isEnabled = KObservableField(true) val isEnabled = ObservableField(true)
var onClickAction: OnDialogButtonClickListener = {} var onClickAction: OnDialogButtonClickListener = {}
var preventDismiss = false var preventDismiss = false