diff --git a/tests/test_stream_core.c b/tests/test_stream_core.c
index ab13f5fc..54c5e82d 100644
--- a/tests/test_stream_core.c
+++ b/tests/test_stream_core.c
@@ -507,36 +507,36 @@ static void test_source_timer(void) {
/* Близкий сосед, цена дополнительных hops и проблем сравниваются в одних единицах, неизвестный RTT не становится нулём. */
static void test_supplier_score(void) {
- struct stream_receive_info near = {.rtt_ms = 10, .path_rtt_ms = 80, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 3}};
- struct stream_receive_info far = {.rtt_ms = 45, .path_rtt_ms = 40, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 2}};
+ struct stream_receive_info near_peer = {.rtt_ms = 10, .path_rtt_ms = 80, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 3}};
+ struct stream_receive_info far_peer = {.rtt_ms = 45, .path_rtt_ms = 40, .rtt_valid = 1, .path_rtt_valid = 1, .path = {.count = 2}};
struct stream_metric_snapshot clean = {.blocks = 100}, late = {.blocks = 100, .late_blocks = 2};
- CHECK(stream_supplier_score(&near, &clean, 1) == 109 && stream_supplier_score(&far, &clean, 1) == 136);
- /* Обычная сумма RTT предпочла бы far (85 < 90); удвоенный RTT соседа предпочитает near. */
- CHECK(stream_supplier_score(&near, &clean, 1) < stream_supplier_score(&far, &clean, 1));
- CHECK(stream_supplier_score(&near, &late, 1) == 129);
- CHECK(stream_supplier_score(&near, &late, 1) < stream_supplier_score(&far, &clean, 1));
+ CHECK(stream_supplier_score(&near_peer, &clean, 1) == 109 && stream_supplier_score(&far_peer, &clean, 1) == 136);
+ /* Обычная сумма RTT предпочла бы far_peer (85 < 90); удвоенный RTT соседа предпочитает near_peer. */
+ CHECK(stream_supplier_score(&near_peer, &clean, 1) < stream_supplier_score(&far_peer, &clean, 1));
+ CHECK(stream_supplier_score(&near_peer, &late, 1) == 129);
+ CHECK(stream_supplier_score(&near_peer, &late, 1) < stream_supplier_score(&far_peer, &clean, 1));
late.late_blocks = 3;
- CHECK(stream_supplier_score(&near, &late, 1) > stream_supplier_score(&far, &clean, 1));
- far = near; far.rtt_ms = 9; far.path.count = 4;
- CHECK(stream_supplier_score(&far, &clean, 1) == 110);
- CHECK(stream_supplier_score(&near, &clean, 1) < stream_supplier_score(&far, &clean, 1));
+ CHECK(stream_supplier_score(&near_peer, &late, 1) > stream_supplier_score(&far_peer, &clean, 1));
+ far_peer = near_peer; far_peer.rtt_ms = 9; far_peer.path.count = 4;
+ CHECK(stream_supplier_score(&far_peer, &clean, 1) == 110);
+ CHECK(stream_supplier_score(&near_peer, &clean, 1) < stream_supplier_score(&far_peer, &clean, 1));
late = (struct stream_metric_snapshot){.blocks = 4, .late_blocks = 1, .stops = 7};
- CHECK(stream_supplier_score(&near, &late, 1) == 369);
+ CHECK(stream_supplier_score(&near_peer, &late, 1) == 369);
late.lag_ms = STREAM_LATE_MS;
- CHECK(stream_supplier_score(&near, &late, 1) == 369);
+ CHECK(stream_supplier_score(&near_peer, &late, 1) == 369);
late.lag_ms++;
- CHECK(stream_supplier_score(&near, &late, 1) == 1109);
+ CHECK(stream_supplier_score(&near_peer, &late, 1) == 1109);
late.lag_ms = 0; late.stopped = 1;
- CHECK(stream_supplier_score(&near, &late, 1) == 1109);
+ CHECK(stream_supplier_score(&near_peer, &late, 1) == 1109);
late.stopped = 0; late.late_blocks = late.blocks;
- CHECK(stream_supplier_score(&near, &late, 1) == 1109); /* История остановок не превышает лимит штрафа. */
- CHECK(stream_supplier_score(&near, &late, 0) == 109);
- near.rtt_valid = 0;
- CHECK(stream_supplier_score(&near, &clean, 1) == UINT64_MAX);
- near.rtt_valid = 1; near.path_rtt_valid = 0;
- CHECK(stream_supplier_score(&near, &clean, 1) == UINT64_MAX);
- near.path_rtt_valid = 1; near.rtt_ms = near.path_rtt_ms = UINT32_MAX;
- CHECK(stream_supplier_score(&near, &late, 1) == 3 * (uint64_t)UINT32_MAX + 1009);
+ CHECK(stream_supplier_score(&near_peer, &late, 1) == 1109); /* История остановок не превышает лимит штрафа. */
+ CHECK(stream_supplier_score(&near_peer, &late, 0) == 109);
+ near_peer.rtt_valid = 0;
+ CHECK(stream_supplier_score(&near_peer, &clean, 1) == UINT64_MAX);
+ near_peer.rtt_valid = 1; near_peer.path_rtt_valid = 0;
+ CHECK(stream_supplier_score(&near_peer, &clean, 1) == UINT64_MAX);
+ near_peer.path_rtt_valid = 1; near_peer.rtt_ms = near_peer.path_rtt_ms = UINT32_MAX;
+ CHECK(stream_supplier_score(&near_peer, &late, 1) == 3 * (uint64_t)UINT32_MAX + 1009);
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] supplier score: nearby peer, hop cost, problem tradeoffs, 1000ms cap, unknown and wide RTT");
}
diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/CallScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/CallScreen.kt
index eeef9d5b..e6d7b0fc 100644
--- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/CallScreen.kt
+++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/CallScreen.kt
@@ -43,6 +43,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
+import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -240,28 +241,29 @@ fun CallScreen(
fontSize = 16.sp
)
Spacer(Modifier.height(8.dp))
- Text(stringResource(R.string.connection_label, st?.connectionType?.label ?: stringResource(R.string.connection_none)),
- color = Color(0xFFAEBCC8), fontSize = 13.sp)
- val bgpPath = st?.bgpPath ?: ""
- if (bgpPath.isNotEmpty()) {
- Spacer(Modifier.height(8.dp))
- Text(
- bgpPath,
- color = Color(0xFFAEBCC8),
- fontSize = 13.sp
- )
- }
- if (phase == CallPhase.ACTIVE) st?.stats?.let { stats ->
- Spacer(Modifier.height(8.dp))
- Text(stringResource(R.string.call_stats, stats.bufferMs, stats.reserveMs,
- stats.minMs, stats.maxMs, "%.2f".format(stats.tempoX100 / 100.0), stats.rttMs, stats.dropped, stats.underruns),
- modifier = Modifier.padding(horizontal = 16.dp), color = Color(0xFFAEBCC8),
- fontSize = 12.sp, textAlign = TextAlign.Center)
- Text(stringResource(R.string.call_output_stats,
- stats.output.queueMs.takeIf { it >= 0 }?.toString() ?: "—",
- stats.output.outputMs.takeIf { it >= 0 }?.toString() ?: "—"),
- modifier = Modifier.padding(horizontal = 16.dp), color = Color(0xFFAEBCC8),
- fontSize = 12.sp, textAlign = TextAlign.Center)
+ ProvideTextStyle(MaterialTheme.typography.bodySmall.copy(
+ color = Color(0xFFAEBCC8), fontSize = 12.sp, lineHeight = 14.sp,
+ textAlign = TextAlign.Center, platformStyle = PlatformTextStyle(includeFontPadding = false)
+ )) {
+ Column(Modifier.fillMaxWidth().padding(horizontal = 16.dp),
+ horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(2.dp)) {
+ LaunchedEffect(Unit) {
+ LogManager.addLog("DEBUG", "call", "compact call diagnostics shown: font=12sp lineHeight=14sp gap=2dp")
+ }
+ Text(stringResource(R.string.connection_label, st?.connectionType?.label ?: stringResource(R.string.connection_none)),
+ modifier = Modifier.fillMaxWidth())
+ val bgpPath = st?.bgpPath ?: ""
+ if (bgpPath.isNotEmpty()) Text(bgpPath, modifier = Modifier.fillMaxWidth())
+ if (phase == CallPhase.ACTIVE) st?.stats?.let { stats ->
+ Text(stringResource(R.string.call_stats, stats.bufferMs, stats.reserveMs,
+ stats.minMs, stats.maxMs, "%.2f".format(stats.tempoX100 / 100.0), stats.rttMs, stats.dropped, stats.underruns),
+ modifier = Modifier.fillMaxWidth())
+ Text(stringResource(R.string.call_output_stats,
+ stats.output.queueMs.takeIf { it >= 0 }?.toString() ?: "—",
+ stats.output.outputMs.takeIf { it >= 0 }?.toString() ?: "—"),
+ modifier = Modifier.fillMaxWidth())
+ }
+ }
}
Spacer(Modifier.height(40.dp))
}
diff --git a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml
index 2eaef868..fc5157f8 100644
--- a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml
+++ b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml
@@ -373,8 +373,8 @@
"неизвестный (%1$d)"
"Не удалось сохранить файл"
"Передать приватный ключ канала участнику «%1$s»?\n\nКлюч передаётся зашифрованным и подписанным. Получатель станет совладельцем и сможет управлять участниками."
- "Буфер: %1$s мс · Запас: %2$s мс\nЗа 10 с: минимум %3$s · максимум %4$s мс\nСкорость: %5$s× · RTT: %6$s мс\nПотери буфера: %7$s · Недостачи: %8$s"
- "Аудиовыход: %2$s мс (включая очередь приложения: %1$s мс)"
+ "Буфер %1$s · запас %2$s мс\nМин–макс за 10 с: %3$s–%4$s мс\nТемп %5$s× · RTT %6$s мс\nСбросы %7$s · недостачи %8$s"
+ "Выход %2$s мс · из них очередь %1$s мс"
- BGP: %1$d узел
- BGP: %1$d узла
diff --git a/tools/chatgui-android/app/src/main/res/values/strings.xml b/tools/chatgui-android/app/src/main/res/values/strings.xml
index d5d5a23c..40cdec22 100644
--- a/tools/chatgui-android/app/src/main/res/values/strings.xml
+++ b/tools/chatgui-android/app/src/main/res/values/strings.xml
@@ -374,8 +374,8 @@
"unknown (%1$d)"
"Could not save file"
"Send the channel private key to “%1$s”?\n\nThe key is transferred encrypted and signed. The recipient will become a co-owner and will be able to manage members."
- "Buffer: %1$s ms · Reserve: %2$s ms\nOver 10 s: min %3$s · max %4$s ms\nSpeed: %5$s× · RTT: %6$s ms\nBuffer drops: %7$s · Underruns: %8$s"
- "Audio output: %2$s ms (includes app queue: %1$s ms)"
+ "Buffer %1$s · reserve %2$s ms\nMin–max over 10 s: %3$s–%4$s ms\nTempo %5$s× · RTT %6$s ms\nDrops %7$s · underruns %8$s"
+ "Output %2$s ms · includes queue %1$s ms"
- BGP: %1$d node
- BGP: %1$d nodes