diff --git a/flutter_client/lib/api/endpoints/library_lists.dart b/flutter_client/lib/api/endpoints/library_lists.dart index f06dc6bd..8b274791 100644 --- a/flutter_client/lib/api/endpoints/library_lists.dart +++ b/flutter_client/lib/api/endpoints/library_lists.dart @@ -12,9 +12,16 @@ class LibraryListsApi { final Dio _dio; Future> listArtists({int limit = 50, int offset = 0}) async { + // Server mounts the artists list at /api/artists (handleListArtists), + // not /api/library/artists. Albums use /api/library/albums for + // historical reasons; the paths aren't symmetric. final r = await _dio.get>( - '/api/library/artists', - queryParameters: {'limit': limit, 'offset': offset}, + '/api/artists', + queryParameters: { + 'limit': limit, + 'offset': offset, + 'sort': 'alpha', + }, ); return Paged.fromJson(r.data ?? const {}, ArtistRef.fromJson); } diff --git a/flutter_client/lib/library/library_screen.dart b/flutter_client/lib/library/library_screen.dart index 323b2959..c198fb7a 100644 --- a/flutter_client/lib/library/library_screen.dart +++ b/flutter_client/lib/library/library_screen.dart @@ -144,10 +144,14 @@ class _ArtistsTab extends ConsumerWidget { childAspectRatio: 0.78, ), itemCount: page.items.length, - itemBuilder: (ctx, i) => ArtistCard( - artist: page.items[i], - onTap: () => ctx.push('/artists/${page.items[i].id}'), - ), + itemBuilder: (ctx, i) { + final artist = page.items[i]; + return ArtistCard( + artist: artist, + onTap: () => ctx.push('/artists/${artist.id}', + extra: artist), + ); + }, ), ), ); @@ -167,20 +171,41 @@ class _AlbumsTab extends ConsumerWidget { ? Center(child: Text("No albums yet — scan a library folder via the server's config.", style: TextStyle(color: fs.ash), textAlign: TextAlign.center)) : RefreshIndicator( onRefresh: () async => ref.refresh(_libraryAlbumsProvider.future), - child: GridView.builder( - padding: const EdgeInsets.all(8), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - mainAxisSpacing: 8, - crossAxisSpacing: 8, - childAspectRatio: 0.78, - ), - itemCount: page.items.length, - itemBuilder: (ctx, i) => AlbumCard( - album: page.items[i], - onTap: () => ctx.push('/albums/${page.items[i].id}'), - ), - ), + // Same responsive 3-up grid as the artist detail + // album list — LayoutBuilder + AlbumCard sized to the + // cell, mainAxisExtent matched to actual card height. + child: LayoutBuilder(builder: (ctx, constraints) { + const cols = 3; + const sidePad = 8.0; + const gap = 8.0; + final cellW = (constraints.maxWidth - + sidePad * 2 - + gap * (cols - 1)) / + cols; + // cover (cellW - 16) + gap (8) + 2-line title (~36) + // + artist line (~16) + small fudge. + final cellH = (cellW - 16) + 8 + 36 + 16 + 4; + return GridView.builder( + padding: const EdgeInsets.all(sidePad), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: cols, + mainAxisExtent: cellH, + mainAxisSpacing: gap, + crossAxisSpacing: gap, + ), + itemCount: page.items.length, + itemBuilder: (ctx, i) { + final album = page.items[i]; + return AlbumCard( + album: album, + width: cellW, + titleMaxLines: 2, + onTap: () => ctx.push('/albums/${album.id}', + extra: album), + ); + }, + ); + }), ), ); } @@ -260,10 +285,14 @@ class _LikedTab extends ConsumerWidget { scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 8), itemCount: ar.items.length, - itemBuilder: (ctx, i) => ArtistCard( - artist: ar.items[i], - onTap: () => ctx.push('/artists/${ar.items[i].id}'), - ), + itemBuilder: (ctx, i) { + final artist = ar.items[i]; + return ArtistCard( + artist: artist, + onTap: () => + ctx.push('/artists/${artist.id}', extra: artist), + ); + }, ), ), ], @@ -275,10 +304,14 @@ class _LikedTab extends ConsumerWidget { scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 8), itemCount: al.items.length, - itemBuilder: (ctx, i) => AlbumCard( - album: al.items[i], - onTap: () => ctx.push('/albums/${al.items[i].id}'), - ), + itemBuilder: (ctx, i) { + final album = al.items[i]; + return AlbumCard( + album: album, + onTap: () => + ctx.push('/albums/${album.id}', extra: album), + ); + }, ), ), ],