subtracks/lib/app/pages/artist_page.dart
2023-05-07 13:28:15 +09:00

153 lines
4.5 KiB
Dart

import 'dart:math';
import 'package:auto_route/auto_route.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../database/database.dart';
import '../../models/query.dart';
import '../../models/support.dart';
import '../../services/audio_service.dart';
import '../../state/music.dart';
import '../../state/settings.dart';
import '../app_router.dart';
import '../buttons.dart';
import '../images.dart';
import '../items.dart';
class ArtistPage extends HookConsumerWidget {
final String id;
const ArtistPage({
super.key,
@pathParam required this.id,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
ref.listen(sourceIdProvider, (_, __) => context.router.popUntilRoot());
final artist = ref.watch(artistProvider(id));
final albums = ref.watch(albumsByArtistIdProvider(id));
return Scaffold(
floatingActionButton: RadioPlayFab(
onPressed: () => artist.hasValue
? ref.read(audioControlProvider).playRadio(
context: QueueContextType.artist,
contextId: artist.valueOrNull!.id,
query: ListQuery(
filters: IList([
FilterWith.equals(
column: 'artist_id',
value: artist.valueOrNull!.id,
)
]),
),
getSongs: (query) => ref
.read(databaseProvider)
.songsList(ref.read(sourceIdProvider), query)
.get(),
)
: null,
),
body: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Stack(
alignment: Alignment.bottomCenter,
fit: StackFit.passthrough,
children: [
ArtistArtImage(
artistId: id,
thumbnail: false,
height: 400,
),
Padding(
padding: const EdgeInsets.all(12),
child: _Title(text: artist.valueOrNull?.name ?? ''),
),
],
),
),
albums.when(
data: (albums) {
albums = albums.sort((a, b) => (b.year ?? 0) - (a.year ?? 0));
return SliverPadding(
padding:
const EdgeInsets.symmetric(horizontal: 24, vertical: 24),
sliver: SliverAlignedGrid.count(
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 24,
itemCount: albums.length,
itemBuilder: (context, i) {
final album = albums.elementAt(i);
return AlbumCard(
album: album,
subtitle: AlbumSubtitle.year,
onTap: () => context.navigateTo(AlbumSongsRoute(
id: album.id,
)),
);
},
),
);
},
error: (_, __) => SliverToBoxAdapter(
child: Container(color: Colors.red),
),
loading: () => const SliverToBoxAdapter(
child: CircularProgressIndicator(),
),
),
],
),
);
}
}
class _Title extends StatelessWidget {
final String text;
const _Title({
required this.text,
});
@override
Widget build(BuildContext context) {
return Text(
text,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.displayMedium!.copyWith(
fontWeight: FontWeight.bold,
color: Colors.white,
shadows: [
Shadow(
offset: Offset.fromDirection(pi / 4, 3),
blurRadius: 16,
color: Colors.black26,
),
Shadow(
offset: Offset.fromDirection(3 * pi / 4, 3),
blurRadius: 16,
color: Colors.black26,
),
Shadow(
offset: Offset.fromDirection(5 * pi / 4, 3),
blurRadius: 16,
color: Colors.black26,
),
Shadow(
offset: Offset.fromDirection(7 * pi / 4, 3),
blurRadius: 16,
color: Colors.black26,
),
],
),
);
}
}