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 HookConsumerWidget { const AlbumGridTile({ super.key, required this.album, this.onTap, }); final Album album; final void Function()? onTap; @override Widget build(BuildContext context, WidgetRef ref) { return CardTheme( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( borderRadius: BorderRadiusGeometry.circular(3), ), margin: EdgeInsets.all(2), child: ImageCard( onTap: onTap, 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}); @override Widget build(BuildContext context) { return ListTile( leading: CircleClip( child: CachedNetworkImage( imageUrl: 'https://placehold.net/400x400.png', placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ), ), title: Text('Some Artist'), ); } } class ImageCard extends StatelessWidget { const ImageCard({ super.key, required this.child, this.onTap, this.onLongPress, }); final Widget child; final void Function()? onTap; final void Function()? onLongPress; @override Widget build(BuildContext context) { return Card( child: Stack( fit: StackFit.passthrough, alignment: Alignment.center, children: [ child, Positioned.fill( child: Material( type: MaterialType.transparency, child: InkWell( onTap: onTap, onLongPress: onLongPress, ), ), ), ], ), ); } }