Commit dec1094a authored by Viktor De Pasquale's avatar Viktor De Pasquale

Added "input" settings item, that opens custom input dialog

Updated order of some items in settings
parent 02e32313
package com.topjohnwu.magisk.redesign.settings package com.topjohnwu.magisk.redesign.settings
import android.content.Context import android.content.Context
import android.os.Environment
import android.view.LayoutInflater
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
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.asTransitive import com.topjohnwu.magisk.utils.asTransitive
import com.topjohnwu.magisk.utils.availableLocales import com.topjohnwu.magisk.utils.availableLocales
import com.topjohnwu.magisk.utils.currentLocale import com.topjohnwu.magisk.utils.currentLocale
import java.io.File
// --- Customization // --- Customization
...@@ -69,16 +77,61 @@ object Restore : SettingsItem.Blank() { ...@@ -69,16 +77,61 @@ object Restore : SettingsItem.Blank() {
fun HideOrRestore() = fun HideOrRestore() =
if (get<Context>().packageName == BuildConfig.APPLICATION_ID) Hide else Restore if (get<Context>().packageName == BuildConfig.APPLICATION_ID) Hide else Restore
//todo new dialog object DownloadPath : SettingsItem.Input() {
object DownloadPath override var value: String by dataObservable(Config.downloadPath) { Config.downloadPath = it }
override val title = R.string.settings_download_path_title.asTransitive()
override val intermediate: String?
get() = if (Utils.ensureDownloadPath(result) != null) result else null
var result = value
@Bindable get
set(value) {
field = value
notifyChange(BR.result)
notifyChange(BR.path)
}
val path
@Bindable get() = File(
Environment.getExternalStorageDirectory(),
result
).absolutePath.orEmpty()
override fun getView(context: Context) = DialogSettingsDownloadPathBinding
.inflate(LayoutInflater.from(context)).also { it.data = this }.root
}
//fixme this
object UpdateChannel : SettingsItem.Selector() { object UpdateChannel : SettingsItem.Selector() {
override var value by dataObservable(Config.updateChannel) { Config.updateChannel = it } override var value by dataObservable(Config.updateChannel) { Config.updateChannel = it }
override val title = R.string.settings_update_channel_title.asTransitive()
init {
val entries = resources.getStringArray(R.array.update_channel).let {
if (!Utils.isCanary && Config.updateChannel < Config.Value.CANARY_CHANNEL)
it.take(it.size - 2).toTypedArray() else it
}
setValues(
entries,
resources.getStringArray(R.array.value_array)
)
}
} }
//fixme new dialog object UpdateChannelUrl : SettingsItem.Input() {
object UpdateChannelUrl override val title = R.string.settings_update_custom.asTransitive()
override var value: String by dataObservable(Config.customChannelUrl) {
Config.customChannelUrl = it
}
override val intermediate: String? get() = result
var result = value
@Bindable get
set(value) {
field = value
notifyChange(BR.result)
}
override fun getView(context: Context) = DialogSettingsUpdateChannelBinding
.inflate(LayoutInflater.from(context)).also { it.data = this }.root
}
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()
......
package com.topjohnwu.magisk.redesign.settings package com.topjohnwu.magisk.redesign.settings
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
...@@ -8,6 +9,7 @@ import androidx.databinding.Bindable ...@@ -8,6 +9,7 @@ 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.Config
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
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
...@@ -29,10 +31,11 @@ class SettingsViewModel : CompatViewModel(), SettingsItem.Callback { ...@@ -29,10 +31,11 @@ class SettingsViewModel : CompatViewModel(), SettingsItem.Callback {
val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) } val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) }
val items = diffListOf( val items = diffListOf(
Customization, Customization,
Theme, Language, Redesign, Theme, Language, Redesign, DownloadPath,
Manager, Manager,
ClearRepoCache, HideOrRestore(), UpdateChecker, SystemlessHosts, Biometrics, UpdateChannel, UpdateChannelUrl, ClearRepoCache, HideOrRestore(), UpdateChecker,
SystemlessHosts, Biometrics,
Magisk, Magisk,
SafeMode, MagiskHide, SafeMode, MagiskHide,
...@@ -44,11 +47,23 @@ class SettingsViewModel : CompatViewModel(), SettingsItem.Callback { ...@@ -44,11 +47,23 @@ class SettingsViewModel : CompatViewModel(), SettingsItem.Callback {
override fun onItemPressed(view: View, item: SettingsItem) = when (item) { override fun onItemPressed(view: View, item: SettingsItem) = when (item) {
// use only instances you want, don't declare everything // use only instances you want, don't declare everything
Theme -> Navigation.theme().publish() is Theme -> Navigation.theme().publish()
Redesign -> DieEvent().publish() is Redesign -> DieEvent().publish()
is UpdateChannel -> item.openUrlIfNecessary(view)
else -> Unit else -> Unit
} }
private fun UpdateChannel.openUrlIfNecessary(view: View) {
if (value == Config.Value.CUSTOM_CHANNEL) {
if (UpdateChannelUrl.value.isBlank()) {
UpdateChannelUrl.onPressed(view, this@SettingsViewModel)
}
UpdateChannelUrl.isEnabled = true
} else {
UpdateChannelUrl.isEnabled = false
}
}
} }
sealed class SettingsItem : ObservableItem<SettingsItem>() { sealed class SettingsItem : ObservableItem<SettingsItem>() {
...@@ -60,6 +75,13 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() { ...@@ -60,6 +75,13 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
@Bindable @Bindable
open val description: TransitiveText = TransitiveText.empty open val description: TransitiveText = TransitiveText.empty
var isEnabled = true
@Bindable get
set(value) {
field = value
notifyChange(BR.enabled)
}
protected open val isFullSpan: Boolean = false protected open val isFullSpan: Boolean = false
@CallSuper @CallSuper
...@@ -127,6 +149,40 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() { ...@@ -127,6 +149,40 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
} }
abstract class Input : Value<String>(), KoinComponent {
override val layoutRes = R.layout.item_settings_input
protected val resources get() = get<Resources>()
protected abstract val intermediate: String?
override fun onPressed(view: View, callback: Callback) {
MagiskDialog(view.context)
.applyTitle(title.getText(resources))
.applyView(getView(view.context))
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
titleRes = android.R.string.ok
onClick {
intermediate?.let { result ->
preventDismiss = false
value = result
it.dismiss()
super.onPressed(view, callback)
return@onClick
}
preventDismiss = true
}
}
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
titleRes = android.R.string.cancel
}
.reveal()
}
abstract fun getView(context: Context): View
}
abstract class Selector : Value<Int>(), KoinComponent { abstract class Selector : Value<Int>(), KoinComponent {
override val layoutRes = R.layout.item_settings_selector override val layoutRes = R.layout.item_settings_selector
......
<?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.DownloadPath" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/margin_generic">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/dialog_custom_download_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{@string/settings_download_path_message(data.path)}"
android:textAppearance="@style/AppearanceFoundation.Caption"
tools:text="@string/settings_download_path_message" />
<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_download_path_title"
app:boxStrokeColor="?colorOnSurfaceVariant"
app:errorTextColor="?colorError"
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="textUri"
android:text="@={data.result}"
android:textAppearance="@style/AppearanceFoundation.Body"
android:textColor="?colorOnSurface"
tools:text="@tools:sample/lorem" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</layout>
<?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.UpdateChannelUrl" />
</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_update_custom_msg"
app:boxStrokeColor="?colorOnSurfaceVariant"
app:errorTextColor="?colorError"
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="textUri"
android:text="@={data.result}"
android:textAppearance="@style/AppearanceFoundation.Body"
android:textColor="?colorOnSurface"
tools:text="@tools:sample/lorem" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</layout>
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
style="@style/WidgetFoundation.Card" style="@style/WidgetFoundation.Card"
android:layout_width="match_parent" android:layout_width="match_parent"
isEnabled="@{item.enabled}"
android:alpha="@{item.enabled ? 1f : .5f}"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="@{(view) -> callback.onItemPressed(view, item)}" android:onClick="@{(view) -> callback.onItemPressed(view, item)}"
tools:layout_gravity="center"> tools:layout_gravity="center">
......
<?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="item"
type="com.topjohnwu.magisk.redesign.settings.SettingsItem.Input" />
<variable
name="callback"
type="com.topjohnwu.magisk.redesign.settings.SettingsItem.Callback" />
</data>
<com.google.android.material.card.MaterialCardView
style="@style/WidgetFoundation.Card"
isEnabled="@{item.enabled}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="@{item.enabled ? 1f : .5f}"
android:onClick="@{(view) -> item.onPressed(view, callback)}"
tools:layout_gravity="center">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?listPreferredItemHeightSmall"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/input_icon"
style="@style/WidgetFoundation.Icon"
gone="@{item.icon == 0}"
android:background="@null"
android:rotation="180"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/input_divider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@{item.icon}"
tools:srcCompat="@drawable/ic_fingerprint" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/input_indicator"
style="@style/WidgetFoundation.Icon"
android:background="@null"
android:rotation="180"
app:layout_constraintBottom_toTopOf="@+id/input_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_back_md2" />
<LinearLayout
android:id="@+id/input_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@{item.icon == 0 ? (int) @dimen/l1 : 0}"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingTop="@dimen/l1"
android:paddingBottom="@dimen/l1"
app:layout_constraintBottom_toTopOf="@+id/input_divider"
app:layout_constraintEnd_toStartOf="@+id/input_indicator"
app:layout_constraintStart_toEndOf="@+id/input_icon"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/input_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="start"
android:text="@{item.title}"
android:textAppearance="@style/AppearanceFoundation.Body"
android:textStyle="bold"
tools:lines="1"
tools:text="@tools:sample/lorem/random" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/input_description"
gone="@{item.description.empty}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{item.description}"
android:textAppearance="@style/AppearanceFoundation.Tiny.Variant"
tools:lines="2"
tools:text="@tools:sample/lorem/random" />
</LinearLayout>
<View
android:id="@+id/input_divider"
gone="@{item.value.empty}"
android:layout_width="match_parent"
android:layout_height="0dp"
android:alpha=".5"
android:background="?colorSurface"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/input_text" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/input_selection"
gone="@{item.value.empty}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/l1"
android:paddingTop="@dimen/l_75"
android:paddingEnd="@dimen/l1"
android:paddingBottom="@dimen/l_75"
android:text="@{item.value}"
android:textAppearance="@style/AppearanceFoundation.Tiny.Variant"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/input_text"
app:layout_constraintTop_toTopOf="@+id/input_divider"
tools:text="@tools:sample/lorem" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
\ No newline at end of file
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
style="@style/WidgetFoundation.Card" style="@style/WidgetFoundation.Card"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
isEnabled="@{item.enabled}"
android:alpha="@{item.enabled ? 1f : .5f}"
android:onClick="@{(view) -> item.onPressed(view, callback)}" android:onClick="@{(view) -> item.onPressed(view, callback)}"
tools:layout_gravity="center"> tools:layout_gravity="center">
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
style="@style/WidgetFoundation.Card" style="@style/WidgetFoundation.Card"
android:layout_width="match_parent" android:layout_width="match_parent"
isEnabled="@{item.enabled}"
android:alpha="@{item.enabled ? 1f : .5f}"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="@{(view) -> item.onPressed(view, callback)}" android:onClick="@{(view) -> item.onPressed(view, callback)}"
tools:layout_gravity="center"> tools:layout_gravity="center">
...@@ -49,6 +51,7 @@ ...@@ -49,6 +51,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/l_25" android:layout_marginEnd="@dimen/l_25"
android:checked="@{item.value}" android:checked="@{item.value}"
isEnabled="@{item.enabled}"
android:text="" android:text=""
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
......
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
<string name="settings_update_channel_title">Update Channel</string> <string name="settings_update_channel_title">Update Channel</string>
<string name="settings_update_stable">Stable</string> <string name="settings_update_stable">Stable</string>
<string name="settings_update_beta">Beta</string> <string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Custom</string> <string name="settings_update_custom">Custom Channel</string>
<string name="settings_update_custom_msg">Insert a custom URL</string> <string name="settings_update_custom_msg">Insert a custom URL</string>
<string name="settings_core_only_title">Magisk Core Only Mode</string> <string name="settings_core_only_title">Magisk Core Only Mode</string>
<string name="settings_core_only_summary">Enable only core features. MagiskSU and MagiskHide will still be enabled, but no modules will be loaded</string> <string name="settings_core_only_summary">Enable only core features. MagiskSU and MagiskHide will still be enabled, but no modules will be loaded</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment