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
|
|
@ -45,12 +45,12 @@ import com.geeksville.mesh.ui.MainScreen
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.meshtastic.core.datastore.UiPreferencesDataSource
|
||||
import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.ui.theme.MODE_DYNAMIC
|
||||
import org.meshtastic.feature.intro.AppIntroductionScreen
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
|
@ -119,13 +119,13 @@ class MainActivity : AppCompatActivity() {
|
|||
Timber.d("App link data is a channel set")
|
||||
model.requestChannelUrl(
|
||||
url = it,
|
||||
onFailure = { Toast.makeText(this, R.string.channel_invalid, Toast.LENGTH_SHORT).show() },
|
||||
onFailure = { Toast.makeText(this, Res.string.channel_invalid, Toast.LENGTH_SHORT).show() },
|
||||
)
|
||||
} else if (it.path?.startsWith("/v/") == true || it.path?.startsWith("/V/") == true) {
|
||||
Timber.d("App link data is a shared contact")
|
||||
model.setSharedContactRequested(
|
||||
url = it,
|
||||
onFailure = { Toast.makeText(this, R.string.contact_invalid, Toast.LENGTH_SHORT).show() },
|
||||
onFailure = { Toast.makeText(this, Res.string.contact_invalid, Toast.LENGTH_SHORT).show() },
|
||||
)
|
||||
} else {
|
||||
Timber.d("App link data is not a channel set")
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ import org.meshtastic.core.datastore.RecentAddressesDataSource
|
|||
import org.meshtastic.core.datastore.model.RecentAddress
|
||||
import org.meshtastic.core.model.util.anonymize
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* A sealed class is used here to represent the different types of devices that can be displayed in the list. This is
|
||||
|
|
@ -135,7 +135,8 @@ constructor(
|
|||
val idBytes = txtRecords["id"]
|
||||
|
||||
val shortName =
|
||||
shortNameBytes?.let { String(it, Charsets.UTF_8) } ?: context.getString(R.string.meshtastic)
|
||||
shortNameBytes?.let { String(it, Charsets.UTF_8) }
|
||||
?: context.getString(Res.string.meshtastic)
|
||||
val deviceId = idBytes?.let { String(it, Charsets.UTF_8) }?.replace("!", "")
|
||||
var displayName = recentMap[address] ?: shortName
|
||||
if (deviceId != null && !displayName.split("_").none { it == deviceId }) {
|
||||
|
|
@ -282,10 +283,10 @@ constructor(
|
|||
if (state != BluetoothDevice.BOND_BONDING) {
|
||||
Timber.d("Bonding completed, state=$state")
|
||||
if (state == BluetoothDevice.BOND_BONDED) {
|
||||
setErrorText(context.getString(R.string.pairing_completed))
|
||||
setErrorText(context.getString(Res.string.pairing_completed))
|
||||
changeDeviceAddress("x${device.address}")
|
||||
} else {
|
||||
setErrorText(context.getString(R.string.pairing_failed_try_again))
|
||||
setErrorText(context.getString(Res.string.pairing_failed_try_again))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ import org.meshtastic.core.model.util.toChannelSet
|
|||
import org.meshtastic.core.service.IMeshService
|
||||
import org.meshtastic.core.service.MeshServiceNotifications
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.toSharedContact
|
||||
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
|
|
@ -59,6 +58,7 @@ import org.meshtastic.proto.AppOnlyProtos
|
|||
import org.meshtastic.proto.MeshProtos
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
// Given a human name, strip out the first letter of the first three words and return that as the
|
||||
// initials for
|
||||
|
|
@ -178,7 +178,7 @@ constructor(
|
|||
.filterNotNull()
|
||||
.onEach {
|
||||
showAlert(
|
||||
title = app.getString(R.string.client_notification),
|
||||
title = app.getString(Res.string.client_notification),
|
||||
message = it,
|
||||
onConfirm = { serviceRepository.clearErrorMessage() },
|
||||
dismissable = false,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
|
|||
import org.meshtastic.core.navigation.NodeDetailRoutes
|
||||
import org.meshtastic.core.navigation.NodesRoutes
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.map.node.NodeMapScreen
|
||||
import org.meshtastic.feature.map.node.NodeMapViewModel
|
||||
import org.meshtastic.feature.node.detail.NodeDetailScreen
|
||||
|
|
@ -58,6 +57,7 @@ import org.meshtastic.feature.node.metrics.PositionLogScreen
|
|||
import org.meshtastic.feature.node.metrics.PowerMetricsScreen
|
||||
import org.meshtastic.feature.node.metrics.SignalMetricsScreen
|
||||
import org.meshtastic.feature.node.metrics.TracerouteLogScreen
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
fun NavGraphBuilder.nodesGraph(navController: NavHostController) {
|
||||
navigation<NodesRoutes.NodesGraph>(startDestination = NodesRoutes.Nodes) {
|
||||
|
|
@ -204,49 +204,49 @@ enum class NodeDetailRoute(
|
|||
val screenComposable: @Composable (metricsViewModel: MetricsViewModel, onNavigateUp: () -> Unit) -> Unit,
|
||||
) {
|
||||
DEVICE(
|
||||
R.string.device,
|
||||
Res.string.device,
|
||||
NodeDetailRoutes.DeviceMetrics,
|
||||
Icons.Default.Router,
|
||||
{ metricsVM, onNavigateUp -> DeviceMetricsScreen(metricsVM, onNavigateUp) },
|
||||
),
|
||||
POSITION_LOG(
|
||||
R.string.position_log,
|
||||
Res.string.position_log,
|
||||
NodeDetailRoutes.PositionLog,
|
||||
Icons.Default.LocationOn,
|
||||
{ metricsVM, onNavigateUp -> PositionLogScreen(metricsVM, onNavigateUp) },
|
||||
),
|
||||
ENVIRONMENT(
|
||||
R.string.environment,
|
||||
Res.string.environment,
|
||||
NodeDetailRoutes.EnvironmentMetrics,
|
||||
Icons.Default.LightMode,
|
||||
{ metricsVM, onNavigateUp -> EnvironmentMetricsScreen(metricsVM, onNavigateUp) },
|
||||
),
|
||||
SIGNAL(
|
||||
R.string.signal,
|
||||
Res.string.signal,
|
||||
NodeDetailRoutes.SignalMetrics,
|
||||
Icons.Default.CellTower,
|
||||
{ metricsVM, onNavigateUp -> SignalMetricsScreen(metricsVM, onNavigateUp) },
|
||||
),
|
||||
TRACEROUTE(
|
||||
R.string.traceroute,
|
||||
Res.string.traceroute,
|
||||
NodeDetailRoutes.TracerouteLog,
|
||||
Icons.Default.PermScanWifi,
|
||||
{ metricsVM, onNavigateUp -> TracerouteLogScreen(viewModel = metricsVM, onNavigateUp = onNavigateUp) },
|
||||
),
|
||||
POWER(
|
||||
R.string.power,
|
||||
Res.string.power,
|
||||
NodeDetailRoutes.PowerMetrics,
|
||||
Icons.Default.Power,
|
||||
{ metricsVM, onNavigateUp -> PowerMetricsScreen(metricsVM, onNavigateUp) },
|
||||
),
|
||||
HOST(
|
||||
R.string.host,
|
||||
Res.string.host,
|
||||
NodeDetailRoutes.HostMetricsLog,
|
||||
Icons.Default.Memory,
|
||||
{ metricsVM, onNavigateUp -> HostMetricsLogScreen(metricsVM, onNavigateUp) },
|
||||
),
|
||||
PAX(
|
||||
R.string.pax,
|
||||
Res.string.pax,
|
||||
NodeDetailRoutes.PaxMetrics,
|
||||
Icons.Default.People,
|
||||
{ metricsVM, onNavigateUp -> PaxMetricsScreen(metricsVM, onNavigateUp) },
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ import org.meshtastic.core.service.MeshServiceNotifications
|
|||
import org.meshtastic.core.service.SERVICE_NOTIFY_ID
|
||||
import org.meshtastic.core.service.ServiceAction
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.proto.AppOnlyProtos
|
||||
import org.meshtastic.proto.ChannelProtos
|
||||
|
|
@ -114,6 +113,7 @@ import java.util.UUID
|
|||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.absoluteValue
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* Handles all the communication with android apps. Also keeps an internal model of the network state.
|
||||
|
|
@ -224,7 +224,7 @@ class MeshService : Service() {
|
|||
|
||||
private fun getSenderName(packet: DataPacket?): String {
|
||||
val name = nodeDBbyID[packet?.from]?.user?.longName
|
||||
return name ?: getString(R.string.unknown_username)
|
||||
return name ?: getString(Res.string.unknown_username)
|
||||
}
|
||||
|
||||
/** start our location requests (if they weren't already running) */
|
||||
|
|
@ -269,7 +269,7 @@ class MeshService : Service() {
|
|||
serviceNotifications.showAlertNotification(
|
||||
contactKey,
|
||||
getSenderName(dataPacket),
|
||||
dataPacket.alert ?: getString(R.string.critical_alert),
|
||||
dataPacket.alert ?: getString(Res.string.critical_alert),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -278,7 +278,7 @@ class MeshService : Service() {
|
|||
when (dataPacket.dataType) {
|
||||
Portnums.PortNum.TEXT_MESSAGE_APP_VALUE -> dataPacket.text!!
|
||||
Portnums.PortNum.WAYPOINT_APP_VALUE -> {
|
||||
getString(R.string.waypoint_received, dataPacket.waypoint!!.name)
|
||||
getString(Res.string.waypoint_received, dataPacket.waypoint!!.name)
|
||||
}
|
||||
|
||||
else -> return
|
||||
|
|
@ -786,7 +786,7 @@ class MeshService : Service() {
|
|||
val u = MeshProtos.Routing.parseFrom(data.payload)
|
||||
|
||||
if (u.errorReason == MeshProtos.Routing.Error.DUTY_CYCLE_LIMIT) {
|
||||
serviceRepository.setErrorMessage(getString(R.string.error_duty_cycle))
|
||||
serviceRepository.setErrorMessage(getString(Res.string.error_duty_cycle))
|
||||
}
|
||||
|
||||
handleAckNak(data.requestId, fromId, u.errorReasonValue, dataPacket.relayNode)
|
||||
|
|
@ -1317,10 +1317,10 @@ class MeshService : Service() {
|
|||
private fun updateServiceStatusNotification(telemetry: TelemetryProtos.Telemetry? = null): Notification {
|
||||
val notificationSummary =
|
||||
when (connectionStateHolder.getState()) {
|
||||
ConnectionState.CONNECTED -> getString(R.string.connected_count).format(numOnlineNodes)
|
||||
ConnectionState.CONNECTED -> getString(Res.string.connected_count).format(numOnlineNodes)
|
||||
|
||||
ConnectionState.DISCONNECTED -> getString(R.string.disconnected)
|
||||
ConnectionState.DEVICE_SLEEP -> getString(R.string.device_sleeping)
|
||||
ConnectionState.DISCONNECTED -> getString(Res.string.disconnected)
|
||||
ConnectionState.DEVICE_SLEEP -> getString(Res.string.device_sleeping)
|
||||
}
|
||||
return serviceNotifications.updateServiceStateNotification(
|
||||
summaryString = notificationSummary,
|
||||
|
|
|
|||
|
|
@ -43,11 +43,11 @@ import org.meshtastic.core.model.util.formatUptime
|
|||
import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
|
||||
import org.meshtastic.core.service.MeshServiceNotifications
|
||||
import org.meshtastic.core.service.SERVICE_NOTIFY_ID
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
import org.meshtastic.proto.TelemetryProtos
|
||||
import org.meshtastic.proto.TelemetryProtos.LocalStats
|
||||
import javax.inject.Inject
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* Manages the creation and display of all app notifications.
|
||||
|
|
@ -79,54 +79,58 @@ class MeshServiceNotificationsImpl @Inject constructor(@ApplicationContext priva
|
|||
object ServiceState :
|
||||
NotificationType(
|
||||
"my_service",
|
||||
R.string.meshtastic_service_notifications,
|
||||
Res.string.meshtastic_service_notifications,
|
||||
NotificationManager.IMPORTANCE_MIN,
|
||||
)
|
||||
|
||||
object DirectMessage :
|
||||
NotificationType(
|
||||
"my_messages",
|
||||
R.string.meshtastic_messages_notifications,
|
||||
Res.string.meshtastic_messages_notifications,
|
||||
NotificationManager.IMPORTANCE_HIGH,
|
||||
)
|
||||
|
||||
object BroadcastMessage :
|
||||
NotificationType(
|
||||
"my_broadcasts",
|
||||
R.string.meshtastic_broadcast_notifications,
|
||||
Res.string.meshtastic_broadcast_notifications,
|
||||
NotificationManager.IMPORTANCE_DEFAULT,
|
||||
)
|
||||
|
||||
object Alert :
|
||||
NotificationType(
|
||||
"my_alerts",
|
||||
R.string.meshtastic_alerts_notifications,
|
||||
Res.string.meshtastic_alerts_notifications,
|
||||
NotificationManager.IMPORTANCE_HIGH,
|
||||
)
|
||||
|
||||
object NewNode :
|
||||
NotificationType(
|
||||
"new_nodes",
|
||||
R.string.meshtastic_new_nodes_notifications,
|
||||
Res.string.meshtastic_new_nodes_notifications,
|
||||
NotificationManager.IMPORTANCE_DEFAULT,
|
||||
)
|
||||
|
||||
object LowBatteryLocal :
|
||||
NotificationType(
|
||||
"low_battery",
|
||||
R.string.meshtastic_low_battery_notifications,
|
||||
Res.string.meshtastic_low_battery_notifications,
|
||||
NotificationManager.IMPORTANCE_DEFAULT,
|
||||
)
|
||||
|
||||
object LowBatteryRemote :
|
||||
NotificationType(
|
||||
"low_battery_remote",
|
||||
R.string.meshtastic_low_battery_temporary_remote_notifications,
|
||||
Res.string.meshtastic_low_battery_temporary_remote_notifications,
|
||||
NotificationManager.IMPORTANCE_DEFAULT,
|
||||
)
|
||||
|
||||
object Client :
|
||||
NotificationType("client_notifications", R.string.client_notification, NotificationManager.IMPORTANCE_HIGH)
|
||||
NotificationType(
|
||||
"client_notifications",
|
||||
Res.string.client_notification,
|
||||
NotificationManager.IMPORTANCE_HIGH,
|
||||
)
|
||||
|
||||
companion object {
|
||||
// A list of all types for easy initialization.
|
||||
|
|
@ -241,7 +245,7 @@ class MeshServiceNotificationsImpl @Inject constructor(@ApplicationContext priva
|
|||
null
|
||||
}
|
||||
|
||||
cachedMessage = message ?: cachedMessage ?: context.getString(R.string.no_local_stats)
|
||||
cachedMessage = message ?: cachedMessage ?: context.getString(Res.string.no_local_stats)
|
||||
|
||||
val notification =
|
||||
createServiceStateNotification(
|
||||
|
|
@ -277,7 +281,7 @@ class MeshServiceNotificationsImpl @Inject constructor(@ApplicationContext priva
|
|||
|
||||
override fun showClientNotification(clientNotification: MeshProtos.ClientNotification) {
|
||||
val notification =
|
||||
createClientNotification(context.getString(R.string.client_notification), clientNotification.message)
|
||||
createClientNotification(context.getString(Res.string.client_notification), clientNotification.message)
|
||||
notificationManager.notify(clientNotification.toString().hashCode(), notification)
|
||||
}
|
||||
|
||||
|
|
@ -357,7 +361,7 @@ class MeshServiceNotificationsImpl @Inject constructor(@ApplicationContext priva
|
|||
}
|
||||
|
||||
private fun createNewNodeSeenNotification(name: String, message: String?): Notification {
|
||||
val title = context.getString(R.string.new_node_seen).format(name)
|
||||
val title = context.getString(Res.string.new_node_seen).format(name)
|
||||
val builder =
|
||||
commonBuilder(NotificationType.NewNode)
|
||||
.setCategory(Notification.CATEGORY_STATUS)
|
||||
|
|
@ -375,9 +379,9 @@ class MeshServiceNotificationsImpl @Inject constructor(@ApplicationContext priva
|
|||
|
||||
private fun createLowBatteryNotification(node: NodeEntity, isRemote: Boolean): Notification {
|
||||
val type = if (isRemote) NotificationType.LowBatteryRemote else NotificationType.LowBatteryLocal
|
||||
val title = context.getString(R.string.low_battery_title).format(node.shortName)
|
||||
val title = context.getString(Res.string.low_battery_title).format(node.shortName)
|
||||
val message =
|
||||
context.getString(R.string.low_battery_message).format(node.longName, node.deviceMetrics.batteryLevel)
|
||||
context.getString(Res.string.low_battery_message).format(node.longName, node.deviceMetrics.batteryLevel)
|
||||
|
||||
return commonBuilder(type)
|
||||
.setCategory(Notification.CATEGORY_STATUS)
|
||||
|
|
@ -427,7 +431,7 @@ class MeshServiceNotificationsImpl @Inject constructor(@ApplicationContext priva
|
|||
}
|
||||
|
||||
private fun createReplyAction(contactKey: String): NotificationCompat.Action {
|
||||
val replyLabel = context.getString(R.string.reply)
|
||||
val replyLabel = context.getString(Res.string.reply)
|
||||
val remoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build()
|
||||
|
||||
val replyIntent =
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ import org.meshtastic.core.navigation.NodesRoutes
|
|||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MultipleChoiceAlertDialog
|
||||
import org.meshtastic.core.ui.component.SimpleAlertDialog
|
||||
import org.meshtastic.core.ui.icon.Conversations
|
||||
|
|
@ -123,13 +122,14 @@ import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
|||
import org.meshtastic.feature.node.metrics.annotateTraceroute
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
import timber.log.Timber
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
enum class TopLevelDestination(@StringRes val label: Int, val icon: ImageVector, val route: Route) {
|
||||
Conversations(R.string.conversations, MeshtasticIcons.Conversations, ContactsRoutes.ContactsGraph),
|
||||
Nodes(R.string.nodes, MeshtasticIcons.Nodes, NodesRoutes.NodesGraph),
|
||||
Map(R.string.map, MeshtasticIcons.Map, MapRoutes.Map),
|
||||
Settings(R.string.bottom_nav_settings, MeshtasticIcons.Settings, SettingsRoutes.SettingsGraph()),
|
||||
Connections(R.string.connections, Icons.Rounded.Wifi, ConnectionsRoutes.ConnectionsGraph),
|
||||
Conversations(Res.string.conversations, MeshtasticIcons.Conversations, ContactsRoutes.ContactsGraph),
|
||||
Nodes(Res.string.nodes, MeshtasticIcons.Nodes, NodesRoutes.NodesGraph),
|
||||
Map(Res.string.map, MeshtasticIcons.Map, MapRoutes.Map),
|
||||
Settings(Res.string.bottom_nav_settings, MeshtasticIcons.Settings, SettingsRoutes.SettingsGraph()),
|
||||
Connections(Res.string.connections, Icons.Rounded.Wifi, ConnectionsRoutes.ConnectionsGraph),
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
|
@ -195,13 +195,13 @@ fun MainScreen(uIViewModel: UIViewModel = hiltViewModel(), scanModel: BTScanMode
|
|||
var message = notification.message
|
||||
val compromisedKeys =
|
||||
if (notification.hasLowEntropyKey() || notification.hasDuplicatedPublicKey()) {
|
||||
message = stringResource(R.string.compromised_keys)
|
||||
message = stringResource(Res.string.compromised_keys)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
SimpleAlertDialog(
|
||||
title = R.string.client_notification,
|
||||
title = Res.string.client_notification,
|
||||
text = { Text(text = message) },
|
||||
onConfirm = {
|
||||
if (compromisedKeys) {
|
||||
|
|
@ -216,13 +216,13 @@ fun MainScreen(uIViewModel: UIViewModel = hiltViewModel(), scanModel: BTScanMode
|
|||
val traceRouteResponse by uIViewModel.tracerouteResponse.observeAsState()
|
||||
traceRouteResponse?.let { response ->
|
||||
SimpleAlertDialog(
|
||||
title = R.string.traceroute,
|
||||
title = Res.string.traceroute,
|
||||
text = {
|
||||
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
|
||||
Text(text = annotateTraceroute(response))
|
||||
}
|
||||
},
|
||||
dismissText = stringResource(R.string.okay),
|
||||
dismissText = stringResource(Res.string.okay),
|
||||
onDismiss = { uIViewModel.clearTracerouteResponse() },
|
||||
)
|
||||
}
|
||||
|
|
@ -278,9 +278,10 @@ fun MainScreen(uIViewModel: UIViewModel = hiltViewModel(), scanModel: BTScanMode
|
|||
Text(
|
||||
if (isConnectionsRoute) {
|
||||
when (connectionState) {
|
||||
ConnectionState.CONNECTED -> stringResource(R.string.connected)
|
||||
ConnectionState.DEVICE_SLEEP -> stringResource(R.string.device_sleeping)
|
||||
ConnectionState.DISCONNECTED -> stringResource(R.string.disconnected)
|
||||
ConnectionState.CONNECTED -> stringResource(Res.string.connected)
|
||||
ConnectionState.DEVICE_SLEEP ->
|
||||
stringResource(Res.string.device_sleeping)
|
||||
ConnectionState.DISCONNECTED -> stringResource(Res.string.disconnected)
|
||||
}
|
||||
} else {
|
||||
stringResource(destination.label)
|
||||
|
|
@ -423,8 +424,8 @@ private fun VersionChecks(viewModel: UIViewModel) {
|
|||
val isOld = info.minAppVersion > BuildConfig.VERSION_CODE && BuildConfig.DEBUG.not()
|
||||
if (isOld) {
|
||||
viewModel.showAlert(
|
||||
resources.getString(R.string.app_too_old),
|
||||
resources.getString(R.string.must_update),
|
||||
resources.getString(Res.string.app_too_old),
|
||||
resources.getString(Res.string.must_update),
|
||||
dismissable = false,
|
||||
onConfirm = {
|
||||
val service = viewModel.meshService ?: return@showAlert
|
||||
|
|
@ -435,8 +436,8 @@ private fun VersionChecks(viewModel: UIViewModel) {
|
|||
myFirmwareVersion?.let {
|
||||
val curVer = DeviceVersion(it)
|
||||
if (curVer < MeshService.absoluteMinDeviceVersion) {
|
||||
val title = resources.getString(R.string.firmware_too_old)
|
||||
val message = resources.getString(R.string.firmware_old)
|
||||
val title = resources.getString(Res.string.firmware_too_old)
|
||||
val message = resources.getString(Res.string.firmware_old)
|
||||
viewModel.showAlert(
|
||||
title = title,
|
||||
html = message,
|
||||
|
|
@ -447,9 +448,9 @@ private fun VersionChecks(viewModel: UIViewModel) {
|
|||
},
|
||||
)
|
||||
} else if (curVer < MeshService.minDeviceVersion) {
|
||||
val title = resources.getString(R.string.should_update_firmware)
|
||||
val title = resources.getString(Res.string.should_update_firmware)
|
||||
val message =
|
||||
resources.getString(R.string.should_update, latestStableFirmwareRelease.asString)
|
||||
resources.getString(Res.string.should_update, latestStableFirmwareRelease.asString)
|
||||
viewModel.showAlert(title = title, message = message, dismissable = false, onConfirm = {})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ import kotlinx.coroutines.delay
|
|||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
|
|
@ -74,6 +73,7 @@ import org.meshtastic.feature.settings.navigation.getNavRouteFrom
|
|||
import org.meshtastic.feature.settings.radio.RadioConfigViewModel
|
||||
import org.meshtastic.feature.settings.radio.component.PacketResponseStateDialog
|
||||
import org.meshtastic.proto.ConfigProtos
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
fun String?.isIPAddress(): Boolean = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
@Suppress("DEPRECATION")
|
||||
|
|
@ -153,18 +153,18 @@ fun ConnectionsScreen(
|
|||
LaunchedEffect(connectionState, regionUnset) {
|
||||
when (connectionState) {
|
||||
ConnectionState.CONNECTED -> {
|
||||
if (regionUnset) R.string.must_set_region else R.string.connected
|
||||
if (regionUnset) Res.string.must_set_region else Res.string.connected
|
||||
}
|
||||
|
||||
ConnectionState.DISCONNECTED -> R.string.not_connected
|
||||
ConnectionState.DEVICE_SLEEP -> R.string.connected_sleeping
|
||||
ConnectionState.DISCONNECTED -> Res.string.not_connected
|
||||
ConnectionState.DEVICE_SLEEP -> Res.string.connected_sleeping
|
||||
}.let { scanModel.setErrorText(context.getString(it)) }
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
MainAppBar(
|
||||
title = stringResource(R.string.connections),
|
||||
title = stringResource(Res.string.connections),
|
||||
ourNode = ourNode,
|
||||
showNodeChip = ourNode != null && connectionState.isConnected(),
|
||||
canNavigateUp = false,
|
||||
|
|
@ -190,7 +190,7 @@ fun ConnectionsScreen(
|
|||
) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
ourNode?.let { node ->
|
||||
TitledCard(title = stringResource(R.string.connected_device)) {
|
||||
TitledCard(title = stringResource(Res.string.connected_device)) {
|
||||
CurrentlyConnectedInfo(
|
||||
node = node,
|
||||
onNavigateToNodeDetails = onNavigateToNodeDetails,
|
||||
|
|
@ -203,7 +203,7 @@ fun ConnectionsScreen(
|
|||
TitledCard(title = null) {
|
||||
ListItem(
|
||||
leadingIcon = Icons.Rounded.Language,
|
||||
text = stringResource(R.string.set_your_region),
|
||||
text = stringResource(Res.string.set_your_region),
|
||||
) {
|
||||
isWaiting = true
|
||||
radioConfigViewModel.setResponseStateLoading(ConfigRoute.LORA)
|
||||
|
|
@ -272,7 +272,7 @@ fun ConnectionsScreen(
|
|||
bondedBleDevices.none { it is DeviceListEntry.Ble && it.bonded }
|
||||
if (showWarningNotPaired) {
|
||||
Text(
|
||||
text = stringResource(R.string.warning_not_paired),
|
||||
text = stringResource(Res.string.warning_not_paired),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
|||
import com.google.accompanist.permissions.MultiplePermissionsState
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* Composable that displays a list of Bluetooth Low Energy (BLE) devices and allows scanning. It handles Bluetooth
|
||||
|
|
@ -118,12 +118,12 @@ fun BLEDevices(
|
|||
val context = LocalContext.current
|
||||
EmptyStateContent(
|
||||
imageVector = Icons.Rounded.BluetoothDisabled,
|
||||
text = stringResource(R.string.bluetooth_disabled),
|
||||
text = stringResource(Res.string.bluetooth_disabled),
|
||||
actionButton = {
|
||||
val intent = Intent(ACTION_BLUETOOTH_SETTINGS)
|
||||
if (intent.resolveActivity(context.packageManager) != null) {
|
||||
Button(onClick = { settingsLauncher.launch(intent) }) {
|
||||
Text(text = stringResource(R.string.open_settings))
|
||||
Text(text = stringResource(Res.string.open_settings))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -142,9 +142,9 @@ fun BLEDevices(
|
|||
Row(modifier = Modifier.alpha(if (isScanning) 0f else 1f)) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Search,
|
||||
contentDescription = stringResource(R.string.scan),
|
||||
contentDescription = stringResource(Res.string.scan),
|
||||
)
|
||||
Text(stringResource(R.string.scan))
|
||||
Text(stringResource(Res.string.scan))
|
||||
}
|
||||
|
||||
if (isScanning) {
|
||||
|
|
@ -159,22 +159,22 @@ fun BLEDevices(
|
|||
imageVector = Icons.Rounded.BluetoothDisabled,
|
||||
text =
|
||||
if (isScanning) {
|
||||
stringResource(R.string.scanning_bluetooth)
|
||||
stringResource(Res.string.scanning_bluetooth)
|
||||
} else {
|
||||
stringResource(R.string.no_ble_devices)
|
||||
stringResource(Res.string.no_ble_devices)
|
||||
},
|
||||
actionButton = scanButton,
|
||||
)
|
||||
} else {
|
||||
bondedDevices.Section(
|
||||
title = stringResource(R.string.bluetooth_paired_devices),
|
||||
title = stringResource(Res.string.bluetooth_paired_devices),
|
||||
connectionState = connectionState,
|
||||
selectedDevice = selectedDevice,
|
||||
onSelect = scanModel::onSelected,
|
||||
)
|
||||
|
||||
availableDevices.Section(
|
||||
title = stringResource(R.string.bluetooth_available_devices),
|
||||
title = stringResource(Res.string.bluetooth_available_devices),
|
||||
connectionState = connectionState,
|
||||
selectedDevice = selectedDevice,
|
||||
onSelect = scanModel::onSelected,
|
||||
|
|
@ -189,13 +189,13 @@ fun BLEDevices(
|
|||
EmptyStateContent(
|
||||
text =
|
||||
if (permissionsState.shouldShowRationale) {
|
||||
stringResource(R.string.permission_missing)
|
||||
stringResource(Res.string.permission_missing)
|
||||
} else {
|
||||
stringResource(R.string.permission_missing_31)
|
||||
stringResource(Res.string.permission_missing_31)
|
||||
},
|
||||
actionButton = {
|
||||
Button(onClick = { checkPermissionsAndScan(permissionsState, scanModel, bluetoothEnabled) }) {
|
||||
Text(text = stringResource(R.string.grant_permissions))
|
||||
Text(text = stringResource(Res.string.grant_permissions))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.geeksville.mesh.ui.connections.DeviceType
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LambdaParameterEventTrailing")
|
||||
@Composable
|
||||
|
|
@ -59,9 +59,9 @@ fun ConnectionsSegmentedBar(
|
|||
}
|
||||
|
||||
private enum class Item(val imageVector: ImageVector, @StringRes val textRes: Int, val deviceType: DeviceType) {
|
||||
BLUETOOTH(imageVector = Icons.Rounded.Bluetooth, textRes = R.string.bluetooth, deviceType = DeviceType.BLE),
|
||||
NETWORK(imageVector = Icons.Rounded.Wifi, textRes = R.string.network, deviceType = DeviceType.TCP),
|
||||
SERIAL(imageVector = Icons.Rounded.Usb, textRes = R.string.serial, deviceType = DeviceType.USB),
|
||||
BLUETOOTH(imageVector = Icons.Rounded.Bluetooth, textRes = Res.string.bluetooth, deviceType = DeviceType.BLE),
|
||||
NETWORK(imageVector = Icons.Rounded.Wifi, textRes = Res.string.network, deviceType = DeviceType.TCP),
|
||||
SERIAL(imageVector = Icons.Rounded.Usb, textRes = Res.string.serial, deviceType = DeviceType.USB),
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
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.MaterialBatteryInfo
|
||||
import org.meshtastic.core.ui.component.NodeChip
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
|
|
@ -45,6 +44,7 @@ import org.meshtastic.core.ui.theme.StatusColors.StatusRed
|
|||
import org.meshtastic.proto.MeshProtos
|
||||
import org.meshtastic.proto.PaxcountProtos
|
||||
import org.meshtastic.proto.TelemetryProtos
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/** Converts Bluetooth RSSI to a 0-4 bar signal strength level. */
|
||||
@Composable
|
||||
|
|
@ -75,7 +75,7 @@ fun CurrentlyConnectedInfo(
|
|||
|
||||
node.metadata?.firmwareVersion?.let { firmwareVersion ->
|
||||
Text(
|
||||
text = stringResource(R.string.firmware_version, firmwareVersion),
|
||||
text = stringResource(Res.string.firmware_version, firmwareVersion),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -94,7 +94,7 @@ fun CurrentlyConnectedInfo(
|
|||
),
|
||||
onClick = onClickDisconnect,
|
||||
) {
|
||||
Text(stringResource(R.string.disconnect))
|
||||
Text(stringResource(Res.string.disconnect))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.geeksville.mesh.model.DeviceListEntry
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
|
|
@ -55,10 +55,10 @@ fun DeviceListItem(connected: Boolean, device: DeviceListEntry, onSelect: () ->
|
|||
|
||||
val contentDescription =
|
||||
when (device) {
|
||||
is DeviceListEntry.Ble -> stringResource(R.string.bluetooth)
|
||||
is DeviceListEntry.Usb -> stringResource(R.string.serial)
|
||||
is DeviceListEntry.Tcp -> stringResource(R.string.network)
|
||||
is DeviceListEntry.Mock -> stringResource(R.string.add)
|
||||
is DeviceListEntry.Ble -> stringResource(Res.string.bluetooth)
|
||||
is DeviceListEntry.Usb -> stringResource(Res.string.serial)
|
||||
is DeviceListEntry.Tcp -> stringResource(Res.string.network)
|
||||
is DeviceListEntry.Mock -> stringResource(Res.string.add)
|
||||
}
|
||||
|
||||
val useSelectable = modifier == Modifier
|
||||
|
|
|
|||
|
|
@ -57,9 +57,9 @@ import com.geeksville.mesh.repository.network.NetworkRepository
|
|||
import com.geeksville.mesh.ui.connections.isIPAddress
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("MagicNumber", "LongMethod")
|
||||
|
|
@ -102,8 +102,11 @@ fun NetworkDevices(
|
|||
Column(verticalArrangement = Arrangement.spacedBy(16.dp), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
val addButton: @Composable () -> Unit = {
|
||||
Button(onClick = { showSearchDialog = true }) {
|
||||
Icon(imageVector = Icons.Rounded.Add, contentDescription = stringResource(R.string.add_network_device))
|
||||
Text(stringResource(R.string.add_network_device))
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Add,
|
||||
contentDescription = stringResource(Res.string.add_network_device),
|
||||
)
|
||||
Text(stringResource(Res.string.add_network_device))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,14 +114,14 @@ fun NetworkDevices(
|
|||
discoveredNetworkDevices.isEmpty() && recentNetworkDevices.isEmpty() -> {
|
||||
EmptyStateContent(
|
||||
imageVector = Icons.Rounded.Wifi,
|
||||
text = stringResource(R.string.no_network_devices),
|
||||
text = stringResource(Res.string.no_network_devices),
|
||||
actionButton = addButton,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (recentNetworkDevices.isNotEmpty()) {
|
||||
TitledCard(title = stringResource(R.string.recent_network_devices)) {
|
||||
TitledCard(title = stringResource(Res.string.recent_network_devices)) {
|
||||
recentNetworkDevices.forEach { device ->
|
||||
DeviceListItem(
|
||||
connected =
|
||||
|
|
@ -140,7 +143,7 @@ fun NetworkDevices(
|
|||
}
|
||||
|
||||
if (discoveredNetworkDevices.isNotEmpty()) {
|
||||
TitledCard(title = stringResource(R.string.discovered_network_devices)) {
|
||||
TitledCard(title = stringResource(Res.string.discovered_network_devices)) {
|
||||
discoveredNetworkDevices.forEach { device ->
|
||||
DeviceListItem(
|
||||
connected =
|
||||
|
|
@ -179,7 +182,7 @@ private fun AddDeviceDialog(
|
|||
state = ipState,
|
||||
labelPosition = TextFieldLabelPosition.Above(),
|
||||
lineLimits = TextFieldLineLimits.SingleLine,
|
||||
label = { Text(stringResource(R.string.ip_address)) },
|
||||
label = { Text(stringResource(Res.string.ip_address)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal, imeAction = ImeAction.Next),
|
||||
modifier = Modifier.weight(.7f),
|
||||
)
|
||||
|
|
@ -189,7 +192,7 @@ private fun AddDeviceDialog(
|
|||
labelPosition = TextFieldLabelPosition.Above(),
|
||||
placeholder = { Text(NetworkRepository.SERVICE_PORT.toString()) },
|
||||
lineLimits = TextFieldLineLimits.SingleLine,
|
||||
label = { Text(stringResource(R.string.ip_port)) },
|
||||
label = { Text(stringResource(Res.string.ip_port)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal, imeAction = ImeAction.Done),
|
||||
modifier = Modifier.weight(.3f),
|
||||
)
|
||||
|
|
@ -197,7 +200,7 @@ private fun AddDeviceDialog(
|
|||
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Button(modifier = Modifier.weight(1f), onClick = { onHideDialog() }) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
Text(stringResource(Res.string.cancel))
|
||||
}
|
||||
|
||||
Button(
|
||||
|
|
@ -226,7 +229,7 @@ private fun AddDeviceDialog(
|
|||
}
|
||||
},
|
||||
) {
|
||||
Text(stringResource(R.string.add_network_device))
|
||||
Text(stringResource(Res.string.add_network_device))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -241,8 +244,8 @@ private fun ConfirmDeleteDialog(
|
|||
) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onHideDialog,
|
||||
title = { Text(stringResource(R.string.delete)) },
|
||||
text = { Text(stringResource(R.string.confirm_delete_node)) },
|
||||
title = { Text(stringResource(Res.string.delete)) },
|
||||
text = { Text(stringResource(Res.string.confirm_delete_node)) },
|
||||
confirmButton = {
|
||||
Button(
|
||||
onClick = {
|
||||
|
|
@ -250,10 +253,10 @@ private fun ConfirmDeleteDialog(
|
|||
onHideDialog()
|
||||
},
|
||||
) {
|
||||
Text(stringResource(R.string.delete))
|
||||
Text(stringResource(Res.string.delete))
|
||||
}
|
||||
},
|
||||
dismissButton = { Button(onClick = { onHideDialog() }) { Text(stringResource(R.string.cancel)) } },
|
||||
dismissButton = { Button(onClick = { onHideDialog() }) { Text(stringResource(Res.string.cancel)) } },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
|||
import com.geeksville.mesh.model.BTScanModel
|
||||
import com.geeksville.mesh.model.DeviceListEntry
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun UsbDevices(
|
||||
|
|
@ -54,7 +54,7 @@ private fun UsbDevices(
|
|||
) {
|
||||
when {
|
||||
usbDevices.isEmpty() ->
|
||||
EmptyStateContent(imageVector = Icons.Rounded.UsbOff, text = stringResource(R.string.no_usb_devices))
|
||||
EmptyStateContent(imageVector = Icons.Rounded.UsbOff, text = stringResource(Res.string.no_usb_devices))
|
||||
|
||||
else ->
|
||||
TitledCard(title = null) {
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.geeksville.mesh.model.Contact
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.SecurityIcon
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.proto.AppOnlyProtos
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
|
|
@ -197,10 +197,10 @@ private fun ContactItemPreview() {
|
|||
val sampleContact =
|
||||
Contact(
|
||||
contactKey = "0^all",
|
||||
shortName = stringResource(R.string.some_username),
|
||||
longName = stringResource(R.string.unknown_username),
|
||||
shortName = stringResource(Res.string.some_username),
|
||||
longName = stringResource(Res.string.unknown_username),
|
||||
lastMessageTime = "Mon",
|
||||
lastMessageText = stringResource(R.string.sample_message),
|
||||
lastMessageText = stringResource(Res.string.sample_message),
|
||||
unreadCount = 2,
|
||||
messageCount = 10,
|
||||
isMuted = true,
|
||||
|
|
|
|||
|
|
@ -64,10 +64,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import com.geeksville.mesh.model.Contact
|
||||
import org.meshtastic.core.database.entity.ContactSettings
|
||||
import org.meshtastic.core.model.util.formatMuteRemainingTime
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.proto.AppOnlyProtos
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Suppress("LongMethod")
|
||||
|
|
@ -143,7 +143,7 @@ fun ContactsScreen(
|
|||
Scaffold(
|
||||
topBar = {
|
||||
MainAppBar(
|
||||
title = stringResource(R.string.conversations),
|
||||
title = stringResource(Res.string.conversations),
|
||||
ourNode = ourNode,
|
||||
showNodeChip = ourNode != null && connectionState.isConnected(),
|
||||
canNavigateUp = false,
|
||||
|
|
@ -232,10 +232,10 @@ fun MuteNotificationsDialog(
|
|||
// Options for mute duration
|
||||
val muteOptions = remember {
|
||||
listOf(
|
||||
R.string.unmute to 0L,
|
||||
R.string.mute_8_hours to TimeUnit.HOURS.toMillis(8),
|
||||
R.string.mute_1_week to TimeUnit.DAYS.toMillis(7),
|
||||
R.string.mute_always to Long.MAX_VALUE,
|
||||
Res.string.unmute to 0L,
|
||||
Res.string.mute_8_hours to TimeUnit.HOURS.toMillis(8),
|
||||
Res.string.mute_1_week to TimeUnit.DAYS.toMillis(7),
|
||||
Res.string.mute_always to Long.MAX_VALUE,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ fun MuteNotificationsDialog(
|
|||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss, // Dismiss the dialog when clicked outside
|
||||
title = { Text(text = stringResource(R.string.mute_notifications)) },
|
||||
title = { Text(text = stringResource(Res.string.mute_notifications)) },
|
||||
text = {
|
||||
Column {
|
||||
// Show current mute status
|
||||
|
|
@ -258,19 +258,20 @@ fun MuteNotificationsDialog(
|
|||
if (remaining > 0) {
|
||||
val (days, hours) = formatMuteRemainingTime(remaining)
|
||||
if (days >= 1) {
|
||||
stringResource(R.string.mute_status_muted_for_days, days, hours)
|
||||
stringResource(Res.string.mute_status_muted_for_days, days, hours)
|
||||
} else {
|
||||
stringResource(R.string.mute_status_muted_for_hours, hours)
|
||||
stringResource(Res.string.mute_status_muted_for_hours, hours)
|
||||
}
|
||||
} else {
|
||||
stringResource(R.string.mute_status_unmuted)
|
||||
stringResource(Res.string.mute_status_unmuted)
|
||||
}
|
||||
}
|
||||
settings.muteUntil == Long.MAX_VALUE -> stringResource(R.string.mute_status_always)
|
||||
else -> stringResource(R.string.mute_status_unmuted)
|
||||
settings.muteUntil == Long.MAX_VALUE ->
|
||||
stringResource(Res.string.mute_status_always)
|
||||
else -> stringResource(Res.string.mute_status_unmuted)
|
||||
}
|
||||
Text(
|
||||
text = stringResource(R.string.currently) + " " + statusText,
|
||||
text = stringResource(Res.string.currently) + " " + statusText,
|
||||
modifier = Modifier.padding(bottom = 8.dp),
|
||||
)
|
||||
}
|
||||
|
|
@ -300,14 +301,14 @@ fun MuteNotificationsDialog(
|
|||
onDismiss() // Dismiss the dialog after confirming
|
||||
},
|
||||
) {
|
||||
Text(stringResource(R.string.okay))
|
||||
Text(stringResource(Res.string.okay))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
Button(
|
||||
onClick = onDismiss, // Dismiss the dialog on cancel
|
||||
) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
Text(stringResource(Res.string.cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -324,7 +325,7 @@ fun DeleteConfirmationDialog(
|
|||
if (showDialog) {
|
||||
val deleteMessage =
|
||||
pluralStringResource(
|
||||
id = R.plurals.delete_messages,
|
||||
id = Res.plurals.delete_messages,
|
||||
count = selectedCount,
|
||||
formatArgs = arrayOf(selectedCount), // Pass the count as a format argument
|
||||
)
|
||||
|
|
@ -342,10 +343,10 @@ fun DeleteConfirmationDialog(
|
|||
onDismiss() // Dismiss the dialog after confirming
|
||||
},
|
||||
) {
|
||||
Text(stringResource(R.string.delete))
|
||||
Text(stringResource(Res.string.delete))
|
||||
}
|
||||
},
|
||||
dismissButton = { Button(onClick = onDismiss) { Text(stringResource(R.string.cancel)) } },
|
||||
dismissButton = { Button(onClick = onDismiss) { Text(stringResource(Res.string.cancel)) } },
|
||||
properties =
|
||||
DialogProperties(
|
||||
dismissOnClickOutside = true, // Allow dismissing by clicking outside
|
||||
|
|
@ -369,7 +370,7 @@ fun SelectionToolbar(
|
|||
title = { Text(text = "$selectedCount") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onCloseSelection) {
|
||||
Icon(Icons.Default.Close, contentDescription = stringResource(R.string.close_selection))
|
||||
Icon(Icons.Default.Close, contentDescription = stringResource(Res.string.close_selection))
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
|
|
@ -390,10 +391,10 @@ fun SelectionToolbar(
|
|||
)
|
||||
}
|
||||
IconButton(onClick = onDeleteSelected) {
|
||||
Icon(Icons.Default.Delete, contentDescription = stringResource(R.string.delete_selection))
|
||||
Icon(Icons.Default.Delete, contentDescription = stringResource(Res.string.delete_selection))
|
||||
}
|
||||
IconButton(onClick = onSelectAll) {
|
||||
Icon(Icons.Default.SelectAll, contentDescription = stringResource(R.string.select_all))
|
||||
Icon(Icons.Default.SelectAll, contentDescription = stringResource(Res.string.select_all))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ import org.meshtastic.core.model.DataPacket
|
|||
import org.meshtastic.core.model.util.getChannel
|
||||
import org.meshtastic.core.model.util.getShortDate
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
|
||||
import org.meshtastic.proto.channelSet
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.map
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@HiltViewModel
|
||||
class ContactsViewModel
|
||||
|
|
@ -87,7 +87,7 @@ constructor(
|
|||
val shortName = user.shortName
|
||||
val longName =
|
||||
if (toBroadcast) {
|
||||
channelSet.getChannel(data.channel)?.name ?: context.getString(R.string.channel_name)
|
||||
channelSet.getChannel(data.channel)?.name ?: context.getString(Res.string.channel_name)
|
||||
} else {
|
||||
user.longName
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ import org.meshtastic.core.model.util.qrCode
|
|||
import org.meshtastic.core.model.util.toChannelSet
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.AdaptiveTwoPane
|
||||
import org.meshtastic.core.ui.component.ChannelSelection
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
|
|
@ -117,6 +116,7 @@ import org.meshtastic.proto.ConfigProtos
|
|||
import org.meshtastic.proto.channelSet
|
||||
import org.meshtastic.proto.copy
|
||||
import timber.log.Timber
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* Composable screen for managing and sharing Meshtastic channels. Allows users to view, edit, and share channel
|
||||
|
|
@ -185,7 +185,7 @@ fun ChannelScreen(
|
|||
rememberLauncherForActivityResult(ScanContract()) { result ->
|
||||
if (result.contents != null) {
|
||||
viewModel.requestChannelUrl(result.contents.toUri()) {
|
||||
Toast.makeText(context, R.string.channel_invalid, Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, Res.string.channel_invalid, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -223,7 +223,7 @@ fun ChannelScreen(
|
|||
channelSet = channels // Throw away user edits
|
||||
|
||||
// Tell the user to try again
|
||||
Toast.makeText(context, R.string.cant_change_no_radio, Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, Res.string.cant_change_no_radio, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,8 +241,8 @@ fun ChannelScreen(
|
|||
channelSet = channels // throw away any edits
|
||||
showResetDialog = false
|
||||
},
|
||||
title = { Text(text = stringResource(R.string.reset_to_defaults)) },
|
||||
text = { Text(text = stringResource(R.string.are_you_sure_change_default)) },
|
||||
title = { Text(text = stringResource(Res.string.reset_to_defaults)) },
|
||||
text = { Text(text = stringResource(Res.string.are_you_sure_change_default)) },
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
|
|
@ -257,7 +257,7 @@ fun ChannelScreen(
|
|||
showResetDialog = false
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.apply))
|
||||
Text(text = stringResource(Res.string.apply))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
|
|
@ -267,7 +267,7 @@ fun ChannelScreen(
|
|||
showResetDialog = false
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.cancel))
|
||||
Text(text = stringResource(Res.string.cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -312,7 +312,7 @@ fun ChannelScreen(
|
|||
onTrackShare = viewModel::trackShare,
|
||||
onConfirm = {
|
||||
viewModel.requestChannelUrl(it) {
|
||||
Toast.makeText(context, R.string.channel_invalid, Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, Res.string.channel_invalid, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -320,13 +320,13 @@ fun ChannelScreen(
|
|||
item {
|
||||
SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth().padding(8.dp)) {
|
||||
SegmentedButton(
|
||||
label = { Text(text = stringResource(R.string.replace)) },
|
||||
label = { Text(text = stringResource(Res.string.replace)) },
|
||||
onClick = { shouldAddChannelsState = false },
|
||||
selected = !shouldAddChannelsState,
|
||||
shape = SegmentedButtonDefaults.itemShape(0, 2),
|
||||
)
|
||||
SegmentedButton(
|
||||
label = { Text(text = stringResource(R.string.add)) },
|
||||
label = { Text(text = stringResource(Res.string.add)) },
|
||||
onClick = { shouldAddChannelsState = true },
|
||||
selected = shouldAddChannelsState,
|
||||
shape = SegmentedButtonDefaults.itemShape(1, 2),
|
||||
|
|
@ -345,12 +345,12 @@ fun ChannelScreen(
|
|||
item {
|
||||
PreferenceFooter(
|
||||
enabled = enabled,
|
||||
negativeText = R.string.reset,
|
||||
negativeText = Res.string.reset,
|
||||
onNegativeClicked = {
|
||||
focusManager.clearFocus()
|
||||
showResetDialog = true
|
||||
},
|
||||
positiveText = R.string.scan,
|
||||
positiveText = Res.string.scan,
|
||||
onPositiveClicked = {
|
||||
focusManager.clearFocus()
|
||||
if (cameraPermissionState.status.isGranted) {
|
||||
|
|
@ -400,11 +400,11 @@ private fun EditChannelUrl(
|
|||
},
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
enabled = enabled,
|
||||
label = { Text(stringResource(R.string.url)) },
|
||||
label = { Text(stringResource(Res.string.url)) },
|
||||
isError = isError,
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
trailingIcon = {
|
||||
val label = stringResource(R.string.url)
|
||||
val label = stringResource(Res.string.url)
|
||||
val isUrlEqual = valueState == channelUrl
|
||||
IconButton(
|
||||
onClick = {
|
||||
|
|
@ -440,9 +440,9 @@ private fun EditChannelUrl(
|
|||
},
|
||||
contentDescription =
|
||||
when {
|
||||
isError -> stringResource(R.string.copy)
|
||||
!isUrlEqual -> stringResource(R.string.send)
|
||||
else -> stringResource(R.string.copy)
|
||||
isError -> stringResource(Res.string.copy)
|
||||
!isUrlEqual -> stringResource(Res.string.send)
|
||||
else -> stringResource(Res.string.copy)
|
||||
},
|
||||
tint =
|
||||
if (isError) {
|
||||
|
|
@ -470,7 +470,7 @@ private fun QrCodeImage(
|
|||
painter =
|
||||
channelSet.qrCode(shouldAddChannel)?.let { BitmapPainter(it.asImageBitmap()) }
|
||||
?: painterResource(id = org.meshtastic.core.ui.R.drawable.qrcode),
|
||||
contentDescription = stringResource(R.string.qr_code),
|
||||
contentDescription = stringResource(Res.string.qr_code),
|
||||
modifier = modifier,
|
||||
contentScale = ContentScale.Inside,
|
||||
alpha = if (enabled) 1.0f else 0.7f,
|
||||
|
|
@ -518,7 +518,7 @@ private fun ChannelListView(
|
|||
enabled = enabled,
|
||||
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.onSurface),
|
||||
) {
|
||||
Text(text = stringResource(R.string.edit))
|
||||
Text(text = stringResource(Res.string.edit))
|
||||
}
|
||||
},
|
||||
second = {
|
||||
|
|
@ -543,13 +543,13 @@ private fun ModemPresetInfo(modemPresetName: String, onClick: () -> Unit) {
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f).padding(16.dp)) {
|
||||
Text(text = stringResource(R.string.modem_preset), fontSize = 16.sp)
|
||||
Text(text = stringResource(Res.string.modem_preset), fontSize = 16.sp)
|
||||
Text(text = modemPresetName, fontSize = 14.sp)
|
||||
}
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = stringResource(R.string.navigate_into_label),
|
||||
contentDescription = stringResource(Res.string.navigate_into_label),
|
||||
modifier = Modifier.padding(end = 16.dp),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import com.geeksville.mesh.model.Contact
|
||||
import com.geeksville.mesh.ui.contact.ContactItem
|
||||
import com.geeksville.mesh.ui.contact.ContactsViewModel
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun ShareScreen(viewModel: ContactsViewModel = hiltViewModel(), onConfirm: (String) -> Unit, onNavigateUp: () -> Unit) {
|
||||
|
|
@ -61,7 +61,7 @@ fun ShareScreen(contacts: List<Contact>, onConfirm: (String) -> Unit, onNavigate
|
|||
Scaffold(
|
||||
topBar = {
|
||||
MainAppBar(
|
||||
title = stringResource(R.string.share_to),
|
||||
title = stringResource(Res.string.share_to),
|
||||
ourNode = null,
|
||||
showNodeChip = false,
|
||||
canNavigateUp = true,
|
||||
|
|
@ -92,7 +92,10 @@ fun ShareScreen(contacts: List<Contact>, onConfirm: (String) -> Unit, onNavigate
|
|||
modifier = Modifier.fillMaxWidth().padding(24.dp),
|
||||
enabled = selectedContact.isNotEmpty(),
|
||||
) {
|
||||
Icon(imageVector = Icons.AutoMirrored.Default.Send, contentDescription = stringResource(R.string.share))
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.Send,
|
||||
contentDescription = stringResource(Res.string.share),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -107,10 +110,10 @@ private fun ShareScreenPreview() {
|
|||
listOf(
|
||||
Contact(
|
||||
contactKey = "0^all",
|
||||
shortName = stringResource(R.string.some_username),
|
||||
longName = stringResource(R.string.unknown_username),
|
||||
shortName = stringResource(Res.string.some_username),
|
||||
longName = stringResource(Res.string.unknown_username),
|
||||
lastMessageTime = "3 minutes ago",
|
||||
lastMessageText = stringResource(R.string.sample_message),
|
||||
lastMessageText = stringResource(Res.string.sample_message),
|
||||
unreadCount = 2,
|
||||
messageCount = 10,
|
||||
isMuted = true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue