feat(discovery): replace hardcoded UI strings with string resources (D047)

This commit is contained in:
James Rich
2026-05-07 19:53:12 -05:00
parent 3f09a9eda5
commit ccaacee2c1
8 changed files with 112 additions and 22 deletions

View File

@@ -288,6 +288,21 @@ discard_changes
disconnect
disconnected
discovered_network_devices
### DISCOVERY ###
discovery_delete_session
discovery_delete_session_confirm
discovery_dwell_minutes
discovery_export_report
discovery_history
discovery_local_mesh
discovery_map
discovery_rerun_analysis
discovery_scan_history
discovery_scan_summary
discovery_session_detail
discovery_start_scan
discovery_stop_scan
discovery_view_map
disk_free_indexed
### DISPLAY ###
display

View File

@@ -312,6 +312,21 @@
<string name="disconnect">Disconnect</string>
<string name="disconnected">Disconnected</string>
<string name="discovered_network_devices">Discovered Network Devices</string>
<!-- DISCOVERY -->
<string name="discovery_delete_session">Delete Session</string>
<string name="discovery_delete_session_confirm">Are you sure you want to delete this discovery session? This action cannot be undone.</string>
<string name="discovery_dwell_minutes">%1$d min</string>
<string name="discovery_export_report">Export report</string>
<string name="discovery_history">Discovery History</string>
<string name="discovery_local_mesh">Local Mesh Discovery</string>
<string name="discovery_map">Discovery Map</string>
<string name="discovery_rerun_analysis">Re-run analysis</string>
<string name="discovery_scan_history">Scan History</string>
<string name="discovery_scan_summary">Scan Summary</string>
<string name="discovery_session_detail">Session Detail</string>
<string name="discovery_start_scan">Start Scan</string>
<string name="discovery_stop_scan">Stop Scan</string>
<string name="discovery_view_map">View map</string>
<string name="disk_free_indexed">Disk Free %1$d</string>
<!-- DISPLAY -->
<string name="display">Display</string>

View File

@@ -42,7 +42,12 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.database.entity.DiscoverySessionEntity
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.back
import org.meshtastic.core.resources.discovery_session_detail
import org.meshtastic.core.resources.discovery_view_map
import org.meshtastic.core.ui.icon.ArrowBack
import org.meshtastic.core.ui.icon.Map
import org.meshtastic.core.ui.icon.MeshtasticIcons
@@ -63,9 +68,11 @@ fun DiscoveryHistoryDetailScreen(
Scaffold(
topBar = {
TopAppBar(
title = { Text("Session Detail") },
title = { Text(stringResource(Res.string.discovery_session_detail)) },
navigationIcon = {
IconButton(onClick = onNavigateUp) { Icon(MeshtasticIcons.ArrowBack, contentDescription = "Back") }
IconButton(onClick = onNavigateUp) {
Icon(MeshtasticIcons.ArrowBack, contentDescription = stringResource(Res.string.back))
}
},
actions = {
val s = session
@@ -75,7 +82,10 @@ fun DiscoveryHistoryDetailScreen(
}
if (s != null && (s.userLatitude != 0.0 || hasAnyMappableNodes)) {
IconButton(onClick = { onNavigateToMap(s.id) }) {
Icon(MeshtasticIcons.Map, contentDescription = "View map")
Icon(
MeshtasticIcons.Map,
contentDescription = stringResource(Res.string.discovery_view_map),
)
}
}
},

View File

@@ -51,8 +51,16 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.common.util.toInstant
import org.meshtastic.core.database.entity.DiscoverySessionEntity
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.back
import org.meshtastic.core.resources.cancel
import org.meshtastic.core.resources.delete
import org.meshtastic.core.resources.discovery_delete_session
import org.meshtastic.core.resources.discovery_delete_session_confirm
import org.meshtastic.core.resources.discovery_history
import org.meshtastic.core.ui.icon.ArrowBack
import org.meshtastic.core.ui.icon.CheckCircle
import org.meshtastic.core.ui.icon.Delete
@@ -73,9 +81,11 @@ fun DiscoveryHistoryScreen(
Scaffold(
topBar = {
TopAppBar(
title = { Text("Discovery History") },
title = { Text(stringResource(Res.string.discovery_history)) },
navigationIcon = {
IconButton(onClick = onNavigateUp) { Icon(MeshtasticIcons.ArrowBack, contentDescription = "Back") }
IconButton(onClick = onNavigateUp) {
Icon(MeshtasticIcons.ArrowBack, contentDescription = stringResource(Res.string.back))
}
},
)
},
@@ -187,10 +197,14 @@ private fun CompletionStatusIcon(status: String) {
private fun DeleteConfirmationDialog(onConfirm: () -> Unit, onDismiss: () -> Unit) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text("Delete Session") },
text = { Text("Are you sure you want to delete this discovery session? This action cannot be undone.") },
confirmButton = { TextButton(onClick = onConfirm) { Text("Delete", color = MaterialTheme.colorScheme.error) } },
dismissButton = { TextButton(onClick = onDismiss) { Text("Cancel") } },
title = { Text(stringResource(Res.string.discovery_delete_session)) },
text = { Text(stringResource(Res.string.discovery_delete_session_confirm)) },
confirmButton = {
TextButton(onClick = onConfirm) {
Text(stringResource(Res.string.delete), color = MaterialTheme.colorScheme.error)
}
},
dismissButton = { TextButton(onClick = onDismiss) { Text(stringResource(Res.string.cancel)) } },
)
}

View File

@@ -31,6 +31,10 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.back
import org.meshtastic.core.resources.discovery_map
import org.meshtastic.core.ui.icon.ArrowBack
import org.meshtastic.core.ui.icon.MeshtasticIcons
import org.meshtastic.core.ui.util.DiscoveryMapNode
@@ -52,9 +56,11 @@ fun DiscoveryMapScreen(viewModel: DiscoveryMapViewModel, onNavigateUp: () -> Uni
Scaffold(
topBar = {
TopAppBar(
title = { Text("Discovery Map") },
title = { Text(stringResource(Res.string.discovery_map)) },
navigationIcon = {
IconButton(onClick = onNavigateUp) { Icon(MeshtasticIcons.ArrowBack, contentDescription = "Back") }
IconButton(onClick = onNavigateUp) {
Icon(MeshtasticIcons.ArrowBack, contentDescription = stringResource(Res.string.back))
}
},
)
},

View File

@@ -54,6 +54,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.back
import org.meshtastic.core.resources.discovery_local_mesh
import org.meshtastic.core.resources.discovery_scan_history
import org.meshtastic.core.resources.discovery_start_scan
import org.meshtastic.core.resources.discovery_stop_scan
import org.meshtastic.core.ui.component.SwitchPreference
import org.meshtastic.core.ui.icon.ArrowBack
import org.meshtastic.core.ui.icon.Close
@@ -108,15 +115,21 @@ fun DiscoveryScanScreen(
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text("Local Mesh Discovery") },
title = { Text(stringResource(Res.string.discovery_local_mesh)) },
navigationIcon = {
IconButton(onClick = onNavigateUp) {
Icon(imageVector = MeshtasticIcons.ArrowBack, contentDescription = "Back")
Icon(
imageVector = MeshtasticIcons.ArrowBack,
contentDescription = stringResource(Res.string.back),
)
}
},
actions = {
IconButton(onClick = onNavigateToHistory) {
Icon(imageVector = MeshtasticIcons.History, contentDescription = "Scan History")
Icon(
imageVector = MeshtasticIcons.History,
contentDescription = stringResource(Res.string.discovery_scan_history),
)
}
},
)
@@ -291,12 +304,12 @@ private fun ScanButton(
modifier = modifier.fillMaxWidth(),
) {
Icon(imageVector = MeshtasticIcons.Close, contentDescription = null)
Text("Stop Scan", modifier = Modifier.padding(start = 8.dp))
Text(stringResource(Res.string.discovery_stop_scan), modifier = Modifier.padding(start = 8.dp))
}
} else {
Button(onClick = onStart, enabled = isConnected && hasPresetsSelected, modifier = modifier.fillMaxWidth()) {
Icon(imageVector = MeshtasticIcons.PlayArrow, contentDescription = null)
Text("Start Scan", modifier = Modifier.padding(start = 8.dp))
Text(stringResource(Res.string.discovery_start_scan), modifier = Modifier.padding(start = 8.dp))
}
}
}

View File

@@ -46,11 +46,18 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.jetbrains.compose.resources.stringResource
import org.meshtastic.core.common.util.DateFormatter
import org.meshtastic.core.common.util.NumberFormatter
import org.meshtastic.core.database.entity.DiscoveredNodeEntity
import org.meshtastic.core.database.entity.DiscoveryPresetResultEntity
import org.meshtastic.core.database.entity.DiscoverySessionEntity
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.back
import org.meshtastic.core.resources.discovery_export_report
import org.meshtastic.core.resources.discovery_rerun_analysis
import org.meshtastic.core.resources.discovery_scan_summary
import org.meshtastic.core.resources.discovery_view_map
import org.meshtastic.core.ui.icon.ArrowBack
import org.meshtastic.core.ui.icon.Map
import org.meshtastic.core.ui.icon.MeshtasticIcons
@@ -131,17 +138,27 @@ private fun DiscoverySummaryContent(
Scaffold(
topBar = {
TopAppBar(
title = { Text("Scan Summary") },
title = { Text(stringResource(Res.string.discovery_scan_summary)) },
navigationIcon = {
IconButton(onClick = onNavigateUp) { Icon(MeshtasticIcons.ArrowBack, contentDescription = "Back") }
IconButton(onClick = onNavigateUp) {
Icon(MeshtasticIcons.ArrowBack, contentDescription = stringResource(Res.string.back))
}
},
actions = {
if (session != null) {
IconButton(onClick = { onNavigateToMap(session.id) }) {
Icon(MeshtasticIcons.Map, contentDescription = "View map")
Icon(
MeshtasticIcons.Map,
contentDescription = stringResource(Res.string.discovery_view_map),
)
}
}
IconButton(onClick = onExport) { Icon(MeshtasticIcons.Share, contentDescription = "Export report") }
IconButton(onClick = onExport) {
Icon(
MeshtasticIcons.Share,
contentDescription = stringResource(Res.string.discovery_export_report),
)
}
},
)
},
@@ -230,7 +247,7 @@ private fun AiSummaryCard(
IconButton(onClick = onRerunAnalysis) {
Icon(
MeshtasticIcons.Refresh,
contentDescription = "Re-run analysis",
contentDescription = stringResource(Res.string.discovery_rerun_analysis),
tint = MaterialTheme.colorScheme.onTertiaryContainer,
)
}

View File

@@ -110,7 +110,7 @@
- [ ] **D044** [P] Add accessibility polish: semantics, progress announcements, disabled-preset explanations, and large-screen layout checks.
- [X] **D045** [P] Finalize 2.4 GHz hardware gating using `DeviceHardwareRepository` + current radio metadata.
- [X] **D046** [P] Add logging / diagnostics and make sure the feature is debuggable through existing app logging tools.
- [ ] **D047** [P] Add strings, icons, and docs updates (`core/resources`, deep-link docs, quickstart references).
- [X] **D047** [P] Add strings, icons, and docs updates (`core/resources`, deep-link docs, quickstart references).
- [ ] **D048** Run targeted and full verification commands.
**Depends on**: all previous phases