From 7491175bb6d4e5261da4b514ede39d95c09e9c88 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Thu, 1 May 2025 13:20:05 +0600 Subject: [PATCH] feat: add metadata api service and models --- .vscode/settings.json | 1 + android/app/proguard-rules.pro | 9 + lib/collections/fonts.gen.dart | 3 + lib/models/metadata/album.dart | 22 + lib/models/metadata/artist.dart | 14 + lib/models/metadata/image.dart | 13 + lib/models/metadata/metadata.dart | 14 + lib/models/metadata/metadata.freezed.dart | 1868 +++++++++++++++++ lib/models/metadata/metadata.g.dart | 193 ++ lib/models/metadata/playlist.dart | 17 + lib/models/metadata/search.dart | 14 + lib/models/metadata/track.dart | 17 + lib/models/metadata/user.dart | 15 + lib/services/metadata/metadata.dart | 308 +++ linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 8 + pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 21 files changed, 2528 insertions(+) create mode 100644 lib/models/metadata/album.dart create mode 100644 lib/models/metadata/artist.dart create mode 100644 lib/models/metadata/image.dart create mode 100644 lib/models/metadata/metadata.dart create mode 100644 lib/models/metadata/metadata.freezed.dart create mode 100644 lib/models/metadata/metadata.g.dart create mode 100644 lib/models/metadata/playlist.dart create mode 100644 lib/models/metadata/search.dart create mode 100644 lib/models/metadata/track.dart create mode 100644 lib/models/metadata/user.dart create mode 100644 lib/services/metadata/metadata.dart diff --git a/.vscode/settings.json b/.vscode/settings.json index 8ae9c74f..b848774e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,7 @@ "ambiguate", "Amoled", "Buildless", + "configurators", "danceability", "fuzzywuzzy", "gapless", diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index 17a13e9d..2142555d 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -1,3 +1,12 @@ +#Flutter Wrapper +-keep class io.flutter.app.** { *; } +-keep class io.flutter.plugin.** { *; } +-keep class io.flutter.util.** { *; } +-keep class io.flutter.view.** { *; } +-keep class io.flutter.** { *; } +-keep class io.flutter.plugins.** { *; } +-keep class de.prosiebensat1digital.** { *; } + -keep class androidx.lifecycle.DefaultLifecycleObserver -keepnames class kotlinx.serialization.** { *; } diff --git a/lib/collections/fonts.gen.dart b/lib/collections/fonts.gen.dart index 033d3a79..c51dfd40 100644 --- a/lib/collections/fonts.gen.dart +++ b/lib/collections/fonts.gen.dart @@ -13,6 +13,9 @@ class FontFamily { /// Font family: BootstrapIcons static const String bootstrapIcons = 'BootstrapIcons'; + /// Font family: Cookie + static const String cookie = 'Cookie'; + /// Font family: RadixIcons static const String radixIcons = 'RadixIcons'; } diff --git a/lib/models/metadata/album.dart b/lib/models/metadata/album.dart new file mode 100644 index 00000000..fba880f6 --- /dev/null +++ b/lib/models/metadata/album.dart @@ -0,0 +1,22 @@ +part of 'metadata.dart'; + +enum SpotubeAlbumType { + album, + single, +} + +@freezed +class SpotubeAlbumObject with _$SpotubeAlbumObject { + factory SpotubeAlbumObject({ + required final String uid, + required final String title, + required final SpotubeArtistObject artist, + @Default([]) final List images, + required final String releaseDate, + required final String externalUrl, + required final SpotubeAlbumType type, + }) = _SpotubeAlbumObject; + + factory SpotubeAlbumObject.fromJson(Map json) => + _$SpotubeAlbumObjectFromJson(json); +} diff --git a/lib/models/metadata/artist.dart b/lib/models/metadata/artist.dart new file mode 100644 index 00000000..2dbb7379 --- /dev/null +++ b/lib/models/metadata/artist.dart @@ -0,0 +1,14 @@ +part of 'metadata.dart'; + +@freezed +class SpotubeArtistObject with _$SpotubeArtistObject { + factory SpotubeArtistObject({ + required final String uid, + required final String name, + @Default([]) final List images, + required final String externalUrl, + }) = _SpotubeArtistObject; + + factory SpotubeArtistObject.fromJson(Map json) => + _$SpotubeArtistObjectFromJson(json); +} diff --git a/lib/models/metadata/image.dart b/lib/models/metadata/image.dart new file mode 100644 index 00000000..aa20c385 --- /dev/null +++ b/lib/models/metadata/image.dart @@ -0,0 +1,13 @@ +part of 'metadata.dart'; + +@freezed +class SpotubeImageObject with _$SpotubeImageObject { + factory SpotubeImageObject({ + required final String url, + required final int width, + required final int height, + }) = _SpotubeImageObject; + + factory SpotubeImageObject.fromJson(Map json) => + _$SpotubeImageObjectFromJson(json); +} diff --git a/lib/models/metadata/metadata.dart b/lib/models/metadata/metadata.dart new file mode 100644 index 00000000..372aec64 --- /dev/null +++ b/lib/models/metadata/metadata.dart @@ -0,0 +1,14 @@ +library metadata_objects; + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'metadata.g.dart'; +part 'metadata.freezed.dart'; + +part 'album.dart'; +part 'artist.dart'; +part 'image.dart'; +part 'playlist.dart'; +part 'search.dart'; +part 'track.dart'; +part 'user.dart'; diff --git a/lib/models/metadata/metadata.freezed.dart b/lib/models/metadata/metadata.freezed.dart new file mode 100644 index 00000000..f2364fce --- /dev/null +++ b/lib/models/metadata/metadata.freezed.dart @@ -0,0 +1,1868 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'metadata.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +SpotubeAlbumObject _$SpotubeAlbumObjectFromJson(Map json) { + return _SpotubeAlbumObject.fromJson(json); +} + +/// @nodoc +mixin _$SpotubeAlbumObject { + String get uid => throw _privateConstructorUsedError; + String get title => throw _privateConstructorUsedError; + SpotubeArtistObject get artist => throw _privateConstructorUsedError; + List get images => throw _privateConstructorUsedError; + String get releaseDate => throw _privateConstructorUsedError; + String get externalUrl => throw _privateConstructorUsedError; + SpotubeAlbumType get type => throw _privateConstructorUsedError; + + /// Serializes this SpotubeAlbumObject to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SpotubeAlbumObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SpotubeAlbumObjectCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SpotubeAlbumObjectCopyWith<$Res> { + factory $SpotubeAlbumObjectCopyWith( + SpotubeAlbumObject value, $Res Function(SpotubeAlbumObject) then) = + _$SpotubeAlbumObjectCopyWithImpl<$Res, SpotubeAlbumObject>; + @useResult + $Res call( + {String uid, + String title, + SpotubeArtistObject artist, + List images, + String releaseDate, + String externalUrl, + SpotubeAlbumType type}); + + $SpotubeArtistObjectCopyWith<$Res> get artist; +} + +/// @nodoc +class _$SpotubeAlbumObjectCopyWithImpl<$Res, $Val extends SpotubeAlbumObject> + implements $SpotubeAlbumObjectCopyWith<$Res> { + _$SpotubeAlbumObjectCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SpotubeAlbumObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? title = null, + Object? artist = null, + Object? images = null, + Object? releaseDate = null, + Object? externalUrl = null, + Object? type = null, + }) { + return _then(_value.copyWith( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + artist: null == artist + ? _value.artist + : artist // ignore: cast_nullable_to_non_nullable + as SpotubeArtistObject, + images: null == images + ? _value.images + : images // ignore: cast_nullable_to_non_nullable + as List, + releaseDate: null == releaseDate + ? _value.releaseDate + : releaseDate // ignore: cast_nullable_to_non_nullable + as String, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as SpotubeAlbumType, + ) as $Val); + } + + /// Create a copy of SpotubeAlbumObject + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SpotubeArtistObjectCopyWith<$Res> get artist { + return $SpotubeArtistObjectCopyWith<$Res>(_value.artist, (value) { + return _then(_value.copyWith(artist: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SpotubeAlbumObjectImplCopyWith<$Res> + implements $SpotubeAlbumObjectCopyWith<$Res> { + factory _$$SpotubeAlbumObjectImplCopyWith(_$SpotubeAlbumObjectImpl value, + $Res Function(_$SpotubeAlbumObjectImpl) then) = + __$$SpotubeAlbumObjectImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String uid, + String title, + SpotubeArtistObject artist, + List images, + String releaseDate, + String externalUrl, + SpotubeAlbumType type}); + + @override + $SpotubeArtistObjectCopyWith<$Res> get artist; +} + +/// @nodoc +class __$$SpotubeAlbumObjectImplCopyWithImpl<$Res> + extends _$SpotubeAlbumObjectCopyWithImpl<$Res, _$SpotubeAlbumObjectImpl> + implements _$$SpotubeAlbumObjectImplCopyWith<$Res> { + __$$SpotubeAlbumObjectImplCopyWithImpl(_$SpotubeAlbumObjectImpl _value, + $Res Function(_$SpotubeAlbumObjectImpl) _then) + : super(_value, _then); + + /// Create a copy of SpotubeAlbumObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? title = null, + Object? artist = null, + Object? images = null, + Object? releaseDate = null, + Object? externalUrl = null, + Object? type = null, + }) { + return _then(_$SpotubeAlbumObjectImpl( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + artist: null == artist + ? _value.artist + : artist // ignore: cast_nullable_to_non_nullable + as SpotubeArtistObject, + images: null == images + ? _value._images + : images // ignore: cast_nullable_to_non_nullable + as List, + releaseDate: null == releaseDate + ? _value.releaseDate + : releaseDate // ignore: cast_nullable_to_non_nullable + as String, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as SpotubeAlbumType, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SpotubeAlbumObjectImpl implements _SpotubeAlbumObject { + _$SpotubeAlbumObjectImpl( + {required this.uid, + required this.title, + required this.artist, + final List images = const [], + required this.releaseDate, + required this.externalUrl, + required this.type}) + : _images = images; + + factory _$SpotubeAlbumObjectImpl.fromJson(Map json) => + _$$SpotubeAlbumObjectImplFromJson(json); + + @override + final String uid; + @override + final String title; + @override + final SpotubeArtistObject artist; + final List _images; + @override + @JsonKey() + List get images { + if (_images is EqualUnmodifiableListView) return _images; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_images); + } + + @override + final String releaseDate; + @override + final String externalUrl; + @override + final SpotubeAlbumType type; + + @override + String toString() { + return 'SpotubeAlbumObject(uid: $uid, title: $title, artist: $artist, images: $images, releaseDate: $releaseDate, externalUrl: $externalUrl, type: $type)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SpotubeAlbumObjectImpl && + (identical(other.uid, uid) || other.uid == uid) && + (identical(other.title, title) || other.title == title) && + (identical(other.artist, artist) || other.artist == artist) && + const DeepCollectionEquality().equals(other._images, _images) && + (identical(other.releaseDate, releaseDate) || + other.releaseDate == releaseDate) && + (identical(other.externalUrl, externalUrl) || + other.externalUrl == externalUrl) && + (identical(other.type, type) || other.type == type)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + uid, + title, + artist, + const DeepCollectionEquality().hash(_images), + releaseDate, + externalUrl, + type); + + /// Create a copy of SpotubeAlbumObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SpotubeAlbumObjectImplCopyWith<_$SpotubeAlbumObjectImpl> get copyWith => + __$$SpotubeAlbumObjectImplCopyWithImpl<_$SpotubeAlbumObjectImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$SpotubeAlbumObjectImplToJson( + this, + ); + } +} + +abstract class _SpotubeAlbumObject implements SpotubeAlbumObject { + factory _SpotubeAlbumObject( + {required final String uid, + required final String title, + required final SpotubeArtistObject artist, + final List images, + required final String releaseDate, + required final String externalUrl, + required final SpotubeAlbumType type}) = _$SpotubeAlbumObjectImpl; + + factory _SpotubeAlbumObject.fromJson(Map json) = + _$SpotubeAlbumObjectImpl.fromJson; + + @override + String get uid; + @override + String get title; + @override + SpotubeArtistObject get artist; + @override + List get images; + @override + String get releaseDate; + @override + String get externalUrl; + @override + SpotubeAlbumType get type; + + /// Create a copy of SpotubeAlbumObject + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SpotubeAlbumObjectImplCopyWith<_$SpotubeAlbumObjectImpl> get copyWith => + throw _privateConstructorUsedError; +} + +SpotubeArtistObject _$SpotubeArtistObjectFromJson(Map json) { + return _SpotubeArtistObject.fromJson(json); +} + +/// @nodoc +mixin _$SpotubeArtistObject { + String get uid => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + List get images => throw _privateConstructorUsedError; + String get externalUrl => throw _privateConstructorUsedError; + + /// Serializes this SpotubeArtistObject to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SpotubeArtistObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SpotubeArtistObjectCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SpotubeArtistObjectCopyWith<$Res> { + factory $SpotubeArtistObjectCopyWith( + SpotubeArtistObject value, $Res Function(SpotubeArtistObject) then) = + _$SpotubeArtistObjectCopyWithImpl<$Res, SpotubeArtistObject>; + @useResult + $Res call( + {String uid, + String name, + List images, + String externalUrl}); +} + +/// @nodoc +class _$SpotubeArtistObjectCopyWithImpl<$Res, $Val extends SpotubeArtistObject> + implements $SpotubeArtistObjectCopyWith<$Res> { + _$SpotubeArtistObjectCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SpotubeArtistObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? name = null, + Object? images = null, + Object? externalUrl = null, + }) { + return _then(_value.copyWith( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + images: null == images + ? _value.images + : images // ignore: cast_nullable_to_non_nullable + as List, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SpotubeArtistObjectImplCopyWith<$Res> + implements $SpotubeArtistObjectCopyWith<$Res> { + factory _$$SpotubeArtistObjectImplCopyWith(_$SpotubeArtistObjectImpl value, + $Res Function(_$SpotubeArtistObjectImpl) then) = + __$$SpotubeArtistObjectImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String uid, + String name, + List images, + String externalUrl}); +} + +/// @nodoc +class __$$SpotubeArtistObjectImplCopyWithImpl<$Res> + extends _$SpotubeArtistObjectCopyWithImpl<$Res, _$SpotubeArtistObjectImpl> + implements _$$SpotubeArtistObjectImplCopyWith<$Res> { + __$$SpotubeArtistObjectImplCopyWithImpl(_$SpotubeArtistObjectImpl _value, + $Res Function(_$SpotubeArtistObjectImpl) _then) + : super(_value, _then); + + /// Create a copy of SpotubeArtistObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? name = null, + Object? images = null, + Object? externalUrl = null, + }) { + return _then(_$SpotubeArtistObjectImpl( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + images: null == images + ? _value._images + : images // ignore: cast_nullable_to_non_nullable + as List, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SpotubeArtistObjectImpl implements _SpotubeArtistObject { + _$SpotubeArtistObjectImpl( + {required this.uid, + required this.name, + final List images = const [], + required this.externalUrl}) + : _images = images; + + factory _$SpotubeArtistObjectImpl.fromJson(Map json) => + _$$SpotubeArtistObjectImplFromJson(json); + + @override + final String uid; + @override + final String name; + final List _images; + @override + @JsonKey() + List get images { + if (_images is EqualUnmodifiableListView) return _images; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_images); + } + + @override + final String externalUrl; + + @override + String toString() { + return 'SpotubeArtistObject(uid: $uid, name: $name, images: $images, externalUrl: $externalUrl)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SpotubeArtistObjectImpl && + (identical(other.uid, uid) || other.uid == uid) && + (identical(other.name, name) || other.name == name) && + const DeepCollectionEquality().equals(other._images, _images) && + (identical(other.externalUrl, externalUrl) || + other.externalUrl == externalUrl)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, uid, name, + const DeepCollectionEquality().hash(_images), externalUrl); + + /// Create a copy of SpotubeArtistObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SpotubeArtistObjectImplCopyWith<_$SpotubeArtistObjectImpl> get copyWith => + __$$SpotubeArtistObjectImplCopyWithImpl<_$SpotubeArtistObjectImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$SpotubeArtistObjectImplToJson( + this, + ); + } +} + +abstract class _SpotubeArtistObject implements SpotubeArtistObject { + factory _SpotubeArtistObject( + {required final String uid, + required final String name, + final List images, + required final String externalUrl}) = _$SpotubeArtistObjectImpl; + + factory _SpotubeArtistObject.fromJson(Map json) = + _$SpotubeArtistObjectImpl.fromJson; + + @override + String get uid; + @override + String get name; + @override + List get images; + @override + String get externalUrl; + + /// Create a copy of SpotubeArtistObject + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SpotubeArtistObjectImplCopyWith<_$SpotubeArtistObjectImpl> get copyWith => + throw _privateConstructorUsedError; +} + +SpotubeImageObject _$SpotubeImageObjectFromJson(Map json) { + return _SpotubeImageObject.fromJson(json); +} + +/// @nodoc +mixin _$SpotubeImageObject { + String get url => throw _privateConstructorUsedError; + int get width => throw _privateConstructorUsedError; + int get height => throw _privateConstructorUsedError; + + /// Serializes this SpotubeImageObject to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SpotubeImageObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SpotubeImageObjectCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SpotubeImageObjectCopyWith<$Res> { + factory $SpotubeImageObjectCopyWith( + SpotubeImageObject value, $Res Function(SpotubeImageObject) then) = + _$SpotubeImageObjectCopyWithImpl<$Res, SpotubeImageObject>; + @useResult + $Res call({String url, int width, int height}); +} + +/// @nodoc +class _$SpotubeImageObjectCopyWithImpl<$Res, $Val extends SpotubeImageObject> + implements $SpotubeImageObjectCopyWith<$Res> { + _$SpotubeImageObjectCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SpotubeImageObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? url = null, + Object? width = null, + Object? height = null, + }) { + return _then(_value.copyWith( + url: null == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String, + width: null == width + ? _value.width + : width // ignore: cast_nullable_to_non_nullable + as int, + height: null == height + ? _value.height + : height // ignore: cast_nullable_to_non_nullable + as int, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SpotubeImageObjectImplCopyWith<$Res> + implements $SpotubeImageObjectCopyWith<$Res> { + factory _$$SpotubeImageObjectImplCopyWith(_$SpotubeImageObjectImpl value, + $Res Function(_$SpotubeImageObjectImpl) then) = + __$$SpotubeImageObjectImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String url, int width, int height}); +} + +/// @nodoc +class __$$SpotubeImageObjectImplCopyWithImpl<$Res> + extends _$SpotubeImageObjectCopyWithImpl<$Res, _$SpotubeImageObjectImpl> + implements _$$SpotubeImageObjectImplCopyWith<$Res> { + __$$SpotubeImageObjectImplCopyWithImpl(_$SpotubeImageObjectImpl _value, + $Res Function(_$SpotubeImageObjectImpl) _then) + : super(_value, _then); + + /// Create a copy of SpotubeImageObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? url = null, + Object? width = null, + Object? height = null, + }) { + return _then(_$SpotubeImageObjectImpl( + url: null == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String, + width: null == width + ? _value.width + : width // ignore: cast_nullable_to_non_nullable + as int, + height: null == height + ? _value.height + : height // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SpotubeImageObjectImpl implements _SpotubeImageObject { + _$SpotubeImageObjectImpl( + {required this.url, required this.width, required this.height}); + + factory _$SpotubeImageObjectImpl.fromJson(Map json) => + _$$SpotubeImageObjectImplFromJson(json); + + @override + final String url; + @override + final int width; + @override + final int height; + + @override + String toString() { + return 'SpotubeImageObject(url: $url, width: $width, height: $height)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SpotubeImageObjectImpl && + (identical(other.url, url) || other.url == url) && + (identical(other.width, width) || other.width == width) && + (identical(other.height, height) || other.height == height)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, url, width, height); + + /// Create a copy of SpotubeImageObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SpotubeImageObjectImplCopyWith<_$SpotubeImageObjectImpl> get copyWith => + __$$SpotubeImageObjectImplCopyWithImpl<_$SpotubeImageObjectImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$SpotubeImageObjectImplToJson( + this, + ); + } +} + +abstract class _SpotubeImageObject implements SpotubeImageObject { + factory _SpotubeImageObject( + {required final String url, + required final int width, + required final int height}) = _$SpotubeImageObjectImpl; + + factory _SpotubeImageObject.fromJson(Map json) = + _$SpotubeImageObjectImpl.fromJson; + + @override + String get url; + @override + int get width; + @override + int get height; + + /// Create a copy of SpotubeImageObject + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SpotubeImageObjectImplCopyWith<_$SpotubeImageObjectImpl> get copyWith => + throw _privateConstructorUsedError; +} + +SpotubePlaylistObject _$SpotubePlaylistObjectFromJson( + Map json) { + return _SpotubePlaylistObject.fromJson(json); +} + +/// @nodoc +mixin _$SpotubePlaylistObject { + String get uid => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + List get images => throw _privateConstructorUsedError; + String get description => throw _privateConstructorUsedError; + String get externalUrl => throw _privateConstructorUsedError; + SpotubeUserObject get owner => throw _privateConstructorUsedError; + List get collaborators => + throw _privateConstructorUsedError; + + /// Serializes this SpotubePlaylistObject to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SpotubePlaylistObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SpotubePlaylistObjectCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SpotubePlaylistObjectCopyWith<$Res> { + factory $SpotubePlaylistObjectCopyWith(SpotubePlaylistObject value, + $Res Function(SpotubePlaylistObject) then) = + _$SpotubePlaylistObjectCopyWithImpl<$Res, SpotubePlaylistObject>; + @useResult + $Res call( + {String uid, + String name, + List images, + String description, + String externalUrl, + SpotubeUserObject owner, + List collaborators}); + + $SpotubeUserObjectCopyWith<$Res> get owner; +} + +/// @nodoc +class _$SpotubePlaylistObjectCopyWithImpl<$Res, + $Val extends SpotubePlaylistObject> + implements $SpotubePlaylistObjectCopyWith<$Res> { + _$SpotubePlaylistObjectCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SpotubePlaylistObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? name = null, + Object? images = null, + Object? description = null, + Object? externalUrl = null, + Object? owner = null, + Object? collaborators = null, + }) { + return _then(_value.copyWith( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + images: null == images + ? _value.images + : images // ignore: cast_nullable_to_non_nullable + as List, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + owner: null == owner + ? _value.owner + : owner // ignore: cast_nullable_to_non_nullable + as SpotubeUserObject, + collaborators: null == collaborators + ? _value.collaborators + : collaborators // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } + + /// Create a copy of SpotubePlaylistObject + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SpotubeUserObjectCopyWith<$Res> get owner { + return $SpotubeUserObjectCopyWith<$Res>(_value.owner, (value) { + return _then(_value.copyWith(owner: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SpotubePlaylistObjectImplCopyWith<$Res> + implements $SpotubePlaylistObjectCopyWith<$Res> { + factory _$$SpotubePlaylistObjectImplCopyWith( + _$SpotubePlaylistObjectImpl value, + $Res Function(_$SpotubePlaylistObjectImpl) then) = + __$$SpotubePlaylistObjectImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String uid, + String name, + List images, + String description, + String externalUrl, + SpotubeUserObject owner, + List collaborators}); + + @override + $SpotubeUserObjectCopyWith<$Res> get owner; +} + +/// @nodoc +class __$$SpotubePlaylistObjectImplCopyWithImpl<$Res> + extends _$SpotubePlaylistObjectCopyWithImpl<$Res, + _$SpotubePlaylistObjectImpl> + implements _$$SpotubePlaylistObjectImplCopyWith<$Res> { + __$$SpotubePlaylistObjectImplCopyWithImpl(_$SpotubePlaylistObjectImpl _value, + $Res Function(_$SpotubePlaylistObjectImpl) _then) + : super(_value, _then); + + /// Create a copy of SpotubePlaylistObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? name = null, + Object? images = null, + Object? description = null, + Object? externalUrl = null, + Object? owner = null, + Object? collaborators = null, + }) { + return _then(_$SpotubePlaylistObjectImpl( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + images: null == images + ? _value._images + : images // ignore: cast_nullable_to_non_nullable + as List, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + owner: null == owner + ? _value.owner + : owner // ignore: cast_nullable_to_non_nullable + as SpotubeUserObject, + collaborators: null == collaborators + ? _value._collaborators + : collaborators // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SpotubePlaylistObjectImpl implements _SpotubePlaylistObject { + _$SpotubePlaylistObjectImpl( + {required this.uid, + required this.name, + final List images = const [], + required this.description, + required this.externalUrl, + required this.owner, + final List collaborators = const []}) + : _images = images, + _collaborators = collaborators; + + factory _$SpotubePlaylistObjectImpl.fromJson(Map json) => + _$$SpotubePlaylistObjectImplFromJson(json); + + @override + final String uid; + @override + final String name; + final List _images; + @override + @JsonKey() + List get images { + if (_images is EqualUnmodifiableListView) return _images; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_images); + } + + @override + final String description; + @override + final String externalUrl; + @override + final SpotubeUserObject owner; + final List _collaborators; + @override + @JsonKey() + List get collaborators { + if (_collaborators is EqualUnmodifiableListView) return _collaborators; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_collaborators); + } + + @override + String toString() { + return 'SpotubePlaylistObject(uid: $uid, name: $name, images: $images, description: $description, externalUrl: $externalUrl, owner: $owner, collaborators: $collaborators)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SpotubePlaylistObjectImpl && + (identical(other.uid, uid) || other.uid == uid) && + (identical(other.name, name) || other.name == name) && + const DeepCollectionEquality().equals(other._images, _images) && + (identical(other.description, description) || + other.description == description) && + (identical(other.externalUrl, externalUrl) || + other.externalUrl == externalUrl) && + (identical(other.owner, owner) || other.owner == owner) && + const DeepCollectionEquality() + .equals(other._collaborators, _collaborators)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + uid, + name, + const DeepCollectionEquality().hash(_images), + description, + externalUrl, + owner, + const DeepCollectionEquality().hash(_collaborators)); + + /// Create a copy of SpotubePlaylistObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SpotubePlaylistObjectImplCopyWith<_$SpotubePlaylistObjectImpl> + get copyWith => __$$SpotubePlaylistObjectImplCopyWithImpl< + _$SpotubePlaylistObjectImpl>(this, _$identity); + + @override + Map toJson() { + return _$$SpotubePlaylistObjectImplToJson( + this, + ); + } +} + +abstract class _SpotubePlaylistObject implements SpotubePlaylistObject { + factory _SpotubePlaylistObject( + {required final String uid, + required final String name, + final List images, + required final String description, + required final String externalUrl, + required final SpotubeUserObject owner, + final List collaborators}) = + _$SpotubePlaylistObjectImpl; + + factory _SpotubePlaylistObject.fromJson(Map json) = + _$SpotubePlaylistObjectImpl.fromJson; + + @override + String get uid; + @override + String get name; + @override + List get images; + @override + String get description; + @override + String get externalUrl; + @override + SpotubeUserObject get owner; + @override + List get collaborators; + + /// Create a copy of SpotubePlaylistObject + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SpotubePlaylistObjectImplCopyWith<_$SpotubePlaylistObjectImpl> + get copyWith => throw _privateConstructorUsedError; +} + +SpotubeSearchResponseObject _$SpotubeSearchResponseObjectFromJson( + Map json) { + return _SpotubeSearchResponseObject.fromJson(json); +} + +/// @nodoc +mixin _$SpotubeSearchResponseObject { + List get tracks => throw _privateConstructorUsedError; + List get albums => throw _privateConstructorUsedError; + List get artists => throw _privateConstructorUsedError; + List get playlists => + throw _privateConstructorUsedError; + + /// Serializes this SpotubeSearchResponseObject to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SpotubeSearchResponseObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SpotubeSearchResponseObjectCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SpotubeSearchResponseObjectCopyWith<$Res> { + factory $SpotubeSearchResponseObjectCopyWith( + SpotubeSearchResponseObject value, + $Res Function(SpotubeSearchResponseObject) then) = + _$SpotubeSearchResponseObjectCopyWithImpl<$Res, + SpotubeSearchResponseObject>; + @useResult + $Res call( + {List tracks, + List albums, + List artists, + List playlists}); +} + +/// @nodoc +class _$SpotubeSearchResponseObjectCopyWithImpl<$Res, + $Val extends SpotubeSearchResponseObject> + implements $SpotubeSearchResponseObjectCopyWith<$Res> { + _$SpotubeSearchResponseObjectCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SpotubeSearchResponseObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? tracks = null, + Object? albums = null, + Object? artists = null, + Object? playlists = null, + }) { + return _then(_value.copyWith( + tracks: null == tracks + ? _value.tracks + : tracks // ignore: cast_nullable_to_non_nullable + as List, + albums: null == albums + ? _value.albums + : albums // ignore: cast_nullable_to_non_nullable + as List, + artists: null == artists + ? _value.artists + : artists // ignore: cast_nullable_to_non_nullable + as List, + playlists: null == playlists + ? _value.playlists + : playlists // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SpotubeSearchResponseObjectImplCopyWith<$Res> + implements $SpotubeSearchResponseObjectCopyWith<$Res> { + factory _$$SpotubeSearchResponseObjectImplCopyWith( + _$SpotubeSearchResponseObjectImpl value, + $Res Function(_$SpotubeSearchResponseObjectImpl) then) = + __$$SpotubeSearchResponseObjectImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {List tracks, + List albums, + List artists, + List playlists}); +} + +/// @nodoc +class __$$SpotubeSearchResponseObjectImplCopyWithImpl<$Res> + extends _$SpotubeSearchResponseObjectCopyWithImpl<$Res, + _$SpotubeSearchResponseObjectImpl> + implements _$$SpotubeSearchResponseObjectImplCopyWith<$Res> { + __$$SpotubeSearchResponseObjectImplCopyWithImpl( + _$SpotubeSearchResponseObjectImpl _value, + $Res Function(_$SpotubeSearchResponseObjectImpl) _then) + : super(_value, _then); + + /// Create a copy of SpotubeSearchResponseObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? tracks = null, + Object? albums = null, + Object? artists = null, + Object? playlists = null, + }) { + return _then(_$SpotubeSearchResponseObjectImpl( + tracks: null == tracks + ? _value._tracks + : tracks // ignore: cast_nullable_to_non_nullable + as List, + albums: null == albums + ? _value._albums + : albums // ignore: cast_nullable_to_non_nullable + as List, + artists: null == artists + ? _value._artists + : artists // ignore: cast_nullable_to_non_nullable + as List, + playlists: null == playlists + ? _value._playlists + : playlists // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SpotubeSearchResponseObjectImpl + implements _SpotubeSearchResponseObject { + _$SpotubeSearchResponseObjectImpl( + {final List tracks = const [], + final List albums = const [], + final List artists = const [], + final List playlists = const []}) + : _tracks = tracks, + _albums = albums, + _artists = artists, + _playlists = playlists; + + factory _$SpotubeSearchResponseObjectImpl.fromJson( + Map json) => + _$$SpotubeSearchResponseObjectImplFromJson(json); + + final List _tracks; + @override + @JsonKey() + List get tracks { + if (_tracks is EqualUnmodifiableListView) return _tracks; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_tracks); + } + + final List _albums; + @override + @JsonKey() + List get albums { + if (_albums is EqualUnmodifiableListView) return _albums; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_albums); + } + + final List _artists; + @override + @JsonKey() + List get artists { + if (_artists is EqualUnmodifiableListView) return _artists; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_artists); + } + + final List _playlists; + @override + @JsonKey() + List get playlists { + if (_playlists is EqualUnmodifiableListView) return _playlists; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_playlists); + } + + @override + String toString() { + return 'SpotubeSearchResponseObject(tracks: $tracks, albums: $albums, artists: $artists, playlists: $playlists)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SpotubeSearchResponseObjectImpl && + const DeepCollectionEquality().equals(other._tracks, _tracks) && + const DeepCollectionEquality().equals(other._albums, _albums) && + const DeepCollectionEquality().equals(other._artists, _artists) && + const DeepCollectionEquality() + .equals(other._playlists, _playlists)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_tracks), + const DeepCollectionEquality().hash(_albums), + const DeepCollectionEquality().hash(_artists), + const DeepCollectionEquality().hash(_playlists)); + + /// Create a copy of SpotubeSearchResponseObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SpotubeSearchResponseObjectImplCopyWith<_$SpotubeSearchResponseObjectImpl> + get copyWith => __$$SpotubeSearchResponseObjectImplCopyWithImpl< + _$SpotubeSearchResponseObjectImpl>(this, _$identity); + + @override + Map toJson() { + return _$$SpotubeSearchResponseObjectImplToJson( + this, + ); + } +} + +abstract class _SpotubeSearchResponseObject + implements SpotubeSearchResponseObject { + factory _SpotubeSearchResponseObject( + {final List tracks, + final List albums, + final List artists, + final List playlists}) = + _$SpotubeSearchResponseObjectImpl; + + factory _SpotubeSearchResponseObject.fromJson(Map json) = + _$SpotubeSearchResponseObjectImpl.fromJson; + + @override + List get tracks; + @override + List get albums; + @override + List get artists; + @override + List get playlists; + + /// Create a copy of SpotubeSearchResponseObject + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SpotubeSearchResponseObjectImplCopyWith<_$SpotubeSearchResponseObjectImpl> + get copyWith => throw _privateConstructorUsedError; +} + +SpotubeTrackObject _$SpotubeTrackObjectFromJson(Map json) { + return _SpotubeTrackObject.fromJson(json); +} + +/// @nodoc +mixin _$SpotubeTrackObject { + String get uid => throw _privateConstructorUsedError; + String get title => throw _privateConstructorUsedError; + List get artists => throw _privateConstructorUsedError; + SpotubeAlbumObject get album => throw _privateConstructorUsedError; + int get durationMs => throw _privateConstructorUsedError; + String get isrc => throw _privateConstructorUsedError; + String get externalUrl => throw _privateConstructorUsedError; + + /// Serializes this SpotubeTrackObject to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SpotubeTrackObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SpotubeTrackObjectCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SpotubeTrackObjectCopyWith<$Res> { + factory $SpotubeTrackObjectCopyWith( + SpotubeTrackObject value, $Res Function(SpotubeTrackObject) then) = + _$SpotubeTrackObjectCopyWithImpl<$Res, SpotubeTrackObject>; + @useResult + $Res call( + {String uid, + String title, + List artists, + SpotubeAlbumObject album, + int durationMs, + String isrc, + String externalUrl}); + + $SpotubeAlbumObjectCopyWith<$Res> get album; +} + +/// @nodoc +class _$SpotubeTrackObjectCopyWithImpl<$Res, $Val extends SpotubeTrackObject> + implements $SpotubeTrackObjectCopyWith<$Res> { + _$SpotubeTrackObjectCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SpotubeTrackObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? title = null, + Object? artists = null, + Object? album = null, + Object? durationMs = null, + Object? isrc = null, + Object? externalUrl = null, + }) { + return _then(_value.copyWith( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + artists: null == artists + ? _value.artists + : artists // ignore: cast_nullable_to_non_nullable + as List, + album: null == album + ? _value.album + : album // ignore: cast_nullable_to_non_nullable + as SpotubeAlbumObject, + durationMs: null == durationMs + ? _value.durationMs + : durationMs // ignore: cast_nullable_to_non_nullable + as int, + isrc: null == isrc + ? _value.isrc + : isrc // ignore: cast_nullable_to_non_nullable + as String, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } + + /// Create a copy of SpotubeTrackObject + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SpotubeAlbumObjectCopyWith<$Res> get album { + return $SpotubeAlbumObjectCopyWith<$Res>(_value.album, (value) { + return _then(_value.copyWith(album: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SpotubeTrackObjectImplCopyWith<$Res> + implements $SpotubeTrackObjectCopyWith<$Res> { + factory _$$SpotubeTrackObjectImplCopyWith(_$SpotubeTrackObjectImpl value, + $Res Function(_$SpotubeTrackObjectImpl) then) = + __$$SpotubeTrackObjectImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String uid, + String title, + List artists, + SpotubeAlbumObject album, + int durationMs, + String isrc, + String externalUrl}); + + @override + $SpotubeAlbumObjectCopyWith<$Res> get album; +} + +/// @nodoc +class __$$SpotubeTrackObjectImplCopyWithImpl<$Res> + extends _$SpotubeTrackObjectCopyWithImpl<$Res, _$SpotubeTrackObjectImpl> + implements _$$SpotubeTrackObjectImplCopyWith<$Res> { + __$$SpotubeTrackObjectImplCopyWithImpl(_$SpotubeTrackObjectImpl _value, + $Res Function(_$SpotubeTrackObjectImpl) _then) + : super(_value, _then); + + /// Create a copy of SpotubeTrackObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? title = null, + Object? artists = null, + Object? album = null, + Object? durationMs = null, + Object? isrc = null, + Object? externalUrl = null, + }) { + return _then(_$SpotubeTrackObjectImpl( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + artists: null == artists + ? _value._artists + : artists // ignore: cast_nullable_to_non_nullable + as List, + album: null == album + ? _value.album + : album // ignore: cast_nullable_to_non_nullable + as SpotubeAlbumObject, + durationMs: null == durationMs + ? _value.durationMs + : durationMs // ignore: cast_nullable_to_non_nullable + as int, + isrc: null == isrc + ? _value.isrc + : isrc // ignore: cast_nullable_to_non_nullable + as String, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SpotubeTrackObjectImpl implements _SpotubeTrackObject { + _$SpotubeTrackObjectImpl( + {required this.uid, + required this.title, + final List artists = const [], + required this.album, + required this.durationMs, + required this.isrc, + required this.externalUrl}) + : _artists = artists; + + factory _$SpotubeTrackObjectImpl.fromJson(Map json) => + _$$SpotubeTrackObjectImplFromJson(json); + + @override + final String uid; + @override + final String title; + final List _artists; + @override + @JsonKey() + List get artists { + if (_artists is EqualUnmodifiableListView) return _artists; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_artists); + } + + @override + final SpotubeAlbumObject album; + @override + final int durationMs; + @override + final String isrc; + @override + final String externalUrl; + + @override + String toString() { + return 'SpotubeTrackObject(uid: $uid, title: $title, artists: $artists, album: $album, durationMs: $durationMs, isrc: $isrc, externalUrl: $externalUrl)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SpotubeTrackObjectImpl && + (identical(other.uid, uid) || other.uid == uid) && + (identical(other.title, title) || other.title == title) && + const DeepCollectionEquality().equals(other._artists, _artists) && + (identical(other.album, album) || other.album == album) && + (identical(other.durationMs, durationMs) || + other.durationMs == durationMs) && + (identical(other.isrc, isrc) || other.isrc == isrc) && + (identical(other.externalUrl, externalUrl) || + other.externalUrl == externalUrl)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + uid, + title, + const DeepCollectionEquality().hash(_artists), + album, + durationMs, + isrc, + externalUrl); + + /// Create a copy of SpotubeTrackObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SpotubeTrackObjectImplCopyWith<_$SpotubeTrackObjectImpl> get copyWith => + __$$SpotubeTrackObjectImplCopyWithImpl<_$SpotubeTrackObjectImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$SpotubeTrackObjectImplToJson( + this, + ); + } +} + +abstract class _SpotubeTrackObject implements SpotubeTrackObject { + factory _SpotubeTrackObject( + {required final String uid, + required final String title, + final List artists, + required final SpotubeAlbumObject album, + required final int durationMs, + required final String isrc, + required final String externalUrl}) = _$SpotubeTrackObjectImpl; + + factory _SpotubeTrackObject.fromJson(Map json) = + _$SpotubeTrackObjectImpl.fromJson; + + @override + String get uid; + @override + String get title; + @override + List get artists; + @override + SpotubeAlbumObject get album; + @override + int get durationMs; + @override + String get isrc; + @override + String get externalUrl; + + /// Create a copy of SpotubeTrackObject + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SpotubeTrackObjectImplCopyWith<_$SpotubeTrackObjectImpl> get copyWith => + throw _privateConstructorUsedError; +} + +SpotubeUserObject _$SpotubeUserObjectFromJson(Map json) { + return _SpotubeUserObject.fromJson(json); +} + +/// @nodoc +mixin _$SpotubeUserObject { + String get uid => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + List get avatars => throw _privateConstructorUsedError; + String get externalUrl => throw _privateConstructorUsedError; + String get displayName => throw _privateConstructorUsedError; + + /// Serializes this SpotubeUserObject to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SpotubeUserObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SpotubeUserObjectCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SpotubeUserObjectCopyWith<$Res> { + factory $SpotubeUserObjectCopyWith( + SpotubeUserObject value, $Res Function(SpotubeUserObject) then) = + _$SpotubeUserObjectCopyWithImpl<$Res, SpotubeUserObject>; + @useResult + $Res call( + {String uid, + String name, + List avatars, + String externalUrl, + String displayName}); +} + +/// @nodoc +class _$SpotubeUserObjectCopyWithImpl<$Res, $Val extends SpotubeUserObject> + implements $SpotubeUserObjectCopyWith<$Res> { + _$SpotubeUserObjectCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SpotubeUserObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? name = null, + Object? avatars = null, + Object? externalUrl = null, + Object? displayName = null, + }) { + return _then(_value.copyWith( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + avatars: null == avatars + ? _value.avatars + : avatars // ignore: cast_nullable_to_non_nullable + as List, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + displayName: null == displayName + ? _value.displayName + : displayName // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SpotubeUserObjectImplCopyWith<$Res> + implements $SpotubeUserObjectCopyWith<$Res> { + factory _$$SpotubeUserObjectImplCopyWith(_$SpotubeUserObjectImpl value, + $Res Function(_$SpotubeUserObjectImpl) then) = + __$$SpotubeUserObjectImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String uid, + String name, + List avatars, + String externalUrl, + String displayName}); +} + +/// @nodoc +class __$$SpotubeUserObjectImplCopyWithImpl<$Res> + extends _$SpotubeUserObjectCopyWithImpl<$Res, _$SpotubeUserObjectImpl> + implements _$$SpotubeUserObjectImplCopyWith<$Res> { + __$$SpotubeUserObjectImplCopyWithImpl(_$SpotubeUserObjectImpl _value, + $Res Function(_$SpotubeUserObjectImpl) _then) + : super(_value, _then); + + /// Create a copy of SpotubeUserObject + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uid = null, + Object? name = null, + Object? avatars = null, + Object? externalUrl = null, + Object? displayName = null, + }) { + return _then(_$SpotubeUserObjectImpl( + uid: null == uid + ? _value.uid + : uid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + avatars: null == avatars + ? _value._avatars + : avatars // ignore: cast_nullable_to_non_nullable + as List, + externalUrl: null == externalUrl + ? _value.externalUrl + : externalUrl // ignore: cast_nullable_to_non_nullable + as String, + displayName: null == displayName + ? _value.displayName + : displayName // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SpotubeUserObjectImpl implements _SpotubeUserObject { + _$SpotubeUserObjectImpl( + {required this.uid, + required this.name, + final List avatars = const [], + required this.externalUrl, + required this.displayName}) + : _avatars = avatars; + + factory _$SpotubeUserObjectImpl.fromJson(Map json) => + _$$SpotubeUserObjectImplFromJson(json); + + @override + final String uid; + @override + final String name; + final List _avatars; + @override + @JsonKey() + List get avatars { + if (_avatars is EqualUnmodifiableListView) return _avatars; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_avatars); + } + + @override + final String externalUrl; + @override + final String displayName; + + @override + String toString() { + return 'SpotubeUserObject(uid: $uid, name: $name, avatars: $avatars, externalUrl: $externalUrl, displayName: $displayName)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SpotubeUserObjectImpl && + (identical(other.uid, uid) || other.uid == uid) && + (identical(other.name, name) || other.name == name) && + const DeepCollectionEquality().equals(other._avatars, _avatars) && + (identical(other.externalUrl, externalUrl) || + other.externalUrl == externalUrl) && + (identical(other.displayName, displayName) || + other.displayName == displayName)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, uid, name, + const DeepCollectionEquality().hash(_avatars), externalUrl, displayName); + + /// Create a copy of SpotubeUserObject + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SpotubeUserObjectImplCopyWith<_$SpotubeUserObjectImpl> get copyWith => + __$$SpotubeUserObjectImplCopyWithImpl<_$SpotubeUserObjectImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$SpotubeUserObjectImplToJson( + this, + ); + } +} + +abstract class _SpotubeUserObject implements SpotubeUserObject { + factory _SpotubeUserObject( + {required final String uid, + required final String name, + final List avatars, + required final String externalUrl, + required final String displayName}) = _$SpotubeUserObjectImpl; + + factory _SpotubeUserObject.fromJson(Map json) = + _$SpotubeUserObjectImpl.fromJson; + + @override + String get uid; + @override + String get name; + @override + List get avatars; + @override + String get externalUrl; + @override + String get displayName; + + /// Create a copy of SpotubeUserObject + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SpotubeUserObjectImplCopyWith<_$SpotubeUserObjectImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/models/metadata/metadata.g.dart b/lib/models/metadata/metadata.g.dart new file mode 100644 index 00000000..ee386b19 --- /dev/null +++ b/lib/models/metadata/metadata.g.dart @@ -0,0 +1,193 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'metadata.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$SpotubeAlbumObjectImpl _$$SpotubeAlbumObjectImplFromJson(Map json) => + _$SpotubeAlbumObjectImpl( + uid: json['uid'] as String, + title: json['title'] as String, + artist: SpotubeArtistObject.fromJson( + Map.from(json['artist'] as Map)), + images: (json['images'] as List?) + ?.map((e) => SpotubeImageObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + releaseDate: json['releaseDate'] as String, + externalUrl: json['externalUrl'] as String, + type: $enumDecode(_$SpotubeAlbumTypeEnumMap, json['type']), + ); + +Map _$$SpotubeAlbumObjectImplToJson( + _$SpotubeAlbumObjectImpl instance) => + { + 'uid': instance.uid, + 'title': instance.title, + 'artist': instance.artist.toJson(), + 'images': instance.images.map((e) => e.toJson()).toList(), + 'releaseDate': instance.releaseDate, + 'externalUrl': instance.externalUrl, + 'type': _$SpotubeAlbumTypeEnumMap[instance.type]!, + }; + +const _$SpotubeAlbumTypeEnumMap = { + SpotubeAlbumType.album: 'album', + SpotubeAlbumType.single: 'single', +}; + +_$SpotubeArtistObjectImpl _$$SpotubeArtistObjectImplFromJson(Map json) => + _$SpotubeArtistObjectImpl( + uid: json['uid'] as String, + name: json['name'] as String, + images: (json['images'] as List?) + ?.map((e) => SpotubeImageObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + externalUrl: json['externalUrl'] as String, + ); + +Map _$$SpotubeArtistObjectImplToJson( + _$SpotubeArtistObjectImpl instance) => + { + 'uid': instance.uid, + 'name': instance.name, + 'images': instance.images.map((e) => e.toJson()).toList(), + 'externalUrl': instance.externalUrl, + }; + +_$SpotubeImageObjectImpl _$$SpotubeImageObjectImplFromJson(Map json) => + _$SpotubeImageObjectImpl( + url: json['url'] as String, + width: (json['width'] as num).toInt(), + height: (json['height'] as num).toInt(), + ); + +Map _$$SpotubeImageObjectImplToJson( + _$SpotubeImageObjectImpl instance) => + { + 'url': instance.url, + 'width': instance.width, + 'height': instance.height, + }; + +_$SpotubePlaylistObjectImpl _$$SpotubePlaylistObjectImplFromJson(Map json) => + _$SpotubePlaylistObjectImpl( + uid: json['uid'] as String, + name: json['name'] as String, + images: (json['images'] as List?) + ?.map((e) => SpotubeImageObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + description: json['description'] as String, + externalUrl: json['externalUrl'] as String, + owner: SpotubeUserObject.fromJson( + Map.from(json['owner'] as Map)), + collaborators: (json['collaborators'] as List?) + ?.map((e) => SpotubeUserObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + ); + +Map _$$SpotubePlaylistObjectImplToJson( + _$SpotubePlaylistObjectImpl instance) => + { + 'uid': instance.uid, + 'name': instance.name, + 'images': instance.images.map((e) => e.toJson()).toList(), + 'description': instance.description, + 'externalUrl': instance.externalUrl, + 'owner': instance.owner.toJson(), + 'collaborators': instance.collaborators.map((e) => e.toJson()).toList(), + }; + +_$SpotubeSearchResponseObjectImpl _$$SpotubeSearchResponseObjectImplFromJson( + Map json) => + _$SpotubeSearchResponseObjectImpl( + tracks: (json['tracks'] as List?) + ?.map((e) => SpotubeTrackObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + albums: (json['albums'] as List?) + ?.map((e) => SpotubeAlbumObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + artists: (json['artists'] as List?) + ?.map((e) => SpotubeArtistObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + playlists: (json['playlists'] as List?) + ?.map((e) => SpotubePlaylistObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + ); + +Map _$$SpotubeSearchResponseObjectImplToJson( + _$SpotubeSearchResponseObjectImpl instance) => + { + '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(), + }; + +_$SpotubeTrackObjectImpl _$$SpotubeTrackObjectImplFromJson(Map json) => + _$SpotubeTrackObjectImpl( + uid: json['uid'] as String, + title: json['title'] as String, + artists: (json['artists'] as List?) + ?.map((e) => SpotubeArtistObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + album: SpotubeAlbumObject.fromJson( + Map.from(json['album'] as Map)), + durationMs: (json['durationMs'] as num).toInt(), + isrc: json['isrc'] as String, + externalUrl: json['externalUrl'] as String, + ); + +Map _$$SpotubeTrackObjectImplToJson( + _$SpotubeTrackObjectImpl instance) => + { + 'uid': instance.uid, + 'title': instance.title, + 'artists': instance.artists.map((e) => e.toJson()).toList(), + 'album': instance.album.toJson(), + 'durationMs': instance.durationMs, + 'isrc': instance.isrc, + 'externalUrl': instance.externalUrl, + }; + +_$SpotubeUserObjectImpl _$$SpotubeUserObjectImplFromJson(Map json) => + _$SpotubeUserObjectImpl( + uid: json['uid'] as String, + name: json['name'] as String, + avatars: (json['avatars'] as List?) + ?.map((e) => SpotubeImageObject.fromJson( + Map.from(e as Map))) + .toList() ?? + const [], + externalUrl: json['externalUrl'] as String, + displayName: json['displayName'] as String, + ); + +Map _$$SpotubeUserObjectImplToJson( + _$SpotubeUserObjectImpl instance) => + { + 'uid': instance.uid, + 'name': instance.name, + 'avatars': instance.avatars.map((e) => e.toJson()).toList(), + 'externalUrl': instance.externalUrl, + 'displayName': instance.displayName, + }; diff --git a/lib/models/metadata/playlist.dart b/lib/models/metadata/playlist.dart new file mode 100644 index 00000000..d6c686dd --- /dev/null +++ b/lib/models/metadata/playlist.dart @@ -0,0 +1,17 @@ +part of 'metadata.dart'; + +@freezed +class SpotubePlaylistObject with _$SpotubePlaylistObject { + factory SpotubePlaylistObject({ + required final String uid, + required final String name, + @Default([]) final List images, + required final String description, + required final String externalUrl, + required final SpotubeUserObject owner, + @Default([]) final List collaborators, + }) = _SpotubePlaylistObject; + + factory SpotubePlaylistObject.fromJson(Map json) => + _$SpotubePlaylistObjectFromJson(json); +} diff --git a/lib/models/metadata/search.dart b/lib/models/metadata/search.dart new file mode 100644 index 00000000..011238f7 --- /dev/null +++ b/lib/models/metadata/search.dart @@ -0,0 +1,14 @@ +part of 'metadata.dart'; + +@freezed +class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject { + factory SpotubeSearchResponseObject({ + @Default([]) final List tracks, + @Default([]) final List albums, + @Default([]) final List artists, + @Default([]) final List playlists, + }) = _SpotubeSearchResponseObject; + + factory SpotubeSearchResponseObject.fromJson(Map json) => + _$SpotubeSearchResponseObjectFromJson(json); +} diff --git a/lib/models/metadata/track.dart b/lib/models/metadata/track.dart new file mode 100644 index 00000000..f555b27f --- /dev/null +++ b/lib/models/metadata/track.dart @@ -0,0 +1,17 @@ +part of 'metadata.dart'; + +@freezed +class SpotubeTrackObject with _$SpotubeTrackObject { + factory SpotubeTrackObject({ + required final String uid, + required final String title, + @Default([]) final List artists, + required final SpotubeAlbumObject album, + required final int durationMs, + required final String isrc, + required final String externalUrl, + }) = _SpotubeTrackObject; + + factory SpotubeTrackObject.fromJson(Map json) => + _$SpotubeTrackObjectFromJson(json); +} diff --git a/lib/models/metadata/user.dart b/lib/models/metadata/user.dart new file mode 100644 index 00000000..878f2da6 --- /dev/null +++ b/lib/models/metadata/user.dart @@ -0,0 +1,15 @@ +part of 'metadata.dart'; + +@freezed +class SpotubeUserObject with _$SpotubeUserObject { + factory SpotubeUserObject({ + required final String uid, + required final String name, + @Default([]) final List avatars, + required final String externalUrl, + required final String displayName, + }) = _SpotubeUserObject; + + factory SpotubeUserObject.fromJson(Map json) => + _$SpotubeUserObjectFromJson(json); +} diff --git a/lib/services/metadata/metadata.dart b/lib/services/metadata/metadata.dart new file mode 100644 index 00000000..29df4a7d --- /dev/null +++ b/lib/services/metadata/metadata.dart @@ -0,0 +1,308 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter_js/flutter_js.dart'; +import 'package:spotube/models/metadata/metadata.dart'; +import 'package:spotube/services/logger/logger.dart'; + +const int defaultMetadataLimit = 20; +const int defaultMetadataOffset = 0; + +/// Signature for metadata and related methods that will return Spotube native +/// objects e.g. SpotubeTrack, SpotubePlaylist, etc. +class MetadataApiSignature { + late final JavascriptRuntime runtime; + + MetadataApiSignature(String libraryCode) { + runtime = getJavascriptRuntime(xhr: true); + runtime.enableHandlePromises(); + + Timer.periodic( + const Duration(milliseconds: 100), + (timer) { + runtime.executePendingJob(); + }, + ); + + runtime.evaluate( + """ + ;$libraryCode; + const metadataApi = new MetadataApi(); + """, + ); + } + + void dispose() { + runtime.dispose(); + } + + Future invoke(String method, [List? args]) async { + final completer = Completer(); + runtime.onMessage(method, (result) { + try { + if (result == null) { + completer.completeError("Result is null"); + } else { + completer.complete(result is String ? jsonDecode(result) : result); + } + } catch (e, stack) { + AppLogger.reportError(e, stack); + } + }); + final code = """ + $method(...${args != null ? jsonEncode(args) : "[]"}) + .then((res) => { + sendMessage("$method", JSON.stringify(res)); + }).catch((err) => { + sendMessage("$method", null); + async}){ + } final res"metadataApi.=>", [limit, offset] ;= await invoke() + + return res.map(es.fromJson).toList(); + """; + + final res = await runtime.evaluateAsync(code); + + if (res.isError) { + AppLogger.reportError("Error evaluating code: $code\n${res.rawResult}"); + completer.completeError("Error evaluating code: $code\n${res.rawResult}"); + return completer.future; + } + + return completer.future; + } + + // ----- Track ------ + Future getTrack(String id) async { + final result = await invoke("metadataApi.getTrack", [id]); + return SpotubeTrackObject.fromJson(result); + } + + Future> listTracks({ + List? ids, + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final result = await invoke( + "metadataApi.listTracks", + [ + ids, + limit, + offset, + ], + ); + + return result.map(SpotubeTrackObject.fromJson).toList(); + } + + Future> listTracksByAlbum( + String albumId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listTracksByAlbum", + [albumId, limit, offset], + ); + + return res.map(SpotubeTrackObject.fromJson).toList(); + } + + Future> listTopTracksByArtist( + String artistId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listTopTracksByArtist", + [artistId, limit, offset], + ); + + return res.map(SpotubeTrackObject.fromJson).toList(); + } + + Future> listTracksByPlaylist( + String playlistId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listTracksByPlaylist", + [playlistId, limit, offset], + ); + + return res.map(SpotubeTrackObject.fromJson).toList(); + } + + Future> listUserSavedTracks( + String userId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listUserSavedTracks", + [userId, limit, offset], + ); + + return res.map(SpotubeTrackObject.fromJson).toList(); + } + + // ----- Album ------ + Future getAlbum(String id) async { + final res = await invoke("metadataApi.getAlbum", [id]); + + return SpotubeAlbumObject.fromJson(res); + } + + Future> listAlbums({ + List? ids, + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listAlbums", + [ids, limit, offset], + ); + + return res.map(SpotubeAlbumObject.fromJson).toList(); + } + + Future> listAlbumsByArtist( + String artistId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listAlbumsByArtist", + [artistId, limit, offset], + ); + + return res.map(SpotubeAlbumObject.fromJson).toList(); + } + + Future> listUserSavedAlbums( + String userId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listUserSavedAlbums", + [userId, limit, offset], + ); + + return res.map(SpotubeAlbumObject.fromJson).toList(); + } + + // ----- Playlist ------ + Future getPlaylist(String id) async { + final res = await invoke("metadataApi.getPlaylist", [id]); + + return SpotubePlaylistObject.fromJson(res); + } + + Future> listPlaylists({ + List? ids, + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listPlaylists", + [ids, limit, offset], + ); + + return res.map(SpotubePlaylistObject.fromJson).toList(); + } + + Future> listUserSavedPlaylists( + String userId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listUserSavedPlaylists", + [userId, limit, offset], + ); + + return res.map(SpotubePlaylistObject.fromJson).toList(); + } + + // ----- Artist ------ + Future getArtist(String id) async { + final res = await invoke("metadataApi.getArtist", [id]); + + return SpotubeArtistObject.fromJson(res); + } + + Future> listArtists({ + List? ids, + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listArtists", + [ids, limit, offset], + ); + + return res.map(SpotubeArtistObject.fromJson).toList(); + } + + Future> listUserSavedArtists( + String userId, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.listUserSavedArtists", + [userId, limit, offset], + ); + + return res.map(SpotubeArtistObject.fromJson).toList(); + } + + // ----- Search ------ + Future search( + String query, { + int limit = defaultMetadataLimit, + int offset = defaultMetadataOffset, + }) async { + final res = await invoke( + "metadataApi.search", + [query, limit, offset], + ); + + return res.map(SpotubeSearchResponseObject.fromJson).toList(); + } + + // ----- User ------ + Future followArtist(String userId, String artistId) async { + await invoke("metadataApi.followArtist", [userId, artistId]); + } + + Future unfollowArtist(String userId, String artistId) async { + await invoke("metadataApi.unfollowArtist", [userId, artistId]); + } + + Future savePlaylist(String userId, String playlistId) async { + await invoke("metadataApi.savePlaylist", [userId, playlistId]); + } + + Future unsavePlaylist(String userId, String playlistId) async { + await invoke("metadataApi.unsavePlaylist", [userId, playlistId]); + } + + Future saveAlbum(String userId, String albumId) async { + await invoke("metadataApi.saveAlbum", [userId, albumId]); + } + + Future unsaveAlbum(String userId, String albumId) async { + await invoke("metadataApi.unsaveAlbum", [userId, albumId]); + } + + Future saveTrack(String userId, String trackId) async { + await invoke("metadataApi.saveTrack", [userId, trackId]); + } + + Future unsaveTrack(String userId, String trackId) async { + await invoke("metadataApi.unsaveTrack", [userId, trackId]); + } +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 06c33e05..3976fd80 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) flutter_js_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterJsPlugin"); + flutter_js_plugin_register_with_registrar(flutter_js_registrar); g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index e98b18eb..c47d2627 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_window file_selector_linux + flutter_js flutter_secure_storage_linux gtk local_notifier diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b92d7882..d44e5a13 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -14,6 +14,7 @@ import desktop_webview_window import device_info_plus import file_selector_macos import flutter_inappwebview_macos +import flutter_js import flutter_secure_storage_macos import local_notifier import media_kit_libs_macos_audio @@ -39,6 +40,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) + FlutterJsPlugin.register(with: registry.registrar(forPlugin: "FlutterJsPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin")) MediaKitLibsMacosAudioPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosAudioPlugin")) diff --git a/pubspec.lock b/pubspec.lock index db9cdb80..76e05a60 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -909,6 +909,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" + flutter_js: + dependency: "direct main" + description: + name: flutter_js + sha256: "6b777cd4e468546f046a2f114d078a4596143269f6fa6bad5c29611d5b896369" + url: "https://pub.dev" + source: hosted + version: "0.8.2" flutter_launcher_icons: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index f3be4108..be622bf1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -142,6 +142,7 @@ dependencies: collection: any otp_util: ^1.0.2 dio_http2_adapter: ^2.6.0 + flutter_js: ^0.8.2 dev_dependencies: build_runner: ^2.4.13 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index d1bee122..9ad3a3a5 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FileSelectorWindows")); FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi")); + FlutterJsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterJsPlugin")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); LocalNotifierPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 32c8a634..a9b74bf4 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -9,6 +9,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_window file_selector_windows flutter_inappwebview_windows + flutter_js flutter_secure_storage_windows local_notifier media_kit_libs_windows_audio