diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 103e00c..44ca2d9 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -3,30 +3,39 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c8b229a..86402f9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,12 +5,12 @@ plugins {
android {
namespace 'dev.bluehouse.enablevolte'
- compileSdk 33
+ compileSdk 34
defaultConfig {
applicationId "dev.bluehouse.enablevolte"
minSdk 29
- targetSdk 33
+ targetSdk 34
versionCode 13
versionName "1.2.8"
@@ -36,6 +36,7 @@ android {
buildFeatures {
compose true
aidl true
+ buildConfig true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.0"
@@ -48,18 +49,17 @@ android {
}
dependencies {
- def nav_version = "2.5.3"
- def material3_version = "1.1.0-beta01"
+ debugImplementation 'androidx.compose.ui:ui-tooling:1.6.1'
def compose_runtime_version = "1.4.0-beta01"
- implementation 'androidx.core:core-ktx:1.9.0'
- implementation 'androidx.appcompat:appcompat:1.6.0'
- implementation 'com.google.android.material:material:1.8.0'
+ implementation 'androidx.core:core-ktx:1.12.0'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
- implementation 'androidx.activity:activity-compose:1.6.1'
+ implementation 'androidx.activity:activity-compose:1.8.2'
- implementation "androidx.navigation:navigation-compose:$nav_version"
+ implementation "androidx.navigation:navigation-compose:2.7.7"
implementation "androidx.compose.runtime:runtime:$compose_runtime_version"
implementation "androidx.compose.runtime:runtime-livedata:$compose_runtime_version"
@@ -68,15 +68,15 @@ dependencies {
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
- implementation "androidx.compose.material:material:1.3.1"
- implementation "androidx.compose.material3:material3:$material3_version"
+ implementation "androidx.compose.material:material:1.6.1"
+ implementation "androidx.compose.material3:material3:1.2.0"
- implementation("io.arrow-kt:arrow-core:1.2.0-RC")
- implementation("io.arrow-kt:arrow-fx-coroutines:1.2.0-RC")
+ implementation "io.arrow-kt:arrow-core:1.2.0-RC"
+ implementation "io.arrow-kt:arrow-fx-coroutines:1.2.0-RC"
implementation "com.google.accompanist:accompanist-systemuicontroller:0.28.0"
- def shizuku_version = "13.1.0"
+ def shizuku_version = "13.1.5"
implementation "dev.rikka.shizuku:api:$shizuku_version"
implementation "dev.rikka.shizuku:provider:$shizuku_version"
implementation 'com.anggrayudi:android-hidden-api:30.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b6efb38..2b48532 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -11,7 +11,7 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.EnableVoLTE"
- tools:targetApi="33"
+ tools:targetApi="34"
android:localeConfig="@xml/locales_config">
Unit)? = null,
) {
+ val localEnabled = enabled && VERSION.SDK_INT >= minSdk
+
if (toggled == null) {
Column(modifier = Modifier.padding(top = 12.dp, bottom = 12.dp)) {
Text(text = label, fontSize = 18.sp, modifier = Modifier.padding(bottom = 4.dp))
@@ -102,7 +111,7 @@ fun BooleanPropertyView(
if (onClick != null) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(top = 12.dp, bottom = 12.dp)) {
Text(text = label, modifier = Modifier.weight(1F), fontSize = 18.sp)
- Switch(checked = toggled, enabled = enabled, onCheckedChange = onClick)
+ Switch(checked = toggled, enabled = localEnabled, onCheckedChange = onClick)
}
} else {
Column(modifier = Modifier.padding(top = 12.dp, bottom = 12.dp)) {
@@ -113,6 +122,90 @@ fun BooleanPropertyView(
}
@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun UserAgentUpdateDialog(
+ labels: Array,
+ values: Array,
+ selectedIndex: Int,
+ typedText: String,
+ dropdownExpanded: Boolean,
+ onTextUpdate: (String) -> Unit,
+ onIndexUpdate: (Int) -> Unit,
+ onDismissRequest: () -> Unit,
+ onExpandedChange: (Boolean) -> Unit,
+) {
+ AlertDialog(onDismissRequest = onDismissRequest) {
+ Surface(
+ modifier = Modifier
+ .wrapContentWidth()
+ .wrapContentHeight(),
+ shape = RoundedCornerShape(10),
+ ) {
+ Column(modifier = Modifier.padding(all = 16.dp)) {
+ Text(text = stringResource(R.string.update_value), style = MaterialTheme.typography.labelMedium, modifier = Modifier.padding(bottom = 24.dp))
+ ExposedDropdownMenuBox(
+ expanded = dropdownExpanded,
+ onExpandedChange = onExpandedChange,
+ 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 = if (values[selectedIndex] == typedText) labels[selectedIndex] else "Custom",
+ onValueChange = {},
+ label = { Text(stringResource(R.string.presets)) },
+ trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = dropdownExpanded) },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ ExposedDropdownMenu(
+ expanded = dropdownExpanded,
+ onDismissRequest = { onExpandedChange(false) },
+ ) {
+ labels.forEachIndexed { i, label ->
+ DropdownMenuItem(
+ text = { Text(text = label) },
+ onClick = {
+ onTextUpdate(values[i])
+ onIndexUpdate(i)
+ onExpandedChange(false)
+ },
+ contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
+ )
+ }
+ }
+ }
+ TextField(textStyle = TextStyle(fontSize = 14.sp), value = typedText, onValueChange = { onTextUpdate(it) })
+ Row(modifier = Modifier.align(Alignment.End).padding(top = 16.dp)) {
+ TextButton(
+ border = BorderStroke(0.5.dp, MaterialTheme.colorScheme.primary),
+ modifier = Modifier.padding(end = 8.dp),
+ shape = ButtonDefaults.outlinedShape,
+ onClick = { onDismissRequest() },
+ ) {
+ Text(stringResource(R.string.dismiss))
+ }
+ TextButton(
+ border = BorderStroke(0.5.dp, MaterialTheme.colorScheme.primary),
+ shape = ButtonDefaults.outlinedShape,
+ colors = ButtonDefaults.filledTonalButtonColors(
+ containerColor = MaterialTheme.colorScheme.primary,
+ ),
+ onClick = {
+ onTextUpdate(typedText)
+ onDismissRequest()
+ },
+ ) {
+ Text(stringResource(R.string.confirm), color = MaterialTheme.colorScheme.onPrimary)
+ }
+ }
+ }
+ }
+ }
+}
+
@Composable
fun UserAgentPropertyView(label: String, value: String?, onUpdate: ((String) -> Unit)? = null) {
val labels = arrayOf(stringResource(R.string.default_), stringResource(R.string.lgu))
@@ -121,79 +214,26 @@ fun UserAgentPropertyView(label: String, value: String?, onUpdate: ((String) ->
var typedText by rememberSaveable { mutableStateOf("") }
var openTextEditDialog by rememberSaveable { mutableStateOf(false) }
var dropdownExpanded by rememberSaveable { mutableStateOf(false) }
- var selectedIndex by rememberSaveable { mutableStateOf(if (values.contains(value)) values.indexOf(value) else 0) }
+ var selectedIndex by rememberSaveable { mutableIntStateOf(if (values.contains(value)) values.indexOf(value) else 0) }
if (onUpdate != null) {
if (openTextEditDialog) {
- AlertDialog(
- onDismissRequest = {
- // Dismiss the dialog when the user clicks outside the dialog or on the back
- // button. If you want to disable that functionality, simply use an empty
- // onDismissRequest.
- openTextEditDialog = false
+ UserAgentUpdateDialog(
+ labels,
+ values,
+ selectedIndex,
+ typedText,
+ dropdownExpanded,
+ onTextUpdate = {
+ typedText = it
+ onUpdate(typedText)
},
- ) {
- Surface(
- modifier = Modifier
- .wrapContentWidth()
- .wrapContentHeight(),
- shape = MaterialTheme.shapes.large,
- ) {
- Column(modifier = Modifier.padding(all = 16.dp)) {
- Text(text = stringResource(R.string.update_value), style = MaterialTheme.typography.titleLarge, modifier = Modifier.padding(bottom = 24.dp))
- 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 = if (values[selectedIndex] == typedText) labels[selectedIndex] else "Custom",
- onValueChange = {},
- label = { Text(stringResource(R.string.presets)) },
- trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = dropdownExpanded) },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
- )
- ExposedDropdownMenu(
- expanded = dropdownExpanded,
- onDismissRequest = { dropdownExpanded = false },
- ) {
- labels.forEachIndexed { i, label ->
- DropdownMenuItem(
- text = { Text(text = label) },
- onClick = {
- typedText = values[i]
- selectedIndex = i
- dropdownExpanded = false
- },
- contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
- )
- }
- }
- }
- TextField(textStyle = TextStyle(fontSize = 14.sp), value = typedText, onValueChange = { typedText = it })
- Row(modifier = Modifier.align(Alignment.End)) {
- TextButton(
- onClick = {
- onUpdate(typedText)
- openTextEditDialog = false
- },
- ) {
- Text(stringResource(R.string.confirm))
- }
- TextButton(
- onClick = {
- openTextEditDialog = false
- },
- ) {
- Text(stringResource(R.string.dismiss))
- }
- }
- }
- }
- }
+ onIndexUpdate = {
+ selectedIndex = it
+ },
+ onDismissRequest = { openTextEditDialog = false },
+ onExpandedChange = { dropdownExpanded = it },
+ )
}
}
ClickablePropertyView(label = label, value = value) {
@@ -204,7 +244,6 @@ fun UserAgentPropertyView(label: String, value: String?, onUpdate: ((String) ->
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StringPropertyView(label: String, value: String?, onUpdate: ((String) -> Unit)? = null) {
var typedText by rememberSaveable { mutableStateOf("") }
@@ -268,9 +307,185 @@ enum class ValueType {
data class ArrayValueType(val v: T)
@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun EditPropertyDialog(
+ availableKeys: Iterable?,
+ configKey: String,
+ selectedValueType: ValueType?,
+ value: String,
+ keyDropdownExpanded: Boolean,
+ valueTypeDropdownExpanded: Boolean,
+ filteringOptions: List,
+ onConfigKeyChange: (String) -> Unit,
+ onValueTypeChange: (ValueType) -> Unit,
+ onValueChange: (String) -> Unit,
+ onUpdate: (String, ValueType?, String) -> Boolean,
+ onKeyDropdownExpandedChange: (Boolean) -> Unit,
+ onValueDropdownExpandedChange: (Boolean) -> Unit,
+ dismissDialog: () -> Unit,
+) {
+ val TAG = "Components:EditPropertyDialog"
+ Dialog(
+ onDismissRequest = { dismissDialog() },
+ 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.labelMedium)
+ if (availableKeys != null) {
+ ExposedDropdownMenuBox(
+ expanded = keyDropdownExpanded,
+ onExpandedChange = {
+ Log.d(TAG, "Expand state change requested: ${!keyDropdownExpanded}")
+ onKeyDropdownExpandedChange(it)
+ },
+ ) {
+ TextField(
+ // The `menuAnchor` modifier must be passed to the text field for correctness.
+ modifier = Modifier
+ .menuAnchor()
+ .fillMaxWidth()
+ .onFocusChanged {
+ onKeyDropdownExpandedChange(it.isFocused)
+ },
+ value = configKey,
+ onValueChange = { onConfigKeyChange(it) },
+ label = { Text(stringResource(R.string.property_name)) },
+ trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = keyDropdownExpanded) },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ if (filteringOptions.isNotEmpty() && keyDropdownExpanded) {
+ ExposedDropdownMenu(
+ expanded = true,
+ onDismissRequest = {},
+ ) {
+ filteringOptions.forEach { selectionOption ->
+ DropdownMenuItem(
+ text = { Text(selectionOption) },
+ onClick = {
+ onConfigKeyChange(selectionOption)
+ onKeyDropdownExpandedChange(false)
+ },
+ contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
+ )
+ }
+ }
+ }
+ }
+ } else {
+ TextField(
+ value = configKey,
+ label = { Text(stringResource(R.string.property_name)) },
+ onValueChange = { onConfigKeyChange(it) },
+ )
+ }
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 4.dp),
+ verticalAlignment = if (selectedValueType == ValueType.Bool) { Alignment.CenterVertically } else { Alignment.Top },
+ ) {
+ ExposedDropdownMenuBox(
+ expanded = valueTypeDropdownExpanded,
+ onExpandedChange = { onValueDropdownExpandedChange(it) },
+ modifier = Modifier
+ .padding(bottom = 8.dp)
+ .weight(1.0F),
+ ) {
+ TextField(
+ // The `menuAnchor` modifier must be passed to the text field for correctness.
+ modifier = Modifier
+ .menuAnchor()
+ .weight(1.0F),
+ readOnly = true,
+ value = selectedValueType?.name ?: "",
+ onValueChange = {},
+ label = { Text(stringResource(R.string.property_type)) },
+ trailingIcon = {
+ ExposedDropdownMenuDefaults.TrailingIcon(expanded = valueTypeDropdownExpanded)
+ },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ ExposedDropdownMenu(
+ expanded = valueTypeDropdownExpanded,
+ onDismissRequest = { onValueDropdownExpandedChange(false) },
+ ) {
+ ValueType.values().forEach { valueType ->
+ DropdownMenuItem(
+ text = { Text(text = valueType.name) },
+ onClick = {
+ if (selectedValueType != valueType) {
+ onValueTypeChange(valueType)
+ onValueChange("")
+ }
+ onValueDropdownExpandedChange(false)
+ },
+ contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
+ )
+ }
+ }
+ }
+ Box(modifier = Modifier.weight(0.05F))
+ Box(modifier = Modifier.weight(1.0F, fill = true)) {
+ when (selectedValueType) {
+ ValueType.Bool -> Row(
+ modifier = Modifier.selectableGroup(),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ RadioButton(
+ selected = value == "true",
+ onClick = { onValueChange("true") },
+ )
+ Text(stringResource(R.string.true_))
+ RadioButton(
+ selected = value == "false",
+ onClick = { onValueChange("false") },
+ )
+ Text(stringResource(R.string.false_))
+ }
+ ValueType.Int, ValueType.Long -> TextField(
+ value = value,
+ onValueChange = { onValueChange(it) },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
+ )
+ is ValueType -> TextField(value = value, onValueChange = { onValueChange(it) })
+ else -> Box(modifier = Modifier.fillMaxWidth())
+ }
+ }
+ }
+ Row(modifier = Modifier.align(Alignment.End).padding(top = 16.dp)) {
+ TextButton(
+ border = BorderStroke(0.5.dp, MaterialTheme.colorScheme.primary),
+ modifier = Modifier.padding(end = 8.dp),
+ shape = ButtonDefaults.outlinedShape,
+ onClick = { dismissDialog() },
+ ) { Text(stringResource(R.string.dismiss)) }
+ TextButton(
+ border = if (selectedValueType != null) BorderStroke(0.5.dp, MaterialTheme.colorScheme.primary) else null,
+ shape = ButtonDefaults.outlinedShape,
+ colors = ButtonDefaults.filledTonalButtonColors(
+ containerColor = MaterialTheme.colorScheme.primary,
+ ),
+ onClick = {
+ if (onUpdate(configKey, selectedValueType, value)) {
+ dismissDialog()
+ }
+ },
+ enabled = selectedValueType != null,
+ ) { Text(stringResource(R.string.confirm)) }
+ }
+ }
+ }
+ }
+}
+
@Composable
fun KeyValueEditView(label: String, availableKeys: Iterable? = null, onUpdate: ((String, ValueType?, String) -> Boolean)) {
- val TAG = "Components:KeyValueEditView"
var configKey by rememberSaveable { mutableStateOf("") }
var selectedValueType: ValueType? by rememberSaveable { mutableStateOf(null) }
var value by rememberSaveable { mutableStateOf("") }
@@ -297,149 +512,28 @@ fun KeyValueEditView(label: String, availableKeys: Iterable? = null, onU
}
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)
- if (availableKeys != null) {
- ExposedDropdownMenuBox(
- expanded = keyDropdownExpanded,
- onExpandedChange = {
- Log.d(TAG, "Expand state change requested: ${!keyDropdownExpanded}")
- keyDropdownExpanded = !keyDropdownExpanded
- },
- ) {
- TextField(
- // The `menuAnchor` modifier must be passed to the text field for correctness.
- modifier = Modifier.menuAnchor().fillMaxWidth().onFocusChanged {
- keyDropdownExpanded = it.isFocused
- },
- value = configKey,
- onValueChange = { configKey = it },
- label = { Text(stringResource(R.string.property_name)) },
- trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = keyDropdownExpanded) },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
- )
- if (filteringOptions.isNotEmpty() && keyDropdownExpanded) {
- ExposedDropdownMenu(
- expanded = true,
- onDismissRequest = {},
- ) {
- filteringOptions.forEach { selectionOption ->
- DropdownMenuItem(
- text = { Text(selectionOption) },
- onClick = {
- configKey = selectionOption
- keyDropdownExpanded = false
- },
- contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
- )
- }
- }
- }
- }
- } else {
- TextField(
- value = configKey,
- label = { Text(stringResource(R.string.property_name)) },
- onValueChange = { configKey = it },
- )
- }
- Row(
- modifier = Modifier.fillMaxWidth().padding(top = 4.dp),
- verticalAlignment = if (selectedValueType == ValueType.Bool) { Alignment.CenterVertically } else { Alignment.Top },
- ) {
- ExposedDropdownMenuBox(
- expanded = valueTypeDropdownExpanded,
- onExpandedChange = { valueTypeDropdownExpanded = !valueTypeDropdownExpanded },
- modifier = Modifier.padding(bottom = 8.dp).weight(1.0F),
- ) {
- TextField(
- // The `menuAnchor` modifier must be passed to the text field for correctness.
- modifier = Modifier.menuAnchor().weight(1.0F),
- readOnly = true,
- value = selectedValueType?.name ?: "",
- onValueChange = {},
- label = { Text(stringResource(R.string.property_type)) },
- trailingIcon = {
- ExposedDropdownMenuDefaults.TrailingIcon(expanded = valueTypeDropdownExpanded)
- },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
- )
- ExposedDropdownMenu(
- expanded = valueTypeDropdownExpanded,
- onDismissRequest = { valueTypeDropdownExpanded = false },
- ) {
- ValueType.values().forEach { valueType ->
- DropdownMenuItem(
- text = { Text(text = valueType.name) },
- onClick = {
- if (selectedValueType != valueType) {
- selectedValueType = valueType
- value = ""
- }
- valueTypeDropdownExpanded = false
- },
- contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
- )
- }
- }
- }
- Box(modifier = Modifier.weight(0.05F))
- Box(modifier = Modifier.weight(1.0F, fill = true)) {
- when (selectedValueType) {
- ValueType.Bool -> Row(
- modifier = Modifier.selectableGroup(),
- verticalAlignment = Alignment.CenterVertically,
- ) {
- RadioButton(
- selected = value == "true",
- onClick = { value = "true" },
- )
- Text(stringResource(R.string.true_))
- RadioButton(
- selected = value == "false",
- onClick = { value = "false" },
- )
- Text(stringResource(R.string.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.fillMaxWidth())
- }
- }
- }
- 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)) }
- }
- }
- }
- }
+ EditPropertyDialog(
+ availableKeys,
+ configKey,
+ selectedValueType,
+ value,
+ keyDropdownExpanded,
+ valueTypeDropdownExpanded,
+ filteringOptions,
+ onConfigKeyChange = { configKey = it },
+ onValueTypeChange = { selectedValueType = it },
+ onValueChange = { value = it },
+ onUpdate = onUpdate,
+ onKeyDropdownExpandedChange = { keyDropdownExpanded = it },
+ onValueDropdownExpandedChange = { valueTypeDropdownExpanded = it },
+ dismissDialog = { openEditPropertyDialog = false },
+ )
}
ClickablePropertyView(label = label, value = "") {
openEditPropertyDialog = true
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ClickablePropertyView(label: String, value: String?, labelFontSize: TextUnit = 18.sp, valueFontSize: TextUnit = 14.sp, labelFontFamily: FontFamily? = null, valueFontFamily: FontFamily? = null, onClick: (() -> Unit)? = null) {
if (value == null) {
@@ -518,7 +612,10 @@ fun FiniteLoadingDialog(current: Int, total: Int) {
Column {
Text(stringResource(R.string.loading), fontWeight = FontWeight.Bold, fontSize = 24.sp)
LinearProgressIndicator(
- modifier = Modifier.semantics(mergeDescendants = true) {}.padding(top = 24.dp, bottom = 4.dp).fillMaxWidth(),
+ modifier = Modifier
+ .semantics(mergeDescendants = true) {}
+ .padding(top = 24.dp, bottom = 4.dp)
+ .fillMaxWidth(),
progress = current.toFloat() / total,
)
Text(stringResource(R.string.loaded, current, total))
@@ -528,3 +625,121 @@ fun FiniteLoadingDialog(current: Int, total: Int) {
}
}
}
+
+@Preview
+@Composable
+fun HeaderTextPreview() {
+ HeaderText("Lorem Ipsum")
+}
+
+@Preview
+@Composable
+fun BooleanPropertyViewPreview() {
+ var toggled by remember { mutableStateOf(false) }
+ BooleanPropertyView(label = "Lorem Ipsum", toggled = toggled) { toggled = !toggled }
+}
+
+@Preview
+@Composable
+fun LowSDKBooleanPropertyViewPreview() {
+ var toggled by remember { mutableStateOf(false) }
+ BooleanPropertyView(label = "Lorem Ipsum", toggled = toggled, minSdk = 999) { toggled = !toggled }
+}
+
+@Preview
+@Composable
+fun UserAgentPropertyViewPreview() {
+ UserAgentPropertyView("Lorem Ipsum", value = stringResource(R.string.ua_default))
+}
+
+@Preview
+@Composable
+fun StringPropertyViewPreview() {
+ var value by remember { mutableStateOf("") }
+ StringPropertyView("Lorem Ipsum", value) { value = it }
+}
+
+@Preview
+@Composable
+fun KeyValueEditViewPreview() {
+ KeyValueEditView("Lorem Ipsum", "dolor sit amet consectetur adipiscing elit".split(" ")) { _, _, _ ->
+ false
+ }
+}
+
+@Preview
+@Composable
+fun ClickablePropertyViewPreview() {
+ val value by remember { mutableStateOf("dolor sit amet") }
+ ClickablePropertyView("Lorem Ipsum", value) {}
+}
+
+@Preview
+@Composable
+fun InfiniteLoadingDialogPreview() {
+ InfiniteLoadingDialog()
+}
+
+@Preview
+@Composable
+fun FiniteLoadingDialogPreview() {
+ FiniteLoadingDialog(1, 2)
+}
+
+@Preview
+@Composable
+fun UserAgentUpdateDialogPreview() {
+ val labels = arrayOf(stringResource(R.string.default_), stringResource(R.string.lgu))
+ val values = arrayOf(stringResource(R.string.ua_default), stringResource(R.string.ua_lgu))
+
+ var typedText by rememberSaveable { mutableStateOf("") }
+ var openTextEditDialog by rememberSaveable { mutableStateOf(false) }
+ var dropdownExpanded by rememberSaveable { mutableStateOf(false) }
+ var selectedIndex by rememberSaveable { mutableIntStateOf(0) }
+
+ UserAgentUpdateDialog(
+ labels,
+ values,
+ selectedIndex,
+ typedText,
+ dropdownExpanded,
+ onTextUpdate = {
+ typedText = it
+ },
+ onIndexUpdate = {
+ selectedIndex = it
+ },
+ onDismissRequest = { openTextEditDialog = false },
+ onExpandedChange = { dropdownExpanded = it },
+ )
+}
+
+@Preview
+@Composable
+fun EditPropertyDialogPreview() {
+ val availableKeys = "Lorem ipsum dolor sit amet consectetur adipiscing elit".split(" ")
+ var configKey by rememberSaveable { mutableStateOf("") }
+ var selectedValueType: ValueType? by rememberSaveable { mutableStateOf(null) }
+ var value by rememberSaveable { mutableStateOf("") }
+ var openEditPropertyDialog by rememberSaveable { mutableStateOf(false) }
+ var keyDropdownExpanded by rememberSaveable { mutableStateOf(false) }
+ var valueTypeDropdownExpanded by rememberSaveable { mutableStateOf(false) }
+ val filteringOptions = listOf()
+
+ EditPropertyDialog(
+ availableKeys,
+ configKey,
+ selectedValueType,
+ value,
+ keyDropdownExpanded,
+ valueTypeDropdownExpanded,
+ filteringOptions,
+ onConfigKeyChange = { configKey = it },
+ onValueTypeChange = { selectedValueType = it },
+ onValueChange = { value = it },
+ onUpdate = { _, _, _ -> false },
+ onKeyDropdownExpandedChange = { keyDropdownExpanded = it },
+ onValueDropdownExpandedChange = { valueTypeDropdownExpanded = it },
+ dismissDialog = { openEditPropertyDialog = false },
+ )
+}
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/HomeActivity.kt b/app/src/main/java/dev/bluehouse/enablevolte/HomeActivity.kt
index 11fd0f3..05d5d49 100644
--- a/app/src/main/java/dev/bluehouse/enablevolte/HomeActivity.kt
+++ b/app/src/main/java/dev/bluehouse/enablevolte/HomeActivity.kt
@@ -35,6 +35,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.Lifecycle
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy
@@ -229,3 +230,16 @@ fun PixelIMSApp() {
NavHost(navController, startDestination = "home", Modifier.padding(innerPadding), builder = navBuilder)
}
}
+
+@Preview
+@Composable
+fun PixelIMSAppPreview() {
+ EnableVoLTETheme {
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colorScheme.surfaceVariant,
+ ) {
+ PixelIMSApp()
+ }
+ }
+}
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt b/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt
index b07e846..48c7815 100644
--- a/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt
+++ b/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt
@@ -3,6 +3,7 @@ package dev.bluehouse.enablevolte
import android.content.Context
import android.content.res.Resources
import android.os.Build
+import android.os.Build.VERSION_CODES
import android.os.IInterface
import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
@@ -31,7 +32,7 @@ open class Moder {
} ?: run {
val i = interfaceLoader()
InterfaceCache.cache[T::class.java.name] = i
- return i as T
+ return i
}
}
@@ -178,7 +179,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.getString(key)
}
@@ -190,7 +191,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.getBoolean(key)
}
@@ -202,7 +203,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.getInt(key)
}
@@ -214,7 +215,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.getLong(key)
}
@@ -226,7 +227,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.getBooleanArray(key)
}
@@ -238,7 +239,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.getIntArray(key)
}
@@ -250,7 +251,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.getStringArray(key)
}
fun getValue(key: String): Any? {
@@ -261,7 +262,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
}
val iCclInstance = this.loadCachedInterface { carrierConfigLoader }
- val config = iCclInstance.getConfigForSubId(subscriptionId, iCclInstance.defaultCarrierServicePackageName)
+ val config = iCclInstance.getConfigForSubIdWithFeature(subscriptionId, iCclInstance.defaultCarrierServicePackageName, "")
return config.get(key)
}
@@ -272,6 +273,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
get() = this.getBooleanValue(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
val isVoNrConfigEnabled: Boolean
+ @RequiresApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
get() = this.getBooleanValue(CarrierConfigManager.KEY_VONR_ENABLED_BOOL) &&
this.getBooleanValue(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL)
@@ -292,15 +294,18 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
get() = this.getBooleanValue(CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL)
val showIMSinSIMInfo: Boolean
+ @RequiresApi(VERSION_CODES.R)
get() = this.getBooleanValue(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL)
val allowAddingAPNs: Boolean
get() = this.getBooleanValue(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL)
val showVoWifiMode: Boolean
+ @RequiresApi(VERSION_CODES.R)
get() = this.getBooleanValue(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL)
val showVoWifiRoamingMode: Boolean
+ @RequiresApi(VERSION_CODES.R)
get() = this.getBooleanValue(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL)
val showVoWifiInNetworkName: Int
@@ -310,6 +315,7 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
get() = this.getBooleanValue(CarrierConfigManager.KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL)
val alwaysDataRATIcon: Boolean
+ @RequiresApi(VERSION_CODES.R)
get() = this.getBooleanValue(CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL)
val supportWfcWifiOnly: Boolean
@@ -325,9 +331,11 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
get() = this.getBooleanValue(CarrierConfigManager.KEY_SUPPORT_SS_OVER_CDMA_BOOL)
val isShow4GForLteEnabled: Boolean
+ @RequiresApi(VERSION_CODES.R)
get() = this.getBooleanValue(CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL)
val isHideEnhancedDataIconEnabled: Boolean
+ @RequiresApi(VERSION_CODES.R)
get() = this.getBooleanValue(CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL)
val is4GPlusEnabled: Boolean
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt b/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt
index baed722..decec26 100644
--- a/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt
+++ b/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt
@@ -3,8 +3,8 @@ package dev.bluehouse.enablevolte.pages
import android.app.StatusBarManager
import android.content.ComponentName
import android.graphics.drawable.Icon
-import android.os.Build
import android.os.Build.VERSION
+import android.os.Build.VERSION_CODES
import android.telephony.CarrierConfigManager
import android.util.Log
import android.widget.Toast
@@ -87,23 +87,23 @@ fun Config(navController: NavController, subId: Int) {
}.flatten().associate { field -> field.name to field.get(field) as String }
reversedConfigurableItems = configurableItems.entries.associate { (k, v) -> v to k }
voLTEEnabled = moder.isVoLteConfigEnabled
- voNREnabled = moder.isVoNrConfigEnabled
+ voNREnabled = VERSION.SDK_INT >= VERSION_CODES.UPSIDE_DOWN_CAKE && moder.isVoNrConfigEnabled
crossSIMEnabled = moder.isCrossSIMConfigEnabled
voWiFiEnabled = moder.isVoWifiConfigEnabled
voWiFiEnabledWhileRoaming = moder.isVoWifiWhileRoamingEnabled
- showIMSinSIMInfo = moder.showIMSinSIMInfo
+ showIMSinSIMInfo = VERSION.SDK_INT >= VERSION_CODES.R && moder.showIMSinSIMInfo
allowAddingAPNs = moder.allowAddingAPNs
- showVoWifiMode = moder.showVoWifiMode
- showVoWifiRoamingMode = moder.showVoWifiRoamingMode
+ showVoWifiMode = VERSION.SDK_INT >= VERSION_CODES.R && moder.showVoWifiMode
+ showVoWifiRoamingMode = VERSION.SDK_INT >= VERSION_CODES.R && moder.showVoWifiRoamingMode
showVoWifiInNetworkName = (moder.showVoWifiInNetworkName == 1)
showVoWifiIcon = moder.showVoWifiIcon
- alwaysDataRATIcon = moder.alwaysDataRATIcon
+ alwaysDataRATIcon = VERSION.SDK_INT >= VERSION_CODES.R && moder.alwaysDataRATIcon
supportWfcWifiOnly = moder.supportWfcWifiOnly
vtEnabled = moder.isVtConfigEnabled
ssOverUtEnabled = moder.ssOverUtEnabled
ssOverCDMAEnabled = moder.ssOverCDMAEnabled
- show4GForLteEnabled = moder.isShow4GForLteEnabled
- hideEnhancedDataIconEnabled = moder.isHideEnhancedDataIconEnabled
+ show4GForLteEnabled = VERSION.SDK_INT >= VERSION_CODES.R && moder.isShow4GForLteEnabled
+ hideEnhancedDataIconEnabled = VERSION.SDK_INT >= VERSION_CODES.R && moder.isHideEnhancedDataIconEnabled
is4GPlusEnabled = moder.is4GPlusEnabled
configuredUserAgent = try {
moder.userAgentConfig
@@ -151,20 +151,23 @@ fun Config(navController: NavController, subId: Int) {
}
}
- BooleanPropertyView(label = stringResource(R.string.enable_vonr), toggled = voNREnabled) {
- voNREnabled = if (voNREnabled) {
- moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_ENABLED_BOOL, false)
- moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL, false)
- false
- } else {
- moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_ENABLED_BOOL, true)
- moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL, true)
- moder.restartIMSRegistration()
- true
+ BooleanPropertyView(label = stringResource(R.string.enable_vonr), toggled = voNREnabled, minSdk = VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ if (VERSION.SDK_INT >= VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ voNREnabled = if (voNREnabled) {
+ moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_ENABLED_BOOL, false)
+ moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL, false)
+ false
+ } else {
+ moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_ENABLED_BOOL, true)
+ moder.updateCarrierConfig(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL, true)
+ moder.restartIMSRegistration()
+ true
+ }
}
}
- BooleanPropertyView(label = stringResource(R.string.enable_crosssim), toggled = crossSIMEnabled, enabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+
+ BooleanPropertyView(label = stringResource(R.string.enable_crosssim), toggled = crossSIMEnabled, minSdk = VERSION_CODES.TIRAMISU) {
+ if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
crossSIMEnabled = if (crossSIMEnabled) {
moder.updateCarrierConfig(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false)
moder.updateCarrierConfig(CarrierConfigManager.KEY_ENABLE_CROSS_SIM_CALLING_ON_OPPORTUNISTIC_DATA_BOOL, false)
@@ -257,7 +260,7 @@ fun Config(navController: NavController, subId: Int) {
}
HeaderText(text = stringResource(R.string.cosmetic_toggles))
- BooleanPropertyView(label = stringResource(R.string.show_vowifi_preference_in_settings), toggled = showVoWifiMode) {
+ BooleanPropertyView(label = stringResource(R.string.show_vowifi_preference_in_settings), toggled = showVoWifiMode, minSdk = VERSION_CODES.R) {
showVoWifiMode = if (showVoWifiMode) {
moder.updateCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, false)
false
@@ -267,7 +270,7 @@ fun Config(navController: NavController, subId: Int) {
true
}
}
- BooleanPropertyView(label = stringResource(R.string.show_vowifi_roaming_preference_in_settings), toggled = showVoWifiRoamingMode) {
+ BooleanPropertyView(label = stringResource(R.string.show_vowifi_roaming_preference_in_settings), toggled = showVoWifiRoamingMode, minSdk = VERSION_CODES.R) {
showVoWifiRoamingMode = if (showVoWifiRoamingMode) {
moder.updateCarrierConfig(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false)
false
@@ -306,7 +309,7 @@ fun Config(navController: NavController, subId: Int) {
true
}
}
- BooleanPropertyView(label = stringResource(R.string.always_show_data_icon), toggled = alwaysDataRATIcon) {
+ BooleanPropertyView(label = stringResource(R.string.always_show_data_icon), toggled = alwaysDataRATIcon, minSdk = VERSION_CODES.R) {
alwaysDataRATIcon = if (alwaysDataRATIcon) {
moder.updateCarrierConfig(CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false)
false
@@ -315,7 +318,7 @@ fun Config(navController: NavController, subId: Int) {
true
}
}
- BooleanPropertyView(label = stringResource(R.string.show_4g_for_lte_data_icon), toggled = show4GForLteEnabled) {
+ BooleanPropertyView(label = stringResource(R.string.show_4g_for_lte_data_icon), toggled = show4GForLteEnabled, minSdk = VERSION_CODES.R) {
show4GForLteEnabled = if (show4GForLteEnabled) {
moder.updateCarrierConfig(CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, false)
false
@@ -324,7 +327,7 @@ fun Config(navController: NavController, subId: Int) {
true
}
}
- BooleanPropertyView(label = stringResource(R.string.hide_enhanced_data_icon), toggled = hideEnhancedDataIconEnabled) {
+ BooleanPropertyView(label = stringResource(R.string.hide_enhanced_data_icon), toggled = hideEnhancedDataIconEnabled, minSdk = VERSION_CODES.R) {
hideEnhancedDataIconEnabled = if (hideEnhancedDataIconEnabled) {
moder.updateCarrierConfig(CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, false)
false
@@ -333,7 +336,7 @@ fun Config(navController: NavController, subId: Int) {
true
}
}
- BooleanPropertyView(label = stringResource(R.string.show_ims_status_in_sim_status), toggled = showIMSinSIMInfo) {
+ BooleanPropertyView(label = stringResource(R.string.show_ims_status_in_sim_status), toggled = showIMSinSIMInfo, minSdk = VERSION_CODES.R) {
showIMSinSIMInfo = if (showIMSinSIMInfo) {
moder.updateCarrierConfig(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false)
false
@@ -343,7 +346,7 @@ fun Config(navController: NavController, subId: Int) {
}
}
- if (VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
HeaderText(text = stringResource(R.string.qstile))
ClickablePropertyView(
label = stringResource(R.string.add_status_tile),
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/pages/Editor.kt b/app/src/main/java/dev/bluehouse/enablevolte/pages/Editor.kt
index cde0c22..0c2edf5 100644
--- a/app/src/main/java/dev/bluehouse/enablevolte/pages/Editor.kt
+++ b/app/src/main/java/dev/bluehouse/enablevolte/pages/Editor.kt
@@ -1,12 +1,12 @@
package dev.bluehouse.enablevolte.pages
import android.telephony.CarrierConfigManager
+import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -24,10 +24,10 @@ import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.AlertDialogDefaults
+import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Divider
-import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -40,6 +40,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
@@ -193,7 +194,7 @@ fun SingleValueEditor(data: DataRow, onValueChange: (String) -> Unit) {
fun MultiValueEditor(_data: ListDataRow, onUpdate: (List) -> Unit) {
val scrollState = rememberScrollState()
var data by remember { mutableStateOf(_data) }
- var editIndex by remember { mutableStateOf(-1) }
+ var editIndex by remember { mutableIntStateOf(-1) }
val items by remember(data.value) { derivedStateOf { data.value } }
LaunchedEffect(items) {
scrollState.scrollTo(scrollState.maxValue)
@@ -282,17 +283,17 @@ fun fieldToDataRow(moder: SubscriptionModer, field: Field): BaseDataRow {
}
}
-@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Editor(subId: Int) {
var sections by remember { mutableStateOf(listOf()) }
var loading by rememberSaveable { mutableStateOf(true) }
var saving by rememberSaveable { mutableStateOf(false) }
var dataToEdit by remember { mutableStateOf(null) }
- var sectionIndexOfEditingData by remember { mutableStateOf(-1) }
- var rowIndexOfEditingData by remember { mutableStateOf(-1) }
- var rowsLoaded by remember { mutableStateOf(0) }
- var rowsToLoad by remember { mutableStateOf(1) }
+ var sectionIndexOfEditingData by remember { mutableIntStateOf(-1) }
+ var rowIndexOfEditingData by remember { mutableIntStateOf(-1) }
+ var rowsLoaded by remember { mutableIntStateOf(0) }
+ var rowsToLoad by remember { mutableIntStateOf(1) }
var searchKeyword by remember { mutableStateOf("") }
var showFieldNameInsteadOfKey by remember { mutableStateOf(false) }
val filteredSections = remember(sections, searchKeyword) {
@@ -450,15 +451,26 @@ fun Editor(subId: Int) {
else -> Box(modifier = Modifier.fillMaxWidth())
}
}
- Row(modifier = Modifier.padding(top = 16.dp)) {
- Spacer(Modifier.weight(1f))
- TextButton(onClick = {
- dataToEdit = null
- saving = true
- updateRow(data)
- saving = false
- }) { Text(stringResource(R.string.confirm)) }
- TextButton(onClick = { dataToEdit = null }) { Text(stringResource(R.string.dismiss)) }
+ Row(modifier = Modifier.align(Alignment.End).padding(top = 16.dp)) {
+ TextButton(
+ border = BorderStroke(0.5.dp, MaterialTheme.colorScheme.primary),
+ modifier = Modifier.padding(end = 8.dp),
+ shape = ButtonDefaults.outlinedShape,
+ onClick = { dataToEdit = null },
+ ) { Text(stringResource(R.string.dismiss)) }
+ TextButton(
+ border = BorderStroke(0.5.dp, MaterialTheme.colorScheme.primary),
+ shape = ButtonDefaults.outlinedShape,
+ colors = ButtonDefaults.filledTonalButtonColors(
+ containerColor = MaterialTheme.colorScheme.primary,
+ ),
+ onClick = {
+ dataToEdit = null
+ saving = true
+ updateRow(data)
+ saving = false
+ },
+ ) { Text(stringResource(R.string.confirm)) }
}
}
}
diff --git a/gradle.properties b/gradle.properties
index a2e90d8..f19c7b9 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -21,5 +21,4 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
-android.defaults.buildfeatures.buildconfig=true
android.nonFinalResIds=false
\ No newline at end of file