feat(library): playlists filter view and configurable default view

Add a fourth Playlists chip/page to the Library filter pager, rendered
as an album-style grid of playlist cells (search filters by name, page
provider short-circuits since playlists come from libraryCollections).
Add a defaultLibraryView setting (last used / all / albums / singles /
playlists) in Library settings, applied on startup and whenever the
shell switches back to the Library tab.
This commit is contained in:
zarzet
2026-07-27 02:12:35 +07:00
parent eaafeef1bb
commit ef3e019a3a
20 changed files with 515 additions and 5 deletions
+24
View File
@@ -5720,6 +5720,30 @@ abstract class AppLocalizations {
/// **'Single track downloads will appear here'**
String get queueEmptySinglesSubtitle;
/// Playlist count label with plural support
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 playlist} other{{count} playlists}}'**
String queuePlaylistCount(int count);
/// Empty state subtitle for the playlists library view
///
/// In en, this message translates to:
/// **'Create a playlist to organize your tracks'**
String get queueEmptyPlaylistsSubtitle;
/// Setting title - which library view opens when switching to the Library tab
///
/// In en, this message translates to:
/// **'Default view'**
String get libraryDefaultView;
/// Default view option - keep the last used library view
///
/// In en, this message translates to:
/// **'Last used'**
String get libraryDefaultViewLastUsed;
/// Empty state title when download history is empty
///
/// In en, this message translates to:
+21
View File
@@ -3466,6 +3466,27 @@ class AppLocalizationsDe extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Einzelne Titel-Downloads werden hier angezeigt';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'Kein Download-Verlauf';
+21
View File
@@ -3426,6 +3426,27 @@ class AppLocalizationsEn extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Single track downloads will appear here';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'No download history';
+21
View File
@@ -3426,6 +3426,27 @@ class AppLocalizationsEs extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Single track downloads will appear here';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'No download history';
+21
View File
@@ -3515,6 +3515,27 @@ class AppLocalizationsFr extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Les téléchargements de titres individuels apparaîtront ici';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'Aucun historique de téléchargement';
+21
View File
@@ -3429,6 +3429,27 @@ class AppLocalizationsId extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Single track downloads will appear here';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'No download history';
+21
View File
@@ -3415,6 +3415,27 @@ class AppLocalizationsJa extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Single track downloads will appear here';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'No download history';
+21
View File
@@ -3325,6 +3325,27 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get queueEmptySinglesSubtitle => '싱글 트랙 다운로드는 여기에 표시됩니다';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => '다운로드 기록이 없음';
+21
View File
@@ -3426,6 +3426,27 @@ class AppLocalizationsPt extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Single track downloads will appear here';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'No download history';
+21
View File
@@ -3455,6 +3455,27 @@ class AppLocalizationsRu extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Single track downloads will appear here';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'Нет истории скачиваний';
+21
View File
@@ -3456,6 +3456,27 @@ class AppLocalizationsTr extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Single track downloads will appear here';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'No download history';
+21
View File
@@ -3469,6 +3469,27 @@ class AppLocalizationsUk extends AppLocalizations {
String get queueEmptySinglesSubtitle =>
'Завантаження окремих треків з’являться тут';
@override
String queuePlaylistCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count playlists',
one: '1 playlist',
);
return '$_temp0';
}
@override
String get queueEmptyPlaylistsSubtitle =>
'Create a playlist to organize your tracks';
@override
String get libraryDefaultView => 'Default view';
@override
String get libraryDefaultViewLastUsed => 'Last used';
@override
String get queueEmptyHistory => 'Немає історії завантажень';
+21
View File
@@ -4415,6 +4415,27 @@
"@queueEmptySinglesSubtitle": {
"description": "Empty state subtitle for single track downloads"
},
"queuePlaylistCount": "{count, plural, =1{1 playlist} other{{count} playlists}}",
"@queuePlaylistCount": {
"description": "Playlist count label with plural support",
"placeholders": {
"count": {
"type": "int"
}
}
},
"queueEmptyPlaylistsSubtitle": "Create a playlist to organize your tracks",
"@queueEmptyPlaylistsSubtitle": {
"description": "Empty state subtitle for the playlists library view"
},
"libraryDefaultView": "Default view",
"@libraryDefaultView": {
"description": "Setting title - which library view opens when switching to the Library tab"
},
"libraryDefaultViewLastUsed": "Last used",
"@libraryDefaultViewLastUsed": {
"description": "Default view option - keep the last used library view"
},
"queueEmptyHistory": "No download history",
"@queueEmptyHistory": {
"description": "Empty state title when download history is empty"
+7
View File
@@ -34,6 +34,10 @@ class AppSettings {
final bool filterContributingArtistsInAlbumArtist;
final String historyViewMode;
final String historyFilterMode;
/// Library view opened when switching to the Library tab:
/// 'last' (keep last used), 'all', 'albums', 'singles', or 'playlists'.
final String defaultLibraryView;
final bool askQualityBeforeDownload;
final bool enableLogging;
final bool useExtensionProviders;
@@ -132,6 +136,7 @@ class AppSettings {
this.filterContributingArtistsInAlbumArtist = false,
this.historyViewMode = 'grid',
this.historyFilterMode = 'all',
this.defaultLibraryView = 'last',
this.askQualityBeforeDownload = true,
this.enableLogging = false,
this.useExtensionProviders = true,
@@ -202,6 +207,7 @@ class AppSettings {
bool? filterContributingArtistsInAlbumArtist,
String? historyViewMode,
String? historyFilterMode,
String? defaultLibraryView,
bool? askQualityBeforeDownload,
bool? enableLogging,
bool? useExtensionProviders,
@@ -279,6 +285,7 @@ class AppSettings {
this.filterContributingArtistsInAlbumArtist,
historyViewMode: historyViewMode ?? this.historyViewMode,
historyFilterMode: historyFilterMode ?? this.historyFilterMode,
defaultLibraryView: defaultLibraryView ?? this.defaultLibraryView,
askQualityBeforeDownload:
askQualityBeforeDownload ?? this.askQualityBeforeDownload,
enableLogging: enableLogging ?? this.enableLogging,
+2
View File
@@ -33,6 +33,7 @@ AppSettings _$AppSettingsFromJson(Map<String, dynamic> json) => AppSettings(
json['filterContributingArtistsInAlbumArtist'] as bool? ?? false,
historyViewMode: json['historyViewMode'] as String? ?? 'grid',
historyFilterMode: json['historyFilterMode'] as String? ?? 'all',
defaultLibraryView: json['defaultLibraryView'] as String? ?? 'last',
askQualityBeforeDownload: json['askQualityBeforeDownload'] as bool? ?? true,
enableLogging: json['enableLogging'] as bool? ?? false,
useExtensionProviders: json['useExtensionProviders'] as bool? ?? true,
@@ -122,6 +123,7 @@ Map<String, dynamic> _$AppSettingsToJson(
instance.filterContributingArtistsInAlbumArtist,
'historyViewMode': instance.historyViewMode,
'historyFilterMode': instance.historyFilterMode,
'defaultLibraryView': instance.defaultLibraryView,
'askQualityBeforeDownload': instance.askQualityBeforeDownload,
'enableLogging': instance.enableLogging,
'useExtensionProviders': instance.useExtensionProviders,
+23
View File
@@ -96,6 +96,13 @@ class SettingsNotifier extends Notifier<AppSettings> {
'album',
'playlist',
};
static const Set<String> _libraryViewValues = {
'last',
'all',
'albums',
'singles',
'playlists',
};
static const Set<String> _extensionVerificationBrowserModeValues = {
'external_first',
'in_app_first',
@@ -149,6 +156,9 @@ class SettingsNotifier extends Notifier<AppSettings> {
loaded.downloadFallbackExtensionIds != null &&
sanitizedDownloadFallbackExtensionIds == null,
defaultSearchTab: sanitizedDefaultSearchTab,
defaultLibraryView: _normalizeDefaultLibraryView(
loaded.defaultLibraryView,
),
defaultService: loaded.defaultService,
searchProvider: loaded.searchProvider,
extensionVerificationBrowserMode:
@@ -353,6 +363,12 @@ class SettingsNotifier extends Notifier<AppSettings> {
return 'all';
}
String _normalizeDefaultLibraryView(String value) {
final normalized = value.trim().toLowerCase();
if (_libraryViewValues.contains(normalized)) return normalized;
return 'last';
}
String _normalizeExtensionVerificationBrowserMode(String value) {
final normalized = value.trim().toLowerCase();
if (_extensionVerificationBrowserModeValues.contains(normalized)) {
@@ -607,6 +623,13 @@ class SettingsNotifier extends Notifier<AppSettings> {
_saveSettings();
}
void setDefaultLibraryView(String view) {
state = state.copyWith(
defaultLibraryView: _normalizeDefaultLibraryView(view),
);
_saveSettings();
}
void setHomeFeedProvider(String? provider) {
if (provider == null || provider.isEmpty) {
state = state.copyWith(clearHomeFeedProvider: true);
+54 -4
View File
@@ -238,8 +238,9 @@ class _QueueTabState extends ConsumerState<QueueTab> {
double _playlistSelectionOverlayBottomPadding = 0;
PageController? _filterPageController;
final List<String> _filterModes = ['all', 'albums', 'singles'];
final List<String> _filterModes = ['all', 'albums', 'singles', 'playlists'];
bool _isPageControllerInitialized = false;
bool _wasTabVisible = false;
static const List<String> _months = [
'Jan',
'Feb',
@@ -327,11 +328,49 @@ class _QueueTabState extends ConsumerState<QueueTab> {
void _initializePageController() {
if (_isPageControllerInitialized) return;
_isPageControllerInitialized = true;
final currentFilter = ref.read(settingsProvider).historyFilterMode;
final initialPage = _filterModes.indexOf(currentFilter).clamp(0, 2);
final settings = ref.read(settingsProvider);
final initialFilter = settings.defaultLibraryView == 'last'
? settings.historyFilterMode
: settings.defaultLibraryView;
final initialPage = _filterModes
.indexOf(initialFilter)
.clamp(0, _filterModes.length - 1);
if (settings.historyFilterMode != _filterModes[initialPage]) {
Future.microtask(() {
if (!mounted) return;
ref
.read(settingsProvider.notifier)
.setHistoryFilterMode(_filterModes[initialPage]);
});
}
_filterPageController = PageController(initialPage: initialPage);
}
/// When the shell switches back to this tab and a fixed default view is
/// configured, jump the filter pager to it.
void _applyDefaultLibraryViewOnTabVisible() {
final isVisible = TickerMode.valuesOf(context).enabled;
final becameVisible = isVisible && !_wasTabVisible;
_wasTabVisible = isVisible;
if (!becameVisible) return;
final defaultView = ref.read(settingsProvider).defaultLibraryView;
if (defaultView == 'last') return;
final index = _filterModes.indexOf(defaultView);
if (index < 0) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
if (ref.read(settingsProvider).historyFilterMode != defaultView) {
ref.read(settingsProvider.notifier).setHistoryFilterMode(defaultView);
}
final controller = _filterPageController;
if (controller != null &&
controller.hasClients &&
controller.page?.round() != index) {
controller.jumpToPage(index);
}
});
}
@override
void dispose() {
_hideSelectionOverlay();
@@ -1118,6 +1157,7 @@ class _QueueTabState extends ConsumerState<QueueTab> {
@override
Widget build(BuildContext context) {
_initializePageController();
_applyDefaultLibraryViewOnTabVisible();
ref.listen(downloadQueueLookupProvider, (previous, next) {
if (previous == null) return;
@@ -1242,7 +1282,7 @@ class _QueueTabState extends ConsumerState<QueueTab> {
collectionState,
totalTrackCount: switch (filterMode) {
'singles' => queueCounts.singleTrackCount,
'albums' => 0,
'albums' || 'playlists' => 0,
_ => queueCounts.allTrackCount,
},
totalAlbumCount: filterMode == 'albums' ? queueCounts.albumCount : null,
@@ -1257,6 +1297,7 @@ class _QueueTabState extends ConsumerState<QueueTab> {
final currentTotalCount = switch (historyFilterMode) {
'albums' => queueCounts.albumCount,
'singles' => queueCounts.singleTrackCount,
'playlists' => 0,
_ => queueCounts.allTrackCount,
};
final hasMoreLibrary = currentLoadedCount < currentTotalCount;
@@ -1461,6 +1502,15 @@ class _QueueTabState extends ConsumerState<QueueTab> {
_animateToFilterPage(2);
},
),
const SizedBox(width: 8),
_FilterChip(
label: context.l10n.searchPlaylists,
count: collectionState.playlists.length,
isSelected: historyFilterMode == 'playlists',
onTap: () {
_animateToFilterPage(3);
},
),
],
),
);
+64 -1
View File
@@ -230,6 +230,19 @@ extension _QueueTabFilterWidgets on _QueueTabState {
: const <_CollectionEntry>[];
final collectionCount = collectionEntries.length;
// Indexes into collectionState.playlists, name-filtered by the search
// query, for the 'playlists' view.
final playlistIndexes = <int>[];
if (filterMode == 'playlists') {
final query = _searchQuery.trim().toLowerCase();
for (var i = 0; i < collectionState.playlists.length; i++) {
if (query.isEmpty ||
collectionState.playlists[i].name.toLowerCase().contains(query)) {
playlistIndexes.add(i);
}
}
}
Widget leadGridCell(int index) {
if (index < activeDownloadIds.length) {
final id = activeDownloadIds[index];
@@ -428,6 +441,49 @@ extension _QueueTabFilterWidgets on _QueueTabState {
),
),
if (filterMode == 'playlists' && playlistIndexes.isNotEmpty) ...[
SliverToBoxAdapter(
child: _countHeaderRow(
context,
context.l10n.queuePlaylistCount(playlistIndexes.length),
[
if (!_isPlaylistSelectionMode)
TextButton.icon(
onPressed: () => _showCreatePlaylistDialog(context),
icon: const Icon(Icons.add, size: 20),
label: Text(context.l10n.collectionCreatePlaylist),
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
),
),
],
),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: _AnimatedLibrarySliverGrid(
maxCrossAxisExtent: _libraryAlbumGridExtent,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 0.72,
delegate: SliverChildBuilderDelegate((context, index) {
final playlistIndex = playlistIndexes[index];
return KeyedSubtree(
key: ValueKey(
'plgrid_${collectionState.playlists[playlistIndex].id}',
),
child: _buildAllTabGridCollectionItem(
context: context,
colorScheme: colorScheme,
entry: _CollectionEntry.playlist(playlistIndex),
collectionState: collectionState,
),
);
}, childCount: playlistIndexes.length),
),
),
],
if (filterMode == 'all') ...[
if (historyViewMode == 'grid')
SliverPadding(
@@ -666,6 +722,7 @@ extension _QueueTabFilterWidgets on _QueueTabState {
(filterMode != 'albums' ||
(filteredGroupedAlbums.isEmpty &&
filteredGroupedLocalAlbums.isEmpty)) &&
(filterMode != 'playlists' || playlistIndexes.isEmpty) &&
!showFilteringIndicator &&
!isPageLoading)
SliverFillRemaining(
@@ -693,7 +750,8 @@ extension _QueueTabFilterWidgets on _QueueTabState {
totalTrackCount > 0 ||
(filterMode == 'albums' &&
(filteredGroupedAlbums.isNotEmpty ||
filteredGroupedLocalAlbums.isNotEmpty)))
filteredGroupedLocalAlbums.isNotEmpty)) ||
(filterMode == 'playlists' && playlistIndexes.isNotEmpty))
SliverToBoxAdapter(
child: SizedBox(height: _isSelectionMode ? 100 : 16),
),
@@ -770,6 +828,11 @@ extension _QueueTabFilterWidgets on _QueueTabState {
subtitle = context.l10n.queueEmptySinglesSubtitle;
icon = Icons.music_note;
break;
case 'playlists':
message = context.l10n.collectionNoPlaylistsYet;
subtitle = context.l10n.queueEmptyPlaylistsSubtitle;
icon = Icons.queue_music;
break;
default:
message = context.l10n.queueEmptyHistory;
subtitle = context.l10n.queueEmptyHistorySubtitle;
+4
View File
@@ -273,6 +273,10 @@ final _queueLibraryPageProvider = FutureProvider.autoDispose
ref.watch(
localLibraryProvider.select((state) => state.loadedIndexVersion),
);
// Playlists render from libraryCollectionsProvider, not the DB.
if (request.filterMode == 'playlists') {
return const _QueueLibraryPageData();
}
final dbQuery = request.toDbQuery();
if (request.filterMode == 'albums') {
final rows = await LibraryDatabase.instance.getQueueAlbumPage(dbQuery);
@@ -337,6 +337,71 @@ class _LibrarySettingsPageState extends ConsumerState<LibrarySettingsPage> {
);
}
String _getDefaultViewLabel(BuildContext context, String view) {
switch (view) {
case 'all':
return context.l10n.historyFilterAll;
case 'albums':
return context.l10n.historyFilterAlbums;
case 'singles':
return context.l10n.historyFilterSingles;
case 'playlists':
return context.l10n.searchPlaylists;
default:
return context.l10n.libraryDefaultViewLastUsed;
}
}
void _showDefaultViewPicker(BuildContext context, String current) {
final colorScheme = Theme.of(context).colorScheme;
final options = [
('last', Icons.history, context.l10n.libraryDefaultViewLastUsed),
('all', Icons.apps, context.l10n.historyFilterAll),
('albums', Icons.album, context.l10n.historyFilterAlbums),
('singles', Icons.music_note, context.l10n.historyFilterSingles),
('playlists', Icons.queue_music, context.l10n.searchPlaylists),
];
showModalBottomSheet<void>(
context: context,
useRootNavigator: true,
backgroundColor: colorScheme.surfaceContainerHigh,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
),
builder: (context) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(24, 24, 24, 16),
child: Text(
context.l10n.libraryDefaultView,
style: Theme.of(
context,
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
),
),
for (final (value, icon, label) in options)
_AutoScanOption(
icon: icon,
title: label,
selected: current == value,
colorScheme: colorScheme,
onTap: () {
ref
.read(settingsProvider.notifier)
.setDefaultLibraryView(value);
Navigator.pop(context);
},
),
const SizedBox(height: 16),
],
),
),
);
}
@override
Widget build(BuildContext context) {
final settings = ref.watch(settingsProvider);
@@ -369,6 +434,26 @@ class _LibrarySettingsPageState extends ConsumerState<LibrarySettingsPage> {
),
),
SliverToBoxAdapter(
child: SettingsGroup(
children: [
SettingsItem(
icon: Icons.grid_view_rounded,
title: context.l10n.libraryDefaultView,
subtitle: _getDefaultViewLabel(
context,
settings.defaultLibraryView,
),
onTap: () => _showDefaultViewPicker(
context,
settings.defaultLibraryView,
),
showDivider: false,
),
],
),
),
SliverToBoxAdapter(
child: SettingsSectionHeader(
title: context.l10n.libraryScanSettings,