refactor: update EditDeviceProfileDialog using dynamic fields

This commit is contained in:
andrekir 2024-08-25 07:38:13 -03:00 committed by Andre K
parent 0b7718f8d5
commit 19e0f7d8b3
3 changed files with 144 additions and 71 deletions

View file

@ -326,7 +326,8 @@ class RadioConfigViewModel @Inject constructor(
if (hasLongName() || hasShortName()) destNode.value?.user?.let {
val user = it.copy(
longName = if (hasLongName()) longName else it.longName,
shortName = if (hasShortName()) shortName else it.shortName
shortName = if (hasShortName()) shortName else it.shortName,
hwModel = MeshProtos.HardwareModel.UNSET,
)
if (it != user) setOwner(user.toProto())
}
@ -337,28 +338,22 @@ class RadioConfigViewModel @Inject constructor(
setResponseStateError(ex.customMessage)
}
if (hasConfig()) {
setConfig(config { device = config.device })
setConfig(config { position = config.position })
setConfig(config { power = config.power })
setConfig(config { network = config.network })
setConfig(config { display = config.display })
setConfig(config { lora = config.lora })
setConfig(config { bluetooth = config.bluetooth })
val descriptor = config.descriptorForType
config.allFields.forEach { (field, value) ->
val newConfig = ConfigProtos.Config.newBuilder()
.setField(descriptor.findFieldByName(field.name), value)
.build()
setConfig(newConfig)
}
}
if (hasModuleConfig()) moduleConfig.let {
setModuleConfig(moduleConfig { mqtt = it.mqtt })
setModuleConfig(moduleConfig { serial = it.serial })
setModuleConfig(moduleConfig { externalNotification = it.externalNotification })
setModuleConfig(moduleConfig { storeForward = it.storeForward })
setModuleConfig(moduleConfig { rangeTest = it.rangeTest })
setModuleConfig(moduleConfig { telemetry = it.telemetry })
setModuleConfig(moduleConfig { cannedMessage = it.cannedMessage })
setModuleConfig(moduleConfig { audio = it.audio })
setModuleConfig(moduleConfig { remoteHardware = it.remoteHardware })
setModuleConfig(moduleConfig { neighborInfo = it.neighborInfo })
setModuleConfig(moduleConfig { ambientLighting = it.ambientLighting })
setModuleConfig(moduleConfig { detectionSensor = it.detectionSensor })
setModuleConfig(moduleConfig { paxcounter = it.paxcounter })
if (hasModuleConfig()) {
val descriptor = moduleConfig.descriptorForType
moduleConfig.allFields.forEach { (field, value) ->
val newConfig = ModuleConfigProtos.ModuleConfig.newBuilder()
.setField(descriptor.findFieldByName(field.name), value)
.build()
setModuleConfig(newConfig)
}
}
meshService?.commitEditSettings()
}

View file

@ -1,18 +1,19 @@
package com.geeksville.mesh.ui.components.config
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.AlertDialog
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@ -21,8 +22,9 @@ import com.geeksville.mesh.ClientOnlyProtos
import com.geeksville.mesh.R
import com.geeksville.mesh.deviceProfile
import com.geeksville.mesh.ui.components.SwitchPreference
import com.google.accompanist.themeadapter.appcompat.AppCompatTheme
import com.google.protobuf.Descriptors
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun EditDeviceProfileDialog(
title: String,
@ -31,72 +33,55 @@ fun EditDeviceProfileDialog(
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
) {
var longNameInput by remember(deviceProfile) { mutableStateOf(deviceProfile.hasLongName()) }
var shortNameInput by remember(deviceProfile) { mutableStateOf(deviceProfile.hasShortName()) }
var channelUrlInput by remember(deviceProfile) { mutableStateOf(deviceProfile.hasChannelUrl()) }
var configInput by remember(deviceProfile) { mutableStateOf(deviceProfile.hasConfig()) }
var moduleConfigInput by remember(deviceProfile) { mutableStateOf(deviceProfile.hasModuleConfig()) }
val state = remember {
val fields = deviceProfile.descriptorForType.fields
mutableStateMapOf<Descriptors.FieldDescriptor, Boolean>()
.apply { putAll(fields.associateWith(deviceProfile::hasField)) }
}
AlertDialog(
title = { Text(title) },
onDismissRequest = onDismissRequest,
text = {
AppCompatTheme {
Column(modifier.fillMaxWidth()) {
SwitchPreference(title = "longName",
checked = longNameInput,
enabled = deviceProfile.hasLongName(),
onCheckedChange = { longNameInput = it }
)
SwitchPreference(title = "shortName",
checked = shortNameInput,
enabled = deviceProfile.hasShortName(),
onCheckedChange = { shortNameInput = it }
)
SwitchPreference(title = "channelUrl",
checked = channelUrlInput,
enabled = deviceProfile.hasChannelUrl(),
onCheckedChange = { channelUrlInput = it }
)
SwitchPreference(title = "config",
checked = configInput,
enabled = deviceProfile.hasConfig(),
onCheckedChange = { configInput = it }
)
SwitchPreference(title = "moduleConfig",
checked = moduleConfigInput,
enabled = deviceProfile.hasModuleConfig(),
onCheckedChange = { moduleConfigInput = it }
Column(modifier.fillMaxWidth()) {
state.keys.sortedBy { it.number }.forEach { field ->
SwitchPreference(
title = field.name,
checked = state[field] == true,
enabled = deviceProfile.hasField(field),
onCheckedChange = { state[field] = it },
padding = PaddingValues(0.dp)
)
}
}
},
buttons = {
Row(
FlowRow(
modifier = modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Button(
TextButton(
modifier = modifier
.fillMaxWidth()
.padding(start = 24.dp)
.padding(horizontal = 24.dp)
.weight(1f),
onClick = onDismissRequest
) { Text(stringResource(R.string.cancel)) }
Button(
modifier = modifier
.fillMaxWidth()
.padding(end = 24.dp)
.padding(horizontal = 24.dp)
.weight(1f),
onClick = {
onAddClick(deviceProfile {
if (longNameInput) longName = deviceProfile.longName
if (shortNameInput) shortName = deviceProfile.shortName
if (channelUrlInput) channelUrl = deviceProfile.channelUrl
if (configInput) config = deviceProfile.config
if (moduleConfigInput) moduleConfig = deviceProfile.moduleConfig
})
val builder = ClientOnlyProtos.DeviceProfile.newBuilder()
deviceProfile.allFields.forEach { (field, value) ->
if (state[field] == true) {
builder.setField(field, value)
}
}
onAddClick(builder.build())
},
enabled = state.values.any { it },
) { Text(stringResource(R.string.save)) }
}
}