perf(node): add stable keys and contentType to telemetry chart lists (#5869)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
James Rich
2026-06-19 13:23:12 -05:00
committed by GitHub
parent 3930252790
commit 3fe1deb01c
8 changed files with 54 additions and 9 deletions

View File

@@ -166,7 +166,11 @@ fun AirQualityMetricsScreen(viewModel: MetricsViewModel, onNavigateUp: () -> Uni
},
listPart = { modifier, selectedX, lazyListState, onCardClick ->
LazyColumn(modifier = modifier.fillMaxSize(), state = lazyListState) {
itemsIndexed(data) { _, telemetry ->
itemsIndexed(
data,
key = { _, telemetry -> telemetry.time },
contentType = { _, _ -> "air_quality_metrics" },
) { _, telemetry ->
AirQualityMetricsCard(
telemetry = telemetry,
isSelected = telemetry.time.toDouble() == selectedX,

View File

@@ -191,7 +191,11 @@ fun DeviceMetricsScreen(viewModel: MetricsViewModel, onNavigateUp: () -> Unit) {
},
listPart = { modifier, selectedX, lazyListState, onCardClick ->
LazyColumn(modifier = modifier.fillMaxSize(), state = lazyListState) {
itemsIndexed(data) { _, telemetry ->
itemsIndexed(
data,
key = { _, telemetry -> telemetry.time },
contentType = { _, _ -> "device_metrics" },
) { _, telemetry ->
DeviceMetricsCard(
telemetry = telemetry,
isSelected = telemetry.time.toDouble() == selectedX,
@@ -560,7 +564,11 @@ private fun DeviceMetricsScreenPreview() {
/* Device Metric Cards */
LazyColumn(modifier = Modifier.fillMaxSize()) {
itemsIndexed(telemetries) { _, telemetry ->
itemsIndexed(
telemetries,
key = { _, telemetry -> telemetry.time },
contentType = { _, _ -> "device_metrics" },
) { _, telemetry ->
DeviceMetricsCard(telemetry = telemetry, isSelected = false, onClick = {})
}
}

View File

@@ -115,7 +115,11 @@ fun EnvironmentMetricsScreen(viewModel: MetricsViewModel, onNavigateUp: () -> Un
},
listPart = { modifier, selectedX, lazyListState, onCardClick ->
LazyColumn(modifier = modifier.fillMaxSize(), state = lazyListState) {
itemsIndexed(filteredTelemetries) { _, telemetry ->
itemsIndexed(
filteredTelemetries,
key = { _, telemetry -> telemetry.time },
contentType = { _, _ -> "environment_metrics" },
) { _, telemetry ->
EnvironmentMetricsCard(
telemetry = telemetry,
environmentDisplayFahrenheit = state.isFahrenheit,

View File

@@ -231,7 +231,11 @@ fun PaxMetricsScreen(metricsViewModel: MetricsViewModel, onNavigateUp: () -> Uni
state = lazyListState,
contentPadding = PaddingValues(horizontal = 16.dp),
) {
itemsIndexed(paxMetrics) { _, (log, pax) ->
itemsIndexed(
paxMetrics,
key = { _, (log, _) -> log.uuid },
contentType = { _, _ -> "pax_metrics" },
) { _, (log, pax) ->
PaxMetricsItem(
log = log,
pax = pax,

View File

@@ -70,7 +70,11 @@ fun PositionLogScreen(viewModel: MetricsViewModel, onNavigateUp: () -> Unit) {
},
listPart = { modifier, selectedX, lazyListState, onCardClick ->
LazyColumn(modifier = modifier.fillMaxSize(), state = lazyListState) {
itemsIndexed(positions) { _, position ->
itemsIndexed(
positions,
key = { _, position -> position.time },
contentType = { _, _ -> "position_log" },
) { _, position ->
PositionCard(
position = position,
displayUnits = state.displayUnits,

View File

@@ -159,7 +159,11 @@ fun PowerMetricsScreen(viewModel: MetricsViewModel, onNavigateUp: () -> Unit) {
},
listPart = { modifier, selectedX, lazyListState, onCardClick ->
LazyColumn(modifier = modifier.fillMaxSize(), state = lazyListState) {
itemsIndexed(data) { _, telemetry ->
itemsIndexed(
data,
key = { _, telemetry -> telemetry.time },
contentType = { _, _ -> "power_metrics" },
) { _, telemetry ->
PowerMetricsCard(
telemetry = telemetry,
isSelected = telemetry.time.toDouble() == selectedX,

View File

@@ -114,12 +114,22 @@ private val LEGEND_DATA =
private sealed interface SignalLogEntry {
val timeSeconds: Int
/** Stable, collision-free identity for use as a LazyColumn item key across both entry types. */
val key: Any
/** Distinguishes the two card layouts so Compose can reuse compositions per type. */
val contentType: Any
data class LocalStatsEntry(val telemetry: Telemetry) : SignalLogEntry {
override val timeSeconds: Int = telemetry.time
override val key: Any = "local_stats_${telemetry.time}"
override val contentType: Any = "local_stats"
}
data class PacketEntry(val meshPacket: MeshPacket) : SignalLogEntry {
override val timeSeconds: Int = meshPacket.rx_time
override val key: Any = "packet_${meshPacket.id}"
override val contentType: Any = "signal_packet"
}
}
@@ -204,7 +214,11 @@ fun SignalMetricsScreen(viewModel: MetricsViewModel, onNavigateUp: () -> Unit, m
}
} else {
LazyColumn(modifier = contentModifier.fillMaxSize(), state = lazyListState) {
itemsIndexed(data) { _, entry ->
itemsIndexed(
data,
key = { _, entry -> entry.key },
contentType = { _, entry -> entry.contentType },
) { _, entry ->
when (entry) {
is SignalLogEntry.LocalStatsEntry ->
LocalStatsCard(