mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 07:17:38 +00:00
Updated settings to level functionality with the legacy
This commit is contained in:
parent
89da45f9ac
commit
3efea47ca8
@ -23,7 +23,7 @@ val redesignModule = module {
|
|||||||
viewModel { ModuleViewModel(get(), get(), get()) }
|
viewModel { ModuleViewModel(get(), get(), get()) }
|
||||||
viewModel { RequestViewModel() }
|
viewModel { RequestViewModel() }
|
||||||
viewModel { SafetynetViewModel(get()) }
|
viewModel { SafetynetViewModel(get()) }
|
||||||
viewModel { SettingsViewModel() }
|
viewModel { SettingsViewModel(get()) }
|
||||||
viewModel { SuperuserViewModel(get(), get(), get()) }
|
viewModel { SuperuserViewModel(get(), get(), get()) }
|
||||||
viewModel { ThemeViewModel() }
|
viewModel { ThemeViewModel() }
|
||||||
viewModel { InstallViewModel() }
|
viewModel { InstallViewModel() }
|
||||||
|
@ -19,4 +19,9 @@ class SettingsFragment : CompatFragment<SettingsViewModel, FragmentSettingsMd2Bi
|
|||||||
activity.title = resources.getString(R.string.section_settings)
|
activity.title = resources.getString(R.string.section_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
viewModel.items.forEach { it.refresh() }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,21 +1,19 @@
|
|||||||
package com.topjohnwu.magisk.redesign.settings
|
package com.topjohnwu.magisk.redesign.settings
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.*
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
|
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
|
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
|
||||||
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.utils.Utils
|
import com.topjohnwu.magisk.utils.*
|
||||||
import com.topjohnwu.magisk.utils.asTransitive
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.magisk.utils.availableLocales
|
|
||||||
import com.topjohnwu.magisk.utils.currentLocale
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
// --- Customization
|
// --- Customization
|
||||||
@ -27,6 +25,7 @@ object Customization : SettingsItem.Section() {
|
|||||||
object Language : SettingsItem.Selector() {
|
object Language : SettingsItem.Selector() {
|
||||||
override var value by dataObservable(0) {
|
override var value by dataObservable(0) {
|
||||||
Config.locale = entryValues.getOrNull(it)?.toString() ?: return@dataObservable
|
Config.locale = entryValues.getOrNull(it)?.toString() ?: return@dataObservable
|
||||||
|
refreshLocale()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val title = R.string.language.asTransitive()
|
override val title = R.string.language.asTransitive()
|
||||||
@ -61,11 +60,34 @@ object Manager : SettingsItem.Section() {
|
|||||||
object ClearRepoCache : SettingsItem.Blank() {
|
object ClearRepoCache : SettingsItem.Blank() {
|
||||||
override val title = R.string.settings_clear_cache_title.asTransitive()
|
override val title = R.string.settings_clear_cache_title.asTransitive()
|
||||||
override val description = R.string.settings_clear_cache_summary.asTransitive()
|
override val description = R.string.settings_clear_cache_summary.asTransitive()
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Info.env.isActive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Hide : SettingsItem.Blank() {
|
object Hide : SettingsItem.Input() {
|
||||||
override val title = R.string.settings_hide_manager_title.asTransitive()
|
override val title = R.string.settings_hide_manager_title.asTransitive()
|
||||||
override val description = R.string.settings_hide_manager_summary.asTransitive()
|
override val description = R.string.settings_hide_manager_summary.asTransitive()
|
||||||
|
override val showStrip = false
|
||||||
|
override var value: String = resources.getString(R.string.re_app_name)
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
notifyChange(BR.value)
|
||||||
|
notifyChange(BR.error)
|
||||||
|
}
|
||||||
|
val isError
|
||||||
|
@Bindable get() = value.length > 14 || value.isBlank()
|
||||||
|
|
||||||
|
override val intermediate: String?
|
||||||
|
get() = if (isError) null else value
|
||||||
|
|
||||||
|
override fun getView(context: Context) = DialogSettingsAppNameBinding
|
||||||
|
.inflate(LayoutInflater.from(context)).also { it.data = this }.root
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Info.env.isActive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Restore : SettingsItem.Blank() {
|
object Restore : SettingsItem.Blank() {
|
||||||
@ -129,11 +151,7 @@ object UpdateChannelUrl : SettingsItem.Input() {
|
|||||||
notifyChange(BR.result)
|
notifyChange(BR.result)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
override fun refresh() {
|
||||||
updateState()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateState() {
|
|
||||||
isEnabled = UpdateChannel.value == Config.Value.CUSTOM_CHANNEL
|
isEnabled = UpdateChannel.value == Config.Value.CUSTOM_CHANNEL
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,19 +162,43 @@ object UpdateChannelUrl : SettingsItem.Input() {
|
|||||||
object UpdateChecker : SettingsItem.Toggle() {
|
object UpdateChecker : SettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_check_update_title.asTransitive()
|
override val title = R.string.settings_check_update_title.asTransitive()
|
||||||
override val description = R.string.settings_check_update_summary.asTransitive()
|
override val description = R.string.settings_check_update_summary.asTransitive()
|
||||||
override var value by dataObservable(Config.checkUpdate) { Config.checkUpdate = it }
|
override var value by dataObservable(Config.checkUpdate) {
|
||||||
|
Config.checkUpdate = it
|
||||||
|
Utils.scheduleUpdateCheck(get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether is module already installed beforehand?
|
// check whether is module already installed beforehand?
|
||||||
object SystemlessHosts : SettingsItem.Blank() {
|
object SystemlessHosts : SettingsItem.Blank() {
|
||||||
override val title = R.string.settings_hosts_title.asTransitive()
|
override val title = R.string.settings_hosts_title.asTransitive()
|
||||||
override val description = R.string.settings_hosts_summary.asTransitive()
|
override val description = R.string.settings_hosts_summary.asTransitive()
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Info.env.isActive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Biometrics : SettingsItem.Toggle() {
|
object Biometrics : SettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_su_biometric_title.asTransitive()
|
override val title = R.string.settings_su_biometric_title.asTransitive()
|
||||||
override val description = R.string.settings_su_biometric_summary.asTransitive()
|
override val description = R.string.settings_su_biometric_summary.asTransitive()
|
||||||
override var value by dataObservable(Config.suBiometric) { Config.suBiometric = it }
|
override var value by dataObservable(Config.suBiometric) { Config.suBiometric = it }
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = BiometricHelper.isSupported && Utils.showSuperUser()
|
||||||
|
if (!isEnabled) {
|
||||||
|
value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Reauthenticate : SettingsItem.Toggle() {
|
||||||
|
override val title = R.string.settings_su_reauth_title.asTransitive()
|
||||||
|
override val description = R.string.settings_su_reauth_summary.asTransitive()
|
||||||
|
override var value by dataObservable(Config.suReAuth) { Config.suReAuth = it }
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O && Utils.showSuperUser()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Magisk
|
// --- Magisk
|
||||||
@ -168,13 +210,35 @@ object Magisk : SettingsItem.Section() {
|
|||||||
object SafeMode : SettingsItem.Toggle() {
|
object SafeMode : SettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_core_only_title.asTransitive()
|
override val title = R.string.settings_core_only_title.asTransitive()
|
||||||
override val description = R.string.settings_core_only_summary.asTransitive()
|
override val description = R.string.settings_core_only_summary.asTransitive()
|
||||||
override var value by dataObservable(Config.coreOnly) { Config.coreOnly = it }
|
override var value by dataObservable(Config.coreOnly) {
|
||||||
|
if (Config.coreOnly == it) return@dataObservable
|
||||||
|
Config.coreOnly = it
|
||||||
|
when {
|
||||||
|
it -> runCatching { Const.MAGISK_DISABLE_FILE.createNewFile() }
|
||||||
|
else -> Const.MAGISK_DISABLE_FILE.delete()
|
||||||
|
}
|
||||||
|
Utils.toast(R.string.settings_reboot_toast, Toast.LENGTH_LONG)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Info.env.isActive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MagiskHide : SettingsItem.Toggle() {
|
object MagiskHide : SettingsItem.Toggle() {
|
||||||
override val title = R.string.magiskhide.asTransitive()
|
override val title = R.string.magiskhide.asTransitive()
|
||||||
override val description = R.string.settings_magiskhide_summary.asTransitive()
|
override val description = R.string.settings_magiskhide_summary.asTransitive()
|
||||||
override var value by dataObservable(Config.magiskHide) { Config.magiskHide = it }
|
override var value by dataObservable(Config.magiskHide) {
|
||||||
|
Config.magiskHide = it
|
||||||
|
when {
|
||||||
|
it -> Shell.su("magiskhide --enable").submit()
|
||||||
|
else -> Shell.su("magiskhide --disable").submit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Info.env.isActive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Superuser
|
// --- Superuser
|
||||||
@ -197,6 +261,10 @@ object AccessMode : SettingsItem.Selector() {
|
|||||||
resources.getStringArray(R.array.value_array)
|
resources.getStringArray(R.array.value_array)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Utils.showSuperUser()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MultiuserMode : SettingsItem.Selector() {
|
object MultiuserMode : SettingsItem.Selector() {
|
||||||
@ -213,6 +281,10 @@ object MultiuserMode : SettingsItem.Selector() {
|
|||||||
resources.getStringArray(R.array.value_array)
|
resources.getStringArray(R.array.value_array)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Const.USER_ID <= 0 && Utils.showSuperUser()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MountNamespaceMode : SettingsItem.Selector() {
|
object MountNamespaceMode : SettingsItem.Selector() {
|
||||||
@ -229,6 +301,10 @@ object MountNamespaceMode : SettingsItem.Selector() {
|
|||||||
resources.getStringArray(R.array.value_array)
|
resources.getStringArray(R.array.value_array)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Utils.showSuperUser()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object AutomaticResponse : SettingsItem.Selector() {
|
object AutomaticResponse : SettingsItem.Selector() {
|
||||||
@ -245,6 +321,10 @@ object AutomaticResponse : SettingsItem.Selector() {
|
|||||||
resources.getStringArray(R.array.value_array)
|
resources.getStringArray(R.array.value_array)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Utils.showSuperUser()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object RequestTimeout : SettingsItem.Selector() {
|
object RequestTimeout : SettingsItem.Selector() {
|
||||||
@ -263,6 +343,10 @@ object RequestTimeout : SettingsItem.Selector() {
|
|||||||
val currentValue = Config.suDefaultTimeout.toString()
|
val currentValue = Config.suDefaultTimeout.toString()
|
||||||
value = entryValues.indexOfFirst { it == currentValue }
|
value = entryValues.indexOfFirst { it == currentValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Utils.showSuperUser()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object SUNotification : SettingsItem.Selector() {
|
object SUNotification : SettingsItem.Selector() {
|
||||||
@ -279,4 +363,8 @@ object SUNotification : SettingsItem.Selector() {
|
|||||||
resources.getStringArray(R.array.value_array)
|
resources.getStringArray(R.array.value_array)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
isEnabled = Utils.showSuperUser()
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,30 +1,47 @@
|
|||||||
package com.topjohnwu.magisk.redesign.settings
|
package com.topjohnwu.magisk.redesign.settings
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import androidx.databinding.ViewDataBinding
|
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
|
||||||
|
import com.topjohnwu.magisk.data.database.RepoDao
|
||||||
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
|
import com.topjohnwu.magisk.model.download.DownloadService
|
||||||
|
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||||
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.ObservableItem
|
import com.topjohnwu.magisk.model.entity.recycler.ObservableItem
|
||||||
import com.topjohnwu.magisk.model.events.DieEvent
|
import com.topjohnwu.magisk.model.events.DieEvent
|
||||||
|
import com.topjohnwu.magisk.model.events.PermissionEvent
|
||||||
|
import com.topjohnwu.magisk.model.events.RecreateEvent
|
||||||
|
import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
import com.topjohnwu.magisk.model.navigation.Navigation
|
||||||
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
||||||
import com.topjohnwu.magisk.redesign.home.itemBindingOf
|
import com.topjohnwu.magisk.redesign.home.itemBindingOf
|
||||||
import com.topjohnwu.magisk.redesign.module.adapterOf
|
import com.topjohnwu.magisk.redesign.module.adapterOf
|
||||||
import com.topjohnwu.magisk.redesign.superuser.diffListOf
|
import com.topjohnwu.magisk.redesign.superuser.diffListOf
|
||||||
|
import com.topjohnwu.magisk.utils.PatchAPK
|
||||||
import com.topjohnwu.magisk.utils.TransitiveText
|
import com.topjohnwu.magisk.utils.TransitiveText
|
||||||
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import io.reactivex.subjects.PublishSubject
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.get
|
import org.koin.core.get
|
||||||
import kotlin.properties.ObservableProperty
|
import kotlin.properties.ObservableProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class SettingsViewModel : CompatViewModel(), SettingsItem.Callback {
|
class SettingsViewModel(
|
||||||
|
private val repositoryDao: RepoDao
|
||||||
|
) : CompatViewModel(), SettingsItem.Callback {
|
||||||
|
|
||||||
val adapter = adapterOf<SettingsItem>()
|
val adapter = adapterOf<SettingsItem>()
|
||||||
val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) }
|
val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) }
|
||||||
@ -34,10 +51,10 @@ class SettingsViewModel : CompatViewModel(), SettingsItem.Callback {
|
|||||||
|
|
||||||
Manager,
|
Manager,
|
||||||
UpdateChannel, UpdateChannelUrl, ClearRepoCache, HideOrRestore(), UpdateChecker,
|
UpdateChannel, UpdateChannelUrl, ClearRepoCache, HideOrRestore(), UpdateChecker,
|
||||||
SystemlessHosts, Biometrics,
|
Biometrics, Reauthenticate,
|
||||||
|
|
||||||
Magisk,
|
Magisk,
|
||||||
SafeMode, MagiskHide,
|
SafeMode, MagiskHide, SystemlessHosts,
|
||||||
|
|
||||||
Superuser,
|
Superuser,
|
||||||
AccessMode, MultiuserMode, MountNamespaceMode, AutomaticResponse, RequestTimeout,
|
AccessMode, MultiuserMode, MountNamespaceMode, AutomaticResponse, RequestTimeout,
|
||||||
@ -45,20 +62,74 @@ class SettingsViewModel : CompatViewModel(), SettingsItem.Callback {
|
|||||||
)
|
)
|
||||||
|
|
||||||
override fun onItemPressed(view: View, item: SettingsItem) = when (item) {
|
override fun onItemPressed(view: View, item: SettingsItem) = when (item) {
|
||||||
|
is DownloadPath -> requireRWPermission()
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemChanged(view: View, item: SettingsItem) = when (item) {
|
||||||
// use only instances you want, don't declare everything
|
// use only instances you want, don't declare everything
|
||||||
is Theme -> Navigation.theme().publish()
|
is Theme -> Navigation.theme().publish()
|
||||||
is Redesign -> DieEvent().publish()
|
is Redesign -> DieEvent().publish()
|
||||||
|
is Language -> RecreateEvent().publish()
|
||||||
|
|
||||||
is UpdateChannel -> openUrlIfNecessary(view)
|
is UpdateChannel -> openUrlIfNecessary(view)
|
||||||
|
is Biometrics -> authenticateOrRevert()
|
||||||
|
is ClearRepoCache -> clearRepoCache()
|
||||||
|
is SystemlessHosts -> createHosts()
|
||||||
|
is Hide -> updateManager(hide = true)
|
||||||
|
is Restore -> updateManager(hide = false)
|
||||||
|
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openUrlIfNecessary(view: View) {
|
private fun openUrlIfNecessary(view: View) {
|
||||||
UpdateChannelUrl.updateState()
|
UpdateChannelUrl.refresh()
|
||||||
if (UpdateChannelUrl.value.isBlank()) {
|
if (UpdateChannelUrl.value.isBlank()) {
|
||||||
UpdateChannelUrl.onPressed(view, this@SettingsViewModel)
|
UpdateChannelUrl.onPressed(view, this@SettingsViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun authenticateOrRevert() {
|
||||||
|
// immediately revert the preference
|
||||||
|
Biometrics.value = !Biometrics.value
|
||||||
|
BiometricDialog {
|
||||||
|
// allow the change on success
|
||||||
|
onSuccess { Biometrics.value = !Biometrics.value }
|
||||||
|
}.publish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearRepoCache() {
|
||||||
|
Completable.fromAction { repositoryDao.clear() }
|
||||||
|
.subscribeK { Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createHosts() {
|
||||||
|
Shell.su("add_hosts_module").submit {
|
||||||
|
Utils.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun requireRWPermission() {
|
||||||
|
val callback = PublishSubject.create<Boolean>()
|
||||||
|
callback.subscribeK { if (!it) requireRWPermission() }
|
||||||
|
PermissionEvent(
|
||||||
|
listOf(
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
), callback
|
||||||
|
).publish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateManager(hide: Boolean) {
|
||||||
|
if (hide) {
|
||||||
|
PatchAPK.hideManager(get(), Hide.value)
|
||||||
|
} else {
|
||||||
|
DownloadService(get()) {
|
||||||
|
subject = DownloadSubject.Manager(Configuration.APK.Restore)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
||||||
@ -81,7 +152,7 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
open fun onPressed(view: View, callback: Callback) {
|
open fun onPressed(view: View, callback: Callback) {
|
||||||
callback.onItemPressed(view, this)
|
callback.onItemChanged(view, this)
|
||||||
|
|
||||||
// notify only after the callback invocation; callback can invalidate the backing data,
|
// notify only after the callback invocation; callback can invalidate the backing data,
|
||||||
// which wouldn't be recognized with reverse approach
|
// which wouldn't be recognized with reverse approach
|
||||||
@ -90,6 +161,8 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
notifyChange(BR.description)
|
notifyChange(BR.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun refresh() {}
|
||||||
|
|
||||||
override fun onBindingBound(binding: ViewDataBinding) {
|
override fun onBindingBound(binding: ViewDataBinding) {
|
||||||
super.onBindingBound(binding)
|
super.onBindingBound(binding)
|
||||||
if (isFullSpan) {
|
if (isFullSpan) {
|
||||||
@ -105,6 +178,7 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onItemPressed(view: View, item: SettingsItem)
|
fun onItemPressed(view: View, item: SettingsItem)
|
||||||
|
fun onItemChanged(view: View, item: SettingsItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
@ -131,6 +205,7 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
override val layoutRes = R.layout.item_settings_toggle
|
override val layoutRes = R.layout.item_settings_toggle
|
||||||
|
|
||||||
override fun onPressed(view: View, callback: Callback) {
|
override fun onPressed(view: View, callback: Callback) {
|
||||||
|
callback.onItemPressed(view, this)
|
||||||
value = !value
|
value = !value
|
||||||
super.onPressed(view, callback)
|
super.onPressed(view, callback)
|
||||||
}
|
}
|
||||||
@ -147,11 +222,13 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
abstract class Input : Value<String>(), KoinComponent {
|
abstract class Input : Value<String>(), KoinComponent {
|
||||||
|
|
||||||
override val layoutRes = R.layout.item_settings_input
|
override val layoutRes = R.layout.item_settings_input
|
||||||
|
open val showStrip = true
|
||||||
|
|
||||||
protected val resources get() = get<Resources>()
|
protected val resources get() = get<Resources>()
|
||||||
protected abstract val intermediate: String?
|
protected abstract val intermediate: String?
|
||||||
|
|
||||||
override fun onPressed(view: View, callback: Callback) {
|
override fun onPressed(view: View, callback: Callback) {
|
||||||
|
callback.onItemPressed(view, this)
|
||||||
MagiskDialog(view.context)
|
MagiskDialog(view.context)
|
||||||
.applyTitle(title.getText(resources))
|
.applyTitle(title.getText(resources))
|
||||||
.applyView(getView(view.context))
|
.applyView(getView(view.context))
|
||||||
@ -210,6 +287,7 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
|
|
||||||
override fun onPressed(view: View, callback: Callback) {
|
override fun onPressed(view: View, callback: Callback) {
|
||||||
if (entries.isEmpty() || entryValues.isEmpty()) return
|
if (entries.isEmpty() || entryValues.isEmpty()) return
|
||||||
|
callback.onItemPressed(view, this)
|
||||||
MagiskDialog(view.context)
|
MagiskDialog(view.context)
|
||||||
.applyTitle(title.getText(resources))
|
.applyTitle(title.getText(resources))
|
||||||
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||||
@ -229,6 +307,11 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
|
|
||||||
override val layoutRes = R.layout.item_settings_blank
|
override val layoutRes = R.layout.item_settings_blank
|
||||||
|
|
||||||
|
override fun onPressed(view: View, callback: Callback) {
|
||||||
|
callback.onItemPressed(view, this)
|
||||||
|
super.onPressed(view, callback)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Section : SettingsItem() {
|
abstract class Section : SettingsItem() {
|
||||||
|
52
app/src/main/res/layout/dialog_settings_app_name.xml
Normal file
52
app/src/main/res/layout/dialog_settings_app_name.xml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="com.topjohnwu.magisk.redesign.settings.Hide" />
|
||||||
|
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/margin_generic">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/margin_generic"
|
||||||
|
android:hint="@string/settings_app_name_hint"
|
||||||
|
app:boxStrokeColor="?colorOnSurfaceVariant"
|
||||||
|
app:counterEnabled="true"
|
||||||
|
app:counterMaxLength="14"
|
||||||
|
app:counterOverflowTextColor="@color/colorError"
|
||||||
|
app:error="@{data.error ? @string/settings_app_name_error : @string/empty}"
|
||||||
|
app:errorEnabled="true"
|
||||||
|
app:errorTextColor="?colorError"
|
||||||
|
app:helperText="@string/settings_app_name_helper"
|
||||||
|
app:hintEnabled="true"
|
||||||
|
app:hintTextAppearance="@style/AppearanceFoundation.Tiny"
|
||||||
|
app:hintTextColor="?colorOnSurfaceVariant">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/dialog_custom_download_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textCapWords"
|
||||||
|
android:text="@={data.value}"
|
||||||
|
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||||
|
android:textColor="?colorOnSurface"
|
||||||
|
tools:text="@tools:sample/lorem" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</layout>
|
@ -21,7 +21,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:alpha="@{item.enabled ? 1f : .5f}"
|
android:alpha="@{item.enabled ? 1f : .5f}"
|
||||||
android:onClick="@{(view) -> callback.onItemPressed(view, item)}"
|
android:onClick="@{(view) -> callback.onItemChanged(view, item)}"
|
||||||
tools:layout_gravity="center">
|
tools:layout_gravity="center">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
@ -92,7 +92,7 @@
|
|||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/input_divider"
|
android:id="@+id/input_divider"
|
||||||
gone="@{item.value.empty}"
|
gone="@{item.value.empty || !item.showStrip}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:alpha=".5"
|
android:alpha=".5"
|
||||||
@ -102,7 +102,7 @@
|
|||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/input_selection"
|
android:id="@+id/input_selection"
|
||||||
gone="@{item.value.empty}"
|
gone="@{item.value.empty || !item.showStrip}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="@dimen/l1"
|
android:paddingStart="@dimen/l1"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user