feat(ui): show the active routing scope under the server card so the Сайты split is never invisible

This commit is contained in:
heaven 2026-06-16 22:00:12 +03:00
parent 55dada7772
commit 91014a8420
3 changed files with 37 additions and 0 deletions

View file

@ -54,6 +54,7 @@ import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@ -66,6 +67,7 @@ import chat.vojo.proxy.R
import chat.vojo.proxy.core.AppSettings
import chat.vojo.proxy.core.ProxyConfig
import chat.vojo.proxy.core.ProxyType
import chat.vojo.proxy.core.RoutingMode
import chat.vojo.proxy.core.formatClock
import chat.vojo.proxy.core.formatRate
import chat.vojo.proxy.service.VpnState
@ -136,6 +138,11 @@ fun ConnectionScreen(
onDisconnect = onDisconnect,
)
if (activeConfig != null) {
Spacer(Modifier.height(10.dp))
RoutingScopeLine(settings, Modifier.padding(start = 4.dp))
}
val stale = connected && applied != null &&
(applied.configId != activeConfig?.id || applied.settings != settings)
if (stale) {
@ -302,6 +309,28 @@ private fun ConnToggle(
}
}
/**
* Subtle line under the server card stating what the proxy actually carries so the
* "Сайты" split is never invisible (an empty list is now a full tunnel; a non-empty list
* shows how much is proxied vs direct).
*/
@Composable
private fun RoutingScopeLine(settings: AppSettings, modifier: Modifier = Modifier) {
val n = settings.routedSites.size
val text = when {
n == 0 -> stringResource(R.string.route_scope_all)
settings.routingMode == RoutingMode.DIRECT_ALL ->
stringResource(R.string.route_scope_only, pluralStringResource(R.plurals.route_rules, n, n))
else ->
stringResource(R.string.route_scope_except, pluralStringResource(R.plurals.route_rules, n, n))
}
Row(modifier, verticalAlignment = Alignment.CenterVertically) {
Box(Modifier.size(5.dp).clip(CircleShape).background(Vojo.fleetSoft.copy(alpha = 0.55f)))
Spacer(Modifier.width(8.dp))
Text(text, color = Vojo.muted, fontSize = 12.5.sp, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ServerPickerSheet(

View file

@ -47,6 +47,10 @@
<string name="stat_peak">Пик</string>
<!-- Per-second suffix appended to a byte rate, e.g. "1.2 МБ/с" -->
<string name="rate_per_second">/с</string>
<!-- Routing scope shown on the Tunnel tab; %1$s is a route_rules count -->
<string name="route_scope_all">Весь трафик через прокси</string>
<string name="route_scope_only">Через прокси: %1$s</string>
<string name="route_scope_except">Через прокси, кроме %1$s</string>
<!-- Servers screen -->
<string name="server_add">Добавить сервер</string>

View file

@ -54,6 +54,10 @@
<string name="stat_peak">Peak</string>
<!-- Per-second suffix appended to a byte rate, e.g. "1.2 MB/s" -->
<string name="rate_per_second">/s</string>
<!-- Routing scope shown on the Tunnel tab; %1$s is a route_rules count -->
<string name="route_scope_all">All traffic through the proxy</string>
<string name="route_scope_only">Through the proxy: %1$s</string>
<string name="route_scope_except">Through the proxy, except %1$s</string>
<!-- Servers screen -->
<string name="server_add">Add server</string>