playlists screen

This commit is contained in:
austinried 2025-12-06 16:38:38 +09:00
parent 97ea3c3230
commit 3fcb938f2b
9 changed files with 106 additions and 10 deletions

View File

@ -4,6 +4,7 @@ import 'screens/album_screen.dart';
import 'screens/artist_screen.dart';
import 'screens/library_screen.dart';
import 'screens/now_playing_screen.dart';
import 'screens/playlist_screen.dart';
import 'screens/preload_screen.dart';
import 'screens/root_shell_screen.dart';
import 'screens/settings_screen.dart';
@ -23,14 +24,19 @@ final router = GoRouter(
builder: (context, state) => LibraryScreen(),
routes: [
GoRoute(
path: 'album/:id',
path: 'albums/:id',
builder: (context, state) =>
AlbumScreen(id: state.pathParameters['id']!),
),
GoRoute(
path: 'artist',
path: 'artists',
builder: (context, state) => ArtistScreen(),
),
GoRoute(
path: 'playlists/:id',
builder: (context, state) =>
PlaylistScreen(id: state.pathParameters['id']!),
),
],
),
],

View File

@ -0,0 +1,77 @@
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../database/query.dart';
import '../../l10n/generated/app_localizations.dart';
import '../state/database.dart';
import '../state/source.dart';
import '../ui/cover_art_theme.dart';
import '../ui/gradient.dart';
import '../ui/lists/header.dart';
import '../ui/lists/items.dart';
import '../ui/lists/songs_list.dart';
class PlaylistScreen extends HookConsumerWidget {
const PlaylistScreen({
super.key,
required this.id,
});
final String id;
@override
Widget build(BuildContext context, WidgetRef ref) {
final l = AppLocalizations.of(context);
final db = ref.watch(databaseProvider);
final sourceId = ref.watch(sourceIdProvider);
final getPlaylist = useMemoized(
() => db.libraryDao.getPlaylist(sourceId, id).getSingle(),
);
final playlist = useFuture(getPlaylist).data;
if (playlist == null) {
return Container();
}
final query = SongsQuery(
sourceId: sourceId,
filter: IList([SongsFilter.playlistId(playlist.id)]),
sort: IList([
SortingTerm.songsAsc(SongsColumn.playlistPosition),
]),
);
return CoverArtTheme(
coverArt: playlist.coverArt,
child: Scaffold(
body: GradientScrollView(
slivers: [
SliverToBoxAdapter(
child: SongsListHeader(
title: playlist.name,
// subtitle: playlist.albumArtist,
coverArt: playlist.coverArt,
playText: l.resourcesPlaylistActionsPlay,
onPlay: () {},
onMore: () {},
),
),
SongsList(
query: query,
itemBuilder: (context, item, index) => SongListTile(
song: item.song,
coverArt: item.albumCoverArt,
showLeading: true,
onTap: () {},
),
),
],
),
),
);
}
}

View File

@ -53,7 +53,7 @@ class AlbumsGrid extends HookConsumerWidget {
itemBuilder: (context, item, index) => AlbumGridTile(
album: item,
onTap: () async {
context.push('/album/${item.id}');
context.push('/albums/${item.id}');
},
),
),

View File

@ -52,7 +52,7 @@ class ArtistsList extends HookConsumerWidget {
artist: artist,
albumCount: albumCount,
onTap: () async {
context.push('/artist/${artist.id}');
context.push('/artists/${artist.id}');
},
);
},

View File

@ -62,11 +62,12 @@ class SongsListHeader extends HookConsumerWidget {
style: theme.textTheme.headlineMedium,
textAlign: TextAlign.center,
),
Text(
subtitle ?? '',
style: theme.textTheme.headlineSmall,
textAlign: TextAlign.center,
),
if (subtitle != null)
Text(
subtitle!,
style: theme.textTheme.headlineSmall,
textAlign: TextAlign.center,
),
],
),
const SizedBox(height: 20),

View File

@ -1,5 +1,6 @@
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
@ -47,7 +48,9 @@ class PlaylistsList extends HookConsumerWidget {
itemBuilder: (context, item, index) {
return PlaylistListTile(
playlist: item,
onTap: () {},
onTap: () {
context.push('/playlists/${item.id}');
},
);
},
),

View File

@ -163,6 +163,7 @@ class LibraryDao extends DatabaseAccessor<SubtracksDatabase>
SongsColumn.album => songs.album,
SongsColumn.artist => songs.artist,
SongsColumn.albumArtist => albums.albumArtist,
SongsColumn.playlistPosition => playlistSongs.position,
},
mode: sort.dir.toMode(),
),
@ -224,6 +225,12 @@ class LibraryDao extends DatabaseAccessor<SubtracksDatabase>
);
}
Selectable<models.Playlist> getPlaylist(int sourceId, String id) {
return db.managers.playlists.filter(
(f) => f.sourceId.equals(sourceId) & f.id.equals(id),
);
}
void _limitQuery({
required LimitContainerMixin query,
required int? limit,

View File

@ -30,6 +30,7 @@ enum SongsColumn {
album,
artist,
albumArtist,
playlistPosition,
}
enum PlaylistsColumn {

View File

@ -74,6 +74,7 @@ const _$SongsColumnEnumMap = {
SongsColumn.album: 'album',
SongsColumn.artist: 'artist',
SongsColumn.albumArtist: 'albumArtist',
SongsColumn.playlistPosition: 'playlistPosition',
};
PlaylistsSortingTerm _$PlaylistsSortingTermFromJson(