mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: Localize traceroute strings (#4228)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
1f07486745
commit
37b59af27b
4 changed files with 67 additions and 21 deletions
|
|
@ -29,6 +29,9 @@ import org.meshtastic.core.model.getFullTracerouteResponse
|
|||
import org.meshtastic.core.service.ServiceRepository
|
||||
import org.meshtastic.core.service.TracerouteResponse
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.traceroute_duration
|
||||
import org.meshtastic.core.strings.traceroute_route_back_to_us
|
||||
import org.meshtastic.core.strings.traceroute_route_towards_dest
|
||||
import org.meshtastic.core.strings.unknown_username
|
||||
import org.meshtastic.proto.MeshProtos.MeshPacket
|
||||
import java.util.Locale
|
||||
|
|
@ -53,10 +56,14 @@ constructor(
|
|||
|
||||
fun handleTraceroute(packet: MeshPacket, logUuid: String?, logInsertJob: kotlinx.coroutines.Job?) {
|
||||
val full =
|
||||
packet.getFullTracerouteResponse { num ->
|
||||
nodeManager.nodeDBbyNodeNum[num]?.let { "${it.longName} (${it.shortName})" }
|
||||
?: getString(Res.string.unknown_username)
|
||||
} ?: return
|
||||
packet.getFullTracerouteResponse(
|
||||
getUser = { num ->
|
||||
nodeManager.nodeDBbyNodeNum[num]?.let { "${it.longName} (${it.shortName})" }
|
||||
?: getString(Res.string.unknown_username)
|
||||
},
|
||||
headerTowards = getString(Res.string.traceroute_route_towards_dest),
|
||||
headerBack = getString(Res.string.traceroute_route_back_to_us),
|
||||
) ?: return
|
||||
|
||||
val requestId = packet.decoded.requestId
|
||||
if (logUuid != null) {
|
||||
|
|
@ -79,7 +86,8 @@ constructor(
|
|||
val elapsedMs = System.currentTimeMillis() - start
|
||||
val seconds = elapsedMs / MILLISECONDS_IN_SECOND
|
||||
Logger.i { "Traceroute $requestId complete in $seconds s" }
|
||||
String.format(Locale.US, "%s\n\nDuration: %.1f s", full, seconds)
|
||||
val durationText = getString(Res.string.traceroute_duration, "%.1f".format(Locale.US, seconds))
|
||||
"$full\n\n$durationText"
|
||||
} else {
|
||||
full
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
* Copyright (c) 2025-2026 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
|
||||
|
|
@ -14,7 +14,6 @@
|
|||
* 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 org.meshtastic.core.model
|
||||
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
|
@ -72,25 +71,36 @@ private fun formatTraceroutePath(nodesList: List<String>, snrList: List<Int>): S
|
|||
.joinToString("\n")
|
||||
}
|
||||
|
||||
private fun RouteDiscovery.getTracerouteResponse(getUser: (nodeNum: Int) -> String): String = buildString {
|
||||
private fun RouteDiscovery.getTracerouteResponse(
|
||||
getUser: (nodeNum: Int) -> String,
|
||||
headerTowards: String = "Route traced toward destination:\n\n",
|
||||
headerBack: String = "Route traced back to us:\n\n",
|
||||
): String = buildString {
|
||||
if (routeList.isNotEmpty()) {
|
||||
append("Route traced toward destination:\n\n")
|
||||
append(headerTowards)
|
||||
append(formatTraceroutePath(routeList.map(getUser), snrTowardsList))
|
||||
}
|
||||
if (routeBackList.isNotEmpty()) {
|
||||
append("\n\n")
|
||||
append("Route traced back to us:\n\n")
|
||||
append(headerBack)
|
||||
append(formatTraceroutePath(routeBackList.map(getUser), snrBackList))
|
||||
}
|
||||
}
|
||||
|
||||
fun MeshProtos.MeshPacket.getTracerouteResponse(getUser: (nodeNum: Int) -> String): String? =
|
||||
fullRouteDiscovery?.getTracerouteResponse(getUser)
|
||||
fun MeshProtos.MeshPacket.getTracerouteResponse(
|
||||
getUser: (nodeNum: Int) -> String,
|
||||
headerTowards: String = "Route traced toward destination:\n\n",
|
||||
headerBack: String = "Route traced back to us:\n\n",
|
||||
): String? = fullRouteDiscovery?.getTracerouteResponse(getUser, headerTowards, headerBack)
|
||||
|
||||
/** Returns a traceroute response string only when the result is complete (both directions). */
|
||||
fun MeshProtos.MeshPacket.getFullTracerouteResponse(getUser: (nodeNum: Int) -> String): String? = fullRouteDiscovery
|
||||
fun MeshProtos.MeshPacket.getFullTracerouteResponse(
|
||||
getUser: (nodeNum: Int) -> String,
|
||||
headerTowards: String = "Route traced toward destination:\n\n",
|
||||
headerBack: String = "Route traced back to us:\n\n",
|
||||
): String? = fullRouteDiscovery
|
||||
?.takeIf { it.routeList.isNotEmpty() && it.routeBackList.isNotEmpty() }
|
||||
?.getTracerouteResponse(getUser)
|
||||
?.getTracerouteResponse(getUser, headerTowards, headerBack)
|
||||
|
||||
enum class TracerouteMapAvailability {
|
||||
Ok,
|
||||
|
|
|
|||
|
|
@ -442,6 +442,10 @@
|
|||
<string name="view_on_map">View on map</string>
|
||||
<string name="traceroute_map_no_data">This traceroute does not have any mappable nodes yet.</string>
|
||||
<string name="traceroute_showing_nodes">Showing %1$d/%2$d nodes</string>
|
||||
<string name="traceroute_duration">Duration: %1$s s</string>
|
||||
<string name="traceroute_time_and_text">%1$s - %2$s</string>
|
||||
<string name="traceroute_route_towards_dest">Route traced toward destination:\n\n</string>
|
||||
<string name="traceroute_route_back_to_us">Route traced back to us:\n\n</string>
|
||||
<string name="twenty_four_hours">24H</string>
|
||||
<string name="forty_eight_hours">48H</string>
|
||||
<string name="one_week">1W</string>
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.meshtastic.core.strings.getString
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.pluralStringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
|
@ -76,7 +77,11 @@ import org.meshtastic.core.strings.routing_error_no_response
|
|||
import org.meshtastic.core.strings.traceroute
|
||||
import org.meshtastic.core.strings.traceroute_diff
|
||||
import org.meshtastic.core.strings.traceroute_direct
|
||||
import org.meshtastic.core.strings.traceroute_duration
|
||||
import org.meshtastic.core.strings.traceroute_hops
|
||||
import org.meshtastic.core.strings.traceroute_route_back_to_us
|
||||
import org.meshtastic.core.strings.traceroute_route_towards_dest
|
||||
import org.meshtastic.core.strings.traceroute_time_and_text
|
||||
import org.meshtastic.core.strings.view_on_map
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.SNR_FAIR_THRESHOLD
|
||||
|
|
@ -165,14 +170,27 @@ fun TracerouteLogScreen(
|
|||
val seconds =
|
||||
(res.received_date - log.received_date).coerceAtLeast(0).toDouble() / MS_PER_SEC
|
||||
val annotatedBase =
|
||||
annotateTraceroute(res.fromRadio.packet.getTracerouteResponse(::getUsername))
|
||||
annotateTraceroute(
|
||||
res.fromRadio.packet.getTracerouteResponse(
|
||||
::getUsername,
|
||||
headerTowards = stringResource(Res.string.traceroute_route_towards_dest),
|
||||
headerBack = stringResource(Res.string.traceroute_route_back_to_us),
|
||||
),
|
||||
)
|
||||
val durationText = stringResource(Res.string.traceroute_duration, "%.1f".format(seconds))
|
||||
buildAnnotatedString {
|
||||
append(annotatedBase)
|
||||
append("\n\nDuration: ${"%.1f".format(seconds)} s")
|
||||
append("\n\n$durationText")
|
||||
}
|
||||
} else {
|
||||
// For cases where there's a result but no full route, display plain text
|
||||
res.fromRadio.packet.getTracerouteResponse(::getUsername)?.let { AnnotatedString(it) }
|
||||
res.fromRadio.packet
|
||||
.getTracerouteResponse(
|
||||
::getUsername,
|
||||
headerTowards = stringResource(Res.string.traceroute_route_towards_dest),
|
||||
headerBack = stringResource(Res.string.traceroute_route_back_to_us),
|
||||
)
|
||||
?.let { AnnotatedString(it) }
|
||||
}
|
||||
}
|
||||
val overlay =
|
||||
|
|
@ -187,14 +205,20 @@ fun TracerouteLogScreen(
|
|||
Box {
|
||||
TracerouteItem(
|
||||
icon = icon,
|
||||
text = "$time - $text",
|
||||
text = stringResource(Res.string.traceroute_time_and_text, time, text),
|
||||
modifier =
|
||||
Modifier.combinedClickable(onLongClick = { expanded = true }) {
|
||||
val dialogMessage =
|
||||
tracerouteDetailsAnnotated
|
||||
?: result?.fromRadio?.packet?.getTracerouteResponse(::getUsername)?.let {
|
||||
AnnotatedString(it)
|
||||
}
|
||||
?: result
|
||||
?.fromRadio
|
||||
?.packet
|
||||
?.getTracerouteResponse(
|
||||
::getUsername,
|
||||
headerTowards = getString(Res.string.traceroute_route_towards_dest),
|
||||
headerBack = getString(Res.string.traceroute_route_back_to_us),
|
||||
)
|
||||
?.let { AnnotatedString(it) }
|
||||
dialogMessage?.let {
|
||||
val responseLogUuid = result?.uuid ?: return@combinedClickable
|
||||
showDialog =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue