refactor(R): Move R file imports to core UI module (#3159)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2025-09-22 20:59:39 -05:00 committed by GitHub
parent e8e7608e52
commit d2db37e0d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
176 changed files with 579 additions and 647 deletions

View file

@ -124,7 +124,6 @@ import coil3.request.ImageRequest
import com.geeksville.mesh.ConfigProtos
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.R
import com.geeksville.mesh.database.entity.FirmwareRelease
import com.geeksville.mesh.database.entity.asDeviceVersion
import com.geeksville.mesh.model.DeviceVersion
@ -162,6 +161,7 @@ import org.meshtastic.core.model.DeviceHardware
import org.meshtastic.core.navigation.NodeDetailRoutes
import org.meshtastic.core.navigation.Route
import org.meshtastic.core.navigation.SettingsRoutes
import org.meshtastic.core.strings.R
private data class VectorMetricInfo(
@StringRes val label: Int,
@ -717,7 +717,12 @@ private fun ColumnScope.DeviceDetailsContent(state: MetricsState) {
} else {
stringResource(R.string.supported_by_community)
},
icon = if (isSupported) Icons.TwoTone.Verified else ImageVector.vectorResource(R.drawable.unverified),
icon =
if (isSupported) {
Icons.TwoTone.Verified
} else {
ImageVector.vectorResource(com.geeksville.mesh.R.drawable.unverified)
},
trailingText = "",
iconTint = if (isSupported) colorScheme.StatusGreen else colorScheme.StatusRed,
)
@ -731,9 +736,9 @@ fun DeviceHardwareImage(deviceHardware: DeviceHardware, modifier: Modifier = Mod
model = ImageRequest.Builder(LocalContext.current).data(imageUrl).build(),
contentScale = ContentScale.Inside,
contentDescription = deviceHardware.displayName,
placeholder = painterResource(R.drawable.hw_unknown),
error = painterResource(R.drawable.hw_unknown),
fallback = painterResource(R.drawable.hw_unknown),
placeholder = painterResource(com.geeksville.mesh.R.drawable.hw_unknown),
error = painterResource(com.geeksville.mesh.R.drawable.hw_unknown),
fallback = painterResource(com.geeksville.mesh.R.drawable.hw_unknown),
modifier = modifier.padding(16.dp),
)
}
@ -982,7 +987,7 @@ private fun EnvironmentMetrics(
DrawableMetricInfo(
R.string.dew_point,
dewPoint.toTempString(isFahrenheit),
R.drawable.ic_outlined_dew_point_24,
com.geeksville.mesh.R.drawable.ic_outlined_dew_point_24,
),
)
}
@ -991,7 +996,7 @@ private fun EnvironmentMetrics(
DrawableMetricInfo(
R.string.soil_temperature,
soilTemperature.toTempString(isFahrenheit),
R.drawable.soil_temperature,
com.geeksville.mesh.R.drawable.soil_temperature,
),
)
}
@ -1000,7 +1005,7 @@ private fun EnvironmentMetrics(
DrawableMetricInfo(
R.string.soil_moisture,
"%d%%".format(soilMoisture),
R.drawable.soil_moisture,
com.geeksville.mesh.R.drawable.soil_moisture,
),
)
}
@ -1009,7 +1014,7 @@ private fun EnvironmentMetrics(
DrawableMetricInfo(
R.string.radiation,
"%.1f µR/h".format(radiation),
R.drawable.ic_filled_radioactive_24,
com.geeksville.mesh.R.drawable.ic_filled_radioactive_24,
),
)
}

View file

@ -47,7 +47,6 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.R
import com.geeksville.mesh.model.DeviceVersion
import com.geeksville.mesh.model.Node
import com.geeksville.mesh.model.UIViewModel
@ -60,6 +59,7 @@ import com.geeksville.mesh.ui.node.components.NodeMenuAction
import com.geeksville.mesh.ui.sharing.AddContactFAB
import com.geeksville.mesh.ui.sharing.SharedContactDialog
import com.geeksville.mesh.ui.sharing.supportsQrCodeSharing
import org.meshtastic.core.strings.R
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3ExpressiveApi::class)
@Suppress("LongMethod", "CyclomaticComplexMethod")

View file

@ -35,26 +35,18 @@ import com.geeksville.mesh.ui.common.theme.AppTheme
import com.geeksville.mesh.util.formatAgo
@Composable
fun LastHeardInfo(
modifier: Modifier = Modifier,
lastHeard: Int,
currentTimeMillis: Long,
) {
fun LastHeardInfo(modifier: Modifier = Modifier, lastHeard: Int, currentTimeMillis: Long) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(2.dp)
horizontalArrangement = Arrangement.spacedBy(2.dp),
) {
Icon(
modifier = Modifier.height(18.dp),
imageVector = ImageVector.vectorResource(id = R.drawable.ic_antenna_24),
contentDescription = null,
)
Text(
text = formatAgo(lastHeard, currentTimeMillis),
fontSize = MaterialTheme.typography.labelLarge.fontSize
)
Text(text = formatAgo(lastHeard, currentTimeMillis), fontSize = MaterialTheme.typography.labelLarge.fontSize)
}
}
@ -64,7 +56,7 @@ fun LastHeardInfoPreview() {
AppTheme {
LastHeardInfo(
lastHeard = (System.currentTimeMillis() / 1000).toInt() - 8600,
currentTimeMillis = System.currentTimeMillis()
currentTimeMillis = System.currentTimeMillis(),
)
}
}

View file

@ -56,10 +56,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.R
import com.geeksville.mesh.model.NodeSortOption
import com.geeksville.mesh.ui.common.preview.LargeFontPreview
import com.geeksville.mesh.ui.common.theme.AppTheme
import org.meshtastic.core.strings.R
@Suppress("LongParameterList")
@Composable

View file

@ -51,7 +51,6 @@ import androidx.compose.ui.unit.dp
import com.geeksville.mesh.ConfigProtos.Config.DeviceConfig
import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.R
import com.geeksville.mesh.model.Node
import com.geeksville.mesh.model.isUnmessageableRole
import com.geeksville.mesh.ui.common.components.BatteryInfo
@ -59,6 +58,7 @@ import com.geeksville.mesh.ui.common.components.SignalInfo
import com.geeksville.mesh.ui.common.preview.NodePreviewParameterProvider
import com.geeksville.mesh.ui.common.theme.AppTheme
import com.geeksville.mesh.util.toDistanceString
import org.meshtastic.core.strings.R
@Suppress("LongMethod", "CyclomaticComplexMethod")
@Composable

View file

@ -54,7 +54,6 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.geeksville.mesh.R
import com.geeksville.mesh.ui.common.components.CopyIconButton
import com.geeksville.mesh.ui.common.theme.AppTheme
import com.geeksville.mesh.ui.common.theme.StatusColors.StatusGreen
@ -62,6 +61,7 @@ import com.geeksville.mesh.ui.common.theme.StatusColors.StatusRed
import com.geeksville.mesh.ui.common.theme.StatusColors.StatusYellow
import com.google.protobuf.ByteString
import org.meshtastic.core.model.Channel
import org.meshtastic.core.strings.R
@Composable
private fun KeyStatusDialog(@StringRes title: Int, @StringRes text: Int, key: ByteString?, onDismiss: () -> Unit = {}) =
@ -129,7 +129,9 @@ fun NodeKeyStatusIcon(
when {
mismatchKey -> Icons.Default.KeyOff to colorScheme.StatusRed
hasPKC -> Icons.Default.Lock to colorScheme.StatusGreen
else -> ImageVector.vectorResource(R.drawable.ic_lock_open_right_24) to colorScheme.StatusYellow
else ->
ImageVector.vectorResource(com.geeksville.mesh.R.drawable.ic_lock_open_right_24) to
colorScheme.StatusYellow
}
IconButton(onClick = { showEncryptionDialog = true }, modifier = modifier) {

View file

@ -38,10 +38,10 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.R
import com.geeksville.mesh.model.Node
import com.geeksville.mesh.model.isUnmessageableRole
import com.geeksville.mesh.ui.common.components.SimpleAlertDialog
import org.meshtastic.core.strings.R
@Suppress("LongMethod")
@Composable
@ -52,12 +52,13 @@ fun NodeMenu(
onDismissMenuRequest: () -> Unit,
onAction: (NodeMenuAction) -> Unit,
) {
val isUnmessageable = if (node.user.hasIsUnmessagable()) {
node.user.isUnmessagable
} else {
// for older firmwares
node.user.role?.isUnmessageableRole() == true
}
val isUnmessageable =
if (node.user.hasIsUnmessagable()) {
node.user.isUnmessagable
} else {
// for older firmwares
node.user.role?.isUnmessageableRole() == true
}
var displayFavoriteDialog by remember { mutableStateOf(false) }
var displayIgnoreDialog by remember { mutableStateOf(false) }
@ -79,14 +80,13 @@ fun NodeMenu(
displayIgnoreDialog = displayIgnoreDialog,
displayRemoveDialog = displayRemoveDialog,
onDismissMenuRequest = dialogDismissRequest,
onAction = onMenuAction
onAction = onMenuAction,
)
DropdownMenu(
modifier = Modifier.background(MaterialTheme.colorScheme.background.copy(alpha = 1f)),
expanded = expanded,
onDismissRequest = onDismissMenuRequest,
) {
if (showFullMenu) {
if (!isUnmessageable) {
DropdownMenuItem(
@ -94,7 +94,7 @@ fun NodeMenu(
dialogDismissRequest()
onMenuAction(NodeMenuAction.DirectMessage(node))
},
text = { Text(stringResource(R.string.direct_message)) }
text = { Text(stringResource(R.string.direct_message)) },
)
}
DropdownMenuItem(
@ -102,21 +102,21 @@ fun NodeMenu(
dialogDismissRequest()
onMenuAction(NodeMenuAction.RequestUserInfo(node))
},
text = { Text(stringResource(R.string.exchange_userinfo)) }
text = { Text(stringResource(R.string.exchange_userinfo)) },
)
DropdownMenuItem(
onClick = {
dialogDismissRequest()
onMenuAction(NodeMenuAction.RequestPosition(node))
},
text = { Text(stringResource(R.string.exchange_position)) }
text = { Text(stringResource(R.string.exchange_position)) },
)
DropdownMenuItem(
onClick = {
dialogDismissRequest()
onMenuAction(NodeMenuAction.TraceRoute(node))
},
text = { Text(stringResource(R.string.traceroute)) }
text = { Text(stringResource(R.string.traceroute)) },
)
DropdownMenuItem(
onClick = {
@ -124,24 +124,20 @@ fun NodeMenu(
displayFavoriteDialog = true
},
enabled = !node.isIgnored,
text = {
Text(stringResource(R.string.favorite))
},
text = { Text(stringResource(R.string.favorite)) },
trailingIcon = {
Icon(
imageVector = if (node.isFavorite) Icons.Filled.Star else Icons.TwoTone.StarBorder,
contentDescription = stringResource(R.string.favorite),
)
}
},
)
DropdownMenuItem(
onClick = {
dialogDismissRequest()
displayIgnoreDialog = true
},
text = {
Text(stringResource(R.string.ignore))
},
text = { Text(stringResource(R.string.ignore)) },
trailingIcon = {
Checkbox(
checked = node.isIgnored,
@ -151,7 +147,7 @@ fun NodeMenu(
},
modifier = Modifier.size(24.dp),
)
}
},
)
DropdownMenuItem(
onClick = {
@ -159,7 +155,7 @@ fun NodeMenu(
displayRemoveDialog = true
},
enabled = !node.isIgnored,
text = { Text(stringResource(R.string.remove)) }
text = { Text(stringResource(R.string.remove)) },
)
HorizontalDivider(Modifier.padding(vertical = 8.dp))
}
@ -168,7 +164,7 @@ fun NodeMenu(
dialogDismissRequest()
onMenuAction(NodeMenuAction.Share(node))
},
text = { Text(stringResource(R.string.share_contact)) }
text = { Text(stringResource(R.string.share_contact)) },
)
DropdownMenuItem(
@ -176,7 +172,7 @@ fun NodeMenu(
dialogDismissRequest()
onMenuAction(NodeMenuAction.MoreDetails(node))
},
text = { Text(stringResource(R.string.more_details)) }
text = { Text(stringResource(R.string.more_details)) },
)
}
}
@ -188,34 +184,36 @@ fun NodeActionDialogs(
displayIgnoreDialog: Boolean,
displayRemoveDialog: Boolean,
onDismissMenuRequest: () -> Unit,
onAction: (NodeMenuAction) -> Unit
onAction: (NodeMenuAction) -> Unit,
) {
if (displayFavoriteDialog) {
SimpleAlertDialog(
title = R.string.favorite,
text = stringResource(
text =
stringResource(
id = if (node.isFavorite) R.string.favorite_remove else R.string.favorite_add,
node.user.longName
node.user.longName,
),
onConfirm = {
onDismissMenuRequest()
onAction(NodeMenuAction.Favorite(node))
},
onDismiss = onDismissMenuRequest
onDismiss = onDismissMenuRequest,
)
}
if (displayIgnoreDialog) {
SimpleAlertDialog(
title = R.string.ignore,
text = stringResource(
text =
stringResource(
id = if (node.isIgnored) R.string.ignore_remove else R.string.ignore_add,
node.user.longName
node.user.longName,
),
onConfirm = {
onDismissMenuRequest()
onAction(NodeMenuAction.Ignore(node))
},
onDismiss = onDismissMenuRequest
onDismiss = onDismissMenuRequest,
)
}
if (displayRemoveDialog) {
@ -226,19 +224,27 @@ fun NodeActionDialogs(
onDismissMenuRequest()
onAction(NodeMenuAction.Remove(node))
},
onDismiss = onDismissMenuRequest
onDismiss = onDismissMenuRequest,
)
}
}
sealed class NodeMenuAction {
data class Remove(val node: Node) : NodeMenuAction()
data class Ignore(val node: Node) : NodeMenuAction()
data class Favorite(val node: Node) : NodeMenuAction()
data class DirectMessage(val node: Node) : NodeMenuAction()
data class RequestUserInfo(val node: Node) : NodeMenuAction()
data class RequestPosition(val node: Node) : NodeMenuAction()
data class TraceRoute(val node: Node) : NodeMenuAction()
data class MoreDetails(val node: Node) : NodeMenuAction()
data class Share(val node: Node) : NodeMenuAction()
}

View file

@ -39,10 +39,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 com.geeksville.mesh.R
import com.geeksville.mesh.ui.common.theme.StatusColors.StatusGreen
import com.geeksville.mesh.ui.common.theme.StatusColors.StatusRed
import com.geeksville.mesh.ui.common.theme.StatusColors.StatusYellow
import org.meshtastic.core.strings.R
@Suppress("LongMethod")
@OptIn(ExperimentalMaterial3Api::class)

View file

@ -34,9 +34,9 @@ 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 com.geeksville.mesh.R
import com.geeksville.mesh.ui.common.theme.AppTheme
import com.geeksville.mesh.ui.settings.components.SettingsItem
import org.meshtastic.core.strings.R
private const val COOL_DOWN_TIME_MS = 30000L