From fd4877a159d9e0dadd8de93f794849ebcfe3b575 Mon Sep 17 00:00:00 2001 From: Frieder Hannenheim Date: Thu, 24 Aug 2023 03:04:37 +0200 Subject: [PATCH] Make Artist tappable in AlbumDetailsPage to go to the artist (#123) * add onTapTitle to CoverSliverAppBar * untested changes * Make artist tappable to go to album artist * remove gesture detector --------- Co-authored-by: FriederHannenheim --- .../pages/album_details_page.dart | 21 +++++++ .../widgets/cover_sliver_appbar.dart | 62 +++++++++++++++---- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/lib/presentation/pages/album_details_page.dart b/src/lib/presentation/pages/album_details_page.dart index c80c69b..39837b9 100644 --- a/src/lib/presentation/pages/album_details_page.dart +++ b/src/lib/presentation/pages/album_details_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/localizations.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:get_it/get_it.dart'; +import 'package:mucke/domain/entities/artist.dart'; import '../../domain/entities/album.dart'; import '../../domain/entities/song.dart'; @@ -9,6 +10,7 @@ import '../l10n_utils.dart'; import '../state/album_page_store.dart'; import '../state/audio_store.dart'; import '../state/music_data_store.dart'; +import '../state/navigation_store.dart'; import '../state/settings_store.dart'; import '../theming.dart'; import '../utils.dart' as utils; @@ -19,6 +21,7 @@ import '../widgets/exclude_level_options.dart'; import '../widgets/like_count_options.dart'; import '../widgets/song_bottom_sheet.dart'; import '../widgets/song_list_tile_numbered.dart'; +import 'artist_details_page.dart'; class AlbumDetailsPage extends StatefulWidget { const AlbumDetailsPage({Key? key, required this.album}) : super(key: key); @@ -48,6 +51,9 @@ class _AlbumDetailsPageState extends State { @override Widget build(BuildContext context) { final AudioStore audioStore = GetIt.I(); + final NavigationStore navStore = GetIt.I(); + final MusicDataStore musicDataStore = GetIt.I(); + return Scaffold( body: Material( @@ -55,6 +61,7 @@ class _AlbumDetailsPageState extends State { builder: (BuildContext context) { final album = widget.album; final songs = store.albumSongStream.value ?? []; + final artists = musicDataStore.artistStream.value ?? []; final totalDuration = songs.fold(const Duration(milliseconds: 0), (Duration d, s) => d + s.duration); final songsByDisc = _songsByDisc(store.albumSongStream.value ?? []); @@ -62,6 +69,9 @@ class _AlbumDetailsPageState extends State { for (int i = 0; i < songsByDisc.length - 1; i++) { discSongNums.add(songsByDisc[i].length + discSongNums[i]); } + Artist? albumArtist; + if (artists.isNotEmpty) + albumArtist = artists.singleWhere((a) => a.name == album.artist); return Scrollbar( child: CustomScrollView( @@ -123,6 +133,17 @@ class _AlbumDetailsPageState extends State { image: utils.getAlbumImage(album.albumArtPath), fit: BoxFit.cover, ), + onTapSubtitle: () async { + if (albumArtist != null) + navStore.pushOnLibrary( + MaterialPageRoute( + builder: (BuildContext context) => + ArtistDetailsPage( + artist: albumArtist!, + ), + ), + ); + }, backgroundColor: utils.bgColor(album.color), button: SizedBox( width: 48, diff --git a/src/lib/presentation/widgets/cover_sliver_appbar.dart b/src/lib/presentation/widgets/cover_sliver_appbar.dart index 825d2fe..f21fe4d 100644 --- a/src/lib/presentation/widgets/cover_sliver_appbar.dart +++ b/src/lib/presentation/widgets/cover_sliver_appbar.dart @@ -1,4 +1,5 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; @@ -15,6 +16,7 @@ class CoverSliverAppBar extends StatefulWidget { required this.cover, required this.backgroundColor, this.button, + this.onTapSubtitle, }) : super(key: key); final String title; @@ -24,6 +26,7 @@ class CoverSliverAppBar extends StatefulWidget { final Widget cover; final Color backgroundColor; final Widget? button; + final AsyncCallback? onTapSubtitle; @override State createState() => _CoverSliverAppBarState(); @@ -54,6 +57,7 @@ class _CoverSliverAppBarState extends State { subtitle: widget.subtitle, subtitle2: widget.subtitle2, button: widget.button, + onTapSubtitle: widget.onTapSubtitle, ), leading: IconButton( icon: const Icon(Icons.chevron_left_rounded), @@ -77,6 +81,7 @@ class Header extends StatelessWidget { required this.cover, required this.backgroundColor, this.button, + this.onTapSubtitle, }) : super(key: key); final String title; @@ -87,6 +92,7 @@ class Header extends StatelessWidget { final double maxHeight; final double minHeight; final Widget? button; + final AsyncCallback? onTapSubtitle; @override Widget build(BuildContext context) { @@ -110,6 +116,7 @@ class Header extends StatelessWidget { title: title, subtitle: subtitle, subtitle2: subtitle2, + onTapSubtitle: onTapSubtitle, ), ], ); @@ -142,6 +149,7 @@ class Header extends StatelessWidget { required String title, String? subtitle, String? subtitle2, + AsyncCallback? onTapSubtitle, }) { // TODO: padding right for enabled multi select return Align( @@ -183,17 +191,7 @@ class Header extends StatelessWidget { width: 10.0, ), if (subtitle != null) - Text( - subtitle, - maxLines: 1, - overflow: TextOverflow.fade, - style: TextStyle( - fontSize: Tween(begin: 0, end: 16).evaluate(animation), - color: Colors.white - .withOpacity(Tween(begin: 0, end: 1).evaluate(animation2)), - fontWeight: FontWeight.w500, - ), - ), + _buildSubtitle(context, subtitle, animation, animation2, onTapSubtitle), if (subtitle2 != null) Text( subtitle2, @@ -210,6 +208,48 @@ class Header extends StatelessWidget { ); } + Widget _buildSubtitle( + BuildContext context, + String subtitle, + Animation animation, + Animation animation2, + AsyncCallback? onTapSubtitle) { + if (onTapSubtitle == null) + return Text( + subtitle, + maxLines: 1, + overflow: TextOverflow.fade, + style: TextStyle( + fontSize: Tween(begin: 0, end: 16).evaluate(animation), + color: Colors.white.withOpacity( + Tween(begin: 0, end: 1).evaluate(animation2)), + fontWeight: FontWeight.w500, + ), + ); + return TextButton( + onPressed: onTapSubtitle, + style: TextButton.styleFrom( + padding: const EdgeInsets.symmetric(horizontal: 4), + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + backgroundColor: Colors.white24, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + side: const BorderSide(color: Colors.white24), + )), + child: Text( + subtitle, + maxLines: 1, + overflow: TextOverflow.fade, + style: TextStyle( + fontSize: Tween(begin: 0, end: 16).evaluate(animation), + color: Colors.white.withOpacity( + Tween(begin: 0, end: 1).evaluate(animation2)), + fontWeight: FontWeight.w500, + ), + )); + } + Widget _buildButton(Animation animation, BuildContext context) { return Positioned( width: 96,