diff --git a/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/CatalogScreen.kt b/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/CatalogScreen.kt index d179291..3e81b24 100644 --- a/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/CatalogScreen.kt +++ b/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/CatalogScreen.kt @@ -43,6 +43,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import pw.binom.viewmate.core.media.JellyfinItem import pw.binom.viewmate.core.media.MirrorJob +import pw.binom.viewmate.core.protocol.DownloadPhase import pw.binom.viewmate.phone.PhoneApp /** Вкладки каталога: Фильмы / Сериалы / Папки. */ @@ -247,6 +248,10 @@ fun CatalogScreen( } val downloaded by app.state.downloadedFlow.collectAsState() val localDownloaded by app.downloadManager.downloadedIds.collectAsState() + // Статус видео на очках: скачанные itemId (свежий GlassesStatus) + живой прогресс + // DownloadProgress (видео очки качают сами, звук — телефон). + val glassesDownloadedIds by app.server.hub.downloadedItemIds.collectAsState() + val glassesDownloads by app.server.hub.glassesDownloads.collectAsState() // подтянуть список, когда появился пользователь Jellyfin LaunchedEffect(userId) { @@ -271,6 +276,7 @@ fun CatalogScreen( modifier = Modifier.fillMaxSize(), ) { items(state.items, key = { it.Id }) { item -> + val videoProgress = glassesDownloads[item.Id]?.get("video.mkv") ItemCard( item = item, posterUrl = posterUrlOrNull(app, item), @@ -279,6 +285,9 @@ fun CatalogScreen( job = state.mirrors[item.Id], downloaded = downloaded, localDownloaded = localDownloaded, + glassesDownloading = videoProgress?.phase == DownloadPhase.DOWNLOADING, + glassesDownloadingPercent = videoProgress?.percent, + glassesDownloaded = item.Id in glassesDownloadedIds, ), onClick = { when { diff --git a/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/Components.kt b/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/Components.kt index 58138e7..59c693d 100644 --- a/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/Components.kt +++ b/app-phone/src/main/kotlin/pw/binom/viewmate/phone/ui/Components.kt @@ -77,11 +77,13 @@ fun BottomNavBar(current: Screen, onSelect: (Screen) -> Unit) { data class MirrorBadge(val text: String, val bg: Color, val fg: Color) /** - * Статус зеркала элемента: + * Статус зеркала элемента (коротко для бейджа каталога): * - ⟳ N% — конвертируется; - * - ↓ часть — что-то скачано локально (телефон) или на очки; - * - ✓ — зеркало готово; - * - ✗ — ошибка; + * - ✗ — ошибка конвертации; + * - ↓ N% — видео скачивается на очки; + * - ▶ — можно смотреть (видео уже на очках); + * - ✓ — зеркало готово (ещё не на очках); + * - ↓ часть — скачано что-то локально (телефон) или на очки; * - нет — ничего нет. */ fun mirrorBadge( @@ -89,6 +91,9 @@ fun mirrorBadge( job: MirrorJob?, downloaded: Map, localDownloaded: Set, + glassesDownloading: Boolean = false, + glassesDownloadingPercent: Int? = null, + glassesDownloaded: Boolean = false, ): MirrorBadge { val status = job?.status val hasLocal = localDownloaded.contains(itemId) @@ -102,6 +107,16 @@ fun mirrorBadge( status == "failed" || status == "error" -> MirrorBadge("✗", PhoneRed, Color.White) + // Видео уже летит на очки — конкретнее «✓ готово» + glassesDownloading -> MirrorBadge( + "↓ ${glassesDownloadingPercent ?: 0}%", + PhoneBlue, + PhoneBlueText, + ) + + // Видео на очках — можно смотреть + glassesDownloaded -> MirrorBadge("▶", PhoneGreen, PhoneGreenText) + status == "done" -> MirrorBadge("✓", PhoneGreen, PhoneGreenText) hasLocal || hasAny -> MirrorBadge("↓ часть", PhoneBlue, PhoneBlueText)