From 9e9ecba4e3f04cf6228675ec4bf1ebb1644e3de3 Mon Sep 17 00:00:00 2001 From: Davis Date: Wed, 28 Feb 2024 08:43:29 -0700 Subject: [PATCH] Move signal info to compose (#879) * Move battery info to compose - always show voltage level and icons to match battery percentage Use tool text in preview, rather than actually set text value Simplify node info layout to avoid defining margins on everything * Move node position to Compose * Update hyperlink color to match previous value * Use compose preview in layout editor * Use compose preview in layout editor * Add simple preview for use in layout * Move last heard node info to Compose Clean up layout of node info * Move signal info to Compose and simplify bind * Prevent long coordinates from colliding with signal info --- .../geeksville/mesh/ui/LinkedCoordinates.kt | 12 +++ .../java/com/geeksville/mesh/ui/SignalInfo.kt | 79 +++++++++++++++++++ .../com/geeksville/mesh/ui/UsersFragment.kt | 54 ++++--------- .../ui/preview/PreviewParameterProviders.kt | 27 +++++++ .../main/res/layout/adapter_node_layout.xml | 18 +++-- 5 files changed, 147 insertions(+), 43 deletions(-) create mode 100644 app/src/main/java/com/geeksville/mesh/ui/SignalInfo.kt create mode 100644 app/src/main/java/com/geeksville/mesh/ui/preview/PreviewParameterProviders.kt diff --git a/app/src/main/java/com/geeksville/mesh/ui/LinkedCoordinates.kt b/app/src/main/java/com/geeksville/mesh/ui/LinkedCoordinates.kt index ace833c1d..2071a9e1a 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/LinkedCoordinates.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/LinkedCoordinates.kt @@ -59,6 +59,18 @@ fun LinkedCoordinates( } } +@Composable +@Preview +fun LinkedCoordinatesSimplePreview() { + AppTheme { + LinkedCoordinates( + position = Position(37.7749, -122.4194, 0), + format = 1, + nodeName = "Test Node Name" + ) + } +} + @Composable @Preview(showBackground = true) @Preview(showBackground = true, uiMode = android.content.res.Configuration.UI_MODE_NIGHT_YES) diff --git a/app/src/main/java/com/geeksville/mesh/ui/SignalInfo.kt b/app/src/main/java/com/geeksville/mesh/ui/SignalInfo.kt new file mode 100644 index 000000000..c092a3dd6 --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/ui/SignalInfo.kt @@ -0,0 +1,79 @@ +package com.geeksville.mesh.ui + +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import com.geeksville.mesh.NodeInfo +import com.geeksville.mesh.ui.preview.NodeInfoPreviewParameterProvider +import com.geeksville.mesh.ui.theme.AppTheme + +@Composable +fun SignalInfo( + nodeInfo: NodeInfo, + isThisNode: Boolean +) { + val text = if (isThisNode) { + "ChUtil %.1f%% AirUtilTX %.1f%%".format( + nodeInfo.deviceMetrics?.channelUtilization, + nodeInfo.deviceMetrics?.airUtilTx + ) + } else { + buildString { + if (nodeInfo.channel > 0) append("ch:${nodeInfo.channel}") + if (nodeInfo.snr < 100F && nodeInfo.rssi < 0) { + if (isNotEmpty()) append(" ") + append("RSSI: %d SNR: %.1f".format(nodeInfo.rssi, nodeInfo.snr)) + } + } + } + if (text.isNotEmpty()) { + Text( + text = text, + color = MaterialTheme.colors.onSurface, + fontSize = MaterialTheme.typography.button.fontSize + ) + } +} + +@Composable +@Preview(showBackground = true) +fun SignalInfoSimplePreview() { + AppTheme { + SignalInfo(NodeInfo( + num = 1, + position = null, + lastHeard = 0, + channel = 0, + snr = 12.5F, + rssi = -42, + deviceMetrics = null, + user = null + ), false) + } +} + +@Composable +@Preview(showBackground = true) +@Preview(showBackground = true, uiMode = android.content.res.Configuration.UI_MODE_NIGHT_YES) +fun SignalInfoPreview( + @PreviewParameter(NodeInfoPreviewParameterProvider::class) + nodeInfo: NodeInfo +) { + AppTheme { + SignalInfo(nodeInfo, false) + } +} + +@Composable +@Preview(showBackground = true) +@Preview(showBackground = true, uiMode = android.content.res.Configuration.UI_MODE_NIGHT_YES) +fun SignalInfoSelfPreview( + @PreviewParameter(NodeInfoPreviewParameterProvider::class) + nodeInfo: NodeInfo +) { + AppTheme { + SignalInfo(nodeInfo, true) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt index a573d2afa..e5d768bfc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt @@ -54,12 +54,12 @@ class UsersFragment : ScreenFragment("Users"), Logging { val chipNode = itemView.chipNode val nodeNameView = itemView.nodeNameView val distanceView = itemView.distanceView - val signalView = itemView.signalView val envMetrics = itemView.envMetrics val background = itemView.nodeCard val nodePosition = itemView.nodePosition val batteryInfo = itemView.batteryInfo val lastHeard = itemView.lastHeardInfo + val signalInfo = itemView.signalInfo fun blink() { val bg = background.backgroundTintList @@ -83,26 +83,28 @@ class UsersFragment : ScreenFragment("Users"), Logging { } fun bind( - batteryLevel: Int?, - voltage: Float?, - position: Position?, + nodeInfo: NodeInfo, + isThisNode: Boolean, gpsFormat: Int, - nodeName: String?, - lastHeard: Int ) { batteryInfo.setContent { AppTheme { - BatteryInfo(batteryLevel, voltage) + BatteryInfo(nodeInfo.batteryLevel, nodeInfo.voltage) } } nodePosition.setContent { AppTheme { - LinkedCoordinates(position, gpsFormat, nodeName) + LinkedCoordinates(nodeInfo.position, gpsFormat, nodeInfo.user?.longName) } } this.lastHeard.setContent { AppTheme { - LastHeardInfo(lastHeard) + LastHeardInfo(nodeInfo.lastHeard) + } + } + this.signalInfo.setContent { + AppTheme { + SignalInfo(nodeInfo, isThisNode) } } } @@ -250,23 +252,21 @@ class UsersFragment : ScreenFragment("Users"), Logging { */ override fun onBindViewHolder(holder: ViewHolder, position: Int) { val n = nodes[position] - val user = n.user val (textColor, nodeColor) = n.colors val isIgnored: Boolean = ignoreIncomingList.contains(n.num) - val name = user?.longName + val isThisNode = n.num == nodes[0].num - holder.bind(n.batteryLevel, n.voltage, n.validPosition, gpsFormat, name, n.lastHeard) + holder.bind(n, isThisNode, gpsFormat) - holder.nodeNameView.text = name + holder.nodeNameView.text = n.user?.longName with(holder.chipNode) { - text = (user?.shortName ?: "UNK").strikeIf(isIgnored) + text = (n.user?.shortName ?: "UNK").strikeIf(isIgnored) chipBackgroundColor = ColorStateList.valueOf(nodeColor) setTextColor(textColor) } - val ourNodeInfo = nodes[0] - val distance = ourNodeInfo.distanceStr(n, displayUnits) + val distance = nodes[0].distanceStr(n, displayUnits) if (distance != null) { holder.distanceView.text = distance holder.distanceView.visibility = View.VISIBLE @@ -282,28 +282,6 @@ class UsersFragment : ScreenFragment("Users"), Logging { holder.envMetrics.visibility = View.GONE } - if (n.num == ourNodeInfo.num) { - val text = "ChUtil %.1f%% AirUtilTX %.1f%%".format( - n.deviceMetrics?.channelUtilization, - n.deviceMetrics?.airUtilTx - ) - holder.signalView.text = text - holder.signalView.visibility = View.VISIBLE - } else { - val text = buildString { - if (n.channel > 0) append("ch:${n.channel}") - if (n.snr < 100f && n.rssi < 0) { - if (isNotEmpty()) append(" ") - append("rssi:%d snr:%.1f".format(n.rssi, n.snr)) - } - } - if (text.isNotEmpty()) { - holder.signalView.text = text - holder.signalView.visibility = View.VISIBLE - } else { - holder.signalView.visibility = View.INVISIBLE - } - } holder.chipNode.setOnClickListener { popup(it, position) } diff --git a/app/src/main/java/com/geeksville/mesh/ui/preview/PreviewParameterProviders.kt b/app/src/main/java/com/geeksville/mesh/ui/preview/PreviewParameterProviders.kt new file mode 100644 index 000000000..3e2a029c6 --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/ui/preview/PreviewParameterProviders.kt @@ -0,0 +1,27 @@ +package com.geeksville.mesh.ui.preview + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import com.geeksville.mesh.DeviceMetrics +import com.geeksville.mesh.NodeInfo + + +class NodeInfoPreviewParameterProvider: PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + NodeInfo( + num = 1, + position = null, + lastHeard = 0, + channel = 0, + snr = 12.5F, + rssi = -42, + deviceMetrics = DeviceMetrics( + channelUtilization = 2.4F, + airUtilTx = 3.5F, + batteryLevel = 85, + voltage = 3.7F + ), + user = null + ) + ) +} \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_node_layout.xml b/app/src/main/res/layout/adapter_node_layout.xml index 15c15b4e5..0817f6ff3 100644 --- a/app/src/main/res/layout/adapter_node_layout.xml +++ b/app/src/main/res/layout/adapter_node_layout.xml @@ -63,7 +63,7 @@ app:layout_constraintTop_toBottomOf="@+id/nodeNameView" android:layout_marginStart="8dp" android:layout_marginTop="8dp" - tools:composableName="com.geeksville.mesh.ui.LinkedCoordinatesKt.LinkedCoordinatesPreview" + tools:composableName="com.geeksville.mesh.ui.LinkedCoordinatesKt.LinkedCoordinatesSimplePreview" /> - + +