mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
parent
00f1b3422f
commit
abfdbc63ce
@ -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!,
|
||||||
|
@ -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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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!,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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!,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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"
|
||||||
}
|
}
|
@ -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(
|
||||||
|
@ -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!,
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -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!,
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -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!,
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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: () {
|
||||||
|
@ -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!,
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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),
|
||||||
|
@ -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