refactor: move node detail logs to shared ViewModel

pull/1371/head
andrekir 2024-10-29 07:40:18 -03:00 zatwierdzone przez Andre K
rodzic e7b30597b7
commit b668a21b68
5 zmienionych plików z 57 dodań i 49 usunięć

Wyświetl plik

@ -38,6 +38,7 @@ import androidx.compose.material.icons.filled.Usb
import androidx.compose.material.icons.filled.Wifi import androidx.compose.material.icons.filled.Wifi
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
@ -129,20 +130,11 @@ class NavGraphFragment : ScreenFragment("NavGraph"), Logging {
AppCompatTheme { AppCompatTheme {
val navController: NavHostController = rememberNavController() 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( Scaffold(
topBar = { topBar = {
MeshAppBar( MeshAppBar(
currentScreen = node?.user?.longName currentScreen = node?.user?.longName
?: stringResource(R.string.unknown_username), ?: stringResource(R.string.unknown_username),
// canNavigateBack = navController.previousBackStackEntry != null,
// navigateUp = { navController.navigateUp() },
canNavigateBack = true, canNavigateBack = true,
navigateUp = { navigateUp = {
if (navController.previousBackStackEntry != null) { if (navController.previousBackStackEntry != null) {
@ -233,7 +225,7 @@ private fun MeshAppBar(
IconButton(onClick = navigateUp) { IconButton(onClick = navigateUp) {
Icon( Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack, 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 radioConfigState by viewModel.radioConfigState.collectAsStateWithLifecycle()
val isWaiting = radioConfigState.responseState.isWaiting() val isWaiting = radioConfigState.responseState.isWaiting()
val metricsViewModel: MetricsViewModel = hiltViewModel()
val metricsState by metricsViewModel.state.collectAsStateWithLifecycle()
if (isWaiting) { if (isWaiting) {
PacketResponseStateDialog( PacketResponseStateDialog(
state = radioConfigState.responseState, state = radioConfigState.responseState,
@ -282,27 +271,25 @@ fun NavGraph(
modifier = modifier, modifier = modifier,
) { ) {
composable("NodeDetails") { composable("NodeDetails") {
NodeDetailsScreen( NodeDetailScreen(
node = node, node = node,
metricsState = metricsState, ) { navController.navigate(route = it) }
onNavigate = { navController.navigate(route = it) },
setSelectedNode = metricsViewModel::setSelectedNode,
)
} }
composable("DeviceMetrics") { composable("DeviceMetrics") {
DeviceMetricsScreen(metricsState.deviceMetrics) val parentEntry = remember { navController.getBackStackEntry("NodeDetails") }
DeviceMetricsScreen(hiltViewModel<MetricsViewModel>(parentEntry))
} }
composable("EnvironmentMetrics") { composable("EnvironmentMetrics") {
EnvironmentMetricsScreen( val parentEntry = remember { navController.getBackStackEntry("NodeDetails") }
metricsState.environmentMetrics, EnvironmentMetricsScreen(hiltViewModel<MetricsViewModel>(parentEntry))
metricsState.environmentDisplayFahrenheit,
)
}
composable("TracerouteList") {
TracerouteLogScreen(metricsViewModel)
} }
composable("SignalMetrics") { composable("SignalMetrics") {
SignalMetricsScreen(metricsState.signalMetrics) val parentEntry = remember { navController.getBackStackEntry("NodeDetails") }
SignalMetricsScreen(hiltViewModel<MetricsViewModel>(parentEntry))
}
composable("TracerouteList") {
val parentEntry = remember { navController.getBackStackEntry("NodeDetails") }
TracerouteLogScreen(hiltViewModel<MetricsViewModel>(parentEntry))
} }
composable("RadioConfig") { composable("RadioConfig") {
RadioConfigScreen( RadioConfigScreen(

Wyświetl plik

@ -46,6 +46,7 @@ import androidx.compose.material.icons.filled.WaterDrop
import androidx.compose.material.icons.filled.Work import androidx.compose.material.icons.filled.Work
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color 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.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp 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.R
import com.geeksville.mesh.database.entity.NodeEntity import com.geeksville.mesh.database.entity.NodeEntity
import com.geeksville.mesh.model.MetricsState import com.geeksville.mesh.model.MetricsState
import com.geeksville.mesh.model.MetricsViewModel
import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.PreferenceCategory
import com.geeksville.mesh.ui.preview.NodeEntityPreviewParameterProvider import com.geeksville.mesh.ui.preview.NodeEntityPreviewParameterProvider
import com.geeksville.mesh.ui.theme.AppTheme import com.geeksville.mesh.ui.theme.AppTheme
@ -67,21 +71,21 @@ import java.util.concurrent.TimeUnit
import kotlin.math.ln import kotlin.math.ln
@Composable @Composable
fun NodeDetailsScreen( fun NodeDetailScreen(
node: NodeEntity?, node: NodeEntity?,
metricsState: MetricsState, viewModel: MetricsViewModel = hiltViewModel(),
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onNavigate: (String) -> Unit, onNavigate: (String) -> Unit,
setSelectedNode: (Int) -> Unit,
) { ) {
val state by viewModel.state.collectAsStateWithLifecycle()
if (node != null) { if (node != null) {
LaunchedEffect(node.num) { LaunchedEffect(node.num) {
setSelectedNode(node.num) viewModel.setSelectedNode(node.num)
} }
NodeDetailList(
NodeDetailsItemList(
node = node, node = node,
metricsState = metricsState, metricsState = state,
onNavigate = onNavigate, onNavigate = onNavigate,
modifier = modifier, modifier = modifier,
) )
@ -97,7 +101,7 @@ fun NodeDetailsScreen(
@Suppress("LongMethod") @Suppress("LongMethod")
@Composable @Composable
private fun NodeDetailsItemList( private fun NodeDetailList(
node: NodeEntity, node: NodeEntity,
metricsState: MetricsState, metricsState: MetricsState,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -453,6 +457,6 @@ private fun NodeDetailsPreview(
node: NodeEntity node: NodeEntity
) { ) {
AppTheme { AppTheme {
NodeDetailsItemList(node, MetricsState.Empty) NodeDetailList(node, MetricsState.Empty)
} }
} }

Wyświetl plik

@ -34,8 +34,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp 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.R
import com.geeksville.mesh.TelemetryProtos.Telemetry import com.geeksville.mesh.TelemetryProtos.Telemetry
import com.geeksville.mesh.model.MetricsViewModel
import com.geeksville.mesh.ui.BatteryInfo import com.geeksville.mesh.ui.BatteryInfo
import com.geeksville.mesh.ui.components.CommonCharts.X_AXIS_SPACING 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.MS_PER_SEC
@ -56,8 +59,10 @@ private val LEGEND_DATA = listOf(
) )
@Composable @Composable
fun DeviceMetricsScreen(telemetries: List<Telemetry>) { fun DeviceMetricsScreen(
viewModel: MetricsViewModel = hiltViewModel(),
) {
val state by viewModel.state.collectAsStateWithLifecycle()
var displayInfoDialog by remember { mutableStateOf(false) } var displayInfoDialog by remember { mutableStateOf(false) }
Column { Column {
@ -76,14 +81,14 @@ fun DeviceMetricsScreen(telemetries: List<Telemetry>) {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight(fraction = 0.33f), .fillMaxHeight(fraction = 0.33f),
telemetries.reversed(), state.deviceMetrics.reversed(),
promptInfoDialog = { displayInfoDialog = true } promptInfoDialog = { displayInfoDialog = true }
) )
/* Device Metric Cards */ /* Device Metric Cards */
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {
items(telemetries) { telemetry -> DeviceMetricsCard(telemetry) } items(state.deviceMetrics) { telemetry -> DeviceMetricsCard(telemetry) }
} }
} }
} }

Wyświetl plik

@ -37,9 +37,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp 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.R
import com.geeksville.mesh.TelemetryProtos.Telemetry import com.geeksville.mesh.TelemetryProtos.Telemetry
import com.geeksville.mesh.copy 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.X_AXIS_SPACING
import com.geeksville.mesh.ui.components.CommonCharts.MS_PER_SEC import com.geeksville.mesh.ui.components.CommonCharts.MS_PER_SEC
import com.geeksville.mesh.ui.components.CommonCharts.TIME_FORMAT import com.geeksville.mesh.ui.components.CommonCharts.TIME_FORMAT
@ -69,15 +72,19 @@ private val LEGEND_DATA = listOf(
) )
@Composable @Composable
fun EnvironmentMetricsScreen(telemetries: List<Telemetry>, environmentDisplayFahrenheit: Boolean) { fun EnvironmentMetricsScreen(
viewModel: MetricsViewModel = hiltViewModel(),
) {
val state by viewModel.state.collectAsStateWithLifecycle()
/* Convert Celsius to Fahrenheit */ /* Convert Celsius to Fahrenheit */
@Suppress("MagicNumber") @Suppress("MagicNumber")
fun celsiusToFahrenheit(celsius: Float): Float { fun celsiusToFahrenheit(celsius: Float): Float {
return (celsius * 1.8F) + 32 return (celsius * 1.8F) + 32
} }
val processedTelemetries: List<Telemetry> = if (environmentDisplayFahrenheit) { val processedTelemetries: List<Telemetry> = if (state.environmentDisplayFahrenheit) {
telemetries.map { telemetry -> state.environmentMetrics.map { telemetry ->
val temperatureFahrenheit = val temperatureFahrenheit =
celsiusToFahrenheit(telemetry.environmentMetrics.temperature) celsiusToFahrenheit(telemetry.environmentMetrics.temperature)
telemetry.copy { telemetry.copy {
@ -86,7 +93,7 @@ fun EnvironmentMetricsScreen(telemetries: List<Telemetry>, environmentDisplayFah
} }
} }
} else { } else {
telemetries state.environmentMetrics
} }
var displayInfoDialog by remember { mutableStateOf(false) } var displayInfoDialog by remember { mutableStateOf(false) }
@ -117,7 +124,7 @@ fun EnvironmentMetricsScreen(telemetries: List<Telemetry>, environmentDisplayFah
items(processedTelemetries) { telemetry -> items(processedTelemetries) { telemetry ->
EnvironmentMetricsCard( EnvironmentMetricsCard(
telemetry, telemetry,
environmentDisplayFahrenheit state.environmentDisplayFahrenheit
) )
} }
} }

Wyświetl plik

@ -36,8 +36,11 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp 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.MeshProtos.MeshPacket
import com.geeksville.mesh.R 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.MS_PER_SEC
import com.geeksville.mesh.ui.components.CommonCharts.LINE_LIMIT import com.geeksville.mesh.ui.components.CommonCharts.LINE_LIMIT
import com.geeksville.mesh.ui.components.CommonCharts.TEXT_PAINT_ALPHA import com.geeksville.mesh.ui.components.CommonCharts.TEXT_PAINT_ALPHA
@ -61,8 +64,10 @@ private val LEGEND_DATA = listOf(
) )
@Composable @Composable
fun SignalMetricsScreen(meshPackets: List<MeshPacket>) { fun SignalMetricsScreen(
viewModel: MetricsViewModel = hiltViewModel(),
) {
val state by viewModel.state.collectAsStateWithLifecycle()
var displayInfoDialog by remember { mutableStateOf(false) } var displayInfoDialog by remember { mutableStateOf(false) }
Column { Column {
@ -81,14 +86,14 @@ fun SignalMetricsScreen(meshPackets: List<MeshPacket>) {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight(fraction = 0.33f), .fillMaxHeight(fraction = 0.33f),
meshPackets = meshPackets.reversed(), meshPackets = state.signalMetrics.reversed(),
promptInfoDialog = { displayInfoDialog = true } promptInfoDialog = { displayInfoDialog = true }
) )
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {
items(meshPackets) { meshPacket -> SignalMetricsCard(meshPacket) } items(state.signalMetrics) { meshPacket -> SignalMetricsCard(meshPacket) }
} }
} }
} }