From b668a21b68465c13d15ca224df785c86ebe4f3ad Mon Sep 17 00:00:00 2001 From: andrekir Date: Tue, 29 Oct 2024 07:40:18 -0300 Subject: [PATCH] refactor: move node detail logs to shared ViewModel --- .../java/com/geeksville/mesh/ui/NavGraph.kt | 41 +++++++------------ .../{NodeDetailsScreen.kt => NodeDetail.kt} | 22 ++++++---- .../mesh/ui/components/DeviceMetrics.kt | 13 ++++-- .../mesh/ui/components/EnvironmentMetrics.kt | 17 +++++--- .../mesh/ui/components/SignalMetrics.kt | 13 ++++-- 5 files changed, 57 insertions(+), 49 deletions(-) rename app/src/main/java/com/geeksville/mesh/ui/{NodeDetailsScreen.kt => NodeDetail.kt} (96%) 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 d209edd90..f8dc899db 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/NavGraph.kt @@ -38,6 +38,7 @@ 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 @@ -129,20 +130,11 @@ class NavGraphFragment : ScreenFragment("NavGraph"), Logging { AppCompatTheme { val navController: NavHostController = rememberNavController() - // Get current back stack entry - // val backStackEntry by navController.currentBackStackEntryAsState() - // Get the name of the current screen - // val currentScreen = backStackEntry?.destination?.route?.let { route -> - // NavRoute.entries.find { it.name == route }?.title - // } - Scaffold( topBar = { MeshAppBar( currentScreen = node?.user?.longName ?: stringResource(R.string.unknown_username), - // canNavigateBack = navController.previousBackStackEntry != null, - // navigateUp = { navController.navigateUp() }, canNavigateBack = true, navigateUp = { if (navController.previousBackStackEntry != null) { @@ -233,7 +225,7 @@ private fun MeshAppBar( IconButton(onClick = navigateUp) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, - null, + contentDescription = stringResource(id = R.string.navigate_back), ) } } @@ -256,9 +248,6 @@ fun NavGraph( val radioConfigState by viewModel.radioConfigState.collectAsStateWithLifecycle() val isWaiting = radioConfigState.responseState.isWaiting() - val metricsViewModel: MetricsViewModel = hiltViewModel() - val metricsState by metricsViewModel.state.collectAsStateWithLifecycle() - if (isWaiting) { PacketResponseStateDialog( state = radioConfigState.responseState, @@ -282,27 +271,25 @@ fun NavGraph( modifier = modifier, ) { composable("NodeDetails") { - NodeDetailsScreen( + NodeDetailScreen( node = node, - metricsState = metricsState, - onNavigate = { navController.navigate(route = it) }, - setSelectedNode = metricsViewModel::setSelectedNode, - ) + ) { navController.navigate(route = it) } } composable("DeviceMetrics") { - DeviceMetricsScreen(metricsState.deviceMetrics) + val parentEntry = remember { navController.getBackStackEntry("NodeDetails") } + DeviceMetricsScreen(hiltViewModel(parentEntry)) } composable("EnvironmentMetrics") { - EnvironmentMetricsScreen( - metricsState.environmentMetrics, - metricsState.environmentDisplayFahrenheit, - ) - } - composable("TracerouteList") { - TracerouteLogScreen(metricsViewModel) + val parentEntry = remember { navController.getBackStackEntry("NodeDetails") } + EnvironmentMetricsScreen(hiltViewModel(parentEntry)) } composable("SignalMetrics") { - SignalMetricsScreen(metricsState.signalMetrics) + val parentEntry = remember { navController.getBackStackEntry("NodeDetails") } + SignalMetricsScreen(hiltViewModel(parentEntry)) + } + composable("TracerouteList") { + val parentEntry = remember { navController.getBackStackEntry("NodeDetails") } + TracerouteLogScreen(hiltViewModel(parentEntry)) } composable("RadioConfig") { RadioConfigScreen( diff --git a/app/src/main/java/com/geeksville/mesh/ui/NodeDetailsScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt similarity index 96% rename from app/src/main/java/com/geeksville/mesh/ui/NodeDetailsScreen.kt rename to app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt index a4256d99a..2abb9db04 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/NodeDetailsScreen.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt @@ -46,6 +46,7 @@ import androidx.compose.material.icons.filled.WaterDrop import androidx.compose.material.icons.filled.Work import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -56,9 +57,12 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.R import com.geeksville.mesh.database.entity.NodeEntity import com.geeksville.mesh.model.MetricsState +import com.geeksville.mesh.model.MetricsViewModel import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.preview.NodeEntityPreviewParameterProvider import com.geeksville.mesh.ui.theme.AppTheme @@ -67,21 +71,21 @@ import java.util.concurrent.TimeUnit import kotlin.math.ln @Composable -fun NodeDetailsScreen( +fun NodeDetailScreen( node: NodeEntity?, - metricsState: MetricsState, + viewModel: MetricsViewModel = hiltViewModel(), modifier: Modifier = Modifier, onNavigate: (String) -> Unit, - setSelectedNode: (Int) -> Unit, ) { + val state by viewModel.state.collectAsStateWithLifecycle() + if (node != null) { LaunchedEffect(node.num) { - setSelectedNode(node.num) + viewModel.setSelectedNode(node.num) } - - NodeDetailsItemList( + NodeDetailList( node = node, - metricsState = metricsState, + metricsState = state, onNavigate = onNavigate, modifier = modifier, ) @@ -97,7 +101,7 @@ fun NodeDetailsScreen( @Suppress("LongMethod") @Composable -private fun NodeDetailsItemList( +private fun NodeDetailList( node: NodeEntity, metricsState: MetricsState, modifier: Modifier = Modifier, @@ -453,6 +457,6 @@ private fun NodeDetailsPreview( node: NodeEntity ) { AppTheme { - NodeDetailsItemList(node, MetricsState.Empty) + NodeDetailList(node, MetricsState.Empty) } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/DeviceMetrics.kt b/app/src/main/java/com/geeksville/mesh/ui/components/DeviceMetrics.kt index f1aed3412..004d06581 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/DeviceMetrics.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/DeviceMetrics.kt @@ -34,8 +34,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.R import com.geeksville.mesh.TelemetryProtos.Telemetry +import com.geeksville.mesh.model.MetricsViewModel import com.geeksville.mesh.ui.BatteryInfo import com.geeksville.mesh.ui.components.CommonCharts.X_AXIS_SPACING import com.geeksville.mesh.ui.components.CommonCharts.MS_PER_SEC @@ -56,8 +59,10 @@ private val LEGEND_DATA = listOf( ) @Composable -fun DeviceMetricsScreen(telemetries: List) { - +fun DeviceMetricsScreen( + viewModel: MetricsViewModel = hiltViewModel(), +) { + val state by viewModel.state.collectAsStateWithLifecycle() var displayInfoDialog by remember { mutableStateOf(false) } Column { @@ -76,14 +81,14 @@ fun DeviceMetricsScreen(telemetries: List) { modifier = Modifier .fillMaxWidth() .fillMaxHeight(fraction = 0.33f), - telemetries.reversed(), + state.deviceMetrics.reversed(), promptInfoDialog = { displayInfoDialog = true } ) /* Device Metric Cards */ LazyColumn( modifier = Modifier.fillMaxSize() ) { - items(telemetries) { telemetry -> DeviceMetricsCard(telemetry) } + items(state.deviceMetrics) { telemetry -> DeviceMetricsCard(telemetry) } } } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/EnvironmentMetrics.kt b/app/src/main/java/com/geeksville/mesh/ui/components/EnvironmentMetrics.kt index 840dafcd7..3204f9446 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/EnvironmentMetrics.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/EnvironmentMetrics.kt @@ -37,9 +37,12 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.R import com.geeksville.mesh.TelemetryProtos.Telemetry import com.geeksville.mesh.copy +import com.geeksville.mesh.model.MetricsViewModel import com.geeksville.mesh.ui.components.CommonCharts.X_AXIS_SPACING import com.geeksville.mesh.ui.components.CommonCharts.MS_PER_SEC import com.geeksville.mesh.ui.components.CommonCharts.TIME_FORMAT @@ -69,15 +72,19 @@ private val LEGEND_DATA = listOf( ) @Composable -fun EnvironmentMetricsScreen(telemetries: List, environmentDisplayFahrenheit: Boolean) { +fun EnvironmentMetricsScreen( + viewModel: MetricsViewModel = hiltViewModel(), +) { + val state by viewModel.state.collectAsStateWithLifecycle() + /* Convert Celsius to Fahrenheit */ @Suppress("MagicNumber") fun celsiusToFahrenheit(celsius: Float): Float { return (celsius * 1.8F) + 32 } - val processedTelemetries: List = if (environmentDisplayFahrenheit) { - telemetries.map { telemetry -> + val processedTelemetries: List = if (state.environmentDisplayFahrenheit) { + state.environmentMetrics.map { telemetry -> val temperatureFahrenheit = celsiusToFahrenheit(telemetry.environmentMetrics.temperature) telemetry.copy { @@ -86,7 +93,7 @@ fun EnvironmentMetricsScreen(telemetries: List, environmentDisplayFah } } } else { - telemetries + state.environmentMetrics } var displayInfoDialog by remember { mutableStateOf(false) } @@ -117,7 +124,7 @@ fun EnvironmentMetricsScreen(telemetries: List, environmentDisplayFah items(processedTelemetries) { telemetry -> EnvironmentMetricsCard( telemetry, - environmentDisplayFahrenheit + state.environmentDisplayFahrenheit ) } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/SignalMetrics.kt b/app/src/main/java/com/geeksville/mesh/ui/components/SignalMetrics.kt index bc3b3d547..f1972676f 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/SignalMetrics.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/SignalMetrics.kt @@ -36,8 +36,11 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.MeshProtos.MeshPacket import com.geeksville.mesh.R +import com.geeksville.mesh.model.MetricsViewModel import com.geeksville.mesh.ui.components.CommonCharts.MS_PER_SEC import com.geeksville.mesh.ui.components.CommonCharts.LINE_LIMIT import com.geeksville.mesh.ui.components.CommonCharts.TEXT_PAINT_ALPHA @@ -61,8 +64,10 @@ private val LEGEND_DATA = listOf( ) @Composable -fun SignalMetricsScreen(meshPackets: List) { - +fun SignalMetricsScreen( + viewModel: MetricsViewModel = hiltViewModel(), +) { + val state by viewModel.state.collectAsStateWithLifecycle() var displayInfoDialog by remember { mutableStateOf(false) } Column { @@ -81,14 +86,14 @@ fun SignalMetricsScreen(meshPackets: List) { modifier = Modifier .fillMaxWidth() .fillMaxHeight(fraction = 0.33f), - meshPackets = meshPackets.reversed(), + meshPackets = state.signalMetrics.reversed(), promptInfoDialog = { displayInfoDialog = true } ) LazyColumn( modifier = Modifier.fillMaxSize() ) { - items(meshPackets) { meshPacket -> SignalMetricsCard(meshPacket) } + items(state.signalMetrics) { meshPacket -> SignalMetricsCard(meshPacket) } } } }