Добавляем индикатор рассинхронизации звука и видео в статус-панели очков

This commit is contained in:
2026-09-02 19:27:11 +03:00
parent 92b483a5e3
commit b2e2d2697d
7 changed files with 92 additions and 6 deletions
@@ -102,6 +102,13 @@ class GlassesApp : Application() {
*/
val answerScrollDelta = MutableStateFlow(0f)
/**
* Индикатор аудио-синхронизации для статус-панели: |звук − видео| в мс
* (AudioSyncInfo от телефона каждый sync-цикл ~5с). null — не выводить
* (видео на очках не играет / данных ещё нет).
*/
val audioSyncDiffMs = MutableStateFlow<Int?>(null)
/** Текущая Activity (для закрытия приложения по команде с телефона). */
var mainActivity: MainActivity? = null
@@ -22,6 +22,7 @@ import pw.binom.viewmate.core.MediaCommand
import pw.binom.viewmate.core.net.GlassesTransport
import pw.binom.viewmate.core.net.WifiGlassesTransport
import pw.binom.viewmate.core.protocol.AssistantStateMsg
import pw.binom.viewmate.core.protocol.AudioSyncInfo
import pw.binom.viewmate.core.protocol.ChatHistoryItem
import pw.binom.viewmate.core.protocol.ChatHistoryMsg
import pw.binom.viewmate.core.protocol.ChatSessionMsg
@@ -338,6 +339,16 @@ class HostConnection(
downloadManager.handleDeleteFiles(msg.itemId)
}
is AudioSyncInfo -> {
// Индикатор |звук − видео| для статус-панели; active=false (видео не играет) — скрываем.
val prev = GlassesApp.instance.audioSyncDiffMs.value
GlassesApp.instance.audioSyncDiffMs.value = if (msg.active) msg.diffMs else null
// Диагностика: скачок diff (по часам очков) — для корреляции с logcat BT-стека телефона за ту же секунду.
if (msg.active && prev != null && msg.diffMs - prev >= 300) {
log("audio", "diff скачок $prev→${msg.diffMs} мс")
}
}
is AssistantStateMsg -> addMessage("AssistantState: ${msg.state} (${msg.recordingSeconds}с)")
is ShowText -> {
@@ -9,6 +9,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -18,6 +19,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import pw.binom.viewmate.glasses.GlassesApp
/**
* Композ-панель статуса (время + заряд). Вызывается внутри [Binocular] content,
@@ -36,12 +38,20 @@ fun StatusPanelCompose(modifier: Modifier = Modifier, scale: Float = 1f) {
val d = data ?: return
val baseStyle = MaterialTheme.typography.bodyMedium
val style = baseStyle.copy(fontSize = baseStyle.fontSize * scale)
// Индикатор |звук − видео| (мс): только когда видео играет на очках (MovieController.movieActive
// + свежее значение от телефона); без видео — ничего не выводить.
val diffMs = GlassesApp.instance.audioSyncDiffMs.collectAsState()
val movieActive = GlassesApp.instance.movieController.movieActive.collectAsState()
Row(
modifier = modifier
.background(Color(0x99000000)) // полупрозрачный чёрный
.padding(horizontal = 10.dp * scale, vertical = 4.dp * scale),
verticalAlignment = Alignment.CenterVertically,
) {
if (movieActive.value && diffMs.value != null) {
Text("${diffMs.value} мс", color = Color(0xFF999999), style = style)
Spacer(Modifier.width(6.dp * scale))
}
Text(d.time, color = Color.White, style = style)
Spacer(Modifier.width(6.dp * scale))
// Процент — цветом статуса заряда (зелёный/белый/красный), без квадратика.