mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Refactor NodeDetails to Metrics (#1222)
* Synced the string used for ChUtil and AirUtilTX in the NodeInfo and Device Metrics. * Refactored NodeDetails to Metrics. * Added string resources for "Hops Away".
This commit is contained in:
parent
d788195340
commit
2c426d470c
7 changed files with 51 additions and 50 deletions
|
|
@ -16,27 +16,27 @@ import kotlinx.coroutines.launch
|
|||
import javax.inject.Inject
|
||||
import kotlin.enums.EnumEntries
|
||||
|
||||
enum class NodeDetailPage(
|
||||
enum class MetricsPage(
|
||||
@StringRes val titleResId: Int,
|
||||
@DrawableRes val drawableResId: Int,
|
||||
) {
|
||||
DEVICE(R.string.device_metrics, R.drawable.baseline_charging_station_24),
|
||||
ENVIRONMENT(R.string.environment_metrics, R.drawable.baseline_thermostat_24),
|
||||
DEVICE(R.string.device, R.drawable.baseline_charging_station_24),
|
||||
ENVIRONMENT(R.string.environment, R.drawable.baseline_thermostat_24),
|
||||
}
|
||||
|
||||
data class NodeDetailsState(
|
||||
val pages: EnumEntries<NodeDetailPage> = NodeDetailPage.entries,
|
||||
data class MetricsState(
|
||||
val pages: EnumEntries<MetricsPage> = MetricsPage.entries,
|
||||
val isLoading: Boolean = false,
|
||||
val deviceMetrics: List<Telemetry> = emptyList(),
|
||||
val environmentMetrics: List<Telemetry> = emptyList(),
|
||||
) {
|
||||
companion object {
|
||||
val Empty = NodeDetailsState()
|
||||
val Empty = MetricsState()
|
||||
}
|
||||
}
|
||||
|
||||
@HiltViewModel
|
||||
class NodeDetailsViewModel @Inject constructor(
|
||||
class MetricsViewModel @Inject constructor(
|
||||
val nodeDB: NodeDB,
|
||||
private val meshLogRepository: MeshLogRepository
|
||||
) : ViewModel() {
|
||||
|
|
@ -50,7 +50,7 @@ class NodeDetailsViewModel @Inject constructor(
|
|||
_deviceMetrics,
|
||||
_environmentMetrics,
|
||||
) { isLoading, device, environment ->
|
||||
NodeDetailsState(
|
||||
MetricsState(
|
||||
isLoading = isLoading,
|
||||
deviceMetrics = device,
|
||||
environmentMetrics = environment,
|
||||
|
|
@ -58,7 +58,7 @@ class NodeDetailsViewModel @Inject constructor(
|
|||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = WhileSubscribed(5_000),
|
||||
initialValue = NodeDetailsState.Empty,
|
||||
initialValue = MetricsState.Empty,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -41,29 +41,29 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.android.Logging
|
||||
import com.geeksville.mesh.model.NodeDetailPage
|
||||
import com.geeksville.mesh.model.NodeDetailsState
|
||||
import com.geeksville.mesh.model.NodeDetailsViewModel
|
||||
import com.geeksville.mesh.model.MetricsPage
|
||||
import com.geeksville.mesh.model.MetricsState
|
||||
import com.geeksville.mesh.model.MetricsViewModel
|
||||
import com.geeksville.mesh.ui.components.DeviceMetricsScreen
|
||||
import com.geeksville.mesh.ui.components.EnvironmentMetricsScreen
|
||||
import com.geeksville.mesh.ui.theme.AppTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal fun FragmentManager.navigateToNodeDetails(nodeNum: Int? = null) {
|
||||
val nodeDetailsFragment = NodeDetailsFragment().apply {
|
||||
internal fun FragmentManager.navigateToMetrics(nodeNum: Int? = null) {
|
||||
val metricsFragment = MetricsFragment().apply {
|
||||
arguments = bundleOf("nodeNum" to nodeNum)
|
||||
}
|
||||
beginTransaction()
|
||||
.replace(R.id.mainActivityLayout, nodeDetailsFragment)
|
||||
.replace(R.id.mainActivityLayout, metricsFragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
|
||||
@AndroidEntryPoint
|
||||
class NodeDetailsFragment : ScreenFragment("NodeDetails"), Logging {
|
||||
class MetricsFragment : ScreenFragment("Metrics"), Logging {
|
||||
|
||||
private val model: NodeDetailsViewModel by viewModels()
|
||||
private val model: MetricsViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
@ -80,7 +80,7 @@ class NodeDetailsFragment : ScreenFragment("NodeDetails"), Logging {
|
|||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
AppTheme {
|
||||
NodeDetailsScreen(
|
||||
MetricsScreen(
|
||||
model = model,
|
||||
nodeName = nodeName,
|
||||
navigateBack = {
|
||||
|
|
@ -95,8 +95,8 @@ class NodeDetailsFragment : ScreenFragment("NodeDetails"), Logging {
|
|||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun NodeDetailsScreen(
|
||||
model: NodeDetailsViewModel = hiltViewModel(),
|
||||
fun MetricsScreen(
|
||||
model: MetricsViewModel = hiltViewModel(),
|
||||
nodeName: String?,
|
||||
navigateBack: () -> Unit,
|
||||
) {
|
||||
|
|
@ -113,7 +113,7 @@ fun NodeDetailsScreen(
|
|||
contentColor = colorResource(R.color.toolbarText),
|
||||
title = {
|
||||
Text(
|
||||
text = "${stringResource(R.string.node_details)}: $nodeName",
|
||||
text = "${stringResource(R.string.metrics)}: $nodeName",
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
|
|
@ -127,7 +127,7 @@ fun NodeDetailsScreen(
|
|||
)
|
||||
},
|
||||
) { innerPadding ->
|
||||
NodeDetailsPagerScreen(
|
||||
MetricsPagerScreen(
|
||||
state = state,
|
||||
pagerState = pagerState,
|
||||
modifier = Modifier.padding(top = innerPadding.calculateTopPadding())
|
||||
|
|
@ -137,8 +137,8 @@ fun NodeDetailsScreen(
|
|||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun NodeDetailsPagerScreen(
|
||||
state: NodeDetailsState,
|
||||
fun MetricsPagerScreen(
|
||||
state: MetricsState,
|
||||
pagerState: PagerState,
|
||||
modifier: Modifier = Modifier,
|
||||
) = with(state) {
|
||||
|
|
@ -178,8 +178,8 @@ fun NodeDetailsPagerScreen(
|
|||
}
|
||||
} else {
|
||||
when (pages[index]) {
|
||||
NodeDetailPage.DEVICE -> DeviceMetricsScreen(deviceMetrics)
|
||||
NodeDetailPage.ENVIRONMENT -> EnvironmentMetricsScreen(environmentMetrics)
|
||||
MetricsPage.DEVICE -> DeviceMetricsScreen(deviceMetrics)
|
||||
MetricsPage.ENVIRONMENT -> EnvironmentMetricsScreen(environmentMetrics)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -189,10 +189,10 @@ fun NodeDetailsPagerScreen(
|
|||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun NodeDetailsPreview() {
|
||||
private fun MetricsPreview() {
|
||||
AppTheme {
|
||||
val state = NodeDetailsState.Empty
|
||||
NodeDetailsPagerScreen(
|
||||
val state = MetricsState.Empty
|
||||
MetricsPagerScreen(
|
||||
state = state,
|
||||
pagerState = rememberPagerState(pageCount = { state.pages.size }),
|
||||
)
|
||||
|
|
@ -4,10 +4,12 @@ import androidx.compose.material.MaterialTheme
|
|||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import com.geeksville.mesh.NodeInfo
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.ui.preview.NodeInfoPreviewParameterProvider
|
||||
import com.geeksville.mesh.ui.theme.AppTheme
|
||||
|
||||
|
|
@ -18,7 +20,7 @@ fun signalInfo(
|
|||
isThisNode: Boolean
|
||||
): Boolean {
|
||||
val text = if (isThisNode) {
|
||||
"ChUtil %.1f%% AirUtilTX %.1f%%".format(
|
||||
stringResource(R.string.channel_air_util).format(
|
||||
nodeInfo.deviceMetrics?.channelUtilization,
|
||||
nodeInfo.deviceMetrics?.airUtilTx
|
||||
)
|
||||
|
|
@ -30,7 +32,7 @@ fun signalInfo(
|
|||
add("RSSI: %d SNR: %.1f".format(nodeInfo.rssi, nodeInfo.snr))
|
||||
}
|
||||
} else {
|
||||
add("Hops Away: %d".format(nodeInfo.hopsAway))
|
||||
add("%s: %d".format(stringResource(R.string.hops_away), nodeInfo.hopsAway))
|
||||
}
|
||||
}.joinToString(" ")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ class UsersFragment : ScreenFragment("Users"), Logging {
|
|||
navigateToRadioConfig(node)
|
||||
}
|
||||
|
||||
R.id.more_details -> {
|
||||
navigateToMoreDetails(node)
|
||||
R.id.metrics -> {
|
||||
navigateToMetrics(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -101,9 +101,9 @@ class UsersFragment : ScreenFragment("Users"), Logging {
|
|||
parentFragmentManager.navigateToRadioConfig(node.num)
|
||||
}
|
||||
|
||||
private fun navigateToMoreDetails(node: NodeInfo) {
|
||||
info("calling MoreDetails --> destNum: ${node.num}")
|
||||
parentFragmentManager.navigateToNodeDetails(node.num)
|
||||
private fun navigateToMetrics(node: NodeInfo) {
|
||||
info("calling Metrics --> destNum: ${node.num}")
|
||||
parentFragmentManager.navigateToMetrics(node.num)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ fun EnvironmentMetricsScreen(telemetries: List<Telemetry>) {
|
|||
@Composable
|
||||
private fun DeviceMetricsChart(modifier: Modifier = Modifier, telemetries: List<Telemetry>) {
|
||||
|
||||
ChartHeader(amount = telemetries.size, title = stringResource(R.string.device_metrics))
|
||||
ChartHeader(amount = telemetries.size)
|
||||
if (telemetries.isEmpty())
|
||||
return
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ private fun DeviceMetricsChart(modifier: Modifier = Modifier, telemetries: List<
|
|||
@Composable
|
||||
private fun EnvironmentMetricsChart(modifier: Modifier = Modifier, telemetries: List<Telemetry>) {
|
||||
|
||||
ChartHeader(amount = telemetries.size, title = stringResource(R.string.environment_metrics))
|
||||
ChartHeader(amount = telemetries.size)
|
||||
if (telemetries.isEmpty())
|
||||
return
|
||||
|
||||
|
|
@ -406,10 +406,8 @@ private fun DeviceMetricsCard(telemetry: Telemetry) {
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
val text = "%s %.2f%% %s %.2f%%".format(
|
||||
stringResource(R.string.channel_utilization),
|
||||
val text = stringResource(R.string.channel_air_util).format(
|
||||
deviceMetrics.channelUtilization,
|
||||
stringResource(R.string.air_utilization),
|
||||
deviceMetrics.airUtilTx
|
||||
)
|
||||
Text(
|
||||
|
|
@ -493,14 +491,14 @@ private fun EnvironmentMetricsCard(telemetry: Telemetry) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun ChartHeader(amount: Int, title: String) {
|
||||
private fun ChartHeader(amount: Int) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = "$amount $title",
|
||||
text = "$amount ${stringResource(R.string.logs)}",
|
||||
modifier = Modifier.wrapContentWidth(),
|
||||
style = TextStyle(fontWeight = FontWeight.Bold),
|
||||
fontSize = MaterialTheme.typography.button.fontSize
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue