mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: add support for Device Hardware json and svg graphics (#1449)
* feat: add support for Device Hardware json and svg graphics Allows for better hardware device display names, graphics, and indication of support. * make detekt happy * Fix: Use first image name to find vector drawable Use the first image name from the `images` list (after removing the ".svg" suffix) to find the corresponding vector drawable resource. * Refactor: Update device detail layout Updated the device detail layout to group device-specific information under a "Device" category. Added a circular background with device-specific color behind the device icon. Moved hardware, support status details to the Device section. * Refactor: Move device hardware logic to MetricsViewModel Moves the logic for retrieving device hardware information and image resources from NodeDetail to MetricsViewModel. Also replaces id lookup with when statement for image resource id mapping. * fix: cache deviceHardwareList, add exception handling * refactor: mutable list unnecessary * default to hw_unknown device image
This commit is contained in:
parent
f08916764c
commit
993f659742
43 changed files with 36489 additions and 13 deletions
|
|
@ -15,10 +15,12 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@file:Suppress("TooManyFunctions")
|
||||
@file:Suppress("TooManyFunctions", "LongMethod")
|
||||
|
||||
package com.geeksville.mesh.ui
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -36,6 +38,7 @@ import androidx.compose.foundation.layout.size
|
|||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
|
|
@ -64,6 +67,7 @@ import androidx.compose.material.icons.filled.Settings
|
|||
import androidx.compose.material.icons.filled.SignalCellularAlt
|
||||
import androidx.compose.material.icons.filled.Speed
|
||||
import androidx.compose.material.icons.filled.Thermostat
|
||||
import androidx.compose.material.icons.filled.Verified
|
||||
import androidx.compose.material.icons.filled.WaterDrop
|
||||
import androidx.compose.material.icons.filled.Work
|
||||
import androidx.compose.material.icons.outlined.Navigation
|
||||
|
|
@ -71,6 +75,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
|
@ -98,8 +103,8 @@ import kotlin.math.ln
|
|||
|
||||
@Composable
|
||||
fun NodeDetailScreen(
|
||||
viewModel: MetricsViewModel = hiltViewModel(),
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: MetricsViewModel = hiltViewModel(),
|
||||
onNavigate: (Any) -> Unit,
|
||||
) {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
|
@ -124,15 +129,20 @@ fun NodeDetailScreen(
|
|||
|
||||
@Composable
|
||||
private fun NodeDetailList(
|
||||
modifier: Modifier = Modifier,
|
||||
node: NodeEntity,
|
||||
metricsState: MetricsState,
|
||||
modifier: Modifier = Modifier,
|
||||
onNavigate: (Any) -> Unit = {},
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
) {
|
||||
item {
|
||||
PreferenceCategory("Device") {
|
||||
DeviceDetailsContent(metricsState)
|
||||
}
|
||||
}
|
||||
item {
|
||||
PreferenceCategory("Details") {
|
||||
NodeDetailsContent(node)
|
||||
|
|
@ -176,7 +186,12 @@ private fun NodeDetailList(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun NodeDetailRow(label: String, icon: ImageVector, value: String) {
|
||||
private fun NodeDetailRow(
|
||||
label: String,
|
||||
icon: ImageVector,
|
||||
value: String,
|
||||
iconTint: Color = MaterialTheme.colors.onSurface
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -186,7 +201,8 @@ private fun NodeDetailRow(label: String, icon: ImageVector, value: String) {
|
|||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = label,
|
||||
modifier = Modifier.size(24.dp)
|
||||
modifier = Modifier.size(24.dp),
|
||||
tint = iconTint
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(label)
|
||||
|
|
@ -196,7 +212,50 @@ private fun NodeDetailRow(label: String, icon: ImageVector, value: String) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun NodeDetailsContent(node: NodeEntity) {
|
||||
private fun DeviceDetailsContent(
|
||||
state: MetricsState,
|
||||
) {
|
||||
val node = state.node ?: return
|
||||
val deviceHardware = state.deviceHardware ?: return
|
||||
val deviceImageRes = state.deviceImageRes
|
||||
val hwModelName = deviceHardware.displayName
|
||||
val isSupported = deviceHardware.activelySupported
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(100.dp)
|
||||
.padding(4.dp)
|
||||
.clip(CircleShape)
|
||||
.background(
|
||||
color = Color(node.colors.second).copy(alpha = .5f),
|
||||
shape = CircleShape
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
imageVector = ImageVector.vectorResource(deviceImageRes),
|
||||
contentDescription = hwModelName,
|
||||
)
|
||||
}
|
||||
NodeDetailRow(
|
||||
label = "Hardware",
|
||||
icon = Icons.Default.Router,
|
||||
value = hwModelName
|
||||
)
|
||||
if (isSupported) {
|
||||
NodeDetailRow(
|
||||
label = "Supported",
|
||||
icon = Icons.Default.Verified,
|
||||
value = "",
|
||||
iconTint = Color.Green
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NodeDetailsContent(
|
||||
node: NodeEntity,
|
||||
) {
|
||||
if (node.mismatchKey) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
|
|
@ -232,11 +291,6 @@ private fun NodeDetailsContent(node: NodeEntity) {
|
|||
icon = Icons.Default.Work,
|
||||
value = node.user.role.name
|
||||
)
|
||||
NodeDetailRow(
|
||||
label = "Hardware",
|
||||
icon = Icons.Default.Router,
|
||||
value = node.user.hwModel.name
|
||||
)
|
||||
if (node.deviceMetrics.uptimeSeconds > 0) {
|
||||
NodeDetailRow(
|
||||
label = "Uptime",
|
||||
|
|
@ -541,6 +595,9 @@ private fun NodeDetailsPreview(
|
|||
node: NodeEntity
|
||||
) {
|
||||
AppTheme {
|
||||
NodeDetailList(node, MetricsState.Empty)
|
||||
NodeDetailList(
|
||||
node = node,
|
||||
metricsState = MetricsState.Empty,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue