fix: Too many artists for a track causing overflows

#1470
This commit is contained in:
Kingkor Roy Tirtho 2024-07-09 23:08:21 +06:00
parent 00f1b3422f
commit abfdbc63ce
13 changed files with 240 additions and 37 deletions

View File

@ -28,6 +28,7 @@ class TrackDetailsDialog extends HookWidget {
artists: track.artists ?? <Artist>[], artists: track.artists ?? <Artist>[],
mainAxisAlignment: WrapAlignment.start, mainAxisAlignment: WrapAlignment.start,
textStyle: const TextStyle(color: Colors.blue), textStyle: const TextStyle(color: Colors.blue),
hideOverflowArtist: false,
), ),
context.l10n.album: LinkText( context.l10n.album: LinkText(
track.album!.name!, track.album!.name!,

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/links/anchor_button.dart'; import 'package:spotube/components/links/anchor_button.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/pages/artist/artist.dart'; import 'package:spotube/pages/artist/artist.dart';
import 'package:spotube/utils/service_utils.dart'; import 'package:spotube/utils/service_utils.dart';
@ -9,7 +11,9 @@ class ArtistLink extends StatelessWidget {
final WrapCrossAlignment crossAxisAlignment; final WrapCrossAlignment crossAxisAlignment;
final WrapAlignment mainAxisAlignment; final WrapAlignment mainAxisAlignment;
final TextStyle textStyle; final TextStyle textStyle;
final bool hideOverflowArtist;
final void Function(String route)? onRouteChange; final void Function(String route)? onRouteChange;
final VoidCallback? onOverflowArtistClick;
const ArtistLink({ const ArtistLink({
super.key, super.key,
@ -18,14 +22,19 @@ class ArtistLink extends StatelessWidget {
this.mainAxisAlignment = WrapAlignment.center, this.mainAxisAlignment = WrapAlignment.center,
this.textStyle = const TextStyle(), this.textStyle = const TextStyle(),
this.onRouteChange, this.onRouteChange,
}); this.hideOverflowArtist = true,
this.onOverflowArtistClick,
}) : assert(hideOverflowArtist ? onOverflowArtistClick != null : true);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData(:colorScheme) = Theme.of(context);
return Wrap( return Wrap(
crossAxisAlignment: crossAxisAlignment, crossAxisAlignment: crossAxisAlignment,
alignment: mainAxisAlignment, alignment: mainAxisAlignment,
children: artists children: [
...(hideOverflowArtist ? artists.take(3).toList() : artists)
.asMap() .asMap()
.entries .entries
.map( .map(
@ -54,8 +63,20 @@ class ArtistLink extends StatelessWidget {
style: textStyle, style: textStyle,
); );
}), }),
) ),
.toList(), if (hideOverflowArtist && artists.length > 3)
AnchorButton(
context.l10n.and_n_more(artists.length - 3),
onTap: () {
onOverflowArtistClick?.call();
},
overflow: TextOverflow.ellipsis,
style: textStyle.copyWith(
color: colorScheme.secondary,
decoration: TextDecoration.underline,
),
),
],
); );
} }
} }

View File

@ -20,6 +20,7 @@ import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart'; import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/database/database.dart'; import 'package:spotube/models/database/database.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/pages/track/track.dart';
import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/authentication/authentication.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart';
@ -27,6 +28,7 @@ import 'package:spotube/provider/local_tracks/local_tracks_provider.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/audio_player.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/provider/spotify_provider.dart'; import 'package:spotube/provider/spotify_provider.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@ -313,7 +315,16 @@ class TrackOptions extends HookConsumerWidget {
), ),
subtitle: Align( subtitle: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: ArtistLink(artists: track.artists!), child: ArtistLink(
artists: track.artists!,
onOverflowArtistClick: () => ServiceUtils.pushNamed(
context,
TrackPage.name,
pathParameters: {
"id": track.id!,
},
),
),
), ),
), ),
], ],

View File

@ -17,9 +17,11 @@ import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/duration.dart'; import 'package:spotube/extensions/duration.dart';
import 'package:spotube/extensions/image.dart'; import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/pages/track/track.dart';
import 'package:spotube/provider/audio_player/querying_track_info.dart'; import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/provider/audio_player/state.dart'; import 'package:spotube/provider/audio_player/state.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
import 'package:spotube/utils/service_utils.dart';
class TrackTile extends HookConsumerWidget { class TrackTile extends HookConsumerWidget {
/// [index] will not be shown if null /// [index] will not be shown if null
@ -245,7 +247,16 @@ class TrackTile extends HookConsumerWidget {
: ClipRect( : ClipRect(
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 40), constraints: const BoxConstraints(maxHeight: 40),
child: ArtistLink(artists: track.artists ?? []), child: ArtistLink(
artists: track.artists ?? [],
onOverflowArtistClick: () => ServiceUtils.pushNamed(
context,
TrackPage.name,
pathParameters: {
"id": track.id!,
},
),
),
), ),
), ),
), ),

View File

@ -325,5 +325,6 @@
"connect_client_alert": "You're being controlled by {client}", "connect_client_alert": "You're being controlled by {client}",
"this_device": "This Device", "this_device": "This Device",
"remote": "Remote", "remote": "Remote",
"stats": "Stats" "stats": "Stats",
"and_n_more": "and {count} more"
} }

View File

@ -7,9 +7,11 @@ import 'package:spotube/components/image/universal_image.dart';
import 'package:spotube/components/links/artist_link.dart'; import 'package:spotube/components/links/artist_link.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart'; import 'package:spotube/extensions/image.dart';
import 'package:spotube/pages/track/track.dart';
import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart';
import 'package:spotube/services/download_manager/download_status.dart'; import 'package:spotube/services/download_manager/download_status.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart'; import 'package:spotube/services/sourced_track/sourced_track.dart';
import 'package:spotube/utils/service_utils.dart';
class DownloadItem extends HookConsumerWidget { class DownloadItem extends HookConsumerWidget {
final Track track; final Track track;
@ -62,6 +64,13 @@ class DownloadItem extends HookConsumerWidget {
subtitle: ArtistLink( subtitle: ArtistLink(
artists: track.artists ?? <Artist>[], artists: track.artists ?? <Artist>[],
mainAxisAlignment: WrapAlignment.start, mainAxisAlignment: WrapAlignment.start,
onOverflowArtistClick: () => ServiceUtils.pushNamed(
context,
TrackPage.name,
pathParameters: {
"id": track.id!,
},
),
), ),
trailing: isQueryingSourceInfo trailing: isQueryingSourceInfo
? Text( ? Text(

View File

@ -24,11 +24,13 @@ import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart';
import 'package:spotube/hooks/utils/use_palette_color.dart'; import 'package:spotube/hooks/utils/use_palette_color.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/pages/lyrics/lyrics.dart'; import 'package:spotube/pages/lyrics/lyrics.dart';
import 'package:spotube/pages/track/track.dart';
import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/authentication/authentication.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/audio_player.dart';
import 'package:spotube/provider/server/active_sourced_track.dart'; import 'package:spotube/provider/server/active_sourced_track.dart';
import 'package:spotube/provider/volume_provider.dart'; import 'package:spotube/provider/volume_provider.dart';
import 'package:spotube/services/sourced_track/sources/youtube.dart'; import 'package:spotube/services/sourced_track/sources/youtube.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@ -260,6 +262,14 @@ class PlayerView extends HookConsumerWidget {
panelController.close(); panelController.close();
GoRouter.of(context).push(route); GoRouter.of(context).push(route);
}, },
onOverflowArtistClick: () =>
ServiceUtils.pushNamed(
context,
TrackPage.name,
pathParameters: {
"id": currentTrack!.id!,
},
),
), ),
], ],
), ),

View File

@ -9,6 +9,7 @@ import 'package:spotube/components/links/link_text.dart';
import 'package:spotube/extensions/artist_simple.dart'; import 'package:spotube/extensions/artist_simple.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/image.dart'; import 'package:spotube/extensions/image.dart';
import 'package:spotube/pages/track/track.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/audio_player.dart';
import 'package:spotube/utils/service_utils.dart'; import 'package:spotube/utils/service_utils.dart';
@ -81,6 +82,13 @@ class PlayerTrackDetails extends HookConsumerWidget {
onRouteChange: (route) { onRouteChange: (route) {
ServiceUtils.push(context, route); ServiceUtils.push(context, route);
}, },
onOverflowArtistClick: () => ServiceUtils.pushNamed(
context,
TrackPage.name,
pathParameters: {
"id": track!.id!,
},
),
) )
], ],
), ),

View File

@ -35,6 +35,13 @@ class StatsAlbumItem extends StatelessWidget {
child: ArtistLink( child: ArtistLink(
artists: album.artists ?? [], artists: album.artists ?? [],
mainAxisAlignment: WrapAlignment.start, mainAxisAlignment: WrapAlignment.start,
onOverflowArtistClick: () => ServiceUtils.pushNamed(
context,
AlbumPage.name,
pathParameters: {
"id": album.id!,
},
),
), ),
), ),
], ],

View File

@ -33,6 +33,13 @@ class StatsTrackItem extends StatelessWidget {
subtitle: ArtistLink( subtitle: ArtistLink(
artists: track.artists!, artists: track.artists!,
mainAxisAlignment: WrapAlignment.start, mainAxisAlignment: WrapAlignment.start,
onOverflowArtistClick: () => ServiceUtils.pushNamed(
context,
TrackPage.name,
pathParameters: {
"id": track.id!,
},
),
), ),
trailing: info, trailing: info,
onTap: () { onTap: () {

View File

@ -144,6 +144,14 @@ class ConnectControlPage extends HookConsumerWidget {
artists: playlist.activeTrack?.artists ?? [], artists: playlist.activeTrack?.artists ?? [],
textStyle: textTheme.bodyMedium!, textStyle: textTheme.bodyMedium!,
mainAxisAlignment: WrapAlignment.start, mainAxisAlignment: WrapAlignment.start,
onOverflowArtistClick: () =>
ServiceUtils.pushNamed(
context,
TrackPage.name,
pathParameters: {
"id": playlist.activeTrack!.id!,
},
),
), ),
), ),
], ],

View File

@ -148,7 +148,12 @@ class TrackPage extends HookConsumerWidget {
children: [ children: [
const Icon(SpotubeIcons.artist), const Icon(SpotubeIcons.artist),
const Gap(5), const Gap(5),
ArtistLink(artists: track.artists!), Flexible(
child: ArtistLink(
artists: track.artists!,
hideOverflowArtist: false,
),
),
], ],
), ),
const Gap(10), const Gap(10),

View File

@ -1 +1,105 @@
{} {
"ar": [
"and_n_more"
],
"bn": [
"and_n_more"
],
"ca": [
"and_n_more"
],
"cs": [
"and_n_more"
],
"de": [
"and_n_more"
],
"es": [
"and_n_more"
],
"eu": [
"and_n_more"
],
"fa": [
"and_n_more"
],
"fi": [
"and_n_more"
],
"fr": [
"and_n_more"
],
"hi": [
"and_n_more"
],
"id": [
"and_n_more"
],
"it": [
"and_n_more"
],
"ja": [
"and_n_more"
],
"ka": [
"and_n_more"
],
"ko": [
"and_n_more"
],
"ne": [
"and_n_more"
],
"nl": [
"and_n_more"
],
"pl": [
"and_n_more"
],
"pt": [
"and_n_more"
],
"ru": [
"and_n_more"
],
"th": [
"and_n_more"
],
"tr": [
"and_n_more"
],
"uk": [
"and_n_more"
],
"vi": [
"and_n_more"
],
"zh": [
"and_n_more"
]
}