2024-07-28 05:04:50 -05:00
|
|
|
@file:Suppress(
|
|
|
|
|
"LongMethod",
|
|
|
|
|
"MagicNumber",
|
|
|
|
|
"CyclomaticComplexMethod",
|
|
|
|
|
)
|
|
|
|
|
|
2024-03-07 01:39:02 -07:00
|
|
|
package com.geeksville.mesh.ui
|
|
|
|
|
|
2024-04-06 05:36:01 -06:00
|
|
|
import androidx.compose.animation.animateColorAsState
|
|
|
|
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
|
|
|
|
import androidx.compose.animation.core.RepeatMode
|
2024-06-23 08:24:29 -03:00
|
|
|
import androidx.compose.animation.core.repeatable
|
2024-04-06 05:36:01 -06:00
|
|
|
import androidx.compose.animation.core.tween
|
|
|
|
|
import androidx.compose.foundation.background
|
2024-07-28 05:04:50 -05:00
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
|
|
|
import androidx.compose.foundation.layout.Column
|
2024-08-03 06:35:00 -05:00
|
|
|
import androidx.compose.foundation.layout.IntrinsicSize
|
2024-07-28 05:04:50 -05:00
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
|
import androidx.compose.foundation.layout.Spacer
|
2024-03-07 01:39:02 -07:00
|
|
|
import androidx.compose.foundation.layout.defaultMinSize
|
|
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
|
|
import androidx.compose.foundation.layout.padding
|
2024-09-23 10:08:35 -03:00
|
|
|
import androidx.compose.foundation.layout.size
|
2024-03-07 01:39:02 -07:00
|
|
|
import androidx.compose.foundation.layout.width
|
2024-07-28 05:04:50 -05:00
|
|
|
import androidx.compose.foundation.text.selection.DisableSelection
|
|
|
|
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
2024-03-07 01:39:02 -07:00
|
|
|
import androidx.compose.material.Card
|
|
|
|
|
import androidx.compose.material.Chip
|
|
|
|
|
import androidx.compose.material.ChipDefaults
|
2024-07-28 05:04:50 -05:00
|
|
|
import androidx.compose.material.Divider
|
2024-03-07 01:39:02 -07:00
|
|
|
import androidx.compose.material.ExperimentalMaterialApi
|
|
|
|
|
import androidx.compose.material.LocalTextStyle
|
|
|
|
|
import androidx.compose.material.MaterialTheme
|
|
|
|
|
import androidx.compose.material.Surface
|
|
|
|
|
import androidx.compose.material.Text
|
|
|
|
|
import androidx.compose.runtime.Composable
|
2024-04-06 05:36:01 -06:00
|
|
|
import androidx.compose.runtime.getValue
|
2024-07-28 05:04:50 -05:00
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
|
|
import androidx.compose.runtime.remember
|
2024-09-23 10:08:35 -03:00
|
|
|
import androidx.compose.runtime.setValue
|
2024-07-28 05:04:50 -05:00
|
|
|
import androidx.compose.ui.Alignment
|
2024-03-07 01:39:02 -07:00
|
|
|
import androidx.compose.ui.Modifier
|
|
|
|
|
import androidx.compose.ui.graphics.Color
|
|
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
|
|
import androidx.compose.ui.text.font.FontStyle
|
|
|
|
|
import androidx.compose.ui.text.font.FontWeight
|
|
|
|
|
import androidx.compose.ui.text.style.TextAlign
|
|
|
|
|
import androidx.compose.ui.text.style.TextDecoration
|
|
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
|
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
|
|
|
|
import androidx.compose.ui.unit.dp
|
2024-03-07 02:34:43 -07:00
|
|
|
import com.geeksville.mesh.ConfigProtos
|
2024-08-10 06:17:51 -05:00
|
|
|
import com.geeksville.mesh.ConfigProtos.Config.DeviceConfig
|
2024-09-21 15:45:10 -03:00
|
|
|
import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig
|
2024-05-27 09:56:26 -03:00
|
|
|
import com.geeksville.mesh.MeshProtos
|
2024-03-07 01:39:02 -07:00
|
|
|
import com.geeksville.mesh.R
|
2024-09-21 15:45:10 -03:00
|
|
|
import com.geeksville.mesh.database.entity.NodeEntity
|
2024-09-23 10:08:35 -03:00
|
|
|
import com.geeksville.mesh.ui.components.NodeKeyStatusIcon
|
|
|
|
|
import com.geeksville.mesh.ui.components.SimpleAlertDialog
|
2024-03-07 02:34:43 -07:00
|
|
|
import com.geeksville.mesh.ui.compose.ElevationInfo
|
|
|
|
|
import com.geeksville.mesh.ui.compose.SatelliteCountInfo
|
2024-09-21 15:45:10 -03:00
|
|
|
import com.geeksville.mesh.ui.preview.NodeEntityPreviewParameterProvider
|
2024-03-07 01:39:02 -07:00
|
|
|
import com.geeksville.mesh.ui.theme.AppTheme
|
2024-03-07 02:34:43 -07:00
|
|
|
import com.geeksville.mesh.util.metersIn
|
2024-09-21 15:45:10 -03:00
|
|
|
import com.geeksville.mesh.util.toDistanceString
|
2024-03-07 01:39:02 -07:00
|
|
|
|
|
|
|
|
@OptIn(ExperimentalMaterialApi::class)
|
|
|
|
|
@Composable
|
2024-09-16 20:27:13 -03:00
|
|
|
fun NodeItem(
|
2024-09-21 15:45:10 -03:00
|
|
|
thisNode: NodeEntity?,
|
|
|
|
|
thatNode: NodeEntity,
|
2024-03-07 01:39:02 -07:00
|
|
|
gpsFormat: Int,
|
|
|
|
|
distanceUnits: Int,
|
|
|
|
|
tempInFahrenheit: Boolean,
|
|
|
|
|
isIgnored: Boolean = false,
|
2024-07-28 05:04:50 -05:00
|
|
|
chipClicked: () -> Unit = {},
|
2024-04-06 05:36:01 -06:00
|
|
|
blinking: Boolean = false,
|
2024-07-28 05:04:50 -05:00
|
|
|
expanded: Boolean = false,
|
2024-08-04 05:47:48 -05:00
|
|
|
currentTimeMillis: Long,
|
2024-03-07 01:39:02 -07:00
|
|
|
) {
|
2024-09-21 15:45:10 -03:00
|
|
|
val isUnknownUser = thatNode.user.hwModel == MeshProtos.HardwareModel.UNSET
|
2024-03-07 01:39:02 -07:00
|
|
|
val unknownShortName = stringResource(id = R.string.unknown_node_short_name)
|
2024-09-21 15:45:10 -03:00
|
|
|
val longName = thatNode.user.longName.ifEmpty { stringResource(id = R.string.unknown_username) }
|
2024-03-07 01:39:02 -07:00
|
|
|
|
2024-09-21 15:45:10 -03:00
|
|
|
val isThisNode = thisNode?.num == thatNode.num
|
|
|
|
|
val distance = thisNode?.distance(thatNode)?.let {
|
|
|
|
|
val system = DisplayConfig.DisplayUnits.forNumber(distanceUnits)
|
|
|
|
|
if (it == 0) null else it.toDistanceString(system)
|
|
|
|
|
}
|
|
|
|
|
val (textColor, nodeColor) = thatNode.colors
|
2024-03-07 01:39:02 -07:00
|
|
|
|
2024-09-21 15:45:10 -03:00
|
|
|
val hwInfoString = thatNode.user.hwModel.let { hwModel ->
|
|
|
|
|
if (hwModel == MeshProtos.HardwareModel.UNSET) MeshProtos.HardwareModel.UNSET.name
|
|
|
|
|
else hwModel.name.replace('_', '-').replace('p', '.').lowercase()
|
|
|
|
|
}
|
|
|
|
|
val roleName = if (isUnknownUser) {
|
|
|
|
|
DeviceConfig.Role.UNRECOGNIZED.name
|
|
|
|
|
} else {
|
|
|
|
|
thatNode.user.role.name
|
|
|
|
|
}
|
|
|
|
|
val nodeId = thatNode.user.id.ifEmpty { "???" }
|
2024-07-28 05:04:50 -05:00
|
|
|
|
2024-04-06 05:36:01 -06:00
|
|
|
val highlight = Color(0x33FFFFFF)
|
|
|
|
|
val bgColor by animateColorAsState(
|
|
|
|
|
targetValue = if (blinking) highlight else Color.Transparent,
|
2024-06-23 08:24:29 -03:00
|
|
|
animationSpec = repeatable(
|
|
|
|
|
iterations = 6,
|
2024-04-06 05:36:01 -06:00
|
|
|
animation = tween(
|
2024-06-23 08:24:29 -03:00
|
|
|
durationMillis = 250,
|
2024-04-06 05:36:01 -06:00
|
|
|
easing = FastOutSlowInEasing
|
|
|
|
|
),
|
|
|
|
|
repeatMode = RepeatMode.Reverse
|
2024-07-28 05:04:50 -05:00
|
|
|
),
|
|
|
|
|
label = "blinking node"
|
2024-04-06 05:36:01 -06:00
|
|
|
)
|
|
|
|
|
|
2024-09-16 18:44:18 -03:00
|
|
|
val style = if (isUnknownUser) {
|
2024-07-28 05:04:50 -05:00
|
|
|
LocalTextStyle.current.copy(fontStyle = FontStyle.Italic)
|
|
|
|
|
} else {
|
|
|
|
|
LocalTextStyle.current
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val (detailsShown, showDetails) = remember { mutableStateOf(expanded) }
|
|
|
|
|
|
2024-09-23 10:08:35 -03:00
|
|
|
var showEncryptionDialog by remember { mutableStateOf(false) }
|
|
|
|
|
if (showEncryptionDialog) {
|
|
|
|
|
val (title, text) = when {
|
|
|
|
|
thatNode.mismatchKey -> R.string.encryption_error to R.string.encryption_error_text
|
|
|
|
|
thatNode.hasPKC -> R.string.encryption_pkc to R.string.encryption_pkc_text
|
|
|
|
|
else -> R.string.encryption_psk to R.string.encryption_psk_text
|
|
|
|
|
}
|
|
|
|
|
SimpleAlertDialog(title, text) { showEncryptionDialog = false }
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-07 01:39:02 -07:00
|
|
|
Card(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.fillMaxWidth()
|
|
|
|
|
.padding(horizontal = 8.dp, vertical = 4.dp)
|
2024-07-28 05:04:50 -05:00
|
|
|
.defaultMinSize(minHeight = 80.dp),
|
|
|
|
|
onClick = { showDetails(!detailsShown) },
|
2024-03-07 01:39:02 -07:00
|
|
|
) {
|
|
|
|
|
Surface {
|
2024-07-28 05:04:50 -05:00
|
|
|
SelectionContainer {
|
|
|
|
|
Column(
|
2024-03-07 01:39:02 -07:00
|
|
|
modifier = Modifier
|
2024-07-28 05:04:50 -05:00
|
|
|
.fillMaxWidth()
|
|
|
|
|
.padding(8.dp)
|
|
|
|
|
.background(bgColor)
|
2024-03-07 01:39:02 -07:00
|
|
|
) {
|
2024-07-28 05:04:50 -05:00
|
|
|
Row(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.fillMaxWidth(),
|
|
|
|
|
verticalAlignment = Alignment.CenterVertically,
|
|
|
|
|
) {
|
|
|
|
|
Chip(
|
|
|
|
|
modifier = Modifier
|
2024-08-03 06:35:00 -05:00
|
|
|
.width(IntrinsicSize.Min)
|
|
|
|
|
.defaultMinSize(minHeight = 32.dp, minWidth = 72.dp),
|
2024-07-28 05:04:50 -05:00
|
|
|
colors = ChipDefaults.chipColors(
|
|
|
|
|
backgroundColor = Color(nodeColor),
|
|
|
|
|
contentColor = Color(textColor)
|
|
|
|
|
),
|
|
|
|
|
onClick = { chipClicked() },
|
|
|
|
|
content = {
|
|
|
|
|
Text(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
2024-09-21 15:45:10 -03:00
|
|
|
text = thatNode.user.shortName.ifEmpty { unknownShortName },
|
2024-07-28 05:04:50 -05:00
|
|
|
fontWeight = FontWeight.Normal,
|
|
|
|
|
fontSize = MaterialTheme.typography.button.fontSize,
|
|
|
|
|
textDecoration = TextDecoration.LineThrough.takeIf { isIgnored },
|
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
)
|
2024-09-23 10:08:35 -03:00
|
|
|
NodeKeyStatusIcon(
|
|
|
|
|
hasPKC = thatNode.hasPKC,
|
|
|
|
|
mismatchKey = thatNode.mismatchKey,
|
|
|
|
|
modifier = Modifier.size(32.dp)
|
|
|
|
|
) { showEncryptionDialog = true }
|
2024-07-28 05:04:50 -05:00
|
|
|
Text(
|
|
|
|
|
modifier = Modifier.weight(1f),
|
2024-09-23 10:08:35 -03:00
|
|
|
text = longName,
|
2024-07-28 05:04:50 -05:00
|
|
|
style = style,
|
|
|
|
|
textDecoration = TextDecoration.LineThrough.takeIf { isIgnored },
|
|
|
|
|
softWrap = true,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
LastHeardInfo(
|
2024-09-21 15:45:10 -03:00
|
|
|
lastHeard = thatNode.lastHeard,
|
2024-08-04 05:47:48 -05:00
|
|
|
currentTimeMillis = currentTimeMillis
|
2024-07-28 05:04:50 -05:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.fillMaxWidth(),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween
|
|
|
|
|
) {
|
|
|
|
|
if (distance != null) {
|
2024-03-07 01:39:02 -07:00
|
|
|
Text(
|
2024-07-28 05:04:50 -05:00
|
|
|
text = distance,
|
2024-03-07 01:39:02 -07:00
|
|
|
fontSize = MaterialTheme.typography.button.fontSize,
|
|
|
|
|
)
|
2024-07-28 05:04:50 -05:00
|
|
|
} else {
|
|
|
|
|
Spacer(modifier = Modifier.width(16.dp))
|
|
|
|
|
}
|
|
|
|
|
BatteryInfo(
|
2024-09-21 15:45:10 -03:00
|
|
|
batteryLevel = thatNode.batteryLevel,
|
|
|
|
|
voltage = thatNode.voltage
|
2024-03-07 01:39:02 -07:00
|
|
|
)
|
2024-07-28 05:04:50 -05:00
|
|
|
}
|
|
|
|
|
Spacer(modifier = Modifier.height(4.dp))
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween
|
|
|
|
|
) {
|
|
|
|
|
signalInfo(
|
2024-09-21 15:45:10 -03:00
|
|
|
node = thatNode,
|
2024-07-28 05:04:50 -05:00
|
|
|
isThisNode = isThisNode
|
2024-03-07 01:39:02 -07:00
|
|
|
)
|
2024-09-21 15:45:10 -03:00
|
|
|
thatNode.validPosition?.let { position ->
|
|
|
|
|
val satCount = position.satsInView
|
2024-07-28 05:04:50 -05:00
|
|
|
if (satCount > 0) {
|
|
|
|
|
SatelliteCountInfo(
|
|
|
|
|
satCount = satCount
|
|
|
|
|
)
|
2024-03-07 02:34:43 -07:00
|
|
|
}
|
2024-07-28 05:04:50 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Spacer(modifier = Modifier.height(4.dp))
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween
|
|
|
|
|
) {
|
2024-09-21 15:45:10 -03:00
|
|
|
val telemetryString = thatNode.getTelemetryString(tempInFahrenheit)
|
|
|
|
|
if (telemetryString.isNotEmpty()) {
|
2024-07-28 05:04:50 -05:00
|
|
|
Text(
|
2024-09-21 15:45:10 -03:00
|
|
|
text = telemetryString,
|
2024-07-28 05:04:50 -05:00
|
|
|
color = MaterialTheme.colors.onSurface,
|
|
|
|
|
fontSize = MaterialTheme.typography.button.fontSize
|
2024-03-07 02:34:43 -07:00
|
|
|
)
|
2024-07-28 05:04:50 -05:00
|
|
|
}
|
2024-05-19 06:47:48 -03:00
|
|
|
}
|
2024-03-07 02:34:43 -07:00
|
|
|
|
2024-07-28 05:04:50 -05:00
|
|
|
if (detailsShown || expanded) {
|
|
|
|
|
Spacer(modifier = Modifier.height(8.dp))
|
|
|
|
|
Divider()
|
|
|
|
|
Spacer(modifier = Modifier.height(8.dp))
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.fillMaxWidth(),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween
|
|
|
|
|
) {
|
2024-09-21 15:45:10 -03:00
|
|
|
thatNode.validPosition?.let {
|
|
|
|
|
DisableSelection {
|
|
|
|
|
LinkedCoordinates(
|
|
|
|
|
latitude = thatNode.latitude,
|
|
|
|
|
longitude = thatNode.longitude,
|
|
|
|
|
format = gpsFormat,
|
|
|
|
|
nodeName = longName
|
|
|
|
|
)
|
|
|
|
|
}
|
2024-03-07 02:34:43 -07:00
|
|
|
}
|
2024-07-28 05:04:50 -05:00
|
|
|
val system =
|
|
|
|
|
ConfigProtos.Config.DisplayConfig.DisplayUnits.forNumber(distanceUnits)
|
2024-09-21 15:45:10 -03:00
|
|
|
thatNode.validPosition?.let { position ->
|
2024-07-28 05:04:50 -05:00
|
|
|
val altitude = position.altitude.metersIn(system)
|
|
|
|
|
val elevationSuffix = stringResource(id = R.string.elevation_suffix)
|
|
|
|
|
ElevationInfo(
|
|
|
|
|
altitude = altitude,
|
|
|
|
|
system = system,
|
|
|
|
|
suffix = elevationSuffix
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Spacer(modifier = Modifier.height(4.dp))
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
) {
|
2024-09-16 18:20:20 -05:00
|
|
|
Text(
|
|
|
|
|
modifier = Modifier.weight(1f),
|
|
|
|
|
text = hwInfoString,
|
|
|
|
|
fontSize = MaterialTheme.typography.button.fontSize,
|
|
|
|
|
style = style,
|
|
|
|
|
)
|
|
|
|
|
Text(
|
|
|
|
|
modifier = Modifier.weight(1f),
|
|
|
|
|
text = roleName,
|
|
|
|
|
textAlign = TextAlign.Center,
|
2024-09-21 15:45:10 -03:00
|
|
|
fontSize = MaterialTheme.typography.button.fontSize,
|
|
|
|
|
style = style,
|
2024-09-16 18:20:20 -05:00
|
|
|
)
|
|
|
|
|
Text(
|
|
|
|
|
modifier = Modifier.weight(1f),
|
|
|
|
|
text = nodeId,
|
|
|
|
|
textAlign = TextAlign.End,
|
2024-09-21 15:45:10 -03:00
|
|
|
fontSize = MaterialTheme.typography.button.fontSize,
|
|
|
|
|
style = style,
|
2024-09-16 18:20:20 -05:00
|
|
|
)
|
2024-07-28 05:04:50 -05:00
|
|
|
}
|
|
|
|
|
}
|
2024-03-07 01:39:02 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
@Preview(showBackground = false)
|
|
|
|
|
fun NodeInfoSimplePreview() {
|
|
|
|
|
AppTheme {
|
2024-09-21 15:45:10 -03:00
|
|
|
val thisNode = NodeEntityPreviewParameterProvider().values.first()
|
|
|
|
|
val thatNode = NodeEntityPreviewParameterProvider().values.last()
|
2024-09-16 20:27:13 -03:00
|
|
|
NodeItem(
|
2024-09-21 15:45:10 -03:00
|
|
|
thisNode = thisNode,
|
|
|
|
|
thatNode = thatNode,
|
2024-03-07 01:39:02 -07:00
|
|
|
1,
|
|
|
|
|
0,
|
2024-08-04 05:47:48 -05:00
|
|
|
true,
|
|
|
|
|
currentTimeMillis = System.currentTimeMillis()
|
2024-03-07 01:39:02 -07:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
@Preview(
|
|
|
|
|
showBackground = true,
|
|
|
|
|
uiMode = android.content.res.Configuration.UI_MODE_NIGHT_YES,
|
|
|
|
|
)
|
|
|
|
|
fun NodeInfoPreview(
|
2024-09-21 15:45:10 -03:00
|
|
|
@PreviewParameter(NodeEntityPreviewParameterProvider::class)
|
|
|
|
|
thatNode: NodeEntity
|
2024-03-07 01:39:02 -07:00
|
|
|
) {
|
|
|
|
|
AppTheme {
|
2024-09-21 15:45:10 -03:00
|
|
|
val thisNode = NodeEntityPreviewParameterProvider().values.first()
|
2024-07-28 05:04:50 -05:00
|
|
|
Column {
|
|
|
|
|
Text(
|
|
|
|
|
text = "Details Collapsed",
|
|
|
|
|
color = MaterialTheme.colors.onBackground
|
|
|
|
|
)
|
2024-09-16 20:27:13 -03:00
|
|
|
NodeItem(
|
2024-09-21 15:45:10 -03:00
|
|
|
thisNode = thisNode,
|
|
|
|
|
thatNode = thatNode,
|
2024-07-28 05:04:50 -05:00
|
|
|
gpsFormat = 0,
|
|
|
|
|
distanceUnits = 1,
|
|
|
|
|
tempInFahrenheit = true,
|
2024-08-04 05:47:48 -05:00
|
|
|
expanded = false,
|
|
|
|
|
currentTimeMillis = System.currentTimeMillis()
|
2024-07-28 05:04:50 -05:00
|
|
|
)
|
|
|
|
|
Text(
|
|
|
|
|
text = "Details Shown",
|
|
|
|
|
color = MaterialTheme.colors.onBackground
|
|
|
|
|
)
|
2024-09-16 20:27:13 -03:00
|
|
|
NodeItem(
|
2024-09-21 15:45:10 -03:00
|
|
|
thisNode = thisNode,
|
|
|
|
|
thatNode = thatNode,
|
2024-07-28 05:04:50 -05:00
|
|
|
gpsFormat = 0,
|
|
|
|
|
distanceUnits = 1,
|
|
|
|
|
tempInFahrenheit = true,
|
2024-08-04 05:47:48 -05:00
|
|
|
expanded = true,
|
|
|
|
|
currentTimeMillis = System.currentTimeMillis()
|
2024-07-28 05:04:50 -05:00
|
|
|
)
|
|
|
|
|
}
|
2024-03-07 01:39:02 -07:00
|
|
|
}
|
2024-06-23 08:24:29 -03:00
|
|
|
}
|