diff --git a/app/src/androidTest/java/com/geeksville/mesh/compose/EditDeviceProfileDialogTest.kt b/app/src/androidTest/java/com/geeksville/mesh/compose/EditDeviceProfileDialogTest.kt
index 9a4e1b2c3..33a55bc0b 100644
--- a/app/src/androidTest/java/com/geeksville/mesh/compose/EditDeviceProfileDialogTest.kt
+++ b/app/src/androidTest/java/com/geeksville/mesh/compose/EditDeviceProfileDialogTest.kt
@@ -27,7 +27,7 @@ import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile
import com.geeksville.mesh.R
import com.geeksville.mesh.deviceProfile
import com.geeksville.mesh.position
-import com.geeksville.mesh.ui.components.config.EditDeviceProfileDialog
+import com.geeksville.mesh.ui.radioconfig.components.EditDeviceProfileDialog
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
diff --git a/app/src/main/java/com/geeksville/mesh/navigation/RadioConfigNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/RadioConfigNavigation.kt
new file mode 100644
index 000000000..4323b2212
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/navigation/RadioConfigNavigation.kt
@@ -0,0 +1,197 @@
+/*
+ * 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 .
+ */
+
+package com.geeksville.mesh.navigation
+
+import androidx.compose.runtime.remember
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.navigation.NavController
+import androidx.navigation.NavGraphBuilder
+import androidx.navigation.compose.composable
+import com.geeksville.mesh.ui.Route
+import com.geeksville.mesh.ui.radioconfig.RadioConfigScreen
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
+import com.geeksville.mesh.ui.radioconfig.components.AmbientLightingConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.AudioConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.BluetoothConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.CannedMessageConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.ChannelConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.DetectionSensorConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.DeviceConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.DisplayConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.ExternalNotificationConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.LoRaConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.MQTTConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.NeighborInfoConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.NetworkConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.PaxcounterConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.PositionConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.PowerConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.RangeTestConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.RemoteHardwareConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.SecurityConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.SerialConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.StoreForwardConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.TelemetryConfigScreen
+import com.geeksville.mesh.ui.radioconfig.components.UserConfigScreen
+
+@Suppress("LongMethod")
+fun NavGraphBuilder.addRadioConfigSection(navController: NavController) {
+ composable {
+ RadioConfigScreen(
+ onNavigate = navController::navigate,
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ UserConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ ChannelConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ DeviceConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ PositionConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ PowerConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ NetworkConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ DisplayConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ LoRaConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ BluetoothConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ SecurityConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ MQTTConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ SerialConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ ExternalNotificationConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ StoreForwardConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ RangeTestConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ TelemetryConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ CannedMessageConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ AudioConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ RemoteHardwareConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ NeighborInfoConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ AmbientLightingConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ DetectionSensorConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+ composable {
+ val parentEntry = remember { navController.getBackStackEntry() }
+ PaxcounterConfigScreen(
+ viewModel = hiltViewModel(parentEntry),
+ )
+ }
+}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt
index d2b020028..a55054b84 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt
@@ -104,12 +104,12 @@ import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.ui.components.AdaptiveTwoPane
import com.geeksville.mesh.ui.components.DropDownPreference
import com.geeksville.mesh.ui.components.PreferenceFooter
-import com.geeksville.mesh.ui.components.config.ChannelCard
-import com.geeksville.mesh.ui.components.config.ChannelSelection
-import com.geeksville.mesh.ui.components.config.EditChannelDialog
import com.geeksville.mesh.ui.components.dragContainer
import com.geeksville.mesh.ui.components.dragDropItemsIndexed
import com.geeksville.mesh.ui.components.rememberDragDropState
+import com.geeksville.mesh.ui.radioconfig.components.ChannelCard
+import com.geeksville.mesh.ui.radioconfig.components.ChannelSelection
+import com.geeksville.mesh.ui.radioconfig.components.EditChannelDialog
import com.geeksville.mesh.ui.theme.AppTheme
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.journeyapps.barcodescanner.ScanContract
diff --git a/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt b/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt
index 6f7e5ba8e..b98546fde 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt
@@ -21,36 +21,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-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.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.res.stringResource
@@ -64,11 +38,10 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute
-import com.geeksville.mesh.MeshProtos.DeviceMetadata
import com.geeksville.mesh.R
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.model.MetricsViewModel
-import com.geeksville.mesh.model.RadioConfigViewModel
+import com.geeksville.mesh.navigation.addRadioConfigSection
import com.geeksville.mesh.ui.components.BaseScaffold
import com.geeksville.mesh.ui.components.DeviceMetricsScreen
import com.geeksville.mesh.ui.components.EnvironmentMetricsScreen
@@ -76,31 +49,8 @@ import com.geeksville.mesh.ui.components.NodeMapScreen
import com.geeksville.mesh.ui.components.PositionLogScreen
import com.geeksville.mesh.ui.components.SignalMetricsScreen
import com.geeksville.mesh.ui.components.TracerouteLogScreen
-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.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
import com.geeksville.mesh.ui.theme.AppTheme
-import com.geeksville.mesh.util.UiText
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.serialization.Serializable
@@ -164,13 +114,6 @@ class NavGraphFragment : ScreenFragment("NavGraph"), Logging {
}
}
-enum class AdminRoute(@StringRes val title: Int) {
- REBOOT(R.string.reboot),
- SHUTDOWN(R.string.shutdown),
- FACTORY_RESET(R.string.factory_reset),
- NODEDB_RESET(R.string.nodedb_reset),
-}
-
sealed interface Route {
@Serializable
data class Messages(val contactKey: String, val message: String = "") : Route
@@ -180,7 +123,7 @@ sealed interface Route {
@Serializable
data class RadioConfig(val destNum: Int? = null) : Route
@Serializable data object User : Route
- @Serializable data object Channels : Route
+ @Serializable data object ChannelConfig : Route
@Serializable data object Device : Route
@Serializable data object Position : Route
@Serializable data object Power : Route
@@ -214,74 +157,6 @@ sealed interface Route {
@Serializable data object TracerouteLog : Route
}
-// Config (type = AdminProtos.AdminMessage.ConfigType)
-enum class ConfigRoute(val title: String, val route: Route, val icon: ImageVector?, val type: Int = 0) {
- USER("User", Route.User, Icons.Default.Person, 0),
- CHANNELS("Channels", Route.Channels, Icons.AutoMirrored.Default.List, 0),
- DEVICE("Device", Route.Device, Icons.Default.Router, 0),
- POSITION("Position", Route.Position, Icons.Default.LocationOn, 1),
- POWER("Power", Route.Power, Icons.Default.Power, 2),
- NETWORK("Network", Route.Network, Icons.Default.Wifi, 3),
- DISPLAY("Display", Route.Display, Icons.Default.DisplaySettings, 4),
- LORA("LoRa", Route.LoRa, Icons.Default.CellTower, 5),
- BLUETOOTH("Bluetooth", Route.Bluetooth, Icons.Default.Bluetooth, 6),
- SECURITY("Security", Route.Security, Icons.Default.Security, type = 7),
- ;
-
- companion object {
- fun filterExcludedFrom(metadata: DeviceMetadata?): List = entries.filter {
- when {
- metadata == null -> true
- it == BLUETOOTH -> metadata.hasBluetooth
- it == NETWORK -> metadata.hasWifi || metadata.hasEthernet
- else -> true // Include all other routes by default
- }
- }
- }
-}
-
-// ModuleConfig (type = AdminProtos.AdminMessage.ModuleConfigType)
-enum class ModuleRoute(val title: String, val route: Route, val icon: ImageVector?, val type: Int = 0) {
- MQTT("MQTT", Route.MQTT, Icons.Default.Cloud, 0),
- SERIAL("Serial", Route.Serial, Icons.Default.Usb, 1),
- EXT_NOTIFICATION("External Notification", Route.ExtNotification, Icons.Default.Notifications, 2),
- STORE_FORWARD("Store & Forward", Route.StoreForward, Icons.AutoMirrored.Default.Forward, 3),
- RANGE_TEST("Range Test", Route.RangeTest, Icons.Default.Speed, 4),
- TELEMETRY("Telemetry", Route.Telemetry, Icons.Default.DataUsage, 5),
- CANNED_MESSAGE("Canned Message", Route.CannedMessage, Icons.AutoMirrored.Default.Message, 6),
- AUDIO("Audio", Route.Audio, Icons.AutoMirrored.Default.VolumeUp, 7),
- REMOTE_HARDWARE("Remote Hardware", Route.RemoteHardware, Icons.Default.SettingsRemote, 8),
- NEIGHBOR_INFO("Neighbor Info", Route.NeighborInfo, Icons.Default.People, 9),
- AMBIENT_LIGHTING("Ambient Lighting", Route.AmbientLighting, Icons.Default.LightMode, 10),
- DETECTION_SENSOR("Detection Sensor", Route.DetectionSensor, Icons.Default.Sensors, 11),
- PAXCOUNTER("Paxcounter", Route.Paxcounter, Icons.Default.PermScanWifi, 12),
- ;
-
- val bitfield: Int get() = 1 shl ordinal
-
- companion object {
- fun filterExcludedFrom(metadata: DeviceMetadata?): List = entries.filter {
- when (metadata) {
- null -> true
- else -> metadata.excludedModules and it.bitfield == 0
- }
- }
- }
-}
-
-/**
- * Generic sealed class defines each possible state of a response.
- */
-sealed class ResponseState {
- data object Empty : ResponseState()
- data class Loading(var total: Int = 1, var completed: Int = 0) : ResponseState()
- data class Success(val result: T) : ResponseState()
- data class Error(val error: UiText) : ResponseState()
-
- fun isWaiting() = this !is Empty
-}
-
-@Suppress("LongMethod")
@Composable
fun NavGraph(
navController: NavHostController = rememberNavController(),
@@ -320,101 +195,7 @@ fun NavGraph(
val parentEntry = remember { navController.getBackStackEntry() }
TracerouteLogScreen(hiltViewModel(parentEntry))
}
- composable {
- RadioConfigScreen { navController.navigate(route = it) }
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- UserConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- ChannelConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- DeviceConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- PositionConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- PowerConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- NetworkConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- DisplayConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- LoRaConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- BluetoothConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- SecurityConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- MQTTConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- SerialConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- ExternalNotificationConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- StoreForwardConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- RangeTestConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- TelemetryConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- CannedMessageConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- AudioConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- RemoteHardwareConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- NeighborInfoConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- AmbientLightingConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- DetectionSensorConfigScreen(hiltViewModel(parentEntry))
- }
- composable {
- val parentEntry = remember { navController.getBackStackEntry() }
- PaxcounterConfigScreen(hiltViewModel(parentEntry))
- }
+ addRadioConfigSection(navController)
composable { backStackEntry ->
val message = backStackEntry.toRoute().message
ShareScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt b/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt
index 8a4e65298..f11bcdf36 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt
@@ -97,6 +97,7 @@ import com.geeksville.mesh.model.MetricsViewModel
import com.geeksville.mesh.model.Node
import com.geeksville.mesh.ui.components.PreferenceCategory
import com.geeksville.mesh.ui.preview.NodePreviewParameterProvider
+import com.geeksville.mesh.ui.radioconfig.NavCard
import com.geeksville.mesh.ui.theme.AppTheme
import com.geeksville.mesh.util.DistanceUnit
import com.geeksville.mesh.util.formatAgo
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/ScannedQrCodeDialog.kt b/app/src/main/java/com/geeksville/mesh/ui/components/ScannedQrCodeDialog.kt
index 2b16eb23c..cff710a74 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/ScannedQrCodeDialog.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/components/ScannedQrCodeDialog.kt
@@ -54,7 +54,7 @@ import com.geeksville.mesh.R
import com.geeksville.mesh.channelSet
import com.geeksville.mesh.copy
import com.geeksville.mesh.model.Channel
-import com.geeksville.mesh.ui.components.config.ChannelSelection
+import com.geeksville.mesh.ui.radioconfig.components.ChannelSelection
/**
* Enables the user to select which channels to accept after scanning a QR code.
diff --git a/app/src/main/java/com/geeksville/mesh/ui/radioconfig/AdminRoute.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/AdminRoute.kt
new file mode 100644
index 000000000..1ff2bd348
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/AdminRoute.kt
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+
+package com.geeksville.mesh.ui.radioconfig
+
+import androidx.annotation.StringRes
+import com.geeksville.mesh.R
+
+enum class AdminRoute(@StringRes val title: Int) {
+ REBOOT(R.string.reboot),
+ SHUTDOWN(R.string.shutdown),
+ FACTORY_RESET(R.string.factory_reset),
+ NODEDB_RESET(R.string.nodedb_reset),
+}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ConfigRoute.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ConfigRoute.kt
new file mode 100644
index 000000000..4f2986c37
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ConfigRoute.kt
@@ -0,0 +1,60 @@
+/*
+ * 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 .
+ */
+
+package com.geeksville.mesh.ui.radioconfig
+
+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 com.geeksville.mesh.MeshProtos.DeviceMetadata
+import com.geeksville.mesh.ui.Route
+
+@Suppress("MagicNumber")
+// Config (type = AdminProtos.AdminMessage.ConfigType)
+enum class ConfigRoute(val title: String, val route: Route, val icon: ImageVector?, val type: Int = 0) {
+ USER("User", Route.User, Icons.Default.Person, 0),
+ CHANNELS("Channels", Route.ChannelConfig, Icons.AutoMirrored.Default.List, 0),
+ DEVICE("Device", Route.Device, Icons.Default.Router, 0),
+ POSITION("Position", Route.Position, Icons.Default.LocationOn, 1),
+ POWER("Power", Route.Power, Icons.Default.Power, 2),
+ NETWORK("Network", Route.Network, Icons.Default.Wifi, 3),
+ DISPLAY("Display", Route.Display, Icons.Default.DisplaySettings, 4),
+ LORA("LoRa", Route.LoRa, Icons.Default.CellTower, 5),
+ BLUETOOTH("Bluetooth", Route.Bluetooth, Icons.Default.Bluetooth, 6),
+ SECURITY("Security", Route.Security, Icons.Default.Security, 7),
+ ;
+
+ companion object {
+ fun filterExcludedFrom(metadata: DeviceMetadata?): List = entries.filter {
+ when {
+ metadata == null -> true
+ it == BLUETOOTH -> metadata.hasBluetooth
+ it == NETWORK -> metadata.hasWifi || metadata.hasEthernet
+ else -> true // Include all other routes by default
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ModuleRoute.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ModuleRoute.kt
new file mode 100644
index 000000000..cd6dc09da
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ModuleRoute.kt
@@ -0,0 +1,66 @@
+/*
+ * 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 .
+ */
+
+package com.geeksville.mesh.ui.radioconfig
+
+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 com.geeksville.mesh.MeshProtos.DeviceMetadata
+import com.geeksville.mesh.ui.Route
+
+@Suppress("MagicNumber")
+// ModuleConfig (type = AdminProtos.AdminMessage.ModuleConfigType)
+enum class ModuleRoute(val title: String, val route: Route, val icon: ImageVector?, val type: Int = 0) {
+ MQTT("MQTT", Route.MQTT, Icons.Default.Cloud, 0),
+ SERIAL("Serial", Route.Serial, Icons.Default.Usb, 1),
+ EXT_NOTIFICATION("External Notification", Route.ExtNotification, Icons.Default.Notifications, 2),
+ STORE_FORWARD("Store & Forward", Route.StoreForward, Icons.AutoMirrored.Default.Forward, 3),
+ RANGE_TEST("Range Test", Route.RangeTest, Icons.Default.Speed, 4),
+ TELEMETRY("Telemetry", Route.Telemetry, Icons.Default.DataUsage, 5),
+ CANNED_MESSAGE("Canned Message", Route.CannedMessage, Icons.AutoMirrored.Default.Message, 6),
+ AUDIO("Audio", Route.Audio, Icons.AutoMirrored.Default.VolumeUp, 7),
+ REMOTE_HARDWARE("Remote Hardware", Route.RemoteHardware, Icons.Default.SettingsRemote, 8),
+ NEIGHBOR_INFO("Neighbor Info", Route.NeighborInfo, Icons.Default.People, 9),
+ AMBIENT_LIGHTING("Ambient Lighting", Route.AmbientLighting, Icons.Default.LightMode, 10),
+ DETECTION_SENSOR("Detection Sensor", Route.DetectionSensor, Icons.Default.Sensors, 11),
+ PAXCOUNTER("Paxcounter", Route.Paxcounter, Icons.Default.PermScanWifi, 12),
+ ;
+
+ val bitfield: Int get() = 1 shl ordinal
+
+ companion object {
+ fun filterExcludedFrom(metadata: DeviceMetadata?): List = entries.filter {
+ when (metadata) {
+ null -> true
+ else -> metadata.excludedModules and it.bitfield == 0
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/RadioConfigScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/RadioConfig.kt
similarity index 82%
rename from app/src/main/java/com/geeksville/mesh/ui/RadioConfigScreen.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/RadioConfig.kt
index 527d6a96f..2889338f7 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/RadioConfigScreen.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/RadioConfig.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui
+package com.geeksville.mesh.ui.radioconfig
import android.app.Activity
import android.content.Intent
@@ -65,13 +65,12 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile
import com.geeksville.mesh.R
-import com.geeksville.mesh.model.RadioConfigState
-import com.geeksville.mesh.model.RadioConfigViewModel
+import com.geeksville.mesh.ui.Route
import com.geeksville.mesh.ui.components.PreferenceCategory
-import com.geeksville.mesh.ui.components.config.EditDeviceProfileDialog
-import com.geeksville.mesh.ui.components.config.PacketResponseStateDialog
+import com.geeksville.mesh.ui.radioconfig.components.EditDeviceProfileDialog
+import com.geeksville.mesh.ui.radioconfig.components.PacketResponseStateDialog
-private fun getNavRouteFrom(routeName: String): Any? {
+private fun getNavRouteFrom(routeName: String): Route? {
return ConfigRoute.entries.find { it.name == routeName }?.route
?: ModuleRoute.entries.find { it.name == routeName }?.route
}
@@ -81,7 +80,7 @@ private fun getNavRouteFrom(routeName: String): Any? {
fun RadioConfigScreen(
viewModel: RadioConfigViewModel = hiltViewModel(),
modifier: Modifier = Modifier,
- onNavigate: (Any) -> Unit = {}
+ onNavigate: (Route) -> Unit = {}
) {
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
var isWaiting by remember { mutableStateOf(false) }
@@ -222,54 +221,57 @@ fun NavCard(
}
}
+@Suppress("LongMethod")
@Composable
private fun NavButton(@StringRes title: Int, enabled: Boolean, onClick: () -> Unit) {
var showDialog by remember { mutableStateOf(false) }
- if (showDialog) AlertDialog(
- onDismissRequest = {},
- shape = RoundedCornerShape(16.dp),
- backgroundColor = MaterialTheme.colors.background,
- title = {
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center,
- ) {
- Icon(
- imageVector = Icons.TwoTone.Warning,
- contentDescription = "warning",
- modifier = Modifier.padding(end = 8.dp)
- )
- Text(
- text = "${stringResource(title)}?\n")
- Icon(
- imageVector = Icons.TwoTone.Warning,
- contentDescription = "warning",
- modifier = Modifier.padding(start = 8.dp)
- )
+ if (showDialog) {
+ AlertDialog(
+ onDismissRequest = {},
+ shape = RoundedCornerShape(16.dp),
+ backgroundColor = MaterialTheme.colors.background,
+ title = {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center,
+ ) {
+ Icon(
+ imageVector = Icons.TwoTone.Warning,
+ contentDescription = "warning",
+ modifier = Modifier.padding(end = 8.dp)
+ )
+ Text(
+ text = "${stringResource(title)}?\n")
+ Icon(
+ imageVector = Icons.TwoTone.Warning,
+ contentDescription = "warning",
+ modifier = Modifier.padding(start = 8.dp)
+ )
+ }
+ },
+ buttons = {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ TextButton(
+ modifier = Modifier.weight(1f),
+ onClick = { showDialog = false },
+ ) { Text(stringResource(R.string.cancel)) }
+ Button(
+ modifier = Modifier.weight(1f),
+ onClick = {
+ showDialog = false
+ onClick()
+ },
+ ) { Text(stringResource(R.string.send)) }
+ }
}
- },
- buttons = {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
- horizontalArrangement = Arrangement.spacedBy(8.dp),
- verticalAlignment = Alignment.CenterVertically,
- ) {
- TextButton(
- modifier = Modifier.weight(1f),
- onClick = { showDialog = false },
- ) { Text(stringResource(R.string.cancel)) }
- Button(
- modifier = Modifier.weight(1f),
- onClick = {
- showDialog = false
- onClick()
- },
- ) { Text(stringResource(R.string.send)) }
- }
- }
- )
+ )
+ }
Column {
Spacer(modifier = Modifier.height(4.dp))
diff --git a/app/src/main/java/com/geeksville/mesh/model/RadioConfigViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/RadioConfigViewModel.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/model/RadioConfigViewModel.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/RadioConfigViewModel.kt
index 6abe72cd7..1523d0cae 100644
--- a/app/src/main/java/com/geeksville/mesh/model/RadioConfigViewModel.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/RadioConfigViewModel.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.model
+package com.geeksville.mesh.ui.radioconfig
import android.app.Application
import android.net.Uri
@@ -39,13 +39,13 @@ import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.config
import com.geeksville.mesh.database.entity.MyNodeEntity
import com.geeksville.mesh.deviceProfile
+import com.geeksville.mesh.model.Node
+import com.geeksville.mesh.model.getChannelList
+import com.geeksville.mesh.model.getStringResFrom
+import com.geeksville.mesh.model.toChannelSet
import com.geeksville.mesh.moduleConfig
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
import com.geeksville.mesh.service.MeshService.ConnectionState
-import com.geeksville.mesh.ui.AdminRoute
-import com.geeksville.mesh.ui.ConfigRoute
-import com.geeksville.mesh.ui.ModuleRoute
-import com.geeksville.mesh.ui.ResponseState
import com.geeksville.mesh.ui.Route
import com.geeksville.mesh.util.UiText
import com.google.protobuf.MessageLite
diff --git a/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ResponseState.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ResponseState.kt
new file mode 100644
index 000000000..0640f4807
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/ResponseState.kt
@@ -0,0 +1,32 @@
+/*
+ * 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 .
+ */
+
+package com.geeksville.mesh.ui.radioconfig
+
+import com.geeksville.mesh.util.UiText
+
+/**
+ * Generic sealed class defines each possible state of a response.
+ */
+sealed class ResponseState {
+ data object Empty : ResponseState()
+ data class Loading(var total: Int = 1, var completed: Int = 0) : ResponseState()
+ data class Success(val result: T) : ResponseState()
+ data class Error(val error: UiText) : ResponseState()
+
+ fun isWaiting() = this !is Empty
+}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/AmbientLightingConfigItemList.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/AmbientLightingConfigItemList.kt
index 2a3eed197..407bfc88e 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/AmbientLightingConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,12 +33,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun AmbientLightingConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/AudioConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/AudioConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/AudioConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/AudioConfigItemList.kt
index ac0f417ec..262ddb086 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/AudioConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/AudioConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,13 +33,13 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun AudioConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/BluetoothConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/BluetoothConfigItemList.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/BluetoothConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/BluetoothConfigItemList.kt
index 662fa5d6a..00dd1a617 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/BluetoothConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/BluetoothConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -34,12 +34,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun BluetoothConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/CannedMessageConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/CannedMessageConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/CannedMessageConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/CannedMessageConfigItemList.kt
index 577be3e4b..988086771 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/CannedMessageConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/CannedMessageConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -36,13 +36,13 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun CannedMessageConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/ChannelSettingsItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/ChannelSettingsItemList.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/ChannelSettingsItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/ChannelSettingsItemList.kt
index dbf189c5f..3b2fa30d0 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/ChannelSettingsItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/ChannelSettingsItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.FastOutSlowInEasing
@@ -70,12 +70,12 @@ 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
import com.geeksville.mesh.ui.components.dragDropItemsIndexed
import com.geeksville.mesh.ui.components.rememberDragDropState
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@OptIn(ExperimentalMaterialApi::class)
@Composable
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DetectionSensorConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DetectionSensorConfigItemList.kt
index 5d6fe423b..fa845d84d 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DetectionSensorConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -36,13 +36,13 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun DetectionSensorConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/DeviceConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DeviceConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/DeviceConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DeviceConfigItemList.kt
index f90c43ebf..0d3c16c40 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/DeviceConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DeviceConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -39,12 +39,12 @@ 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
import com.geeksville.mesh.ui.components.PreferenceFooter
import com.geeksville.mesh.ui.components.SwitchPreference
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
private val DeviceConfig.Role.stringRes: Int
get() = when (this) {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/DisplayConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DisplayConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/DisplayConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DisplayConfigItemList.kt
index 8fdd542a8..1d97802c5 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/DisplayConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/DisplayConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -34,12 +34,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun DisplayConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/EditChannelDialog.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/EditChannelDialog.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/EditChannelDialog.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/EditChannelDialog.kt
index 30eb67145..405cd00a1 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/EditChannelDialog.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/EditChannelDialog.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/EditDeviceProfileDialog.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/EditDeviceProfileDialog.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/EditDeviceProfileDialog.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/EditDeviceProfileDialog.kt
index 93a108276..e8bf571ee 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/EditDeviceProfileDialog.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/EditDeviceProfileDialog.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/ExternalNotificationConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/ExternalNotificationConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/ExternalNotificationConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/ExternalNotificationConfigItemList.kt
index abe534106..094d0d139 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/ExternalNotificationConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/ExternalNotificationConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -36,13 +36,13 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun ExternalNotificationConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/LoRaConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/LoRaConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/LoRaConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/LoRaConfigItemList.kt
index 029d5d8d0..17a3279c4 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/LoRaConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/LoRaConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -37,7 +37,6 @@ 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
@@ -46,6 +45,7 @@ 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.radioconfig.RadioConfigViewModel
@Composable
fun LoRaConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/MQTTConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/MQTTConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/MQTTConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/MQTTConfigItemList.kt
index 59587adbf..ef5964161 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/MQTTConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/MQTTConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -38,7 +38,6 @@ 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
@@ -46,6 +45,7 @@ import com.geeksville.mesh.ui.components.PositionPrecisionPreference
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.radioconfig.RadioConfigViewModel
@Composable
fun MQTTConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/NeighborInfoConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/NeighborInfoConfigItemList.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/NeighborInfoConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/NeighborInfoConfigItemList.kt
index 5fd11d5e6..5eb8aa889 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/NeighborInfoConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/NeighborInfoConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -35,12 +35,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.ModuleConfigProtos
import com.geeksville.mesh.R
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.radioconfig.RadioConfigViewModel
@Composable
fun NeighborInfoConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/NetworkConfigItemList.kt
similarity index 99%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/NetworkConfigItemList.kt
index 45c00f168..a8483bc31 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/NetworkConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/NetworkConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.foundation.layout.fillMaxSize
@@ -46,7 +46,6 @@ 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
@@ -55,6 +54,7 @@ import com.geeksville.mesh.ui.components.PreferenceCategory
import com.geeksville.mesh.ui.components.PreferenceFooter
import com.geeksville.mesh.ui.components.SimpleAlertDialog
import com.geeksville.mesh.ui.components.SwitchPreference
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/PacketResponseStateDialog.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PacketResponseStateDialog.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/PacketResponseStateDialog.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PacketResponseStateDialog.kt
index 32ed25077..0ea426889 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/PacketResponseStateDialog.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PacketResponseStateDialog.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Arrangement
@@ -37,7 +37,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.R
-import com.geeksville.mesh.ui.ResponseState
+import com.geeksville.mesh.ui.radioconfig.ResponseState
@Composable
fun PacketResponseStateDialog(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/PaxcounterConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PaxcounterConfigItemList.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/PaxcounterConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PaxcounterConfigItemList.kt
index d1b199045..cc9311947 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/PaxcounterConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PaxcounterConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,12 +33,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun PaxcounterConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/PositionConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PositionConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/PositionConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PositionConfigItemList.kt
index 523b637f2..af534c778 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/PositionConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PositionConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -36,13 +36,13 @@ 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
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.radioconfig.RadioConfigViewModel
@Composable
fun PositionConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/PowerConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PowerConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/PowerConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PowerConfigItemList.kt
index 471b76d77..5244e1850 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/PowerConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/PowerConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -34,11 +34,11 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun PowerConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/RangeTestConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/RangeTestConfigItemList.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/RangeTestConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/RangeTestConfigItemList.kt
index d956cf4fa..f77e41665 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/RangeTestConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/RangeTestConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,12 +33,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun RangeTestConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/RemoteHardwareConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/RemoteHardwareConfigItemList.kt
similarity index 97%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/RemoteHardwareConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/RemoteHardwareConfigItemList.kt
index 88c48a72b..adea2af30 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/RemoteHardwareConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/RemoteHardwareConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,12 +33,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun RemoteHardwareConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/SecurityConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/SecurityConfigItemList.kt
index 4e08db93d..55d7b0550 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/SecurityConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -34,12 +34,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun SecurityConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/SerialConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/SerialConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/SerialConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/SerialConfigItemList.kt
index 0c89cff0e..38d388303 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/SerialConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/SerialConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,13 +33,13 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun SerialConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/StoreForwardConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/StoreForwardConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/StoreForwardConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/StoreForwardConfigItemList.kt
index 42319a85f..90ddf141a 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/StoreForwardConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/StoreForwardConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,12 +33,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun StoreForwardConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/TelemetryConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/TelemetryConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/TelemetryConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/TelemetryConfigItemList.kt
index fdda8b588..a8e72a3f1 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/TelemetryConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/TelemetryConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -33,12 +33,12 @@ 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
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
@Composable
fun TelemetryConfigScreen(
diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/UserConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/UserConfigItemList.kt
similarity index 98%
rename from app/src/main/java/com/geeksville/mesh/ui/components/config/UserConfigItemList.kt
rename to app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/UserConfigItemList.kt
index 87d4321a9..b71bb3c14 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/components/config/UserConfigItemList.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/radioconfig/components/UserConfigItemList.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.ui.components.config
+package com.geeksville.mesh.ui.radioconfig.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -36,13 +36,13 @@ 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
import com.geeksville.mesh.ui.components.PreferenceFooter
import com.geeksville.mesh.ui.components.RegularPreference
import com.geeksville.mesh.ui.components.SwitchPreference
+import com.geeksville.mesh.ui.radioconfig.RadioConfigViewModel
import com.geeksville.mesh.user
@Composable
diff --git a/config/detekt/detekt-baseline.xml b/config/detekt/detekt-baseline.xml
index a1b8943b3..c13ab3d07 100644
--- a/config/detekt/detekt-baseline.xml
+++ b/config/detekt/detekt-baseline.xml
@@ -129,7 +129,6 @@
FinalNewline:SoftwareUpdateService.kt$com.geeksville.mesh.service.SoftwareUpdateService.kt
FinalNewline:SqlTileWriterExt.kt$com.geeksville.mesh.util.SqlTileWriterExt.kt
FinalNewline:TCPInterfaceFactory.kt$com.geeksville.mesh.repository.radio.TCPInterfaceFactory.kt
- FinalNewline:Theme.kt$com.geeksville.mesh.ui.theme.Theme.kt
FinalNewline:UsbBroadcastReceiver.kt$com.geeksville.mesh.repository.usb.UsbBroadcastReceiver.kt
FinalNewline:UsbRepositoryModule.kt$com.geeksville.mesh.repository.usb.UsbRepositoryModule.kt
ForbiddenComment:MapFragment.kt$// TODO: Accept filename input param from user
@@ -161,7 +160,6 @@
LongMethod:MainActivity.kt$MainActivity$override fun onOptionsItemSelected(item: MenuItem): Boolean
LongMethod:MapFragment.kt$@Composable fun MapView( model: UIViewModel = viewModel(), )
LongMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)
- LongMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigItemList( networkConfig: NetworkConfig, enabled: Boolean, onSaveClicked: (NetworkConfig) -> Unit, )
LongMethod:PowerConfigItemList.kt$@Composable fun PowerConfigItemList( powerConfig: PowerConfig, enabled: Boolean, onSaveClicked: (PowerConfig) -> Unit, )
LongMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)
LongMethod:SerialConfigItemList.kt$@Composable fun SerialConfigItemList( serialConfig: SerialConfig, enabled: Boolean, onSaveClicked: (SerialConfig) -> Unit, )
@@ -300,20 +298,6 @@
MagicNumber:NOAAWmsTileSource.kt$NOAAWmsTileSource$360.0
MagicNumber:NOAAWmsTileSource.kt$NOAAWmsTileSource$4
MagicNumber:NOAAWmsTileSource.kt$NOAAWmsTileSource$5
- MagicNumber:NavGraph.kt$ConfigRoute.BLUETOOTH$6
- MagicNumber:NavGraph.kt$ConfigRoute.DISPLAY$4
- MagicNumber:NavGraph.kt$ConfigRoute.LORA$5
- MagicNumber:NavGraph.kt$ConfigRoute.NETWORK$3
- MagicNumber:NavGraph.kt$ModuleRoute.AMBIENT_LIGHTING$10
- MagicNumber:NavGraph.kt$ModuleRoute.AUDIO$7
- MagicNumber:NavGraph.kt$ModuleRoute.CANNED_MESSAGE$6
- MagicNumber:NavGraph.kt$ModuleRoute.DETECTION_SENSOR$11
- MagicNumber:NavGraph.kt$ModuleRoute.NEIGHBOR_INFO$9
- MagicNumber:NavGraph.kt$ModuleRoute.PAXCOUNTER$12
- MagicNumber:NavGraph.kt$ModuleRoute.RANGE_TEST$4
- MagicNumber:NavGraph.kt$ModuleRoute.REMOTE_HARDWARE$8
- MagicNumber:NavGraph.kt$ModuleRoute.STORE_FORWARD$3
- MagicNumber:NavGraph.kt$ModuleRoute.TELEMETRY$5
MagicNumber:NodeInfo.kt$DeviceMetrics.Companion$1000
MagicNumber:NodeInfo.kt$EnvironmentMetrics.Companion$1000
MagicNumber:NodeInfo.kt$NodeInfo$0.114
@@ -513,8 +497,6 @@
MultiLineIfElse:NOAAWmsTileSource.kt$NOAAWmsTileSource$sb.append("service=WMS")
MultiLineIfElse:NodeInfo.kt$MeshUser$hwModel.name.replace('_', '-').replace('p', '.').lowercase()
MultiLineIfElse:NodeInfo.kt$MeshUser$null
- MultiLineIfElse:RadioConfigScreen.kt$AlertDialog( onDismissRequest = {}, shape = RoundedCornerShape(16.dp), backgroundColor = MaterialTheme.colors.background, title = { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center, ) { Icon( imageVector = Icons.TwoTone.Warning, contentDescription = "warning", modifier = Modifier.padding(end = 8.dp) ) Text( text = "${stringResource(title)}?\n") Icon( imageVector = Icons.TwoTone.Warning, contentDescription = "warning", modifier = Modifier.padding(start = 8.dp) ) } }, buttons = { Row( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { TextButton( modifier = Modifier.weight(1f), onClick = { showDialog = false }, ) { Text(stringResource(R.string.cancel)) } Button( modifier = Modifier.weight(1f), onClick = { showDialog = false onClick() }, ) { Text(stringResource(R.string.send)) } } } )
- MultiLineIfElse:RadioConfigViewModel.kt$RadioConfigViewModel$try { setChannels(channelUrl) } catch (ex: Exception) { errormsg("DeviceProfile channel import error", ex) setResponseStateError(ex.customMessage) }
MultiLineIfElse:RadioConfigViewModel.kt$RadioConfigViewModel$viewModelScope.launch { radioConfigRepository.replaceAllSettings(new) }
MultiLineIfElse:RadioInterfaceService.kt$RadioInterfaceService$startInterface()
MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$cb
@@ -582,7 +564,6 @@
NewLineAtEndOfFile:SoftwareUpdateService.kt$com.geeksville.mesh.service.SoftwareUpdateService.kt
NewLineAtEndOfFile:SqlTileWriterExt.kt$com.geeksville.mesh.util.SqlTileWriterExt.kt
NewLineAtEndOfFile:TCPInterfaceFactory.kt$com.geeksville.mesh.repository.radio.TCPInterfaceFactory.kt
- NewLineAtEndOfFile:Theme.kt$com.geeksville.mesh.ui.theme.Theme.kt
NewLineAtEndOfFile:UsbBroadcastReceiver.kt$com.geeksville.mesh.repository.usb.UsbBroadcastReceiver.kt
NewLineAtEndOfFile:UsbRepositoryModule.kt$com.geeksville.mesh.repository.usb.UsbRepositoryModule.kt
NoBlankLineBeforeRbrace:BluetoothInterface.kt$BluetoothInterface$
@@ -617,8 +598,6 @@
NoWildcardImports:BluetoothInterface.kt$import com.geeksville.mesh.service.*
NoWildcardImports:DeviceVersionTest.kt$import org.junit.Assert.*
NoWildcardImports:ExampleUnitTest.kt$import org.junit.Assert.*
- NoWildcardImports:MeshService.kt$import com.geeksville.mesh.*
- NoWildcardImports:MeshService.kt$import com.geeksville.mesh.util.*
NoWildcardImports:MockInterface.kt$import com.geeksville.mesh.*
NoWildcardImports:PreferenceFooter.kt$import androidx.compose.foundation.layout.*
NoWildcardImports:PreferenceFooter.kt$import androidx.compose.material.*
@@ -732,8 +711,6 @@
WildcardImport:BluetoothInterface.kt$import com.geeksville.mesh.service.*
WildcardImport:DeviceVersionTest.kt$import org.junit.Assert.*
WildcardImport:ExampleUnitTest.kt$import org.junit.Assert.*
- WildcardImport:MeshService.kt$import com.geeksville.mesh.*
- WildcardImport:MeshService.kt$import com.geeksville.mesh.util.*
WildcardImport:MockInterface.kt$import com.geeksville.mesh.*
WildcardImport:PreferenceFooter.kt$import androidx.compose.foundation.layout.*
WildcardImport:PreferenceFooter.kt$import androidx.compose.material.*