refactor(icons): migrate to self-hosted VectorDrawable XMLs via MeshtasticIcons (#5030)

This commit is contained in:
James Rich 2026-04-09 20:35:52 -05:00 committed by GitHub
parent 5e57efeb06
commit dba037466e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
344 changed files with 3760 additions and 2631 deletions

View file

@ -17,11 +17,6 @@
package org.meshtastic.feature.node.component
import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ForkLeft
import androidx.compose.material.icons.rounded.Icecream
import androidx.compose.material.icons.rounded.Memory
import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -43,6 +38,11 @@ import org.meshtastic.core.resources.latest_stable_firmware
import org.meshtastic.core.resources.remote_admin
import org.meshtastic.core.resources.request_metadata
import org.meshtastic.core.ui.component.ListItem
import org.meshtastic.core.ui.icon.ForkLeft
import org.meshtastic.core.ui.icon.Icecream
import org.meshtastic.core.ui.icon.Memory
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Settings
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
import org.meshtastic.core.ui.theme.StatusColors.StatusOrange
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
@ -63,7 +63,7 @@ fun AdministrationSection(
Column {
ListItem(
text = stringResource(Res.string.request_metadata),
leadingIcon = Icons.Rounded.Memory,
leadingIcon = MeshtasticIcons.Memory,
trailingIcon = null,
onClick = {
onAction(NodeDetailAction.TriggerServiceAction(ServiceAction.GetDeviceMetadata(node.num)))
@ -74,7 +74,7 @@ fun AdministrationSection(
ListItem(
text = stringResource(Res.string.remote_admin),
leadingIcon = Icons.Rounded.Settings,
leadingIcon = MeshtasticIcons.Settings,
enabled = metricsState.isLocal || node.metadata != null,
) {
onAction(NodeDetailAction.Navigate(SettingsRoutes.Settings(node.num)))
@ -101,8 +101,8 @@ private fun FirmwareSection(
firmwareEdition?.let { edition ->
val icon =
when (edition) {
FirmwareEdition.VANILLA -> Icons.Rounded.Icecream
else -> Icons.Rounded.ForkLeft
FirmwareEdition.VANILLA -> MeshtasticIcons.Icecream
else -> MeshtasticIcons.ForkLeft
}
ListItem(
@ -138,7 +138,7 @@ private fun FirmwareVersionItems(
ListItem(
text = stringResource(Res.string.installed_firmware_version),
leadingIcon = Icons.Rounded.Memory,
leadingIcon = MeshtasticIcons.Memory,
supportingText = version.substringBeforeLast("."),
copyable = true,
leadingIconTint = statusColor,
@ -149,7 +149,7 @@ private fun FirmwareVersionItems(
ListItem(
text = stringResource(Res.string.latest_stable_firmware),
leadingIcon = Icons.Rounded.Memory,
leadingIcon = MeshtasticIcons.Memory,
supportingText = latestStable.id.substringBeforeLast(".").replace("v", ""),
copyable = true,
leadingIconTint = MaterialTheme.colorScheme.StatusGreen,
@ -161,7 +161,7 @@ private fun FirmwareVersionItems(
ListItem(
text = stringResource(Res.string.latest_alpha_firmware),
leadingIcon = Icons.Rounded.Memory,
leadingIcon = MeshtasticIcons.Memory,
supportingText = latestAlpha.id.substringBeforeLast(".").replace("v", ""),
copyable = true,
leadingIconTint = MaterialTheme.colorScheme.StatusYellow,

View file

@ -16,8 +16,6 @@
*/
package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Tsunami
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -25,6 +23,8 @@ import androidx.compose.ui.graphics.Color
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.channel_label
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Tsunami
@Composable
fun ChannelInfo(
@ -34,7 +34,7 @@ fun ChannelInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Tsunami,
icon = MeshtasticIcons.Tsunami,
contentDescription = stringResource(Res.string.channel_label),
text = channel.toString(),
contentColor = contentColor,

View file

@ -25,9 +25,6 @@ import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ErrorOutline
import androidx.compose.material.icons.rounded.GpsFixed
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@ -70,6 +67,9 @@ import org.meshtastic.core.resources.compass_uncertainty_unknown
import org.meshtastic.core.resources.elevation_suffix
import org.meshtastic.core.resources.exchange_position
import org.meshtastic.core.resources.last_position_update
import org.meshtastic.core.ui.icon.ErrorOutline
import org.meshtastic.core.ui.icon.GpsFixed
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.feature.node.compass.CompassUiState
import org.meshtastic.feature.node.compass.CompassWarning
import kotlin.math.PI
@ -152,7 +152,7 @@ fun CompassSheetContent(
)
// Quick way to re-request a fresh fix without leaving the compass sheet
Button(onClick = onRequestPosition, modifier = Modifier.fillMaxWidth()) {
Icon(imageVector = Icons.Rounded.GpsFixed, contentDescription = null)
Icon(imageVector = MeshtasticIcons.GpsFixed, contentDescription = null)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(Res.string.exchange_position))
}
@ -189,7 +189,7 @@ private fun WarningList(
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Icon(
imageVector = Icons.Rounded.ErrorOutline,
imageVector = MeshtasticIcons.ErrorOutline,
contentDescription = null,
tint = MaterialTheme.colorScheme.onErrorContainer,
)
@ -204,13 +204,13 @@ private fun WarningList(
if (warnings.contains(CompassWarning.NO_LOCATION_PERMISSION)) {
Button(onClick = onRequestPermission, modifier = Modifier.fillMaxWidth()) {
Icon(imageVector = Icons.Rounded.GpsFixed, contentDescription = null)
Icon(imageVector = MeshtasticIcons.GpsFixed, contentDescription = null)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(Res.string.compass_no_location_permission))
}
} else if (warnings.contains(CompassWarning.LOCATION_DISABLED)) {
Button(onClick = onOpenLocationSettings, modifier = Modifier.fillMaxWidth()) {
Icon(imageVector = Icons.Rounded.GpsFixed, contentDescription = null)
Icon(imageVector = MeshtasticIcons.GpsFixed, contentDescription = null)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(Res.string.compass_location_disabled))
}

View file

@ -23,15 +23,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Message
import androidx.compose.material.icons.automirrored.filled.VolumeOff
import androidx.compose.material.icons.automirrored.filled.VolumeUp
import androidx.compose.material.icons.automirrored.outlined.VolumeMute
import androidx.compose.material.icons.rounded.Delete
import androidx.compose.material.icons.rounded.QrCode2
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StarBorder
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
@ -57,6 +48,15 @@ import org.meshtastic.core.resources.remove
import org.meshtastic.core.resources.share_contact
import org.meshtastic.core.ui.component.ListItem
import org.meshtastic.core.ui.component.SwitchListItem
import org.meshtastic.core.ui.icon.Delete
import org.meshtastic.core.ui.icon.Favorite
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Message
import org.meshtastic.core.ui.icon.NotFavorite
import org.meshtastic.core.ui.icon.QrCode2
import org.meshtastic.core.ui.icon.VolumeMute
import org.meshtastic.core.ui.icon.VolumeOff
import org.meshtastic.core.ui.icon.VolumeUp
import org.meshtastic.feature.node.model.LogsType
import org.meshtastic.feature.node.model.MetricsState
import org.meshtastic.feature.node.model.NodeDetailAction
@ -113,7 +113,7 @@ private fun PrimaryActionsRow(node: Node, isLocal: Boolean, onAction: (NodeDetai
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
),
) {
Icon(Icons.AutoMirrored.Filled.Message, contentDescription = null)
Icon(MeshtasticIcons.Message, contentDescription = null)
Spacer(Modifier.width(8.dp))
Text(stringResource(Res.string.direct_message))
}
@ -124,7 +124,7 @@ private fun PrimaryActionsRow(node: Node, isLocal: Boolean, onAction: (NodeDetai
modifier = if (node.isEffectivelyUnmessageable || isLocal) Modifier.weight(1f) else Modifier,
shape = MaterialTheme.shapes.large,
) {
Icon(Icons.Rounded.QrCode2, contentDescription = null)
Icon(MeshtasticIcons.QrCode2, contentDescription = null)
if (node.isEffectivelyUnmessageable || isLocal) {
Spacer(Modifier.width(8.dp))
Text(stringResource(Res.string.share_contact))
@ -137,7 +137,7 @@ private fun PrimaryActionsRow(node: Node, isLocal: Boolean, onAction: (NodeDetai
onCheckedChange = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.Favorite(node))) },
) {
Icon(
imageVector = if (node.isFavorite) Icons.Rounded.Star else Icons.Rounded.StarBorder,
imageVector = if (node.isFavorite) MeshtasticIcons.Favorite else MeshtasticIcons.NotFavorite,
contentDescription = stringResource(Res.string.favorite),
tint = if (node.isFavorite) Color.Yellow else LocalContentColor.current,
)
@ -153,9 +153,9 @@ private fun ManagementActions(node: Node, onAction: (NodeDetailAction) -> Unit)
text = stringResource(Res.string.ignore),
leadingIcon =
if (node.isIgnored) {
Icons.AutoMirrored.Outlined.VolumeMute
MeshtasticIcons.VolumeMute
} else {
Icons.AutoMirrored.Default.VolumeUp
MeshtasticIcons.VolumeUp
},
checked = node.isIgnored,
onClick = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.Ignore(node))) },
@ -166,9 +166,9 @@ private fun ManagementActions(node: Node, onAction: (NodeDetailAction) -> Unit)
text = stringResource(Res.string.mute_notifications),
leadingIcon =
if (node.isMuted) {
Icons.AutoMirrored.Filled.VolumeOff
MeshtasticIcons.VolumeOff
} else {
Icons.AutoMirrored.Default.VolumeUp
MeshtasticIcons.VolumeUp
},
checked = node.isMuted,
onClick = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.Mute(node))) },
@ -177,7 +177,7 @@ private fun ManagementActions(node: Node, onAction: (NodeDetailAction) -> Unit)
ListItem(
text = stringResource(Res.string.remove),
leadingIcon = Icons.Rounded.Delete,
leadingIcon = MeshtasticIcons.Delete,
trailingIcon = null,
textColor = MaterialTheme.colorScheme.error,
leadingIconTint = MaterialTheme.colorScheme.error,

View file

@ -27,9 +27,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Router
import androidx.compose.material.icons.twotone.Verified
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@ -51,6 +48,9 @@ import org.meshtastic.core.resources.img_hw_unknown
import org.meshtastic.core.resources.supported
import org.meshtastic.core.resources.supported_by_community
import org.meshtastic.core.ui.component.ListItem
import org.meshtastic.core.ui.icon.HardwareModel
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Verified
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
import org.meshtastic.feature.node.model.MetricsState
@ -78,7 +78,7 @@ fun DeviceDetailsSection(state: MetricsState, modifier: Modifier = Modifier) {
?: deviceHardware.displayName
ListItem(
text = stringResource(Res.string.hardware),
leadingIcon = Icons.Rounded.Router,
leadingIcon = MeshtasticIcons.HardwareModel,
supportingText = deviceText,
copyable = true,
trailingIcon = null,
@ -116,7 +116,7 @@ private fun SupportStatusItem(isSupported: Boolean) {
},
leadingIcon =
if (isSupported) {
Icons.TwoTone.Verified
MeshtasticIcons.Verified
} else {
org.jetbrains.compose.resources.vectorResource(org.meshtastic.core.resources.Res.drawable.ic_unverified)
},

View file

@ -16,8 +16,6 @@
*/
package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.SocialDistance
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -25,6 +23,8 @@ import androidx.compose.ui.graphics.Color
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.distance
import org.meshtastic.core.ui.icon.Distance
import org.meshtastic.core.ui.icon.MeshtasticIcons
@Composable
fun DistanceInfo(
@ -34,7 +34,7 @@ fun DistanceInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.SocialDistance,
icon = MeshtasticIcons.Distance,
contentDescription = stringResource(Res.string.distance),
label = stringResource(Res.string.distance),
text = distance,

View file

@ -19,20 +19,7 @@ package org.meshtastic.feature.node.component
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Navigation
import androidx.compose.material.icons.rounded.Air
import androidx.compose.material.icons.rounded.BlurOn
import androidx.compose.material.icons.rounded.Bolt
import androidx.compose.material.icons.rounded.Height
import androidx.compose.material.icons.rounded.LightMode
import androidx.compose.material.icons.rounded.Power
import androidx.compose.material.icons.rounded.Scale
import androidx.compose.material.icons.rounded.Speed
import androidx.compose.material.icons.rounded.Thermostat
import androidx.compose.material.icons.rounded.WaterDrop
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.common.util.NumberFormatter
@ -62,6 +49,18 @@ import org.meshtastic.core.resources.uv_lux
import org.meshtastic.core.resources.voltage
import org.meshtastic.core.resources.weight
import org.meshtastic.core.resources.wind
import org.meshtastic.core.ui.icon.AirQuality
import org.meshtastic.core.ui.icon.Altitude
import org.meshtastic.core.ui.icon.Humidity
import org.meshtastic.core.ui.icon.LightMode
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Particulate
import org.meshtastic.core.ui.icon.PowerSupply
import org.meshtastic.core.ui.icon.Pressure
import org.meshtastic.core.ui.icon.Temperature
import org.meshtastic.core.ui.icon.Voltage
import org.meshtastic.core.ui.icon.Weight
import org.meshtastic.core.ui.icon.WindDirection
import org.meshtastic.feature.node.model.DrawableMetricInfo
import org.meshtastic.feature.node.model.VectorMetricInfo
import org.meshtastic.proto.Config
@ -73,153 +72,158 @@ internal fun EnvironmentMetrics(
displayUnits: Config.DisplayConfig.DisplayUnits,
isFahrenheit: Boolean = false,
) {
val vectorMetrics =
remember(node.environmentMetrics, isFahrenheit, displayUnits) {
buildList {
with(node.environmentMetrics) {
temperature?.let { temp ->
if (!temp.isNaN()) {
add(
VectorMetricInfo(
label = Res.string.temperature,
value = temp.toTempString(isFahrenheit),
icon = Icons.Rounded.Thermostat,
),
)
}
}
relative_humidity?.let { rh ->
add(
VectorMetricInfo(
Res.string.humidity,
"${NumberFormatter.format(rh, 0)}%",
Icons.Rounded.WaterDrop,
),
)
}
barometric_pressure?.let { bp ->
add(
VectorMetricInfo(
Res.string.pressure,
"${NumberFormatter.format(bp, 0)} hPa",
Icons.Rounded.Speed,
),
)
}
gas_resistance?.let { gr ->
add(
VectorMetricInfo(
label = Res.string.gas_resistance,
value = "${NumberFormatter.format(gr, 0)}",
icon = Icons.Rounded.BlurOn,
),
)
}
voltage?.let { v ->
add(
VectorMetricInfo(
label = Res.string.voltage,
value = "${NumberFormatter.format(v, 2)}V",
icon = Icons.Rounded.Bolt,
),
)
}
current?.let { c ->
add(
VectorMetricInfo(
label = Res.string.current,
value = "${NumberFormatter.format(c, 1)}mA",
icon = Icons.Rounded.Power,
),
)
}
iaq?.let { i -> add(VectorMetricInfo(Res.string.iaq, i.toString(), Icons.Rounded.Air)) }
distance?.let { d ->
add(
VectorMetricInfo(
label = Res.string.distance,
value = d.toSmallDistanceString(displayUnits),
icon = Icons.Rounded.Height,
),
)
}
lux?.let { l ->
add(
VectorMetricInfo(
label = Res.string.lux,
value = "${NumberFormatter.format(l, 0)} lx",
icon = Icons.Rounded.LightMode,
),
)
}
uv_lux?.let { uvl ->
add(
VectorMetricInfo(
label = Res.string.uv_lux,
value = "${NumberFormatter.format(uvl, 0)} lx",
icon = Icons.Rounded.LightMode,
),
)
}
wind_speed?.let { ws ->
@Suppress("MagicNumber")
val normalizedBearing = ((wind_direction ?: 0) + 180) % 360
add(
VectorMetricInfo(
label = Res.string.wind,
value = ws.toSpeedString(displayUnits),
icon = Icons.Outlined.Navigation,
rotateIcon = normalizedBearing.toFloat(),
),
)
}
weight?.let { w ->
add(
VectorMetricInfo(
label = Res.string.weight,
value = "${NumberFormatter.format(w, 2)} kg",
icon = Icons.Rounded.Scale,
),
)
}
if (temperature != null && relative_humidity != null) {
val dewPoint = UnitConversions.calculateDewPoint(temperature!!, relative_humidity!!)
if (!dewPoint.isNaN()) {
add(
DrawableMetricInfo(
label = Res.string.dew_point,
value = dewPoint.toTempString(isFahrenheit),
icon = Res.drawable.ic_dew_point,
),
)
}
}
soil_temperature?.let { st ->
if (!st.isNaN()) {
add(
DrawableMetricInfo(
label = Res.string.soil_temperature,
value = st.toTempString(isFahrenheit),
icon = Res.drawable.ic_soil_temperature,
),
)
}
}
soil_moisture?.let { sm ->
add(DrawableMetricInfo(Res.string.soil_moisture, "$sm%", Res.drawable.ic_soil_moisture))
}
radiation?.let { r ->
add(
DrawableMetricInfo(
label = Res.string.radiation,
value = "${NumberFormatter.format(r, 1)} µR/h",
icon = Res.drawable.ic_radioactive,
),
)
}
val vectorMetrics = buildList {
with(node.environmentMetrics) {
temperature?.let { temp ->
if (!temp.isNaN()) {
add(
VectorMetricInfo(
label = Res.string.temperature,
value = temp.toTempString(isFahrenheit),
icon = MeshtasticIcons.Temperature,
),
)
}
}
relative_humidity?.let { rh ->
add(
VectorMetricInfo(
label = Res.string.humidity,
value = "${NumberFormatter.format(rh, 0)}%",
icon = MeshtasticIcons.Humidity,
),
)
}
barometric_pressure?.let { bp ->
add(
VectorMetricInfo(
label = Res.string.pressure,
value = "${NumberFormatter.format(bp, 0)} hPa",
icon = MeshtasticIcons.Pressure,
),
)
}
gas_resistance?.let { gr ->
add(
VectorMetricInfo(
label = Res.string.gas_resistance,
value = "${NumberFormatter.format(gr, 0)}",
icon = MeshtasticIcons.Particulate,
),
)
}
voltage?.let { v ->
add(
VectorMetricInfo(
label = Res.string.voltage,
value = "${NumberFormatter.format(v, 2)}V",
icon = MeshtasticIcons.Voltage,
),
)
}
current?.let { c ->
add(
VectorMetricInfo(
label = Res.string.current,
value = "${NumberFormatter.format(c, 1)}mA",
icon = MeshtasticIcons.PowerSupply,
),
)
}
iaq?.let { i ->
add(VectorMetricInfo(label = Res.string.iaq, value = i.toString(), icon = MeshtasticIcons.AirQuality))
}
distance?.let { d ->
add(
VectorMetricInfo(
label = Res.string.distance,
value = d.toSmallDistanceString(displayUnits),
icon = MeshtasticIcons.Altitude,
),
)
}
lux?.let { l ->
add(
VectorMetricInfo(
label = Res.string.lux,
value = "${NumberFormatter.format(l, 0)} lx",
icon = MeshtasticIcons.LightMode,
),
)
}
uv_lux?.let { uvl ->
add(
VectorMetricInfo(
label = Res.string.uv_lux,
value = "${NumberFormatter.format(uvl, 0)} lx",
icon = MeshtasticIcons.LightMode,
),
)
}
wind_speed?.let { ws ->
@Suppress("MagicNumber")
val normalizedBearing = ((wind_direction ?: 0) + 180) % 360
add(
VectorMetricInfo(
label = Res.string.wind,
value = ws.toSpeedString(displayUnits),
icon = MeshtasticIcons.WindDirection,
rotateIcon = normalizedBearing.toFloat(),
),
)
}
weight?.let { w ->
add(
VectorMetricInfo(
label = Res.string.weight,
value = "${NumberFormatter.format(w, 2)} kg",
icon = MeshtasticIcons.Weight,
),
)
}
if (temperature != null && relative_humidity != null) {
val dewPoint = UnitConversions.calculateDewPoint(temperature!!, relative_humidity!!)
if (!dewPoint.isNaN()) {
add(
DrawableMetricInfo(
label = Res.string.dew_point,
value = dewPoint.toTempString(isFahrenheit),
icon = Res.drawable.ic_dew_point,
),
)
}
}
soil_temperature?.let { st ->
if (!st.isNaN()) {
add(
DrawableMetricInfo(
label = Res.string.soil_temperature,
value = st.toTempString(isFahrenheit),
icon = Res.drawable.ic_soil_temperature,
),
)
}
}
soil_moisture?.let { sm ->
add(
DrawableMetricInfo(
label = Res.string.soil_moisture,
value = "$sm%",
icon = Res.drawable.ic_soil_moisture,
),
)
}
radiation?.let { r ->
add(
DrawableMetricInfo(
label = Res.string.radiation,
value = "${NumberFormatter.format(r, 1)} µR/h",
icon = Res.drawable.ic_radioactive,
),
)
}
}
}
FlowRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,

View file

@ -25,9 +25,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Download
import androidx.compose.material.icons.rounded.Link
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@ -41,6 +38,9 @@ import org.meshtastic.core.database.entity.FirmwareRelease
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.download
import org.meshtastic.core.resources.view_release
import org.meshtastic.core.ui.icon.Download
import org.meshtastic.core.ui.icon.LinkIcon
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.util.rememberOpenUrl
@Composable
@ -56,12 +56,15 @@ fun FirmwareReleaseSheetContent(firmwareRelease: FirmwareRelease, modifier: Modi
Markdown(modifier = Modifier.padding(8.dp), content = firmwareRelease.releaseNotes)
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = { openUrl(firmwareRelease.pageUrl) }, modifier = Modifier.weight(1f)) {
Icon(imageVector = Icons.Rounded.Link, contentDescription = stringResource(Res.string.view_release))
Icon(
imageVector = MeshtasticIcons.LinkIcon,
contentDescription = stringResource(Res.string.view_release),
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(Res.string.view_release))
}
Button(onClick = { openUrl(firmwareRelease.zipUrl) }, modifier = Modifier.weight(1f)) {
Icon(imageVector = Icons.Rounded.Download, contentDescription = stringResource(Res.string.download))
Icon(imageVector = MeshtasticIcons.Download, contentDescription = stringResource(Res.string.download))
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(Res.string.download))
}

View file

@ -16,8 +16,6 @@
*/
package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.CrueltyFree
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -25,12 +23,14 @@ import androidx.compose.ui.graphics.Color
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.hops_away
import org.meshtastic.core.ui.icon.HopCount
import org.meshtastic.core.ui.icon.MeshtasticIcons
@Composable
fun HopsInfo(hops: Int, modifier: Modifier = Modifier, contentColor: Color = MaterialTheme.colorScheme.onSurface) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.CrueltyFree,
icon = MeshtasticIcons.HopCount,
contentDescription = stringResource(Res.string.hops_away),
label = stringResource(Res.string.hops_away),
text = hops.toString(),

View file

@ -17,9 +17,6 @@
package org.meshtastic.feature.node.component
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.KeyboardArrowRight
import androidx.compose.material.icons.rounded.LocationOn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
@ -42,6 +39,9 @@ import org.meshtastic.core.resources.elevation_suffix
import org.meshtastic.core.resources.last_position_update
import org.meshtastic.core.ui.component.BasicListItem
import org.meshtastic.core.ui.component.icon
import org.meshtastic.core.ui.icon.KeyboardArrowRight
import org.meshtastic.core.ui.icon.LocationOn
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.util.createClipEntry
import org.meshtastic.core.ui.util.formatAgo
import org.meshtastic.core.ui.util.rememberOpenMap
@ -80,9 +80,9 @@ fun LinkedCoordinatesItem(
)
},
text = stringResource(Res.string.last_position_update),
leadingIcon = Icons.Rounded.LocationOn,
leadingIcon = MeshtasticIcons.LocationOn,
supportingText = "$ago$coordinates$elevationText",
trailingContent = Icons.AutoMirrored.Rounded.KeyboardArrowRight.icon(),
trailingContent = MeshtasticIcons.KeyboardArrowRight.icon(),
onClick = { openMap(node.latitude, node.longitude, node.user.long_name) },
onLongClick = { coroutineScope.launch { clipboard.setClipEntry(createClipEntry(coordinates, copyLabel)) } },
)

View file

@ -16,14 +16,6 @@
*/
package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.VolumeOff
import androidx.compose.material.icons.automirrored.filled.VolumeUp
import androidx.compose.material.icons.filled.DoDisturbOn
import androidx.compose.material.icons.outlined.DoDisturbOn
import androidx.compose.material.icons.rounded.DeleteOutline
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StarBorder
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
@ -42,6 +34,13 @@ import org.meshtastic.core.resources.remove
import org.meshtastic.core.resources.remove_favorite
import org.meshtastic.core.resources.remove_ignored
import org.meshtastic.core.resources.unmute
import org.meshtastic.core.ui.icon.DeleteNode
import org.meshtastic.core.ui.icon.DoDisturb
import org.meshtastic.core.ui.icon.Favorite
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.NotFavorite
import org.meshtastic.core.ui.icon.VolumeOff
import org.meshtastic.core.ui.icon.VolumeUp
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
/**
@ -80,7 +79,7 @@ private fun FavoriteMenuItem(node: Node, onFavorite: () -> Unit, onDismiss: () -
enabled = !node.isIgnored,
leadingIcon = {
Icon(
imageVector = if (isFavorite) Icons.Rounded.Star else Icons.Rounded.StarBorder,
imageVector = if (isFavorite) MeshtasticIcons.Favorite else MeshtasticIcons.NotFavorite,
contentDescription = null,
)
},
@ -98,7 +97,7 @@ private fun IgnoreMenuItem(node: Node, onIgnore: () -> Unit, onDismiss: () -> Un
},
leadingIcon = {
Icon(
imageVector = if (isIgnored) Icons.Filled.DoDisturbOn else Icons.Outlined.DoDisturbOn,
imageVector = if (isIgnored) MeshtasticIcons.DoDisturb else MeshtasticIcons.DoDisturb,
contentDescription = null,
tint = MaterialTheme.colorScheme.StatusRed,
)
@ -122,7 +121,7 @@ private fun MuteMenuItem(node: Node, onMute: () -> Unit, onDismiss: () -> Unit)
},
leadingIcon = {
Icon(
imageVector = if (isMuted) Icons.AutoMirrored.Filled.VolumeOff else Icons.AutoMirrored.Filled.VolumeUp,
imageVector = if (isMuted) MeshtasticIcons.VolumeOff else MeshtasticIcons.VolumeUp,
contentDescription = null,
)
},
@ -140,7 +139,7 @@ private fun RemoveMenuItem(node: Node, onRemove: () -> Unit, onDismiss: () -> Un
enabled = !node.isIgnored,
leadingIcon = {
Icon(
imageVector = Icons.Rounded.DeleteOutline,
imageVector = MeshtasticIcons.DeleteNode,
contentDescription = null,
tint = if (node.isIgnored) LocalContentColor.current else MaterialTheme.colorScheme.StatusRed,
)

View file

@ -29,9 +29,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.Notes
import androidx.compose.material.icons.rounded.Numbers
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
@ -78,14 +75,17 @@ import org.meshtastic.core.resources.uptime
import org.meshtastic.core.resources.user_id
import org.meshtastic.core.resources.via_mqtt
import org.meshtastic.core.ui.icon.ArrowCircleUp
import org.meshtastic.core.ui.icon.ChannelUtilization
import org.meshtastic.core.ui.icon.Cloud
import org.meshtastic.core.ui.icon.DeviceNumbers
import org.meshtastic.core.ui.icon.History
import org.meshtastic.core.ui.icon.Hops
import org.meshtastic.core.ui.icon.HopCount
import org.meshtastic.core.ui.icon.KeyOff
import org.meshtastic.core.ui.icon.Lock
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.MqttConnected
import org.meshtastic.core.ui.icon.Notes
import org.meshtastic.core.ui.icon.Person
import org.meshtastic.core.ui.icon.Rssi
import org.meshtastic.core.ui.icon.Snr
import org.meshtastic.core.ui.icon.Verified
import org.meshtastic.core.ui.icon.role
import org.meshtastic.core.ui.util.createClipEntry
@ -189,7 +189,7 @@ private fun StatusMessageRow(status: String) {
InfoItem(
label = stringResource(Res.string.status_message),
value = status,
icon = Icons.AutoMirrored.Rounded.Notes,
icon = MeshtasticIcons.Notes,
modifier = Modifier.fillMaxWidth(),
)
}
@ -200,13 +200,13 @@ private fun NodeIdentificationRow(node: Node) {
InfoItem(
label = stringResource(Res.string.node_id),
value = DataPacket.nodeNumToDefaultId(node.num),
icon = Icons.Rounded.Numbers,
icon = MeshtasticIcons.DeviceNumbers,
modifier = Modifier.weight(1f),
)
InfoItem(
label = stringResource(Res.string.node_number),
value = node.num.toUInt().toString(),
icon = Icons.Rounded.Numbers,
icon = MeshtasticIcons.DeviceNumbers,
modifier = Modifier.weight(1f),
)
}
@ -225,7 +225,7 @@ private fun HearsAndHopsRow(node: Node) {
InfoItem(
label = stringResource(Res.string.hops_away),
value = node.hopsAway.toString(),
icon = MeshtasticIcons.Hops,
icon = MeshtasticIcons.HopCount,
modifier = Modifier.weight(1f),
)
} else {
@ -264,7 +264,7 @@ private fun SignalRow(node: Node) {
InfoItem(
label = stringResource(Res.string.snr),
value = formatString("%.1f dB", node.snr),
icon = MeshtasticIcons.ChannelUtilization,
icon = MeshtasticIcons.Snr,
modifier = Modifier.weight(1f),
)
} else {
@ -274,7 +274,7 @@ private fun SignalRow(node: Node) {
InfoItem(
label = stringResource(Res.string.rssi),
value = formatString("%d dBm", node.rssi),
icon = MeshtasticIcons.ChannelUtilization,
icon = MeshtasticIcons.Rssi,
modifier = Modifier.weight(1f),
)
} else {
@ -290,7 +290,7 @@ private fun MqttAndVerificationRow(node: Node) {
InfoItem(
label = stringResource(Res.string.via_mqtt),
value = "Yes",
icon = MeshtasticIcons.Cloud,
icon = MeshtasticIcons.MqttConnected,
modifier = Modifier.weight(1f),
)
} else {

View file

@ -29,10 +29,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Sort
import androidx.compose.material.icons.rounded.Clear
import androidx.compose.material.icons.rounded.Search
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
@ -72,6 +68,10 @@ import org.meshtastic.core.resources.node_filter_show_ignored
import org.meshtastic.core.resources.node_filter_title
import org.meshtastic.core.resources.node_sort_button
import org.meshtastic.core.resources.node_sort_title
import org.meshtastic.core.ui.icon.Clear
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Search
import org.meshtastic.core.ui.icon.Sort
@Suppress("LongParameterList")
@Composable
@ -173,13 +173,13 @@ private fun NodeFilterTextField(filterText: String, onTextChange: (String) -> Un
)
},
leadingIcon = {
Icon(Icons.Rounded.Search, contentDescription = stringResource(Res.string.node_filter_placeholder))
Icon(MeshtasticIcons.Search, contentDescription = stringResource(Res.string.node_filter_placeholder))
},
onValueChange = onTextChange,
trailingIcon = {
if (filterText.isNotEmpty() || isFocused) {
Icon(
Icons.Rounded.Clear,
MeshtasticIcons.Clear,
contentDescription = stringResource(Res.string.desc_node_filter_clear),
modifier =
Modifier.clickable {
@ -208,7 +208,7 @@ private fun NodeSortButton(
IconButton(onClick = { expanded = true }) {
Icon(
imageVector = Icons.AutoMirrored.Filled.Sort,
imageVector = MeshtasticIcons.Sort,
contentDescription = stringResource(Res.string.node_sort_button),
modifier = Modifier.heightIn(max = 48.dp),
tint = MaterialTheme.colorScheme.onSurface,

View file

@ -29,8 +29,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.Notes
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
@ -48,6 +46,7 @@ import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.resources.vectorResource
import org.meshtastic.core.common.util.formatString
import org.meshtastic.core.model.ConnectionState
import org.meshtastic.core.model.Node
@ -90,6 +89,7 @@ import org.meshtastic.core.ui.component.determineSignalQuality
import org.meshtastic.core.ui.icon.AirUtilization
import org.meshtastic.core.ui.icon.ChannelUtilization
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Notes
import org.meshtastic.proto.Config
private const val ACTIVE_ALPHA = 0.5f
@ -178,7 +178,7 @@ fun NodeItem(
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.Notes,
imageVector = MeshtasticIcons.Notes,
contentDescription = null,
modifier = Modifier.size(16.dp),
tint = contentColor.copy(alpha = 0.7f),
@ -284,7 +284,7 @@ private fun NodeSignalRow(thatNode: Node, isThisNode: Boolean, contentColor: Col
if (thatNode.snr < 100f && thatNode.rssi < 0) {
val quality = determineSignalQuality(thatNode.snr, thatNode.rssi)
IconInfo(
icon = quality.imageVector,
icon = vectorResource(quality.icon),
contentDescription = stringResource(Res.string.signal_quality),
contentColor = quality.color.invoke(),
text = stringResource(quality.nameRes),

View file

@ -46,12 +46,12 @@ import org.meshtastic.core.resources.favorite
import org.meshtastic.core.resources.mute_always
import org.meshtastic.core.resources.unmessageable
import org.meshtastic.core.resources.unmonitored_or_infrastructure
import org.meshtastic.core.ui.icon.CloudDone
import org.meshtastic.core.ui.icon.CloudOffTwoTone
import org.meshtastic.core.ui.icon.CloudSync
import org.meshtastic.core.ui.icon.CloudTwoTone
import org.meshtastic.core.ui.icon.DeviceSleep
import org.meshtastic.core.ui.icon.Disconnected
import org.meshtastic.core.ui.icon.Favorite
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.MqttDelivered
import org.meshtastic.core.ui.icon.MqttSyncing
import org.meshtastic.core.ui.icon.Unmessageable
import org.meshtastic.core.ui.icon.VolumeOff
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
@ -135,7 +135,7 @@ private fun ThisNodeStatusBadge(connectionState: ConnectionState) {
@Composable
private fun ConnectedStatusIcon() {
Icon(
imageVector = MeshtasticIcons.CloudDone,
imageVector = MeshtasticIcons.MqttDelivered,
contentDescription = stringResource(Res.string.connected),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.StatusGreen,
@ -145,7 +145,7 @@ private fun ConnectedStatusIcon() {
@Composable
private fun ConnectingStatusIcon() {
Icon(
imageVector = MeshtasticIcons.CloudSync,
imageVector = MeshtasticIcons.MqttSyncing,
contentDescription = stringResource(Res.string.connecting),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.StatusOrange,
@ -155,7 +155,7 @@ private fun ConnectingStatusIcon() {
@Composable
private fun DisconnectedStatusIcon() {
Icon(
imageVector = MeshtasticIcons.CloudOffTwoTone,
imageVector = MeshtasticIcons.Disconnected,
contentDescription = stringResource(Res.string.disconnected),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.StatusRed,
@ -165,7 +165,7 @@ private fun DisconnectedStatusIcon() {
@Composable
private fun DeviceSleepStatusIcon() {
Icon(
imageVector = MeshtasticIcons.CloudTwoTone,
imageVector = MeshtasticIcons.DeviceSleep,
contentDescription = stringResource(Res.string.device_sleeping),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.StatusYellow,

View file

@ -23,8 +23,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Save
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
@ -48,6 +46,8 @@ import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.add_a_note
import org.meshtastic.core.resources.notes
import org.meshtastic.core.resources.save
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Save
@Composable
fun NotesSection(node: Node, onSaveNotes: (Int, String) -> Unit, modifier: Modifier = Modifier) {
@ -86,7 +86,10 @@ fun NotesSection(node: Node, onSaveNotes: (Int, String) -> Unit, modifier: Modif
},
enabled = edited,
) {
Icon(imageVector = Icons.Rounded.Save, contentDescription = stringResource(Res.string.save))
Icon(
imageVector = MeshtasticIcons.Save,
contentDescription = stringResource(Res.string.save),
)
}
},
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),

View file

@ -28,10 +28,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Explore
import androidx.compose.material.icons.rounded.LocationOn
import androidx.compose.material.icons.rounded.SocialDistance
import androidx.compose.material3.AssistChip
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
@ -46,12 +42,17 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.resources.vectorResource
import org.meshtastic.core.model.Node
import org.meshtastic.core.model.util.toDistanceString
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.exchange_position
import org.meshtastic.core.resources.open_compass
import org.meshtastic.core.resources.position
import org.meshtastic.core.ui.icon.Compass
import org.meshtastic.core.ui.icon.Distance
import org.meshtastic.core.ui.icon.LocationOn
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.util.LocalInlineMapProvider
import org.meshtastic.feature.node.model.LogsType
import org.meshtastic.feature.node.model.MetricsState
@ -106,7 +107,7 @@ fun PositionSection(
AssistChip(
onClick = { onAction(NodeDetailAction.Navigate(LogsType.NODE_MAP.routeFactory(node.num))) },
label = { Text(stringResource(LogsType.NODE_MAP.titleRes)) },
leadingIcon = { Icon(LogsType.NODE_MAP.icon, null, Modifier.size(18.dp)) },
leadingIcon = { Icon(vectorResource(LogsType.NODE_MAP.icon), null, Modifier.size(18.dp)) },
)
}
@ -116,7 +117,7 @@ fun PositionSection(
onAction(NodeDetailAction.Navigate(LogsType.POSITIONS.routeFactory(node.num)))
},
label = { Text(stringResource(LogsType.POSITIONS.titleRes)) },
leadingIcon = { Icon(LogsType.POSITIONS.icon, null, Modifier.size(18.dp)) },
leadingIcon = { Icon(vectorResource(LogsType.POSITIONS.icon), null, Modifier.size(18.dp)) },
)
}
}
@ -141,7 +142,7 @@ private fun PositionMap(node: Node, distance: String?) {
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(Icons.Rounded.SocialDistance, null, Modifier.size(16.dp))
Icon(MeshtasticIcons.Distance, null, Modifier.size(16.dp))
Spacer(Modifier.width(6.dp))
Text(distance, style = MaterialTheme.typography.labelLarge)
}
@ -176,7 +177,7 @@ private fun PositionActionButtons(
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
),
) {
Icon(Icons.Rounded.LocationOn, null, Modifier.size(18.dp))
Icon(MeshtasticIcons.LocationOn, null, Modifier.size(18.dp))
Spacer(Modifier.width(6.dp))
Text(
text = stringResource(Res.string.exchange_position),
@ -193,7 +194,7 @@ private fun PositionActionButtons(
modifier = if (isLocal) Modifier.fillMaxWidth() else Modifier.weight(COMPASS_BUTTON_WEIGHT),
shape = MaterialTheme.shapes.large,
) {
Icon(Icons.Rounded.Explore, null, Modifier.size(18.dp))
Icon(MeshtasticIcons.Compass, null, Modifier.size(18.dp))
Spacer(Modifier.width(6.dp))
Text(
text = stringResource(Res.string.open_compass),

View file

@ -19,11 +19,7 @@ package org.meshtastic.feature.node.component
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Bolt
import androidx.compose.material.icons.rounded.Power
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.common.util.NumberFormatter
@ -32,6 +28,9 @@ import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.channel_1
import org.meshtastic.core.resources.channel_2
import org.meshtastic.core.resources.channel_3
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.PowerSupply
import org.meshtastic.core.ui.icon.Voltage
import org.meshtastic.feature.node.model.VectorMetricInfo
/**
@ -44,61 +43,58 @@ import org.meshtastic.feature.node.model.VectorMetricInfo
@Composable
@Suppress("LongMethod", "CyclomaticComplexMethod")
internal fun PowerMetrics(node: Node) {
val metrics =
remember(node.powerMetrics) {
buildList {
with(node.powerMetrics) {
if ((ch1_voltage ?: 0f) != 0f) {
add(
VectorMetricInfo(
Res.string.channel_1,
"${NumberFormatter.format(ch1_voltage ?: 0f, 2)}V",
Icons.Rounded.Bolt,
),
)
add(
VectorMetricInfo(
Res.string.channel_1,
"${NumberFormatter.format(ch1_current ?: 0f, 1)}mA",
Icons.Rounded.Power,
),
)
}
if ((ch2_voltage ?: 0f) != 0f) {
add(
VectorMetricInfo(
Res.string.channel_2,
"${NumberFormatter.format(ch2_voltage ?: 0f, 2)}V",
Icons.Rounded.Bolt,
),
)
add(
VectorMetricInfo(
Res.string.channel_2,
"${NumberFormatter.format(ch2_current ?: 0f, 1)}mA",
Icons.Rounded.Power,
),
)
}
if ((ch3_voltage ?: 0f) != 0f) {
add(
VectorMetricInfo(
Res.string.channel_3,
"${NumberFormatter.format(ch3_voltage ?: 0f, 2)}V",
Icons.Rounded.Bolt,
),
)
add(
VectorMetricInfo(
Res.string.channel_3,
"${NumberFormatter.format(ch3_current ?: 0f, 1)}mA",
Icons.Rounded.Power,
),
)
}
}
val metrics = buildList {
with(node.powerMetrics) {
if ((ch1_voltage ?: 0f) != 0f) {
add(
VectorMetricInfo(
Res.string.channel_1,
"${NumberFormatter.format(ch1_voltage ?: 0f, 2)}V",
MeshtasticIcons.Voltage,
),
)
add(
VectorMetricInfo(
Res.string.channel_1,
"${NumberFormatter.format(ch1_current ?: 0f, 1)}mA",
MeshtasticIcons.PowerSupply,
),
)
}
if ((ch2_voltage ?: 0f) != 0f) {
add(
VectorMetricInfo(
Res.string.channel_2,
"${NumberFormatter.format(ch2_voltage ?: 0f, 2)}V",
MeshtasticIcons.Voltage,
),
)
add(
VectorMetricInfo(
Res.string.channel_2,
"${NumberFormatter.format(ch2_current ?: 0f, 1)}mA",
MeshtasticIcons.PowerSupply,
),
)
}
if ((ch3_voltage ?: 0f) != 0f) {
add(
VectorMetricInfo(
Res.string.channel_3,
"${NumberFormatter.format(ch3_voltage ?: 0f, 2)}V",
MeshtasticIcons.Voltage,
),
)
add(
VectorMetricInfo(
Res.string.channel_3,
"${NumberFormatter.format(ch3_current ?: 0f, 1)}mA",
MeshtasticIcons.PowerSupply,
),
)
}
}
}
FlowRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,

View file

@ -16,8 +16,6 @@
*/
package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.twotone.SatelliteAlt
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -25,6 +23,8 @@ import androidx.compose.ui.graphics.Color
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.sats
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Satellites
@Composable
fun SatelliteCountInfo(
@ -34,7 +34,7 @@ fun SatelliteCountInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.TwoTone.SatelliteAlt,
icon = MeshtasticIcons.Satellites,
contentDescription = stringResource(Res.string.sats),
label = stringResource(Res.string.sats),
text = "$satCount",

View file

@ -41,31 +41,32 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.resources.vectorResource
import org.meshtastic.core.model.Node
import org.meshtastic.core.model.TelemetryType
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.ic_air
import org.meshtastic.core.resources.ic_person
import org.meshtastic.core.resources.ic_thermostat
import org.meshtastic.core.resources.logs
import org.meshtastic.core.resources.request_air_quality_metrics
import org.meshtastic.core.resources.request_telemetry
import org.meshtastic.core.resources.telemetry
import org.meshtastic.core.resources.userinfo
import org.meshtastic.core.ui.icon.AirQuality
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Person
import org.meshtastic.core.ui.icon.Refresh
import org.meshtastic.core.ui.icon.Temperature
import org.meshtastic.feature.node.model.LogsType
import org.meshtastic.feature.node.model.MetricsState
import org.meshtastic.feature.node.model.NodeDetailAction
private data class TelemetricFeature(
val titleRes: StringResource,
val icon: ImageVector,
val icon: DrawableResource,
val requestAction: ((Node) -> NodeMenuAction)?,
val logsType: LogsType? = null,
val isVisible: (Node) -> Boolean = { true },
@ -118,7 +119,7 @@ private fun rememberTelemetricFeatures(
listOf(
TelemetricFeature(
titleRes = Res.string.userinfo,
icon = MeshtasticIcons.Person,
icon = Res.drawable.ic_person,
requestAction = { NodeMenuAction.RequestUserInfo(it) },
isVisible = { !isLocal },
),
@ -154,7 +155,7 @@ private fun rememberTelemetricFeatures(
),
TelemetricFeature(
titleRes = LogsType.ENVIRONMENT.titleRes,
icon = MeshtasticIcons.Temperature,
icon = Res.drawable.ic_thermostat,
requestAction = { NodeMenuAction.RequestTelemetry(it, TelemetryType.ENVIRONMENT) },
logsType = LogsType.ENVIRONMENT,
content = { EnvironmentMetrics(it, metricsState.displayUnits, metricsState.isFahrenheit) },
@ -162,7 +163,7 @@ private fun rememberTelemetricFeatures(
),
TelemetricFeature(
titleRes = Res.string.request_air_quality_metrics,
icon = MeshtasticIcons.AirQuality,
icon = Res.drawable.ic_air,
requestAction = { NodeMenuAction.RequestTelemetry(it, TelemetryType.AIR_QUALITY) },
),
TelemetricFeature(
@ -201,7 +202,11 @@ private fun FeatureRow(node: Node, feature: TelemetricFeature, hasLogs: Boolean,
ListItem(
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
leadingContent = {
Icon(imageVector = feature.icon, contentDescription = null, tint = MaterialTheme.colorScheme.primary)
Icon(
imageVector = vectorResource(feature.icon),
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
)
},
headlineContent = {
Text(
@ -229,7 +234,7 @@ private fun FeatureRow(node: Node, feature: TelemetricFeature, hasLogs: Boolean,
},
) {
Icon(
imageVector = feature.logsType?.icon ?: feature.icon,
imageVector = vectorResource(feature.logsType?.icon ?: feature.icon),
modifier = Modifier.size(24.dp),
contentDescription = logsDescription,
tint = MaterialTheme.colorScheme.primary,

View file

@ -18,16 +18,6 @@
package org.meshtastic.feature.node.component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Air
import androidx.compose.material.icons.rounded.ElectricBolt
import androidx.compose.material.icons.rounded.Fingerprint
import androidx.compose.material.icons.rounded.Grass
import androidx.compose.material.icons.rounded.People
import androidx.compose.material.icons.rounded.Router
import androidx.compose.material.icons.rounded.Thermostat
import androidx.compose.material.icons.rounded.WaterDrop
import androidx.compose.material.icons.rounded.Work
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -45,6 +35,16 @@ import org.meshtastic.core.resources.role
import org.meshtastic.core.resources.soil_moisture
import org.meshtastic.core.resources.soil_temperature
import org.meshtastic.core.resources.temperature
import org.meshtastic.core.ui.icon.AirQuality
import org.meshtastic.core.ui.icon.ElectricPower
import org.meshtastic.core.ui.icon.HardwareModel
import org.meshtastic.core.ui.icon.Humidity
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.NodeId
import org.meshtastic.core.ui.icon.PeopleCount
import org.meshtastic.core.ui.icon.Role
import org.meshtastic.core.ui.icon.SoilMoisture
import org.meshtastic.core.ui.icon.Temperature
@Composable
fun TemperatureInfo(
@ -54,7 +54,7 @@ fun TemperatureInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Thermostat,
icon = MeshtasticIcons.Temperature,
contentDescription = stringResource(Res.string.env_metrics_log),
label = stringResource(Res.string.temperature),
text = temp,
@ -70,7 +70,7 @@ fun HumidityInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.WaterDrop,
icon = MeshtasticIcons.Humidity,
contentDescription = stringResource(Res.string.env_metrics_log),
label = stringResource(Res.string.humidity),
text = humidity,
@ -86,7 +86,7 @@ fun SoilTemperatureInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Grass,
icon = MeshtasticIcons.SoilMoisture,
contentDescription = stringResource(Res.string.env_metrics_log),
label = stringResource(Res.string.soil_temperature),
text = temp,
@ -102,7 +102,7 @@ fun SoilMoistureInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Grass,
icon = MeshtasticIcons.SoilMoisture,
contentDescription = stringResource(Res.string.env_metrics_log),
label = stringResource(Res.string.soil_moisture),
text = moisture,
@ -118,7 +118,7 @@ fun PaxcountInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.People,
icon = MeshtasticIcons.PeopleCount,
contentDescription = stringResource(Res.string.pax_metrics_log),
label = stringResource(Res.string.pax),
text = pax,
@ -134,7 +134,7 @@ fun AirQualityInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Air,
icon = MeshtasticIcons.AirQuality,
contentDescription = stringResource(Res.string.env_metrics_log),
label = stringResource(Res.string.iaq),
text = iaq,
@ -151,7 +151,7 @@ fun PowerInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.ElectricBolt,
icon = MeshtasticIcons.ElectricPower,
contentDescription = stringResource(Res.string.env_metrics_log),
label = label,
text = value,
@ -167,7 +167,7 @@ fun HardwareInfo(
) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Router,
icon = MeshtasticIcons.HardwareModel,
contentDescription = stringResource(Res.string.hardware_model),
text = hwModel,
style = MaterialTheme.typography.labelSmall,
@ -179,7 +179,7 @@ fun HardwareInfo(
fun RoleInfo(role: String, modifier: Modifier = Modifier, contentColor: Color = MaterialTheme.colorScheme.onSurface) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Work,
icon = MeshtasticIcons.Role,
contentDescription = stringResource(Res.string.role),
text = role,
style = MaterialTheme.typography.labelSmall,
@ -191,7 +191,7 @@ fun RoleInfo(role: String, modifier: Modifier = Modifier, contentColor: Color =
fun NodeIdInfo(id: String, modifier: Modifier = Modifier, contentColor: Color = MaterialTheme.colorScheme.onSurface) {
IconInfo(
modifier = modifier,
icon = Icons.Rounded.Fingerprint,
icon = MeshtasticIcons.NodeId,
contentDescription = stringResource(Res.string.node_id),
text = id,
style = MaterialTheme.typography.labelSmall,

View file

@ -29,10 +29,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.List
import androidx.compose.material.icons.rounded.BarChart
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@ -80,6 +76,9 @@ import org.meshtastic.core.resources.logs
import org.meshtastic.core.resources.max
import org.meshtastic.core.resources.min
import org.meshtastic.core.ui.component.MainAppBar
import org.meshtastic.core.ui.icon.BarChart
import org.meshtastic.core.ui.icon.Info
import org.meshtastic.core.ui.icon.List
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Refresh
@ -260,9 +259,9 @@ fun <T> BaseMetricScreen(
Icon(
imageVector =
if (isChartExpanded) {
Icons.AutoMirrored.Rounded.List
MeshtasticIcons.List
} else {
Icons.Rounded.BarChart
MeshtasticIcons.BarChart
},
contentDescription =
stringResource(
@ -272,7 +271,10 @@ fun <T> BaseMetricScreen(
}
if (infoData.isNotEmpty()) {
IconButton(onClick = { displayInfoDialog = true }) {
Icon(imageVector = Icons.Rounded.Info, contentDescription = stringResource(Res.string.info))
Icon(
imageVector = MeshtasticIcons.Info,
contentDescription = stringResource(Res.string.info),
)
}
}
if (telemetryType != null) {

View file

@ -33,8 +33,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon
@ -63,6 +61,8 @@ import org.meshtastic.core.resources.close
import org.meshtastic.core.resources.info
import org.meshtastic.core.resources.rssi
import org.meshtastic.core.resources.snr
import org.meshtastic.core.ui.icon.Info
import org.meshtastic.core.ui.icon.MeshtasticIcons
import kotlin.time.Duration.Companion.days
object CommonCharts {
@ -196,7 +196,7 @@ fun Legend(
@Composable
fun LegendInfoDialog(infoData: List<InfoDialogData>, onDismiss: () -> Unit) {
AlertDialog(
icon = { Icon(imageVector = Icons.Rounded.Info, contentDescription = null) },
icon = { Icon(imageVector = MeshtasticIcons.Info, contentDescription = null) },
title = {
Text(
text = stringResource(Res.string.info),

View file

@ -67,7 +67,7 @@ import org.meshtastic.core.resources.uptime
import org.meshtastic.core.resources.wifi_devices
import org.meshtastic.core.ui.component.IconInfo
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Paxcount
import org.meshtastic.core.ui.icon.PeopleCount
import org.meshtastic.core.ui.theme.GraphColors.Orange
import org.meshtastic.core.ui.theme.GraphColors.Purple
import org.meshtastic.proto.Paxcount as ProtoPaxcount
@ -242,7 +242,7 @@ fun PaxcountInfo(
) {
IconInfo(
modifier = modifier,
icon = MeshtasticIcons.Paxcount,
icon = MeshtasticIcons.PeopleCount,
contentDescription = stringResource(Res.string.pax_metrics_log),
text = pax,
contentColor = contentColor,

View file

@ -16,16 +16,7 @@
*/
package org.meshtastic.feature.node.model
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ChargingStation
import androidx.compose.material.icons.rounded.Groups
import androidx.compose.material.icons.rounded.LocationOn
import androidx.compose.material.icons.rounded.Map
import androidx.compose.material.icons.rounded.Memory
import androidx.compose.material.icons.rounded.Power
import androidx.compose.material.icons.rounded.SignalCellularAlt
import androidx.compose.material.icons.rounded.Thermostat
import androidx.compose.ui.graphics.vector.ImageVector
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.meshtastic.core.navigation.NodeDetailRoutes
import org.meshtastic.core.navigation.Route
@ -33,6 +24,16 @@ import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.device_metrics_log
import org.meshtastic.core.resources.env_metrics_log
import org.meshtastic.core.resources.host_metrics_log
import org.meshtastic.core.resources.ic_charging_station
import org.meshtastic.core.resources.ic_groups
import org.meshtastic.core.resources.ic_location_on
import org.meshtastic.core.resources.ic_map
import org.meshtastic.core.resources.ic_memory
import org.meshtastic.core.resources.ic_people
import org.meshtastic.core.resources.ic_power
import org.meshtastic.core.resources.ic_route
import org.meshtastic.core.resources.ic_signal_cellular_alt
import org.meshtastic.core.resources.ic_thermostat
import org.meshtastic.core.resources.neighbor_info
import org.meshtastic.core.resources.node_map
import org.meshtastic.core.resources.pax_metrics_log
@ -40,19 +41,16 @@ import org.meshtastic.core.resources.position_log
import org.meshtastic.core.resources.power_metrics_log
import org.meshtastic.core.resources.signal_quality
import org.meshtastic.core.resources.traceroute_log
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.icon.Paxcount
import org.meshtastic.core.ui.icon.Route
enum class LogsType(val titleRes: StringResource, val icon: ImageVector, val routeFactory: (Int) -> Route) {
DEVICE(Res.string.device_metrics_log, Icons.Rounded.ChargingStation, { NodeDetailRoutes.DeviceMetrics(it) }),
NODE_MAP(Res.string.node_map, Icons.Rounded.Map, { NodeDetailRoutes.NodeMap(it) }),
POSITIONS(Res.string.position_log, Icons.Rounded.LocationOn, { NodeDetailRoutes.PositionLog(it) }),
ENVIRONMENT(Res.string.env_metrics_log, Icons.Rounded.Thermostat, { NodeDetailRoutes.EnvironmentMetrics(it) }),
SIGNAL(Res.string.signal_quality, Icons.Rounded.SignalCellularAlt, { NodeDetailRoutes.SignalMetrics(it) }),
POWER(Res.string.power_metrics_log, Icons.Rounded.Power, { NodeDetailRoutes.PowerMetrics(it) }),
TRACEROUTE(Res.string.traceroute_log, MeshtasticIcons.Route, { NodeDetailRoutes.TracerouteLog(it) }),
NEIGHBOR_INFO(Res.string.neighbor_info, Icons.Rounded.Groups, { NodeDetailRoutes.NeighborInfoLog(it) }),
HOST(Res.string.host_metrics_log, Icons.Rounded.Memory, { NodeDetailRoutes.HostMetricsLog(it) }),
PAX(Res.string.pax_metrics_log, MeshtasticIcons.Paxcount, { NodeDetailRoutes.PaxMetrics(it) }),
enum class LogsType(val titleRes: StringResource, val icon: DrawableResource, val routeFactory: (Int) -> Route) {
DEVICE(Res.string.device_metrics_log, Res.drawable.ic_charging_station, { NodeDetailRoutes.DeviceMetrics(it) }),
NODE_MAP(Res.string.node_map, Res.drawable.ic_map, { NodeDetailRoutes.NodeMap(it) }),
POSITIONS(Res.string.position_log, Res.drawable.ic_location_on, { NodeDetailRoutes.PositionLog(it) }),
ENVIRONMENT(Res.string.env_metrics_log, Res.drawable.ic_thermostat, { NodeDetailRoutes.EnvironmentMetrics(it) }),
SIGNAL(Res.string.signal_quality, Res.drawable.ic_signal_cellular_alt, { NodeDetailRoutes.SignalMetrics(it) }),
POWER(Res.string.power_metrics_log, Res.drawable.ic_power, { NodeDetailRoutes.PowerMetrics(it) }),
TRACEROUTE(Res.string.traceroute_log, Res.drawable.ic_route, { NodeDetailRoutes.TracerouteLog(it) }),
NEIGHBOR_INFO(Res.string.neighbor_info, Res.drawable.ic_groups, { NodeDetailRoutes.NeighborInfoLog(it) }),
HOST(Res.string.host_metrics_log, Res.drawable.ic_memory, { NodeDetailRoutes.HostMetricsLog(it) }),
PAX(Res.string.pax_metrics_log, Res.drawable.ic_people, { NodeDetailRoutes.PaxMetrics(it) }),
}

View file

@ -16,25 +16,15 @@
*/
package org.meshtastic.feature.node.navigation
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.CellTower
import androidx.compose.material.icons.rounded.Groups
import androidx.compose.material.icons.rounded.LightMode
import androidx.compose.material.icons.rounded.LocationOn
import androidx.compose.material.icons.rounded.Memory
import androidx.compose.material.icons.rounded.People
import androidx.compose.material.icons.rounded.PermScanWifi
import androidx.compose.material.icons.rounded.Power
import androidx.compose.material.icons.rounded.Router
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.navigation3.ListDetailSceneStrategy
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavBackStack
import androidx.navigation3.runtime.NavKey
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.koin.compose.viewmodel.koinViewModel
import org.koin.core.parameter.parametersOf
@ -46,6 +36,15 @@ import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.device
import org.meshtastic.core.resources.environment
import org.meshtastic.core.resources.host
import org.meshtastic.core.resources.ic_cell_tower
import org.meshtastic.core.resources.ic_groups
import org.meshtastic.core.resources.ic_light_mode
import org.meshtastic.core.resources.ic_location_on
import org.meshtastic.core.resources.ic_memory
import org.meshtastic.core.resources.ic_people
import org.meshtastic.core.resources.ic_perm_scan_wifi
import org.meshtastic.core.resources.ic_power
import org.meshtastic.core.resources.ic_router
import org.meshtastic.core.resources.neighbor_info
import org.meshtastic.core.resources.pax
import org.meshtastic.core.resources.position_log
@ -196,61 +195,61 @@ private inline fun <reified R : Route> EntryProviderScope<NavKey>.addNodeDetailS
enum class NodeDetailRoute(
val title: StringResource,
val routeClass: KClass<out Route>,
val icon: ImageVector?,
val icon: DrawableResource? = null,
val screenComposable: @Composable (metricsViewModel: MetricsViewModel, onNavigateUp: () -> Unit) -> Unit,
) {
DEVICE(
Res.string.device,
NodeDetailRoutes.DeviceMetrics::class,
Icons.Rounded.Router,
Res.drawable.ic_router,
{ metricsVM, onNavigateUp -> DeviceMetricsScreen(metricsVM, onNavigateUp) },
),
POSITION_LOG(
Res.string.position_log,
NodeDetailRoutes.PositionLog::class,
Icons.Rounded.LocationOn,
Res.drawable.ic_location_on,
{ metricsVM, onNavigateUp -> PositionLogScreen(metricsVM, onNavigateUp) },
),
ENVIRONMENT(
Res.string.environment,
NodeDetailRoutes.EnvironmentMetrics::class,
Icons.Rounded.LightMode,
Res.drawable.ic_light_mode,
{ metricsVM, onNavigateUp -> EnvironmentMetricsScreen(metricsVM, onNavigateUp) },
),
SIGNAL(
Res.string.signal,
NodeDetailRoutes.SignalMetrics::class,
Icons.Rounded.CellTower,
Res.drawable.ic_cell_tower,
{ metricsVM, onNavigateUp -> SignalMetricsScreen(metricsVM, onNavigateUp) },
),
TRACEROUTE(
Res.string.traceroute,
NodeDetailRoutes.TracerouteLog::class,
Icons.Rounded.PermScanWifi,
Res.drawable.ic_perm_scan_wifi,
{ metricsVM, onNavigateUp -> TracerouteLogScreen(viewModel = metricsVM, onNavigateUp = onNavigateUp) },
),
NEIGHBOR_INFO(
Res.string.neighbor_info,
NodeDetailRoutes.NeighborInfoLog::class,
Icons.Rounded.Groups,
Res.drawable.ic_groups,
{ metricsVM, onNavigateUp -> NeighborInfoLogScreen(viewModel = metricsVM, onNavigateUp = onNavigateUp) },
),
POWER(
Res.string.power,
NodeDetailRoutes.PowerMetrics::class,
Icons.Rounded.Power,
Res.drawable.ic_power,
{ metricsVM, onNavigateUp -> PowerMetricsScreen(metricsVM, onNavigateUp) },
),
HOST(
Res.string.host,
NodeDetailRoutes.HostMetricsLog::class,
Icons.Rounded.Memory,
{ metricsVM, onNavigateUp -> HostMetricsLogScreen(viewModel = metricsVM, onNavigateUp = onNavigateUp) },
Res.drawable.ic_memory,
{ metricsVM, onNavigateUp -> HostMetricsLogScreen(metricsVM, onNavigateUp) },
),
PAX(
Res.string.pax,
NodeDetailRoutes.PaxMetrics::class,
Icons.Rounded.People,
Res.drawable.ic_people,
{ metricsVM, onNavigateUp -> PaxMetricsScreen(metricsVM, onNavigateUp) },
),
}