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:
edde746
2026-08-09 17:14:47 +02:00
parent 8e5279a487
commit 9d13584c00
29 changed files with 118 additions and 13 deletions
+2
View File
@@ -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",
+2
View File
@@ -323,6 +323,8 @@
"showNavBarLabels": "Показвай етикети в навигационната лента",
"showNavBarLabelsDescription": "Показвай текстови етикети под иконите в навигационната лента",
"startupSection": "Начален раздел",
"showExploreTab": "",
"showExploreTabDescription": "",
"liveTvDefaultFavorites": "По подразбиране към любими канали",
"liveTvDefaultFavoritesDescription": "Показвай само любими канали при отваряне на телевизия на живо",
"display": "Дисплей",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -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ő",
+2
View File
@@ -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",
+2
View File
@@ -323,6 +323,8 @@
"showNavBarLabels": "ナビゲーションバーのラベルを表示",
"showNavBarLabelsDescription": "ナビゲーションバーのアイコンの下にテキストラベルを表示",
"startupSection": "起動時のセクション",
"showExploreTab": "",
"showExploreTabDescription": "",
"liveTvDefaultFavorites": "お気に入りチャンネルをデフォルトに",
"liveTvDefaultFavoritesDescription": "ライブTVを開いたときにお気に入りチャンネルのみ表示",
"display": "ディスプレイ",
+2
View File
@@ -323,6 +323,8 @@
"showNavBarLabels": "Навигация панелінің мәтіндерін көрсету",
"showNavBarLabelsDescription": "Навигация белгішелерінің астында мәтінді көрсету",
"startupSection": "Бастапқы бөлім",
"showExploreTab": "",
"showExploreTabDescription": "",
"liveTvDefaultFavorites": "Тікелей TV-де таңдаулы арналарды әдепкі ету",
"liveTvDefaultFavoritesDescription": "Тікелей TV ашылғанда тек таңдаулы арналарды көрсету",
"display": "Дисплей",
+2
View File
@@ -323,6 +323,8 @@
"showNavBarLabels": "내비게이션 바 라벨 표시",
"showNavBarLabelsDescription": "내비게이션 바 아이콘 아래에 텍스트 라벨을 표시합니다",
"startupSection": "시작 섹션",
"showExploreTab": "",
"showExploreTabDescription": "",
"liveTvDefaultFavorites": "즐겨찾기 채널 기본 설정",
"liveTvDefaultFavoritesDescription": "라이브 TV를 열 때 즐겨찾기 채널만 표시",
"display": "디스플레이",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -323,6 +323,8 @@
"showNavBarLabels": "Показывать подписи панели навигации",
"showNavBarLabelsDescription": "Отображать текстовые подписи под иконками панели навигации",
"startupSection": "Начальный раздел",
"showExploreTab": "",
"showExploreTabDescription": "",
"liveTvDefaultFavorites": "Избранные каналы по умолчанию",
"liveTvDefaultFavoritesDescription": "Показывать только избранные каналы при открытии ТВ",
"display": "Экран",
+1 -1
View File
@@ -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
+14 -6
View File
@@ -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',
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -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",
+2
View File
@@ -323,6 +323,8 @@
"showNavBarLabels": "顯示導覽列標籤",
"showNavBarLabelsDescription": "在導覽列圖示下方顯示文字標籤",
"startupSection": "啟動頁面",
"showExploreTab": "",
"showExploreTabDescription": "",
"liveTvDefaultFavorites": "預設顯示最愛頻道",
"liveTvDefaultFavoritesDescription": "開啟直播電視時僅顯示最愛頻道",
"display": "顯示器",
+2
View File
@@ -323,6 +323,8 @@
"showNavBarLabels": "显示导航栏标签",
"showNavBarLabelsDescription": "在导航栏图标下方显示文字标签",
"startupSection": "启动页面",
"showExploreTab": "",
"showExploreTabDescription": "",
"liveTvDefaultFavorites": "默认显示收藏频道",
"liveTvDefaultFavoritesDescription": "打开直播电视时仅显示收藏频道",
"display": "显示",
+11 -2
View File
@@ -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,
+6
View File
@@ -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,
+5 -3
View File
@@ -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();