android: route check results as cards with status pills

This commit is contained in:
Denozordec committed 2026-10-10 00:32:24 +07:00
1 parent 7a7673119e
commit 2681233449
4 files changed
+61 -35

No files matched your search

@@ -33,6 +33,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import org.strongswan.android.ui.compose.components.ShxStatusPill
import org.strongswan.android.ui.compose.components.ShxSectionCard
import org.strongswan.android.ui.compose.theme.LocalShxStatusColors
import org.strongswan.android.R
import org.strongswan.android.logic.CharonVpnService
import org.strongswan.android.logic.routing.RouteCheck
@@ -98,50 +103,68 @@ fun RouteCheckScreen()
@Composable
private fun RouteCheckResult(report: RouteCheck.Report)
{
Column(modifier = Modifier.padding(top = ShxSpacing.md))
val status = LocalShxStatusColors.current
Column(
modifier = Modifier.padding(top = ShxSpacing.lg),
verticalArrangement = Arrangement.spacedBy(ShxSpacing.md),
)
{
if (!report.vpnNetworkFound)
{
Text(
ShxStatusPill(
text = stringResource(R.string.route_check_no_vpn),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
containerColor = status.disconnectedContainer,
contentColor = status.onDisconnectedContainer,
shape = MaterialTheme.shapes.small,
style = MaterialTheme.typography.labelMedium,
)
}
RouteCheckRow(stringResource(R.string.route_check_via_vpn_dns), report.vpnDnsIps)
RouteCheckRow(stringResource(R.string.route_check_via_direct_dns), report.directDnsIps)
Text(
text = stringResource(R.string.route_check_routes),
style = MaterialTheme.typography.titleSmall,
modifier = Modifier.padding(top = 10.dp),
)
for (route in report.routes)
ShxSectionCard(title = stringResource(R.string.route_check_dns_section))
{
val label = stringResource(
when (route.kind)
RouteCheckRow(stringResource(R.string.route_check_via_vpn_dns), report.vpnDnsIps)
RouteCheckRow(stringResource(R.string.route_check_via_direct_dns), report.directDnsIps)
}
ShxSectionCard(title = stringResource(R.string.route_check_routes))
{
for (route in report.routes)
{
val label = stringResource(
when (route.kind)
{
RouteCheck.RouteKind.TUNNEL -> R.string.route_verdict_tunnel
RouteCheck.RouteKind.DIRECT_RU -> R.string.route_verdict_direct
RouteCheck.RouteKind.TUNNEL_DNS -> R.string.route_verdict_dns
},
)
val direct = route.kind == RouteCheck.RouteKind.DIRECT_RU
Row(
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(ShxSpacing.md),
)
{
RouteCheck.RouteKind.TUNNEL -> R.string.route_verdict_tunnel
RouteCheck.RouteKind.DIRECT_RU -> R.string.route_verdict_direct
RouteCheck.RouteKind.TUNNEL_DNS -> R.string.route_verdict_dns
},
)
Text(
text = "${route.ip} — $label",
style = MaterialTheme.typography.bodySmall,
fontFamily = FontFamily.Monospace,
modifier = Modifier.padding(top = 2.dp),
)
}
if (report.routes.isEmpty())
{
Text(
text = stringResource(R.string.route_check_resolve_failed),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
)
Text(
text = route.ip,
style = MaterialTheme.typography.bodySmall,
fontFamily = FontFamily.Monospace,
modifier = Modifier.weight(1f),
)
ShxStatusPill(
text = label,
containerColor = if (direct) status.connectingContainer else status.connectedContainer,
contentColor = if (direct) status.onConnectingContainer else status.onConnectedContainer,
)
}
}
if (report.routes.isEmpty())
{
Text(
text = stringResource(R.string.route_check_resolve_failed),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
)
}
}
}
Spacer(Modifier.height(ShxSpacing.sm))
}
@Composable
@@ -150,7 +173,7 @@ private fun RouteCheckRow(label: String, ips: List<String>)
Text(
text = label,
style = MaterialTheme.typography.titleSmall,
modifier = Modifier.padding(top = ShxSpacing.sm),
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
text = ips.joinToString(", ").ifEmpty { stringResource(R.string.route_check_none) },
@@ -512,4 +512,5 @@
<string name="apps_show_system">Systemapps anzeigen</string>
<string name="auto_connect_location_title">Standortzugriff erforderlich</string>
<string name="auto_connect_location_why">Android gibt den WLAN-Namen nur an Apps mit Standortzugriff weiter. Er dient ausschließlich dem Erkennen Ihrer vertrauenswürdigen Netzwerke; der Standort selbst wird nie gelesen oder gesendet.</string>
<string name="route_check_dns_section">DNS</string>
</resources>
@@ -509,4 +509,5 @@
<string name="apps_show_system">Показывать системные приложения</string>
<string name="auto_connect_location_title">Нужен доступ к геолокации</string>
<string name="auto_connect_location_why">Android сообщает имя Wi-Fi сети только приложениям с доступом к геолокации. Оно нужно лишь для распознавания доверенных сетей; сама геолокация не читается и не передаётся.</string>
<string name="route_check_dns_section">DNS</string>
</resources>
@@ -514,4 +514,5 @@
<string name="apps_show_system">Show system apps</string>
<string name="auto_connect_location_title">Location access needed</string>
<string name="auto_connect_location_why">Android only reveals the Wi-Fi network name to apps with location access. The app uses it solely to recognize your trusted networks; the location itself is never read or sent.</string>
<string name="route_check_dns_section">DNS</string>
</resources>