mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Alias strings R to Res (#3619)
This commit is contained in:
parent
a687328f08
commit
0833a6767e
153 changed files with 1403 additions and 1350 deletions
|
|
@ -33,7 +33,6 @@ import org.meshtastic.core.database.model.Node
|
|||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.service.ServiceAction
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.InsetDivider
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
|
|
@ -44,6 +43,7 @@ import org.meshtastic.core.ui.theme.StatusColors.StatusYellow
|
|||
import org.meshtastic.feature.node.model.MetricsState
|
||||
import org.meshtastic.feature.node.model.NodeDetailAction
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
|
|
@ -54,9 +54,9 @@ fun AdministrationSection(
|
|||
onFirmwareSelect: (FirmwareRelease) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
TitledCard(stringResource(R.string.administration), modifier = modifier) {
|
||||
TitledCard(stringResource(Res.string.administration), modifier = modifier) {
|
||||
ListItem(
|
||||
text = stringResource(R.string.request_metadata),
|
||||
text = stringResource(Res.string.request_metadata),
|
||||
leadingIcon = Icons.Default.Memory,
|
||||
trailingIcon = null,
|
||||
onClick = { onAction(NodeDetailAction.TriggerServiceAction(ServiceAction.GetDeviceMetadata(node.num))) },
|
||||
|
|
@ -65,7 +65,7 @@ fun AdministrationSection(
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.remote_admin),
|
||||
text = stringResource(Res.string.remote_admin),
|
||||
leadingIcon = Icons.Default.Settings,
|
||||
enabled = metricsState.isLocal || node.metadata != null,
|
||||
) {
|
||||
|
|
@ -75,7 +75,7 @@ fun AdministrationSection(
|
|||
val firmwareVersion = node.metadata?.firmwareVersion
|
||||
val firmwareEdition = metricsState.firmwareEdition
|
||||
if (firmwareVersion != null || (firmwareEdition != null && metricsState.isLocal)) {
|
||||
TitledCard(stringResource(R.string.firmware)) {
|
||||
TitledCard(stringResource(Res.string.firmware)) {
|
||||
firmwareEdition?.let {
|
||||
val icon =
|
||||
when (it) {
|
||||
|
|
@ -84,7 +84,7 @@ fun AdministrationSection(
|
|||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.firmware_edition),
|
||||
text = stringResource(Res.string.firmware_edition),
|
||||
leadingIcon = icon,
|
||||
supportingText = it.name,
|
||||
copyable = true,
|
||||
|
|
@ -101,7 +101,7 @@ fun AdministrationSection(
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.installed_firmware_version),
|
||||
text = stringResource(Res.string.installed_firmware_version),
|
||||
leadingIcon = Icons.Default.Memory,
|
||||
supportingText = firmwareVersion.substringBeforeLast("."),
|
||||
copyable = true,
|
||||
|
|
@ -112,7 +112,7 @@ fun AdministrationSection(
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.latest_stable_firmware),
|
||||
text = stringResource(Res.string.latest_stable_firmware),
|
||||
leadingIcon = Icons.Default.Memory,
|
||||
supportingText = latestStable.id.substringBeforeLast(".").replace("v", ""),
|
||||
copyable = true,
|
||||
|
|
@ -124,7 +124,7 @@ fun AdministrationSection(
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.latest_alpha_firmware),
|
||||
text = stringResource(Res.string.latest_alpha_firmware),
|
||||
leadingIcon = Icons.Default.Memory,
|
||||
supportingText = latestAlpha.id.substringBeforeLast(".").replace("v", ""),
|
||||
copyable = true,
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.InsetDivider
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.SwitchListItem
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.feature.node.model.NodeDetailAction
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun DeviceActions(
|
||||
|
|
@ -67,9 +67,9 @@ fun DeviceActions(
|
|||
onConfirmIgnore = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.Ignore(it))) },
|
||||
onConfirmRemove = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.Remove(it))) },
|
||||
)
|
||||
TitledCard(title = stringResource(R.string.actions), modifier = modifier) {
|
||||
TitledCard(title = stringResource(Res.string.actions), modifier = modifier) {
|
||||
ListItem(
|
||||
text = stringResource(R.string.share_contact),
|
||||
text = stringResource(Res.string.share_contact),
|
||||
leadingIcon = Icons.Rounded.QrCode2,
|
||||
trailingIcon = null,
|
||||
onClick = { onAction(NodeDetailAction.ShareContact) },
|
||||
|
|
@ -82,7 +82,7 @@ fun DeviceActions(
|
|||
InsetDivider()
|
||||
|
||||
SwitchListItem(
|
||||
text = stringResource(R.string.favorite),
|
||||
text = stringResource(Res.string.favorite),
|
||||
leadingIcon = if (node.isFavorite) Icons.Default.Star else Icons.Default.StarBorder,
|
||||
leadingIconTint = if (node.isFavorite) Color.Yellow else LocalContentColor.current,
|
||||
checked = node.isFavorite,
|
||||
|
|
@ -92,7 +92,7 @@ fun DeviceActions(
|
|||
InsetDivider()
|
||||
|
||||
SwitchListItem(
|
||||
text = stringResource(R.string.ignore),
|
||||
text = stringResource(Res.string.ignore),
|
||||
leadingIcon =
|
||||
if (node.isIgnored) Icons.AutoMirrored.Outlined.VolumeMute else Icons.AutoMirrored.Default.VolumeUp,
|
||||
checked = node.isIgnored,
|
||||
|
|
@ -102,7 +102,7 @@ fun DeviceActions(
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.remove),
|
||||
text = stringResource(Res.string.remove),
|
||||
leadingIcon = Icons.Rounded.Delete,
|
||||
trailingIcon = null,
|
||||
onClick = { displayRemoveDialog = true },
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@ import androidx.compose.ui.unit.dp
|
|||
import coil3.compose.AsyncImage
|
||||
import coil3.request.ImageRequest
|
||||
import org.meshtastic.core.model.DeviceHardware
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.InsetDivider
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
|
||||
import org.meshtastic.feature.node.model.MetricsState
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun DeviceDetailsSection(state: MetricsState, modifier: Modifier = Modifier) {
|
||||
|
|
@ -58,7 +58,7 @@ fun DeviceDetailsSection(state: MetricsState, modifier: Modifier = Modifier) {
|
|||
val deviceHardware = state.deviceHardware ?: return
|
||||
val hwModelName = deviceHardware.displayName
|
||||
val isSupported = deviceHardware.activelySupported
|
||||
TitledCard(stringResource(R.string.device), modifier = modifier) {
|
||||
TitledCard(stringResource(Res.string.device), modifier = modifier) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Box(
|
||||
|
|
@ -77,7 +77,7 @@ fun DeviceDetailsSection(state: MetricsState, modifier: Modifier = Modifier) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.hardware),
|
||||
text = stringResource(Res.string.hardware),
|
||||
leadingIcon = Icons.Default.Router,
|
||||
supportingText = hwModelName,
|
||||
copyable = true,
|
||||
|
|
@ -89,9 +89,9 @@ fun DeviceDetailsSection(state: MetricsState, modifier: Modifier = Modifier) {
|
|||
ListItem(
|
||||
text =
|
||||
if (isSupported) {
|
||||
stringResource(R.string.supported)
|
||||
stringResource(Res.string.supported)
|
||||
} else {
|
||||
stringResource(R.string.supported_by_community)
|
||||
stringResource(Res.string.supported_by_community)
|
||||
},
|
||||
leadingIcon =
|
||||
if (isSupported) {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun DistanceInfo(
|
||||
|
|
@ -37,7 +37,7 @@ fun DistanceInfo(
|
|||
IconInfo(
|
||||
modifier = modifier,
|
||||
icon = Icons.Rounded.SocialDistance,
|
||||
contentDescription = stringResource(R.string.distance),
|
||||
contentDescription = stringResource(Res.string.distance),
|
||||
text = distance,
|
||||
contentColor = contentColor,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -25,23 +25,23 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import org.meshtastic.core.model.util.metersIn
|
||||
import org.meshtastic.core.model.util.toString
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.icon.Elevation
|
||||
import org.meshtastic.core.ui.icon.MeshtasticIcons
|
||||
import org.meshtastic.proto.ConfigProtos.Config.DisplayConfig.DisplayUnits
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun ElevationInfo(
|
||||
modifier: Modifier = Modifier,
|
||||
altitude: Int,
|
||||
system: DisplayUnits,
|
||||
suffix: String = stringResource(R.string.elevation_suffix),
|
||||
suffix: String = stringResource(Res.string.elevation_suffix),
|
||||
contentColor: Color = MaterialTheme.colorScheme.onSurface,
|
||||
) {
|
||||
IconInfo(
|
||||
modifier = modifier,
|
||||
icon = MeshtasticIcons.Elevation,
|
||||
contentDescription = stringResource(R.string.altitude),
|
||||
contentDescription = stringResource(Res.string.altitude),
|
||||
text = altitude.metersIn(system).toString(system) + " " + suffix,
|
||||
contentColor = contentColor,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ import org.meshtastic.core.model.util.UnitConversions
|
|||
import org.meshtastic.core.model.util.UnitConversions.toTempString
|
||||
import org.meshtastic.core.model.util.toSmallDistanceString
|
||||
import org.meshtastic.core.model.util.toSpeedString
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.node.model.DrawableMetricInfo
|
||||
import org.meshtastic.feature.node.model.VectorMetricInfo
|
||||
import org.meshtastic.proto.ConfigProtos
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("CyclomaticComplexMethod", "LongMethod")
|
||||
@Composable
|
||||
|
|
@ -60,7 +60,7 @@ internal fun EnvironmentMetrics(
|
|||
if (hasTemperature()) {
|
||||
add(
|
||||
VectorMetricInfo(
|
||||
R.string.temperature,
|
||||
Res.string.temperature,
|
||||
temperature.toTempString(isFahrenheit),
|
||||
Icons.Default.Thermostat,
|
||||
),
|
||||
|
|
@ -69,7 +69,7 @@ internal fun EnvironmentMetrics(
|
|||
if (hasRelativeHumidity()) {
|
||||
add(
|
||||
VectorMetricInfo(
|
||||
R.string.humidity,
|
||||
Res.string.humidity,
|
||||
"%.0f%%".format(relativeHumidity),
|
||||
Icons.Default.WaterDrop,
|
||||
),
|
||||
|
|
@ -78,7 +78,7 @@ internal fun EnvironmentMetrics(
|
|||
if (hasBarometricPressure()) {
|
||||
add(
|
||||
VectorMetricInfo(
|
||||
R.string.pressure,
|
||||
Res.string.pressure,
|
||||
"%.0f hPa".format(barometricPressure),
|
||||
Icons.Default.Speed,
|
||||
),
|
||||
|
|
@ -87,38 +87,38 @@ internal fun EnvironmentMetrics(
|
|||
if (hasGasResistance()) {
|
||||
add(
|
||||
VectorMetricInfo(
|
||||
R.string.gas_resistance,
|
||||
Res.string.gas_resistance,
|
||||
"%.0f MΩ".format(gasResistance),
|
||||
Icons.Default.BlurOn,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (hasVoltage()) {
|
||||
add(VectorMetricInfo(R.string.voltage, "%.2fV".format(voltage), Icons.Default.Bolt))
|
||||
add(VectorMetricInfo(Res.string.voltage, "%.2fV".format(voltage), Icons.Default.Bolt))
|
||||
}
|
||||
if (hasCurrent()) {
|
||||
add(VectorMetricInfo(R.string.current, "%.1fmA".format(current), Icons.Default.Power))
|
||||
add(VectorMetricInfo(Res.string.current, "%.1fmA".format(current), Icons.Default.Power))
|
||||
}
|
||||
if (hasIaq()) add(VectorMetricInfo(R.string.iaq, iaq.toString(), Icons.Default.Air))
|
||||
if (hasIaq()) add(VectorMetricInfo(Res.string.iaq, iaq.toString(), Icons.Default.Air))
|
||||
if (hasDistance()) {
|
||||
add(
|
||||
VectorMetricInfo(
|
||||
R.string.distance,
|
||||
Res.string.distance,
|
||||
distance.toSmallDistanceString(displayUnits),
|
||||
Icons.Default.Height,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (hasLux()) add(VectorMetricInfo(R.string.lux, "%.0f lx".format(lux), Icons.Default.LightMode))
|
||||
if (hasLux()) add(VectorMetricInfo(Res.string.lux, "%.0f lx".format(lux), Icons.Default.LightMode))
|
||||
if (hasUvLux()) {
|
||||
add(VectorMetricInfo(R.string.uv_lux, "%.0f lx".format(uvLux), Icons.Default.LightMode))
|
||||
add(VectorMetricInfo(Res.string.uv_lux, "%.0f lx".format(uvLux), Icons.Default.LightMode))
|
||||
}
|
||||
if (hasWindSpeed()) {
|
||||
@Suppress("MagicNumber")
|
||||
val normalizedBearing = (windDirection + 180) % 360
|
||||
add(
|
||||
VectorMetricInfo(
|
||||
R.string.wind,
|
||||
Res.string.wind,
|
||||
windSpeed.toSpeedString(displayUnits),
|
||||
Icons.Outlined.Navigation,
|
||||
normalizedBearing.toFloat(),
|
||||
|
|
@ -126,7 +126,7 @@ internal fun EnvironmentMetrics(
|
|||
)
|
||||
}
|
||||
if (hasWeight()) {
|
||||
add(VectorMetricInfo(R.string.weight, "%.2f kg".format(weight), Icons.Default.Scale))
|
||||
add(VectorMetricInfo(Res.string.weight, "%.2f kg".format(weight), Icons.Default.Scale))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ internal fun EnvironmentMetrics(
|
|||
val dewPoint = UnitConversions.calculateDewPoint(temperature, relativeHumidity)
|
||||
add(
|
||||
DrawableMetricInfo(
|
||||
R.string.dew_point,
|
||||
Res.string.dew_point,
|
||||
dewPoint.toTempString(isFahrenheit),
|
||||
org.meshtastic.feature.node.R.drawable.ic_outlined_dew_point_24,
|
||||
),
|
||||
|
|
@ -148,7 +148,7 @@ internal fun EnvironmentMetrics(
|
|||
if (hasSoilTemperature()) {
|
||||
add(
|
||||
DrawableMetricInfo(
|
||||
R.string.soil_temperature,
|
||||
Res.string.soil_temperature,
|
||||
soilTemperature.toTempString(isFahrenheit),
|
||||
org.meshtastic.feature.node.R.drawable.soil_temperature,
|
||||
),
|
||||
|
|
@ -157,7 +157,7 @@ internal fun EnvironmentMetrics(
|
|||
if (hasSoilMoisture()) {
|
||||
add(
|
||||
DrawableMetricInfo(
|
||||
R.string.soil_moisture,
|
||||
Res.string.soil_moisture,
|
||||
"%d%%".format(soilMoisture),
|
||||
org.meshtastic.feature.node.R.drawable.soil_moisture,
|
||||
),
|
||||
|
|
@ -166,7 +166,7 @@ internal fun EnvironmentMetrics(
|
|||
if (hasRadiation()) {
|
||||
add(
|
||||
DrawableMetricInfo(
|
||||
R.string.radiation,
|
||||
Res.string.radiation,
|
||||
"%.1f µR/h".format(radiation),
|
||||
org.meshtastic.feature.node.R.drawable.ic_filled_radioactive_24,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.core.net.toUri
|
||||
import com.mikepenz.markdown.m3.Markdown
|
||||
import org.meshtastic.core.database.entity.FirmwareRelease
|
||||
import org.meshtastic.core.strings.R
|
||||
import timber.log.Timber
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun FirmwareReleaseSheetContent(firmwareRelease: FirmwareRelease, modifier: Modifier = Modifier) {
|
||||
|
|
@ -64,15 +64,15 @@ fun FirmwareReleaseSheetContent(firmwareRelease: FirmwareRelease, modifier: Modi
|
|||
val intent = Intent(Intent.ACTION_VIEW, firmwareRelease.pageUrl.toUri())
|
||||
context.startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Toast.makeText(context, R.string.error_no_app_to_handle_link, Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(context, Res.string.error_no_app_to_handle_link, Toast.LENGTH_LONG).show()
|
||||
Timber.e(e)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Link, contentDescription = stringResource(R.string.view_release))
|
||||
Icon(imageVector = Icons.Default.Link, contentDescription = stringResource(Res.string.view_release))
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.view_release))
|
||||
Text(text = stringResource(Res.string.view_release))
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
|
|
@ -80,15 +80,15 @@ fun FirmwareReleaseSheetContent(firmwareRelease: FirmwareRelease, modifier: Modi
|
|||
val intent = Intent(Intent.ACTION_VIEW, firmwareRelease.zipUrl.toUri())
|
||||
context.startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Toast.makeText(context, R.string.error_no_app_to_handle_link, Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(context, Res.string.error_no_app_to_handle_link, Toast.LENGTH_LONG).show()
|
||||
Timber.e(e)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Download, contentDescription = stringResource(R.string.download))
|
||||
Icon(imageVector = Icons.Default.Download, contentDescription = stringResource(Res.string.download))
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.download))
|
||||
Text(text = stringResource(Res.string.download))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
|||
import org.meshtastic.core.model.util.formatAgo
|
||||
import org.meshtastic.core.ui.R
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun LastHeardInfo(
|
||||
|
|
@ -39,7 +40,7 @@ fun LastHeardInfo(
|
|||
IconInfo(
|
||||
modifier = modifier,
|
||||
icon = ImageVector.vectorResource(id = R.drawable.ic_antenna_24),
|
||||
contentDescription = stringResource(org.meshtastic.core.strings.R.string.node_sort_last_heard),
|
||||
contentDescription = stringResource(Res.string.node_sort_last_heard),
|
||||
text = formatAgo(lastHeard, currentTimeMillis),
|
||||
contentColor = contentColor,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ import kotlinx.coroutines.launch
|
|||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.util.GPSFormat
|
||||
import org.meshtastic.core.model.util.formatAgo
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.BasicListItem
|
||||
import org.meshtastic.core.ui.component.icon
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import timber.log.Timber
|
||||
import java.net.URLEncoder
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
|
|
@ -56,7 +56,7 @@ fun LinkedCoordinatesItem(node: Node) {
|
|||
val coordinates = GPSFormat.toDec(node.latitude, node.longitude)
|
||||
|
||||
BasicListItem(
|
||||
text = stringResource(R.string.last_position_update),
|
||||
text = stringResource(Res.string.last_position_update),
|
||||
leadingIcon = Icons.Default.LocationOn,
|
||||
supportingText = "$ago • $coordinates",
|
||||
trailingContent = Icons.AutoMirrored.Rounded.KeyboardArrowRight.icon(),
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.feature.node.model.LogsType
|
||||
import org.meshtastic.feature.node.model.MetricsState
|
||||
import org.meshtastic.feature.node.model.NodeDetailAction
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
@Suppress("MultipleEmitters")
|
||||
|
|
@ -41,13 +41,13 @@ fun MetricsSection(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (node.hasEnvironmentMetrics) {
|
||||
TitledCard(stringResource(R.string.environment), modifier = modifier) {}
|
||||
TitledCard(stringResource(Res.string.environment), modifier = modifier) {}
|
||||
EnvironmentMetrics(node, isFahrenheit = metricsState.isFahrenheit, displayUnits = metricsState.displayUnits)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
if (node.hasPowerMetrics) {
|
||||
TitledCard(stringResource(R.string.power), modifier = modifier) {}
|
||||
TitledCard(stringResource(Res.string.power), modifier = modifier) {}
|
||||
PowerMetrics(node)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ fun MetricsSection(
|
|||
val nonPositionLogs = availableLogs.filter { it != LogsType.NODE_MAP && it != LogsType.POSITIONS }
|
||||
|
||||
if (nonPositionLogs.isNotEmpty()) {
|
||||
TitledCard(title = stringResource(R.string.logs), modifier = modifier) {
|
||||
TitledCard(title = stringResource(Res.string.logs), modifier = modifier) {
|
||||
nonPositionLogs.forEach { type ->
|
||||
ListItem(text = stringResource(type.titleRes), leadingIcon = type.icon) {
|
||||
onAction(NodeDetailAction.Navigate(type.route))
|
||||
|
|
|
|||
|
|
@ -44,32 +44,32 @@ import androidx.compose.ui.unit.dp
|
|||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.util.formatAgo
|
||||
import org.meshtastic.core.model.util.formatUptime
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.InsetDivider
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.feature.node.model.isEffectivelyUnmessageable
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun NodeDetailsSection(node: Node, modifier: Modifier = Modifier) {
|
||||
TitledCard(title = stringResource(R.string.details), modifier = modifier) {
|
||||
TitledCard(title = stringResource(Res.string.details), modifier = modifier) {
|
||||
if (node.mismatchKey) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.KeyOff,
|
||||
contentDescription = stringResource(R.string.encryption_error),
|
||||
contentDescription = stringResource(Res.string.encryption_error),
|
||||
tint = Color.Red,
|
||||
)
|
||||
Spacer(Modifier.width(12.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.encryption_error),
|
||||
text = stringResource(Res.string.encryption_error),
|
||||
style = MaterialTheme.typography.titleLarge.copy(color = Color.Red),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.encryption_error_text),
|
||||
text = stringResource(Res.string.encryption_error_text),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
|
@ -82,7 +82,7 @@ fun NodeDetailsSection(node: Node, modifier: Modifier = Modifier) {
|
|||
@Composable
|
||||
private fun MainNodeDetails(node: Node) {
|
||||
ListItem(
|
||||
text = stringResource(R.string.long_name),
|
||||
text = stringResource(Res.string.long_name),
|
||||
leadingIcon = Icons.TwoTone.Person,
|
||||
supportingText = node.user.longName.ifEmpty { "???" },
|
||||
copyable = true,
|
||||
|
|
@ -92,7 +92,7 @@ private fun MainNodeDetails(node: Node) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.short_name),
|
||||
text = stringResource(Res.string.short_name),
|
||||
leadingIcon = Icons.Outlined.Person,
|
||||
supportingText = node.user.shortName.ifEmpty { "???" },
|
||||
copyable = true,
|
||||
|
|
@ -102,7 +102,7 @@ private fun MainNodeDetails(node: Node) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.node_number),
|
||||
text = stringResource(Res.string.node_number),
|
||||
leadingIcon = Icons.Default.Numbers,
|
||||
supportingText = node.num.toUInt().toString(),
|
||||
copyable = true,
|
||||
|
|
@ -112,7 +112,7 @@ private fun MainNodeDetails(node: Node) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.user_id),
|
||||
text = stringResource(Res.string.user_id),
|
||||
leadingIcon = Icons.Default.Person,
|
||||
supportingText = node.user.id,
|
||||
copyable = true,
|
||||
|
|
@ -122,7 +122,7 @@ private fun MainNodeDetails(node: Node) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.role),
|
||||
text = stringResource(Res.string.role),
|
||||
leadingIcon = Icons.Default.Work,
|
||||
supportingText = node.user.role.name,
|
||||
trailingIcon = null,
|
||||
|
|
@ -132,7 +132,7 @@ private fun MainNodeDetails(node: Node) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.unmonitored_or_infrastructure),
|
||||
text = stringResource(Res.string.unmonitored_or_infrastructure),
|
||||
leadingIcon = Icons.Outlined.NoCell,
|
||||
trailingIcon = null,
|
||||
)
|
||||
|
|
@ -141,7 +141,7 @@ private fun MainNodeDetails(node: Node) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.uptime),
|
||||
text = stringResource(Res.string.uptime),
|
||||
leadingIcon = Icons.Default.CheckCircle,
|
||||
supportingText = formatUptime(node.deviceMetrics.uptimeSeconds),
|
||||
trailingIcon = null,
|
||||
|
|
@ -151,7 +151,7 @@ private fun MainNodeDetails(node: Node) {
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.node_sort_last_heard),
|
||||
text = stringResource(Res.string.node_sort_last_heard),
|
||||
leadingIcon = Icons.Default.History,
|
||||
supportingText = formatAgo(node.lastHeard),
|
||||
trailingIcon = null,
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.database.model.NodeSortOption
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
|
|
@ -114,7 +114,7 @@ fun NodeFilterTextField(
|
|||
.padding(vertical = 16.dp, horizontal = 24.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.node_filter_ignored),
|
||||
text = stringResource(Res.string.node_filter_ignored),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
|
|
@ -135,20 +135,20 @@ private fun NodeFilterTextField(filterText: String, onTextChange: (String) -> Un
|
|||
value = filterText,
|
||||
placeholder = {
|
||||
Text(
|
||||
text = stringResource(R.string.node_filter_placeholder),
|
||||
text = stringResource(Res.string.node_filter_placeholder),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.35F),
|
||||
)
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(Icons.Default.Search, contentDescription = stringResource(R.string.node_filter_placeholder))
|
||||
Icon(Icons.Default.Search, contentDescription = stringResource(Res.string.node_filter_placeholder))
|
||||
},
|
||||
onValueChange = onTextChange,
|
||||
trailingIcon = {
|
||||
if (filterText.isNotEmpty() || isFocused) {
|
||||
Icon(
|
||||
Icons.Default.Clear,
|
||||
contentDescription = stringResource(R.string.desc_node_filter_clear),
|
||||
contentDescription = stringResource(Res.string.desc_node_filter_clear),
|
||||
modifier =
|
||||
Modifier.clickable {
|
||||
onTextChange("")
|
||||
|
|
@ -177,7 +177,7 @@ private fun NodeSortButton(
|
|||
IconButton(onClick = { expanded = true }) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.Sort,
|
||||
contentDescription = stringResource(R.string.node_sort_button),
|
||||
contentDescription = stringResource(Res.string.node_sort_button),
|
||||
modifier = Modifier.heightIn(max = 48.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
|
|
@ -188,7 +188,7 @@ private fun NodeSortButton(
|
|||
onDismissRequest = { expanded = false },
|
||||
modifier = Modifier.background(MaterialTheme.colorScheme.background.copy(alpha = 1f)),
|
||||
) {
|
||||
DropdownMenuTitle(text = stringResource(R.string.node_sort_title))
|
||||
DropdownMenuTitle(text = stringResource(Res.string.node_sort_title))
|
||||
|
||||
NodeSortOption.entries.forEach { sort ->
|
||||
DropdownMenuRadio(
|
||||
|
|
@ -200,28 +200,28 @@ private fun NodeSortButton(
|
|||
|
||||
HorizontalDivider(modifier = Modifier.padding(MenuDefaults.DropdownMenuItemContentPadding))
|
||||
|
||||
DropdownMenuTitle(text = stringResource(R.string.node_filter_title))
|
||||
DropdownMenuTitle(text = stringResource(Res.string.node_filter_title))
|
||||
|
||||
DropdownMenuCheck(
|
||||
text = stringResource(R.string.node_filter_include_unknown),
|
||||
text = stringResource(Res.string.node_filter_include_unknown),
|
||||
checked = toggles.includeUnknown,
|
||||
onClick = toggles.onToggleIncludeUnknown,
|
||||
)
|
||||
|
||||
DropdownMenuCheck(
|
||||
text = stringResource(R.string.node_filter_only_online),
|
||||
text = stringResource(Res.string.node_filter_only_online),
|
||||
checked = toggles.onlyOnline,
|
||||
onClick = toggles.onToggleOnlyOnline,
|
||||
)
|
||||
|
||||
DropdownMenuCheck(
|
||||
text = stringResource(R.string.node_filter_only_direct),
|
||||
text = stringResource(Res.string.node_filter_only_direct),
|
||||
checked = toggles.onlyDirect,
|
||||
onClick = toggles.onToggleOnlyDirect,
|
||||
)
|
||||
|
||||
DropdownMenuCheck(
|
||||
text = stringResource(R.string.node_filter_show_ignored),
|
||||
text = stringResource(Res.string.node_filter_show_ignored),
|
||||
checked = toggles.showIgnored,
|
||||
onClick = toggles.onToggleShowIgnored,
|
||||
trailing =
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ import androidx.compose.ui.unit.dp
|
|||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.database.model.isUnmessageableRole
|
||||
import org.meshtastic.core.model.util.toDistanceString
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MaterialBatteryInfo
|
||||
import org.meshtastic.core.ui.component.NodeChip
|
||||
import org.meshtastic.core.ui.component.NodeKeyStatusIcon
|
||||
|
|
@ -57,6 +56,7 @@ import org.meshtastic.core.ui.component.SignalInfo
|
|||
import org.meshtastic.core.ui.component.preview.NodePreviewParameterProvider
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.proto.ConfigProtos.Config.DisplayConfig
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
|
|
@ -74,7 +74,7 @@ fun NodeItem(
|
|||
) {
|
||||
val isFavorite = remember(thatNode) { thatNode.isFavorite }
|
||||
val isIgnored = thatNode.isIgnored
|
||||
val longName = thatNode.user.longName.ifEmpty { stringResource(R.string.unknown_username) }
|
||||
val longName = thatNode.user.longName.ifEmpty { stringResource(Res.string.unknown_username) }
|
||||
val isThisNode = remember(thatNode) { thisNode?.num == thatNode.num }
|
||||
val system = remember(distanceUnits) { DisplayConfig.DisplayUnits.forNumber(distanceUnits) }
|
||||
val distance =
|
||||
|
|
@ -165,7 +165,7 @@ fun NodeItem(
|
|||
ElevationInfo(
|
||||
altitude = position.altitude,
|
||||
system = system,
|
||||
suffix = stringResource(R.string.elevation_suffix),
|
||||
suffix = stringResource(Res.string.elevation_suffix),
|
||||
contentColor = contentColor,
|
||||
)
|
||||
val satCount = position.satsInView
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ package org.meshtastic.feature.node.component
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.SimpleAlertDialog
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun NodeActionDialogs(
|
||||
|
|
@ -36,10 +36,10 @@ fun NodeActionDialogs(
|
|||
) {
|
||||
if (displayFavoriteDialog) {
|
||||
SimpleAlertDialog(
|
||||
title = R.string.favorite,
|
||||
title = Res.string.favorite,
|
||||
text =
|
||||
stringResource(
|
||||
id = if (node.isFavorite) R.string.favorite_remove else R.string.favorite_add,
|
||||
id = if (node.isFavorite) Res.string.favorite_remove else Res.string.favorite_add,
|
||||
node.user.longName,
|
||||
),
|
||||
onConfirm = {
|
||||
|
|
@ -51,10 +51,10 @@ fun NodeActionDialogs(
|
|||
}
|
||||
if (displayIgnoreDialog) {
|
||||
SimpleAlertDialog(
|
||||
title = R.string.ignore,
|
||||
title = Res.string.ignore,
|
||||
text =
|
||||
stringResource(
|
||||
id = if (node.isIgnored) R.string.ignore_remove else R.string.ignore_add,
|
||||
id = if (node.isIgnored) Res.string.ignore_remove else Res.string.ignore_add,
|
||||
node.user.longName,
|
||||
),
|
||||
onConfirm = {
|
||||
|
|
@ -66,8 +66,8 @@ fun NodeActionDialogs(
|
|||
}
|
||||
if (displayRemoveDialog) {
|
||||
SimpleAlertDialog(
|
||||
title = R.string.remove,
|
||||
text = R.string.remove_node_text,
|
||||
title = Res.string.remove,
|
||||
text = Res.string.remove_node_text,
|
||||
onConfirm = {
|
||||
onDismissMenuRequest()
|
||||
onConfirmRemove(node)
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusYellow
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
|
|
@ -58,9 +58,9 @@ fun NodeStatusIcons(isThisNode: Boolean, isUnmessageable: Boolean, isFavorite: B
|
|||
Text(
|
||||
stringResource(
|
||||
if (isConnected) {
|
||||
R.string.connected
|
||||
Res.string.connected
|
||||
} else {
|
||||
R.string.disconnected
|
||||
Res.string.disconnected
|
||||
},
|
||||
),
|
||||
)
|
||||
|
|
@ -72,14 +72,14 @@ fun NodeStatusIcons(isThisNode: Boolean, isUnmessageable: Boolean, isFavorite: B
|
|||
@Suppress("MagicNumber")
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.CloudDone,
|
||||
contentDescription = stringResource(R.string.connected),
|
||||
contentDescription = stringResource(Res.string.connected),
|
||||
modifier = Modifier.size(24.dp), // Smaller size for badge
|
||||
tint = MaterialTheme.colorScheme.StatusGreen,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.CloudOff,
|
||||
contentDescription = stringResource(R.string.not_connected),
|
||||
contentDescription = stringResource(Res.string.not_connected),
|
||||
modifier = Modifier.size(24.dp), // Smaller size for badge
|
||||
tint = MaterialTheme.colorScheme.StatusRed,
|
||||
)
|
||||
|
|
@ -90,13 +90,13 @@ fun NodeStatusIcons(isThisNode: Boolean, isUnmessageable: Boolean, isFavorite: B
|
|||
if (isUnmessageable) {
|
||||
TooltipBox(
|
||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
|
||||
tooltip = { PlainTooltip { Text(stringResource(R.string.unmonitored_or_infrastructure)) } },
|
||||
tooltip = { PlainTooltip { Text(stringResource(Res.string.unmonitored_or_infrastructure)) } },
|
||||
state = rememberTooltipState(),
|
||||
) {
|
||||
IconButton(onClick = {}, modifier = Modifier.size(24.dp)) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.NoCell,
|
||||
contentDescription = stringResource(R.string.unmessageable),
|
||||
contentDescription = stringResource(Res.string.unmessageable),
|
||||
modifier = Modifier.size(24.dp), // Smaller size for badge
|
||||
)
|
||||
}
|
||||
|
|
@ -105,13 +105,13 @@ fun NodeStatusIcons(isThisNode: Boolean, isUnmessageable: Boolean, isFavorite: B
|
|||
if (isFavorite && !isThisNode) {
|
||||
TooltipBox(
|
||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
|
||||
tooltip = { PlainTooltip { Text(stringResource(R.string.favorite)) } },
|
||||
tooltip = { PlainTooltip { Text(stringResource(Res.string.favorite)) } },
|
||||
state = rememberTooltipState(),
|
||||
) {
|
||||
IconButton(onClick = {}, modifier = Modifier.size(24.dp)) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Star,
|
||||
contentDescription = stringResource(R.string.favorite),
|
||||
contentDescription = stringResource(Res.string.favorite),
|
||||
modifier = Modifier.size(24.dp), // Smaller size for badge
|
||||
tint = MaterialTheme.colorScheme.StatusYellow,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun NotesSection(node: Node, onSaveNotes: (Int, String) -> Unit, modifier: Modifier = Modifier) {
|
||||
if (node.isFavorite) {
|
||||
TitledCard(title = stringResource(R.string.notes), modifier = modifier) {
|
||||
TitledCard(title = stringResource(Res.string.notes), modifier = modifier) {
|
||||
val originalNotes = node.notes
|
||||
var notes by remember(node.notes) { mutableStateOf(node.notes) }
|
||||
val edited = notes.trim() != originalNotes.trim()
|
||||
|
|
@ -54,7 +54,7 @@ fun NotesSection(node: Node, onSaveNotes: (Int, String) -> Unit, modifier: Modif
|
|||
value = notes,
|
||||
onValueChange = { notes = it },
|
||||
modifier = Modifier.fillMaxWidth().padding(8.dp),
|
||||
placeholder = { Text(stringResource(R.string.add_a_note)) },
|
||||
placeholder = { Text(stringResource(Res.string.add_a_note)) },
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
|
|
@ -63,7 +63,7 @@ fun NotesSection(node: Node, onSaveNotes: (Int, String) -> Unit, modifier: Modif
|
|||
},
|
||||
enabled = edited,
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Save, contentDescription = stringResource(R.string.save))
|
||||
Icon(imageVector = Icons.Default.Save, contentDescription = stringResource(Res.string.save))
|
||||
}
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.util.toDistanceString
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.InsetDivider
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.feature.node.model.LogsType
|
||||
import org.meshtastic.feature.node.model.MetricsState
|
||||
import org.meshtastic.feature.node.model.NodeDetailAction
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* Displays node position details, last update time, distance, and related actions like requesting position and
|
||||
|
|
@ -51,7 +51,7 @@ fun PositionSection(
|
|||
) {
|
||||
val distance = ourNode?.distance(node)?.takeIf { it > 0 }?.toDistanceString(metricsState.displayUnits)
|
||||
val hasValidPosition = node.latitude != 0.0 || node.longitude != 0.0
|
||||
TitledCard(title = stringResource(R.string.position), modifier = modifier) {
|
||||
TitledCard(title = stringResource(Res.string.position), modifier = modifier) {
|
||||
// Current position coordinates (linked)
|
||||
if (hasValidPosition) {
|
||||
InlineMap(node = node, Modifier.fillMaxWidth().height(200.dp))
|
||||
|
|
@ -64,7 +64,7 @@ fun PositionSection(
|
|||
InsetDivider()
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.node_sort_distance),
|
||||
text = stringResource(Res.string.node_sort_distance),
|
||||
leadingIcon = Icons.Default.SocialDistance,
|
||||
supportingText = distance,
|
||||
copyable = true,
|
||||
|
|
@ -76,7 +76,7 @@ fun PositionSection(
|
|||
|
||||
// Exchange position action
|
||||
ListItem(
|
||||
text = stringResource(R.string.exchange_position),
|
||||
text = stringResource(Res.string.exchange_position),
|
||||
leadingIcon = Icons.Default.LocationOn,
|
||||
trailingIcon = null,
|
||||
onClick = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.RequestPosition(node))) },
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.node.model.VectorMetricInfo
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* Displays environmental metrics for a node, including temperature, humidity, pressure, and other sensor data.
|
||||
|
|
@ -46,16 +46,16 @@ internal fun PowerMetrics(node: Node) {
|
|||
buildList {
|
||||
with(node.powerMetrics) {
|
||||
if (ch1Voltage != 0f) {
|
||||
add(VectorMetricInfo(R.string.channel_1, "%.2fV".format(ch1Voltage), Icons.Default.Bolt))
|
||||
add(VectorMetricInfo(R.string.channel_1, "%.1fmA".format(ch1Current), Icons.Default.Power))
|
||||
add(VectorMetricInfo(Res.string.channel_1, "%.2fV".format(ch1Voltage), Icons.Default.Bolt))
|
||||
add(VectorMetricInfo(Res.string.channel_1, "%.1fmA".format(ch1Current), Icons.Default.Power))
|
||||
}
|
||||
if (ch2Voltage != 0f) {
|
||||
add(VectorMetricInfo(R.string.channel_2, "%.2fV".format(ch2Voltage), Icons.Default.Bolt))
|
||||
add(VectorMetricInfo(R.string.channel_2, "%.1fmA".format(ch2Current), Icons.Default.Power))
|
||||
add(VectorMetricInfo(Res.string.channel_2, "%.2fV".format(ch2Voltage), Icons.Default.Bolt))
|
||||
add(VectorMetricInfo(Res.string.channel_2, "%.1fmA".format(ch2Current), Icons.Default.Power))
|
||||
}
|
||||
if (ch3Voltage != 0f) {
|
||||
add(VectorMetricInfo(R.string.channel_3, "%.2fV".format(ch3Voltage), Icons.Default.Bolt))
|
||||
add(VectorMetricInfo(R.string.channel_3, "%.1fmA".format(ch3Current), Icons.Default.Power))
|
||||
add(VectorMetricInfo(Res.string.channel_3, "%.2fV".format(ch3Voltage), Icons.Default.Bolt))
|
||||
add(VectorMetricInfo(Res.string.channel_3, "%.1fmA".format(ch3Current), Icons.Default.Power))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,17 +23,17 @@ import androidx.compose.material.icons.filled.Person
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.InsetDivider
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.feature.node.model.NodeDetailAction
|
||||
import org.meshtastic.feature.node.model.isEffectivelyUnmessageable
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
internal fun RemoteDeviceActions(node: Node, lastTracerouteTime: Long?, onAction: (NodeDetailAction) -> Unit) {
|
||||
if (!node.isEffectivelyUnmessageable) {
|
||||
ListItem(
|
||||
text = stringResource(R.string.direct_message),
|
||||
text = stringResource(Res.string.direct_message),
|
||||
leadingIcon = Icons.AutoMirrored.TwoTone.Message,
|
||||
trailingIcon = null,
|
||||
onClick = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.DirectMessage(node))) },
|
||||
|
|
@ -43,7 +43,7 @@ internal fun RemoteDeviceActions(node: Node, lastTracerouteTime: Long?, onAction
|
|||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(R.string.exchange_userinfo),
|
||||
text = stringResource(Res.string.exchange_userinfo),
|
||||
leadingIcon = Icons.Default.Person,
|
||||
trailingIcon = null,
|
||||
onClick = { onAction(NodeDetailAction.HandleNodeMenuAction(NodeMenuAction.RequestUserInfo(node))) },
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun SatelliteCountInfo(
|
||||
|
|
@ -36,7 +37,7 @@ fun SatelliteCountInfo(
|
|||
IconInfo(
|
||||
modifier = modifier,
|
||||
icon = Icons.TwoTone.SatelliteAlt,
|
||||
contentDescription = stringResource(org.meshtastic.core.strings.R.string.sats),
|
||||
contentDescription = stringResource(Res.string.sats),
|
||||
text = "$satCount",
|
||||
contentColor = contentColor,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,15 +34,15 @@ import androidx.compose.ui.platform.LocalDensity
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.BasicListItem
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val COOL_DOWN_TIME_MS = 30000L
|
||||
|
||||
@Composable
|
||||
fun TracerouteButton(
|
||||
text: String = stringResource(R.string.traceroute),
|
||||
text: String = stringResource(Res.string.traceroute),
|
||||
lastTracerouteTime: Long?,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.AddContactFAB
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.rememberTimeTickWithLifecycle
|
||||
|
|
@ -70,6 +69,7 @@ import org.meshtastic.feature.node.component.NodeActionDialogs
|
|||
import org.meshtastic.feature.node.component.NodeFilterTextField
|
||||
import org.meshtastic.feature.node.component.NodeItem
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
|
|
@ -95,8 +95,8 @@ fun NodeListScreen(viewModel: NodeListViewModel = hiltViewModel(), navigateToNod
|
|||
Scaffold(
|
||||
topBar = {
|
||||
MainAppBar(
|
||||
title = stringResource(R.string.nodes),
|
||||
subtitle = stringResource(R.string.node_count_template, onlineNodeCount, totalNodeCount),
|
||||
title = stringResource(Res.string.nodes),
|
||||
subtitle = stringResource(Res.string.node_count_template, onlineNodeCount, totalNodeCount),
|
||||
ourNode = ourNode,
|
||||
showNodeChip = false,
|
||||
canNavigateUp = false,
|
||||
|
|
@ -233,7 +233,7 @@ private fun ContextMenu(
|
|||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
text = { Text(stringResource(if (isFavorite) R.string.remove_favorite else R.string.add_favorite)) },
|
||||
text = { Text(stringResource(if (isFavorite) Res.string.remove_favorite else Res.string.add_favorite)) },
|
||||
)
|
||||
|
||||
DropdownMenuItem(
|
||||
|
|
@ -250,7 +250,7 @@ private fun ContextMenu(
|
|||
},
|
||||
text = {
|
||||
Text(
|
||||
text = stringResource(if (isIgnored) R.string.remove_ignored else R.string.ignore),
|
||||
text = stringResource(if (isIgnored) Res.string.remove_ignored else Res.string.ignore),
|
||||
color = MaterialTheme.colorScheme.StatusRed,
|
||||
)
|
||||
},
|
||||
|
|
@ -271,7 +271,7 @@ private fun ContextMenu(
|
|||
},
|
||||
text = {
|
||||
Text(
|
||||
text = stringResource(R.string.remove),
|
||||
text = stringResource(Res.string.remove),
|
||||
color = if (isIgnored) Color.Unspecified else MaterialTheme.colorScheme.StatusRed,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -56,11 +56,11 @@ import androidx.compose.ui.text.style.TextDecoration
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_MINUTE_FORMAT
|
||||
import org.meshtastic.feature.node.metrics.CommonCharts.MAX_PERCENT_VALUE
|
||||
import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
|
||||
import java.text.DateFormat
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
object CommonCharts {
|
||||
val DATE_TIME_FORMAT: DateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM)
|
||||
|
|
@ -93,7 +93,7 @@ fun ChartHeader(amount: Int) {
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = "$amount ${stringResource(R.string.logs)}",
|
||||
text = "$amount ${stringResource(Res.string.logs)}",
|
||||
modifier = Modifier.wrapContentWidth(),
|
||||
style = TextStyle(fontWeight = FontWeight.Bold),
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
|
|
@ -254,7 +254,7 @@ fun Legend(legendData: List<LegendData>, displayInfoIcon: Boolean = true, prompt
|
|||
Icon(
|
||||
imageVector = Icons.Default.Info,
|
||||
modifier = Modifier.clickable { promptInfoDialog() },
|
||||
contentDescription = stringResource(R.string.info),
|
||||
contentDescription = stringResource(Res.string.info),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +272,11 @@ fun Legend(legendData: List<LegendData>, displayInfoIcon: Boolean = true, prompt
|
|||
fun LegendInfoDialog(pairedRes: List<Pair<Int, Int>>, onDismiss: () -> Unit) {
|
||||
AlertDialog(
|
||||
title = {
|
||||
Text(text = stringResource(R.string.info), modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center)
|
||||
Text(
|
||||
text = stringResource(Res.string.info),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
|
|
@ -289,7 +293,7 @@ fun LegendInfoDialog(pairedRes: List<Pair<Int, Int>>, onDismiss: () -> Unit) {
|
|||
}
|
||||
},
|
||||
onDismissRequest = onDismiss,
|
||||
confirmButton = { TextButton(onClick = onDismiss) { Text(stringResource(R.string.close)) } },
|
||||
confirmButton = { TextButton(onClick = onDismiss) { Text(stringResource(Res.string.close)) } },
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
)
|
||||
}
|
||||
|
|
@ -322,8 +326,8 @@ private fun LegendLabel(text: String, color: Color, isLine: Boolean = false) {
|
|||
private fun LegendPreview() {
|
||||
val data =
|
||||
listOf(
|
||||
LegendData(nameRes = R.string.rssi, color = Color.Red),
|
||||
LegendData(nameRes = R.string.snr, color = Color.Green),
|
||||
LegendData(nameRes = Res.string.rssi, color = Color.Red),
|
||||
LegendData(nameRes = Res.string.snr, color = Color.Green),
|
||||
)
|
||||
Legend(legendData = data, promptInfoDialog = {})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.MaterialBatteryInfo
|
||||
import org.meshtastic.core.ui.component.OptionLabel
|
||||
|
|
@ -77,6 +76,7 @@ import org.meshtastic.feature.node.metrics.GraphUtil.plotPoint
|
|||
import org.meshtastic.feature.node.model.TimeFrame
|
||||
import org.meshtastic.proto.TelemetryProtos
|
||||
import org.meshtastic.proto.TelemetryProtos.Telemetry
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val CHART_WEIGHT = 1f
|
||||
private const val Y_AXIS_WEIGHT = 0.1f
|
||||
|
|
@ -98,15 +98,15 @@ private enum class Device(val color: Color) {
|
|||
|
||||
private val LEGEND_DATA =
|
||||
listOf(
|
||||
LegendData(nameRes = R.string.battery, color = Device.BATTERY.color, isLine = true, environmentMetric = null),
|
||||
LegendData(nameRes = Res.string.battery, color = Device.BATTERY.color, isLine = true, environmentMetric = null),
|
||||
LegendData(
|
||||
nameRes = R.string.channel_utilization,
|
||||
nameRes = Res.string.channel_utilization,
|
||||
color = Device.CH_UTIL.color,
|
||||
isLine = false,
|
||||
environmentMetric = null,
|
||||
),
|
||||
LegendData(
|
||||
nameRes = R.string.air_utilization,
|
||||
nameRes = Res.string.air_utilization,
|
||||
color = Device.AIR_UTIL.color,
|
||||
isLine = false,
|
||||
environmentMetric = null,
|
||||
|
|
@ -138,8 +138,8 @@ fun DeviceMetricsScreen(viewModel: MetricsViewModel = hiltViewModel(), onNavigat
|
|||
LegendInfoDialog(
|
||||
pairedRes =
|
||||
listOf(
|
||||
Pair(R.string.channel_utilization, R.string.ch_util_definition),
|
||||
Pair(R.string.air_utilization, R.string.air_util_definition),
|
||||
Pair(Res.string.channel_utilization, Res.string.ch_util_definition),
|
||||
Pair(Res.string.air_utilization, Res.string.air_util_definition),
|
||||
),
|
||||
onDismiss = { displayInfoDialog = false },
|
||||
)
|
||||
|
|
@ -341,7 +341,7 @@ private fun DeviceMetricsCard(telemetry: Telemetry) {
|
|||
/* Channel Utilization and Air Utilization Tx */
|
||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
val text =
|
||||
stringResource(R.string.channel_air_util)
|
||||
stringResource(Res.string.channel_air_util)
|
||||
.format(deviceMetrics.channelUtilization, deviceMetrics.airUtilTx)
|
||||
Text(
|
||||
text = text,
|
||||
|
|
@ -404,8 +404,8 @@ private fun DeviceMetricsScreenPreview() {
|
|||
LegendInfoDialog(
|
||||
pairedRes =
|
||||
listOf(
|
||||
Pair(R.string.channel_utilization, R.string.ch_util_definition),
|
||||
Pair(R.string.air_utilization, R.string.air_util_definition),
|
||||
Pair(Res.string.channel_utilization, Res.string.ch_util_definition),
|
||||
Pair(Res.string.air_utilization, Res.string.air_util_definition),
|
||||
),
|
||||
onDismiss = { displayInfoDialog = false },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -40,11 +40,11 @@ import androidx.compose.ui.platform.LocalDensity
|
|||
import androidx.compose.ui.platform.LocalWindowInfo
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.node.metrics.GraphUtil.createPath
|
||||
import org.meshtastic.feature.node.metrics.GraphUtil.drawPathWithGradient
|
||||
import org.meshtastic.feature.node.model.TimeFrame
|
||||
import org.meshtastic.proto.TelemetryProtos.Telemetry
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val CHART_WEIGHT = 1f
|
||||
private const val Y_AXIS_WEIGHT = 0.1f
|
||||
|
|
@ -53,13 +53,13 @@ private const val Y_AXIS_WEIGHT = 0.1f
|
|||
private val LEGEND_DATA_1 =
|
||||
listOf(
|
||||
LegendData(
|
||||
nameRes = R.string.temperature,
|
||||
nameRes = Res.string.temperature,
|
||||
color = Environment.TEMPERATURE.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.TEMPERATURE,
|
||||
),
|
||||
LegendData(
|
||||
nameRes = R.string.humidity,
|
||||
nameRes = Res.string.humidity,
|
||||
color = Environment.HUMIDITY.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.HUMIDITY,
|
||||
|
|
@ -68,25 +68,25 @@ private val LEGEND_DATA_1 =
|
|||
private val LEGEND_DATA_2 =
|
||||
listOf(
|
||||
LegendData(
|
||||
nameRes = R.string.iaq,
|
||||
nameRes = Res.string.iaq,
|
||||
color = Environment.IAQ.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.IAQ,
|
||||
),
|
||||
LegendData(
|
||||
nameRes = R.string.baro_pressure,
|
||||
nameRes = Res.string.baro_pressure,
|
||||
color = Environment.BAROMETRIC_PRESSURE.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.BAROMETRIC_PRESSURE,
|
||||
),
|
||||
LegendData(
|
||||
nameRes = R.string.lux,
|
||||
nameRes = Res.string.lux,
|
||||
color = Environment.LUX.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.LUX,
|
||||
),
|
||||
LegendData(
|
||||
nameRes = R.string.uv_lux,
|
||||
nameRes = Res.string.uv_lux,
|
||||
color = Environment.UV_LUX.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.UV_LUX,
|
||||
|
|
@ -96,13 +96,13 @@ private val LEGEND_DATA_2 =
|
|||
private val LEGEND_DATA_3 =
|
||||
listOf(
|
||||
LegendData(
|
||||
nameRes = R.string.soil_temperature,
|
||||
nameRes = Res.string.soil_temperature,
|
||||
color = Environment.SOIL_TEMPERATURE.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.SOIL_TEMPERATURE,
|
||||
),
|
||||
LegendData(
|
||||
nameRes = R.string.soil_moisture,
|
||||
nameRes = Res.string.soil_moisture,
|
||||
color = Environment.SOIL_MOISTURE.color,
|
||||
isLine = true,
|
||||
environmentMetric = Environment.SOIL_MOISTURE,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.model.util.UnitConversions.celsiusToFahrenheit
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.IaqDisplayMode
|
||||
import org.meshtastic.core.ui.component.IndoorAirQuality
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
|
|
@ -62,6 +61,7 @@ import org.meshtastic.feature.node.model.TimeFrame
|
|||
import org.meshtastic.proto.TelemetryProtos
|
||||
import org.meshtastic.proto.TelemetryProtos.Telemetry
|
||||
import org.meshtastic.proto.copy
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun EnvironmentMetricsScreen(viewModel: MetricsViewModel = hiltViewModel(), onNavigateUp: () -> Unit) {
|
||||
|
|
@ -106,7 +106,7 @@ fun EnvironmentMetricsScreen(viewModel: MetricsViewModel = hiltViewModel(), onNa
|
|||
Column(modifier = Modifier.padding(innerPadding)) {
|
||||
if (displayInfoDialog) {
|
||||
LegendInfoDialog(
|
||||
pairedRes = listOf(Pair(R.string.iaq, R.string.iaq_definition)),
|
||||
pairedRes = listOf(Pair(Res.string.iaq, Res.string.iaq_definition)),
|
||||
onDismiss = { displayInfoDialog = false },
|
||||
)
|
||||
}
|
||||
|
|
@ -140,7 +140,7 @@ private fun TemperatureDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics, e
|
|||
if (!temperature.isNaN()) {
|
||||
val textFormat = if (environmentDisplayFahrenheit) "%s %.1f°F" else "%s %.1f°C"
|
||||
Text(
|
||||
text = textFormat.format(stringResource(R.string.temperature), temperature),
|
||||
text = textFormat.format(stringResource(Res.string.temperature), temperature),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -161,7 +161,7 @@ private fun HumidityAndBarometricPressureDisplay(envMetrics: TelemetryProtos.Env
|
|||
if (hasHumidity) {
|
||||
val humidity = envMetrics.relativeHumidity!!
|
||||
Text(
|
||||
text = "%s %.2f%%".format(stringResource(R.string.humidity), humidity),
|
||||
text = "%s %.2f%%".format(stringResource(Res.string.humidity), humidity),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
modifier = Modifier.padding(vertical = 0.dp),
|
||||
|
|
@ -192,7 +192,8 @@ private fun SoilMetricsDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics, e
|
|||
envMetrics.soilMoisture?.let { soilMoistureValue ->
|
||||
if (soilMoistureValue != Int.MIN_VALUE) {
|
||||
Text(
|
||||
text = soilMoistureTextFormat.format(stringResource(R.string.soil_moisture), soilMoistureValue),
|
||||
text =
|
||||
soilMoistureTextFormat.format(stringResource(Res.string.soil_moisture), soilMoistureValue),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -203,7 +204,7 @@ private fun SoilMetricsDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics, e
|
|||
Text(
|
||||
text =
|
||||
soilTemperatureTextFormat.format(
|
||||
stringResource(R.string.soil_temperature),
|
||||
stringResource(Res.string.soil_temperature),
|
||||
soilTemperature,
|
||||
),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
|
|
@ -225,7 +226,7 @@ private fun LuxUVLuxDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics) {
|
|||
if (hasLux) {
|
||||
val luxValue = envMetrics.lux!!
|
||||
Text(
|
||||
text = "%s %.0f lx".format(stringResource(R.string.lux), luxValue),
|
||||
text = "%s %.0f lx".format(stringResource(Res.string.lux), luxValue),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -233,7 +234,7 @@ private fun LuxUVLuxDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics) {
|
|||
if (hasUvLux) {
|
||||
val uvLuxValue = envMetrics.uvLux!!
|
||||
Text(
|
||||
text = "%s %.0f UVlx".format(stringResource(R.string.uv_lux), uvLuxValue),
|
||||
text = "%s %.0f UVlx".format(stringResource(Res.string.uv_lux), uvLuxValue),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -252,7 +253,7 @@ private fun VoltageCurrentDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics
|
|||
if (hasVoltage) {
|
||||
val voltage = envMetrics.voltage!!
|
||||
Text(
|
||||
text = "%s %.2f V".format(stringResource(R.string.voltage), voltage),
|
||||
text = "%s %.2f V".format(stringResource(Res.string.voltage), voltage),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -260,7 +261,7 @@ private fun VoltageCurrentDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics
|
|||
if (hasCurrent) {
|
||||
val current = envMetrics.current!!
|
||||
Text(
|
||||
text = "%s %.2f mA".format(stringResource(R.string.current), current),
|
||||
text = "%s %.2f mA".format(stringResource(Res.string.current), current),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -279,7 +280,7 @@ private fun GasCompositionDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics
|
|||
if (iaqValue != null && iaqValue != Int.MIN_VALUE) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = stringResource(R.string.iaq),
|
||||
text = stringResource(Res.string.iaq),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -289,7 +290,7 @@ private fun GasCompositionDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics
|
|||
}
|
||||
if (gasResistance != null && !gasResistance.isNaN()) {
|
||||
Text(
|
||||
text = "%s %.2f Ohm".format(stringResource(R.string.gas_resistance), gasResistance),
|
||||
text = "%s %.2f Ohm".format(stringResource(Res.string.gas_resistance), gasResistance),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
@ -301,7 +302,7 @@ private fun GasCompositionDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics
|
|||
// Spacer(modifier = Modifier.height(4.dp))
|
||||
// Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
// Text(
|
||||
// text = "%s %.0f ppm".format(stringResource(R.string.co2), co2),
|
||||
// text = "%s %.0f ppm".format(stringResource(Res.string.co2), co2),
|
||||
// color = MaterialTheme.colorScheme.onSurface,
|
||||
// fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
// )
|
||||
|
|
@ -311,7 +312,7 @@ private fun GasCompositionDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics
|
|||
// Spacer(modifier = Modifier.height(4.dp))
|
||||
// Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
// Text(
|
||||
// text = "%s %.0f ppb".format(stringResource(R.string.tvoc), tvoc),
|
||||
// text = "%s %.0f ppb".format(stringResource(Res.string.tvoc), tvoc),
|
||||
// color = MaterialTheme.colorScheme.onSurface,
|
||||
// fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
// )
|
||||
|
|
@ -325,7 +326,7 @@ private fun RadiationDisplay(envMetrics: TelemetryProtos.EnvironmentMetrics) {
|
|||
if (!radiation.isNaN() && radiation > 0f) {
|
||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
Text(
|
||||
text = "%s %.2f µR/h".format(stringResource(R.string.radiation), radiation),
|
||||
text = "%s %.2f µR/h".format(stringResource(Res.string.radiation), radiation),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -55,12 +55,12 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.model.util.formatUptime
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.feature.node.metrics.CommonCharts.DATE_TIME_FORMAT
|
||||
import org.meshtastic.proto.TelemetryProtos
|
||||
import java.text.DecimalFormat
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
|
|
@ -113,36 +113,36 @@ fun HostMetricsItem(modifier: Modifier = Modifier, telemetry: TelemetryProtos.Te
|
|||
fontSize = MaterialTheme.typography.labelLarge.fontSize,
|
||||
)
|
||||
LogLine(
|
||||
label = stringResource(R.string.uptime),
|
||||
label = stringResource(Res.string.uptime),
|
||||
value = formatUptime(hostMetrics.uptimeSeconds),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
LogLine(
|
||||
label = stringResource(R.string.free_memory),
|
||||
label = stringResource(Res.string.free_memory),
|
||||
value = formatBytes(hostMetrics.freememBytes),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
LogLine(
|
||||
label = stringResource(R.string.disk_free_indexed, 1),
|
||||
label = stringResource(Res.string.disk_free_indexed, 1),
|
||||
value = formatBytes(hostMetrics.diskfree1Bytes),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
if (hostMetrics.hasDiskfree2Bytes()) {
|
||||
LogLine(
|
||||
label = stringResource(R.string.disk_free_indexed, 2),
|
||||
label = stringResource(Res.string.disk_free_indexed, 2),
|
||||
value = formatBytes(hostMetrics.diskfree2Bytes),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
if (hostMetrics.hasDiskfree3Bytes()) {
|
||||
LogLine(
|
||||
label = stringResource(R.string.disk_free_indexed, 3),
|
||||
label = stringResource(Res.string.disk_free_indexed, 3),
|
||||
value = formatBytes(hostMetrics.diskfree3Bytes),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
LogLine(
|
||||
label = stringResource(R.string.load_indexed, 1),
|
||||
label = stringResource(Res.string.load_indexed, 1),
|
||||
value = (hostMetrics.load1 / 100.0).toString(),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
|
@ -154,7 +154,7 @@ fun HostMetricsItem(modifier: Modifier = Modifier, telemetry: TelemetryProtos.Te
|
|||
strokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
|
||||
)
|
||||
LogLine(
|
||||
label = stringResource(R.string.load_indexed, 5),
|
||||
label = stringResource(Res.string.load_indexed, 5),
|
||||
value = (hostMetrics.load5 / 100.0).toString(),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
|
@ -166,7 +166,7 @@ fun HostMetricsItem(modifier: Modifier = Modifier, telemetry: TelemetryProtos.Te
|
|||
strokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
|
||||
)
|
||||
LogLine(
|
||||
label = stringResource(R.string.load_indexed, 15),
|
||||
label = stringResource(Res.string.load_indexed, 15),
|
||||
value = (hostMetrics.load15 / 100.0).toString(),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
|
@ -178,7 +178,7 @@ fun HostMetricsItem(modifier: Modifier = Modifier, telemetry: TelemetryProtos.Te
|
|||
strokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
|
||||
)
|
||||
if (hostMetrics.hasUserString()) {
|
||||
Text(text = stringResource(R.string.user_string), style = MaterialTheme.typography.bodyMedium)
|
||||
Text(text = stringResource(Res.string.user_string), style = MaterialTheme.typography.bodyMedium)
|
||||
Text(text = hostMetrics.userString, style = TextStyle(fontFamily = FontFamily.Monospace))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ import org.meshtastic.core.proto.safeNumber
|
|||
import org.meshtastic.core.proto.toPosition
|
||||
import org.meshtastic.core.service.ServiceAction
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.node.model.MetricsState
|
||||
import org.meshtastic.feature.node.model.TimeFrame
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
|
|
@ -66,6 +65,7 @@ import java.io.FileWriter
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val DEFAULT_ID_SUFFIX_LENGTH = 4
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ constructor(
|
|||
private fun createFallbackNode(nodeNum: Int): Node {
|
||||
val userId = DataPacket.nodeNumToDefaultId(nodeNum)
|
||||
val safeUserId = userId.padStart(DEFAULT_ID_SUFFIX_LENGTH, '0').takeLast(DEFAULT_ID_SUFFIX_LENGTH)
|
||||
val longName = app.getString(R.string.fallback_node_name) + " $safeUserId"
|
||||
val longName = app.getString(Res.string.fallback_node_name) + " $safeUserId"
|
||||
val defaultUser =
|
||||
MeshProtos.User.newBuilder()
|
||||
.setId(userId)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.database.entity.MeshLog
|
||||
import org.meshtastic.core.model.util.formatUptime
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.OptionLabel
|
||||
import org.meshtastic.core.ui.component.SlidingSelector
|
||||
|
|
@ -65,15 +64,16 @@ import org.meshtastic.proto.PaxcountProtos
|
|||
import org.meshtastic.proto.Portnums.PortNum
|
||||
import java.text.DateFormat
|
||||
import java.util.Date
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val CHART_WEIGHT = 1f
|
||||
private const val Y_AXIS_WEIGHT = 0.1f
|
||||
private const val CHART_WIDTH_RATIO = CHART_WEIGHT / (CHART_WEIGHT + Y_AXIS_WEIGHT + Y_AXIS_WEIGHT)
|
||||
|
||||
private enum class PaxSeries(val color: Color, val legendRes: Int) {
|
||||
PAX(Color.Black, R.string.pax),
|
||||
BLE(Color.Cyan, R.string.ble_devices),
|
||||
WIFI(Color.Green, R.string.wifi_devices),
|
||||
PAX(Color.Black, Res.string.pax),
|
||||
BLE(Color.Cyan, Res.string.ble_devices),
|
||||
WIFI(Color.Green, Res.string.wifi_devices),
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
|
|
@ -228,7 +228,7 @@ fun PaxMetricsScreen(metricsViewModel: MetricsViewModel = hiltViewModel(), onNav
|
|||
// List
|
||||
if (paxMetrics.isEmpty()) {
|
||||
Text(
|
||||
text = stringResource(R.string.no_pax_metrics_logs),
|
||||
text = stringResource(Res.string.no_pax_metrics_logs),
|
||||
modifier = Modifier.fillMaxSize().padding(16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
|
@ -314,7 +314,7 @@ fun PaxMetricsItem(log: MeshLog, pax: PaxcountProtos.Paxcount, dateFormat: DateF
|
|||
modifier = Modifier.weight(1f, fill = true),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.uptime) + ": " + formatUptime(pax.uptime),
|
||||
text = stringResource(Res.string.uptime) + ": " + formatUptime(pax.uptime),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
textAlign = TextAlign.End,
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
|
|
|
|||
|
|
@ -65,12 +65,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import org.meshtastic.core.model.util.metersIn
|
||||
import org.meshtastic.core.model.util.toString
|
||||
import org.meshtastic.core.proto.formatPositionTime
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.proto.ConfigProtos.Config.DisplayConfig.DisplayUnits
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
import java.text.DateFormat
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
private fun RowScope.PositionText(text: String, weight: Float) {
|
||||
|
|
@ -91,15 +91,15 @@ private const val WEIGHT_40 = .40f
|
|||
@Composable
|
||||
private fun HeaderItem(compactWidth: Boolean) {
|
||||
Row(modifier = Modifier.fillMaxWidth().padding(8.dp), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
PositionText(stringResource(R.string.latitude), WEIGHT_20)
|
||||
PositionText(stringResource(R.string.longitude), WEIGHT_20)
|
||||
PositionText(stringResource(R.string.sats), WEIGHT_10)
|
||||
PositionText(stringResource(R.string.alt), WEIGHT_15)
|
||||
PositionText(stringResource(Res.string.latitude), WEIGHT_20)
|
||||
PositionText(stringResource(Res.string.longitude), WEIGHT_20)
|
||||
PositionText(stringResource(Res.string.sats), WEIGHT_10)
|
||||
PositionText(stringResource(Res.string.alt), WEIGHT_15)
|
||||
if (!compactWidth) {
|
||||
PositionText(stringResource(R.string.speed), WEIGHT_15)
|
||||
PositionText(stringResource(R.string.heading), WEIGHT_15)
|
||||
PositionText(stringResource(Res.string.speed), WEIGHT_15)
|
||||
PositionText(stringResource(Res.string.heading), WEIGHT_15)
|
||||
}
|
||||
PositionText(stringResource(R.string.timestamp), WEIGHT_40)
|
||||
PositionText(stringResource(Res.string.timestamp), WEIGHT_40)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,15 +143,15 @@ private fun ActionButtons(
|
|||
enabled = clearButtonEnabled,
|
||||
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Delete, contentDescription = stringResource(R.string.clear))
|
||||
Icon(imageVector = Icons.Default.Delete, contentDescription = stringResource(Res.string.clear))
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.clear))
|
||||
Text(text = stringResource(Res.string.clear))
|
||||
}
|
||||
|
||||
OutlinedButton(modifier = Modifier.weight(1f), onClick = onSave, enabled = saveButtonEnabled) {
|
||||
Icon(imageVector = Icons.Default.Save, contentDescription = stringResource(R.string.save))
|
||||
Icon(imageVector = Icons.Default.Save, contentDescription = stringResource(Res.string.save))
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text(text = stringResource(R.string.save))
|
||||
Text(text = stringResource(Res.string.save))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.OptionLabel
|
||||
import org.meshtastic.core.ui.component.SlidingSelector
|
||||
|
|
@ -73,6 +72,7 @@ import org.meshtastic.feature.node.model.TimeFrame
|
|||
import org.meshtastic.proto.TelemetryProtos.Telemetry
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private enum class Power(val color: Color, val min: Float, val max: Float) {
|
||||
|
|
@ -84,9 +84,9 @@ private enum class Power(val color: Color, val min: Float, val max: Float) {
|
|||
}
|
||||
|
||||
private enum class PowerChannel(@StringRes val strRes: Int) {
|
||||
ONE(R.string.channel_1),
|
||||
TWO(R.string.channel_2),
|
||||
THREE(R.string.channel_3),
|
||||
ONE(Res.string.channel_1),
|
||||
TWO(Res.string.channel_2),
|
||||
THREE(Res.string.channel_3),
|
||||
}
|
||||
|
||||
private const val CHART_WEIGHT = 1f
|
||||
|
|
@ -112,8 +112,8 @@ fun minMaxGraphVoltage(valueMin: Float, valueMax: Float): Pair<Float, Float> {
|
|||
|
||||
private val LEGEND_DATA =
|
||||
listOf(
|
||||
LegendData(nameRes = R.string.current, color = Power.CURRENT.color, isLine = true, environmentMetric = null),
|
||||
LegendData(nameRes = R.string.voltage, color = VOLTAGE_COLOR, isLine = true, environmentMetric = null),
|
||||
LegendData(nameRes = Res.string.current, color = Power.CURRENT.color, isLine = true, environmentMetric = null),
|
||||
LegendData(nameRes = Res.string.voltage, color = VOLTAGE_COLOR, isLine = true, environmentMetric = null),
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
@ -321,21 +321,21 @@ private fun PowerMetricsCard(telemetry: Telemetry) {
|
|||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
|
||||
if (telemetry.powerMetrics.hasCh1Current() || telemetry.powerMetrics.hasCh1Voltage()) {
|
||||
PowerChannelColumn(
|
||||
R.string.channel_1,
|
||||
Res.string.channel_1,
|
||||
telemetry.powerMetrics.ch1Voltage,
|
||||
telemetry.powerMetrics.ch1Current,
|
||||
)
|
||||
}
|
||||
if (telemetry.powerMetrics.hasCh2Current() || telemetry.powerMetrics.hasCh2Voltage()) {
|
||||
PowerChannelColumn(
|
||||
R.string.channel_2,
|
||||
Res.string.channel_2,
|
||||
telemetry.powerMetrics.ch2Voltage,
|
||||
telemetry.powerMetrics.ch2Current,
|
||||
)
|
||||
}
|
||||
if (telemetry.powerMetrics.hasCh3Current() || telemetry.powerMetrics.hasCh3Voltage()) {
|
||||
PowerChannelColumn(
|
||||
R.string.channel_3,
|
||||
Res.string.channel_3,
|
||||
telemetry.powerMetrics.ch3Voltage,
|
||||
telemetry.powerMetrics.ch3Current,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.LoraSignalIndicator
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.OptionLabel
|
||||
|
|
@ -68,6 +67,7 @@ import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
|
|||
import org.meshtastic.feature.node.metrics.GraphUtil.plotPoint
|
||||
import org.meshtastic.feature.node.model.TimeFrame
|
||||
import org.meshtastic.proto.MeshProtos.MeshPacket
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private enum class Metric(val color: Color, val min: Float, val max: Float) {
|
||||
|
|
@ -85,8 +85,8 @@ private const val CHART_WIDTH_RATIO = CHART_WEIGHT / (CHART_WEIGHT + Y_AXIS_WEIG
|
|||
|
||||
private val LEGEND_DATA =
|
||||
listOf(
|
||||
LegendData(nameRes = R.string.rssi, color = Metric.RSSI.color, environmentMetric = null),
|
||||
LegendData(nameRes = R.string.snr, color = Metric.SNR.color, environmentMetric = null),
|
||||
LegendData(nameRes = Res.string.rssi, color = Metric.RSSI.color, environmentMetric = null),
|
||||
LegendData(nameRes = Res.string.snr, color = Metric.SNR.color, environmentMetric = null),
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
@ -114,8 +114,8 @@ fun SignalMetricsScreen(viewModel: MetricsViewModel = hiltViewModel(), onNavigat
|
|||
LegendInfoDialog(
|
||||
pairedRes =
|
||||
listOf(
|
||||
Pair(R.string.snr, R.string.snr_definition),
|
||||
Pair(R.string.rssi, R.string.rssi_definition),
|
||||
Pair(Res.string.snr, Res.string.snr_definition),
|
||||
Pair(Res.string.rssi, Res.string.rssi_definition),
|
||||
),
|
||||
onDismiss = { displayInfoDialog = false },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.model.fullRouteDiscovery
|
||||
import org.meshtastic.core.model.getTracerouteResponse
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.SNR_FAIR_THRESHOLD
|
||||
import org.meshtastic.core.ui.component.SNR_GOOD_THRESHOLD
|
||||
|
|
@ -76,6 +75,7 @@ import org.meshtastic.core.ui.theme.StatusColors.StatusYellow
|
|||
import org.meshtastic.feature.node.metrics.CommonCharts.MS_PER_SEC
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
import java.text.DateFormat
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Suppress("LongMethod")
|
||||
|
|
@ -95,7 +95,7 @@ fun TracerouteLogScreen(
|
|||
if (showDialog != null) {
|
||||
val message = showDialog ?: AnnotatedString("") // Should not be null if dialog is shown
|
||||
SimpleAlertDialog(
|
||||
title = R.string.traceroute,
|
||||
title = Res.string.traceroute,
|
||||
text = { SelectionContainer { Text(text = message) } },
|
||||
onDismiss = { showDialog = null },
|
||||
)
|
||||
|
|
@ -185,11 +185,11 @@ private fun DeleteItem(onClick: () -> Unit) {
|
|||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
contentDescription = stringResource(R.string.delete),
|
||||
contentDescription = stringResource(Res.string.delete),
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(text = stringResource(R.string.delete), color = MaterialTheme.colorScheme.error)
|
||||
Text(text = stringResource(Res.string.delete), color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -202,7 +202,7 @@ private fun TracerouteItem(icon: ImageVector, text: String, modifier: Modifier =
|
|||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(imageVector = icon, contentDescription = stringResource(R.string.traceroute))
|
||||
Icon(imageVector = icon, contentDescription = stringResource(Res.string.traceroute))
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(text = text, style = MaterialTheme.typography.bodyLarge)
|
||||
}
|
||||
|
|
@ -213,23 +213,23 @@ private fun TracerouteItem(icon: ImageVector, text: String, modifier: Modifier =
|
|||
@Composable
|
||||
private fun MeshProtos.RouteDiscovery?.getTextAndIcon(): Pair<String, ImageVector> = when {
|
||||
this == null -> {
|
||||
stringResource(R.string.routing_error_no_response) to Icons.Default.PersonOff
|
||||
stringResource(Res.string.routing_error_no_response) to Icons.Default.PersonOff
|
||||
}
|
||||
// A direct route means the sender and receiver are the only two nodes in the route.
|
||||
routeCount <= 2 && routeBackCount <= 2 -> { // also check routeBackCount for direct to be more robust
|
||||
stringResource(R.string.traceroute_direct) to Icons.Default.Group
|
||||
stringResource(Res.string.traceroute_direct) to Icons.Default.Group
|
||||
}
|
||||
|
||||
routeCount == routeBackCount -> {
|
||||
val hops = routeCount - 2
|
||||
pluralStringResource(R.plurals.traceroute_hops, hops, hops) to Icons.Default.Groups
|
||||
pluralStringResource(Res.plurals.traceroute_hops, hops, hops) to Icons.Default.Groups
|
||||
}
|
||||
|
||||
else -> {
|
||||
// Asymmetric route
|
||||
val towards = maxOf(0, routeCount - 2)
|
||||
val back = maxOf(0, routeBackCount - 2)
|
||||
stringResource(R.string.traceroute_diff, towards, back) to Icons.Default.Groups
|
||||
stringResource(Res.string.traceroute_diff, towards, back) to Icons.Default.Groups
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,16 +31,16 @@ import androidx.compose.material.icons.filled.Thermostat
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import org.meshtastic.core.navigation.NodeDetailRoutes
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
enum class LogsType(@StringRes val titleRes: Int, val icon: ImageVector, val route: Route) {
|
||||
DEVICE(R.string.device_metrics_log, Icons.Default.ChargingStation, NodeDetailRoutes.DeviceMetrics),
|
||||
NODE_MAP(R.string.node_map, Icons.Default.Map, NodeDetailRoutes.NodeMap),
|
||||
POSITIONS(R.string.position_log, Icons.Default.LocationOn, NodeDetailRoutes.PositionLog),
|
||||
ENVIRONMENT(R.string.env_metrics_log, Icons.Default.Thermostat, NodeDetailRoutes.EnvironmentMetrics),
|
||||
SIGNAL(R.string.sig_metrics_log, Icons.Default.SignalCellularAlt, NodeDetailRoutes.SignalMetrics),
|
||||
POWER(R.string.power_metrics_log, Icons.Default.Power, NodeDetailRoutes.PowerMetrics),
|
||||
TRACEROUTE(R.string.traceroute_log, Icons.Default.Route, NodeDetailRoutes.TracerouteLog),
|
||||
HOST(R.string.host_metrics_log, Icons.Default.Memory, NodeDetailRoutes.HostMetricsLog),
|
||||
PAX(R.string.pax_metrics_log, Icons.Default.People, NodeDetailRoutes.PaxMetrics),
|
||||
DEVICE(Res.string.device_metrics_log, Icons.Default.ChargingStation, NodeDetailRoutes.DeviceMetrics),
|
||||
NODE_MAP(Res.string.node_map, Icons.Default.Map, NodeDetailRoutes.NodeMap),
|
||||
POSITIONS(Res.string.position_log, Icons.Default.LocationOn, NodeDetailRoutes.PositionLog),
|
||||
ENVIRONMENT(Res.string.env_metrics_log, Icons.Default.Thermostat, NodeDetailRoutes.EnvironmentMetrics),
|
||||
SIGNAL(Res.string.sig_metrics_log, Icons.Default.SignalCellularAlt, NodeDetailRoutes.SignalMetrics),
|
||||
POWER(Res.string.power_metrics_log, Icons.Default.Power, NodeDetailRoutes.PowerMetrics),
|
||||
TRACEROUTE(Res.string.traceroute_log, Icons.Default.Route, NodeDetailRoutes.TracerouteLog),
|
||||
HOST(Res.string.host_metrics_log, Icons.Default.Memory, NodeDetailRoutes.HostMetricsLog),
|
||||
PAX(Res.string.pax_metrics_log, Icons.Default.People, NodeDetailRoutes.PaxMetrics),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ import org.meshtastic.core.database.entity.FirmwareRelease
|
|||
import org.meshtastic.core.database.entity.MeshLog
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.DeviceHardware
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.proto.ConfigProtos
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
import org.meshtastic.proto.TelemetryProtos
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
data class MetricsState(
|
||||
val isLocal: Boolean = false,
|
||||
|
|
@ -88,12 +88,12 @@ data class MetricsState(
|
|||
/** Supported time frames used to display data. */
|
||||
@Suppress("MagicNumber")
|
||||
enum class TimeFrame(val seconds: Long, @StringRes val strRes: Int) {
|
||||
TWENTY_FOUR_HOURS(TimeUnit.DAYS.toSeconds(1), R.string.twenty_four_hours),
|
||||
FORTY_EIGHT_HOURS(TimeUnit.DAYS.toSeconds(2), R.string.forty_eight_hours),
|
||||
ONE_WEEK(TimeUnit.DAYS.toSeconds(7), R.string.one_week),
|
||||
TWO_WEEKS(TimeUnit.DAYS.toSeconds(14), R.string.two_weeks),
|
||||
FOUR_WEEKS(TimeUnit.DAYS.toSeconds(28), R.string.four_weeks),
|
||||
MAX(0L, R.string.max),
|
||||
TWENTY_FOUR_HOURS(TimeUnit.DAYS.toSeconds(1), Res.string.twenty_four_hours),
|
||||
FORTY_EIGHT_HOURS(TimeUnit.DAYS.toSeconds(2), Res.string.forty_eight_hours),
|
||||
ONE_WEEK(TimeUnit.DAYS.toSeconds(7), Res.string.one_week),
|
||||
TWO_WEEKS(TimeUnit.DAYS.toSeconds(14), Res.string.two_weeks),
|
||||
FOUR_WEEKS(TimeUnit.DAYS.toSeconds(28), Res.string.four_weeks),
|
||||
MAX(0L, Res.string.max),
|
||||
;
|
||||
|
||||
fun calculateOldestTime(): Long = if (this == MAX) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue