Make :core:strings a Compose Multiplatform library (#3617)

This commit is contained in:
Phil Oliver 2025-11-10 19:58:38 -05:00 committed by GitHub
parent d7fff4add2
commit 28590bfcdf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
206 changed files with 1722 additions and 470 deletions

View file

@ -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) {

View file

@ -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),

View file

@ -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),

View file

@ -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"
}

View file

@ -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)
}

View file

@ -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>

View file

@ -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(

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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(

View file

@ -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

View file

@ -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

View file

@ -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(

View file

@ -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(

View file

@ -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) {

View file

@ -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,
) {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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,
) {

View file

@ -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 },
) {

View file

@ -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

View file

@ -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 = {},

View file

@ -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(

View file

@ -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

View file

@ -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()
}

View file

@ -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