mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-02-05 13:22:59 -05:00
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
This commit is contained in:
@@ -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)
|
||||
|
||||
79
app/src/main/java/com/geeksville/mesh/ui/SignalInfo.kt
Normal file
79
app/src/main/java/com/geeksville/mesh/ui/SignalInfo.kt
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<NodeInfo> {
|
||||
override val values: Sequence<NodeInfo>
|
||||
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
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
@@ -85,17 +85,25 @@
|
||||
tools:composableName="com.geeksville.mesh.ui.LastHeardInfoKt.LastHeardInfoPreview"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/signalView"
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/lastHeardInfo"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="nodePosition, lastHeardInfo"
|
||||
/>
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/signalInfo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier"
|
||||
app:layout_constraintBottom_toTopOf="@id/envMetrics"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
tools:text="RSSI: -40 SNR: -8"
|
||||
tools:composableName="com.geeksville.mesh.ui.SignalInfoKt.SignalInfoSimplePreview"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
|
||||
Reference in New Issue
Block a user