feat: add Host Metrics Log screen (#1969)

This commit is contained in:
James Rich 2025-05-28 15:57:38 -05:00 committed by GitHub
parent ef1c71722a
commit e31d4170b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 388 additions and 208 deletions

View file

@ -35,8 +35,6 @@
package com.geeksville.mesh.navigation
import androidx.annotation.StringRes
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
@ -204,6 +202,9 @@ sealed interface Route {
@Serializable
data object TracerouteLog : Route
@Serializable
data object HostMetricsLog : Route
}
fun NavDestination.isConfigRoute(): Boolean {
@ -225,7 +226,6 @@ fun NavDestination.showLongNameTitle(): Boolean {
)
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Suppress("LongMethod")
@Composable
fun NavGraph(
@ -233,98 +233,95 @@ fun NavGraph(
uIViewModel: UIViewModel = hiltViewModel(),
navController: NavHostController = rememberNavController(),
) {
SharedTransitionLayout {
NavHost(
navController = navController,
startDestination = if (uIViewModel.bondedAddress.isNullOrBlank()) {
Route.Settings
} else {
Route.Contacts
},
modifier = modifier,
) {
composable<Route.Contacts> {
ContactsScreen(
uIViewModel,
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)
}
composable<Route.Channels> {
ChannelScreen(uIViewModel)
}
composable<Route.Settings>(
deepLinks = listOf(
navDeepLink {
uriPattern = "$DEEP_LINK_BASE_URI/settings"
action = "android.intent.action.VIEW"
}
)
) { backStackEntry ->
SettingsScreen(
uIViewModel,
onNavigateToRadioConfig = {
navController.navigate(Route.RadioConfig()) {
popUpTo(Route.Settings) {
inclusive = false
}
}
},
onNavigateToNodeDetails = { navController.navigate(Route.NodeDetail(it)) }
)
}
composable<Route.DebugPanel> {
DebugScreen()
}
composable<Route.Messages>(
deepLinks = listOf(
navDeepLink {
uriPattern = "$DEEP_LINK_BASE_URI/messages/{contactKey}?message={message}"
action = "android.intent.action.VIEW"
},
)
) { backStackEntry ->
val args = backStackEntry.toRoute<Route.Messages>()
MessageScreen(
contactKey = args.contactKey,
message = args.message,
viewModel = uIViewModel,
navigateToMessages = { navController.navigate(Route.Messages(it)) },
navigateToNodeDetails = { navController.navigate(Route.NodeDetail(it)) },
onNavigateBack = navController::navigateUp,
)
}
composable<Route.QuickChat> {
QuickChatScreen()
}
nodeDetailGraph(
navController,
NavHost(
navController = navController,
startDestination = if (uIViewModel.bondedAddress.isNullOrBlank()) {
Route.Settings
} else {
Route.Contacts
},
modifier = modifier,
) {
composable<Route.Contacts> {
ContactsScreen(
uIViewModel,
sharedTransitionScope = this@SharedTransitionLayout
onNavigate = { navController.navigate(Route.Messages(it)) }
)
radioConfigGraph(navController, uIViewModel)
composable<Route.Share>(
deepLinks = listOf(
navDeepLink {
uriPattern = "$DEEP_LINK_BASE_URI/share?message={message}"
action = "android.intent.action.VIEW"
}
)
) { backStackEntry ->
val message = backStackEntry.toRoute<Route.Share>().message
ShareScreen(uIViewModel) {
navController.navigate(Route.Messages(it, message)) {
popUpTo<Route.Share> { inclusive = true }
}
composable<Route.Nodes> {
NodeScreen(
model = uIViewModel,
navigateToMessages = { navController.navigate(Route.Messages(it)) },
navigateToNodeDetails = { navController.navigate(Route.NodeDetail(it)) },
)
}
composable<Route.Map> {
MapView(uIViewModel)
}
composable<Route.Channels> {
ChannelScreen(uIViewModel)
}
composable<Route.Settings>(
deepLinks = listOf(
navDeepLink {
uriPattern = "$DEEP_LINK_BASE_URI/settings"
action = "android.intent.action.VIEW"
}
)
) { backStackEntry ->
SettingsScreen(
uIViewModel,
onNavigateToRadioConfig = {
navController.navigate(Route.RadioConfig()) {
popUpTo(Route.Settings) {
inclusive = false
}
}
},
onNavigateToNodeDetails = { navController.navigate(Route.NodeDetail(it)) }
)
}
composable<Route.DebugPanel> {
DebugScreen()
}
composable<Route.Messages>(
deepLinks = listOf(
navDeepLink {
uriPattern = "$DEEP_LINK_BASE_URI/messages/{contactKey}?message={message}"
action = "android.intent.action.VIEW"
},
)
) { backStackEntry ->
val args = backStackEntry.toRoute<Route.Messages>()
MessageScreen(
contactKey = args.contactKey,
message = args.message,
viewModel = uIViewModel,
navigateToMessages = { navController.navigate(Route.Messages(it)) },
navigateToNodeDetails = { navController.navigate(Route.NodeDetail(it)) },
onNavigateBack = navController::navigateUp,
)
}
composable<Route.QuickChat> {
QuickChatScreen()
}
nodeDetailGraph(
navController,
uIViewModel,
)
radioConfigGraph(navController, uIViewModel)
composable<Route.Share>(
deepLinks = listOf(
navDeepLink {
uriPattern = "$DEEP_LINK_BASE_URI/share?message={message}"
action = "android.intent.action.VIEW"
}
)
) { backStackEntry ->
val message = backStackEntry.toRoute<Route.Share>().message
ShareScreen(uIViewModel) {
navController.navigate(Route.Messages(it, message)) {
popUpTo<Route.Share> { inclusive = true }
}
}
}

View file

@ -18,12 +18,11 @@
package com.geeksville.mesh.navigation
import androidx.annotation.StringRes
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionScope
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CellTower
import androidx.compose.material.icons.filled.LightMode
import androidx.compose.material.icons.filled.LocationOn
import androidx.compose.material.icons.filled.Memory
import androidx.compose.material.icons.filled.PermScanWifi
import androidx.compose.material.icons.filled.Power
import androidx.compose.material.icons.filled.Router
@ -39,17 +38,16 @@ import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.ui.NodeDetailScreen
import com.geeksville.mesh.ui.components.DeviceMetricsScreen
import com.geeksville.mesh.ui.components.EnvironmentMetricsScreen
import com.geeksville.mesh.ui.components.HostMetricsLogScreen
import com.geeksville.mesh.ui.components.NodeMapScreen
import com.geeksville.mesh.ui.components.PositionLogScreen
import com.geeksville.mesh.ui.components.PowerMetricsScreen
import com.geeksville.mesh.ui.components.SignalMetricsScreen
import com.geeksville.mesh.ui.components.TracerouteLogScreen
@OptIn(ExperimentalSharedTransitionApi::class)
fun NavGraphBuilder.nodeDetailGraph(
navController: NavHostController,
uiViewModel: UIViewModel,
sharedTransitionScope: SharedTransitionScope,
) {
navigation<Graph.NodeDetailGraph>(
startDestination = Route.NodeDetail(),
@ -61,8 +59,6 @@ fun NavGraphBuilder.nodeDetailGraph(
NodeDetailScreen(
uiViewModel = uiViewModel,
viewModel = hiltViewModel(parentEntry),
sharedTransitionScope = sharedTransitionScope,
animatedContentScope = this@composable,
) {
navController.navigate(it) {
popUpTo(Route.NodeDetail()) {
@ -89,6 +85,7 @@ fun NavGraphBuilder.nodeDetailGraph(
NodeDetailRoute.SIGNAL -> SignalMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.TRACEROUTE -> TracerouteLogScreen(hiltViewModel(parentEntry))
NodeDetailRoute.POWER -> PowerMetricsScreen(hiltViewModel(parentEntry))
NodeDetailRoute.HOST -> HostMetricsLogScreen(hiltViewModel(parentEntry))
}
}
}
@ -107,4 +104,5 @@ enum class NodeDetailRoute(
SIGNAL(R.string.signal, Route.SignalMetrics, Icons.Default.CellTower),
TRACEROUTE(R.string.traceroute, Route.TracerouteLog, Icons.Default.PermScanWifi),
POWER(R.string.power, Route.PowerMetrics, Icons.Default.Power),
HOST(R.string.host, Route.HostMetricsLog, Icons.Default.Memory),
}