diff --git a/lib/i18n/az.i18n.json b/lib/i18n/az.i18n.json index 7830c175..bf8971a4 100644 --- a/lib/i18n/az.i18n.json +++ b/lib/i18n/az.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Kanala bax", "favorites": "Sevimlilər", "reorderFavorites": "Sevimliləri yenidən sırala", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Sevimlilər yüklənə bilmədi.", "favoritesUpdateFailed": "Sevimlilər yenilənə bilmədi.", "joinSession": "Davam edən seansa qoşul", diff --git a/lib/i18n/bg.i18n.json b/lib/i18n/bg.i18n.json index fe68c2c9..bba19dfa 100644 --- a/lib/i18n/bg.i18n.json +++ b/lib/i18n/bg.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Гледай канал", "favorites": "Любими", "reorderFavorites": "Пренареди любимите", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Любимите не можаха да се заредят. Проверете връзката си и опитайте отново.", "favoritesUpdateFailed": "Любимите не можаха да бъдат обновени. Проверете връзката си и опитайте отново.", "joinSession": "Присъедини се към текуща сесия", diff --git a/lib/i18n/da.i18n.json b/lib/i18n/da.i18n.json index 07eea859..88728fb7 100644 --- a/lib/i18n/da.i18n.json +++ b/lib/i18n/da.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Se kanal", "favorites": "Favoritter", "reorderFavorites": "Omarranger favoritter", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Favoritter kunne ikke indlæses. Kontrollér forbindelsen, og prøv igen.", "favoritesUpdateFailed": "Favoritterne kunne ikke opdateres. Kontrollér forbindelsen, og prøv igen.", "joinSession": "Deltag i igangværende session", diff --git a/lib/i18n/de.i18n.json b/lib/i18n/de.i18n.json index 959f8d6e..9c0f3ef4 100644 --- a/lib/i18n/de.i18n.json +++ b/lib/i18n/de.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Kanal ansehen", "favorites": "Favoriten", "reorderFavorites": "Favoriten sortieren", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Favoriten konnten nicht geladen werden. Überprüfe deine Verbindung und versuche es erneut.", "favoritesUpdateFailed": "Favoriten konnten nicht aktualisiert werden. Prüfe deine Verbindung und versuche es erneut.", "joinSession": "Aktueller Sitzung beitreten", diff --git a/lib/i18n/en.i18n.json b/lib/i18n/en.i18n.json index 0add721f..3a2669f6 100644 --- a/lib/i18n/en.i18n.json +++ b/lib/i18n/en.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Watch Channel", "favorites": "Favorites", "reorderFavorites": "Reorder Favorites", + "noFavoriteChannels": "No favorite channels", + "noFavoriteChannelsHint": "Show all channels, then long-press a channel to add it to your favorites.", + "showAllChannels": "Show All Channels", "favoritesLoadFailed": "Could not load favorites. Check your connection and try again.", "favoritesUpdateFailed": "Could not update favorites. Check your connection and try again.", "joinSession": "Join Session in Progress", diff --git a/lib/i18n/es.i18n.json b/lib/i18n/es.i18n.json index d9083576..47961665 100644 --- a/lib/i18n/es.i18n.json +++ b/lib/i18n/es.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Ver canal", "favorites": "Favoritos", "reorderFavorites": "Reordenar favoritos", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "No se pudieron cargar los favoritos. Comprueba tu conexión e inténtalo de nuevo.", "favoritesUpdateFailed": "No se pudieron actualizar los favoritos. Comprueba tu conexión e inténtalo de nuevo.", "joinSession": "Unirse a sesión en curso", diff --git a/lib/i18n/fr.i18n.json b/lib/i18n/fr.i18n.json index 25110058..afadacae 100644 --- a/lib/i18n/fr.i18n.json +++ b/lib/i18n/fr.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Regarder la chaîne", "favorites": "Favoris", "reorderFavorites": "Réorganiser les favoris", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Impossible de charger les favoris. Vérifiez votre connexion et réessayez.", "favoritesUpdateFailed": "Impossible de mettre à jour les favoris. Vérifiez votre connexion et réessayez.", "joinSession": "Rejoindre la session en cours", diff --git a/lib/i18n/hu.i18n.json b/lib/i18n/hu.i18n.json index 60116ac6..f9429d36 100644 --- a/lib/i18n/hu.i18n.json +++ b/lib/i18n/hu.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Csatorna nézése", "favorites": "Kedvencek", "reorderFavorites": "Kedvencek rendezése", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Nem sikerült a kedvencek betöltése. Ellenőrizd a kapcsolatot és próbáld újra.", "favoritesUpdateFailed": "Nem sikerült frissíteni a kedvenceket. Ellenőrizd a kapcsolatot, majd próbáld újra.", "joinSession": "Csatlakozás a folyamatban lévő adáshoz", diff --git a/lib/i18n/it.i18n.json b/lib/i18n/it.i18n.json index 38f7b53f..d76d524d 100644 --- a/lib/i18n/it.i18n.json +++ b/lib/i18n/it.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Guarda il canale", "favorites": "Preferiti", "reorderFavorites": "Riordina i preferiti", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Impossibile caricare i preferiti. Controlla la connessione e riprova.", "favoritesUpdateFailed": "Impossibile aggiornare i preferiti. Controlla la connessione e riprova.", "joinSession": "Partecipa alla sessione in corso", diff --git a/lib/i18n/ja.i18n.json b/lib/i18n/ja.i18n.json index b00a6b84..21bcef84 100644 --- a/lib/i18n/ja.i18n.json +++ b/lib/i18n/ja.i18n.json @@ -1262,6 +1262,9 @@ "watchChannel": "チャンネルを視聴", "favorites": "お気に入り", "reorderFavorites": "お気に入りを並べ替え", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "お気に入りを読み込めませんでした。接続を確認してもう一度お試しください。", "favoritesUpdateFailed": "お気に入りを更新できませんでした。接続を確認してもう一度お試しください。", "joinSession": "進行中のセッションに参加", diff --git a/lib/i18n/kk.i18n.json b/lib/i18n/kk.i18n.json index 1facd63d..2712a099 100644 --- a/lib/i18n/kk.i18n.json +++ b/lib/i18n/kk.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Арнаны көру", "favorites": "Таңдаулылар", "reorderFavorites": "Таңдаулыларды қайта реттеу", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Таңдаулыларды жүктеу мүмкін болмады.", "favoritesUpdateFailed": "Таңдаулыларды жаңарту мүмкін болмады.", "joinSession": "Сеансқа қосылу", diff --git a/lib/i18n/ko.i18n.json b/lib/i18n/ko.i18n.json index b1199c67..268b47d7 100644 --- a/lib/i18n/ko.i18n.json +++ b/lib/i18n/ko.i18n.json @@ -1262,6 +1262,9 @@ "watchChannel": "채널 시청", "favorites": "즐겨찾기", "reorderFavorites": "즐겨찾기 순서 변경", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "즐겨찾기를 불러올 수 없습니다. 연결을 확인하고 다시 시도하세요.", "favoritesUpdateFailed": "즐겨찾기를 업데이트할 수 없습니다. 연결을 확인하고 다시 시도하세요.", "joinSession": "진행 중인 세션 참여", diff --git a/lib/i18n/nb.i18n.json b/lib/i18n/nb.i18n.json index 6602b649..a20387f6 100644 --- a/lib/i18n/nb.i18n.json +++ b/lib/i18n/nb.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Se kanal", "favorites": "Favoritter", "reorderFavorites": "Endre rekkefølge på favoritter", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Kunne ikke laste inn favoritter. Kontroller tilkoblingen og prøv på nytt.", "favoritesUpdateFailed": "Kunne ikke oppdatere favorittene. Kontroller tilkoblingen og prøv på nytt.", "joinSession": "Bli med i pågående økt", diff --git a/lib/i18n/nl.i18n.json b/lib/i18n/nl.i18n.json index 00f9be35..3e06f2a3 100644 --- a/lib/i18n/nl.i18n.json +++ b/lib/i18n/nl.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Kanaal bekijken", "favorites": "Favorieten", "reorderFavorites": "Favorieten herordenen", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Favorieten konden niet worden geladen. Controleer je verbinding en probeer het opnieuw.", "favoritesUpdateFailed": "Favorieten konden niet worden bijgewerkt. Controleer je verbinding en probeer het opnieuw.", "joinSession": "Deelnemen aan lopende sessie", diff --git a/lib/i18n/pl.i18n.json b/lib/i18n/pl.i18n.json index 248a0ee7..cc874e19 100644 --- a/lib/i18n/pl.i18n.json +++ b/lib/i18n/pl.i18n.json @@ -1286,6 +1286,9 @@ "watchChannel": "Oglądaj kanał", "favorites": "Ulubione", "reorderFavorites": "Zmień kolejność ulubionych", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Nie udało się wczytać ulubionych. Sprawdź połączenie i spróbuj ponownie.", "favoritesUpdateFailed": "Nie udało się zaktualizować ulubionych. Sprawdź połączenie i spróbuj ponownie.", "joinSession": "Dołącz do trwającej sesji", diff --git a/lib/i18n/pt.i18n.json b/lib/i18n/pt.i18n.json index 1b7e5689..3588ecf2 100644 --- a/lib/i18n/pt.i18n.json +++ b/lib/i18n/pt.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Assistir ao canal", "favorites": "Favoritos", "reorderFavorites": "Reordenar favoritos", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Não foi possível carregar os favoritos. Verifique sua conexão e tente novamente.", "favoritesUpdateFailed": "Não foi possível atualizar os favoritos. Verifique sua conexão e tente novamente.", "joinSession": "Entrar na sessão em andamento", diff --git a/lib/i18n/ru.i18n.json b/lib/i18n/ru.i18n.json index 581e1d78..6bafaacf 100644 --- a/lib/i18n/ru.i18n.json +++ b/lib/i18n/ru.i18n.json @@ -1286,6 +1286,9 @@ "watchChannel": "Смотреть канал", "favorites": "Избранное", "reorderFavorites": "Изменить порядок избранного", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Не удалось загрузить избранное. Проверьте подключение и повторите попытку.", "favoritesUpdateFailed": "Не удалось обновить избранное. Проверьте подключение и повторите попытку.", "joinSession": "Присоединиться к текущему сеансу", diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 40239216..ce6a2720 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,7 +4,7 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 22 -/// Strings: 38877 (1767 per locale) +/// Strings: 38880 (1767 per locale) // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_en.g.dart b/lib/i18n/strings_en.g.dart index 0d5f6ca0..93c4ffd8 100644 --- a/lib/i18n/strings_en.g.dart +++ b/lib/i18n/strings_en.g.dart @@ -3259,6 +3259,15 @@ class Translations$liveTv$en { /// en: 'Reorder Favorites' String get reorderFavorites => 'Reorder Favorites'; + /// en: 'No favorite channels' + String get noFavoriteChannels => 'No favorite channels'; + + /// en: 'Show all channels, then long-press a channel to add it to your favorites.' + String get noFavoriteChannelsHint => 'Show all channels, then long-press a channel to add it to your favorites.'; + + /// en: 'Show All Channels' + String get showAllChannels => 'Show All Channels'; + /// en: 'Could not load favorites. Check your connection and try again.' String get favoritesLoadFailed => 'Could not load favorites. Check your connection and try again.'; @@ -7281,6 +7290,9 @@ extension on Translations { 'liveTv.watchChannel' => 'Watch Channel', 'liveTv.favorites' => 'Favorites', 'liveTv.reorderFavorites' => 'Reorder Favorites', + 'liveTv.noFavoriteChannels' => 'No favorite channels', + 'liveTv.noFavoriteChannelsHint' => 'Show all channels, then long-press a channel to add it to your favorites.', + 'liveTv.showAllChannels' => 'Show All Channels', 'liveTv.favoritesLoadFailed' => 'Could not load favorites. Check your connection and try again.', 'liveTv.favoritesUpdateFailed' => 'Could not update favorites. Check your connection and try again.', 'liveTv.joinSession' => 'Join Session in Progress', @@ -7667,11 +7679,11 @@ extension on Translations { 'performanceOverlay.matrix' => 'Matrix', 'performanceOverlay.primaries' => 'Primaries', 'performanceOverlay.transfer' => 'Transfer', + _ => null, + } ?? switch (path) { 'performanceOverlay.renderFps' => 'Render FPS', 'performanceOverlay.displayFps' => 'Display FPS', 'performanceOverlay.avSync' => 'A/V Sync', - _ => null, - } ?? switch (path) { 'performanceOverlay.dropped' => 'Dropped', 'performanceOverlay.dvRpus' => 'DV RPUs', 'performanceOverlay.dvRpuAverage' => 'DV RPU Avg', diff --git a/lib/i18n/sv.i18n.json b/lib/i18n/sv.i18n.json index 5e9e75db..32c25bab 100644 --- a/lib/i18n/sv.i18n.json +++ b/lib/i18n/sv.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Titta på kanal", "favorites": "Favoriter", "reorderFavorites": "Ordna om favoriter", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Det gick inte att läsa in favoriter. Kontrollera anslutningen och försök igen.", "favoritesUpdateFailed": "Det gick inte att uppdatera favoriterna. Kontrollera anslutningen och försök igen.", "joinSession": "Gå med i pågående session", diff --git a/lib/i18n/tr.i18n.json b/lib/i18n/tr.i18n.json index 069f281a..b980cf61 100644 --- a/lib/i18n/tr.i18n.json +++ b/lib/i18n/tr.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Kanalı İzle", "favorites": "Favoriler", "reorderFavorites": "Favorileri Yeniden Sırala", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Favoriler yüklenemedi. Bağlantınızı kontrol edip tekrar deneyin.", "favoritesUpdateFailed": "Favoriler güncellenemedi. Bağlantınızı kontrol edip tekrar deneyin.", "joinSession": "Devam Eden Oturuma Katıl", diff --git a/lib/i18n/uz.i18n.json b/lib/i18n/uz.i18n.json index eef28eae..2ef5e778 100644 --- a/lib/i18n/uz.i18n.json +++ b/lib/i18n/uz.i18n.json @@ -1270,6 +1270,9 @@ "watchChannel": "Kanalni tomosha qilish", "favorites": "Tanlanganlar", "reorderFavorites": "Tanlanganlarni tartiblash", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "Tanlanganlarni yuklab boʻlmadi.", "favoritesUpdateFailed": "Tanlanganlarni yangilab boʻlmadi.", "joinSession": "Seansga qoʻshilish", diff --git a/lib/i18n/zh-Hant.i18n.json b/lib/i18n/zh-Hant.i18n.json index 4a52145b..9895b172 100644 --- a/lib/i18n/zh-Hant.i18n.json +++ b/lib/i18n/zh-Hant.i18n.json @@ -1262,6 +1262,9 @@ "watchChannel": "觀看頻道", "favorites": "最愛", "reorderFavorites": "重新排序最愛頻道", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "無法載入最愛頻道。請檢查網路連線後重試。", "favoritesUpdateFailed": "無法更新最愛頻道。請檢查網路連線後重試。", "joinSession": "加入進行中的「一起看」", diff --git a/lib/i18n/zh.i18n.json b/lib/i18n/zh.i18n.json index f537edad..7afebd1b 100644 --- a/lib/i18n/zh.i18n.json +++ b/lib/i18n/zh.i18n.json @@ -1262,6 +1262,9 @@ "watchChannel": "观看频道", "favorites": "收藏", "reorderFavorites": "重新排序收藏", + "noFavoriteChannels": "", + "noFavoriteChannelsHint": "", + "showAllChannels": "", "favoritesLoadFailed": "无法加载收藏。请检查网络连接后重试。", "favoritesUpdateFailed": "无法更新收藏。请检查网络连接后重试。", "joinSession": "加入正在进行的会话", diff --git a/lib/screens/livetv/live_tv_screen.dart b/lib/screens/livetv/live_tv_screen.dart index f26e9c15..ee48f0d4 100644 --- a/lib/screens/livetv/live_tv_screen.dart +++ b/lib/screens/livetv/live_tv_screen.dart @@ -53,6 +53,10 @@ class _LiveTvScreenState extends State final _whatsOnTabKey = GlobalKey(); final _recordingsTabKey = GlobalKey(); + /// Focus target for the "Show all channels" action shown when the favorites + /// filter empties the guide; lets D-pad users reach the action from the tab bar. + final _guideEmptyStateActionFocusNode = FocusNode(debugLabel: 'guide_empty_state_action'); + /// Visible tabs in the current session. Recordings tab is included only /// when at least one Live TV server has `liveTvDvr` capability. List _visibleTabs = [LiveTvTab.guide, LiveTvTab.whatsOn]; @@ -96,6 +100,10 @@ class _LiveTvScreenState extends State sourceForChannel: _sourceForChannel, ); + /// True when the favorites filter removed every loaded channel, so the guide + /// tab shows an explanatory empty state instead of a bare timeline. + bool get _guideShowsFavoritesEmptyState => _channels.isNotEmpty && _filteredChannels.isEmpty; + String _liveServerScopeKey(LiveTvServerInfo serverInfo) => '${serverInfo.serverId}\u0000${serverInfo.dvrKey}'; _FavoriteScope? _favoriteScopeForChannel(LiveTvChannel channel) { @@ -138,6 +146,7 @@ class _LiveTvScreenState extends State _guideTabFocusNode.dispose(); _whatsOnTabFocusNode.dispose(); _recordingsTabFocusNode.dispose(); + _guideEmptyStateActionFocusNode.dispose(); disposeTabNavigation(); super.dispose(); } @@ -496,6 +505,18 @@ class _LiveTvScreenState extends State }); } + /// Clears the favorites filter from the guide's empty state. When the action + /// button owned the focus (TV/D-pad), hand focus to the guide content that + /// replaces it so focus is not dropped. + void _showAllChannelsFromEmptyState() { + final hadFocus = _guideEmptyStateActionFocusNode.hasFocus; + _toggleFavoritesFilter(); + if (!hadFocus) return; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) _focusCurrentTab(); + }); + } + void _toggleFavorite(LiveTvChannel channel) { _enqueueFavoriteMutation(() { final source = _sourceForChannel(channel); @@ -597,7 +618,12 @@ class _LiveTvScreenState extends State if (tabController.index < _visibleTabs.length) { switch (_visibleTabs[tabController.index]) { case LiveTvTab.guide: - _guideTabKey.currentState?.focusContent(); + final guideState = _guideTabKey.currentState; + if (guideState != null) { + guideState.focusContent(); + } else if (_guideShowsFavoritesEmptyState && _guideEmptyStateActionFocusNode.context != null) { + _guideEmptyStateActionFocusNode.requestFocus(); + } case LiveTvTab.whatsOn: _whatsOnTabKey.currentState?.focusFirstHub(); case LiveTvTab.recordings: @@ -683,14 +709,27 @@ class _LiveTvScreenState extends State Widget _buildTabContent(LiveTvTab tab, List guideChannels) { return switch (tab) { - LiveTvTab.guide => GuideTab( - key: _guideTabKey, - channels: guideChannels, - isFavoriteChannel: _isFavoriteChannel, - onToggleFavorite: _toggleFavorite, - onNavigateUp: focusTabBar, - onBack: onTabBarBack, - ), + LiveTvTab.guide => + guideChannels.isEmpty && _channels.isNotEmpty + ? EmptyStateWidget( + icon: Symbols.star_outline_rounded, + message: t.liveTv.noFavoriteChannels, + subtitle: t.liveTv.noFavoriteChannelsHint, + actionLabel: t.liveTv.showAllChannels, + actionIcon: Symbols.list_rounded, + actionFocusNode: _guideEmptyStateActionFocusNode, + onAction: _showAllChannelsFromEmptyState, + onActionNavigateUp: focusTabBar, + onActionBack: onTabBarBack, + ) + : GuideTab( + key: _guideTabKey, + channels: guideChannels, + isFavoriteChannel: _isFavoriteChannel, + onToggleFavorite: _toggleFavorite, + onNavigateUp: focusTabBar, + onBack: onTabBarBack, + ), LiveTvTab.whatsOn => WhatsOnTab( key: _whatsOnTabKey, channels: _channels, diff --git a/test/screens/livetv/live_tv_screen_test.dart b/test/screens/livetv/live_tv_screen_test.dart index 0ab672ca..aa56c054 100644 --- a/test/screens/livetv/live_tv_screen_test.dart +++ b/test/screens/livetv/live_tv_screen_test.dart @@ -35,7 +35,7 @@ void main() { await settings.write(SettingsService.liveTvDefaultFavorites, true); }); - testWidgets('loaded empty favorites produces an empty Guide after preserving channels during load', (tester) async { + testWidgets('loaded empty favorites shows the favorites empty state and can restore all channels', (tester) async { final harness = await _pumpLiveTvScreen(tester); addTearDown(() async { await tester.pumpWidget(const SizedBox.shrink()); @@ -48,8 +48,31 @@ void main() { harness.liveTv.favorites.complete(const []); await tester.pumpAndSettle(); - expect(find.byIcon(Symbols.star_rounded), findsOneWidget); - expect(_guideChannels(tester), isEmpty); + expect(find.byType(GuideTab), findsNothing); + expect(find.text(t.liveTv.noFavoriteChannels), findsOneWidget); + expect(find.text(t.liveTv.showAllChannels), findsOneWidget); + + await tester.tap(find.text(t.liveTv.showAllChannels)); + await tester.pumpAndSettle(); + + expect(find.text(t.liveTv.noFavoriteChannels), findsNothing); + expect(find.byIcon(Symbols.star_outline_rounded), findsOneWidget); + expect(_guideChannels(tester).map((channel) => channel.key), ['channel-a']); + }); + + testWidgets('favorites matching no loaded channel show the favorites empty state', (tester) async { + final harness = await _pumpLiveTvScreen(tester); + addTearDown(() async { + await tester.pumpWidget(const SizedBox.shrink()); + harness.dispose(); + }); + + harness.liveTv.favorites.complete([FavoriteChannel(id: 'channel-gone', source: 'server://server-a/provider-a')]); + await tester.pumpAndSettle(); + + expect(find.byType(GuideTab), findsNothing); + expect(find.text(t.liveTv.noFavoriteChannels), findsOneWidget); + expect(find.text(t.liveTv.showAllChannels), findsOneWidget); }); testWidgets('refresh keeps the favorites filter narrow while favorites reload', (tester) async {