fix: refactor node detail navigation (#2009)

resolves #2004
This commit is contained in:
James Rich
2025-06-03 15:19:50 -05:00
committed by GitHub
parent 3115bbe58d
commit ff5cc55a60
3 changed files with 65 additions and 57 deletions

View File

@@ -37,7 +37,6 @@ import com.geeksville.mesh.ui.debug.DebugScreen
import com.geeksville.mesh.ui.map.MapView
import com.geeksville.mesh.ui.message.MessageScreen
import com.geeksville.mesh.ui.message.QuickChatScreen
import com.geeksville.mesh.ui.node.NodeScreen
import com.geeksville.mesh.ui.sharing.ShareScreen
import kotlinx.serialization.Serializable
@@ -52,9 +51,6 @@ const val DEEP_LINK_BASE_URI = "meshtastic://meshtastic"
@Serializable
sealed interface Graph : Route {
@Serializable
data class NodeDetailGraph(val destNum: Int) : Graph
@Serializable
data class RadioConfigGraph(val destNum: Int? = null) : Graph
}
@@ -64,9 +60,6 @@ sealed interface Route {
@Serializable
data object Contacts : Route
@Serializable
data object Nodes : Route
@Serializable
data object Map : Route
@@ -223,13 +216,6 @@ fun NavGraph(
onNavigate = { navController.navigate(Route.Messages(it)) }
)
}
composable<Route.Nodes> {
NodeScreen(
model = uIViewModel,
navigateToMessages = { navController.navigate(Route.Messages(it)) },
navigateToNodeDetails = { navController.navigate(Route.NodeDetail(it)) },
)
}
composable<Route.Map> {
MapView(uIViewModel)
}
@@ -262,7 +248,7 @@ fun NavGraph(
composable<Route.QuickChat> {
QuickChatScreen()
}
nodeDetailGraph(
nodesGraph(
navController,
uIViewModel,
)

View File

@@ -32,7 +32,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.navigation
import androidx.navigation.compose.navigation
import com.geeksville.mesh.R
import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.ui.metrics.DeviceMetricsScreen
@@ -44,57 +44,78 @@ import com.geeksville.mesh.ui.metrics.SignalMetricsScreen
import com.geeksville.mesh.ui.metrics.TracerouteLogScreen
import com.geeksville.mesh.ui.node.NodeDetailScreen
import com.geeksville.mesh.ui.node.NodeMapScreen
import com.geeksville.mesh.ui.node.NodeScreen
import kotlinx.serialization.Serializable
fun NavGraphBuilder.nodeDetailGraph(
sealed class NodesRoutes {
@Serializable
data object Nodes : Route
@Serializable
data object NodesGraph : Graph
}
fun NavGraphBuilder.nodesGraph(
navController: NavHostController,
uiViewModel: UIViewModel,
) {
navigation<Graph.NodeDetailGraph>(
startDestination = Route.NodeDetail(),
navigation<NodesRoutes.NodesGraph>(
startDestination = NodesRoutes.Nodes,
) {
composable<Route.NodeDetail> { backStackEntry ->
val parentEntry = remember(backStackEntry) {
navController.getBackStackEntry<Graph.NodeDetailGraph>()
}
NodeDetailScreen(
uiViewModel = uiViewModel,
composable<NodesRoutes.Nodes> {
NodeScreen(
model = uiViewModel,
navigateToMessages = {
navController.navigate(Route.Messages(it)) {
popUpTo(Route.NodeDetail()) {
inclusive = false
}
}
navController.navigate(Route.Messages(it))
},
onNavigate = {
navController.navigate(it) {
popUpTo(Route.NodeDetail()) {
inclusive = false
}
}
navigateToNodeDetails = {
navController.navigate(Route.NodeDetail(it))
},
viewModel = hiltViewModel(parentEntry),
)
}
NodeDetailRoute.entries.forEach { nodeDetailRoute ->
composable(nodeDetailRoute.route::class) { backStackEntry ->
val parentEntry = remember(backStackEntry) {
navController.getBackStackEntry<Graph.NodeDetailGraph>()
}
when (nodeDetailRoute) {
NodeDetailRoute.DEVICE -> DeviceMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.NODE_MAP -> NodeMapScreen(hiltViewModel(parentEntry))
NodeDetailRoute.POSITION_LOG -> PositionLogScreen(hiltViewModel(parentEntry))
NodeDetailRoute.ENVIRONMENT -> EnvironmentMetricsScreen(
hiltViewModel(
parentEntry
)
)
nodeDetailRoutes(navController, uiViewModel)
}
}
NodeDetailRoute.SIGNAL -> SignalMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.TRACEROUTE -> TracerouteLogScreen(viewModel = hiltViewModel(parentEntry))
NodeDetailRoute.POWER -> PowerMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.HOST -> HostMetricsLogScreen(hiltViewModel(parentEntry))
}
fun NavGraphBuilder.nodeDetailRoutes(
navController: NavHostController,
uiViewModel: UIViewModel,
) {
composable<Route.NodeDetail> {
NodeDetailScreen(
uiViewModel = uiViewModel,
navigateToMessages = {
navController.navigate(Route.Messages(it))
},
onNavigate = {
navController.navigate(it)
},
viewModel = hiltViewModel(),
)
}
NodeDetailRoute.entries.forEach { nodeDetailRoute ->
composable(nodeDetailRoute.route::class) { backStackEntry ->
val parentEntry = remember(backStackEntry) {
navController.getBackStackEntry<NodesRoutes.NodesGraph>()
}
when (nodeDetailRoute) {
NodeDetailRoute.DEVICE -> DeviceMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.NODE_MAP -> NodeMapScreen(hiltViewModel(parentEntry))
NodeDetailRoute.POSITION_LOG -> PositionLogScreen(hiltViewModel(parentEntry))
NodeDetailRoute.ENVIRONMENT -> EnvironmentMetricsScreen(
hiltViewModel(
parentEntry
)
)
NodeDetailRoute.SIGNAL -> SignalMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.TRACEROUTE -> TracerouteLogScreen(
viewModel = hiltViewModel(
parentEntry
)
)
NodeDetailRoute.POWER -> PowerMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.HOST -> HostMetricsLogScreen(hiltViewModel(parentEntry))
}
}
}

View File

@@ -77,6 +77,7 @@ import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.navigation.ChannelsRoutes
import com.geeksville.mesh.navigation.ConnectionsRoutes
import com.geeksville.mesh.navigation.NavGraph
import com.geeksville.mesh.navigation.NodesRoutes
import com.geeksville.mesh.navigation.Route
import com.geeksville.mesh.navigation.showLongNameTitle
import com.geeksville.mesh.service.MeshService
@@ -88,7 +89,7 @@ import com.geeksville.mesh.ui.debug.DebugMenuActions
enum class TopLevelDestination(@StringRes val label: Int, val icon: ImageVector, val route: Route) {
Contacts(R.string.contacts, Icons.AutoMirrored.TwoTone.Chat, Route.Contacts),
Nodes(R.string.nodes, Icons.TwoTone.People, Route.Nodes),
Nodes(R.string.nodes, Icons.TwoTone.People, NodesRoutes.Nodes),
Map(R.string.map, Icons.TwoTone.Map, Route.Map),
Channels(R.string.channels, Icons.TwoTone.Contactless, ChannelsRoutes.Channels),
Connections(R.string.connections, Icons.TwoTone.CloudOff, ConnectionsRoutes.Connections),