mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-12-08 08:17:31 +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 'album.dart';
|
||||||
part 'artist.dart';
|
part 'artist.dart';
|
||||||
|
part 'feed.dart';
|
||||||
part 'image.dart';
|
part 'image.dart';
|
||||||
|
part 'pagination.dart';
|
||||||
part 'playlist.dart';
|
part 'playlist.dart';
|
||||||
part 'search.dart';
|
part 'search.dart';
|
||||||
part 'track.dart';
|
part 'track.dart';
|
||||||
part 'user.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,
|
'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 _$$SpotubeImageObjectImplFromJson(Map json) =>
|
||||||
_$SpotubeImageObjectImpl(
|
_$SpotubeImageObjectImpl(
|
||||||
url: json['url'] as String,
|
url: json['url'] as String,
|
||||||
@ -75,6 +96,31 @@ Map<String, dynamic> _$$SpotubeImageObjectImplToJson(
|
|||||||
'height': instance.height,
|
'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 _$$SpotubePlaylistObjectImplFromJson(Map json) =>
|
||||||
_$SpotubePlaylistObjectImpl(
|
_$SpotubePlaylistObjectImpl(
|
||||||
uid: json['uid'] as String,
|
uid: json['uid'] as String,
|
||||||
@ -110,35 +156,21 @@ Map<String, dynamic> _$$SpotubePlaylistObjectImplToJson(
|
|||||||
_$SpotubeSearchResponseObjectImpl _$$SpotubeSearchResponseObjectImplFromJson(
|
_$SpotubeSearchResponseObjectImpl _$$SpotubeSearchResponseObjectImplFromJson(
|
||||||
Map json) =>
|
Map json) =>
|
||||||
_$SpotubeSearchResponseObjectImpl(
|
_$SpotubeSearchResponseObjectImpl(
|
||||||
tracks: (json['tracks'] as List<dynamic>?)
|
tracks: _paginationTracksFromJson(json['tracks'] as Map<String, dynamic>),
|
||||||
?.map((e) => SpotubeTrackObject.fromJson(
|
albums: _paginationAlbumsFromJson(json['albums'] as Map<String, dynamic>),
|
||||||
Map<String, dynamic>.from(e as Map)))
|
artists:
|
||||||
.toList() ??
|
_paginationArtistsFromJson(json['artists'] as Map<String, dynamic>),
|
||||||
const [],
|
playlists: _paginationPlaylistsFromJson(
|
||||||
albums: (json['albums'] as List<dynamic>?)
|
json['playlists'] as Map<String, 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 [],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$SpotubeSearchResponseObjectImplToJson(
|
Map<String, dynamic> _$$SpotubeSearchResponseObjectImplToJson(
|
||||||
_$SpotubeSearchResponseObjectImpl instance) =>
|
_$SpotubeSearchResponseObjectImpl instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'tracks': instance.tracks.map((e) => e.toJson()).toList(),
|
'tracks': _paginationToJson(instance.tracks),
|
||||||
'albums': instance.albums.map((e) => e.toJson()).toList(),
|
'albums': _paginationToJson(instance.albums),
|
||||||
'artists': instance.artists.map((e) => e.toJson()).toList(),
|
'artists': _paginationToJson(instance.artists),
|
||||||
'playlists': instance.playlists.map((e) => e.toJson()).toList(),
|
'playlists': _paginationToJson(instance.playlists),
|
||||||
};
|
};
|
||||||
|
|
||||||
_$SpotubeTrackObjectImpl _$$SpotubeTrackObjectImplFromJson(Map json) =>
|
_$SpotubeTrackObjectImpl _$$SpotubeTrackObjectImplFromJson(Map json) =>
|
||||||
@ -191,3 +223,26 @@ Map<String, dynamic> _$$SpotubeUserObjectImplToJson(
|
|||||||
'externalUrl': instance.externalUrl,
|
'externalUrl': instance.externalUrl,
|
||||||
'displayName': instance.displayName,
|
'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';
|
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
|
@freezed
|
||||||
class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject {
|
class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject {
|
||||||
factory SpotubeSearchResponseObject({
|
factory SpotubeSearchResponseObject({
|
||||||
@Default([]) final List<SpotubeTrackObject> tracks,
|
@JsonKey(
|
||||||
@Default([]) final List<SpotubeAlbumObject> albums,
|
fromJson: _paginationTracksFromJson,
|
||||||
@Default([]) final List<SpotubeArtistObject> artists,
|
toJson: _paginationToJson,
|
||||||
@Default([]) final List<SpotubePlaylistObject> playlists,
|
)
|
||||||
|
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;
|
}) = _SpotubeSearchResponseObject;
|
||||||
|
|
||||||
factory SpotubeSearchResponseObject.fromJson(Map<String, dynamic> json) =>
|
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/fetch.dart';
|
||||||
import 'package:flutter_js/extensions/xhr.dart';
|
import 'package:flutter_js/extensions/xhr.dart';
|
||||||
import 'package:flutter_js/flutter_js.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/models/metadata/metadata.dart';
|
||||||
import 'package:spotube/services/logger/logger.dart';
|
import 'package:spotube/services/logger/logger.dart';
|
||||||
|
import 'package:spotube/services/metadata/apis/localstorage.dart';
|
||||||
|
|
||||||
const int defaultMetadataLimit = 20;
|
const defaultMetadataLimit = "20";
|
||||||
const int defaultMetadataOffset = 0;
|
|
||||||
|
|
||||||
/// Signature for metadata and related methods that will return Spotube native
|
/// Signature for metadata and related methods that will return Spotube native
|
||||||
/// objects e.g. SpotubeTrack, SpotubePlaylist, etc.
|
/// objects e.g. SpotubeTrack, SpotubePlaylist, etc.
|
||||||
class MetadataApiSignature {
|
class MetadataApiSignature {
|
||||||
final JavascriptRuntime runtime;
|
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();
|
final runtime = getJavascriptRuntime(xhr: true).enableXhr();
|
||||||
runtime.enableHandlePromises();
|
runtime.enableHandlePromises();
|
||||||
await runtime.enableFetch();
|
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() {
|
void dispose() {
|
||||||
@ -97,73 +110,91 @@ class MetadataApiSignature {
|
|||||||
return SpotubeTrackObject.fromJson(result);
|
return SpotubeTrackObject.fromJson(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpotubeTrackObject>> listTracks({
|
Future<SpotubePaginationResponseObject<SpotubeTrackObject>> listTracks({
|
||||||
List<String>? ids,
|
List<String>? ids,
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final result = await invoke(
|
final result = await invoke(
|
||||||
"metadataApi.listTracks",
|
"metadataApi.listTracks",
|
||||||
[
|
[
|
||||||
ids,
|
ids,
|
||||||
limit,
|
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, {
|
String albumId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listTracksByAlbum",
|
"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, {
|
String artistId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listTopTracksByArtist",
|
"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, {
|
String playlistId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listTracksByPlaylist",
|
"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, {
|
String userId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listUserSavedTracks",
|
"metadataApi.listUserSavedTracks",
|
||||||
[userId, limit, offset],
|
[userId, limit, cursor],
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.map(SpotubeTrackObject.fromJson).toList();
|
return SpotubePaginationResponseObject<SpotubeTrackObject>.fromJson(
|
||||||
|
res,
|
||||||
|
SpotubeTrackObject.fromJson,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- Album ------
|
// ----- Album ------
|
||||||
@ -173,43 +204,54 @@ class MetadataApiSignature {
|
|||||||
return SpotubeAlbumObject.fromJson(res);
|
return SpotubeAlbumObject.fromJson(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpotubeAlbumObject>> listAlbums({
|
Future<SpotubePaginationResponseObject<SpotubeAlbumObject>> listAlbums({
|
||||||
List<String>? ids,
|
List<String>? ids,
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listAlbums",
|
"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, {
|
String artistId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listAlbumsByArtist",
|
"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, {
|
String userId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listUserSavedAlbums",
|
"metadataApi.listUserSavedAlbums",
|
||||||
[userId, limit, offset],
|
[userId, limit, cursor],
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.map(SpotubeAlbumObject.fromJson).toList();
|
return SpotubePaginationResponseObject.fromJson(
|
||||||
|
res,
|
||||||
|
SpotubeAlbumObject.fromJson,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- Playlist ------
|
// ----- Playlist ------
|
||||||
@ -219,30 +261,114 @@ class MetadataApiSignature {
|
|||||||
return SpotubePlaylistObject.fromJson(res);
|
return SpotubePlaylistObject.fromJson(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpotubePlaylistObject>> listPlaylists({
|
Future<SpotubePaginationResponseObject<SpotubePlaylistObject>>
|
||||||
List<String>? ids,
|
listFeedPlaylists(
|
||||||
int limit = defaultMetadataLimit,
|
String feedId, {
|
||||||
int offset = defaultMetadataOffset,
|
String limit = defaultMetadataLimit,
|
||||||
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listPlaylists",
|
"metadataApi.listFeedPlaylists",
|
||||||
[ids, limit, offset],
|
[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, {
|
String userId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listUserSavedPlaylists",
|
"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 ------
|
// ----- Artist ------
|
||||||
@ -252,44 +378,70 @@ class MetadataApiSignature {
|
|||||||
return SpotubeArtistObject.fromJson(res);
|
return SpotubeArtistObject.fromJson(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpotubeArtistObject>> listArtists({
|
Future<SpotubePaginationResponseObject<SpotubeArtistObject>> listArtists({
|
||||||
List<String>? ids,
|
List<String>? ids,
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listArtists",
|
"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, {
|
String userId, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.listUserSavedArtists",
|
"metadataApi.listUserSavedArtists",
|
||||||
[userId, limit, offset],
|
[userId, limit, cursor],
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.map(SpotubeArtistObject.fromJson).toList();
|
return SpotubePaginationResponseObject.fromJson(
|
||||||
|
res,
|
||||||
|
SpotubeArtistObject.fromJson,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- Search ------
|
// ----- Search ------
|
||||||
Future<SpotubeSearchResponseObject> search(
|
Future<SpotubeSearchResponseObject> search(
|
||||||
String query, {
|
String query, {
|
||||||
int limit = defaultMetadataLimit,
|
String limit = defaultMetadataLimit,
|
||||||
int offset = defaultMetadataOffset,
|
String? cursor,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await invoke(
|
final res = await invoke(
|
||||||
"metadataApi.search",
|
"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 ------
|
// ----- User ------
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user