mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-12-07 15:59:42 +00:00
Compare commits
2 Commits
9a861b9954
...
abe04b28b2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abe04b28b2 | ||
|
|
8ac30c0031 |
14
lib/models/metadata/feed.dart
Normal file
14
lib/models/metadata/feed.dart
Normal file
@ -0,0 +1,14 @@
|
||||
part of 'metadata.dart';
|
||||
|
||||
@freezed
|
||||
class SpotubeFeedObject with _$SpotubeFeedObject {
|
||||
factory SpotubeFeedObject({
|
||||
required final String uid,
|
||||
required final String name,
|
||||
required final String externalUrl,
|
||||
@Default([]) final List<SpotubeImageObject> images,
|
||||
}) = _SpotubeFeedObject;
|
||||
|
||||
factory SpotubeFeedObject.fromJson(Map<String, dynamic> json) =>
|
||||
_$SpotubeFeedObjectFromJson(json);
|
||||
}
|
||||
@ -7,8 +7,12 @@ part 'metadata.freezed.dart';
|
||||
|
||||
part 'album.dart';
|
||||
part 'artist.dart';
|
||||
part 'feed.dart';
|
||||
part 'image.dart';
|
||||
part 'pagination.dart';
|
||||
part 'playlist.dart';
|
||||
part 'search.dart';
|
||||
part 'track.dart';
|
||||
part 'user.dart';
|
||||
|
||||
part 'plugin.dart';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -60,6 +60,27 @@ Map<String, dynamic> _$$SpotubeArtistObjectImplToJson(
|
||||
'externalUrl': instance.externalUrl,
|
||||
};
|
||||
|
||||
_$SpotubeFeedObjectImpl _$$SpotubeFeedObjectImplFromJson(Map json) =>
|
||||
_$SpotubeFeedObjectImpl(
|
||||
uid: json['uid'] as String,
|
||||
name: json['name'] as String,
|
||||
externalUrl: json['externalUrl'] as String,
|
||||
images: (json['images'] as List<dynamic>?)
|
||||
?.map((e) => SpotubeImageObject.fromJson(
|
||||
Map<String, dynamic>.from(e as Map)))
|
||||
.toList() ??
|
||||
const [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$SpotubeFeedObjectImplToJson(
|
||||
_$SpotubeFeedObjectImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'uid': instance.uid,
|
||||
'name': instance.name,
|
||||
'externalUrl': instance.externalUrl,
|
||||
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
_$SpotubeImageObjectImpl _$$SpotubeImageObjectImplFromJson(Map json) =>
|
||||
_$SpotubeImageObjectImpl(
|
||||
url: json['url'] as String,
|
||||
@ -75,6 +96,31 @@ Map<String, dynamic> _$$SpotubeImageObjectImplToJson(
|
||||
'height': instance.height,
|
||||
};
|
||||
|
||||
_$SpotubePaginationResponseObjectImpl<T>
|
||||
_$$SpotubePaginationResponseObjectImplFromJson<T>(
|
||||
Map json,
|
||||
T Function(Object? json) fromJsonT,
|
||||
) =>
|
||||
_$SpotubePaginationResponseObjectImpl<T>(
|
||||
total: (json['total'] as num).toInt(),
|
||||
nextCursor: json['nextCursor'] as String?,
|
||||
limit: json['limit'] as String,
|
||||
hasMore: json['hasMore'] as bool,
|
||||
items: (json['items'] as List<dynamic>).map(fromJsonT).toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$SpotubePaginationResponseObjectImplToJson<T>(
|
||||
_$SpotubePaginationResponseObjectImpl<T> instance,
|
||||
Object? Function(T value) toJsonT,
|
||||
) =>
|
||||
<String, dynamic>{
|
||||
'total': instance.total,
|
||||
'nextCursor': instance.nextCursor,
|
||||
'limit': instance.limit,
|
||||
'hasMore': instance.hasMore,
|
||||
'items': instance.items.map(toJsonT).toList(),
|
||||
};
|
||||
|
||||
_$SpotubePlaylistObjectImpl _$$SpotubePlaylistObjectImplFromJson(Map json) =>
|
||||
_$SpotubePlaylistObjectImpl(
|
||||
uid: json['uid'] as String,
|
||||
@ -110,35 +156,21 @@ Map<String, dynamic> _$$SpotubePlaylistObjectImplToJson(
|
||||
_$SpotubeSearchResponseObjectImpl _$$SpotubeSearchResponseObjectImplFromJson(
|
||||
Map json) =>
|
||||
_$SpotubeSearchResponseObjectImpl(
|
||||
tracks: (json['tracks'] as List<dynamic>?)
|
||||
?.map((e) => SpotubeTrackObject.fromJson(
|
||||
Map<String, dynamic>.from(e as Map)))
|
||||
.toList() ??
|
||||
const [],
|
||||
albums: (json['albums'] as List<dynamic>?)
|
||||
?.map((e) => SpotubeAlbumObject.fromJson(
|
||||
Map<String, dynamic>.from(e as Map)))
|
||||
.toList() ??
|
||||
const [],
|
||||
artists: (json['artists'] as List<dynamic>?)
|
||||
?.map((e) => SpotubeArtistObject.fromJson(
|
||||
Map<String, dynamic>.from(e as Map)))
|
||||
.toList() ??
|
||||
const [],
|
||||
playlists: (json['playlists'] as List<dynamic>?)
|
||||
?.map((e) => SpotubePlaylistObject.fromJson(
|
||||
Map<String, dynamic>.from(e as Map)))
|
||||
.toList() ??
|
||||
const [],
|
||||
tracks: _paginationTracksFromJson(json['tracks'] as Map<String, dynamic>),
|
||||
albums: _paginationAlbumsFromJson(json['albums'] as Map<String, dynamic>),
|
||||
artists:
|
||||
_paginationArtistsFromJson(json['artists'] as Map<String, dynamic>),
|
||||
playlists: _paginationPlaylistsFromJson(
|
||||
json['playlists'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$SpotubeSearchResponseObjectImplToJson(
|
||||
_$SpotubeSearchResponseObjectImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'tracks': instance.tracks.map((e) => e.toJson()).toList(),
|
||||
'albums': instance.albums.map((e) => e.toJson()).toList(),
|
||||
'artists': instance.artists.map((e) => e.toJson()).toList(),
|
||||
'playlists': instance.playlists.map((e) => e.toJson()).toList(),
|
||||
'tracks': _paginationToJson(instance.tracks),
|
||||
'albums': _paginationToJson(instance.albums),
|
||||
'artists': _paginationToJson(instance.artists),
|
||||
'playlists': _paginationToJson(instance.playlists),
|
||||
};
|
||||
|
||||
_$SpotubeTrackObjectImpl _$$SpotubeTrackObjectImplFromJson(Map json) =>
|
||||
@ -191,3 +223,26 @@ Map<String, dynamic> _$$SpotubeUserObjectImplToJson(
|
||||
'externalUrl': instance.externalUrl,
|
||||
'displayName': instance.displayName,
|
||||
};
|
||||
|
||||
_$PluginConfigurationImpl _$$PluginConfigurationImplFromJson(Map json) =>
|
||||
_$PluginConfigurationImpl(
|
||||
type: $enumDecode(_$PluginTypeEnumMap, json['type']),
|
||||
name: json['name'] as String,
|
||||
description: json['description'] as String,
|
||||
version: json['version'] as String,
|
||||
author: json['author'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$PluginConfigurationImplToJson(
|
||||
_$PluginConfigurationImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'type': _$PluginTypeEnumMap[instance.type]!,
|
||||
'name': instance.name,
|
||||
'description': instance.description,
|
||||
'version': instance.version,
|
||||
'author': instance.author,
|
||||
};
|
||||
|
||||
const _$PluginTypeEnumMap = {
|
||||
PluginType.metadata: 'metadata',
|
||||
};
|
||||
|
||||
22
lib/models/metadata/pagination.dart
Normal file
22
lib/models/metadata/pagination.dart
Normal file
@ -0,0 +1,22 @@
|
||||
part of 'metadata.dart';
|
||||
|
||||
@Freezed(genericArgumentFactories: true)
|
||||
class SpotubePaginationResponseObject<T>
|
||||
with _$SpotubePaginationResponseObject {
|
||||
factory SpotubePaginationResponseObject({
|
||||
required int total,
|
||||
required String? nextCursor,
|
||||
required String limit,
|
||||
required bool hasMore,
|
||||
required List<T> items,
|
||||
}) = _SpotubePaginationResponseObject;
|
||||
|
||||
factory SpotubePaginationResponseObject.fromJson(
|
||||
Map<String, Object?> json,
|
||||
T Function(Map<String, dynamic> json) fromJsonT,
|
||||
) =>
|
||||
_$SpotubePaginationResponseObjectFromJson(
|
||||
json,
|
||||
(json) => fromJsonT(json as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
21
lib/models/metadata/plugin.dart
Normal file
21
lib/models/metadata/plugin.dart
Normal file
@ -0,0 +1,21 @@
|
||||
part of 'metadata.dart';
|
||||
|
||||
enum PluginType { metadata }
|
||||
|
||||
@freezed
|
||||
class PluginConfiguration with _$PluginConfiguration {
|
||||
const PluginConfiguration._();
|
||||
|
||||
factory PluginConfiguration({
|
||||
required PluginType type,
|
||||
required String name,
|
||||
required String description,
|
||||
required String version,
|
||||
required String author,
|
||||
}) = _PluginConfiguration;
|
||||
|
||||
factory PluginConfiguration.fromJson(Map<String, dynamic> json) =>
|
||||
_$PluginConfigurationFromJson(json);
|
||||
|
||||
String get slug => name.toLowerCase().replaceAll(RegExp(r'[^a-z0-9]+'), '-');
|
||||
}
|
||||
@ -1,12 +1,71 @@
|
||||
part of 'metadata.dart';
|
||||
|
||||
SpotubePaginationResponseObject<SpotubeTrackObject> _paginationTracksFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) {
|
||||
return SpotubePaginationResponseObject<SpotubeTrackObject>.fromJson(
|
||||
json,
|
||||
(json) => SpotubeTrackObject.fromJson(json),
|
||||
);
|
||||
}
|
||||
|
||||
SpotubePaginationResponseObject<SpotubeAlbumObject> _paginationAlbumsFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) {
|
||||
return SpotubePaginationResponseObject<SpotubeAlbumObject>.fromJson(
|
||||
json,
|
||||
(json) => SpotubeAlbumObject.fromJson(json),
|
||||
);
|
||||
}
|
||||
|
||||
SpotubePaginationResponseObject<SpotubeArtistObject> _paginationArtistsFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) {
|
||||
return SpotubePaginationResponseObject<SpotubeArtistObject>.fromJson(
|
||||
json,
|
||||
(json) => SpotubeArtistObject.fromJson(json),
|
||||
);
|
||||
}
|
||||
|
||||
SpotubePaginationResponseObject<SpotubePlaylistObject>
|
||||
_paginationPlaylistsFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) {
|
||||
return SpotubePaginationResponseObject<SpotubePlaylistObject>.fromJson(
|
||||
json,
|
||||
(json) => SpotubePlaylistObject.fromJson(json),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic>? _paginationToJson(
|
||||
SpotubePaginationResponseObject? instance,
|
||||
) {
|
||||
return instance?.toJson((item) => item.toJson());
|
||||
}
|
||||
|
||||
@freezed
|
||||
class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject {
|
||||
factory SpotubeSearchResponseObject({
|
||||
@Default([]) final List<SpotubeTrackObject> tracks,
|
||||
@Default([]) final List<SpotubeAlbumObject> albums,
|
||||
@Default([]) final List<SpotubeArtistObject> artists,
|
||||
@Default([]) final List<SpotubePlaylistObject> playlists,
|
||||
@JsonKey(
|
||||
fromJson: _paginationTracksFromJson,
|
||||
toJson: _paginationToJson,
|
||||
)
|
||||
final SpotubePaginationResponseObject<SpotubeTrackObject>? tracks,
|
||||
@JsonKey(
|
||||
fromJson: _paginationAlbumsFromJson,
|
||||
toJson: _paginationToJson,
|
||||
)
|
||||
final SpotubePaginationResponseObject<SpotubeAlbumObject>? albums,
|
||||
@JsonKey(
|
||||
fromJson: _paginationArtistsFromJson,
|
||||
toJson: _paginationToJson,
|
||||
)
|
||||
final SpotubePaginationResponseObject<SpotubeArtistObject>? artists,
|
||||
@JsonKey(
|
||||
fromJson: _paginationPlaylistsFromJson,
|
||||
toJson: _paginationToJson,
|
||||
)
|
||||
final SpotubePaginationResponseObject<SpotubePlaylistObject>? playlists,
|
||||
}) = _SpotubeSearchResponseObject;
|
||||
|
||||
factory SpotubeSearchResponseObject.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
60
lib/services/metadata/apis/localstorage.dart
Normal file
60
lib/services/metadata/apis/localstorage.dart
Normal file
@ -0,0 +1,60 @@
|
||||
import 'package:flutter_js/flutter_js.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class PluginLocalStorageApi {
|
||||
final JavascriptRuntime runtime;
|
||||
final SharedPreferences sharedPreferences;
|
||||
|
||||
final String pluginName;
|
||||
|
||||
PluginLocalStorageApi({
|
||||
required this.runtime,
|
||||
required this.sharedPreferences,
|
||||
required this.pluginName,
|
||||
}) {
|
||||
runtime.onMessage("LocalStorage.getItem", (args) {
|
||||
final key = args[0];
|
||||
final value = getItem(key);
|
||||
runtime.evaluate(
|
||||
"""
|
||||
eventEmitter.emit('LocalStorage.getItem', ${value != null ? "'$value'" : "null"});
|
||||
""",
|
||||
);
|
||||
});
|
||||
|
||||
runtime.onMessage("LocalStorage.setItem", (args) {
|
||||
final map = args[0] as Map<String, dynamic>;
|
||||
setItem(map["key"], map["value"]);
|
||||
});
|
||||
|
||||
runtime.onMessage("LocalStorage.removeItem", (args) {
|
||||
final map = args[0];
|
||||
removeItem(map["key"]);
|
||||
});
|
||||
|
||||
runtime.onMessage("LocalStorage.clear", (args) {
|
||||
clear();
|
||||
});
|
||||
}
|
||||
|
||||
void setItem(String key, String value) async {
|
||||
await sharedPreferences.setString("plugin.$pluginName.$key", value);
|
||||
}
|
||||
|
||||
String? getItem(String key) {
|
||||
return sharedPreferences.getString("plugin.$pluginName.$key");
|
||||
}
|
||||
|
||||
void removeItem(String key) async {
|
||||
await sharedPreferences.remove("plugin.$pluginName.$key");
|
||||
}
|
||||
|
||||
void clear() async {
|
||||
final keys = sharedPreferences.getKeys();
|
||||
for (String key in keys) {
|
||||
if (key.startsWith("plugin.$pluginName.")) {
|
||||
await sharedPreferences.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,20 +4,23 @@ import 'dart:convert';
|
||||
import 'package:flutter_js/extensions/fetch.dart';
|
||||
import 'package:flutter_js/extensions/xhr.dart';
|
||||
import 'package:flutter_js/flutter_js.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/services/logger/logger.dart';
|
||||
import 'package:spotube/services/metadata/apis/localstorage.dart';
|
||||
|
||||
const int defaultMetadataLimit = 20;
|
||||
const int defaultMetadataOffset = 0;
|
||||
const defaultMetadataLimit = "20";
|
||||
|
||||
/// Signature for metadata and related methods that will return Spotube native
|
||||
/// objects e.g. SpotubeTrack, SpotubePlaylist, etc.
|
||||
class MetadataApiSignature {
|
||||
final JavascriptRuntime runtime;
|
||||
final PluginLocalStorageApi localStorageApi;
|
||||
|
||||
MetadataApiSignature._(this.runtime);
|
||||
MetadataApiSignature._(this.runtime, this.localStorageApi);
|
||||
|
||||
static Future<MetadataApiSignature> init(String libraryCode) async {
|
||||
static Future<MetadataApiSignature> init(
|
||||
String libraryCode, PluginConfiguration config) async {
|
||||
final runtime = getJavascriptRuntime(xhr: true).enableXhr();
|
||||
runtime.enableHandlePromises();
|
||||
await runtime.enableFetch();
|
||||
@ -42,7 +45,17 @@ class MetadataApiSignature {
|
||||
);
|
||||
}
|
||||
|
||||
return MetadataApiSignature._(runtime);
|
||||
// Create all the PluginAPIs after library code is evaluated
|
||||
final localStorageApi = PluginLocalStorageApi(
|
||||
runtime: runtime,
|
||||
sharedPreferences: await SharedPreferences.getInstance(),
|
||||
pluginName: config.slug,
|
||||
);
|
||||
|
||||
return MetadataApiSignature._(
|
||||
runtime,
|
||||
localStorageApi,
|
||||
);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
@ -97,73 +110,91 @@ class MetadataApiSignature {
|
||||
return SpotubeTrackObject.fromJson(result);
|
||||
}
|
||||
|
||||
Future<List<SpotubeTrackObject>> listTracks({
|
||||
Future<SpotubePaginationResponseObject<SpotubeTrackObject>> listTracks({
|
||||
List<String>? ids,
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final result = await invoke(
|
||||
"metadataApi.listTracks",
|
||||
[
|
||||
ids,
|
||||
limit,
|
||||
offset,
|
||||
cursor,
|
||||
],
|
||||
);
|
||||
|
||||
return result.map(SpotubeTrackObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject<SpotubeTrackObject>.fromJson(
|
||||
result,
|
||||
SpotubeTrackObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubeTrackObject>> listTracksByAlbum(
|
||||
Future<SpotubePaginationResponseObject<SpotubeTrackObject>> listTracksByAlbum(
|
||||
String albumId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listTracksByAlbum",
|
||||
[albumId, limit, offset],
|
||||
[albumId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeTrackObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject<SpotubeTrackObject>.fromJson(
|
||||
res,
|
||||
SpotubeTrackObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubeTrackObject>> listTopTracksByArtist(
|
||||
Future<SpotubePaginationResponseObject<SpotubeTrackObject>>
|
||||
listTopTracksByArtist(
|
||||
String artistId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listTopTracksByArtist",
|
||||
[artistId, limit, offset],
|
||||
[artistId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeTrackObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject<SpotubeTrackObject>.fromJson(
|
||||
res,
|
||||
SpotubeTrackObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubeTrackObject>> listTracksByPlaylist(
|
||||
Future<SpotubePaginationResponseObject<SpotubeTrackObject>>
|
||||
listTracksByPlaylist(
|
||||
String playlistId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listTracksByPlaylist",
|
||||
[playlistId, limit, offset],
|
||||
[playlistId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeTrackObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject<SpotubeTrackObject>.fromJson(
|
||||
res,
|
||||
SpotubeTrackObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubeTrackObject>> listUserSavedTracks(
|
||||
Future<SpotubePaginationResponseObject<SpotubeTrackObject>>
|
||||
listUserSavedTracks(
|
||||
String userId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listUserSavedTracks",
|
||||
[userId, limit, offset],
|
||||
[userId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeTrackObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject<SpotubeTrackObject>.fromJson(
|
||||
res,
|
||||
SpotubeTrackObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
// ----- Album ------
|
||||
@ -173,43 +204,54 @@ class MetadataApiSignature {
|
||||
return SpotubeAlbumObject.fromJson(res);
|
||||
}
|
||||
|
||||
Future<List<SpotubeAlbumObject>> listAlbums({
|
||||
Future<SpotubePaginationResponseObject<SpotubeAlbumObject>> listAlbums({
|
||||
List<String>? ids,
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listAlbums",
|
||||
[ids, limit, offset],
|
||||
[ids, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeAlbumObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject<SpotubeAlbumObject>.fromJson(
|
||||
res,
|
||||
SpotubeAlbumObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubeAlbumObject>> listAlbumsByArtist(
|
||||
Future<SpotubePaginationResponseObject<SpotubeAlbumObject>>
|
||||
listAlbumsByArtist(
|
||||
String artistId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listAlbumsByArtist",
|
||||
[artistId, limit, offset],
|
||||
[artistId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeAlbumObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
res,
|
||||
SpotubeAlbumObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubeAlbumObject>> listUserSavedAlbums(
|
||||
Future<SpotubePaginationResponseObject<SpotubeAlbumObject>>
|
||||
listUserSavedAlbums(
|
||||
String userId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listUserSavedAlbums",
|
||||
[userId, limit, offset],
|
||||
[userId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeAlbumObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
res,
|
||||
SpotubeAlbumObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
// ----- Playlist ------
|
||||
@ -219,30 +261,114 @@ class MetadataApiSignature {
|
||||
return SpotubePlaylistObject.fromJson(res);
|
||||
}
|
||||
|
||||
Future<List<SpotubePlaylistObject>> listPlaylists({
|
||||
List<String>? ids,
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
Future<SpotubePaginationResponseObject<SpotubePlaylistObject>>
|
||||
listFeedPlaylists(
|
||||
String feedId, {
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listPlaylists",
|
||||
[ids, limit, offset],
|
||||
"metadataApi.listFeedPlaylists",
|
||||
[feedId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubePlaylistObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
res,
|
||||
SpotubePlaylistObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubePlaylistObject>> listUserSavedPlaylists(
|
||||
Future<SpotubePaginationResponseObject<SpotubePlaylistObject>>
|
||||
listUserSavedPlaylists(
|
||||
String userId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listUserSavedPlaylists",
|
||||
[userId, limit, offset],
|
||||
[userId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubePlaylistObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
res,
|
||||
SpotubePlaylistObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<SpotubePlaylistObject> createPlaylist(
|
||||
String userId,
|
||||
String name, {
|
||||
String? description,
|
||||
bool? public,
|
||||
bool? collaborative,
|
||||
String? imageBase64,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.createPlaylist",
|
||||
[
|
||||
userId,
|
||||
name,
|
||||
description,
|
||||
public,
|
||||
collaborative,
|
||||
imageBase64,
|
||||
],
|
||||
);
|
||||
|
||||
return SpotubePlaylistObject.fromJson(res);
|
||||
}
|
||||
|
||||
Future<void> updatePlaylist(
|
||||
String playlistId, {
|
||||
String? name,
|
||||
String? description,
|
||||
bool? public,
|
||||
bool? collaborative,
|
||||
String? imageBase64,
|
||||
}) async {
|
||||
await invoke(
|
||||
"metadataApi.updatePlaylist",
|
||||
[
|
||||
playlistId,
|
||||
name,
|
||||
description,
|
||||
public,
|
||||
collaborative,
|
||||
imageBase64,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deletePlaylist(String userId, String playlistId) async {
|
||||
await unsavePlaylist(userId, playlistId);
|
||||
}
|
||||
|
||||
Future<void> addTracksToPlaylist(
|
||||
String playlistId,
|
||||
List<String> trackIds, {
|
||||
int? position,
|
||||
}) async {
|
||||
await invoke(
|
||||
"metadataApi.addTracksToPlaylist",
|
||||
[
|
||||
playlistId,
|
||||
trackIds,
|
||||
position,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removeTracksFromPlaylist(
|
||||
String playlistId,
|
||||
List<String> trackIds,
|
||||
) async {
|
||||
await invoke(
|
||||
"metadataApi.removeTracksFromPlaylist",
|
||||
[
|
||||
playlistId,
|
||||
trackIds,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// ----- Artist ------
|
||||
@ -252,44 +378,70 @@ class MetadataApiSignature {
|
||||
return SpotubeArtistObject.fromJson(res);
|
||||
}
|
||||
|
||||
Future<List<SpotubeArtistObject>> listArtists({
|
||||
Future<SpotubePaginationResponseObject<SpotubeArtistObject>> listArtists({
|
||||
List<String>? ids,
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listArtists",
|
||||
[ids, limit, offset],
|
||||
[ids, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeArtistObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
res,
|
||||
SpotubeArtistObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SpotubeArtistObject>> listUserSavedArtists(
|
||||
Future<SpotubePaginationResponseObject<SpotubeArtistObject>>
|
||||
listUserSavedArtists(
|
||||
String userId, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.listUserSavedArtists",
|
||||
[userId, limit, offset],
|
||||
[userId, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeArtistObject.fromJson).toList();
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
res,
|
||||
SpotubeArtistObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
// ----- Search ------
|
||||
Future<SpotubeSearchResponseObject> search(
|
||||
String query, {
|
||||
int limit = defaultMetadataLimit,
|
||||
int offset = defaultMetadataOffset,
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke(
|
||||
"metadataApi.search",
|
||||
[query, limit, offset],
|
||||
[query, limit, cursor],
|
||||
);
|
||||
|
||||
return res.map(SpotubeSearchResponseObject.fromJson).toList();
|
||||
return SpotubeSearchResponseObject.fromJson(res);
|
||||
}
|
||||
|
||||
// ----- Feed ------
|
||||
Future<SpotubeFeedObject> getFeed(String id) async {
|
||||
final res = await invoke("metadataApi.getFeed", [id]);
|
||||
|
||||
return SpotubeFeedObject.fromJson(res);
|
||||
}
|
||||
|
||||
Future<SpotubePaginationResponseObject<SpotubeFeedObject>> listFeeds({
|
||||
String limit = defaultMetadataLimit,
|
||||
String? cursor,
|
||||
}) async {
|
||||
final res = await invoke("metadataApi.listFeeds", [limit, cursor]);
|
||||
|
||||
return SpotubePaginationResponseObject.fromJson(
|
||||
res,
|
||||
SpotubeFeedObject.fromJson,
|
||||
);
|
||||
}
|
||||
|
||||
// ----- User ------
|
||||
|
||||
Loading…
Reference in New Issue
Block a user