mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
parent
00f1b3422f
commit
abfdbc63ce
@ -28,6 +28,7 @@ class TrackDetailsDialog extends HookWidget {
|
||||
artists: track.artists ?? <Artist>[],
|
||||
mainAxisAlignment: WrapAlignment.start,
|
||||
textStyle: const TextStyle(color: Colors.blue),
|
||||
hideOverflowArtist: false,
|
||||
),
|
||||
context.l10n.album: LinkText(
|
||||
track.album!.name!,
|
||||
|
@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:spotify/spotify.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/utils/service_utils.dart';
|
||||
|
||||
@ -9,7 +11,9 @@ class ArtistLink extends StatelessWidget {
|
||||
final WrapCrossAlignment crossAxisAlignment;
|
||||
final WrapAlignment mainAxisAlignment;
|
||||
final TextStyle textStyle;
|
||||
final bool hideOverflowArtist;
|
||||
final void Function(String route)? onRouteChange;
|
||||
final VoidCallback? onOverflowArtistClick;
|
||||
|
||||
const ArtistLink({
|
||||
super.key,
|
||||
@ -18,44 +22,61 @@ class ArtistLink extends StatelessWidget {
|
||||
this.mainAxisAlignment = WrapAlignment.center,
|
||||
this.textStyle = const TextStyle(),
|
||||
this.onRouteChange,
|
||||
});
|
||||
this.hideOverflowArtist = true,
|
||||
this.onOverflowArtistClick,
|
||||
}) : assert(hideOverflowArtist ? onOverflowArtistClick != null : true);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData(:colorScheme) = Theme.of(context);
|
||||
|
||||
return Wrap(
|
||||
crossAxisAlignment: crossAxisAlignment,
|
||||
alignment: mainAxisAlignment,
|
||||
children: artists
|
||||
.asMap()
|
||||
.entries
|
||||
.map(
|
||||
(artist) => Builder(builder: (context) {
|
||||
if (artist.value.name == null) {
|
||||
return Text("Spotify", style: textStyle);
|
||||
}
|
||||
return AnchorButton(
|
||||
(artist.key != artists.length - 1)
|
||||
? "${artist.value.name}, "
|
||||
: artist.value.name!,
|
||||
onTap: () {
|
||||
if (onRouteChange != null) {
|
||||
onRouteChange?.call("/artist/${artist.value.id}");
|
||||
} else {
|
||||
ServiceUtils.pushNamed(
|
||||
context,
|
||||
ArtistPage.name,
|
||||
pathParameters: {
|
||||
"id": artist.value.id!,
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: textStyle,
|
||||
);
|
||||
}),
|
||||
)
|
||||
.toList(),
|
||||
children: [
|
||||
...(hideOverflowArtist ? artists.take(3).toList() : artists)
|
||||
.asMap()
|
||||
.entries
|
||||
.map(
|
||||
(artist) => Builder(builder: (context) {
|
||||
if (artist.value.name == null) {
|
||||
return Text("Spotify", style: textStyle);
|
||||
}
|
||||
return AnchorButton(
|
||||
(artist.key != artists.length - 1)
|
||||
? "${artist.value.name}, "
|
||||
: artist.value.name!,
|
||||
onTap: () {
|
||||
if (onRouteChange != null) {
|
||||
onRouteChange?.call("/artist/${artist.value.id}");
|
||||
} else {
|
||||
ServiceUtils.pushNamed(
|
||||
context,
|
||||
ArtistPage.name,
|
||||
pathParameters: {
|
||||
"id": artist.value.id!,
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: textStyle,
|
||||
);
|
||||
}),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/extensions/image.dart';
|
||||
import 'package:spotube/models/database/database.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/blacklist_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/spotify/spotify.dart';
|
||||
import 'package:spotube/provider/spotify_provider.dart';
|
||||
import 'package:spotube/utils/service_utils.dart';
|
||||
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
@ -313,7 +315,16 @@ class TrackOptions extends HookConsumerWidget {
|
||||
),
|
||||
subtitle: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: ArtistLink(artists: track.artists!),
|
||||
child: ArtistLink(
|
||||
artists: track.artists!,
|
||||
onOverflowArtistClick: () => ServiceUtils.pushNamed(
|
||||
context,
|
||||
TrackPage.name,
|
||||
pathParameters: {
|
||||
"id": track.id!,
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -17,9 +17,11 @@ import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/duration.dart';
|
||||
import 'package:spotube/extensions/image.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/state.dart';
|
||||
import 'package:spotube/provider/blacklist_provider.dart';
|
||||
import 'package:spotube/utils/service_utils.dart';
|
||||
|
||||
class TrackTile extends HookConsumerWidget {
|
||||
/// [index] will not be shown if null
|
||||
@ -245,7 +247,16 @@ class TrackTile extends HookConsumerWidget {
|
||||
: ClipRect(
|
||||
child: ConstrainedBox(
|
||||
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!,
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -325,5 +325,6 @@
|
||||
"connect_client_alert": "You're being controlled by {client}",
|
||||
"this_device": "This Device",
|
||||
"remote": "Remote",
|
||||
"stats": "Stats"
|
||||
"stats": "Stats",
|
||||
"and_n_more": "and {count} more"
|
||||
}
|
@ -7,9 +7,11 @@ import 'package:spotube/components/image/universal_image.dart';
|
||||
import 'package:spotube/components/links/artist_link.dart';
|
||||
import 'package:spotube/extensions/context.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/services/download_manager/download_status.dart';
|
||||
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
||||
import 'package:spotube/utils/service_utils.dart';
|
||||
|
||||
class DownloadItem extends HookConsumerWidget {
|
||||
final Track track;
|
||||
@ -62,6 +64,13 @@ class DownloadItem extends HookConsumerWidget {
|
||||
subtitle: ArtistLink(
|
||||
artists: track.artists ?? <Artist>[],
|
||||
mainAxisAlignment: WrapAlignment.start,
|
||||
onOverflowArtistClick: () => ServiceUtils.pushNamed(
|
||||
context,
|
||||
TrackPage.name,
|
||||
pathParameters: {
|
||||
"id": track.id!,
|
||||
},
|
||||
),
|
||||
),
|
||||
trailing: isQueryingSourceInfo
|
||||
? Text(
|
||||
|
@ -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/models/local_track.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/audio_player/audio_player.dart';
|
||||
import 'package:spotube/provider/server/active_sourced_track.dart';
|
||||
import 'package:spotube/provider/volume_provider.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';
|
||||
|
||||
@ -260,6 +262,14 @@ class PlayerView extends HookConsumerWidget {
|
||||
panelController.close();
|
||||
GoRouter.of(context).push(route);
|
||||
},
|
||||
onOverflowArtistClick: () =>
|
||||
ServiceUtils.pushNamed(
|
||||
context,
|
||||
TrackPage.name,
|
||||
pathParameters: {
|
||||
"id": currentTrack!.id!,
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -9,6 +9,7 @@ import 'package:spotube/components/links/link_text.dart';
|
||||
import 'package:spotube/extensions/artist_simple.dart';
|
||||
import 'package:spotube/extensions/constrains.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/utils/service_utils.dart';
|
||||
|
||||
@ -81,6 +82,13 @@ class PlayerTrackDetails extends HookConsumerWidget {
|
||||
onRouteChange: (route) {
|
||||
ServiceUtils.push(context, route);
|
||||
},
|
||||
onOverflowArtistClick: () => ServiceUtils.pushNamed(
|
||||
context,
|
||||
TrackPage.name,
|
||||
pathParameters: {
|
||||
"id": track!.id!,
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -35,6 +35,13 @@ class StatsAlbumItem extends StatelessWidget {
|
||||
child: ArtistLink(
|
||||
artists: album.artists ?? [],
|
||||
mainAxisAlignment: WrapAlignment.start,
|
||||
onOverflowArtistClick: () => ServiceUtils.pushNamed(
|
||||
context,
|
||||
AlbumPage.name,
|
||||
pathParameters: {
|
||||
"id": album.id!,
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -33,6 +33,13 @@ class StatsTrackItem extends StatelessWidget {
|
||||
subtitle: ArtistLink(
|
||||
artists: track.artists!,
|
||||
mainAxisAlignment: WrapAlignment.start,
|
||||
onOverflowArtistClick: () => ServiceUtils.pushNamed(
|
||||
context,
|
||||
TrackPage.name,
|
||||
pathParameters: {
|
||||
"id": track.id!,
|
||||
},
|
||||
),
|
||||
),
|
||||
trailing: info,
|
||||
onTap: () {
|
||||
|
@ -144,6 +144,14 @@ class ConnectControlPage extends HookConsumerWidget {
|
||||
artists: playlist.activeTrack?.artists ?? [],
|
||||
textStyle: textTheme.bodyMedium!,
|
||||
mainAxisAlignment: WrapAlignment.start,
|
||||
onOverflowArtistClick: () =>
|
||||
ServiceUtils.pushNamed(
|
||||
context,
|
||||
TrackPage.name,
|
||||
pathParameters: {
|
||||
"id": playlist.activeTrack!.id!,
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -148,7 +148,12 @@ class TrackPage extends HookConsumerWidget {
|
||||
children: [
|
||||
const Icon(SpotubeIcons.artist),
|
||||
const Gap(5),
|
||||
ArtistLink(artists: track.artists!),
|
||||
Flexible(
|
||||
child: ArtistLink(
|
||||
artists: track.artists!,
|
||||
hideOverflowArtist: false,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Gap(10),
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user