mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
refactor: use metadata artist object for artist card and artist page
This commit is contained in:
parent
4b09f6c96b
commit
b8cae569b4
@ -15,17 +15,20 @@ abstract class FakeData {
|
||||
..href = "text"
|
||||
..total = 1;
|
||||
|
||||
static final Artist artist = Artist()
|
||||
..id = "1"
|
||||
..name = "Wow artist Good!"
|
||||
..images = [image]
|
||||
..popularity = 1
|
||||
..type = "type"
|
||||
..uri = "uri"
|
||||
..externalUrls = externalUrls
|
||||
..genres = ["genre"]
|
||||
..href = "text"
|
||||
..followers = followers;
|
||||
static final SpotubeFullArtistObject artist = SpotubeFullArtistObject(
|
||||
id: "1",
|
||||
name: "What an artist",
|
||||
externalUri: "https://example.com",
|
||||
followers: 10000,
|
||||
genres: ["genre"],
|
||||
images: [
|
||||
SpotubeImageObject(
|
||||
height: 100,
|
||||
width: 100,
|
||||
url: "https://dummyimage.com/100x100/cfcfcf/cfcfcf.jpg",
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
static final externalIds = ExternalIds()
|
||||
..isrc = "text"
|
||||
@ -40,7 +43,7 @@ abstract class FakeData {
|
||||
..label = "label"
|
||||
..popularity = 1
|
||||
..albumType = AlbumType.album
|
||||
..artists = [artist]
|
||||
// ..artists = [artist]
|
||||
..availableMarkets = [Market.BD]
|
||||
..externalUrls = externalUrls
|
||||
..href = "text"
|
||||
@ -83,7 +86,7 @@ abstract class FakeData {
|
||||
|
||||
static final Track track = Track()
|
||||
..id = "1"
|
||||
..artists = [artist, artist, artist]
|
||||
// ..artists = [artist, artist, artist]
|
||||
// ..album = albumSimple
|
||||
..availableMarkets = [Market.BD]
|
||||
..discNumber = 1
|
||||
|
@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
|
||||
import 'package:skeletonizer/skeletonizer.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/collections/fake.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/modules/album/album_card.dart';
|
||||
@ -31,14 +30,16 @@ class HorizontalPlaybuttonCardView<T> extends HookWidget {
|
||||
}) : assert(
|
||||
items.every(
|
||||
(item) =>
|
||||
item is PlaylistSimple || item is Artist || item is AlbumSimple,
|
||||
item is SpotubeSimpleAlbumObject ||
|
||||
item is SpotubeSimplePlaylistObject ||
|
||||
item is SpotubeFullArtistObject,
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scrollController = useScrollController();
|
||||
final isArtist = items.every((s) => s is Artist);
|
||||
final isArtist = items.every((s) => s is SpotubeFullArtistObject);
|
||||
final scale = context.theme.scaling;
|
||||
|
||||
return Padding(
|
||||
@ -99,11 +100,12 @@ class HorizontalPlaybuttonCardView<T> extends HookWidget {
|
||||
final item = items[index];
|
||||
|
||||
return switch (item) {
|
||||
PlaylistSimple() =>
|
||||
SpotubeSimplePlaylistObject() =>
|
||||
PlaylistCard(item as SpotubeSimplePlaylistObject),
|
||||
AlbumSimple() =>
|
||||
SpotubeSimpleAlbumObject() =>
|
||||
AlbumCard(item as SpotubeSimpleAlbumObject),
|
||||
Artist() => ArtistCard(item as Artist),
|
||||
SpotubeFullArtistObject() =>
|
||||
ArtistCard(item as SpotubeFullArtistObject),
|
||||
_ => const SizedBox.shrink(),
|
||||
};
|
||||
}),
|
||||
|
@ -1,8 +1,9 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/artist/albums.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
class ArtistAlbumList extends HookConsumerWidget {
|
||||
@ -15,15 +16,15 @@ class ArtistAlbumList extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final albumsQuery = ref.watch(artistAlbumsProvider(artistId));
|
||||
final albumsQuery = ref.watch(metadataPluginArtistAlbumsProvider(artistId));
|
||||
final albumsQueryNotifier =
|
||||
ref.watch(artistAlbumsProvider(artistId).notifier);
|
||||
ref.watch(metadataPluginArtistAlbumsProvider(artistId).notifier);
|
||||
|
||||
final albums = albumsQuery.asData?.value.items ?? [];
|
||||
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return HorizontalPlaybuttonCardView<Album>(
|
||||
return HorizontalPlaybuttonCardView<SpotubeSimpleAlbumObject>(
|
||||
isLoadingNextPage: albumsQuery.isLoadingNextPage,
|
||||
hasNextPage: albumsQuery.asData?.value.hasMore ?? false,
|
||||
items: albums,
|
||||
|
@ -4,16 +4,15 @@ import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/collections/routes.gr.dart';
|
||||
import 'package:spotube/components/image/universal_image.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/extensions/image.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
|
||||
import 'package:spotube/provider/blacklist_provider.dart';
|
||||
|
||||
class ArtistCard extends HookConsumerWidget {
|
||||
final Artist artist;
|
||||
final SpotubeFullArtistObject artist;
|
||||
const ArtistCard(this.artist, {super.key});
|
||||
|
||||
@override
|
||||
@ -36,18 +35,18 @@ class ArtistCard extends HookConsumerWidget {
|
||||
width: 180,
|
||||
child: Button.card(
|
||||
onPressed: () {
|
||||
context.navigateTo(ArtistRoute(artistId: artist.id!));
|
||||
context.navigateTo(ArtistRoute(artistId: artist.id));
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Avatar(
|
||||
initials: artist.name!.trim()[0].toUpperCase(),
|
||||
initials: artist.name.trim()[0].toUpperCase(),
|
||||
provider: backgroundImage,
|
||||
size: 130,
|
||||
),
|
||||
const Gap(10),
|
||||
AutoSizeText(
|
||||
artist.name!,
|
||||
artist.name,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -11,8 +11,9 @@ import 'package:spotube/extensions/context.dart';
|
||||
|
||||
import 'package:spotube/pages/artist/section/footer.dart';
|
||||
import 'package:spotube/pages/artist/section/header.dart';
|
||||
import 'package:spotube/pages/artist/section/related_artists.dart';
|
||||
// import 'package:spotube/pages/artist/section/related_artists.dart';
|
||||
import 'package:spotube/pages/artist/section/top_tracks.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/artist/artist.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
|
||||
@ -31,7 +32,7 @@ class ArtistPage extends HookConsumerWidget {
|
||||
final scrollController = useScrollController();
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final artistQuery = ref.watch(artistProvider(artistId));
|
||||
final artistQuery = ref.watch(metadataPluginArtistProvider(artistId));
|
||||
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
@ -74,16 +75,16 @@ class ArtistPage extends HookConsumerWidget {
|
||||
ArtistPageTopTracks(artistId: artistId),
|
||||
const SliverGap(20),
|
||||
SliverToBoxAdapter(child: ArtistAlbumList(artistId)),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Text(
|
||||
context.l10n.fans_also_like,
|
||||
style: theme.typography.h4,
|
||||
),
|
||||
),
|
||||
),
|
||||
ArtistPageRelatedArtists(artistId: artistId),
|
||||
// SliverPadding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// sliver: SliverToBoxAdapter(
|
||||
// child: Text(
|
||||
// context.l10n.fans_also_like,
|
||||
// style: theme.typography.h4,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ArtistPageRelatedArtists(artistId: artistId),
|
||||
const SliverGap(20),
|
||||
if (artistQuery.asData?.value != null)
|
||||
SliverToBoxAdapter(
|
||||
|
@ -1,17 +1,16 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/image/universal_image.dart';
|
||||
import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/image.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
class ArtistPageFooter extends ConsumerWidget {
|
||||
final Artist artist;
|
||||
final SpotubeFullArtistObject artist;
|
||||
const ArtistPageFooter({super.key, required this.artist});
|
||||
|
||||
@override
|
||||
|
@ -8,10 +8,11 @@ import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/image/universal_image.dart';
|
||||
import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/extensions/image.dart';
|
||||
import 'package:spotube/models/database/database.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/blacklist_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/artist/artist.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
import 'package:spotube/utils/primitive_utils.dart';
|
||||
|
||||
@ -21,7 +22,7 @@ class ArtistPageHeader extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final artistQuery = ref.watch(artistProvider(artistId));
|
||||
final artistQuery = ref.watch(metadataPluginArtistProvider(artistId));
|
||||
final artist = artistQuery.asData?.value ?? FakeData.artist;
|
||||
|
||||
final theme = Theme.of(context);
|
||||
@ -30,7 +31,7 @@ class ArtistPageHeader extends HookConsumerWidget {
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
ref.watch(blacklistProvider);
|
||||
final blacklistNotifier = ref.watch(blacklistProvider.notifier);
|
||||
final isBlackListed = blacklistNotifier.containsArtist(artist);
|
||||
final isBlackListed = /* blacklistNotifier.containsArtist(artist) */ false;
|
||||
|
||||
final image = artist.images.asUrlString(
|
||||
placeholder: ImagePlaceholder.artist,
|
||||
@ -111,13 +112,11 @@ class ArtistPageHeader extends HookConsumerWidget {
|
||||
IconButton.ghost(
|
||||
icon: const Icon(SpotubeIcons.share),
|
||||
onPressed: () async {
|
||||
if (artist.externalUrls?.spotify != null) {
|
||||
await Clipboard.setData(
|
||||
ClipboardData(
|
||||
text: artist.externalUrls!.spotify!,
|
||||
text: artist.externalUri,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (!context.mounted) return;
|
||||
|
||||
@ -199,7 +198,7 @@ class ArtistPageHeader extends HookConsumerWidget {
|
||||
child: AutoSizeText(
|
||||
context.l10n.followers(
|
||||
PrimitiveUtils.toReadableNumber(
|
||||
artist.followers!.total!.toDouble(),
|
||||
artist.followers!.toDouble(),
|
||||
),
|
||||
),
|
||||
maxLines: 1,
|
||||
|
@ -3,6 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/modules/artist/artist_card.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
@Deprecated("Related artists are no longer supported by Spotube")
|
||||
class ArtistPageRelatedArtists extends ConsumerWidget {
|
||||
final String artistId;
|
||||
const ArtistPageRelatedArtists({
|
||||
@ -28,7 +29,11 @@ class ArtistPageRelatedArtists extends ConsumerWidget {
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final artist = artists.elementAt(index);
|
||||
return ArtistCard(artist);
|
||||
return SizedBox(
|
||||
width: 180,
|
||||
// child: ArtistCard(artist),
|
||||
);
|
||||
// return ArtistCard(artist);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -17,7 +17,8 @@ import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart';
|
||||
import 'package:spotube/components/waypoint.dart';
|
||||
import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/library/artists.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
|
||||
@ -28,10 +29,11 @@ class UserArtistsPage extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
|
||||
final artistQuery = ref.watch(followedArtistsProvider);
|
||||
final artistQueryNotifier = ref.watch(followedArtistsProvider.notifier);
|
||||
final artistQuery = ref.watch(metadataPluginSavedArtistsProvider);
|
||||
final artistQueryNotifier =
|
||||
ref.watch(metadataPluginSavedArtistsProvider.notifier);
|
||||
|
||||
final searchText = useState('');
|
||||
|
||||
@ -43,7 +45,7 @@ class UserArtistsPage extends HookConsumerWidget {
|
||||
}
|
||||
return artists
|
||||
.map((e) => (
|
||||
weightedRatio(e.name!, searchText.value),
|
||||
weightedRatio(e.name, searchText.value),
|
||||
e,
|
||||
))
|
||||
.sorted((a, b) => b.$1.compareTo(a.$1))
|
||||
@ -54,7 +56,7 @@ class UserArtistsPage extends HookConsumerWidget {
|
||||
|
||||
final controller = useScrollController();
|
||||
|
||||
if (auth.asData?.value == null) {
|
||||
if (authenticated.asData?.value != true) {
|
||||
return const AnonymousFallback();
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class MetadataPluginArtistAlbumNotifier
|
||||
}
|
||||
}
|
||||
|
||||
final metadataPluginArtistAlbumsProvider = AsyncNotifierFamilyProvider<
|
||||
final metadataPluginArtistAlbumsProvider = AsyncNotifierProviderFamily<
|
||||
MetadataPluginArtistAlbumNotifier,
|
||||
SpotubePaginationResponseObject<SpotubeSimpleAlbumObject>,
|
||||
String>(
|
||||
|
@ -10,10 +10,12 @@ class MetadataPluginSavedArtistNotifier
|
||||
int offset,
|
||||
int limit,
|
||||
) async {
|
||||
return await (await metadataPlugin).user.savedArtists(
|
||||
final artists = await (await metadataPlugin).user.savedArtists(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
);
|
||||
|
||||
return artists;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1,8 +1,8 @@
|
||||
part of '../spotify.dart';
|
||||
|
||||
final artistWikipediaSummaryProvider = FutureProvider.autoDispose
|
||||
.family<Summary?, ArtistSimple>((ref, artist) async {
|
||||
final query = artist.name!.replaceAll(" ", "_");
|
||||
.family<Summary?, SpotubeFullArtistObject>((ref, artist) async {
|
||||
final query = artist.name.replaceAll(" ", "_");
|
||||
final res = await wikipedia.pageContent.pageSummaryTitleGet(query);
|
||||
|
||||
if (res?.type != "standard") {
|
||||
|
@ -7,6 +7,7 @@ import 'package:drift/drift.dart';
|
||||
import 'package:spotube/collections/assets.gen.dart';
|
||||
import 'package:spotube/collections/env.dart';
|
||||
import 'package:spotube/models/database/database.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/database/database.dart';
|
||||
import 'package:spotube/services/logger/logger.dart';
|
||||
|
Loading…
Reference in New Issue
Block a user