mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-03-28 02:32:24 -04:00
Decouple settings screens from NavHostController (#3450)
This commit is contained in:
@@ -53,8 +53,8 @@ private fun NavGraphBuilder.configRoutes(navController: NavHostController) {
|
||||
composable(configRoute.route::class) { backStackEntry ->
|
||||
val parentEntry = remember(backStackEntry) { navController.getBackStackEntry(ChannelsRoutes.ChannelsGraph) }
|
||||
when (configRoute) {
|
||||
ConfigRoute.CHANNELS -> ChannelConfigScreen(navController, hiltViewModel(parentEntry))
|
||||
ConfigRoute.LORA -> LoRaConfigScreen(navController, hiltViewModel(parentEntry))
|
||||
ConfigRoute.CHANNELS -> ChannelConfigScreen(hiltViewModel(parentEntry), navController::popBackStack)
|
||||
ConfigRoute.LORA -> LoRaConfigScreen(hiltViewModel(parentEntry), navController::popBackStack)
|
||||
else -> Unit // Should not happen if ConfigRoute enum is exhaustive for this context
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,6 @@ private fun NavGraphBuilder.configRoutes(navController: NavHostController) {
|
||||
composable<SettingsRoutes.LoRa> { backStackEntry ->
|
||||
val parentEntry =
|
||||
remember(backStackEntry) { navController.getBackStackEntry(ConnectionsRoutes.ConnectionsGraph) }
|
||||
LoRaConfigScreen(navController = navController, viewModel = hiltViewModel<RadioConfigViewModel>(parentEntry))
|
||||
LoRaConfigScreen(viewModel = hiltViewModel<RadioConfigViewModel>(parentEntry), navController::popBackStack)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,26 +9,27 @@
|
||||
<ID>ComposableParamOrder:MapReportingPreference.kt$MapReportingPreference</ID>
|
||||
<ID>ComposableParamOrder:NodeActionButton.kt$NodeActionButton</ID>
|
||||
<ID>ComposableParamOrder:WarningDialog.kt$WarningDialog</ID>
|
||||
<ID>CyclomaticComplexMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>CyclomaticComplexMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>CyclomaticComplexMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>CyclomaticComplexMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>CyclomaticComplexMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)</ID>
|
||||
<ID>CyclomaticComplexMethod:SettingsNavigation.kt$@Suppress("LongMethod") fun NavGraphBuilder.settingsGraph(navController: NavHostController)</ID>
|
||||
<ID>LambdaParameterEventTrailing:NodeActionButton.kt$onClick</ID>
|
||||
<ID>LongMethod:AudioConfigItemList.kt$@Composable fun AudioConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:CannedMessageConfigItemList.kt$@Composable fun CannedMessageConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:DetectionSensorConfigItemList.kt$@Composable fun DetectionSensorConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:DeviceConfigItemList.kt$@Composable fun DeviceConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:DisplayConfigItemList.kt$@Composable fun DisplayConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:ExternalNotificationConfigItemList.kt$@Composable fun ExternalNotificationConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:LoRaConfigItemList.kt$@Composable fun LoRaConfigScreen(navController: NavController, viewModel: RadioConfigViewModel)</ID>
|
||||
<ID>LongMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:PowerConfigItemList.kt$@Composable fun PowerConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:AudioConfigItemList.kt$@Composable fun AudioConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:CannedMessageConfigItemList.kt$@Composable fun CannedMessageConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:DetectionSensorConfigItemList.kt$@Composable fun DetectionSensorConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:DeviceConfigItemList.kt$@Composable fun DeviceConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:DisplayConfigItemList.kt$@Composable fun DisplayConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:ExternalNotificationConfigItemList.kt$@Composable fun ExternalNotificationConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:LoRaConfigItemList.kt$@Composable fun LoRaConfigScreen(viewModel: RadioConfigViewModel, onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:PowerConfigItemList.kt$@Composable fun PowerConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)</ID>
|
||||
<ID>LongMethod:SecurityConfigItemList.kt$@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun SecurityConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:SerialConfigItemList.kt$@Composable fun SerialConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:StoreForwardConfigItemList.kt$@Composable fun StoreForwardConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:TelemetryConfigItemList.kt$@Composable fun TelemetryConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:UserConfigItemList.kt$@Composable fun UserConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel())</ID>
|
||||
<ID>LongMethod:SecurityConfigItemList.kt$@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun SecurityConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:SerialConfigItemList.kt$@Composable fun SerialConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:StoreForwardConfigItemList.kt$@Composable fun StoreForwardConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:TelemetryConfigItemList.kt$@Composable fun TelemetryConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>LongMethod:UserConfigItemList.kt$@Composable fun UserConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit)</ID>
|
||||
<ID>MagicNumber:Debug.kt$3</ID>
|
||||
<ID>MagicNumber:EditChannelDialog.kt$16</ID>
|
||||
<ID>MagicNumber:EditChannelDialog.kt$32</ID>
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.meshtastic.feature.settings.navigation
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.List
|
||||
import androidx.compose.material.icons.filled.Bluetooth
|
||||
import androidx.compose.material.icons.filled.CellTower
|
||||
import androidx.compose.material.icons.filled.DisplaySettings
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.Power
|
||||
import androidx.compose.material.icons.filled.Router
|
||||
import androidx.compose.material.icons.filled.Security
|
||||
import androidx.compose.material.icons.filled.Wifi
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.proto.MeshProtos.DeviceMetadata
|
||||
|
||||
enum class ConfigRoute(@StringRes val title: Int, val route: Route, val icon: ImageVector?, val type: Int = 0) {
|
||||
USER(R.string.user, SettingsRoutes.User, Icons.Default.Person, 0),
|
||||
CHANNELS(R.string.channels, SettingsRoutes.ChannelConfig, Icons.AutoMirrored.Default.List, 0),
|
||||
DEVICE(
|
||||
R.string.device,
|
||||
SettingsRoutes.Device,
|
||||
Icons.Default.Router,
|
||||
AdminProtos.AdminMessage.ConfigType.DEVICE_CONFIG_VALUE,
|
||||
),
|
||||
POSITION(
|
||||
R.string.position,
|
||||
SettingsRoutes.Position,
|
||||
Icons.Default.LocationOn,
|
||||
AdminProtos.AdminMessage.ConfigType.POSITION_CONFIG_VALUE,
|
||||
),
|
||||
POWER(
|
||||
R.string.power,
|
||||
SettingsRoutes.Power,
|
||||
Icons.Default.Power,
|
||||
AdminProtos.AdminMessage.ConfigType.POWER_CONFIG_VALUE,
|
||||
),
|
||||
NETWORK(
|
||||
R.string.network,
|
||||
SettingsRoutes.Network,
|
||||
Icons.Default.Wifi,
|
||||
AdminProtos.AdminMessage.ConfigType.NETWORK_CONFIG_VALUE,
|
||||
),
|
||||
DISPLAY(
|
||||
R.string.display,
|
||||
SettingsRoutes.Display,
|
||||
Icons.Default.DisplaySettings,
|
||||
AdminProtos.AdminMessage.ConfigType.DISPLAY_CONFIG_VALUE,
|
||||
),
|
||||
LORA(
|
||||
R.string.lora,
|
||||
SettingsRoutes.LoRa,
|
||||
Icons.Default.CellTower,
|
||||
AdminProtos.AdminMessage.ConfigType.LORA_CONFIG_VALUE,
|
||||
),
|
||||
BLUETOOTH(
|
||||
R.string.bluetooth,
|
||||
SettingsRoutes.Bluetooth,
|
||||
Icons.Default.Bluetooth,
|
||||
AdminProtos.AdminMessage.ConfigType.BLUETOOTH_CONFIG_VALUE,
|
||||
),
|
||||
SECURITY(
|
||||
R.string.security,
|
||||
SettingsRoutes.Security,
|
||||
Icons.Default.Security,
|
||||
AdminProtos.AdminMessage.ConfigType.SECURITY_CONFIG_VALUE,
|
||||
),
|
||||
;
|
||||
|
||||
companion object {
|
||||
private fun filterExcludedFrom(metadata: DeviceMetadata?): List<ConfigRoute> = entries.filter {
|
||||
when {
|
||||
metadata == null -> true // Include all routes if metadata is null
|
||||
it == BLUETOOTH -> metadata.hasBluetooth
|
||||
it == NETWORK -> metadata.hasWifi || metadata.hasEthernet
|
||||
else -> true // Include all other routes by default
|
||||
}
|
||||
}
|
||||
|
||||
val radioConfigRoutes = listOf(LORA, CHANNELS, SECURITY)
|
||||
|
||||
fun deviceConfigRoutes(metadata: DeviceMetadata?): List<ConfigRoute> =
|
||||
filterExcludedFrom(metadata) - radioConfigRoutes
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.meshtastic.feature.settings.navigation
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Forward
|
||||
import androidx.compose.material.icons.automirrored.filled.Message
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||
import androidx.compose.material.icons.filled.Cloud
|
||||
import androidx.compose.material.icons.filled.DataUsage
|
||||
import androidx.compose.material.icons.filled.LightMode
|
||||
import androidx.compose.material.icons.filled.Notifications
|
||||
import androidx.compose.material.icons.filled.People
|
||||
import androidx.compose.material.icons.filled.PermScanWifi
|
||||
import androidx.compose.material.icons.filled.Sensors
|
||||
import androidx.compose.material.icons.filled.SettingsRemote
|
||||
import androidx.compose.material.icons.filled.Speed
|
||||
import androidx.compose.material.icons.filled.Usb
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.proto.MeshProtos.DeviceMetadata
|
||||
|
||||
enum class ModuleRoute(@StringRes val title: Int, val route: Route, val icon: ImageVector?, val type: Int = 0) {
|
||||
MQTT(
|
||||
R.string.mqtt,
|
||||
SettingsRoutes.MQTT,
|
||||
Icons.Default.Cloud,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.MQTT_CONFIG_VALUE,
|
||||
),
|
||||
SERIAL(
|
||||
R.string.serial,
|
||||
SettingsRoutes.Serial,
|
||||
Icons.Default.Usb,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.SERIAL_CONFIG_VALUE,
|
||||
),
|
||||
EXT_NOTIFICATION(
|
||||
R.string.external_notification,
|
||||
SettingsRoutes.ExtNotification,
|
||||
Icons.Default.Notifications,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.EXTNOTIF_CONFIG_VALUE,
|
||||
),
|
||||
STORE_FORWARD(
|
||||
R.string.store_forward,
|
||||
SettingsRoutes.StoreForward,
|
||||
Icons.AutoMirrored.Default.Forward,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.STOREFORWARD_CONFIG_VALUE,
|
||||
),
|
||||
RANGE_TEST(
|
||||
R.string.range_test,
|
||||
SettingsRoutes.RangeTest,
|
||||
Icons.Default.Speed,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.RANGETEST_CONFIG_VALUE,
|
||||
),
|
||||
TELEMETRY(
|
||||
R.string.telemetry,
|
||||
SettingsRoutes.Telemetry,
|
||||
Icons.Default.DataUsage,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.TELEMETRY_CONFIG_VALUE,
|
||||
),
|
||||
CANNED_MESSAGE(
|
||||
R.string.canned_message,
|
||||
SettingsRoutes.CannedMessage,
|
||||
Icons.AutoMirrored.Default.Message,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.CANNEDMSG_CONFIG_VALUE,
|
||||
),
|
||||
AUDIO(
|
||||
R.string.audio,
|
||||
SettingsRoutes.Audio,
|
||||
Icons.AutoMirrored.Default.VolumeUp,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.AUDIO_CONFIG_VALUE,
|
||||
),
|
||||
REMOTE_HARDWARE(
|
||||
R.string.remote_hardware,
|
||||
SettingsRoutes.RemoteHardware,
|
||||
Icons.Default.SettingsRemote,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.REMOTEHARDWARE_CONFIG_VALUE,
|
||||
),
|
||||
NEIGHBOR_INFO(
|
||||
R.string.neighbor_info,
|
||||
SettingsRoutes.NeighborInfo,
|
||||
Icons.Default.People,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.NEIGHBORINFO_CONFIG_VALUE,
|
||||
),
|
||||
AMBIENT_LIGHTING(
|
||||
R.string.ambient_lighting,
|
||||
SettingsRoutes.AmbientLighting,
|
||||
Icons.Default.LightMode,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.AMBIENTLIGHTING_CONFIG_VALUE,
|
||||
),
|
||||
DETECTION_SENSOR(
|
||||
R.string.detection_sensor,
|
||||
SettingsRoutes.DetectionSensor,
|
||||
Icons.Default.Sensors,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.DETECTIONSENSOR_CONFIG_VALUE,
|
||||
),
|
||||
PAXCOUNTER(
|
||||
R.string.paxcounter,
|
||||
SettingsRoutes.Paxcounter,
|
||||
Icons.Default.PermScanWifi,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.PAXCOUNTER_CONFIG_VALUE,
|
||||
),
|
||||
;
|
||||
|
||||
val bitfield: Int
|
||||
get() = 1 shl ordinal
|
||||
|
||||
companion object {
|
||||
fun filterExcludedFrom(metadata: DeviceMetadata?): List<ModuleRoute> = entries.filter {
|
||||
when (metadata) {
|
||||
null -> true // Include all routes if metadata is null
|
||||
else -> metadata.excludedModules and it.bitfield == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,39 +17,8 @@
|
||||
|
||||
package org.meshtastic.feature.settings.navigation
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Forward
|
||||
import androidx.compose.material.icons.automirrored.filled.List
|
||||
import androidx.compose.material.icons.automirrored.filled.Message
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||
import androidx.compose.material.icons.filled.Bluetooth
|
||||
import androidx.compose.material.icons.filled.CellTower
|
||||
import androidx.compose.material.icons.filled.Cloud
|
||||
import androidx.compose.material.icons.filled.DataUsage
|
||||
import androidx.compose.material.icons.filled.DisplaySettings
|
||||
import androidx.compose.material.icons.filled.LightMode
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
import androidx.compose.material.icons.filled.Notifications
|
||||
import androidx.compose.material.icons.filled.People
|
||||
import androidx.compose.material.icons.filled.PermScanWifi
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.Power
|
||||
import androidx.compose.material.icons.filled.Router
|
||||
import androidx.compose.material.icons.filled.Security
|
||||
import androidx.compose.material.icons.filled.Sensors
|
||||
import androidx.compose.material.icons.filled.SettingsRemote
|
||||
import androidx.compose.material.icons.filled.Speed
|
||||
import androidx.compose.material.icons.filled.Usb
|
||||
import androidx.compose.material.icons.filled.Wifi
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.NavDestination.Companion.hasRoute
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.composable
|
||||
@@ -59,7 +28,6 @@ import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
|
||||
import org.meshtastic.core.navigation.NodesRoutes
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.settings.SettingsScreen
|
||||
import org.meshtastic.feature.settings.debugging.DebugScreen
|
||||
import org.meshtastic.feature.settings.radio.CleanNodeDatabaseScreen
|
||||
@@ -87,8 +55,6 @@ import org.meshtastic.feature.settings.radio.component.SerialConfigScreen
|
||||
import org.meshtastic.feature.settings.radio.component.StoreForwardConfigScreen
|
||||
import org.meshtastic.feature.settings.radio.component.TelemetryConfigScreen
|
||||
import org.meshtastic.feature.settings.radio.component.UserConfigScreen
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.proto.MeshProtos.DeviceMetadata
|
||||
|
||||
fun getNavRouteFrom(routeName: String): Route? =
|
||||
ConfigRoute.entries.find { it.name == routeName }?.route ?: ModuleRoute.entries.find { it.name == routeName }?.route
|
||||
@@ -113,6 +79,7 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) {
|
||||
navController.navigate(it) { popUpTo(SettingsRoutes.Settings()) { inclusive = false } }
|
||||
}
|
||||
}
|
||||
|
||||
composable<SettingsRoutes.CleanNodeDb>(
|
||||
deepLinks =
|
||||
listOf(
|
||||
@@ -123,8 +90,80 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) {
|
||||
) {
|
||||
CleanNodeDatabaseScreen()
|
||||
}
|
||||
configRoutesScreens(navController)
|
||||
moduleRoutesScreens(navController)
|
||||
|
||||
ConfigRoute.entries.forEach { entry ->
|
||||
composable(entry.route::class) { backStackEntry ->
|
||||
val parentEntry =
|
||||
remember(backStackEntry) { navController.getBackStackEntry(SettingsRoutes.SettingsGraph::class) }
|
||||
val viewModel = hiltViewModel<RadioConfigViewModel>(parentEntry)
|
||||
|
||||
when (entry) {
|
||||
ConfigRoute.USER -> UserConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.CHANNELS -> ChannelConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.DEVICE -> DeviceConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.POSITION -> PositionConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.POWER -> PowerConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.NETWORK -> NetworkConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.DISPLAY -> DisplayConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.LORA -> LoRaConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.BLUETOOTH -> BluetoothConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ConfigRoute.SECURITY -> SecurityConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleRoute.entries.forEach { entry ->
|
||||
composable(entry.route::class) { backStackEntry ->
|
||||
val parentEntry =
|
||||
remember(backStackEntry) { navController.getBackStackEntry<SettingsRoutes.SettingsGraph>() }
|
||||
val viewModel = hiltViewModel<RadioConfigViewModel>(parentEntry)
|
||||
|
||||
when (entry) {
|
||||
ModuleRoute.MQTT -> MQTTConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.SERIAL -> SerialConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.EXT_NOTIFICATION ->
|
||||
ExternalNotificationConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.STORE_FORWARD ->
|
||||
StoreForwardConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.RANGE_TEST -> RangeTestConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.TELEMETRY -> TelemetryConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.CANNED_MESSAGE ->
|
||||
CannedMessageConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.AUDIO -> AudioConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.REMOTE_HARDWARE ->
|
||||
RemoteHardwareConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.NEIGHBOR_INFO ->
|
||||
NeighborInfoConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.AMBIENT_LIGHTING ->
|
||||
AmbientLightingConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.DETECTION_SENSOR ->
|
||||
DetectionSensorConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
|
||||
ModuleRoute.PAXCOUNTER -> PaxcounterConfigScreen(viewModel, onBack = navController::popBackStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
composable<SettingsRoutes.DebugPanel>(
|
||||
deepLinks =
|
||||
listOf(navDeepLink<SettingsRoutes.DebugPanel>(basePath = "$DEEP_LINK_BASE_URI/settings/debug_panel")),
|
||||
@@ -133,397 +172,3 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun NavDestination.isConfigRoute(): Boolean =
|
||||
ConfigRoute.entries.any { hasRoute(it.route::class) } || ModuleRoute.entries.any { hasRoute(it.route::class) }
|
||||
|
||||
/**
|
||||
* Helper to define a composable route for a radio configuration screen within the radio config graph.
|
||||
*
|
||||
* This function simplifies adding screens by handling common tasks like:
|
||||
* - Setting up deep links based on the route's name.
|
||||
* - Retrieving the parent [NavBackStackEntry] for the [SettingsRoutes.SettingsGraph].
|
||||
* - Providing the [RadioConfigViewModel] scoped to the parent graph, which the [screenContent] will use.
|
||||
*
|
||||
* @param R The type of the [Route] object, must be serializable.
|
||||
* @param navController The [NavHostController] for navigation.
|
||||
* @param routeNameString The string name of the route (from the enum entry's name) used for deep link paths.
|
||||
* @param screenContent A lambda that defines the composable content for the screen. It receives the parent-scoped
|
||||
* [RadioConfigViewModel].
|
||||
*/
|
||||
private inline fun <reified R : Route> NavGraphBuilder.addRadioConfigScreenComposable(
|
||||
navController: NavHostController,
|
||||
routeNameString: String,
|
||||
crossinline screenContent: @Composable (navController: NavController, viewModel: RadioConfigViewModel) -> Unit,
|
||||
) {
|
||||
composable<R>(
|
||||
deepLinks =
|
||||
listOf(
|
||||
navDeepLink<R>(
|
||||
basePath = "$DEEP_LINK_BASE_URI/settings/radio/{destNum}/${routeNameString.lowercase()}",
|
||||
),
|
||||
navDeepLink<R>(basePath = "$DEEP_LINK_BASE_URI/settings/radio/${routeNameString.lowercase()}"),
|
||||
),
|
||||
) { backStackEntry ->
|
||||
val parentEntry =
|
||||
remember(backStackEntry) { navController.getBackStackEntry(SettingsRoutes.SettingsGraph::class) }
|
||||
val viewModel = hiltViewModel<RadioConfigViewModel>(parentEntry)
|
||||
screenContent(navController, viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun NavGraphBuilder.configRoutesScreens(navController: NavHostController) {
|
||||
ConfigRoute.entries.forEach { entry ->
|
||||
when (entry.route) {
|
||||
is SettingsRoutes.User ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.User>(navController, entry.name, entry.screenComposable)
|
||||
|
||||
is SettingsRoutes.ChannelConfig ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.ChannelConfig>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.Device ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Device>(navController, entry.name, entry.screenComposable)
|
||||
|
||||
is SettingsRoutes.Position ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Position>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.Power ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Power>(navController, entry.name, entry.screenComposable)
|
||||
|
||||
is SettingsRoutes.Network ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Network>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.Display ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Display>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.LoRa ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.LoRa>(navController, entry.name, entry.screenComposable)
|
||||
|
||||
is SettingsRoutes.Bluetooth ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Bluetooth>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.Security ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Security>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
else -> Unit // Should not happen if ConfigRoute enum is exhaustive for this context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
private fun NavGraphBuilder.moduleRoutesScreens(navController: NavHostController) {
|
||||
ModuleRoute.entries.forEach { entry ->
|
||||
when (entry.route) {
|
||||
is SettingsRoutes.MQTT ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.MQTT>(navController, entry.name, entry.screenComposable)
|
||||
|
||||
is SettingsRoutes.Serial ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Serial>(navController, entry.name, entry.screenComposable)
|
||||
|
||||
is SettingsRoutes.ExtNotification ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.ExtNotification>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.StoreForward ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.StoreForward>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.RangeTest ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.RangeTest>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.Telemetry ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Telemetry>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.CannedMessage ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.CannedMessage>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.Audio ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Audio>(navController, entry.name, entry.screenComposable)
|
||||
|
||||
is SettingsRoutes.RemoteHardware ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.RemoteHardware>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.NeighborInfo ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.NeighborInfo>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.AmbientLighting ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.AmbientLighting>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.DetectionSensor ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.DetectionSensor>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
is SettingsRoutes.Paxcounter ->
|
||||
addRadioConfigScreenComposable<SettingsRoutes.Paxcounter>(
|
||||
navController,
|
||||
entry.name,
|
||||
entry.screenComposable,
|
||||
)
|
||||
|
||||
else -> Unit // Should not happen if ModuleRoute enum is exhaustive for this context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
enum class ConfigRoute(
|
||||
@StringRes val title: Int,
|
||||
val route: Route,
|
||||
val icon: ImageVector?,
|
||||
val type: Int = 0,
|
||||
val screenComposable: @Composable (navController: NavController, viewModel: RadioConfigViewModel) -> Unit,
|
||||
) {
|
||||
USER(R.string.user, SettingsRoutes.User, Icons.Default.Person, 0, { nc, vm -> UserConfigScreen(nc, vm) }),
|
||||
CHANNELS(
|
||||
R.string.channels,
|
||||
SettingsRoutes.ChannelConfig,
|
||||
Icons.AutoMirrored.Default.List,
|
||||
0,
|
||||
{ nc, vm -> ChannelConfigScreen(nc, vm) },
|
||||
),
|
||||
DEVICE(
|
||||
R.string.device,
|
||||
SettingsRoutes.Device,
|
||||
Icons.Default.Router,
|
||||
AdminProtos.AdminMessage.ConfigType.DEVICE_CONFIG_VALUE,
|
||||
{ nc, vm -> DeviceConfigScreen(nc, vm) },
|
||||
),
|
||||
POSITION(
|
||||
R.string.position,
|
||||
SettingsRoutes.Position,
|
||||
Icons.Default.LocationOn,
|
||||
AdminProtos.AdminMessage.ConfigType.POSITION_CONFIG_VALUE,
|
||||
{ nc, vm -> PositionConfigScreen(nc, vm) },
|
||||
),
|
||||
POWER(
|
||||
R.string.power,
|
||||
SettingsRoutes.Power,
|
||||
Icons.Default.Power,
|
||||
AdminProtos.AdminMessage.ConfigType.POWER_CONFIG_VALUE,
|
||||
{ nc, vm -> PowerConfigScreen(nc, vm) },
|
||||
),
|
||||
NETWORK(
|
||||
R.string.network,
|
||||
SettingsRoutes.Network,
|
||||
Icons.Default.Wifi,
|
||||
AdminProtos.AdminMessage.ConfigType.NETWORK_CONFIG_VALUE,
|
||||
{ nc, vm -> NetworkConfigScreen(nc, vm) },
|
||||
),
|
||||
DISPLAY(
|
||||
R.string.display,
|
||||
SettingsRoutes.Display,
|
||||
Icons.Default.DisplaySettings,
|
||||
AdminProtos.AdminMessage.ConfigType.DISPLAY_CONFIG_VALUE,
|
||||
{ nc, vm -> DisplayConfigScreen(nc, vm) },
|
||||
),
|
||||
LORA(
|
||||
R.string.lora,
|
||||
SettingsRoutes.LoRa,
|
||||
Icons.Default.CellTower,
|
||||
AdminProtos.AdminMessage.ConfigType.LORA_CONFIG_VALUE,
|
||||
{ nc, vm -> LoRaConfigScreen(nc, vm) },
|
||||
),
|
||||
BLUETOOTH(
|
||||
R.string.bluetooth,
|
||||
SettingsRoutes.Bluetooth,
|
||||
Icons.Default.Bluetooth,
|
||||
AdminProtos.AdminMessage.ConfigType.BLUETOOTH_CONFIG_VALUE,
|
||||
{ nc, vm -> BluetoothConfigScreen(nc, vm) },
|
||||
),
|
||||
SECURITY(
|
||||
R.string.security,
|
||||
SettingsRoutes.Security,
|
||||
Icons.Default.Security,
|
||||
AdminProtos.AdminMessage.ConfigType.SECURITY_CONFIG_VALUE,
|
||||
{ nc, vm -> SecurityConfigScreen(nc, vm) },
|
||||
),
|
||||
;
|
||||
|
||||
companion object {
|
||||
private fun filterExcludedFrom(metadata: DeviceMetadata?): List<ConfigRoute> = entries.filter {
|
||||
when {
|
||||
metadata == null -> true // Include all routes if metadata is null
|
||||
it == BLUETOOTH -> metadata.hasBluetooth
|
||||
it == NETWORK -> metadata.hasWifi || metadata.hasEthernet
|
||||
else -> true // Include all other routes by default
|
||||
}
|
||||
}
|
||||
|
||||
val radioConfigRoutes = listOf(LORA, CHANNELS, SECURITY)
|
||||
|
||||
fun deviceConfigRoutes(metadata: DeviceMetadata?): List<ConfigRoute> =
|
||||
filterExcludedFrom(metadata) - radioConfigRoutes
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
enum class ModuleRoute(
|
||||
@StringRes val title: Int,
|
||||
val route: Route,
|
||||
val icon: ImageVector?,
|
||||
val type: Int = 0,
|
||||
val screenComposable: @Composable (navController: NavController, viewModel: RadioConfigViewModel) -> Unit,
|
||||
) {
|
||||
MQTT(
|
||||
R.string.mqtt,
|
||||
SettingsRoutes.MQTT,
|
||||
Icons.Default.Cloud,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.MQTT_CONFIG_VALUE,
|
||||
{ nc, vm -> MQTTConfigScreen(nc, vm) },
|
||||
),
|
||||
SERIAL(
|
||||
R.string.serial,
|
||||
SettingsRoutes.Serial,
|
||||
Icons.Default.Usb,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.SERIAL_CONFIG_VALUE,
|
||||
{ nc, vm -> SerialConfigScreen(nc, vm) },
|
||||
),
|
||||
EXT_NOTIFICATION(
|
||||
R.string.external_notification,
|
||||
SettingsRoutes.ExtNotification,
|
||||
Icons.Default.Notifications,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.EXTNOTIF_CONFIG_VALUE,
|
||||
{ nc, vm -> ExternalNotificationConfigScreen(nc, vm) },
|
||||
),
|
||||
STORE_FORWARD(
|
||||
R.string.store_forward,
|
||||
SettingsRoutes.StoreForward,
|
||||
Icons.AutoMirrored.Default.Forward,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.STOREFORWARD_CONFIG_VALUE,
|
||||
{ nc, vm -> StoreForwardConfigScreen(nc, vm) },
|
||||
),
|
||||
RANGE_TEST(
|
||||
R.string.range_test,
|
||||
SettingsRoutes.RangeTest,
|
||||
Icons.Default.Speed,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.RANGETEST_CONFIG_VALUE,
|
||||
{ nc, vm -> RangeTestConfigScreen(nc, vm) },
|
||||
),
|
||||
TELEMETRY(
|
||||
R.string.telemetry,
|
||||
SettingsRoutes.Telemetry,
|
||||
Icons.Default.DataUsage,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.TELEMETRY_CONFIG_VALUE,
|
||||
{ nc, vm -> TelemetryConfigScreen(nc, vm) },
|
||||
),
|
||||
CANNED_MESSAGE(
|
||||
R.string.canned_message,
|
||||
SettingsRoutes.CannedMessage,
|
||||
Icons.AutoMirrored.Default.Message,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.CANNEDMSG_CONFIG_VALUE,
|
||||
{ nc, vm -> CannedMessageConfigScreen(nc, vm) },
|
||||
),
|
||||
AUDIO(
|
||||
R.string.audio,
|
||||
SettingsRoutes.Audio,
|
||||
Icons.AutoMirrored.Default.VolumeUp,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.AUDIO_CONFIG_VALUE,
|
||||
{ nc, vm -> AudioConfigScreen(nc, vm) },
|
||||
),
|
||||
REMOTE_HARDWARE(
|
||||
R.string.remote_hardware,
|
||||
SettingsRoutes.RemoteHardware,
|
||||
Icons.Default.SettingsRemote,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.REMOTEHARDWARE_CONFIG_VALUE,
|
||||
{ nc, vm -> RemoteHardwareConfigScreen(nc, vm) },
|
||||
),
|
||||
NEIGHBOR_INFO(
|
||||
R.string.neighbor_info,
|
||||
SettingsRoutes.NeighborInfo,
|
||||
Icons.Default.People,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.NEIGHBORINFO_CONFIG_VALUE,
|
||||
{ nc, vm -> NeighborInfoConfigScreen(nc, vm) },
|
||||
),
|
||||
AMBIENT_LIGHTING(
|
||||
R.string.ambient_lighting,
|
||||
SettingsRoutes.AmbientLighting,
|
||||
Icons.Default.LightMode,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.AMBIENTLIGHTING_CONFIG_VALUE,
|
||||
{ nc, vm -> AmbientLightingConfigScreen(nc, vm) },
|
||||
),
|
||||
DETECTION_SENSOR(
|
||||
R.string.detection_sensor,
|
||||
SettingsRoutes.DetectionSensor,
|
||||
Icons.Default.Sensors,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.DETECTIONSENSOR_CONFIG_VALUE,
|
||||
{ nc, vm -> DetectionSensorConfigScreen(nc, vm) },
|
||||
),
|
||||
PAXCOUNTER(
|
||||
R.string.paxcounter,
|
||||
SettingsRoutes.Paxcounter,
|
||||
Icons.Default.PermScanWifi,
|
||||
AdminProtos.AdminMessage.ModuleConfigType.PAXCOUNTER_CONFIG_VALUE,
|
||||
{ nc, vm -> PaxcounterConfigScreen(nc, vm) },
|
||||
),
|
||||
;
|
||||
|
||||
val bitfield: Int
|
||||
get() = 1 shl ordinal
|
||||
|
||||
companion object {
|
||||
fun filterExcludedFrom(metadata: DeviceMetadata?): List<ModuleRoute> = entries.filter {
|
||||
when (metadata) {
|
||||
null -> true // Include all routes if metadata is null
|
||||
else -> metadata.excludedModules and it.bitfield == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
import org.meshtastic.core.ui.component.SwitchPreference
|
||||
@@ -36,7 +35,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun AmbientLightingConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun AmbientLightingConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val ambientLightingConfig = state.moduleConfig.ambientLighting
|
||||
val formState = rememberConfigState(initialValue = ambientLightingConfig)
|
||||
@@ -44,7 +43,7 @@ fun AmbientLightingConfigScreen(navController: NavController, viewModel: RadioCo
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.ambient_lighting),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -38,7 +37,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun AudioConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun AudioConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val audioConfig = state.moduleConfig.audio
|
||||
val formState = rememberConfigState(initialValue = audioConfig)
|
||||
@@ -46,7 +45,7 @@ fun AudioConfigScreen(navController: NavController, viewModel: RadioConfigViewMo
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.audio),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -38,7 +37,7 @@ import org.meshtastic.proto.config
|
||||
import org.meshtastic.proto.copy
|
||||
|
||||
@Composable
|
||||
fun BluetoothConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun BluetoothConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val bluetoothConfig = state.radioConfig.bluetooth
|
||||
val formState = rememberConfigState(initialValue = bluetoothConfig)
|
||||
@@ -46,7 +45,7 @@ fun BluetoothConfigScreen(navController: NavController, viewModel: RadioConfigVi
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.bluetooth),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -32,7 +32,6 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -44,7 +43,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun CannedMessageConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun CannedMessageConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val cannedMessageConfig = state.moduleConfig.cannedMessage
|
||||
val messages = state.cannedMessageMessages
|
||||
@@ -54,7 +53,7 @@ fun CannedMessageConfigScreen(navController: NavController, viewModel: RadioConf
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.canned_message),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -60,7 +60,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.strings.R
|
||||
@@ -120,7 +119,7 @@ private fun ChannelCard(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChannelConfigScreen(navController: NavController, viewModel: RadioConfigViewModel) {
|
||||
fun ChannelConfigScreen(viewModel: RadioConfigViewModel, onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
|
||||
if (state.responseState.isWaiting()) {
|
||||
@@ -129,7 +128,7 @@ fun ChannelConfigScreen(navController: NavController, viewModel: RadioConfigView
|
||||
|
||||
ChannelSettingsItemList(
|
||||
title = stringResource(id = R.string.channels),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
settingsList = state.channelList,
|
||||
loraConfig = state.radioConfig.lora,
|
||||
maxChannels = viewModel.maxChannels,
|
||||
|
||||
@@ -30,7 +30,6 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -45,7 +44,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun DetectionSensorConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun DetectionSensorConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val detectionSensorConfig = state.moduleConfig.detectionSensor
|
||||
val formState = rememberConfigState(initialValue = detectionSensorConfig)
|
||||
@@ -53,7 +52,7 @@ fun DetectionSensorConfigScreen(navController: NavController, viewModel: RadioCo
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.detection_sensor),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -48,7 +48,6 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -92,7 +91,7 @@ private val DeviceConfig.RebroadcastMode.description: Int
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DeviceConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun DeviceConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val deviceConfig = state.radioConfig.device
|
||||
val formState = rememberConfigState(initialValue = deviceConfig)
|
||||
@@ -111,7 +110,7 @@ fun DeviceConfigScreen(navController: NavController, viewModel: RadioConfigViewM
|
||||
val focusManager = LocalFocusManager.current
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.device),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -25,7 +25,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.SwitchPreference
|
||||
@@ -38,14 +37,14 @@ import org.meshtastic.proto.config
|
||||
import org.meshtastic.proto.copy
|
||||
|
||||
@Composable
|
||||
fun DisplayConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun DisplayConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val displayConfig = state.radioConfig.display
|
||||
val formState = rememberConfigState(initialValue = displayConfig)
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.display),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -33,7 +33,6 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -47,7 +46,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun ExternalNotificationConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun ExternalNotificationConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val extNotificationConfig = state.moduleConfig.externalNotification
|
||||
val ringtone = state.ringtone
|
||||
@@ -57,7 +56,7 @@ fun ExternalNotificationConfigScreen(navController: NavController, viewModel: Ra
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.external_notification),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -28,7 +28,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.model.ChannelOption
|
||||
import org.meshtastic.core.model.RegionInfo
|
||||
@@ -45,7 +44,7 @@ import org.meshtastic.proto.config
|
||||
import org.meshtastic.proto.copy
|
||||
|
||||
@Composable
|
||||
fun LoRaConfigScreen(navController: NavController, viewModel: RadioConfigViewModel) {
|
||||
fun LoRaConfigScreen(viewModel: RadioConfigViewModel, onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val loraConfig = state.radioConfig.lora
|
||||
val primarySettings = state.channelList.getOrNull(0) ?: return
|
||||
@@ -56,7 +55,7 @@ fun LoRaConfigScreen(navController: NavController, viewModel: RadioConfigViewMod
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.lora),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -31,7 +31,6 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.EditPasswordPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -42,7 +41,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun MQTTConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun MQTTConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val destNode by viewModel.destNode.collectAsStateWithLifecycle()
|
||||
val destNum = destNode?.num
|
||||
@@ -68,7 +67,7 @@ fun MQTTConfigScreen(navController: NavController, viewModel: RadioConfigViewMod
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.mqtt),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected && consentValid,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
import org.meshtastic.core.ui.component.SwitchPreference
|
||||
@@ -36,7 +35,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun NeighborInfoConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun NeighborInfoConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val neighborInfoConfig = state.moduleConfig.neighborInfo
|
||||
val formState = rememberConfigState(initialValue = neighborInfoConfig)
|
||||
@@ -44,7 +43,7 @@ fun NeighborInfoConfigScreen(navController: NavController, viewModel: RadioConfi
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.neighbor_info),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -40,7 +40,6 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import com.journeyapps.barcodescanner.ScanContract
|
||||
import com.journeyapps.barcodescanner.ScanOptions
|
||||
import org.meshtastic.core.strings.R
|
||||
@@ -61,7 +60,7 @@ private fun ScanErrorDialog(onDismiss: () -> Unit = {}) =
|
||||
SimpleAlertDialog(title = R.string.error, text = R.string.wifi_qr_code_error, onDismiss = onDismiss)
|
||||
|
||||
@Composable
|
||||
fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun NetworkConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val networkConfig = state.radioConfig.network
|
||||
val formState = rememberConfigState(initialValue = networkConfig)
|
||||
@@ -101,7 +100,7 @@ fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigView
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.network),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -27,7 +27,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.SignedIntegerEditTextPreference
|
||||
@@ -40,7 +39,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun PaxcounterConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun PaxcounterConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val paxcounterConfig = state.moduleConfig.paxcounter
|
||||
val formState = rememberConfigState(initialValue = paxcounterConfig)
|
||||
@@ -48,7 +47,7 @@ fun PaxcounterConfigScreen(navController: NavController, viewModel: RadioConfigV
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.paxcounter),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -39,7 +39,6 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.location.LocationCompat
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -61,7 +60,7 @@ import org.meshtastic.proto.copy
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var phoneLocation: Location? by remember { mutableStateOf(null) }
|
||||
@@ -122,7 +121,7 @@ fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigVie
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.position),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -27,7 +27,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -40,7 +39,7 @@ import org.meshtastic.proto.config
|
||||
import org.meshtastic.proto.copy
|
||||
|
||||
@Composable
|
||||
fun PowerConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun PowerConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val powerConfig = state.radioConfig.power
|
||||
val formState = rememberConfigState(initialValue = powerConfig)
|
||||
@@ -48,7 +47,7 @@ fun PowerConfigScreen(navController: NavController, viewModel: RadioConfigViewMo
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.power),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -25,7 +25,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.SwitchPreference
|
||||
@@ -37,14 +36,14 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun RangeTestConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun RangeTestConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val rangeTestConfig = state.moduleConfig.rangeTest
|
||||
val formState = rememberConfigState(initialValue = rangeTestConfig)
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.range_test),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.EditListPreference
|
||||
import org.meshtastic.core.ui.component.SwitchPreference
|
||||
@@ -36,7 +35,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun RemoteHardwareConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun RemoteHardwareConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val remoteHardwareConfig = state.moduleConfig.remoteHardware
|
||||
val formState = rememberConfigState(initialValue = remoteHardwareConfig)
|
||||
@@ -44,7 +43,7 @@ fun RemoteHardwareConfigScreen(navController: NavController, viewModel: RadioCon
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.remote_hardware),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -43,7 +43,6 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import com.google.protobuf.ByteString
|
||||
import org.meshtastic.core.model.util.encodeToString
|
||||
import org.meshtastic.core.model.util.toByteString
|
||||
@@ -61,7 +60,7 @@ import java.security.SecureRandom
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun SecurityConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun SecurityConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val node by viewModel.destNode.collectAsStateWithLifecycle()
|
||||
val securityConfig = state.radioConfig.security
|
||||
@@ -125,7 +124,7 @@ fun SecurityConfigScreen(navController: NavController, viewModel: RadioConfigVie
|
||||
val focusManager = LocalFocusManager.current
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.security),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
@@ -38,7 +37,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun SerialConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun SerialConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val serialConfig = state.moduleConfig.serial
|
||||
val formState = rememberConfigState(initialValue = serialConfig)
|
||||
@@ -46,7 +45,7 @@ fun SerialConfigScreen(navController: NavController, viewModel: RadioConfigViewM
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.serial),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.EditTextPreference
|
||||
import org.meshtastic.core.ui.component.SwitchPreference
|
||||
@@ -36,7 +35,7 @@ import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.moduleConfig
|
||||
|
||||
@Composable
|
||||
fun StoreForwardConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun StoreForwardConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val storeForwardConfig = state.moduleConfig.storeForward
|
||||
val formState = rememberConfigState(initialValue = storeForwardConfig)
|
||||
@@ -44,7 +43,7 @@ fun StoreForwardConfigScreen(navController: NavController, viewModel: RadioConfi
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.store_forward),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -25,7 +25,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
@@ -40,7 +39,7 @@ import org.meshtastic.proto.moduleConfig
|
||||
private const val MIN_FW_FOR_TELEMETRY_TOGGLE = "2.7.12"
|
||||
|
||||
@Composable
|
||||
fun TelemetryConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun TelemetryConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val telemetryConfig = state.moduleConfig.telemetry
|
||||
val formState = rememberConfigState(initialValue = telemetryConfig)
|
||||
@@ -49,7 +48,7 @@ fun TelemetryConfigScreen(navController: NavController, viewModel: RadioConfigVi
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.telemetry),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected,
|
||||
responseState = state.responseState,
|
||||
|
||||
@@ -29,7 +29,6 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavController
|
||||
import org.meshtastic.core.database.model.isUnmessageableRole
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.strings.R
|
||||
@@ -41,7 +40,7 @@ import org.meshtastic.feature.settings.radio.RadioConfigViewModel
|
||||
import org.meshtastic.proto.copy
|
||||
|
||||
@Composable
|
||||
fun UserConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) {
|
||||
fun UserConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
val userConfig = state.userConfig
|
||||
val formState = rememberConfigState(initialValue = userConfig)
|
||||
@@ -54,7 +53,7 @@ fun UserConfigScreen(navController: NavController, viewModel: RadioConfigViewMod
|
||||
|
||||
RadioConfigScreenList(
|
||||
title = stringResource(id = R.string.user),
|
||||
onBack = { navController.popBackStack() },
|
||||
onBack = onBack,
|
||||
configState = formState,
|
||||
enabled = state.connected && validNames,
|
||||
responseState = state.responseState,
|
||||
|
||||
Reference in New Issue
Block a user