mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2025-12-24 00:07:48 -05:00
Make :core:strings a Compose Multiplatform library (#3617)
This commit is contained in:
@@ -87,42 +87,42 @@ android {
|
||||
androidResources.localeFilters.addAll(
|
||||
listOf(
|
||||
"en",
|
||||
"ar-rSA",
|
||||
"b+sr+Latn",
|
||||
"bg-rBG",
|
||||
"ca-rES",
|
||||
"cs-rCZ",
|
||||
"de-rDE",
|
||||
"el-rGR",
|
||||
"es-rES",
|
||||
"et-rEE",
|
||||
"fi-rFI",
|
||||
"fr-rFR",
|
||||
"ga-rIE",
|
||||
"gl-rES",
|
||||
"hr-rHR",
|
||||
"ht-rHT",
|
||||
"hu-rHU",
|
||||
"is-rIS",
|
||||
"it-rIT",
|
||||
"iw-rIL",
|
||||
"ja-rJP",
|
||||
"ko-rKR",
|
||||
"lt-rLT",
|
||||
"nl-rNL",
|
||||
"no-rNO",
|
||||
"pl-rPL",
|
||||
"ar",
|
||||
"bg",
|
||||
"ca",
|
||||
"cs",
|
||||
"de",
|
||||
"el",
|
||||
"es",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"ga",
|
||||
"gl",
|
||||
"hr",
|
||||
"ht",
|
||||
"hu",
|
||||
"is",
|
||||
"it",
|
||||
"iw",
|
||||
"ja",
|
||||
"ko",
|
||||
"lt",
|
||||
"nl",
|
||||
"no",
|
||||
"pl",
|
||||
"pt",
|
||||
"pt-rBR",
|
||||
"pt-rPT",
|
||||
"ro-rRO",
|
||||
"ru-rRU",
|
||||
"sk-rSK",
|
||||
"sl-rSI",
|
||||
"sq-rAL",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk",
|
||||
"sl",
|
||||
"sq",
|
||||
"sr",
|
||||
"srp",
|
||||
"sv-rSE",
|
||||
"tr-rTR",
|
||||
"uk-rUA",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"zh-rCN",
|
||||
"zh-rTW",
|
||||
),
|
||||
|
||||
@@ -46,13 +46,15 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.core.datastore.UiPreferencesDataSource
|
||||
import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.channel_invalid
|
||||
import org.meshtastic.core.strings.contact_invalid
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.ui.theme.MODE_DYNAMIC
|
||||
import org.meshtastic.core.ui.util.showToast
|
||||
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() {
|
||||
|
||||
@@ -47,14 +47,18 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.getString
|
||||
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.Res
|
||||
import org.meshtastic.core.strings.meshtastic
|
||||
import org.meshtastic.core.strings.pairing_completed
|
||||
import org.meshtastic.core.strings.pairing_failed_try_again
|
||||
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,8 +139,7 @@ constructor(
|
||||
val idBytes = txtRecords["id"]
|
||||
|
||||
val shortName =
|
||||
shortNameBytes?.let { String(it, Charsets.UTF_8) }
|
||||
?: context.getString(Res.string.meshtastic)
|
||||
shortNameBytes?.let { String(it, Charsets.UTF_8) } ?: 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 }) {
|
||||
@@ -283,10 +286,10 @@ constructor(
|
||||
if (state != BluetoothDevice.BOND_BONDING) {
|
||||
Timber.d("Bonding completed, state=$state")
|
||||
if (state == BluetoothDevice.BOND_BONDED) {
|
||||
setErrorText(context.getString(Res.string.pairing_completed))
|
||||
setErrorText(getString(Res.string.pairing_completed))
|
||||
changeDeviceAddress("x${device.address}")
|
||||
} else {
|
||||
setErrorText(context.getString(Res.string.pairing_failed_try_again))
|
||||
setErrorText(getString(Res.string.pairing_failed_try_again))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import org.meshtastic.core.analytics.platform.PlatformAnalytics
|
||||
import org.meshtastic.core.data.repository.FirmwareReleaseRepository
|
||||
import org.meshtastic.core.data.repository.MeshLogRepository
|
||||
@@ -51,6 +52,8 @@ 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.Res
|
||||
import org.meshtastic.core.strings.client_notification
|
||||
import org.meshtastic.core.ui.component.toSharedContact
|
||||
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
@@ -58,7 +61,6 @@ 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 +180,7 @@ constructor(
|
||||
.filterNotNull()
|
||||
.onEach {
|
||||
showAlert(
|
||||
title = app.getString(Res.string.client_notification),
|
||||
title = getString(Res.string.client_notification),
|
||||
message = it,
|
||||
onConfirm = { serviceRepository.clearErrorMessage() },
|
||||
dismissable = false,
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package com.geeksville.mesh.navigation
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CellTower
|
||||
import androidx.compose.material.icons.filled.LightMode
|
||||
@@ -39,11 +38,22 @@ import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.navigation
|
||||
import androidx.navigation.navDeepLink
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.meshtastic.core.navigation.ContactsRoutes
|
||||
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.core.strings.Res
|
||||
import org.meshtastic.core.strings.device
|
||||
import org.meshtastic.core.strings.environment
|
||||
import org.meshtastic.core.strings.host
|
||||
import org.meshtastic.core.strings.pax
|
||||
import org.meshtastic.core.strings.position_log
|
||||
import org.meshtastic.core.strings.power
|
||||
import org.meshtastic.core.strings.signal
|
||||
import org.meshtastic.core.strings.traceroute
|
||||
import org.meshtastic.feature.map.node.NodeMapScreen
|
||||
import org.meshtastic.feature.map.node.NodeMapViewModel
|
||||
import org.meshtastic.feature.node.detail.NodeDetailScreen
|
||||
@@ -57,7 +67,6 @@ 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) {
|
||||
@@ -198,7 +207,7 @@ private inline fun <reified R : Route> NavGraphBuilder.addNodeDetailScreenCompos
|
||||
}
|
||||
|
||||
enum class NodeDetailRoute(
|
||||
@StringRes val title: Int,
|
||||
val title: StringResource,
|
||||
val route: Route,
|
||||
val icon: ImageVector?,
|
||||
val screenComposable: @Composable (metricsViewModel: MetricsViewModel, onNavigateUp: () -> Unit) -> Unit,
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.geeksville.mesh.util.ignoreException
|
||||
import com.geeksville.mesh.util.toRemoteExceptions
|
||||
import com.google.protobuf.ByteString
|
||||
import com.google.protobuf.InvalidProtocolBufferException
|
||||
import com.meshtastic.core.strings.getString
|
||||
import dagger.Lazy
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -86,6 +87,14 @@ 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.Res
|
||||
import org.meshtastic.core.strings.connected_count
|
||||
import org.meshtastic.core.strings.critical_alert
|
||||
import org.meshtastic.core.strings.device_sleeping
|
||||
import org.meshtastic.core.strings.disconnected
|
||||
import org.meshtastic.core.strings.error_duty_cycle
|
||||
import org.meshtastic.core.strings.unknown_username
|
||||
import org.meshtastic.core.strings.waypoint_received
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.proto.AppOnlyProtos
|
||||
import org.meshtastic.proto.ChannelProtos
|
||||
@@ -113,7 +122,6 @@ 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.
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.media.AudioAttributes
|
||||
import android.media.RingtoneManager
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.Person
|
||||
import androidx.core.app.RemoteInput
|
||||
@@ -37,17 +36,32 @@ import androidx.core.net.toUri
|
||||
import com.geeksville.mesh.MainActivity
|
||||
import com.geeksville.mesh.R.raw
|
||||
import com.geeksville.mesh.service.ReplyReceiver.Companion.KEY_TEXT_REPLY
|
||||
import com.meshtastic.core.strings.getString
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.meshtastic.core.database.entity.NodeEntity
|
||||
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.Res
|
||||
import org.meshtastic.core.strings.client_notification
|
||||
import org.meshtastic.core.strings.low_battery_message
|
||||
import org.meshtastic.core.strings.low_battery_title
|
||||
import org.meshtastic.core.strings.meshtastic_alerts_notifications
|
||||
import org.meshtastic.core.strings.meshtastic_broadcast_notifications
|
||||
import org.meshtastic.core.strings.meshtastic_low_battery_notifications
|
||||
import org.meshtastic.core.strings.meshtastic_low_battery_temporary_remote_notifications
|
||||
import org.meshtastic.core.strings.meshtastic_messages_notifications
|
||||
import org.meshtastic.core.strings.meshtastic_new_nodes_notifications
|
||||
import org.meshtastic.core.strings.meshtastic_service_notifications
|
||||
import org.meshtastic.core.strings.new_node_seen
|
||||
import org.meshtastic.core.strings.no_local_stats
|
||||
import org.meshtastic.core.strings.reply
|
||||
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.
|
||||
@@ -73,7 +87,7 @@ class MeshServiceNotificationsImpl @Inject constructor(@ApplicationContext priva
|
||||
*/
|
||||
private sealed class NotificationType(
|
||||
val channelId: String,
|
||||
@StringRes val channelNameRes: Int,
|
||||
val channelNameRes: StringResource,
|
||||
val importance: Int,
|
||||
) {
|
||||
object ServiceState :
|
||||
|
||||
@@ -21,7 +21,6 @@ package com.geeksville.mesh.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.Animatable
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
@@ -71,8 +70,6 @@ import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavDestination
|
||||
@@ -100,6 +97,9 @@ import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.navigation.ConnectionsRoutes
|
||||
import org.meshtastic.core.navigation.ContactsRoutes
|
||||
@@ -108,6 +108,25 @@ 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.Res
|
||||
import org.meshtastic.core.strings.app_too_old
|
||||
import org.meshtastic.core.strings.bottom_nav_settings
|
||||
import org.meshtastic.core.strings.client_notification
|
||||
import org.meshtastic.core.strings.compromised_keys
|
||||
import org.meshtastic.core.strings.connected
|
||||
import org.meshtastic.core.strings.connections
|
||||
import org.meshtastic.core.strings.conversations
|
||||
import org.meshtastic.core.strings.device_sleeping
|
||||
import org.meshtastic.core.strings.disconnected
|
||||
import org.meshtastic.core.strings.firmware_old
|
||||
import org.meshtastic.core.strings.firmware_too_old
|
||||
import org.meshtastic.core.strings.map
|
||||
import org.meshtastic.core.strings.must_update
|
||||
import org.meshtastic.core.strings.nodes
|
||||
import org.meshtastic.core.strings.okay
|
||||
import org.meshtastic.core.strings.should_update
|
||||
import org.meshtastic.core.strings.should_update_firmware
|
||||
import org.meshtastic.core.strings.traceroute
|
||||
import org.meshtastic.core.ui.component.MultipleChoiceAlertDialog
|
||||
import org.meshtastic.core.ui.component.SimpleAlertDialog
|
||||
import org.meshtastic.core.ui.icon.Conversations
|
||||
@@ -122,9 +141,8 @@ 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) {
|
||||
enum class TopLevelDestination(val label: StringResource, val icon: ImageVector, val route: Route) {
|
||||
Conversations(Res.string.conversations, MeshtasticIcons.Conversations, ContactsRoutes.ContactsGraph),
|
||||
Nodes(Res.string.nodes, MeshtasticIcons.Nodes, NodesRoutes.NodesGraph),
|
||||
Map(Res.string.map, MeshtasticIcons.Map, MapRoutes.Map),
|
||||
@@ -392,7 +410,6 @@ private fun VersionChecks(viewModel: UIViewModel) {
|
||||
val connectionState by viewModel.connectionState.collectAsStateWithLifecycle()
|
||||
val myNodeInfo by viewModel.myNodeInfo.collectAsStateWithLifecycle()
|
||||
val context = LocalContext.current
|
||||
val resources = LocalResources.current
|
||||
|
||||
val myFirmwareVersion = myNodeInfo?.firmwareVersion
|
||||
|
||||
@@ -424,8 +441,8 @@ private fun VersionChecks(viewModel: UIViewModel) {
|
||||
val isOld = info.minAppVersion > BuildConfig.VERSION_CODE && BuildConfig.DEBUG.not()
|
||||
if (isOld) {
|
||||
viewModel.showAlert(
|
||||
resources.getString(Res.string.app_too_old),
|
||||
resources.getString(Res.string.must_update),
|
||||
getString(Res.string.app_too_old),
|
||||
getString(Res.string.must_update),
|
||||
dismissable = false,
|
||||
onConfirm = {
|
||||
val service = viewModel.meshService ?: return@showAlert
|
||||
@@ -436,8 +453,8 @@ private fun VersionChecks(viewModel: UIViewModel) {
|
||||
myFirmwareVersion?.let {
|
||||
val curVer = DeviceVersion(it)
|
||||
if (curVer < MeshService.absoluteMinDeviceVersion) {
|
||||
val title = resources.getString(Res.string.firmware_too_old)
|
||||
val message = resources.getString(Res.string.firmware_old)
|
||||
val title = getString(Res.string.firmware_too_old)
|
||||
val message = getString(Res.string.firmware_old)
|
||||
viewModel.showAlert(
|
||||
title = title,
|
||||
html = message,
|
||||
@@ -448,9 +465,8 @@ private fun VersionChecks(viewModel: UIViewModel) {
|
||||
},
|
||||
)
|
||||
} else if (curVer < MeshService.minDeviceVersion) {
|
||||
val title = resources.getString(Res.string.should_update_firmware)
|
||||
val message =
|
||||
resources.getString(Res.string.should_update, latestStableFirmwareRelease.asString)
|
||||
val title = getString(Res.string.should_update_firmware)
|
||||
val message = getString(Res.string.should_update, latestStableFirmwareRelease.asString)
|
||||
viewModel.showAlert(title = title, message = message, dismissable = false, onConfirm = {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,6 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -62,9 +60,20 @@ import com.geeksville.mesh.ui.connections.components.NetworkDevices
|
||||
import com.geeksville.mesh.ui.connections.components.UsbDevices
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import kotlinx.coroutines.delay
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.connected
|
||||
import org.meshtastic.core.strings.connected_device
|
||||
import org.meshtastic.core.strings.connected_sleeping
|
||||
import org.meshtastic.core.strings.connections
|
||||
import org.meshtastic.core.strings.must_set_region
|
||||
import org.meshtastic.core.strings.not_connected
|
||||
import org.meshtastic.core.strings.set_your_region
|
||||
import org.meshtastic.core.strings.warning_not_paired
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
@@ -73,7 +82,6 @@ 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")
|
||||
@@ -104,7 +112,6 @@ fun ConnectionsScreen(
|
||||
val connectionState by
|
||||
connectionsViewModel.connectionState.collectAsStateWithLifecycle(ConnectionState.DISCONNECTED)
|
||||
val scanning by scanModel.spinner.collectAsStateWithLifecycle(false)
|
||||
val context = LocalContext.current
|
||||
val ourNode by connectionsViewModel.ourNodeInfo.collectAsStateWithLifecycle()
|
||||
val selectedDevice by scanModel.selectedNotNullFlow.collectAsStateWithLifecycle()
|
||||
val bluetoothState by connectionsViewModel.bluetoothState.collectAsStateWithLifecycle()
|
||||
@@ -158,7 +165,7 @@ fun ConnectionsScreen(
|
||||
|
||||
ConnectionState.DISCONNECTED -> Res.string.not_connected
|
||||
ConnectionState.DEVICE_SLEEP -> Res.string.connected_sleeping
|
||||
}.let { scanModel.setErrorText(context.getString(it)) }
|
||||
}.let { scanModel.setErrorText(getString(it)) }
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
|
||||
@@ -43,7 +43,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.geeksville.mesh.model.BTScanModel
|
||||
@@ -51,9 +50,20 @@ import com.geeksville.mesh.model.DeviceListEntry
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.MultiplePermissionsState
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.bluetooth_available_devices
|
||||
import org.meshtastic.core.strings.bluetooth_disabled
|
||||
import org.meshtastic.core.strings.bluetooth_paired_devices
|
||||
import org.meshtastic.core.strings.grant_permissions
|
||||
import org.meshtastic.core.strings.no_ble_devices
|
||||
import org.meshtastic.core.strings.open_settings
|
||||
import org.meshtastic.core.strings.permission_missing
|
||||
import org.meshtastic.core.strings.permission_missing_31
|
||||
import org.meshtastic.core.strings.scan
|
||||
import org.meshtastic.core.strings.scanning_bluetooth
|
||||
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
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package com.geeksville.mesh.ui.connections.components
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Bluetooth
|
||||
import androidx.compose.material.icons.rounded.Usb
|
||||
@@ -30,12 +29,16 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
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.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.bluetooth
|
||||
import org.meshtastic.core.strings.network
|
||||
import org.meshtastic.core.strings.serial
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LambdaParameterEventTrailing")
|
||||
@Composable
|
||||
@@ -58,7 +61,7 @@ fun ConnectionsSegmentedBar(
|
||||
}
|
||||
}
|
||||
|
||||
private enum class Item(val imageVector: ImageVector, @StringRes val textRes: Int, val deviceType: DeviceType) {
|
||||
private enum class Item(val imageVector: ImageVector, val textRes: StringResource, val deviceType: DeviceType) {
|
||||
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),
|
||||
|
||||
@@ -32,11 +32,14 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.disconnect
|
||||
import org.meshtastic.core.strings.firmware_version
|
||||
import org.meshtastic.core.ui.component.MaterialBatteryInfo
|
||||
import org.meshtastic.core.ui.component.NodeChip
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
@@ -44,7 +47,6 @@ 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
|
||||
|
||||
@@ -33,9 +33,13 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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 as Res
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.add
|
||||
import org.meshtastic.core.strings.bluetooth
|
||||
import org.meshtastic.core.strings.network
|
||||
import org.meshtastic.core.strings.serial
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
|
||||
@@ -46,7 +46,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
@@ -56,10 +55,20 @@ import com.geeksville.mesh.model.DeviceListEntry
|
||||
import com.geeksville.mesh.repository.network.NetworkRepository
|
||||
import com.geeksville.mesh.ui.connections.isIPAddress
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.add_network_device
|
||||
import org.meshtastic.core.strings.cancel
|
||||
import org.meshtastic.core.strings.confirm_delete_node
|
||||
import org.meshtastic.core.strings.delete
|
||||
import org.meshtastic.core.strings.discovered_network_devices
|
||||
import org.meshtastic.core.strings.ip_address
|
||||
import org.meshtastic.core.strings.ip_port
|
||||
import org.meshtastic.core.strings.no_network_devices
|
||||
import org.meshtastic.core.strings.recent_network_devices
|
||||
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")
|
||||
|
||||
@@ -21,14 +21,15 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.UsbOff
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import com.geeksville.mesh.model.BTScanModel
|
||||
import com.geeksville.mesh.model.DeviceListEntry
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.no_usb_devices
|
||||
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(
|
||||
|
||||
@@ -44,7 +44,6 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@@ -53,10 +52,14 @@ 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.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.sample_message
|
||||
import org.meshtastic.core.strings.some_username
|
||||
import org.meshtastic.core.strings.unknown_username
|
||||
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
|
||||
|
||||
@@ -55,19 +55,37 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.geeksville.mesh.model.Contact
|
||||
import org.jetbrains.compose.resources.pluralStringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.entity.ContactSettings
|
||||
import org.meshtastic.core.model.util.formatMuteRemainingTime
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.cancel
|
||||
import org.meshtastic.core.strings.close_selection
|
||||
import org.meshtastic.core.strings.conversations
|
||||
import org.meshtastic.core.strings.currently
|
||||
import org.meshtastic.core.strings.delete
|
||||
import org.meshtastic.core.strings.delete_messages
|
||||
import org.meshtastic.core.strings.delete_selection
|
||||
import org.meshtastic.core.strings.mute_1_week
|
||||
import org.meshtastic.core.strings.mute_8_hours
|
||||
import org.meshtastic.core.strings.mute_always
|
||||
import org.meshtastic.core.strings.mute_notifications
|
||||
import org.meshtastic.core.strings.mute_status_always
|
||||
import org.meshtastic.core.strings.mute_status_muted_for_days
|
||||
import org.meshtastic.core.strings.mute_status_muted_for_hours
|
||||
import org.meshtastic.core.strings.mute_status_unmuted
|
||||
import org.meshtastic.core.strings.okay
|
||||
import org.meshtastic.core.strings.select_all
|
||||
import org.meshtastic.core.strings.unmute
|
||||
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")
|
||||
|
||||
@@ -17,15 +17,14 @@
|
||||
|
||||
package com.geeksville.mesh.ui.contact
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.geeksville.mesh.model.Contact
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.data.repository.PacketRepository
|
||||
import org.meshtastic.core.data.repository.RadioConfigRepository
|
||||
@@ -34,17 +33,17 @@ 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.Res
|
||||
import org.meshtastic.core.strings.channel_name
|
||||
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
|
||||
@Inject
|
||||
constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val nodeRepository: NodeRepository,
|
||||
private val packetRepository: PacketRepository,
|
||||
radioConfigRepository: RadioConfigRepository,
|
||||
@@ -87,7 +86,7 @@ constructor(
|
||||
val shortName = user.shortName
|
||||
val longName =
|
||||
if (toBroadcast) {
|
||||
channelSet.getChannel(data.channel)?.name ?: context.getString(Res.string.channel_name)
|
||||
channelSet.getChannel(data.channel)?.name ?: getString(Res.string.channel_name)
|
||||
} else {
|
||||
user.longName
|
||||
}
|
||||
|
||||
@@ -78,7 +78,6 @@ import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
@@ -94,12 +93,31 @@ import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.journeyapps.barcodescanner.ScanContract
|
||||
import com.journeyapps.barcodescanner.ScanOptions
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.model.util.getChannelUrl
|
||||
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.Res
|
||||
import org.meshtastic.core.strings.add
|
||||
import org.meshtastic.core.strings.apply
|
||||
import org.meshtastic.core.strings.are_you_sure_change_default
|
||||
import org.meshtastic.core.strings.cancel
|
||||
import org.meshtastic.core.strings.cant_change_no_radio
|
||||
import org.meshtastic.core.strings.channel_invalid
|
||||
import org.meshtastic.core.strings.copy
|
||||
import org.meshtastic.core.strings.edit
|
||||
import org.meshtastic.core.strings.modem_preset
|
||||
import org.meshtastic.core.strings.navigate_into_label
|
||||
import org.meshtastic.core.strings.qr_code
|
||||
import org.meshtastic.core.strings.replace
|
||||
import org.meshtastic.core.strings.reset
|
||||
import org.meshtastic.core.strings.reset_to_defaults
|
||||
import org.meshtastic.core.strings.scan
|
||||
import org.meshtastic.core.strings.send
|
||||
import org.meshtastic.core.strings.url
|
||||
import org.meshtastic.core.ui.component.AdaptiveTwoPane
|
||||
import org.meshtastic.core.ui.component.ChannelSelection
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
@@ -116,7 +134,6 @@ 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
|
||||
|
||||
@@ -35,7 +35,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
@@ -43,9 +42,15 @@ 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.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.sample_message
|
||||
import org.meshtastic.core.strings.share
|
||||
import org.meshtastic.core.strings.share_to
|
||||
import org.meshtastic.core.strings.some_username
|
||||
import org.meshtastic.core.strings.unknown_username
|
||||
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) {
|
||||
|
||||
19
app/src/main/res/values/strings.xml
Normal file
19
app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Copyright (c) 2025 Meshtastic LLC
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Meshtastic</string>
|
||||
</resources>
|
||||
@@ -112,5 +112,10 @@ gradlePlugin {
|
||||
implementationClass = "SpotlessConventionPlugin"
|
||||
}
|
||||
|
||||
register("kmpLibrary") {
|
||||
id = libs.plugins.meshtastic.kmp.library.get().pluginId
|
||||
implementationClass = "KmpLibraryConventionPlugin"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import com.android.build.api.dsl.androidLibrary
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import java.io.FileInputStream
|
||||
import java.util.Properties
|
||||
|
||||
class KmpLibraryConventionPlugin : Plugin<Project> {
|
||||
override fun apply(target: Project) {
|
||||
with(target) {
|
||||
apply(plugin = "org.jetbrains.kotlin.multiplatform")
|
||||
apply(plugin = "org.jetbrains.kotlin.plugin.compose")
|
||||
apply(plugin = "com.android.kotlin.multiplatform.library")
|
||||
apply(plugin = "meshtastic.detekt")
|
||||
apply(plugin = "meshtastic.spotless")
|
||||
apply(plugin = "com.autonomousapps.dependency-analysis")
|
||||
|
||||
val configPropertiesFile = rootProject.file("config.properties")
|
||||
val configProperties = Properties()
|
||||
|
||||
if (configPropertiesFile.exists()) {
|
||||
FileInputStream(configPropertiesFile).use { configProperties.load(it) }
|
||||
}
|
||||
|
||||
extensions.configure<KotlinMultiplatformExtension> {
|
||||
@Suppress("UnstableApiUsage")
|
||||
androidLibrary {
|
||||
compileSdk = configProperties.getProperty("COMPILE_SDK").toInt()
|
||||
minSdk = configProperties.getProperty("MIN_SDK").toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,10 @@
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.android.kotlin.multiplatform.library) apply false
|
||||
alias(libs.plugins.android.library) apply false
|
||||
alias(libs.plugins.compose) apply false
|
||||
alias(libs.plugins.compose.compiler) apply false
|
||||
alias(libs.plugins.compose.multiplatform) apply false
|
||||
alias(libs.plugins.datadog) apply false
|
||||
alias(libs.plugins.devtools.ksp) apply false
|
||||
alias(libs.plugins.firebase.crashlytics) apply false
|
||||
@@ -30,6 +32,7 @@ plugins {
|
||||
alias(libs.plugins.room) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
alias(libs.plugins.kotlin.jvm) apply false
|
||||
alias(libs.plugins.kotlin.multiplatform) apply false
|
||||
alias(libs.plugins.kotlin.parcelize) apply false
|
||||
alias(libs.plugins.kotlin.serialization) apply false
|
||||
alias(libs.plugins.ktorfit) apply false
|
||||
|
||||
@@ -17,15 +17,37 @@
|
||||
|
||||
package org.meshtastic.core.database.model
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.meshtastic.core.database.entity.Reaction
|
||||
import org.meshtastic.core.model.MessageStatus
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.delivery_confirmed
|
||||
import org.meshtastic.core.strings.error
|
||||
import org.meshtastic.core.strings.message_delivery_status
|
||||
import org.meshtastic.core.strings.message_status_enroute
|
||||
import org.meshtastic.core.strings.message_status_queued
|
||||
import org.meshtastic.core.strings.routing_error_admin_bad_session_key
|
||||
import org.meshtastic.core.strings.routing_error_admin_public_key_unauthorized
|
||||
import org.meshtastic.core.strings.routing_error_bad_request
|
||||
import org.meshtastic.core.strings.routing_error_duty_cycle_limit
|
||||
import org.meshtastic.core.strings.routing_error_got_nak
|
||||
import org.meshtastic.core.strings.routing_error_max_retransmit
|
||||
import org.meshtastic.core.strings.routing_error_no_channel
|
||||
import org.meshtastic.core.strings.routing_error_no_interface
|
||||
import org.meshtastic.core.strings.routing_error_no_response
|
||||
import org.meshtastic.core.strings.routing_error_no_route
|
||||
import org.meshtastic.core.strings.routing_error_none
|
||||
import org.meshtastic.core.strings.routing_error_not_authorized
|
||||
import org.meshtastic.core.strings.routing_error_pki_failed
|
||||
import org.meshtastic.core.strings.routing_error_pki_unknown_pubkey
|
||||
import org.meshtastic.core.strings.routing_error_rate_limit_exceeded
|
||||
import org.meshtastic.core.strings.routing_error_timeout
|
||||
import org.meshtastic.core.strings.routing_error_too_large
|
||||
import org.meshtastic.core.strings.unrecognized
|
||||
import org.meshtastic.proto.MeshProtos.Routing
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
@StringRes
|
||||
fun getStringResFrom(routingError: Int): Int = when (routingError) {
|
||||
fun getStringResFrom(routingError: Int): StringResource = when (routingError) {
|
||||
Routing.Error.NONE_VALUE -> Res.string.routing_error_none
|
||||
Routing.Error.NO_ROUTE_VALUE -> Res.string.routing_error_no_route
|
||||
Routing.Error.GOT_NAK_VALUE -> Res.string.routing_error_got_nak
|
||||
@@ -66,7 +88,7 @@ data class Message(
|
||||
val viaMqtt: Boolean = false,
|
||||
val relayNode: Int? = null,
|
||||
) {
|
||||
fun getStatusStringRes(): Pair<Int, Int> {
|
||||
fun getStatusStringRes(): Pair<StringResource, StringResource> {
|
||||
val title = if (routingError > 0) Res.string.error else Res.string.message_delivery_status
|
||||
val text =
|
||||
when (status) {
|
||||
|
||||
@@ -17,10 +17,17 @@
|
||||
|
||||
package org.meshtastic.core.database.model
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.node_sort_alpha
|
||||
import org.meshtastic.core.strings.node_sort_channel
|
||||
import org.meshtastic.core.strings.node_sort_distance
|
||||
import org.meshtastic.core.strings.node_sort_hops_away
|
||||
import org.meshtastic.core.strings.node_sort_last_heard
|
||||
import org.meshtastic.core.strings.node_sort_via_favorite
|
||||
import org.meshtastic.core.strings.node_sort_via_mqtt
|
||||
|
||||
enum class NodeSortOption(val sqlValue: String, @StringRes val stringRes: Int) {
|
||||
enum class NodeSortOption(val sqlValue: String, val stringRes: StringResource) {
|
||||
LAST_HEARD("last_heard", Res.string.node_sort_last_heard),
|
||||
ALPHABETICAL("alpha", Res.string.node_sort_alpha),
|
||||
DISTANCE("distance", Res.string.node_sort_distance),
|
||||
|
||||
@@ -17,12 +17,21 @@
|
||||
|
||||
package org.meshtastic.core.model
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.label_long_fast
|
||||
import org.meshtastic.core.strings.label_long_moderate
|
||||
import org.meshtastic.core.strings.label_long_slow
|
||||
import org.meshtastic.core.strings.label_medium_fast
|
||||
import org.meshtastic.core.strings.label_medium_slow
|
||||
import org.meshtastic.core.strings.label_short_fast
|
||||
import org.meshtastic.core.strings.label_short_slow
|
||||
import org.meshtastic.core.strings.label_short_turbo
|
||||
import org.meshtastic.core.strings.label_very_long_slow
|
||||
import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig
|
||||
import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig.ModemPreset
|
||||
import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig.RegionCode
|
||||
import kotlin.math.floor
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/** hash a string into an integer using the djb2 algorithm by Dan Bernstein http://www.cse.yorku.ca/~oz/hash.html */
|
||||
private fun hash(name: String): UInt { // using UInt instead of Long to match RadioInterface.cpp results
|
||||
@@ -296,7 +305,7 @@ enum class RegionInfo(
|
||||
}
|
||||
}
|
||||
|
||||
enum class ChannelOption(val modemPreset: ModemPreset, @StringRes val labelRes: Int, val bandwidth: Float) {
|
||||
enum class ChannelOption(val modemPreset: ModemPreset, val labelRes: StringResource, val bandwidth: Float) {
|
||||
VERY_LONG_SLOW(ModemPreset.VERY_LONG_SLOW, Res.string.label_very_long_slow, .0625f),
|
||||
LONG_FAST(ModemPreset.LONG_FAST, Res.string.label_long_fast, .250f),
|
||||
LONG_MODERATE(ModemPreset.LONG_MODERATE, Res.string.label_long_moderate, .125f),
|
||||
|
||||
@@ -14,7 +14,30 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import com.android.build.api.dsl.androidLibrary
|
||||
|
||||
plugins { alias(libs.plugins.meshtastic.android.library) }
|
||||
plugins {
|
||||
alias(libs.plugins.meshtastic.kmp.library)
|
||||
alias(libs.plugins.compose.multiplatform)
|
||||
}
|
||||
|
||||
android { namespace = "org.meshtastic.core.strings" }
|
||||
kotlin {
|
||||
@Suppress("UnstableApiUsage")
|
||||
androidLibrary {
|
||||
namespace = "org.meshtastic.core.strings"
|
||||
androidResources.enable = true
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
implementation(compose.runtime)
|
||||
// API because consuming modules will always need this dependency
|
||||
api(compose.components.resources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compose.resources {
|
||||
publicResClass = true
|
||||
packageOfResClass = "org.meshtastic.core.strings"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.meshtastic.core.strings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
||||
fun Context.getString(stringResource: StringResource): String = runBlocking {
|
||||
org.jetbrains.compose.resources.getString(stringResource)
|
||||
}
|
||||
|
||||
fun Context.getString(stringResource: StringResource, vararg formatArgs: Any): String = runBlocking {
|
||||
org.jetbrains.compose.resources.getString(stringResource, *formatArgs)
|
||||
}
|
||||
|
||||
fun Resources.getString(stringResource: StringResource): String = runBlocking {
|
||||
org.jetbrains.compose.resources.getString(stringResource)
|
||||
}
|
||||
|
||||
fun Resources.getString(stringResource: StringResource, vararg formatArgs: Any): String = runBlocking {
|
||||
org.jetbrains.compose.resources.getString(stringResource, *formatArgs)
|
||||
}
|
||||
@@ -22,7 +22,6 @@
|
||||
<string name="zh_CN" translatable="false">简体中文</string>
|
||||
<string name="zh_TW" translatable="false">繁體中文</string>
|
||||
|
||||
<string name="app_name" translatable="false">Meshtastic</string>
|
||||
<string name="some_username" translatable="false">SKH</string>
|
||||
<string name="sample_message" translatable="false">hey I found the cache, it is over here next to the big tiger. I\'m kinda scared.</string>
|
||||
|
||||
@@ -29,7 +29,6 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextLinkStyles
|
||||
@@ -37,7 +36,9 @@ import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.fromHtml
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.okay
|
||||
|
||||
@Composable
|
||||
fun SimpleAlertDialog(
|
||||
|
||||
@@ -38,7 +38,9 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.clear
|
||||
import org.meshtastic.core.strings.close
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.collectIsPressedAsState
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -28,11 +27,12 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
@Composable
|
||||
fun ClickableTextField(
|
||||
@StringRes label: Int,
|
||||
label: StringResource,
|
||||
enabled: Boolean,
|
||||
trailingIcon: ImageVector,
|
||||
value: String,
|
||||
|
||||
@@ -40,7 +40,6 @@ import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
@@ -55,15 +54,19 @@ import com.google.zxing.WriterException
|
||||
import com.journeyapps.barcodescanner.BarcodeEncoder
|
||||
import com.journeyapps.barcodescanner.ScanContract
|
||||
import com.journeyapps.barcodescanner.ScanOptions
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.qr_code
|
||||
import org.meshtastic.core.strings.scan_qr_code
|
||||
import org.meshtastic.core.strings.share_contact
|
||||
import org.meshtastic.core.ui.R
|
||||
import org.meshtastic.core.ui.share.SharedContactDialog
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
import timber.log.Timber
|
||||
import java.net.MalformedURLException
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/**
|
||||
* Composable FloatingActionButton to initiate scanning a QR code for adding a contact. Handles camera permission
|
||||
|
||||
@@ -27,9 +27,10 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ClipEntry
|
||||
import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.copy
|
||||
|
||||
@Composable
|
||||
fun CopyIconButton(
|
||||
|
||||
@@ -39,16 +39,18 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.protobuf.ByteString
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.model.util.encodeToString
|
||||
import org.meshtastic.core.model.util.toByteString
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.error
|
||||
import org.meshtastic.core.strings.reset
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
|
||||
@@ -35,17 +35,23 @@ import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.protobuf.ByteString
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.add
|
||||
import org.meshtastic.core.strings.delete
|
||||
import org.meshtastic.core.strings.gpio_pin
|
||||
import org.meshtastic.core.strings.ignore_incoming
|
||||
import org.meshtastic.core.strings.name
|
||||
import org.meshtastic.core.strings.type
|
||||
import org.meshtastic.proto.ModuleConfigProtos.RemoteHardwarePin
|
||||
import org.meshtastic.proto.ModuleConfigProtos.RemoteHardwarePinType
|
||||
import org.meshtastic.proto.copy
|
||||
import org.meshtastic.proto.remoteHardwarePin
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
|
||||
@@ -29,13 +29,15 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.hide_password
|
||||
import org.meshtastic.core.strings.show_password
|
||||
|
||||
@Composable
|
||||
fun EditPasswordPreference(
|
||||
|
||||
@@ -38,13 +38,14 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusState
|
||||
import androidx.compose.ui.focus.onFocusEvent
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.error
|
||||
|
||||
@Composable
|
||||
fun SignedIntegerEditTextPreference(
|
||||
|
||||
@@ -51,12 +51,16 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.air_quality_icon
|
||||
import org.meshtastic.core.strings.close
|
||||
import org.meshtastic.core.strings.indoor_air_quality_iaq
|
||||
import org.meshtastic.core.ui.theme.IAQColors.IAQDangerouslyPolluted
|
||||
import org.meshtastic.core.ui.theme.IAQColors.IAQExcellent
|
||||
import org.meshtastic.core.ui.theme.IAQColors.IAQExtremelyPolluted
|
||||
@@ -65,7 +69,6 @@ import org.meshtastic.core.ui.theme.IAQColors.IAQHeavilyPolluted
|
||||
import org.meshtastic.core.ui.theme.IAQColors.IAQLightlyPolluted
|
||||
import org.meshtastic.core.ui.theme.IAQColors.IAQModeratelyPolluted
|
||||
import org.meshtastic.core.ui.theme.IAQColors.IAQSeverelyPolluted
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
enum class Iaq(val color: Color, val description: String, val range: IntRange) {
|
||||
|
||||
@@ -43,13 +43,22 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.bad
|
||||
import org.meshtastic.core.strings.fair
|
||||
import org.meshtastic.core.strings.good
|
||||
import org.meshtastic.core.strings.none_quality
|
||||
import org.meshtastic.core.strings.rssi
|
||||
import org.meshtastic.core.strings.signal
|
||||
import org.meshtastic.core.strings.signal_quality
|
||||
import org.meshtastic.core.strings.snr
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusOrange
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusYellow
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
const val SNR_GOOD_THRESHOLD = -7f
|
||||
const val SNR_FAIR_THRESHOLD = -15f
|
||||
@@ -59,7 +68,7 @@ const val RSSI_FAIR_THRESHOLD = -126
|
||||
|
||||
@Stable
|
||||
enum class Quality(
|
||||
@Stable val nameRes: Int,
|
||||
@Stable val nameRes: StringResource,
|
||||
@Stable val imageVector: ImageVector,
|
||||
@Stable val color: @Composable () -> Color,
|
||||
) {
|
||||
|
||||
@@ -33,17 +33,20 @@ import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.application_icon
|
||||
import org.meshtastic.core.strings.navigate_back
|
||||
import org.meshtastic.core.ui.component.preview.BooleanProvider
|
||||
import org.meshtastic.core.ui.component.preview.previewNode
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
||||
@@ -33,11 +33,13 @@ import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.unknown
|
||||
import org.meshtastic.core.ui.icon.BatteryEmpty
|
||||
import org.meshtastic.core.ui.icon.BatteryUnknown
|
||||
import org.meshtastic.core.ui.icon.MeshtasticIcons
|
||||
@@ -45,7 +47,6 @@ import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusOrange
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val FORMAT = "%d%%"
|
||||
private const val SIZE_ICON = 20
|
||||
|
||||
@@ -35,11 +35,13 @@ import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.dbm_value
|
||||
import org.meshtastic.core.ui.icon.MeshtasticIcons
|
||||
import org.meshtastic.core.ui.icon.SignalCellular0Bar
|
||||
import org.meshtastic.core.ui.icon.SignalCellular1Bar
|
||||
@@ -51,7 +53,6 @@ import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusOrange
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusRed
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusYellow
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val SIZE_ICON = 20
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import android.util.Base64
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -53,19 +52,32 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.protobuf.ByteString
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.config_security_public_key
|
||||
import org.meshtastic.core.strings.encryption_error
|
||||
import org.meshtastic.core.strings.encryption_error_text
|
||||
import org.meshtastic.core.strings.encryption_pkc
|
||||
import org.meshtastic.core.strings.encryption_pkc_text
|
||||
import org.meshtastic.core.strings.encryption_psk
|
||||
import org.meshtastic.core.strings.encryption_psk_text
|
||||
import org.meshtastic.core.strings.security_icon_help_dismiss
|
||||
import org.meshtastic.core.strings.security_icon_help_show_all
|
||||
import org.meshtastic.core.strings.security_icon_help_show_less
|
||||
import org.meshtastic.core.strings.show_all_key_title
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
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
|
||||
|
||||
/**
|
||||
* function to display information about the current node's encryption key.
|
||||
@@ -131,9 +143,9 @@ fun NodeKeyStatusIcon(
|
||||
enum class NodeKeySecurityState(
|
||||
@Stable val icon: ImageVector,
|
||||
@Stable val color: @Composable () -> Color,
|
||||
@StringRes val descriptionResId: Int,
|
||||
@StringRes val helpTextResId: Int,
|
||||
@Stable val title: Int,
|
||||
val descriptionResId: StringResource,
|
||||
val helpTextResId: StringResource,
|
||||
@Stable val title: StringResource,
|
||||
) {
|
||||
// State for public key mismatch
|
||||
PKM(
|
||||
@@ -164,7 +176,7 @@ enum class NodeKeySecurityState(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun KeyStatusDialog(@StringRes title: Int, @StringRes text: Int, key: ByteString?, onDismiss: () -> Unit = {}) {
|
||||
private fun KeyStatusDialog(title: StringResource, text: StringResource, key: ByteString?, onDismiss: () -> Unit = {}) {
|
||||
var showAll by rememberSaveable { mutableStateOf(false) }
|
||||
AlertDialog(
|
||||
modifier = Modifier,
|
||||
|
||||
@@ -27,15 +27,17 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.model.util.DistanceUnit
|
||||
import org.meshtastic.core.model.util.toDistanceString
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.position_enabled
|
||||
import org.meshtastic.core.strings.precise_location
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val POSITION_ENABLED = 32
|
||||
private const val POSITION_DISABLED = 0
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -29,17 +28,18 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
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.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
@Deprecated(message = "Use overload that accepts Strings for button text.")
|
||||
@Composable
|
||||
fun PreferenceFooter(
|
||||
enabled: Boolean,
|
||||
@StringRes negativeText: Int,
|
||||
negativeText: StringResource,
|
||||
onNegativeClicked: () -> Unit,
|
||||
@StringRes positiveText: Int,
|
||||
positiveText: StringResource,
|
||||
onPositiveClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -57,18 +56,34 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.model.util.getChannel
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.security_icon_badge_warning_description
|
||||
import org.meshtastic.core.strings.security_icon_description
|
||||
import org.meshtastic.core.strings.security_icon_help_dismiss
|
||||
import org.meshtastic.core.strings.security_icon_help_green_lock
|
||||
import org.meshtastic.core.strings.security_icon_help_red_open_lock
|
||||
import org.meshtastic.core.strings.security_icon_help_show_all
|
||||
import org.meshtastic.core.strings.security_icon_help_show_less
|
||||
import org.meshtastic.core.strings.security_icon_help_title
|
||||
import org.meshtastic.core.strings.security_icon_help_title_all
|
||||
import org.meshtastic.core.strings.security_icon_help_warning_precise_mqtt
|
||||
import org.meshtastic.core.strings.security_icon_help_yellow_open_lock
|
||||
import org.meshtastic.core.strings.security_icon_insecure_no_precise
|
||||
import org.meshtastic.core.strings.security_icon_insecure_precise_only
|
||||
import org.meshtastic.core.strings.security_icon_secure
|
||||
import org.meshtastic.core.strings.security_icon_warning_precise_mqtt
|
||||
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.proto.AppOnlyProtos
|
||||
import org.meshtastic.proto.ChannelProtos.ChannelSettings
|
||||
import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val PRECISE_POSITION_BITS = 32
|
||||
|
||||
@@ -87,8 +102,8 @@ private const val PRECISE_POSITION_BITS = 32
|
||||
enum class SecurityState(
|
||||
@Stable val icon: ImageVector,
|
||||
@Stable val color: @Composable () -> Color,
|
||||
@StringRes val descriptionResId: Int,
|
||||
@StringRes val helpTextResId: Int,
|
||||
val descriptionResId: StringResource,
|
||||
val helpTextResId: StringResource,
|
||||
@Stable val badgeIcon: ImageVector? = null,
|
||||
@Stable val badgeIconColor: @Composable () -> Color? = { null },
|
||||
) {
|
||||
|
||||
@@ -28,15 +28,19 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.channel_air_util
|
||||
import org.meshtastic.core.strings.hops_away
|
||||
import org.meshtastic.core.strings.signal
|
||||
import org.meshtastic.core.strings.signal_quality
|
||||
import org.meshtastic.core.ui.component.preview.NodePreviewParameterProvider
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
const val MAX_VALID_SNR = 100F
|
||||
const val MAX_VALID_RSSI = 0
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
@@ -28,16 +27,21 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.cancel
|
||||
import org.meshtastic.core.strings.message
|
||||
import org.meshtastic.core.strings.okay
|
||||
import org.meshtastic.core.strings.sample_message
|
||||
import org.meshtastic.core.ui.theme.AppTheme
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun SimpleAlertDialog(
|
||||
@StringRes title: Int,
|
||||
title: StringResource,
|
||||
text: @Composable (() -> Unit)? = null,
|
||||
confirmText: String? = null,
|
||||
onConfirm: (() -> Unit)? = null,
|
||||
@@ -74,8 +78,8 @@ fun SimpleAlertDialog(
|
||||
|
||||
@Composable
|
||||
fun SimpleAlertDialog(
|
||||
@StringRes title: Int,
|
||||
@StringRes text: Int,
|
||||
title: StringResource,
|
||||
text: StringResource,
|
||||
onConfirm: (() -> Unit)? = null,
|
||||
onDismiss: () -> Unit = {},
|
||||
) = SimpleAlertDialog(
|
||||
@@ -87,7 +91,7 @@ fun SimpleAlertDialog(
|
||||
|
||||
@Composable
|
||||
fun SimpleAlertDialog(
|
||||
@StringRes title: Int,
|
||||
title: StringResource,
|
||||
text: String,
|
||||
onConfirm: (() -> Unit)? = null,
|
||||
onDismiss: () -> Unit = {},
|
||||
|
||||
@@ -43,7 +43,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -51,13 +50,19 @@ import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.accept
|
||||
import org.meshtastic.core.strings.add
|
||||
import org.meshtastic.core.strings.cancel
|
||||
import org.meshtastic.core.strings.new_channel_rcvd
|
||||
import org.meshtastic.core.strings.replace
|
||||
import org.meshtastic.core.ui.component.ChannelSelection
|
||||
import org.meshtastic.proto.AppOnlyProtos.ChannelSet
|
||||
import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig.ModemPreset
|
||||
import org.meshtastic.proto.channelSet
|
||||
import org.meshtastic.proto.copy
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun ScannedQrCodeDialog(
|
||||
|
||||
@@ -23,14 +23,19 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.cancel
|
||||
import org.meshtastic.core.strings.import_known_shared_contact_text
|
||||
import org.meshtastic.core.strings.import_label
|
||||
import org.meshtastic.core.strings.import_shared_contact
|
||||
import org.meshtastic.core.strings.public_key_changed
|
||||
import org.meshtastic.core.ui.component.SimpleAlertDialog
|
||||
import org.meshtastic.core.ui.component.compareUsers
|
||||
import org.meshtastic.core.ui.component.userFieldsToString
|
||||
import org.meshtastic.proto.AdminProtos
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
/** A dialog for importing a shared contact that was scanned from a QR code. */
|
||||
@Composable
|
||||
|
||||
@@ -19,16 +19,17 @@ package org.meshtastic.core.ui.util
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.getString
|
||||
|
||||
suspend fun Context.showToast(@StringRes resId: Int) {
|
||||
showToast(getString(resId))
|
||||
suspend fun Context.showToast(stringResource: StringResource) {
|
||||
showToast(getString(stringResource))
|
||||
}
|
||||
|
||||
suspend fun Context.showToast(text: CharSequence) {
|
||||
suspend fun Context.showToast(stringResource: StringResource, vararg formatArgs: Any) {
|
||||
Toast.makeText(this, getString(stringResource, formatArgs), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
suspend fun Context.showToast(text: String) {
|
||||
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
suspend fun Context.showToast(@StringRes resId: Int, vararg formatArgs: Any) {
|
||||
Toast.makeText(this, getString(resId, formatArgs), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
package org.meshtastic.core.ui.util
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.unknown_age
|
||||
import org.meshtastic.proto.ChannelProtos
|
||||
import org.meshtastic.proto.ChannelProtos.ChannelSettings
|
||||
import org.meshtastic.proto.MeshProtos
|
||||
@@ -28,7 +30,6 @@ import org.meshtastic.proto.channel
|
||||
import org.meshtastic.proto.channelSettings
|
||||
import java.text.DateFormat
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
private const val SECONDS_TO_MILLIS = 1000L
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ pull_request_labels:
|
||||
- automation
|
||||
- l10n
|
||||
files:
|
||||
- source: /**/src/main/res/values/strings.xml
|
||||
- source: /**/src/commonMain/composeResources/values/strings.xml
|
||||
translation: /%original_path%-%android_code%/strings.xml
|
||||
translate_attributes: 0
|
||||
content_segmentation: 0
|
||||
|
||||
@@ -24,12 +24,18 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.analytics_notice
|
||||
import org.meshtastic.core.strings.analytics_platforms
|
||||
import org.meshtastic.core.strings.datadog_link
|
||||
import org.meshtastic.core.strings.firebase_link
|
||||
import org.meshtastic.core.strings.for_more_information_see_our_privacy_policy
|
||||
import org.meshtastic.core.strings.privacy_url
|
||||
import org.meshtastic.core.ui.component.AutoLinkText
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
|
||||
@Composable
|
||||
fun AnalyticsIntro(modifier: Modifier = Modifier) {
|
||||
|
||||
@@ -30,11 +30,15 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.configure_critical_alerts
|
||||
import org.meshtastic.core.strings.critical_alerts
|
||||
import org.meshtastic.core.strings.critical_alerts_dnd_request_text
|
||||
import org.meshtastic.core.strings.skip
|
||||
|
||||
/**
|
||||
* Screen for explaining and guiding the user to configure critical alert settings. This screen is part of the app
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
package org.meshtastic.feature.intro
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
||||
/**
|
||||
* Data class representing the UI elements for a feature row in the app introduction.
|
||||
@@ -29,6 +29,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
||||
*/
|
||||
internal data class FeatureUIData(
|
||||
val icon: ImageVector,
|
||||
@StringRes val titleRes: Int? = null,
|
||||
@StringRes val subtitleRes: Int,
|
||||
val titleRes: StringResource? = null,
|
||||
val subtitleRes: StringResource,
|
||||
)
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package org.meshtastic.feature.intro
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -29,13 +28,14 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
/** Tag used for identifying clickable annotations in text, specifically for linking to settings. */
|
||||
internal const val SETTINGS_TAG = "settings_link_tag"
|
||||
@@ -80,8 +80,8 @@ internal fun FeatureRow(feature: FeatureUIData) {
|
||||
*/
|
||||
@Composable
|
||||
internal fun Context.createClickableAnnotatedString(
|
||||
@StringRes fullTextRes: Int,
|
||||
@StringRes linkTextRes: Int,
|
||||
fullTextRes: StringResource,
|
||||
linkTextRes: StringResource,
|
||||
tag: String,
|
||||
): AnnotatedString {
|
||||
val fullText = stringResource(fullTextRes)
|
||||
|
||||
@@ -26,7 +26,20 @@ import androidx.compose.material.icons.outlined.Router
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.configure_location_permissions
|
||||
import org.meshtastic.core.strings.distance_filters
|
||||
import org.meshtastic.core.strings.distance_filters_description
|
||||
import org.meshtastic.core.strings.distance_measurements
|
||||
import org.meshtastic.core.strings.distance_measurements_description
|
||||
import org.meshtastic.core.strings.mesh_map_location
|
||||
import org.meshtastic.core.strings.mesh_map_location_description
|
||||
import org.meshtastic.core.strings.next
|
||||
import org.meshtastic.core.strings.phone_location
|
||||
import org.meshtastic.core.strings.phone_location_description
|
||||
import org.meshtastic.core.strings.settings
|
||||
import org.meshtastic.core.strings.share_location
|
||||
import org.meshtastic.core.strings.share_location_description
|
||||
|
||||
/**
|
||||
* Screen for configuring location permissions during the app introduction. It explains why location permissions are
|
||||
|
||||
@@ -33,11 +33,24 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.strings.R as Res
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.app_notifications
|
||||
import org.meshtastic.core.strings.configure_notification_permissions
|
||||
import org.meshtastic.core.strings.critical_alerts
|
||||
import org.meshtastic.core.strings.critical_alerts_description
|
||||
import org.meshtastic.core.strings.incoming_messages
|
||||
import org.meshtastic.core.strings.low_battery
|
||||
import org.meshtastic.core.strings.new_nodes
|
||||
import org.meshtastic.core.strings.next
|
||||
import org.meshtastic.core.strings.notification_permissions_description
|
||||
import org.meshtastic.core.strings.notifications_for_channel_and_direct_messages
|
||||
import org.meshtastic.core.strings.notifications_for_low_battery_alerts
|
||||
import org.meshtastic.core.strings.notifications_for_newly_discovered_nodes
|
||||
import org.meshtastic.core.strings.settings
|
||||
|
||||
/**
|
||||
* Screen for configuring notification permissions during the app introduction. It explains why notification permissions
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user