mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
feat: add artist and album providers
This commit is contained in:
parent
326d8212f6
commit
758b0bc9d9
22
lib/provider/metadata_plugin/album/album.dart
Normal file
22
lib/provider/metadata_plugin/album/album.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/error.dart';
|
||||
|
||||
final metadataPluginAlbumProvider =
|
||||
FutureProvider.autoDispose.family<SpotubeFullAlbumObject, String>(
|
||||
(ref, id) async {
|
||||
ref.cacheFor();
|
||||
|
||||
final metadataPlugin = await ref.watch(metadataPluginProvider.future);
|
||||
|
||||
if (metadataPlugin == null) {
|
||||
throw MetadataPluginException.noDefaultPlugin(
|
||||
"No metadata plugin is not set",
|
||||
);
|
||||
}
|
||||
|
||||
return metadataPlugin.album.getAlbum(id);
|
||||
},
|
||||
);
|
32
lib/provider/metadata_plugin/artist/albums.dart
Normal file
32
lib/provider/metadata_plugin/artist/albums.dart
Normal file
@ -0,0 +1,32 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/family_paginated.dart';
|
||||
|
||||
class MetadataPluginArtistAlbumNotifier
|
||||
extends FamilyPaginatedAsyncNotifier<SpotubeSimpleAlbumObject, String> {
|
||||
@override
|
||||
Future<SpotubePaginationResponseObject<SpotubeSimpleAlbumObject>> fetch(
|
||||
int offset,
|
||||
int limit,
|
||||
) async {
|
||||
return await (await metadataPlugin).artist.albums(
|
||||
arg,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
build(arg) async {
|
||||
ref.watch(metadataPluginProvider);
|
||||
return await fetch(0, 20);
|
||||
}
|
||||
}
|
||||
|
||||
final metadataPluginArtistAlbumsProvider = AsyncNotifierFamilyProvider<
|
||||
MetadataPluginArtistAlbumNotifier,
|
||||
SpotubePaginationResponseObject<SpotubeSimpleAlbumObject>,
|
||||
String>(
|
||||
() => MetadataPluginArtistAlbumNotifier(),
|
||||
);
|
22
lib/provider/metadata_plugin/artist/artist.dart
Normal file
22
lib/provider/metadata_plugin/artist/artist.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/error.dart';
|
||||
|
||||
final metadataPluginArtistProvider =
|
||||
FutureProvider.autoDispose.family<SpotubeFullArtistObject, String>(
|
||||
(ref, artistId) async {
|
||||
ref.cacheFor();
|
||||
|
||||
final metadataPlugin = await ref.watch(metadataPluginProvider.future);
|
||||
|
||||
if (metadataPlugin == null) {
|
||||
throw MetadataPluginException.noDefaultPlugin(
|
||||
"No metadata plugin is not set",
|
||||
);
|
||||
}
|
||||
|
||||
return metadataPlugin.artist.getArtist(artistId);
|
||||
},
|
||||
);
|
38
lib/provider/metadata_plugin/artist/top_tracks.dart
Normal file
38
lib/provider/metadata_plugin/artist/top_tracks.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/family_paginated.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
|
||||
class MetadataPluginArtistTopTracksNotifier
|
||||
extends AutoDisposeFamilyPaginatedAsyncNotifier<SpotubeFullTrackObject,
|
||||
String> {
|
||||
MetadataPluginArtistTopTracksNotifier() : super();
|
||||
|
||||
@override
|
||||
fetch(offset, limit) async {
|
||||
final tracks = await (await metadataPlugin).artist.topTracks(
|
||||
arg,
|
||||
offset: offset,
|
||||
limit: limit,
|
||||
);
|
||||
|
||||
return tracks;
|
||||
}
|
||||
|
||||
@override
|
||||
build(arg) async {
|
||||
ref.cacheFor();
|
||||
|
||||
ref.watch(metadataPluginProvider);
|
||||
return await fetch(0, 20);
|
||||
}
|
||||
}
|
||||
|
||||
final metadataPluginArtistTopTracksProvider =
|
||||
AutoDisposeAsyncNotifierProviderFamily<
|
||||
MetadataPluginArtistTopTracksNotifier,
|
||||
SpotubePaginationResponseObject<SpotubeFullTrackObject>,
|
||||
String>(
|
||||
() => MetadataPluginArtistTopTracksNotifier(),
|
||||
);
|
@ -0,0 +1,73 @@
|
||||
import 'package:riverpod/riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/paginated.dart';
|
||||
|
||||
class MetadataPluginSavedArtistNotifier
|
||||
extends PaginatedAsyncNotifier<SpotubeFullArtistObject> {
|
||||
@override
|
||||
Future<SpotubePaginationResponseObject<SpotubeFullArtistObject>> fetch(
|
||||
int offset,
|
||||
int limit,
|
||||
) async {
|
||||
return await (await metadataPlugin).user.savedArtists(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
build() async {
|
||||
ref.watch(metadataPluginProvider);
|
||||
return await fetch(0, 20);
|
||||
}
|
||||
|
||||
Future<void> addFavorite(List<SpotubeFullArtistObject> artists) async {
|
||||
await update((state) async {
|
||||
(await metadataPlugin).artist.save(artists.map((e) => e.id).toList());
|
||||
return state.copyWith(
|
||||
items: [...state.items, artists],
|
||||
) as SpotubePaginationResponseObject<SpotubeFullArtistObject>;
|
||||
});
|
||||
|
||||
for (final artist in artists) {
|
||||
ref.invalidate(metadataPluginIsSavedArtistProvider(artist.id));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> removeFavorite(List<SpotubeFullArtistObject> artists) async {
|
||||
await update((state) async {
|
||||
final artistIds = artists.map((e) => e.id).toList();
|
||||
(await metadataPlugin).artist.unsave(artistIds);
|
||||
return state.copyWith(
|
||||
items: state.items
|
||||
.where(
|
||||
(e) =>
|
||||
artistIds.contains((e as SpotubeFullArtistObject).id) ==
|
||||
false,
|
||||
)
|
||||
.toList() as List<SpotubeFullArtistObject>,
|
||||
) as SpotubePaginationResponseObject<SpotubeFullArtistObject>;
|
||||
});
|
||||
|
||||
for (final artist in artists) {
|
||||
ref.invalidate(metadataPluginIsSavedArtistProvider(artist.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final metadataPluginSavedArtistsProvider = AsyncNotifierProvider<
|
||||
MetadataPluginSavedArtistNotifier,
|
||||
SpotubePaginationResponseObject<SpotubeFullArtistObject>>(
|
||||
() => MetadataPluginSavedArtistNotifier(),
|
||||
);
|
||||
|
||||
final metadataPluginIsSavedArtistProvider =
|
||||
FutureProvider.autoDispose.family<bool, String>(
|
||||
(ref, artistId) async {
|
||||
final metadataPlugin = await ref.watch(metadataPluginProvider.future);
|
||||
|
||||
return metadataPlugin!.user
|
||||
.isSavedArtists([artistId]).then((value) => value.first);
|
||||
},
|
||||
);
|
22
lib/provider/metadata_plugin/playlist/playlist.dart
Normal file
22
lib/provider/metadata_plugin/playlist/playlist.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/error.dart';
|
||||
|
||||
final metadataPluginPlaylistProvider =
|
||||
FutureProvider.autoDispose.family<SpotubeFullPlaylistObject, String>(
|
||||
(ref, id) async {
|
||||
ref.cacheFor();
|
||||
|
||||
final metadataPlugin = await ref.watch(metadataPluginProvider.future);
|
||||
|
||||
if (metadataPlugin == null) {
|
||||
throw MetadataPluginException.noDefaultPlugin(
|
||||
"No metadata plugin is not set",
|
||||
);
|
||||
}
|
||||
|
||||
return metadataPlugin.playlist.getPlaylist(id);
|
||||
},
|
||||
);
|
36
lib/provider/metadata_plugin/tracks/album.dart
Normal file
36
lib/provider/metadata_plugin/tracks/album.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/family_paginated.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
|
||||
class MetadataPluginAlbumTracksNotifier
|
||||
extends AutoDisposeFamilyPaginatedAsyncNotifier<SpotubeFullTrackObject,
|
||||
String> {
|
||||
MetadataPluginAlbumTracksNotifier() : super();
|
||||
|
||||
@override
|
||||
fetch(offset, limit) async {
|
||||
final tracks = await (await metadataPlugin).album.tracks(
|
||||
arg,
|
||||
offset: offset,
|
||||
limit: limit,
|
||||
);
|
||||
|
||||
return tracks;
|
||||
}
|
||||
|
||||
@override
|
||||
build(arg) async {
|
||||
ref.cacheFor();
|
||||
|
||||
ref.watch(metadataPluginProvider);
|
||||
return await fetch(0, 20);
|
||||
}
|
||||
}
|
||||
|
||||
final metadataPluginAlbumTracksProvider =
|
||||
AutoDisposeAsyncNotifierProviderFamily<MetadataPluginAlbumTracksNotifier,
|
||||
SpotubePaginationResponseObject<SpotubeFullTrackObject>, String>(
|
||||
() => MetadataPluginAlbumTracksNotifier(),
|
||||
);
|
@ -4,9 +4,10 @@ import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/family_paginated.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
|
||||
class PlaylistTracksNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
||||
SpotubeFullTrackObject, String> {
|
||||
PlaylistTracksNotifier() : super();
|
||||
class MetadataPluginPlaylistTracksNotifier
|
||||
extends AutoDisposeFamilyPaginatedAsyncNotifier<SpotubeFullTrackObject,
|
||||
String> {
|
||||
MetadataPluginPlaylistTracksNotifier() : super();
|
||||
|
||||
@override
|
||||
fetch(offset, limit) async {
|
||||
@ -29,7 +30,7 @@ class PlaylistTracksNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
||||
}
|
||||
|
||||
final metadataPluginPlaylistTracksProvider =
|
||||
AutoDisposeAsyncNotifierProviderFamily<PlaylistTracksNotifier,
|
||||
AutoDisposeAsyncNotifierProviderFamily<MetadataPluginPlaylistTracksNotifier,
|
||||
SpotubePaginationResponseObject<SpotubeFullTrackObject>, String>(
|
||||
() => PlaylistTracksNotifier(),
|
||||
() => MetadataPluginPlaylistTracksNotifier(),
|
||||
);
|
||||
|
@ -0,0 +1,79 @@
|
||||
import 'package:hetu_script/hetu_script.dart';
|
||||
import 'package:hetu_script/values.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
|
||||
class MetadataPluginArtistEndpoint {
|
||||
final Hetu hetu;
|
||||
MetadataPluginArtistEndpoint(this.hetu);
|
||||
|
||||
HTInstance get hetuMetadataArtist =>
|
||||
(hetu.fetch("metadataPlugin") as HTInstance).memberGet("artist")
|
||||
as HTInstance;
|
||||
|
||||
Future<SpotubeFullArtistObject> getArtist(String id) async {
|
||||
final raw = await hetuMetadataArtist
|
||||
.invoke("getArtist", positionalArgs: [id]) as Map;
|
||||
|
||||
return SpotubeFullArtistObject.fromJson(
|
||||
raw.cast<String, dynamic>(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<SpotubePaginationResponseObject<SpotubeFullTrackObject>> topTracks(
|
||||
String id, {
|
||||
int? offset,
|
||||
int? limit,
|
||||
}) async {
|
||||
final raw = await hetuMetadataArtist.invoke(
|
||||
"topTracks",
|
||||
positionalArgs: [id],
|
||||
namedArgs: {
|
||||
"offset": offset,
|
||||
"limit": limit,
|
||||
}..removeWhere((key, value) => value == null),
|
||||
) as Map;
|
||||
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
raw.cast<String, dynamic>(),
|
||||
(Map json) => SpotubeFullTrackObject.fromJson(
|
||||
json.cast<String, dynamic>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<SpotubePaginationResponseObject<SpotubeSimpleAlbumObject>> albums(
|
||||
String id, {
|
||||
int? offset,
|
||||
int? limit,
|
||||
}) async {
|
||||
final raw = await hetuMetadataArtist.invoke(
|
||||
"albums",
|
||||
positionalArgs: [id],
|
||||
namedArgs: {
|
||||
"offset": offset,
|
||||
"limit": limit,
|
||||
}..removeWhere((key, value) => value == null),
|
||||
) as Map;
|
||||
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
raw.cast<String, dynamic>(),
|
||||
(Map json) => SpotubeSimpleAlbumObject.fromJson(
|
||||
json.cast<String, dynamic>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> save(List<String> ids) async {
|
||||
await hetuMetadataArtist.invoke(
|
||||
"save",
|
||||
positionalArgs: [ids],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> unsave(List<String> ids) async {
|
||||
await hetuMetadataArtist.invoke(
|
||||
"unsave",
|
||||
positionalArgs: [ids],
|
||||
);
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import 'package:spotube/components/titlebar/titlebar.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/services/metadata/apis/localstorage.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/album.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/artist.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/auth.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/playlist.dart';
|
||||
import 'package:spotube/services/metadata/endpoints/user.dart';
|
||||
@ -74,12 +75,16 @@ class MetadataPlugin {
|
||||
final Hetu hetu;
|
||||
|
||||
late final MetadataAuthEndpoint auth;
|
||||
|
||||
late final MetadataPluginAlbumEndpoint album;
|
||||
late final MetadataPluginArtistEndpoint artist;
|
||||
late final MetadataPluginPlaylistEndpoint playlist;
|
||||
late final MetadataPluginUserEndpoint user;
|
||||
|
||||
MetadataPlugin._(this.hetu) {
|
||||
auth = MetadataAuthEndpoint(hetu);
|
||||
|
||||
artist = MetadataPluginArtistEndpoint(hetu);
|
||||
album = MetadataPluginAlbumEndpoint(hetu);
|
||||
playlist = MetadataPluginPlaylistEndpoint(hetu);
|
||||
user = MetadataPluginUserEndpoint(hetu);
|
||||
|
Loading…
Reference in New Issue
Block a user