fix(app-phone): watch при перезапуске очков — guard по реальному состоянию (shouldSkipReWatch)
Штатный сценарий (подтверждён на железе): очки перезапустились при живом телефоне — audioSync.isActive остаётся true от прошлого просмотра и блокировал watch («пропущено: аудио-плеер уже активен») до перезапуска телефона. - shouldSkipReWatch(playing, positionMs) = playing && positionMs > 0: повторный тап пропускается только если очки реально играют; иначе audioSync.stop() и новый watch - Обрыв-сценарий не затронут (позиция>0 → guard пропускает, resume) - Тесты 70/0 (3 новых); железо: перезапуск очков → тап «Смотреть» → просмотр с 0 + звук синхронен (diff 145)
This commit is contained in:
@@ -130,13 +130,20 @@ fun DetailsScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onWatch() {
|
fun onWatch() {
|
||||||
// звук уже играет — повторный тап не должен пересоздавать аудио-плеер.
|
|
||||||
// state.playing в guard НЕ включаем: он остаётся true после рестарта телефона
|
|
||||||
// (очки продолжают играть), когда аудио-плеер ещё не создан, и блокировал бы запуск звука.
|
|
||||||
if (app.audioSync.isActive) {
|
if (app.audioSync.isActive) {
|
||||||
log("watch", "пропущено: аудио-плеер уже активен (audioSync.isActive=true)")
|
// Очки реально играют (позиция растёт) — повторный тап не должен
|
||||||
scope.launch { snackbar.showSnackbar("уже играет") }
|
// пересоздавать звук. Если очки перезапустились/на паузе (позиция 0
|
||||||
return
|
// или не играют) — старый аудио-плеер мёртв: сбрасываем и запускаем
|
||||||
|
// новый watch (звук пересоздастся с позиции очков).
|
||||||
|
val playing = app.state.playing
|
||||||
|
val positionMs = app.server.hub.positionMs.value ?: 0L
|
||||||
|
if (shouldSkipReWatch(playing, positionMs)) {
|
||||||
|
log("watch", "пропущено: аудио-плеер уже активен и очки играют (pos=$positionMs)")
|
||||||
|
scope.launch { snackbar.showSnackbar("уже играет") }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log("watch", "очки не играют (playing=$playing, pos=$positionMs) — сбрасываю аудио-плеер")
|
||||||
|
app.audioSync.stop()
|
||||||
}
|
}
|
||||||
if (!glassesFully) {
|
if (!glassesFully) {
|
||||||
log("watch", "пропущено: контент не скачан на очки (glassesFully=false)")
|
log("watch", "пропущено: контент не скачан на очки (glassesFully=false)")
|
||||||
@@ -590,6 +597,14 @@ private fun ConversionStatus(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guard повторного тапа «Смотреть на очках» при живом аудио-плеере: пропускаем
|
||||||
|
* перезапуск звука только если очки реально играют (playing=true и позиция >0).
|
||||||
|
* Очки на паузе или перезапустились (позиция 0) — старый плеер мёртв, нужно сбросить и создать заново.
|
||||||
|
*/
|
||||||
|
internal fun shouldSkipReWatch(playing: Boolean, positionMs: Long): Boolean =
|
||||||
|
playing && positionMs > 0
|
||||||
|
|
||||||
private fun detailMeta(item: JellyfinItem): String {
|
private fun detailMeta(item: JellyfinItem): String {
|
||||||
val parts = mutableListOf<String>()
|
val parts = mutableListOf<String>()
|
||||||
when (item.Type) {
|
when (item.Type) {
|
||||||
|
|||||||
@@ -2,9 +2,26 @@ package pw.binom.viewmate.phone.ui
|
|||||||
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFalse
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class ComponentsTest {
|
class ComponentsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldSkipReWatchWhenPlayingWithPosition() {
|
||||||
|
assertTrue(shouldSkipReWatch(playing = true, positionMs = 42_000), "очки играют и позиция >0 — повторный тап пропускаем")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldNotSkipReWatchWhenNotPlaying() {
|
||||||
|
assertFalse(shouldSkipReWatch(playing = false, positionMs = 42_000), "очки не играют — сбрасываем плеер и перезапускаем watch")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldNotSkipReWatchWhenPositionZero() {
|
||||||
|
assertFalse(shouldSkipReWatch(playing = true, positionMs = 0), "позиция 0 — очки перезапустились/на паузе, старый плеер мёртв")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun bytesToSizeKilobytes() {
|
fun bytesToSizeKilobytes() {
|
||||||
assertEquals("512 КБ", bytesToSize(512 * 1024L))
|
assertEquals("512 КБ", bytesToSize(512 * 1024L))
|
||||||
|
|||||||
Reference in New Issue
Block a user