From e9bc9c9b15f36408800cdd791f0137161c3c37b8 Mon Sep 17 00:00:00 2001 From: Phil Oliver <3497406+poliver@users.noreply.github.com> Date: Mon, 3 Nov 2025 19:31:24 -0500 Subject: [PATCH] Move `SettingsNavigation` back to `:app` module (#3604) --- app/detekt-baseline.xml | 1 + .../mesh/navigation/ChannelsNavigation.kt | 20 +++----- .../mesh/navigation/ConnectionsNavigation.kt | 12 ++--- .../mesh}/navigation/SettingsNavigation.kt | 49 +++++++++++++------ .../main/java/com/geeksville/mesh/ui/Main.kt | 2 +- feature/settings/detekt-baseline.xml | 2 +- .../feature/settings/debugging/Debug.kt | 2 +- .../settings/navigation/SettingsNavUtils.kt | 23 +++++++++ 8 files changed, 72 insertions(+), 39 deletions(-) rename {feature/settings/src/main/kotlin/org/meshtastic/feature/settings => app/src/main/java/com/geeksville/mesh}/navigation/SettingsNavigation.kt (84%) create mode 100644 feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavUtils.kt diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml index fae4c81d4..360c359e3 100644 --- a/app/detekt-baseline.xml +++ b/app/detekt-baseline.xml @@ -11,6 +11,7 @@ ComposableParamOrder:EmptyStateContent.kt$EmptyStateContent ComposableParamOrder:Share.kt$ShareScreen CyclomaticComplexMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket) + CyclomaticComplexMethod:SettingsNavigation.kt$@Suppress("LongMethod") fun NavGraphBuilder.settingsGraph(navController: NavHostController) EmptyClassBlock:DebugLogFile.kt$BinaryLogFile${ } EmptyFunctionBlock:NopInterface.kt$NopInterface${ } EmptyFunctionBlock:NsdManager.kt$<no name provided>${ } diff --git a/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt index 3e2866346..ccf513922 100644 --- a/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt +++ b/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt @@ -27,7 +27,7 @@ import androidx.navigation.navigation import com.geeksville.mesh.ui.sharing.ChannelScreen import org.meshtastic.core.navigation.ChannelsRoutes import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI -import org.meshtastic.feature.settings.navigation.ConfigRoute +import org.meshtastic.core.navigation.SettingsRoutes import org.meshtastic.feature.settings.radio.channel.ChannelConfigScreen import org.meshtastic.feature.settings.radio.component.LoRaConfigScreen @@ -44,19 +44,13 @@ fun NavGraphBuilder.channelsGraph(navController: NavHostController) { onNavigateUp = { navController.navigateUp() }, ) } - configRoutes(navController) - } -} -private fun NavGraphBuilder.configRoutes(navController: NavHostController) { - ConfigRoute.entries.forEach { configRoute -> - composable(configRoute.route::class) { backStackEntry -> - val parentEntry = remember(backStackEntry) { navController.getBackStackEntry(ChannelsRoutes.ChannelsGraph) } - when (configRoute) { - 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 - } + navController.configComposable { + ChannelConfigScreen(viewModel = it, onBack = navController::popBackStack) + } + + navController.configComposable { + LoRaConfigScreen(viewModel = it, onBack = navController::popBackStack) } } } diff --git a/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt index 425905908..8c94d688e 100644 --- a/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt +++ b/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt @@ -29,7 +29,6 @@ import org.meshtastic.core.navigation.ConnectionsRoutes import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI import org.meshtastic.core.navigation.NodesRoutes import org.meshtastic.core.navigation.SettingsRoutes -import org.meshtastic.feature.settings.radio.RadioConfigViewModel import org.meshtastic.feature.settings.radio.component.LoRaConfigScreen /** Navigation graph for for the top level ConnectionsScreen - [ConnectionsRoutes.Connections]. */ @@ -55,14 +54,9 @@ fun NavGraphBuilder.connectionsGraph(navController: NavHostController) { onConfigNavigate = { route -> navController.navigate(route) }, ) } - configRoutes(navController) - } -} -private fun NavGraphBuilder.configRoutes(navController: NavHostController) { - composable { backStackEntry -> - val parentEntry = - remember(backStackEntry) { navController.getBackStackEntry(ConnectionsRoutes.ConnectionsGraph) } - LoRaConfigScreen(viewModel = hiltViewModel(parentEntry), navController::popBackStack) + navController.configComposable { + LoRaConfigScreen(viewModel = it, onBack = navController::popBackStack) + } } } diff --git a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt similarity index 84% rename from feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavigation.kt rename to app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt index f7d2d6530..cf2098ce4 100644 --- a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavigation.kt +++ b/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt @@ -15,8 +15,11 @@ * along with this program. If not, see . */ -package org.meshtastic.feature.settings.navigation +@file:Suppress("Wrapping", "SpacingAroundColon") +package com.geeksville.mesh.navigation + +import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.navigation.NavGraphBuilder @@ -25,11 +28,14 @@ import androidx.navigation.compose.composable import androidx.navigation.navDeepLink import androidx.navigation.navigation import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI +import org.meshtastic.core.navigation.Graph import org.meshtastic.core.navigation.NodesRoutes import org.meshtastic.core.navigation.Route import org.meshtastic.core.navigation.SettingsRoutes import org.meshtastic.feature.settings.SettingsScreen import org.meshtastic.feature.settings.debugging.DebugScreen +import org.meshtastic.feature.settings.navigation.ConfigRoute +import org.meshtastic.feature.settings.navigation.ModuleRoute import org.meshtastic.feature.settings.radio.CleanNodeDatabaseScreen import org.meshtastic.feature.settings.radio.RadioConfigViewModel import org.meshtastic.feature.settings.radio.channel.ChannelConfigScreen @@ -55,9 +61,7 @@ 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 - -fun getNavRouteFrom(routeName: String): Route? = - ConfigRoute.entries.find { it.name == routeName }?.route ?: ModuleRoute.entries.find { it.name == routeName }?.route +import kotlin.reflect.KClass @Suppress("LongMethod") fun NavGraphBuilder.settingsGraph(navController: NavHostController) { @@ -92,11 +96,10 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) { } ConfigRoute.entries.forEach { entry -> - composable(entry.route::class) { backStackEntry -> - val parentEntry = - remember(backStackEntry) { navController.getBackStackEntry(SettingsRoutes.SettingsGraph::class) } - val viewModel = hiltViewModel(parentEntry) - + navController.configComposable( + route = entry.route::class, + parentGraphRoute = SettingsRoutes.SettingsGraph::class, + ) { viewModel -> when (entry) { ConfigRoute.USER -> UserConfigScreen(viewModel, onBack = navController::popBackStack) @@ -122,11 +125,10 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) { } ModuleRoute.entries.forEach { entry -> - composable(entry.route::class) { backStackEntry -> - val parentEntry = - remember(backStackEntry) { navController.getBackStackEntry() } - val viewModel = hiltViewModel(parentEntry) - + navController.configComposable( + route = entry.route::class, + parentGraphRoute = SettingsRoutes.SettingsGraph::class, + ) { viewModel -> when (entry) { ModuleRoute.MQTT -> MQTTConfigScreen(viewModel, onBack = navController::popBackStack) @@ -172,3 +174,22 @@ fun NavGraphBuilder.settingsGraph(navController: NavHostController) { } } } + +context(_: NavGraphBuilder) +inline fun NavHostController.configComposable( + noinline content: @Composable (RadioConfigViewModel) -> Unit, +) { + configComposable(route = R::class, parentGraphRoute = G::class, content = content) +} + +context(navGraphBuilder: NavGraphBuilder) +fun NavHostController.configComposable( + route: KClass, + parentGraphRoute: KClass, + content: @Composable (RadioConfigViewModel) -> Unit, +) { + navGraphBuilder.composable(route = route) { backStackEntry -> + val parentEntry = remember(backStackEntry) { getBackStackEntry(parentGraphRoute) } + content(hiltViewModel(parentEntry)) + } +} diff --git a/app/src/main/java/com/geeksville/mesh/ui/Main.kt b/app/src/main/java/com/geeksville/mesh/ui/Main.kt index 856c6d63d..c28d2b2fc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Main.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Main.kt @@ -90,6 +90,7 @@ import com.geeksville.mesh.navigation.connectionsGraph import com.geeksville.mesh.navigation.contactsGraph import com.geeksville.mesh.navigation.mapGraph import com.geeksville.mesh.navigation.nodesGraph +import com.geeksville.mesh.navigation.settingsGraph import com.geeksville.mesh.repository.radio.MeshActivity import com.geeksville.mesh.service.MeshService import com.geeksville.mesh.ui.connections.DeviceType @@ -120,7 +121,6 @@ import org.meshtastic.core.ui.share.SharedContactDialog import org.meshtastic.core.ui.theme.StatusColors.StatusBlue import org.meshtastic.core.ui.theme.StatusColors.StatusGreen import org.meshtastic.feature.node.metrics.annotateTraceroute -import org.meshtastic.feature.settings.navigation.settingsGraph import org.meshtastic.proto.MeshProtos import timber.log.Timber diff --git a/feature/settings/detekt-baseline.xml b/feature/settings/detekt-baseline.xml index 8961b388d..809b837cf 100644 --- a/feature/settings/detekt-baseline.xml +++ b/feature/settings/detekt-baseline.xml @@ -12,7 +12,6 @@ CyclomaticComplexMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) CyclomaticComplexMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) CyclomaticComplexMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) - CyclomaticComplexMethod:SettingsNavigation.kt$@Suppress("LongMethod") fun NavGraphBuilder.settingsGraph(navController: NavHostController) LambdaParameterEventTrailing:NodeActionButton.kt$onClick LongMethod:AudioConfigItemList.kt$@Composable fun AudioConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) LongMethod:CannedMessageConfigItemList.kt$@Composable fun CannedMessageConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack: () -> Unit) @@ -36,6 +35,7 @@ MagicNumber:EditChannelDialog.kt$32 MagicNumber:PacketResponseStateDialog.kt$100 ModifierMissing:CleanNodeDatabaseScreen.kt$CleanNodeDatabaseScreen + ModifierMissing:Debug.kt$DebugScreen ModifierMissing:DeviceConfigItemList.kt$DeviceConfigScreen ModifierMissing:MapReportingPreference.kt$MapReportingPreference ModifierMissing:NetworkConfigItemList.kt$NetworkConfigScreen diff --git a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/Debug.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/Debug.kt index f2b7cd9ec..1f69872fb 100644 --- a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/Debug.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/Debug.kt @@ -103,7 +103,7 @@ private var redactedKeys: List = listOf("session_passkey", "private_key" @Suppress("LongMethod") @Composable -internal fun DebugScreen(onNavigateUp: () -> Unit, viewModel: DebugViewModel = hiltViewModel()) { +fun DebugScreen(onNavigateUp: () -> Unit, viewModel: DebugViewModel = hiltViewModel()) { val listState = rememberLazyListState() val logs by viewModel.meshLog.collectAsStateWithLifecycle() val searchState by viewModel.searchState.collectAsStateWithLifecycle() diff --git a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavUtils.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavUtils.kt new file mode 100644 index 000000000..59b533579 --- /dev/null +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavUtils.kt @@ -0,0 +1,23 @@ +/* + * 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 org.meshtastic.feature.settings.navigation + +import org.meshtastic.core.navigation.Route + +fun getNavRouteFrom(routeName: String): Route? = + ConfigRoute.entries.find { it.name == routeName }?.route ?: ModuleRoute.entries.find { it.name == routeName }?.route