feat(settings): add appearance toggle to hide the Explore tab
The Explore tab appears for every Plex-backed profile because the Plex Discover catalog source connects implicitly, with no way to opt out short of a Jellyfin-only profile. Add a Show Explore Tab switch to Appearance > Navigation that hides the tab in the bottom navigation and side rail. UI-only: catalog sources stay connected so watchlist surfaces keep working while the tab is hidden. close #1844
This commit is contained in:
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Naviqasiya paneli yazılarını göstər",
|
||||
"showNavBarLabelsDescription": "Naviqasiya paneli ikonlarının altında mətni göstər",
|
||||
"startupSection": "Başlanğıc bölməsi",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Canlı TV-də sevimli kanalları defolt et",
|
||||
"liveTvDefaultFavoritesDescription": "Canlı TV açıldıqda yalnız sevimli kanalları göstər",
|
||||
"display": "Ekran",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Показвай етикети в навигационната лента",
|
||||
"showNavBarLabelsDescription": "Показвай текстови етикети под иконите в навигационната лента",
|
||||
"startupSection": "Начален раздел",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "По подразбиране към любими канали",
|
||||
"liveTvDefaultFavoritesDescription": "Показвай само любими канали при отваряне на телевизия на живо",
|
||||
"display": "Дисплей",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Vis tekst på navigationslinjen",
|
||||
"showNavBarLabelsDescription": "Vis tekst under ikonerne på navigationslinjen",
|
||||
"startupSection": "Startsektion",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Vis favoritkanaler som standard",
|
||||
"liveTvDefaultFavoritesDescription": "Vis kun favoritkanaler ved åbning af Live TV",
|
||||
"display": "Skærm",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Navigationsleisten-Beschriftungen anzeigen",
|
||||
"showNavBarLabelsDescription": "Textbeschriftungen unter den Symbolen der Navigationsleiste anzeigen",
|
||||
"startupSection": "Startbereich",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Standardmäßig Favoritenkanäle",
|
||||
"liveTvDefaultFavoritesDescription": "Beim Öffnen von Live TV nur Favoritenkanäle anzeigen",
|
||||
"display": "Anzeige",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Show Navigation Bar Labels",
|
||||
"showNavBarLabelsDescription": "Display text labels under navigation bar icons",
|
||||
"startupSection": "Startup Section",
|
||||
"showExploreTab": "Show Explore Tab",
|
||||
"showExploreTabDescription": "Display the Explore tab with content from Plex Discover and connected trackers",
|
||||
"liveTvDefaultFavorites": "Default to Favorite Channels",
|
||||
"liveTvDefaultFavoritesDescription": "Show only favorite channels when opening Live TV",
|
||||
"display": "Display",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Mostrar etiquetas de la barra de navegación",
|
||||
"showNavBarLabelsDescription": "Mostrar etiquetas de texto bajo los iconos de la barra de navegación",
|
||||
"startupSection": "Sección de inicio",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Canales favoritos por defecto",
|
||||
"liveTvDefaultFavoritesDescription": "Mostrar solo canales favoritos al abrir TV en vivo",
|
||||
"display": "Pantalla",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Afficher les libellés de la barre de navigation",
|
||||
"showNavBarLabelsDescription": "Afficher les libellés sous les icônes de la barre de navigation",
|
||||
"startupSection": "Section de démarrage",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Chaînes favorites par défaut",
|
||||
"liveTvDefaultFavoritesDescription": "Afficher uniquement les chaînes favorites à l'ouverture de la TV en direct",
|
||||
"display": "Affichage",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Navigációs sáv címkéinek megjelenítése",
|
||||
"showNavBarLabelsDescription": "Szöveges címkék megjelenítése a navigációs sáv ikonjai alatt",
|
||||
"startupSection": "Indítási oldal",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Kedvenc csatornák alapértelmezés szerint",
|
||||
"liveTvDefaultFavoritesDescription": "Csak a kedvenc csatornák megjelenítése az Élő TV megnyitásakor",
|
||||
"display": "Kijelző",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Mostra le etichette della barra di navigazione",
|
||||
"showNavBarLabelsDescription": "Mostra le etichette di testo sotto le icone della barra di navigazione",
|
||||
"startupSection": "Sezione di avvio",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Apri sui canali preferiti",
|
||||
"liveTvDefaultFavoritesDescription": "Mostra solo i canali preferiti quando apri la TV in diretta",
|
||||
"display": "Schermo",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "ナビゲーションバーのラベルを表示",
|
||||
"showNavBarLabelsDescription": "ナビゲーションバーのアイコンの下にテキストラベルを表示",
|
||||
"startupSection": "起動時のセクション",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "お気に入りチャンネルをデフォルトに",
|
||||
"liveTvDefaultFavoritesDescription": "ライブTVを開いたときにお気に入りチャンネルのみ表示",
|
||||
"display": "ディスプレイ",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Навигация панелінің мәтіндерін көрсету",
|
||||
"showNavBarLabelsDescription": "Навигация белгішелерінің астында мәтінді көрсету",
|
||||
"startupSection": "Бастапқы бөлім",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Тікелей TV-де таңдаулы арналарды әдепкі ету",
|
||||
"liveTvDefaultFavoritesDescription": "Тікелей TV ашылғанда тек таңдаулы арналарды көрсету",
|
||||
"display": "Дисплей",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "내비게이션 바 라벨 표시",
|
||||
"showNavBarLabelsDescription": "내비게이션 바 아이콘 아래에 텍스트 라벨을 표시합니다",
|
||||
"startupSection": "시작 섹션",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "즐겨찾기 채널 기본 설정",
|
||||
"liveTvDefaultFavoritesDescription": "라이브 TV를 열 때 즐겨찾기 채널만 표시",
|
||||
"display": "디스플레이",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Vis etiketter i navigasjonsfeltet",
|
||||
"showNavBarLabelsDescription": "Vis tekstetiketter under ikonene i navigasjonsfeltet",
|
||||
"startupSection": "Startseksjon",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Vis favorittkanaler som standard",
|
||||
"liveTvDefaultFavoritesDescription": "Vis bare favorittkanaler når du åpner Direkte-TV",
|
||||
"display": "Skjerm",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Labels op navigatiebalk tonen",
|
||||
"showNavBarLabelsDescription": "Tekstlabels onder de pictogrammen op de navigatiebalk weergeven",
|
||||
"startupSection": "Opstartsectie",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Standaard favoriete zenders",
|
||||
"liveTvDefaultFavoritesDescription": "Toon alleen favoriete zenders bij het openen van Live TV",
|
||||
"display": "Weergave",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Pokaż etykiety paska nawigacji",
|
||||
"showNavBarLabelsDescription": "Wyświetl tekstowe etykiety pod ikonami paska nawigacji",
|
||||
"startupSection": "Sekcja startowa",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Domyślnie ulubione kanały",
|
||||
"liveTvDefaultFavoritesDescription": "Pokaż tylko ulubione kanały po otwarciu telewizji na żywo",
|
||||
"display": "Ekran",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Mostrar Rótulos da Barra de Navegação",
|
||||
"showNavBarLabelsDescription": "Exibir rótulos de texto sob os ícones da barra de navegação",
|
||||
"startupSection": "Seção inicial",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Canais favoritos por padrão",
|
||||
"liveTvDefaultFavoritesDescription": "Mostrar apenas os canais favoritos ao abrir a TV ao vivo",
|
||||
"display": "Tela",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Показывать подписи панели навигации",
|
||||
"showNavBarLabelsDescription": "Отображать текстовые подписи под иконками панели навигации",
|
||||
"startupSection": "Начальный раздел",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Избранные каналы по умолчанию",
|
||||
"liveTvDefaultFavoritesDescription": "Показывать только избранные каналы при открытии ТВ",
|
||||
"display": "Экран",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 22
|
||||
/// Strings: 38354 (1743 per locale)
|
||||
/// Strings: 38356 (1743 per locale)
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
||||
@@ -1047,6 +1047,12 @@ class Translations$settings$en {
|
||||
/// en: 'Startup Section'
|
||||
String get startupSection => 'Startup Section';
|
||||
|
||||
/// en: 'Show Explore Tab'
|
||||
String get showExploreTab => 'Show Explore Tab';
|
||||
|
||||
/// en: 'Display the Explore tab with content from Plex Discover and connected trackers'
|
||||
String get showExploreTabDescription => 'Display the Explore tab with content from Plex Discover and connected trackers';
|
||||
|
||||
/// en: 'Default to Favorite Channels'
|
||||
String get liveTvDefaultFavorites => 'Default to Favorite Channels';
|
||||
|
||||
@@ -6384,6 +6390,8 @@ extension on Translations {
|
||||
'settings.showNavBarLabels' => 'Show Navigation Bar Labels',
|
||||
'settings.showNavBarLabelsDescription' => 'Display text labels under navigation bar icons',
|
||||
'settings.startupSection' => 'Startup Section',
|
||||
'settings.showExploreTab' => 'Show Explore Tab',
|
||||
'settings.showExploreTabDescription' => 'Display the Explore tab with content from Plex Discover and connected trackers',
|
||||
'settings.liveTvDefaultFavorites' => 'Default to Favorite Channels',
|
||||
'settings.liveTvDefaultFavoritesDescription' => 'Show only favorite channels when opening Live TV',
|
||||
'settings.display' => 'Display',
|
||||
@@ -6583,10 +6591,10 @@ extension on Translations {
|
||||
'rateSheet.saved' => 'Saved',
|
||||
'rateSheet.notAvailable' => 'No match found',
|
||||
'rateSheet.noConnectedServices' => 'Connect a service in Settings to rate there.',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, movie',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, TV show',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, movie',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, TV show',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
'accessibility.mediaCardSeason' => ({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}',
|
||||
'accessibility.mediaCardWatched' => 'watched',
|
||||
@@ -7097,10 +7105,10 @@ extension on Translations {
|
||||
'explore.stats.viewersAllTime' => ({required Object n}) => '${n} viewers',
|
||||
'explore.stats.planning' => ({required Object n}) => '${n} planning to watch',
|
||||
'explore.stats.favorited' => ({required Object n}) => '${n} favorites',
|
||||
'explore.stats.dropRate' => ({required Object percent}) => '${percent} dropped it',
|
||||
'explore.stats.comments' => ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, one: '${n} comment', other: '${n} comments', ),
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'explore.stats.dropRate' => ({required Object percent}) => '${percent} dropped it',
|
||||
'explore.stats.comments' => ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, one: '${n} comment', other: '${n} comments', ),
|
||||
'explore.stats.votes' => ({required Object n}) => '${n} votes',
|
||||
'explore.stats.watching' => ({required Object n}) => '${n} watching it',
|
||||
'explore.stats.completed' => ({required Object n}) => '${n} completed',
|
||||
@@ -7611,10 +7619,10 @@ extension on Translations {
|
||||
'externalPlayer.title' => 'External Player',
|
||||
'externalPlayer.useExternalPlayer' => 'Use External Player',
|
||||
'externalPlayer.useExternalPlayerDescription' => 'Open videos in another app',
|
||||
'externalPlayer.selectPlayer' => 'Select Player',
|
||||
'externalPlayer.customPlayers' => 'Custom Players',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.selectPlayer' => 'Select Player',
|
||||
'externalPlayer.customPlayers' => 'Custom Players',
|
||||
'externalPlayer.systemDefault' => 'System Default',
|
||||
'externalPlayer.addCustomPlayer' => 'Add Custom Player',
|
||||
'externalPlayer.playerName' => 'Player Name',
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Visa navigeringsfältets etiketter",
|
||||
"showNavBarLabelsDescription": "Visa textetiketter under navigeringsfältets ikoner",
|
||||
"startupSection": "Startsida",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Öppna med favoriter",
|
||||
"liveTvDefaultFavoritesDescription": "Visa endast favoritkanaler när Live-TV öppnas",
|
||||
"display": "Skärm",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Gezinme Çubuğu Etiketlerini Göster",
|
||||
"showNavBarLabelsDescription": "Gezinme çubuğu simgelerinin altında metin etiketlerini göster",
|
||||
"startupSection": "Başlangıç Bölümü",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Canlı TV'de Favorileri Varsayılan Yap",
|
||||
"liveTvDefaultFavoritesDescription": "Canlı TV açıldığında yalnızca favori kanalları göster",
|
||||
"display": "Ekran",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "Navigatsiya paneli matnlarini koʻrsatish",
|
||||
"showNavBarLabelsDescription": "Navigatsiya belgilarining ostida matnni koʻrsatish",
|
||||
"startupSection": "Boshlangʻich boʻlim",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "Jonli TV-da tanlangan kanallarni standart qilish",
|
||||
"liveTvDefaultFavoritesDescription": "Jonli TV ochilganda faqat tanlangan kanallarni koʻrsatish",
|
||||
"display": "Displey",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "顯示導覽列標籤",
|
||||
"showNavBarLabelsDescription": "在導覽列圖示下方顯示文字標籤",
|
||||
"startupSection": "啟動頁面",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "預設顯示最愛頻道",
|
||||
"liveTvDefaultFavoritesDescription": "開啟直播電視時僅顯示最愛頻道",
|
||||
"display": "顯示器",
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
"showNavBarLabels": "显示导航栏标签",
|
||||
"showNavBarLabelsDescription": "在导航栏图标下方显示文字标签",
|
||||
"startupSection": "启动页面",
|
||||
"showExploreTab": "",
|
||||
"showExploreTabDescription": "",
|
||||
"liveTvDefaultFavorites": "默认显示收藏频道",
|
||||
"liveTvDefaultFavoritesDescription": "打开直播电视时仅显示收藏频道",
|
||||
"display": "显示",
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'dart:io' show Platform, exit;
|
||||
export '../navigation/main_screen_scope.dart'
|
||||
show MainScreenFocusScope, MainScreenScopeAspect, SideNavigationBleedBuilder;
|
||||
|
||||
import 'package:flutter/foundation.dart' show ValueListenable;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart'
|
||||
show HardwareKeyboard, KeyDownEvent, KeyRepeatEvent, KeyUpEvent, LogicalKeyboardKey;
|
||||
@@ -246,6 +247,7 @@ class _MainScreenState extends State<MainScreen>
|
||||
OfflineModeProvider? _offlineModeProvider;
|
||||
MultiServerProvider? _multiServerProvider;
|
||||
CatalogSourcesProvider? _catalogSourcesProvider;
|
||||
ValueListenable<bool>? _showExploreTabListenable;
|
||||
RouteObserver<PageRoute<dynamic>>? _profileRouteObserver;
|
||||
bool _lastHasLiveTv = false;
|
||||
bool _lastHasExplore = false;
|
||||
@@ -347,10 +349,14 @@ class _MainScreenState extends State<MainScreen>
|
||||
_lastHasLiveTv = false;
|
||||
}
|
||||
try {
|
||||
_lastHasExplore = context.read<CatalogSourcesProvider>().hasAnySource;
|
||||
_lastHasExplore = context.read<CatalogSourcesProvider>().hasAnySource && _showExploreTabSetting;
|
||||
} catch (_) {
|
||||
_lastHasExplore = false;
|
||||
}
|
||||
// Re-evaluate Explore tab visibility when the appearance toggle flips
|
||||
// mid-session; the catalog-sources listener covers source changes.
|
||||
_showExploreTabListenable = SettingsService.instanceOrNull?.listenable(SettingsService.showExploreTab);
|
||||
_showExploreTabListenable?.addListener(_handleCatalogSourcesChanged);
|
||||
_currentTab = _defaultTabForMode(_isOffline);
|
||||
_lastOnlineTabId = _isOffline ? null : NavigationTabId.discover;
|
||||
_autoSwitchedToDownloads = _isOffline && _currentTab == NavigationTabId.downloads;
|
||||
@@ -887,6 +893,7 @@ class _MainScreenState extends State<MainScreen>
|
||||
_offlineModeProvider?.removeListener(_handleOfflineStatusChanged);
|
||||
_multiServerProvider?.removeListener(_handleLiveTvChanged);
|
||||
_catalogSourcesProvider?.removeListener(_handleCatalogSourcesChanged);
|
||||
_showExploreTabListenable?.removeListener(_handleCatalogSourcesChanged);
|
||||
if (_bindingSettleListener != null) {
|
||||
_activeProfileForListener?.removeListener(_bindingSettleListener!);
|
||||
}
|
||||
@@ -1078,8 +1085,10 @@ class _MainScreenState extends State<MainScreen>
|
||||
}
|
||||
}
|
||||
|
||||
bool get _showExploreTabSetting => SettingsService.instanceOrNull?.read(SettingsService.showExploreTab) ?? true;
|
||||
|
||||
void _handleCatalogSourcesChanged() {
|
||||
final hasExplore = _catalogSourcesProvider?.hasAnySource ?? false;
|
||||
final hasExplore = (_catalogSourcesProvider?.hasAnySource ?? false) && _showExploreTabSetting;
|
||||
if (hasExplore == _lastHasExplore) return;
|
||||
_lastHasExplore = hasExplore;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:provider/provider.dart';
|
||||
|
||||
import '../../i18n/app_locale_utils.dart';
|
||||
import '../../i18n/strings.g.dart';
|
||||
import '../../providers/catalog_sources_provider.dart';
|
||||
import '../../providers/multi_server_provider.dart';
|
||||
import '../../providers/theme_provider.dart';
|
||||
import '../../profiles/active_profile_provider.dart';
|
||||
@@ -29,9 +30,12 @@ class AppearanceSettingsScreen extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Watched at build level so the tile can be excluded with a plain `if` —
|
||||
// Watched at build level so the tiles can be excluded with a plain `if` —
|
||||
// a child that renders SizedBox.shrink() would corrupt the group corners.
|
||||
final hasMultipleProfiles = context.watch<ActiveProfileProvider>().hasMultipleProfiles;
|
||||
// Nullable watch: hosts without the profile session scope (tests) simply
|
||||
// never show the Explore toggle, mirroring the tab's own visibility.
|
||||
final hasExplore = context.watch<CatalogSourcesProvider?>()?.hasAnySource ?? false;
|
||||
return SettingsPage(
|
||||
title: Text(t.settings.appearance),
|
||||
children: [
|
||||
@@ -112,6 +116,13 @@ class AppearanceSettingsScreen extends StatelessWidget {
|
||||
title: t.settings.navigation,
|
||||
children: [
|
||||
_startupSectionSelector(),
|
||||
if (hasExplore)
|
||||
SettingSwitchTile(
|
||||
pref: SettingsService.showExploreTab,
|
||||
icon: Symbols.explore_rounded,
|
||||
title: t.settings.showExploreTab,
|
||||
subtitle: t.settings.showExploreTabDescription,
|
||||
),
|
||||
if (Platform.isAndroid || PlatformDetector.isDesktopOS())
|
||||
SettingSwitchTile(
|
||||
pref: SettingsService.forceTvMode,
|
||||
|
||||
@@ -444,6 +444,11 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
values: NavigationTabId.values,
|
||||
defaultValue: NavigationTabId.discover,
|
||||
);
|
||||
|
||||
/// Whether the Explore tab (Plex Discover / tracker catalog rows) is shown
|
||||
/// at all. UI-only: catalog sources stay connected so watchlist surfaces
|
||||
/// keep working while the tab is hidden.
|
||||
static const showExploreTab = BoolPref('show_explore_tab', defaultValue: true);
|
||||
static const alwaysKeepSidebarOpen = BoolPref('always_keep_sidebar_open');
|
||||
static const showUnwatchedCount = BoolPref('show_unwatched_count', defaultValue: true);
|
||||
static const showEpisodeNumberOnCards = BoolPref('show_episode_number_on_cards', defaultValue: true);
|
||||
@@ -920,6 +925,7 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
autoPlayNextEpisode,
|
||||
useExoPlayer,
|
||||
startupSection,
|
||||
showExploreTab,
|
||||
alwaysKeepSidebarOpen,
|
||||
showUnwatchedCount,
|
||||
showEpisodeNumberOnCards,
|
||||
|
||||
@@ -652,7 +652,7 @@ class SideNavigationRailState extends State<SideNavigationRail> with MountedSetS
|
||||
final hasLiveTv = context.watch<MultiServerProvider>().hasLiveTv;
|
||||
// Nullable watch: rail tests (and any host without the profile session
|
||||
// scope) simply never show the Explore item.
|
||||
final hasExplore = context.watch<CatalogSourcesProvider?>()?.hasAnySource ?? false;
|
||||
final hasExploreSource = context.watch<CatalogSourcesProvider?>()?.hasAnySource ?? false;
|
||||
// Nullable watch: rail tests (and any host without the profile session
|
||||
// scope) simply never show the Now Playing item. TV-only — it is the
|
||||
// way back into the now-playing screen there; desktop already has the
|
||||
@@ -660,14 +660,16 @@ class SideNavigationRailState extends State<SideNavigationRail> with MountedSetS
|
||||
final musicService = context.watch<MusicPlaybackService?>();
|
||||
final nowPlayingTrack = widget.isOfflineMode || !PlatformDetector.isTV() ? null : musicService?.currentTrack;
|
||||
|
||||
// Listen to fullscreen + groupLibrariesByServer setting so the rail
|
||||
// rebuilds when the user toggles "Group libraries by server" in Appearance.
|
||||
// Listen to fullscreen + the groupLibrariesByServer / showExploreTab
|
||||
// settings so the rail rebuilds when they are toggled in Appearance.
|
||||
return ListenableBuilder(
|
||||
listenable: Listenable.merge([
|
||||
FullscreenStateManager(),
|
||||
SettingsService.instance.listenable(SettingsService.groupLibrariesByServer),
|
||||
SettingsService.instance.listenable(SettingsService.showExploreTab),
|
||||
]),
|
||||
builder: (context, _) {
|
||||
final hasExplore = hasExploreSource && SettingsService.instance.read(SettingsService.showExploreTab);
|
||||
// Server grouping: only when multi-server AND the user-facing toggle is on.
|
||||
final groupByServerSetting = SettingsService.instance.read(SettingsService.groupLibrariesByServer);
|
||||
final showServerHeaders = serverIds.length > 1 && groupByServerSetting;
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:plezy/media/media_backend.dart';
|
||||
import 'package:plezy/media/media_kind.dart';
|
||||
import 'package:plezy/media/media_library.dart';
|
||||
import 'package:plezy/navigation/navigation_tabs.dart';
|
||||
import 'package:plezy/providers/catalog_sources_provider.dart';
|
||||
import 'package:plezy/providers/hidden_libraries_provider.dart';
|
||||
import 'package:plezy/providers/libraries_provider.dart';
|
||||
import 'package:plezy/providers/multi_server_provider.dart';
|
||||
@@ -25,6 +26,12 @@ import '../test_helpers/multi_server_fixtures.dart';
|
||||
import '../test_helpers/prefs.dart';
|
||||
import '../test_helpers/theme.dart';
|
||||
|
||||
/// Minimal source-bearing stand-in: the rail only reads [hasAnySource].
|
||||
class _FakeCatalogSourcesProvider extends CatalogSourcesProvider {
|
||||
@override
|
||||
bool get hasAnySource => true;
|
||||
}
|
||||
|
||||
MediaLibrary _library({
|
||||
required String id,
|
||||
required String title,
|
||||
@@ -68,6 +75,7 @@ Future<void> _pumpBasicRail(
|
||||
bool isSidebarFocused = false,
|
||||
bool alwaysExpanded = false,
|
||||
double? height,
|
||||
CatalogSourcesProvider? catalogSources,
|
||||
}) async {
|
||||
await SettingsService.getInstance();
|
||||
|
||||
@@ -102,6 +110,7 @@ Future<void> _pumpBasicRail(
|
||||
ChangeNotifierProvider<LibrariesProvider>.value(value: librariesProvider),
|
||||
ChangeNotifierProvider<HiddenLibrariesProvider>.value(value: hiddenLibrariesProvider),
|
||||
ChangeNotifierProvider<MultiServerProvider>.value(value: multiServerProvider),
|
||||
if (catalogSources != null) ChangeNotifierProvider<CatalogSourcesProvider>.value(value: catalogSources),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: ThemeData(extensions: const [testMonoTokens]),
|
||||
@@ -295,6 +304,22 @@ void main() {
|
||||
expect(targetRect.bottom, lessThanOrEqualTo(railRect.bottom));
|
||||
});
|
||||
|
||||
testWidgets('Explore item follows the showExploreTab appearance setting', (tester) async {
|
||||
final catalogSources = _FakeCatalogSourcesProvider();
|
||||
addTearDown(catalogSources.dispose);
|
||||
|
||||
await _pumpBasicRail(tester, alwaysExpanded: true, catalogSources: catalogSources);
|
||||
expect(find.widgetWithText(NavigationRailItem, 'Explore'), findsOneWidget);
|
||||
|
||||
await SettingsService.instance.write(SettingsService.showExploreTab, false);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.widgetWithText(NavigationRailItem, 'Explore'), findsNothing);
|
||||
|
||||
await SettingsService.instance.write(SettingsService.showExploreTab, true);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.widgetWithText(NavigationRailItem, 'Explore'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('reports interaction expansion for shell content push', (tester) async {
|
||||
await SettingsService.getInstance();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user