playlists list

This commit is contained in:
austinried
2025-12-06 10:22:14 +09:00
parent a4e4c6fa57
commit f3969dc6af
13 changed files with 1040 additions and 32 deletions

View File

@@ -41,9 +41,9 @@ class AlbumScreen extends HookConsumerWidget {
sourceId: sourceId,
filter: IList([SongsFilter.albumId(album.id)]),
sort: IList([
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.disc),
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.track),
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.title),
SortingTerm.songsAsc(SongsColumn.disc),
SortingTerm.songsAsc(SongsColumn.track),
SortingTerm.songsAsc(SongsColumn.title),
]),
);

View File

@@ -12,6 +12,7 @@ import '../state/source.dart';
import '../ui/lists/albums_grid.dart';
import '../ui/lists/artists_list.dart';
import '../ui/lists/items.dart';
import '../ui/lists/playlists_list.dart';
import '../ui/lists/songs_list.dart';
import '../util/custom_scroll_fix.dart';
@@ -79,11 +80,11 @@ class LibraryTabBarView extends HookConsumerWidget {
final songsQuery = SongsQuery(
sourceId: sourceId,
sort: IList([
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.albumArtist),
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.album),
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.disc),
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.track),
SongsSortingTerm(dir: SortDirection.asc, by: SongsColumn.title),
SortingTerm.songsAsc(SongsColumn.albumArtist),
SortingTerm.songsAsc(SongsColumn.album),
SortingTerm.songsAsc(SongsColumn.disc),
SortingTerm.songsAsc(SongsColumn.track),
SortingTerm.songsAsc(SongsColumn.title),
]),
);
@@ -96,6 +97,7 @@ class LibraryTabBarView extends HookConsumerWidget {
sliver: switch (tab) {
LibraryTab.albums => AlbumsGrid(),
LibraryTab.artists => ArtistsList(),
LibraryTab.playlists => PlaylistsList(),
LibraryTab.songs => SongsList(
query: songsQuery,
itemBuilder: (context, item, index) => SongListTile(

View File

@@ -27,10 +27,7 @@ class AlbumsGrid extends HookConsumerWidget {
AlbumsQuery(
sourceId: ref.read(sourceIdProvider),
sort: IList([
AlbumsSortingTerm(
dir: SortDirection.desc,
by: AlbumsColumn.created,
),
SortingTerm.albumsDesc(AlbumsColumn.created),
]),
limit: kPageSize,
offset: (pageKey - 1) * kPageSize,

View File

@@ -27,10 +27,7 @@ class ArtistsList extends HookConsumerWidget {
ArtistsQuery(
sourceId: ref.read(sourceIdProvider),
sort: IList([
ArtistsSortingTerm(
dir: SortDirection.asc,
by: ArtistsColumn.name,
),
SortingTerm.artistsAsc(ArtistsColumn.name),
]),
limit: kPageSize,
offset: (pageKey - 1) * kPageSize,

View File

@@ -38,12 +38,12 @@ class ArtistListTile extends StatelessWidget {
const ArtistListTile({
super.key,
required this.artist,
this.albumCount,
required this.albumCount,
this.onTap,
});
final Artist artist;
final int? albumCount;
final int albumCount;
final void Function()? onTap;
@override
@@ -56,7 +56,33 @@ class ArtistListTile extends StatelessWidget {
),
),
title: Text(artist.name),
subtitle: albumCount != null ? Text('$albumCount albums') : null,
subtitle: Text('$albumCount albums'),
onTap: onTap,
);
}
}
class PlaylistListTile extends StatelessWidget {
const PlaylistListTile({
super.key,
required this.playlist,
this.albumCount,
this.onTap,
});
final Playlist playlist;
final int? albumCount;
final void Function()? onTap;
@override
Widget build(BuildContext context) {
return ListTile(
leading: CoverArtImage(
coverArt: playlist.coverArt,
thumbnail: true,
),
title: Text(playlist.name),
subtitle: Text(playlist.comment ?? ''),
onTap: onTap,
);
}

View File

@@ -0,0 +1,58 @@
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import '../../../database/query.dart';
import '../../../sources/models.dart';
import '../../hooks/use_on_source.dart';
import '../../hooks/use_paging_controller.dart';
import '../../state/database.dart';
import '../../state/source.dart';
import 'items.dart';
const kPageSize = 30;
class PlaylistsList extends HookConsumerWidget {
const PlaylistsList({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final db = ref.watch(databaseProvider);
final controller = usePagingController<int, Playlist>(
getNextPageKey: (state) =>
state.lastPageIsEmpty ? null : state.nextIntPageKey,
fetchPage: (pageKey) => db.libraryDao.listPlaylists(
PlaylistsQuery(
sourceId: ref.read(sourceIdProvider),
sort: IList([
SortingTerm.playlistsDesc(PlaylistsColumn.created),
]),
limit: kPageSize,
offset: (pageKey - 1) * kPageSize,
),
),
);
useOnSourceChange(ref, (_) => controller.refresh());
useOnSourceSync(ref, controller.refresh);
return PagingListener(
controller: controller,
builder: (context, state, fetchNextPage) {
return PagedSliverList(
state: state,
fetchNextPage: fetchNextPage,
builderDelegate: PagedChildBuilderDelegate<Playlist>(
itemBuilder: (context, item, index) {
return PlaylistListTile(
playlist: item,
onTap: () {},
);
},
),
);
},
);
}
}