c47deb3c87
HorizontalScrollRow takes an optional shared ScrollController so multi-row sections (Most played: 3 rows) couple their scroll like the web HorizontalScrollRow.svelte. Cards fall back to the synced album-fallback.svg when coverUrl is empty.
52 lines
1.6 KiB
Dart
52 lines
1.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
|
|
import '../../models/album.dart';
|
|
import '../../theme/theme_extension.dart';
|
|
|
|
class AlbumCard extends StatelessWidget {
|
|
const AlbumCard({required this.album, required this.onTap, super.key});
|
|
final AlbumRef album;
|
|
final VoidCallback onTap;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final fs = Theme.of(context).extension<FabledSwordTheme>()!;
|
|
return GestureDetector(
|
|
onTap: onTap,
|
|
child: SizedBox(
|
|
width: 140,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(6),
|
|
child: Container(
|
|
width: 124,
|
|
height: 124,
|
|
color: fs.slate,
|
|
child: album.coverUrl.isEmpty
|
|
? SvgPicture.asset('assets/svg/album-fallback.svg', fit: BoxFit.cover)
|
|
: Image.network(album.coverUrl, fit: BoxFit.cover),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
album.title,
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: TextStyle(color: fs.parchment, fontSize: 14),
|
|
),
|
|
Text(
|
|
album.artistName,
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: TextStyle(color: fs.ash, fontSize: 12),
|
|
),
|
|
]),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|