display albums from db

This commit is contained in:
austinried
2025-11-08 18:27:37 +09:00
parent 0c80dbdba5
commit 933775b92f
17 changed files with 305 additions and 127 deletions

View File

@@ -1,20 +1,35 @@
import 'package:drift/drift.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import '../../sources/models.dart';
import '../hooks/use_paging_controller.dart';
import '../state/database.dart';
import '../state/settings.dart';
import 'list_items.dart';
class AlbumsGrid extends HookWidget {
const kPageSize = 30;
class AlbumsGrid extends HookConsumerWidget {
const AlbumsGrid({super.key});
@override
Widget build(BuildContext context) {
final controller = usePagingController<int, String>(
Widget build(BuildContext context, WidgetRef ref) {
final db = ref.watch(databaseProvider);
final sourceId = ref.watch(sourceIdProvider);
final controller = usePagingController<int, Album>(
getNextPageKey: (state) =>
state.lastPageIsEmpty ? null : state.nextIntPageKey,
fetchPage: (pageKey) => List.generate(30, (_) => pageKey.toString()),
fetchPage: (pageKey) async {
final query = db.albums.select()
..where((f) => f.sourceId.equals(sourceId))
..limit(kPageSize, offset: (pageKey - 1) * kPageSize);
return await query.get();
},
);
return PagingListener(
@@ -26,10 +41,11 @@ class AlbumsGrid extends HookWidget {
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
builderDelegate: PagedChildBuilderDelegate<String>(
builderDelegate: PagedChildBuilderDelegate<Album>(
itemBuilder: (context, item, index) => AlbumGridTile(
onTap: () {
context.push('/album');
album: item,
onTap: () async {
context.push('/album/${item.id}');
},
),
),

View File

@@ -1,18 +1,26 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:octo_image/octo_image.dart';
import '../../sources/models.dart';
import '../state/source.dart';
import '../util/clip.dart';
class AlbumGridTile extends StatelessWidget {
class AlbumGridTile extends HookConsumerWidget {
const AlbumGridTile({
super.key,
required this.album,
this.onTap,
});
final Album album;
final void Function()? onTap;
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
return CardTheme(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
@@ -21,16 +29,50 @@ class AlbumGridTile extends StatelessWidget {
margin: EdgeInsets.all(2),
child: ImageCard(
onTap: onTap,
child: CachedNetworkImage(
imageUrl: 'https://placehold.net/400x400.png',
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
child: CoverArtImage(coverArt: album.coverArt),
),
);
}
}
class CoverArtImage extends HookConsumerWidget {
const CoverArtImage({
super.key,
this.coverArt,
this.thumbnail = false,
});
final String? coverArt;
final bool thumbnail;
@override
Widget build(BuildContext context, WidgetRef ref) {
final source = ref.watch(sourceProvider);
CachedNetworkImageProvider buildImageProvider() =>
CachedNetworkImageProvider(
coverArt != null
? source.coverArtUri(coverArt!, thumbnail: thumbnail).toString()
: 'https://placehold.net/400x400.png',
);
final imageProvider = useState(buildImageProvider());
useEffect(() {
imageProvider.value = buildImageProvider();
return;
}, [source, coverArt, thumbnail]);
return OctoImage(
image: imageProvider.value,
placeholderBuilder: (context) => Icon(Symbols.album_rounded),
errorBuilder: (context, error, trace) => Icon(Icons.error),
fit: BoxFit.cover,
fadeOutDuration: Duration(milliseconds: 100),
fadeInDuration: Duration(milliseconds: 200),
);
}
}
class ArtistListTile extends StatelessWidget {
const ArtistListTile({super.key});
@@ -71,7 +113,7 @@ class ImageCard extends StatelessWidget {
child,
Positioned.fill(
child: Material(
color: Colors.transparent,
type: MaterialType.transparency,
child: InkWell(
onTap: onTap,
onLongPress: onLongPress,