diff --git a/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt b/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt index cc366ee8..1547241e 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt @@ -54,43 +54,38 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController -import com.geeksville.mesh.Position import com.geeksville.mesh.R import com.geeksville.mesh.android.Logging -import com.geeksville.mesh.config import com.geeksville.mesh.database.entity.NodeEntity -import com.geeksville.mesh.model.Channel import com.geeksville.mesh.model.MetricsViewModel import com.geeksville.mesh.model.RadioConfigViewModel -import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.DeviceMetricsScreen import com.geeksville.mesh.ui.components.EnvironmentMetricsScreen import com.geeksville.mesh.ui.components.SignalMetricsScreen import com.geeksville.mesh.ui.components.TracerouteLogScreen -import com.geeksville.mesh.ui.components.config.AmbientLightingConfigItemList -import com.geeksville.mesh.ui.components.config.AudioConfigItemList -import com.geeksville.mesh.ui.components.config.BluetoothConfigItemList -import com.geeksville.mesh.ui.components.config.CannedMessageConfigItemList -import com.geeksville.mesh.ui.components.config.ChannelSettingsItemList -import com.geeksville.mesh.ui.components.config.DetectionSensorConfigItemList -import com.geeksville.mesh.ui.components.config.DeviceConfigItemList -import com.geeksville.mesh.ui.components.config.DisplayConfigItemList -import com.geeksville.mesh.ui.components.config.ExternalNotificationConfigItemList -import com.geeksville.mesh.ui.components.config.LoRaConfigItemList -import com.geeksville.mesh.ui.components.config.MQTTConfigItemList -import com.geeksville.mesh.ui.components.config.NeighborInfoConfigItemList -import com.geeksville.mesh.ui.components.config.NetworkConfigItemList -import com.geeksville.mesh.ui.components.config.PacketResponseStateDialog -import com.geeksville.mesh.ui.components.config.PaxcounterConfigItemList -import com.geeksville.mesh.ui.components.config.PositionConfigItemList -import com.geeksville.mesh.ui.components.config.PowerConfigItemList -import com.geeksville.mesh.ui.components.config.RangeTestConfigItemList -import com.geeksville.mesh.ui.components.config.RemoteHardwareConfigItemList -import com.geeksville.mesh.ui.components.config.SecurityConfigItemList -import com.geeksville.mesh.ui.components.config.SerialConfigItemList -import com.geeksville.mesh.ui.components.config.StoreForwardConfigItemList -import com.geeksville.mesh.ui.components.config.TelemetryConfigItemList -import com.geeksville.mesh.ui.components.config.UserConfigItemList +import com.geeksville.mesh.ui.components.config.AmbientLightingConfigScreen +import com.geeksville.mesh.ui.components.config.AudioConfigScreen +import com.geeksville.mesh.ui.components.config.BluetoothConfigScreen +import com.geeksville.mesh.ui.components.config.CannedMessageConfigScreen +import com.geeksville.mesh.ui.components.config.ChannelConfigScreen +import com.geeksville.mesh.ui.components.config.DetectionSensorConfigScreen +import com.geeksville.mesh.ui.components.config.DeviceConfigScreen +import com.geeksville.mesh.ui.components.config.DisplayConfigScreen +import com.geeksville.mesh.ui.components.config.ExternalNotificationConfigScreen +import com.geeksville.mesh.ui.components.config.LoRaConfigScreen +import com.geeksville.mesh.ui.components.config.MQTTConfigScreen +import com.geeksville.mesh.ui.components.config.NeighborInfoConfigScreen +import com.geeksville.mesh.ui.components.config.NetworkConfigScreen +import com.geeksville.mesh.ui.components.config.PaxcounterConfigScreen +import com.geeksville.mesh.ui.components.config.PositionConfigScreen +import com.geeksville.mesh.ui.components.config.PowerConfigScreen +import com.geeksville.mesh.ui.components.config.RangeTestConfigScreen +import com.geeksville.mesh.ui.components.config.RemoteHardwareConfigScreen +import com.geeksville.mesh.ui.components.config.SecurityConfigScreen +import com.geeksville.mesh.ui.components.config.SerialConfigScreen +import com.geeksville.mesh.ui.components.config.StoreForwardConfigScreen +import com.geeksville.mesh.ui.components.config.TelemetryConfigScreen +import com.geeksville.mesh.ui.components.config.UserConfigScreen import com.google.accompanist.themeadapter.appcompat.AppCompatTheme import dagger.hilt.android.AndroidEntryPoint @@ -232,7 +227,7 @@ private fun MeshAppBar( ) } -@Suppress("LongMethod", "CyclomaticComplexMethod") +@Suppress("LongMethod") @Composable fun NavGraph( node: NodeEntity?, @@ -241,22 +236,6 @@ fun NavGraph( startDestination: String, modifier: Modifier = Modifier, ) { - val state by viewModel.radioConfigState.collectAsStateWithLifecycle() - if (state.responseState.isWaiting()) { - PacketResponseStateDialog( - state = state.responseState, - onDismiss = viewModel::clearPacketResponse, - onComplete = { - val route = state.route - if (ConfigRoute.entries.any { it.name == route } || - ModuleRoute.entries.any { it.name == route }) { - navController.navigate(route = route) - viewModel.clearPacketResponse() - } - }, - ) - } - NavHost( navController = navController, startDestination = startDestination, @@ -287,268 +266,76 @@ fun NavGraph( RadioConfigScreen( node = node, viewModel = viewModel, - ) + ) { navController.navigate(route = it) } } composable(ConfigRoute.USER.name) { - UserConfigItemList( - userConfig = state.userConfig, - enabled = state.connected, - onSaveClicked = { userInput -> - viewModel.setOwner(userInput) - } - ) + UserConfigScreen(viewModel) } composable(ConfigRoute.CHANNELS.name) { - ChannelSettingsItemList( - settingsList = state.channelList, - modemPresetName = Channel(loraConfig = state.radioConfig.lora).name, - enabled = state.connected, - maxChannels = viewModel.maxChannels, - onPositiveClicked = { channelListInput -> - viewModel.updateChannels(channelListInput, state.channelList) - }, - ) + ChannelConfigScreen(viewModel) } composable(ConfigRoute.DEVICE.name) { - DeviceConfigItemList( - deviceConfig = state.radioConfig.device, - enabled = state.connected, - onSaveClicked = { deviceInput -> - val config = config { device = deviceInput } - viewModel.setConfig(config) - } - ) + DeviceConfigScreen(viewModel) } composable(ConfigRoute.POSITION.name) { - val currentPosition = Position( - latitude = node?.latitude ?: 0.0, - longitude = node?.longitude ?: 0.0, - altitude = node?.position?.altitude ?: 0, - time = 1, // ignore time for fixed_position - ) - PositionConfigItemList( - location = currentPosition, - positionConfig = state.radioConfig.position, - enabled = state.connected, - onSaveClicked = { locationInput, positionInput -> - if (positionInput.fixedPosition) { - if (locationInput != currentPosition) { - viewModel.setFixedPosition(locationInput) - } - } else { - if (state.radioConfig.position.fixedPosition) { - // fixed position changed from enabled to disabled - viewModel.removeFixedPosition() - } - } - val config = config { position = positionInput } - viewModel.setConfig(config) - } - ) + PositionConfigScreen(viewModel) } composable(ConfigRoute.POWER.name) { - PowerConfigItemList( - powerConfig = state.radioConfig.power, - enabled = state.connected, - onSaveClicked = { powerInput -> - val config = config { power = powerInput } - viewModel.setConfig(config) - } - ) + PowerConfigScreen(viewModel) } composable(ConfigRoute.NETWORK.name) { - NetworkConfigItemList( - networkConfig = state.radioConfig.network, - enabled = state.connected, - onSaveClicked = { networkInput -> - val config = config { network = networkInput } - viewModel.setConfig(config) - } - ) + NetworkConfigScreen(viewModel) } composable(ConfigRoute.DISPLAY.name) { - DisplayConfigItemList( - displayConfig = state.radioConfig.display, - enabled = state.connected, - onSaveClicked = { displayInput -> - val config = config { display = displayInput } - viewModel.setConfig(config) - } - ) + DisplayConfigScreen(viewModel) } composable(ConfigRoute.LORA.name) { - LoRaConfigItemList( - loraConfig = state.radioConfig.lora, - primarySettings = state.channelList.getOrNull(0) ?: return@composable, - enabled = state.connected, - onSaveClicked = { loraInput -> - val config = config { lora = loraInput } - viewModel.setConfig(config) - }, - hasPaFan = viewModel.hasPaFan, - ) + LoRaConfigScreen(viewModel) } composable(ConfigRoute.BLUETOOTH.name) { - BluetoothConfigItemList( - bluetoothConfig = state.radioConfig.bluetooth, - enabled = state.connected, - onSaveClicked = { bluetoothInput -> - val config = config { bluetooth = bluetoothInput } - viewModel.setConfig(config) - } - ) + BluetoothConfigScreen(viewModel) } composable(ConfigRoute.SECURITY.name) { - SecurityConfigItemList( - securityConfig = state.radioConfig.security, - enabled = state.connected, - onConfirm = { securityInput -> - val config = config { security = securityInput } - viewModel.setConfig(config) - } - ) + SecurityConfigScreen(viewModel) } composable(ModuleRoute.MQTT.name) { - MQTTConfigItemList( - mqttConfig = state.moduleConfig.mqtt, - enabled = state.connected, - onSaveClicked = { mqttInput -> - val config = moduleConfig { mqtt = mqttInput } - viewModel.setModuleConfig(config) - } - ) + MQTTConfigScreen(viewModel) } composable(ModuleRoute.SERIAL.name) { - SerialConfigItemList( - serialConfig = state.moduleConfig.serial, - enabled = state.connected, - onSaveClicked = { serialInput -> - val config = moduleConfig { serial = serialInput } - viewModel.setModuleConfig(config) - } - ) + SerialConfigScreen(viewModel) } composable(ModuleRoute.EXTERNAL_NOTIFICATION.name) { - ExternalNotificationConfigItemList( - ringtone = state.ringtone, - extNotificationConfig = state.moduleConfig.externalNotification, - enabled = state.connected, - onSaveClicked = { ringtoneInput, extNotificationInput -> - if (ringtoneInput != state.ringtone) { - viewModel.setRingtone(ringtoneInput) - } - if (extNotificationInput != state.moduleConfig.externalNotification) { - val config = moduleConfig { externalNotification = extNotificationInput } - viewModel.setModuleConfig(config) - } - } - ) + ExternalNotificationConfigScreen(viewModel) } composable(ModuleRoute.STORE_FORWARD.name) { - StoreForwardConfigItemList( - storeForwardConfig = state.moduleConfig.storeForward, - enabled = state.connected, - onSaveClicked = { storeForwardInput -> - val config = moduleConfig { storeForward = storeForwardInput } - viewModel.setModuleConfig(config) - } - ) + StoreForwardConfigScreen(viewModel) } composable(ModuleRoute.RANGE_TEST.name) { - RangeTestConfigItemList( - rangeTestConfig = state.moduleConfig.rangeTest, - enabled = state.connected, - onSaveClicked = { rangeTestInput -> - val config = moduleConfig { rangeTest = rangeTestInput } - viewModel.setModuleConfig(config) - } - ) + RangeTestConfigScreen(viewModel) } composable(ModuleRoute.TELEMETRY.name) { - TelemetryConfigItemList( - telemetryConfig = state.moduleConfig.telemetry, - enabled = state.connected, - onSaveClicked = { telemetryInput -> - val config = moduleConfig { telemetry = telemetryInput } - viewModel.setModuleConfig(config) - } - ) + TelemetryConfigScreen(viewModel) } composable(ModuleRoute.CANNED_MESSAGE.name) { - CannedMessageConfigItemList( - messages = state.cannedMessageMessages, - cannedMessageConfig = state.moduleConfig.cannedMessage, - enabled = state.connected, - onSaveClicked = { messagesInput, cannedMessageInput -> - if (messagesInput != state.cannedMessageMessages) { - viewModel.setCannedMessages(messagesInput) - } - if (cannedMessageInput != state.moduleConfig.cannedMessage) { - val config = moduleConfig { cannedMessage = cannedMessageInput } - viewModel.setModuleConfig(config) - } - } - ) + CannedMessageConfigScreen(viewModel) } composable(ModuleRoute.AUDIO.name) { - AudioConfigItemList( - audioConfig = state.moduleConfig.audio, - enabled = state.connected, - onSaveClicked = { audioInput -> - val config = moduleConfig { audio = audioInput } - viewModel.setModuleConfig(config) - } - ) + AudioConfigScreen(viewModel) } composable(ModuleRoute.REMOTE_HARDWARE.name) { - RemoteHardwareConfigItemList( - remoteHardwareConfig = state.moduleConfig.remoteHardware, - enabled = state.connected, - onSaveClicked = { remoteHardwareInput -> - val config = moduleConfig { remoteHardware = remoteHardwareInput } - viewModel.setModuleConfig(config) - } - ) + RemoteHardwareConfigScreen(viewModel) } composable(ModuleRoute.NEIGHBOR_INFO.name) { - NeighborInfoConfigItemList( - neighborInfoConfig = state.moduleConfig.neighborInfo, - enabled = state.connected, - onSaveClicked = { neighborInfoInput -> - val config = moduleConfig { neighborInfo = neighborInfoInput } - viewModel.setModuleConfig(config) - } - ) + NeighborInfoConfigScreen(viewModel) } composable(ModuleRoute.AMBIENT_LIGHTING.name) { - AmbientLightingConfigItemList( - ambientLightingConfig = state.moduleConfig.ambientLighting, - enabled = state.connected, - onSaveClicked = { ambientLightingInput -> - val config = moduleConfig { ambientLighting = ambientLightingInput } - viewModel.setModuleConfig(config) - } - ) + AmbientLightingConfigScreen(viewModel) } composable(ModuleRoute.DETECTION_SENSOR.name) { - DetectionSensorConfigItemList( - detectionSensorConfig = state.moduleConfig.detectionSensor, - enabled = state.connected, - onSaveClicked = { detectionSensorInput -> - val config = moduleConfig { detectionSensor = detectionSensorInput } - viewModel.setModuleConfig(config) - } - ) + DetectionSensorConfigScreen(viewModel) } composable(ModuleRoute.PAXCOUNTER.name) { - PaxcounterConfigItemList( - paxcounterConfig = state.moduleConfig.paxcounter, - enabled = state.connected, - onSaveClicked = { paxcounterConfigInput -> - val config = moduleConfig { paxcounter = paxcounterConfigInput } - viewModel.setModuleConfig(config) - } - ) + PaxcounterConfigScreen(viewModel) } } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/RadioConfigScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/RadioConfigScreen.kt index c1b02b67..442bbd01 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/RadioConfigScreen.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/RadioConfigScreen.kt @@ -44,6 +44,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile import com.geeksville.mesh.R @@ -51,17 +52,38 @@ import com.geeksville.mesh.database.entity.NodeEntity import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.config.EditDeviceProfileDialog +import com.geeksville.mesh.ui.components.config.PacketResponseStateDialog -@Suppress("LongMethod") +@Suppress("LongMethod", "CyclomaticComplexMethod") @Composable fun RadioConfigScreen( node: NodeEntity?, - viewModel: RadioConfigViewModel, + viewModel: RadioConfigViewModel = hiltViewModel(), modifier: Modifier = Modifier, + onNavigate: (String) -> Unit = {} ) { val isLocal = node?.num == viewModel.myNodeNum val state by viewModel.radioConfigState.collectAsStateWithLifecycle() - val isWaiting = state.responseState.isWaiting() + var isWaiting by remember { mutableStateOf(false) } + + if (isWaiting) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = { + isWaiting = false + viewModel.clearPacketResponse() + }, + onComplete = { + val route = state.route + if (ConfigRoute.entries.any { it.name == route } || + ModuleRoute.entries.any { it.name == route }) { + isWaiting = false + viewModel.clearPacketResponse() + onNavigate(route) + } + }, + ) + } var deviceProfile by remember { mutableStateOf(null) } var showEditDeviceProfileDialog by remember { mutableStateOf(false) } @@ -115,6 +137,7 @@ fun RadioConfigScreen( isLocal = isLocal, modifier = modifier, onRouteClick = { route -> + isWaiting = true viewModel.setResponseStateLoading(route) }, onImport = { diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt index 7242608a..a787cf90 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun AmbientLightingConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + AmbientLightingConfigItemList( + ambientLightingConfig = state.moduleConfig.ambientLighting, + enabled = state.connected, + onSaveClicked = { ambientLightingInput -> + val config = moduleConfig { ambientLighting = ambientLightingInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun AmbientLightingConfigItemList( ambientLightingConfig: ModuleConfigProtos.ModuleConfig.AmbientLightingConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/AudioConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/AudioConfigItemList.kt index e9ebefa4..cd3667bb 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/AudioConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/AudioConfigItemList.kt @@ -12,14 +12,41 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.AudioConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun AudioConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + AudioConfigItemList( + audioConfig = state.moduleConfig.audio, + enabled = state.connected, + onSaveClicked = { audioInput -> + val config = moduleConfig { audio = audioInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun AudioConfigItemList( audioConfig: AudioConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/BluetoothConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/BluetoothConfigItemList.kt index c4a51155..9c38cefc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/BluetoothConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/BluetoothConfigItemList.kt @@ -12,14 +12,41 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos.Config.BluetoothConfig +import com.geeksville.mesh.config import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun BluetoothConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + BluetoothConfigItemList( + bluetoothConfig = state.radioConfig.bluetooth, + enabled = state.connected, + onSaveClicked = { bluetoothInput -> + val config = config { bluetooth = bluetoothInput } + viewModel.setConfig(config) + } + ) +} + @Composable fun BluetoothConfigItemList( bluetoothConfig: BluetoothConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/CannedMessageConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/CannedMessageConfigItemList.kt index 651e6fbc..f962c5e9 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/CannedMessageConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/CannedMessageConfigItemList.kt @@ -15,14 +15,47 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.CannedMessageConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun CannedMessageConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + CannedMessageConfigItemList( + messages = state.cannedMessageMessages, + cannedMessageConfig = state.moduleConfig.cannedMessage, + enabled = state.connected, + onSaveClicked = { messagesInput, cannedMessageInput -> + if (messagesInput != state.cannedMessageMessages) { + viewModel.setCannedMessages(messagesInput) + } + if (cannedMessageInput != state.moduleConfig.cannedMessage) { + val config = moduleConfig { cannedMessage = cannedMessageInput } + viewModel.setModuleConfig(config) + } + } + ) +} + @Composable fun CannedMessageConfigItemList( messages: String, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/ChannelSettingsItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/ChannelSettingsItemList.kt index 0ee0f8bb..c130d855 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/ChannelSettingsItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/ChannelSettingsItemList.kt @@ -47,10 +47,13 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ChannelProtos.ChannelSettings import com.geeksville.mesh.R import com.geeksville.mesh.channelSettings import com.geeksville.mesh.model.Channel +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.dragContainer @@ -147,6 +150,30 @@ fun ChannelSelection( ) } +@Composable +fun ChannelConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + ChannelSettingsItemList( + settingsList = state.channelList, + modemPresetName = Channel(loraConfig = state.radioConfig.lora).name, + enabled = state.connected, + maxChannels = viewModel.maxChannels, + onPositiveClicked = { channelListInput -> + viewModel.updateChannels(channelListInput, state.channelList) + }, + ) +} + @Composable fun ChannelSettingsItemList( settingsList: List, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt index 7826faaa..4cb887a1 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt @@ -15,14 +15,41 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun DetectionSensorConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + DetectionSensorConfigItemList( + detectionSensorConfig = state.moduleConfig.detectionSensor, + enabled = state.connected, + onSaveClicked = { detectionSensorInput -> + val config = moduleConfig { detectionSensor = detectionSensorInput } + viewModel.setModuleConfig(config) + } + ) +} + @Suppress("LongMethod") @Composable fun DetectionSensorConfigItemList( diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/DeviceConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/DeviceConfigItemList.kt index 9222bb4b..c25d725d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/DeviceConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/DeviceConfigItemList.kt @@ -16,9 +16,13 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos.Config.DeviceConfig import com.geeksville.mesh.R +import com.geeksville.mesh.config import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory @@ -41,6 +45,29 @@ private val DeviceConfig.Role.stringRes: Int else -> R.string.unrecognized } +@Composable +fun DeviceConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + DeviceConfigItemList( + deviceConfig = state.radioConfig.device, + enabled = state.connected, + onSaveClicked = { deviceInput -> + val config = config { device = deviceInput } + viewModel.setConfig(config) + } + ) +} + @Composable fun DeviceConfigItemList( deviceConfig: DeviceConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/DisplayConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/DisplayConfigItemList.kt index e21d2580..4d53018d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/DisplayConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/DisplayConfigItemList.kt @@ -12,14 +12,41 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig +import com.geeksville.mesh.config import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun DisplayConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + DisplayConfigItemList( + displayConfig = state.radioConfig.display, + enabled = state.connected, + onSaveClicked = { displayInput -> + val config = config { display = displayInput } + viewModel.setConfig(config) + } + ) +} + @Composable fun DisplayConfigItemList( displayConfig: DisplayConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/ExternalNotificationConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/ExternalNotificationConfigItemList.kt index 7f9adb93..fdddcc86 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/ExternalNotificationConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/ExternalNotificationConfigItemList.kt @@ -15,14 +15,47 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.ExternalNotificationConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference import com.geeksville.mesh.ui.components.TextDividerPreference +@Composable +fun ExternalNotificationConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + ExternalNotificationConfigItemList( + ringtone = state.ringtone, + extNotificationConfig = state.moduleConfig.externalNotification, + enabled = state.connected, + onSaveClicked = { ringtoneInput, extNotificationInput -> + if (ringtoneInput != state.ringtone) { + viewModel.setRingtone(ringtoneInput) + } + if (extNotificationInput != state.moduleConfig.externalNotification) { + val config = moduleConfig { externalNotification = extNotificationInput } + viewModel.setModuleConfig(config) + } + } + ) +} + @Composable fun ExternalNotificationConfigItemList( ringtone: String, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/LoRaConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/LoRaConfigItemList.kt index a870e39f..3b64c025 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/LoRaConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/LoRaConfigItemList.kt @@ -13,10 +13,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ChannelProtos.ChannelSettings import com.geeksville.mesh.ConfigProtos.Config.LoRaConfig +import com.geeksville.mesh.config import com.geeksville.mesh.copy import com.geeksville.mesh.model.Channel +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.model.RegionInfo import com.geeksville.mesh.model.numChannels import com.geeksville.mesh.ui.components.DropDownPreference @@ -26,6 +30,31 @@ import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun LoRaConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + LoRaConfigItemList( + loraConfig = state.radioConfig.lora, + primarySettings = state.channelList.getOrNull(0) ?: return, + enabled = state.connected, + onSaveClicked = { loraInput -> + val config = config { lora = loraInput } + viewModel.setConfig(config) + }, + hasPaFan = viewModel.hasPaFan, + ) +} + @Suppress("LongMethod") @Composable fun LoRaConfigItemList( diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/MQTTConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/MQTTConfigItemList.kt index 6289518d..d20903f9 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/MQTTConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/MQTTConfigItemList.kt @@ -17,8 +17,12 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.MQTTConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditPasswordPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PositionPrecisionPreference @@ -26,6 +30,29 @@ import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun MQTTConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + MQTTConfigItemList( + mqttConfig = state.moduleConfig.mqtt, + enabled = state.connected, + onSaveClicked = { mqttInput -> + val config = moduleConfig { mqtt = mqttInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun MQTTConfigItemList( mqttConfig: MQTTConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/NeighborInfoConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/NeighborInfoConfigItemList.kt index 7a8ef4f9..102672e0 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/NeighborInfoConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/NeighborInfoConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun NeighborInfoConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + NeighborInfoConfigItemList( + neighborInfoConfig = state.moduleConfig.neighborInfo, + enabled = state.connected, + onSaveClicked = { neighborInfoInput -> + val config = moduleConfig { neighborInfo = neighborInfoInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun NeighborInfoConfigItemList( neighborInfoConfig: ModuleConfigProtos.ModuleConfig.NeighborInfoConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt index 78d0a6c1..5e965b83 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt @@ -23,9 +23,13 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos.Config.NetworkConfig import com.geeksville.mesh.R +import com.geeksville.mesh.config import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditIPv4Preference import com.geeksville.mesh.ui.components.EditPasswordPreference @@ -46,6 +50,29 @@ private fun ScanErrorDialog( onDismiss = onDismiss, ) +@Composable +fun NetworkConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + NetworkConfigItemList( + networkConfig = state.radioConfig.network, + enabled = state.connected, + onSaveClicked = { networkInput -> + val config = config { network = networkInput } + viewModel.setConfig(config) + } + ) +} + @Composable fun NetworkConfigItemList( networkConfig: NetworkConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/PaxcounterConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/PaxcounterConfigItemList.kt index a74db4cd..bb4a158f 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/PaxcounterConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/PaxcounterConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun PaxcounterConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + PaxcounterConfigItemList( + paxcounterConfig = state.moduleConfig.paxcounter, + enabled = state.connected, + onSaveClicked = { paxcounterConfigInput -> + val config = moduleConfig { paxcounter = paxcounterConfigInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun PaxcounterConfigItemList( paxcounterConfig: ModuleConfigProtos.ModuleConfig.PaxcounterConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/PositionConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/PositionConfigItemList.kt index b3dd2868..846fbab8 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/PositionConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/PositionConfigItemList.kt @@ -12,10 +12,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos import com.geeksville.mesh.ConfigProtos.Config.PositionConfig import com.geeksville.mesh.Position +import com.geeksville.mesh.config import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.BitwisePreference import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference @@ -23,6 +27,48 @@ import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun PositionConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + val node by viewModel.destNode.collectAsStateWithLifecycle() + val currentPosition = Position( + latitude = node?.latitude ?: 0.0, + longitude = node?.longitude ?: 0.0, + altitude = node?.position?.altitude ?: 0, + time = 1, // ignore time for fixed_position + ) + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + PositionConfigItemList( + location = currentPosition, + positionConfig = state.radioConfig.position, + enabled = state.connected, + onSaveClicked = { locationInput, positionInput -> + if (positionInput.fixedPosition) { + if (locationInput != currentPosition) { + viewModel.setFixedPosition(locationInput) + } + } else { + if (state.radioConfig.position.fixedPosition) { + // fixed position changed from enabled to disabled + viewModel.removeFixedPosition() + } + } + val config = config { position = positionInput } + viewModel.setConfig(config) + } + ) +} + @Suppress("LongMethod", "CyclomaticComplexMethod") @Composable fun PositionConfigItemList( diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/PowerConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/PowerConfigItemList.kt index cd7b915d..d289833d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/PowerConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/PowerConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos.Config.PowerConfig +import com.geeksville.mesh.config import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun PowerConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + PowerConfigItemList( + powerConfig = state.radioConfig.power, + enabled = state.connected, + onSaveClicked = { powerInput -> + val config = config { power = powerInput } + viewModel.setConfig(config) + } + ) +} + @Composable fun PowerConfigItemList( powerConfig: PowerConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/RangeTestConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/RangeTestConfigItemList.kt index 2ab9c39e..2d76f49f 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/RangeTestConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/RangeTestConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.RangeTestConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun RangeTestConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + RangeTestConfigItemList( + rangeTestConfig = state.moduleConfig.rangeTest, + enabled = state.connected, + onSaveClicked = { rangeTestInput -> + val config = moduleConfig { rangeTest = rangeTestInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun RangeTestConfigItemList( rangeTestConfig: RangeTestConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/RemoteHardwareConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/RemoteHardwareConfigItemList.kt index b7f93ecc..5ba1a71d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/RemoteHardwareConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/RemoteHardwareConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.RemoteHardwareConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditListPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun RemoteHardwareConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + RemoteHardwareConfigItemList( + remoteHardwareConfig = state.moduleConfig.remoteHardware, + enabled = state.connected, + onSaveClicked = { remoteHardwareInput -> + val config = moduleConfig { remoteHardware = remoteHardwareInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun RemoteHardwareConfigItemList( remoteHardwareConfig: RemoteHardwareConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt index ef5beac5..72530328 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt @@ -12,14 +12,41 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos.Config.SecurityConfig +import com.geeksville.mesh.config import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.ui.components.EditBase64Preference import com.geeksville.mesh.ui.components.EditListPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun SecurityConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + SecurityConfigItemList( + securityConfig = state.radioConfig.security, + enabled = state.connected, + onConfirm = { securityInput -> + val config = config { security = securityInput } + viewModel.setConfig(config) + } + ) +} + @Suppress("LongMethod") @Composable fun SecurityConfigItemList( diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/SerialConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/SerialConfigItemList.kt index 38ebe139..a999c681 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/SerialConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/SerialConfigItemList.kt @@ -12,14 +12,41 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.SerialConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.DropDownPreference import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun SerialConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + SerialConfigItemList( + serialConfig = state.moduleConfig.serial, + enabled = state.connected, + onSaveClicked = { serialInput -> + val config = moduleConfig { serial = serialInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun SerialConfigItemList( serialConfig: SerialConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/StoreForwardConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/StoreForwardConfigItemList.kt index 8028cda4..141281b3 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/StoreForwardConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/StoreForwardConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.StoreForwardConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun StoreForwardConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + StoreForwardConfigItemList( + storeForwardConfig = state.moduleConfig.storeForward, + enabled = state.connected, + onSaveClicked = { storeForwardInput -> + val config = moduleConfig { storeForward = storeForwardInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun StoreForwardConfigItemList( storeForwardConfig: StoreForwardConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/TelemetryConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/TelemetryConfigItemList.kt index 48e46303..e4734b7e 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/TelemetryConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/TelemetryConfigItemList.kt @@ -12,13 +12,40 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.TelemetryConfig import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel +import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceFooter import com.geeksville.mesh.ui.components.SwitchPreference +@Composable +fun TelemetryConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + TelemetryConfigItemList( + telemetryConfig = state.moduleConfig.telemetry, + enabled = state.connected, + onSaveClicked = { telemetryInput -> + val config = moduleConfig { telemetry = telemetryInput } + viewModel.setModuleConfig(config) + } + ) +} + @Composable fun TelemetryConfigItemList( telemetryConfig: TelemetryConfig, diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/UserConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/UserConfigItemList.kt index 3b7077b5..8e23bd51 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/UserConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/UserConfigItemList.kt @@ -15,8 +15,11 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.copy +import com.geeksville.mesh.model.RadioConfigViewModel import com.geeksville.mesh.model.getInitials import com.geeksville.mesh.ui.components.EditTextPreference import com.geeksville.mesh.ui.components.PreferenceCategory @@ -25,6 +28,26 @@ import com.geeksville.mesh.ui.components.RegularPreference import com.geeksville.mesh.ui.components.SwitchPreference import com.geeksville.mesh.user +@Composable +fun UserConfigScreen( + viewModel: RadioConfigViewModel = hiltViewModel(), +) { + val state by viewModel.radioConfigState.collectAsStateWithLifecycle() + + if (state.responseState.isWaiting()) { + PacketResponseStateDialog( + state = state.responseState, + onDismiss = viewModel::clearPacketResponse, + ) + } + + UserConfigItemList( + userConfig = state.userConfig, + enabled = true, + onSaveClicked = viewModel::setOwner, + ) +} + @Composable fun UserConfigItemList( userConfig: MeshProtos.User,