Skip to content

Commit

Permalink
feat: add dialog to manually set any value (#96)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyujin-cho authored Mar 26, 2023
1 parent f516059 commit 6a664a8
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 21 deletions.
128 changes: 128 additions & 0 deletions app/src/main/java/dev/bluehouse/enablevolte/Components.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
package dev.bluehouse.enablevolte

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
Expand All @@ -29,8 +38,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
Expand Down Expand Up @@ -230,6 +242,122 @@ fun StringPropertyView(label: String, value: String?, onUpdate: ((String) -> Uni
}
}

enum class ValueType {
Int,
Long,
Bool,
String,
IntArray,
LongArray,
BoolArray,
StringArray,
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun KeyValueEditView(label: String, onUpdate: ((String, ValueType?, String) -> Boolean)) {
var configKey by rememberSaveable { mutableStateOf("") }
var selectedValueType: ValueType? by rememberSaveable { mutableStateOf(null) }
var value by rememberSaveable { mutableStateOf("") }
var openEditPropertyDialog by rememberSaveable { mutableStateOf(false) }
var dropdownExpanded by rememberSaveable { mutableStateOf(false) }

if (openEditPropertyDialog) {
Dialog(
onDismissRequest = { openEditPropertyDialog = false },
properties = DialogProperties(),
) {
Card(
colors = CardDefaults.cardColors(
containerColor = AlertDialogDefaults.containerColor,
contentColor = AlertDialogDefaults.textContentColor,
),
) {
Column(modifier = Modifier.padding(20.dp)) {
Text(stringResource(R.string.update_value), modifier = Modifier.padding(bottom = 16.dp), style = MaterialTheme.typography.titleLarge)
TextField(
value = configKey,
label = { Text(stringResource(R.string.property_name)) },
onValueChange = { configKey = it },
)
ExposedDropdownMenuBox(
expanded = dropdownExpanded,
onExpandedChange = { dropdownExpanded = !dropdownExpanded },
modifier = Modifier.padding(bottom = 8.dp),
) {
TextField(
// The `menuAnchor` modifier must be passed to the text field for correctness.
modifier = Modifier.menuAnchor().wrapContentWidth(),
readOnly = true,
value = selectedValueType?.name ?: "",
onValueChange = {},
label = { Text(stringResource(R.string.property_type)) },
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = dropdownExpanded)
},
colors = ExposedDropdownMenuDefaults.textFieldColors(),
)
ExposedDropdownMenu(
expanded = dropdownExpanded,
onDismissRequest = { dropdownExpanded = false },
) {
ValueType.values().forEach { valueType ->
DropdownMenuItem(
text = { Text(text = valueType.name) },
onClick = {
if (selectedValueType != valueType) {
selectedValueType = valueType
value = ""
}
dropdownExpanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
)
}
}
}
when (selectedValueType) {
ValueType.Bool -> Row(
modifier = Modifier.selectableGroup(),
verticalAlignment = Alignment.CenterVertically,
) {
RadioButton(
selected = value == "true",
onClick = { value = "true" },
)
Text("true")
RadioButton(
selected = value == "false",
onClick = { value = "false" },
)
Text("false")
}
ValueType.Int, ValueType.Long -> TextField(
value = value,
onValueChange = { value = it },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
)
is ValueType -> TextField(value = value, onValueChange = { value = it })
else -> Box(modifier = Modifier.defaultMinSize(minHeight = 48.dp))
}
Row(modifier = Modifier.padding(top = 16.dp)) {
Spacer(Modifier.weight(1f))
TextButton(onClick = {
if (onUpdate(configKey, selectedValueType, value)) {
openEditPropertyDialog = false
}
}, enabled = selectedValueType != null) { Text(stringResource(R.string.confirm)) }
TextButton(onClick = { openEditPropertyDialog = false }) { Text(stringResource(R.string.dismiss)) }
}
}
}
}
}
ClickablePropertyView(label = label, value = "") {
openEditPropertyDialog = true
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ClickablePropertyView(label: String, value: String?, onClick: (() -> Unit)? = null) {
Expand Down
11 changes: 9 additions & 2 deletions app/src/main/java/dev/bluehouse/enablevolte/HomeActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.navigation
import androidx.navigation.compose.rememberNavController
import dev.bluehouse.enablevolte.pages.Config
import dev.bluehouse.enablevolte.pages.DumpedConfig
import dev.bluehouse.enablevolte.pages.Home
import dev.bluehouse.enablevolte.ui.theme.EnableVoLTETheme
import org.lsposed.hiddenapibypass.HiddenApiBypass
Expand Down Expand Up @@ -90,8 +92,13 @@ fun PixelIMSApp() {
Home(navController)
}
for (subscription in subscriptions) {
composable("config${subscription.subscriptionId}") {
Config(navController, subscription.subscriptionId)
navigation(startDestination = "editConfig${subscription.subscriptionId}", route = "config${subscription.subscriptionId}") {
composable("editConfig${subscription.subscriptionId}") {
Config(navController, subscription.subscriptionId)
}
composable("dumpConfig${subscription.subscriptionId}") {
DumpedConfig(subscription.subscriptionId)
}
}
}
}
Expand Down
94 changes: 75 additions & 19 deletions app/src/main/java/dev/bluehouse/enablevolte/Moder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -95,36 +95,49 @@ class CarrierModer(private val context: Context) : Moder() {
}

class SubscriptionModer(val subscriptionId: Int) : Moder() {
fun updateCarrierConfig(key: String, value: Boolean) {
Log.d(TAG, "Setting $key to $value")
private fun publishBundle(fn: (PersistableBundle) -> Unit) {
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
val overrideBundle = PersistableBundle()
overrideBundle.putBoolean(key, value)
fn(overrideBundle)
iCclInstance.overrideConfig(this.subscriptionId, overrideBundle, true)
}
fun updateCarrierConfig(key: String, value: Boolean) {
Log.d(TAG, "Setting $key to $value")
publishBundle { it.putBoolean(key, value) }
}

fun updateCarrierConfig(key: String, value: String) {
Log.d(TAG, "Setting $key to $value")
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
val overrideBundle = PersistableBundle()
overrideBundle.putString(key, value)
iCclInstance.overrideConfig(this.subscriptionId, overrideBundle, true)
publishBundle { it.putString(key, value) }
}

fun updateCarrierConfig(key: String, value: Int) {
Log.d(TAG, "Setting $key to $value")
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
val overrideBundle = PersistableBundle()
overrideBundle.putInt(key, value)
iCclInstance.overrideConfig(this.subscriptionId, overrideBundle, true)
publishBundle { it.putInt(key, value) }
}
fun updateCarrierConfig(key: String, value: Long) {
Log.d(TAG, "Setting $key to $value")
publishBundle { it.putLong(key, value) }
}

fun updateCarrierConfig(key: String, value: IntArray) {
Log.d(TAG, "Setting $key to $value")
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
val overrideBundle = PersistableBundle()
overrideBundle.putIntArray(key, value)
iCclInstance.overrideConfig(this.subscriptionId, overrideBundle, true)
publishBundle { it.putIntArray(key, value) }
}

fun updateCarrierConfig(key: String, value: BooleanArray) {
Log.d(TAG, "Setting $key to $value")
publishBundle { it.putBooleanArray(key, value) }
}

fun updateCarrierConfig(key: String, value: Array<String>) {
Log.d(TAG, "Setting $key to $value")
publishBundle { it.putStringArray(key, value) }
}

fun updateCarrierConfig(key: String, value: LongArray) {
Log.d(TAG, "Setting $key to $value")
publishBundle { it.putLongArray(key, value) }
}

fun clearCarrierConfig() {
Expand All @@ -138,7 +151,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
telephony.resetIms(sub.getSlotIndex(this.subscriptionId))
}

private fun getStringValue(key: String): String {
fun getStringValue(key: String): String {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return ""
Expand All @@ -149,7 +162,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
return config.getString(key)
}

private fun getBooleanValue(key: String): Boolean {
fun getBooleanValue(key: String): Boolean {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return false
Expand All @@ -160,7 +173,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
return config.getBoolean(key)
}

private fun getIntValue(key: String): Int {
fun getIntValue(key: String): Int {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return -1
Expand All @@ -171,7 +184,29 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
return config.getInt(key)
}

private fun getIntArrayValue(key: String): IntArray {
fun getLongValue(key: String): Long {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return -1
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }

val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
return config.getLong(key)
}

fun getBooleanArrayValue(key: String): BooleanArray {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return booleanArrayOf()
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }

val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
return config.getBooleanArray(key)
}

fun getIntArrayValue(key: String): IntArray {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return intArrayOf()
Expand All @@ -182,6 +217,27 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
return config.getIntArray(key)
}

fun getStringArrayValue(key: String): Array<String> {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return arrayOf()
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }

val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
return config.getStringArray(key)
}
fun getValue(key: String): Any? {
val subscriptionId = this.subscriptionId
if (subscriptionId < 0) {
return null
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }

val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
return config.get(key)
}

val isVoLteConfigEnabled: Boolean
get() = this.getBooleanValue(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)

Expand Down
Loading

0 comments on commit 6a664a8

Please sign in to comment.