updates
This commit is contained in:
parent
d558aba246
commit
3bd713d667
17 changed files with 1566 additions and 132 deletions
|
|
@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
|
||||
import '../downloads/download_manager.dart';
|
||||
import '../history/play_history.dart';
|
||||
import '../library/browse_query.dart';
|
||||
import '../library/library_index.dart';
|
||||
import '../playback/playback_engine.dart';
|
||||
import '../playlists/playlists.dart';
|
||||
|
|
@ -17,7 +18,9 @@ import 'favorites.dart';
|
|||
// `BrowseMode`/`SearchMode` are defined in the settings store (so they can be
|
||||
// persisted) but historically lived here — re-export so existing importers of
|
||||
// this file keep resolving them.
|
||||
export '../settings/settings_store.dart' show BrowseMode, SearchMode;
|
||||
export '../settings/settings_store.dart'
|
||||
show BrowseMode, SearchMode, AlbumSort, TrackSort;
|
||||
export '../library/browse_query.dart' show BrowseFilter;
|
||||
|
||||
// ---- Connection ---------------------------------------------------------
|
||||
|
||||
|
|
@ -296,6 +299,58 @@ final libraryIndexProvider =
|
|||
return controller;
|
||||
});
|
||||
|
||||
// ---- Browse filtering / sorting -----------------------------------------
|
||||
|
||||
/// Session-only genre/year filter for the Albums grid (resets on restart).
|
||||
final albumFilterProvider =
|
||||
StateProvider<BrowseFilter>((_) => const BrowseFilter());
|
||||
|
||||
/// Session-only genre/year filter for the Tracks list (resets on restart).
|
||||
final trackFilterProvider =
|
||||
StateProvider<BrowseFilter>((_) => const BrowseFilter());
|
||||
|
||||
/// Distinct genres present across all albums, for the album genre picker.
|
||||
final albumGenresProvider = Provider<List<String>>((ref) {
|
||||
final albums = ref.watch(albumsProvider).valueOrNull ?? const <Album>[];
|
||||
return distinctGenres(albums.map((a) => a.genre));
|
||||
});
|
||||
|
||||
/// Distinct release years present across all albums, newest first.
|
||||
final albumYearsProvider = Provider<List<int>>((ref) {
|
||||
final albums = ref.watch(albumsProvider).valueOrNull ?? const <Album>[];
|
||||
return distinctYears(albums.map((a) => a.year));
|
||||
});
|
||||
|
||||
/// Albums after applying the session filter and the persisted sort. Async so
|
||||
/// callers keep the underlying load/error states from [albumsProvider].
|
||||
final visibleAlbumsProvider = Provider<AsyncValue<List<Album>>>((ref) {
|
||||
final filter = ref.watch(albumFilterProvider);
|
||||
final sort = ref.watch(settingsProvider.select((s) => s.albumSort));
|
||||
return ref
|
||||
.watch(albumsProvider)
|
||||
.whenData((albums) => applyAlbumQuery(albums, filter, sort));
|
||||
});
|
||||
|
||||
/// Distinct genres present across all indexed tracks.
|
||||
final trackGenresProvider = Provider<List<String>>((ref) {
|
||||
final songs = ref.watch(libraryIndexProvider).songs;
|
||||
return distinctGenres(songs.map((s) => s.genre));
|
||||
});
|
||||
|
||||
/// Distinct release years present across all indexed tracks, newest first.
|
||||
final trackYearsProvider = Provider<List<int>>((ref) {
|
||||
final songs = ref.watch(libraryIndexProvider).songs;
|
||||
return distinctYears(songs.map((s) => s.year));
|
||||
});
|
||||
|
||||
/// Indexed tracks after applying the session filter and the persisted sort.
|
||||
final visibleTracksProvider = Provider<List<Song>>((ref) {
|
||||
final filter = ref.watch(trackFilterProvider);
|
||||
final sort = ref.watch(settingsProvider.select((s) => s.trackSort));
|
||||
final songs = ref.watch(libraryIndexProvider).songs;
|
||||
return applyTrackQuery(songs, filter, sort);
|
||||
});
|
||||
|
||||
/// Recently-added albums (`getAlbumList2` type `newest`) — a discovery shelf on
|
||||
/// the Home tab. Small page; the Home shelf shows the first handful.
|
||||
final newestAlbumsProvider = FutureProvider<List<Album>>((ref) async {
|
||||
|
|
@ -418,6 +473,11 @@ final downloadManagerProvider =
|
|||
ref.listen<String?>(serverKeyProvider, (_, _) {
|
||||
controller.reloadForServer();
|
||||
});
|
||||
// Raising the concurrency cap should launch queued downloads right away.
|
||||
ref.listen<int>(
|
||||
settingsProvider.select((s) => s.maxConcurrentDownloads),
|
||||
(_, _) => controller.onConcurrencyChanged(),
|
||||
);
|
||||
return controller;
|
||||
});
|
||||
|
||||
|
|
@ -451,6 +511,30 @@ final realPlaylistsProvider = Provider<List<Playlist>>((ref) => ref
|
|||
final tagsProvider = Provider<List<Playlist>>(
|
||||
(ref) => ref.watch(playlistsProvider).playlists.where(isTagPlaylist).toList());
|
||||
|
||||
/// The signed-in user's name on the active server, or null when disconnected.
|
||||
/// Used to split owned playlists from ones shared by other users.
|
||||
final currentUsernameProvider = Provider<String?>(
|
||||
(ref) => ref.watch(connectionProvider).credentials?.username);
|
||||
|
||||
/// The user's own playlists (owned, or owner unknown). Backs the main list and
|
||||
/// the "add to playlist" sheet — you can only add tracks to your own playlists.
|
||||
final myPlaylistsProvider = Provider<List<Playlist>>((ref) {
|
||||
final me = ref.watch(currentUsernameProvider);
|
||||
return ref
|
||||
.watch(realPlaylistsProvider)
|
||||
.where((p) => isOwnedBy(p, me))
|
||||
.toList();
|
||||
});
|
||||
|
||||
/// Playlists shared by *other* users on the same server (public, owner != me).
|
||||
final sharedPlaylistsProvider = Provider<List<Playlist>>((ref) {
|
||||
final me = ref.watch(currentUsernameProvider);
|
||||
return ref
|
||||
.watch(realPlaylistsProvider)
|
||||
.where((p) => !isOwnedBy(p, me))
|
||||
.toList();
|
||||
});
|
||||
|
||||
// ---- Playback -----------------------------------------------------------
|
||||
|
||||
final playbackProvider =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue