kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
refactor(config): extract components from `NavGraph` to screens
rodzic
74ae3fd594
commit
1aa0b138fc
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<DeviceProfile?>(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 = {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<ChannelSettings>,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Ładowanie…
Reference in New Issue