mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-12-06 07:29:42 +00:00
chore: wip implemented rust side
This commit is contained in:
parent
67cf9805a5
commit
57553cdb2e
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -30,5 +30,8 @@
|
|||||||
"README.md": "LICENSE,CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,CONTRIBUTION.md,CHANGELOG.md,PRIVACY_POLICY.md",
|
"README.md": "LICENSE,CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,CONTRIBUTION.md,CHANGELOG.md,PRIVACY_POLICY.md",
|
||||||
"*.dart": "${capture}.g.dart,${capture}.freezed.dart"
|
"*.dart": "${capture}.g.dart,${capture}.freezed.dart"
|
||||||
},
|
},
|
||||||
"dart.flutterSdkPath": ".fvm/versions/3.35.2"
|
"dart.flutterSdkPath": ".fvm/versions/3.35.2",
|
||||||
|
"rust-analyzer.files.exclude": [
|
||||||
|
"rust/src/frb_generated.rs"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@ -1,3 +1,7 @@
|
|||||||
rust_input: crate::api
|
rust_input: crate::api
|
||||||
rust_root: rust/
|
rust_root: rust/
|
||||||
dart_output: lib/src/rust
|
dart_output: lib/src/rust
|
||||||
|
web: false
|
||||||
|
enable_lifetime: true
|
||||||
|
rust_preamble: |
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
|||||||
@ -45,6 +45,9 @@ import 'package:spotube/services/kv_store/encrypted_kv_store.dart';
|
|||||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||||
import 'package:spotube/services/logger/logger.dart';
|
import 'package:spotube/services/logger/logger.dart';
|
||||||
import 'package:spotube/services/wm_tools/wm_tools.dart';
|
import 'package:spotube/services/wm_tools/wm_tools.dart';
|
||||||
|
import 'package:spotube/src/rust/api/plugin/models/core.dart';
|
||||||
|
import 'package:spotube/src/rust/api/plugin/plugin.dart';
|
||||||
|
import 'package:spotube/src/rust/frb_generated.dart';
|
||||||
import 'package:spotube/utils/migrations/sandbox.dart';
|
import 'package:spotube/utils/migrations/sandbox.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
@ -55,6 +58,23 @@ import 'package:shadcn_flutter/shadcn_flutter.dart';
|
|||||||
import 'package:yt_dlp_dart/yt_dlp_dart.dart';
|
import 'package:yt_dlp_dart/yt_dlp_dart.dart';
|
||||||
import 'package:flutter_new_pipe_extractor/flutter_new_pipe_extractor.dart';
|
import 'package:flutter_new_pipe_extractor/flutter_new_pipe_extractor.dart';
|
||||||
|
|
||||||
|
const pluginJS = """
|
||||||
|
class CoreEndpoint {
|
||||||
|
async checkUpdate() {
|
||||||
|
console.log('Core checkUpdate');
|
||||||
|
}
|
||||||
|
support() {
|
||||||
|
return 'Metadata';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestingPlugin {
|
||||||
|
constructor() {
|
||||||
|
this.core = new CoreEndpoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
Future<void> main(List<String> rawArgs) async {
|
Future<void> main(List<String> rawArgs) async {
|
||||||
if (rawArgs.contains("web_view_title_bar")) {
|
if (rawArgs.contains("web_view_title_bar")) {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@ -94,6 +114,26 @@ Future<void> main(List<String> rawArgs) async {
|
|||||||
|
|
||||||
await KVStoreService.initialize();
|
await KVStoreService.initialize();
|
||||||
|
|
||||||
|
await RustLib.init();
|
||||||
|
|
||||||
|
final plugin = SpotubePlugin();
|
||||||
|
final sender = SpotubePlugin.newContext(
|
||||||
|
pluginScript: pluginJS,
|
||||||
|
pluginConfig: const PluginConfiguration(
|
||||||
|
entryPoint: "TestingPlugin",
|
||||||
|
abilities: [PluginAbility.metadata],
|
||||||
|
apis: [],
|
||||||
|
author: "KRTirtho",
|
||||||
|
description: "Testing Plugin",
|
||||||
|
name: "Testing Plugin",
|
||||||
|
pluginApiVersion: "2.0.0",
|
||||||
|
repository: null,
|
||||||
|
version: "0.1.0",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await plugin.dispose(tx: sender);
|
||||||
|
|
||||||
if (kIsDesktop) {
|
if (kIsDesktop) {
|
||||||
await windowManager.setPreventClose(true);
|
await windowManager.setPreventClose(true);
|
||||||
await YtDlp.instance
|
await YtDlp.instance
|
||||||
|
|||||||
12
lib/src/rust/api/plugin/commands.dart
Normal file
12
lib/src/rust/api/plugin/commands.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../frb_generated.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
|
||||||
|
// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `AlbumCommands`, `ArtistCommands`, `AudioSourceCommands`, `AuthCommands`, `BrowseCommands`, `CoreCommands`, `PlaylistCommands`, `SearchCommands`, `TrackCommands`, `UserCommands`
|
||||||
|
|
||||||
|
// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<PluginCommand>>
|
||||||
|
abstract class PluginCommand implements RustOpaqueInterface {}
|
||||||
58
lib/src/rust/api/plugin/models/album.dart
Normal file
58
lib/src/rust/api/plugin/models/album.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'artist.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
part 'album.freezed.dart';
|
||||||
|
part 'album.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`
|
||||||
|
|
||||||
|
enum SpotubeAlbumType {
|
||||||
|
album,
|
||||||
|
single,
|
||||||
|
compilation,
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeFullAlbumObject with _$SpotubeFullAlbumObject {
|
||||||
|
const factory SpotubeFullAlbumObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required List<SpotubeImageObject> images,
|
||||||
|
required String releaseDate,
|
||||||
|
required String externalUri,
|
||||||
|
required int totalTracks,
|
||||||
|
required SpotubeAlbumType albumType,
|
||||||
|
String? recordLabel,
|
||||||
|
List<String>? genres,
|
||||||
|
}) = _SpotubeFullAlbumObject;
|
||||||
|
|
||||||
|
factory SpotubeFullAlbumObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeFullAlbumObjectFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeSimpleAlbumObject with _$SpotubeSimpleAlbumObject {
|
||||||
|
const factory SpotubeSimpleAlbumObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String externalUri,
|
||||||
|
required List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required List<SpotubeImageObject> images,
|
||||||
|
required SpotubeAlbumType albumType,
|
||||||
|
String? releaseDate,
|
||||||
|
}) = _SpotubeSimpleAlbumObject;
|
||||||
|
|
||||||
|
factory SpotubeSimpleAlbumObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeSimpleAlbumObjectFromJson(json);
|
||||||
|
}
|
||||||
742
lib/src/rust/api/plugin/models/album.freezed.dart
Normal file
742
lib/src/rust/api/plugin/models/album.freezed.dart
Normal file
@ -0,0 +1,742 @@
|
|||||||
|
// 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 'album.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(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');
|
||||||
|
|
||||||
|
SpotubeFullAlbumObject _$SpotubeFullAlbumObjectFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return _SpotubeFullAlbumObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeFullAlbumObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeSimpleArtistObject> get artists =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject> get images => throw _privateConstructorUsedError;
|
||||||
|
String get releaseDate => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
int get totalTracks => throw _privateConstructorUsedError;
|
||||||
|
SpotubeAlbumType get albumType => throw _privateConstructorUsedError;
|
||||||
|
String? get recordLabel => throw _privateConstructorUsedError;
|
||||||
|
List<String>? get genres => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeFullAlbumObject to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$SpotubeFullAlbumObjectCopyWith<SpotubeFullAlbumObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeFullAlbumObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeFullAlbumObjectCopyWith(SpotubeFullAlbumObject value,
|
||||||
|
$Res Function(SpotubeFullAlbumObject) then) =
|
||||||
|
_$SpotubeFullAlbumObjectCopyWithImpl<$Res, SpotubeFullAlbumObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
List<SpotubeSimpleArtistObject> artists,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
String releaseDate,
|
||||||
|
String externalUri,
|
||||||
|
int totalTracks,
|
||||||
|
SpotubeAlbumType albumType,
|
||||||
|
String? recordLabel,
|
||||||
|
List<String>? genres});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SpotubeFullAlbumObjectCopyWithImpl<$Res,
|
||||||
|
$Val extends SpotubeFullAlbumObject>
|
||||||
|
implements $SpotubeFullAlbumObjectCopyWith<$Res> {
|
||||||
|
_$SpotubeFullAlbumObjectCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? releaseDate = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? totalTracks = null,
|
||||||
|
Object? albumType = null,
|
||||||
|
Object? recordLabel = freezed,
|
||||||
|
Object? genres = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
artists: null == artists
|
||||||
|
? _value.artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleArtistObject>,
|
||||||
|
images: null == images
|
||||||
|
? _value.images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
releaseDate: null == releaseDate
|
||||||
|
? _value.releaseDate
|
||||||
|
: releaseDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
totalTracks: null == totalTracks
|
||||||
|
? _value.totalTracks
|
||||||
|
: totalTracks // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
albumType: null == albumType
|
||||||
|
? _value.albumType
|
||||||
|
: albumType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeAlbumType,
|
||||||
|
recordLabel: freezed == recordLabel
|
||||||
|
? _value.recordLabel
|
||||||
|
: recordLabel // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
genres: freezed == genres
|
||||||
|
? _value.genres
|
||||||
|
: genres // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>?,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$SpotubeFullAlbumObjectImplCopyWith<$Res>
|
||||||
|
implements $SpotubeFullAlbumObjectCopyWith<$Res> {
|
||||||
|
factory _$$SpotubeFullAlbumObjectImplCopyWith(
|
||||||
|
_$SpotubeFullAlbumObjectImpl value,
|
||||||
|
$Res Function(_$SpotubeFullAlbumObjectImpl) then) =
|
||||||
|
__$$SpotubeFullAlbumObjectImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
List<SpotubeSimpleArtistObject> artists,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
String releaseDate,
|
||||||
|
String externalUri,
|
||||||
|
int totalTracks,
|
||||||
|
SpotubeAlbumType albumType,
|
||||||
|
String? recordLabel,
|
||||||
|
List<String>? genres});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$SpotubeFullAlbumObjectImplCopyWithImpl<$Res>
|
||||||
|
extends _$SpotubeFullAlbumObjectCopyWithImpl<$Res,
|
||||||
|
_$SpotubeFullAlbumObjectImpl>
|
||||||
|
implements _$$SpotubeFullAlbumObjectImplCopyWith<$Res> {
|
||||||
|
__$$SpotubeFullAlbumObjectImplCopyWithImpl(
|
||||||
|
_$SpotubeFullAlbumObjectImpl _value,
|
||||||
|
$Res Function(_$SpotubeFullAlbumObjectImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? releaseDate = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? totalTracks = null,
|
||||||
|
Object? albumType = null,
|
||||||
|
Object? recordLabel = freezed,
|
||||||
|
Object? genres = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeFullAlbumObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
artists: null == artists
|
||||||
|
? _value._artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleArtistObject>,
|
||||||
|
images: null == images
|
||||||
|
? _value._images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
releaseDate: null == releaseDate
|
||||||
|
? _value.releaseDate
|
||||||
|
: releaseDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
totalTracks: null == totalTracks
|
||||||
|
? _value.totalTracks
|
||||||
|
: totalTracks // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
albumType: null == albumType
|
||||||
|
? _value.albumType
|
||||||
|
: albumType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeAlbumType,
|
||||||
|
recordLabel: freezed == recordLabel
|
||||||
|
? _value.recordLabel
|
||||||
|
: recordLabel // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
genres: freezed == genres
|
||||||
|
? _value._genres
|
||||||
|
: genres // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeFullAlbumObjectImpl implements _SpotubeFullAlbumObject {
|
||||||
|
const _$SpotubeFullAlbumObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required final List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required this.releaseDate,
|
||||||
|
required this.externalUri,
|
||||||
|
required this.totalTracks,
|
||||||
|
required this.albumType,
|
||||||
|
this.recordLabel,
|
||||||
|
final List<String>? genres})
|
||||||
|
: _artists = artists,
|
||||||
|
_images = images,
|
||||||
|
_genres = genres;
|
||||||
|
|
||||||
|
factory _$SpotubeFullAlbumObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeFullAlbumObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
final List<SpotubeSimpleArtistObject> _artists;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleArtistObject> get artists {
|
||||||
|
if (_artists is EqualUnmodifiableListView) return _artists;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_artists);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SpotubeImageObject> _images;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images {
|
||||||
|
if (_images is EqualUnmodifiableListView) return _images;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String releaseDate;
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
@override
|
||||||
|
final int totalTracks;
|
||||||
|
@override
|
||||||
|
final SpotubeAlbumType albumType;
|
||||||
|
@override
|
||||||
|
final String? recordLabel;
|
||||||
|
final List<String>? _genres;
|
||||||
|
@override
|
||||||
|
List<String>? get genres {
|
||||||
|
final value = _genres;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_genres is EqualUnmodifiableListView) return _genres;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeFullAlbumObject(typeName: $typeName, id: $id, name: $name, artists: $artists, images: $images, releaseDate: $releaseDate, externalUri: $externalUri, totalTracks: $totalTracks, albumType: $albumType, recordLabel: $recordLabel, genres: $genres)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeFullAlbumObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
const DeepCollectionEquality().equals(other._artists, _artists) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images) &&
|
||||||
|
(identical(other.releaseDate, releaseDate) ||
|
||||||
|
other.releaseDate == releaseDate) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri) &&
|
||||||
|
(identical(other.totalTracks, totalTracks) ||
|
||||||
|
other.totalTracks == totalTracks) &&
|
||||||
|
(identical(other.albumType, albumType) ||
|
||||||
|
other.albumType == albumType) &&
|
||||||
|
(identical(other.recordLabel, recordLabel) ||
|
||||||
|
other.recordLabel == recordLabel) &&
|
||||||
|
const DeepCollectionEquality().equals(other._genres, _genres));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
typeName,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
const DeepCollectionEquality().hash(_artists),
|
||||||
|
const DeepCollectionEquality().hash(_images),
|
||||||
|
releaseDate,
|
||||||
|
externalUri,
|
||||||
|
totalTracks,
|
||||||
|
albumType,
|
||||||
|
recordLabel,
|
||||||
|
const DeepCollectionEquality().hash(_genres));
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$SpotubeFullAlbumObjectImplCopyWith<_$SpotubeFullAlbumObjectImpl>
|
||||||
|
get copyWith => __$$SpotubeFullAlbumObjectImplCopyWithImpl<
|
||||||
|
_$SpotubeFullAlbumObjectImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeFullAlbumObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeFullAlbumObject implements SpotubeFullAlbumObject {
|
||||||
|
const factory _SpotubeFullAlbumObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required final String releaseDate,
|
||||||
|
required final String externalUri,
|
||||||
|
required final int totalTracks,
|
||||||
|
required final SpotubeAlbumType albumType,
|
||||||
|
final String? recordLabel,
|
||||||
|
final List<String>? genres}) = _$SpotubeFullAlbumObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeFullAlbumObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeFullAlbumObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleArtistObject> get artists;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images;
|
||||||
|
@override
|
||||||
|
String get releaseDate;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
int get totalTracks;
|
||||||
|
@override
|
||||||
|
SpotubeAlbumType get albumType;
|
||||||
|
@override
|
||||||
|
String? get recordLabel;
|
||||||
|
@override
|
||||||
|
List<String>? get genres;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$SpotubeFullAlbumObjectImplCopyWith<_$SpotubeFullAlbumObjectImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpotubeSimpleAlbumObject _$SpotubeSimpleAlbumObjectFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return _SpotubeSimpleAlbumObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeSimpleAlbumObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeSimpleArtistObject> get artists =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject> get images => throw _privateConstructorUsedError;
|
||||||
|
SpotubeAlbumType get albumType => throw _privateConstructorUsedError;
|
||||||
|
String? get releaseDate => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeSimpleAlbumObject to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$SpotubeSimpleAlbumObjectCopyWith<SpotubeSimpleAlbumObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeSimpleAlbumObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeSimpleAlbumObjectCopyWith(SpotubeSimpleAlbumObject value,
|
||||||
|
$Res Function(SpotubeSimpleAlbumObject) then) =
|
||||||
|
_$SpotubeSimpleAlbumObjectCopyWithImpl<$Res, SpotubeSimpleAlbumObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeSimpleArtistObject> artists,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
SpotubeAlbumType albumType,
|
||||||
|
String? releaseDate});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SpotubeSimpleAlbumObjectCopyWithImpl<$Res,
|
||||||
|
$Val extends SpotubeSimpleAlbumObject>
|
||||||
|
implements $SpotubeSimpleAlbumObjectCopyWith<$Res> {
|
||||||
|
_$SpotubeSimpleAlbumObjectCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? albumType = null,
|
||||||
|
Object? releaseDate = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
artists: null == artists
|
||||||
|
? _value.artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleArtistObject>,
|
||||||
|
images: null == images
|
||||||
|
? _value.images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
albumType: null == albumType
|
||||||
|
? _value.albumType
|
||||||
|
: albumType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeAlbumType,
|
||||||
|
releaseDate: freezed == releaseDate
|
||||||
|
? _value.releaseDate
|
||||||
|
: releaseDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$SpotubeSimpleAlbumObjectImplCopyWith<$Res>
|
||||||
|
implements $SpotubeSimpleAlbumObjectCopyWith<$Res> {
|
||||||
|
factory _$$SpotubeSimpleAlbumObjectImplCopyWith(
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl value,
|
||||||
|
$Res Function(_$SpotubeSimpleAlbumObjectImpl) then) =
|
||||||
|
__$$SpotubeSimpleAlbumObjectImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeSimpleArtistObject> artists,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
SpotubeAlbumType albumType,
|
||||||
|
String? releaseDate});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$SpotubeSimpleAlbumObjectImplCopyWithImpl<$Res>
|
||||||
|
extends _$SpotubeSimpleAlbumObjectCopyWithImpl<$Res,
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl>
|
||||||
|
implements _$$SpotubeSimpleAlbumObjectImplCopyWith<$Res> {
|
||||||
|
__$$SpotubeSimpleAlbumObjectImplCopyWithImpl(
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl _value,
|
||||||
|
$Res Function(_$SpotubeSimpleAlbumObjectImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? albumType = null,
|
||||||
|
Object? releaseDate = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeSimpleAlbumObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
artists: null == artists
|
||||||
|
? _value._artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleArtistObject>,
|
||||||
|
images: null == images
|
||||||
|
? _value._images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
albumType: null == albumType
|
||||||
|
? _value.albumType
|
||||||
|
: albumType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeAlbumType,
|
||||||
|
releaseDate: freezed == releaseDate
|
||||||
|
? _value.releaseDate
|
||||||
|
: releaseDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeSimpleAlbumObjectImpl implements _SpotubeSimpleAlbumObject {
|
||||||
|
const _$SpotubeSimpleAlbumObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.externalUri,
|
||||||
|
required final List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required this.albumType,
|
||||||
|
this.releaseDate})
|
||||||
|
: _artists = artists,
|
||||||
|
_images = images;
|
||||||
|
|
||||||
|
factory _$SpotubeSimpleAlbumObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeSimpleAlbumObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
final List<SpotubeSimpleArtistObject> _artists;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleArtistObject> get artists {
|
||||||
|
if (_artists is EqualUnmodifiableListView) return _artists;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_artists);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SpotubeImageObject> _images;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images {
|
||||||
|
if (_images is EqualUnmodifiableListView) return _images;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final SpotubeAlbumType albumType;
|
||||||
|
@override
|
||||||
|
final String? releaseDate;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeSimpleAlbumObject(typeName: $typeName, id: $id, name: $name, externalUri: $externalUri, artists: $artists, images: $images, albumType: $albumType, releaseDate: $releaseDate)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeSimpleAlbumObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri) &&
|
||||||
|
const DeepCollectionEquality().equals(other._artists, _artists) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images) &&
|
||||||
|
(identical(other.albumType, albumType) ||
|
||||||
|
other.albumType == albumType) &&
|
||||||
|
(identical(other.releaseDate, releaseDate) ||
|
||||||
|
other.releaseDate == releaseDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
typeName,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
externalUri,
|
||||||
|
const DeepCollectionEquality().hash(_artists),
|
||||||
|
const DeepCollectionEquality().hash(_images),
|
||||||
|
albumType,
|
||||||
|
releaseDate);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$SpotubeSimpleAlbumObjectImplCopyWith<_$SpotubeSimpleAlbumObjectImpl>
|
||||||
|
get copyWith => __$$SpotubeSimpleAlbumObjectImplCopyWithImpl<
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeSimpleAlbumObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeSimpleAlbumObject implements SpotubeSimpleAlbumObject {
|
||||||
|
const factory _SpotubeSimpleAlbumObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final String externalUri,
|
||||||
|
required final List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required final SpotubeAlbumType albumType,
|
||||||
|
final String? releaseDate}) = _$SpotubeSimpleAlbumObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeSimpleAlbumObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleArtistObject> get artists;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images;
|
||||||
|
@override
|
||||||
|
SpotubeAlbumType get albumType;
|
||||||
|
@override
|
||||||
|
String? get releaseDate;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleAlbumObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$SpotubeSimpleAlbumObjectImplCopyWith<_$SpotubeSimpleAlbumObjectImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
83
lib/src/rust/api/plugin/models/album.g.dart
Normal file
83
lib/src/rust/api/plugin/models/album.g.dart
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'album.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeFullAlbumObjectImpl _$$SpotubeFullAlbumObjectImplFromJson(Map json) =>
|
||||||
|
_$SpotubeFullAlbumObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
artists: (json['artists'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeSimpleArtistObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
images: (json['images'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeImageObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
releaseDate: json['releaseDate'] as String,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
totalTracks: (json['totalTracks'] as num).toInt(),
|
||||||
|
albumType: $enumDecode(_$SpotubeAlbumTypeEnumMap, json['albumType']),
|
||||||
|
recordLabel: json['recordLabel'] as String?,
|
||||||
|
genres:
|
||||||
|
(json['genres'] as List<dynamic>?)?.map((e) => e as String).toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeFullAlbumObjectImplToJson(
|
||||||
|
_$SpotubeFullAlbumObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'artists': instance.artists.map((e) => e.toJson()).toList(),
|
||||||
|
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||||
|
'releaseDate': instance.releaseDate,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
'totalTracks': instance.totalTracks,
|
||||||
|
'albumType': _$SpotubeAlbumTypeEnumMap[instance.albumType]!,
|
||||||
|
'recordLabel': instance.recordLabel,
|
||||||
|
'genres': instance.genres,
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$SpotubeAlbumTypeEnumMap = {
|
||||||
|
SpotubeAlbumType.album: 'album',
|
||||||
|
SpotubeAlbumType.single: 'single',
|
||||||
|
SpotubeAlbumType.compilation: 'compilation',
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl _$$SpotubeSimpleAlbumObjectImplFromJson(
|
||||||
|
Map json) =>
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
artists: (json['artists'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeSimpleArtistObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
images: (json['images'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeImageObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
albumType: $enumDecode(_$SpotubeAlbumTypeEnumMap, json['albumType']),
|
||||||
|
releaseDate: json['releaseDate'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeSimpleAlbumObjectImplToJson(
|
||||||
|
_$SpotubeSimpleAlbumObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
'artists': instance.artists.map((e) => e.toJson()).toList(),
|
||||||
|
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||||
|
'albumType': _$SpotubeAlbumTypeEnumMap[instance.albumType]!,
|
||||||
|
'releaseDate': instance.releaseDate,
|
||||||
|
};
|
||||||
43
lib/src/rust/api/plugin/models/artist.dart
Normal file
43
lib/src/rust/api/plugin/models/artist.dart
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
part 'artist.freezed.dart';
|
||||||
|
part 'artist.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeFullArtistObject with _$SpotubeFullArtistObject {
|
||||||
|
const factory SpotubeFullArtistObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String externalUri,
|
||||||
|
required List<SpotubeImageObject> images,
|
||||||
|
List<String>? genres,
|
||||||
|
int? followers,
|
||||||
|
}) = _SpotubeFullArtistObject;
|
||||||
|
|
||||||
|
factory SpotubeFullArtistObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeFullArtistObjectFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeSimpleArtistObject with _$SpotubeSimpleArtistObject {
|
||||||
|
const factory SpotubeSimpleArtistObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String externalUri,
|
||||||
|
List<SpotubeImageObject>? images,
|
||||||
|
}) = _SpotubeSimpleArtistObject;
|
||||||
|
|
||||||
|
factory SpotubeSimpleArtistObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeSimpleArtistObjectFromJson(json);
|
||||||
|
}
|
||||||
572
lib/src/rust/api/plugin/models/artist.freezed.dart
Normal file
572
lib/src/rust/api/plugin/models/artist.freezed.dart
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
// 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 'artist.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(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');
|
||||||
|
|
||||||
|
SpotubeFullArtistObject _$SpotubeFullArtistObjectFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return _SpotubeFullArtistObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeFullArtistObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject> get images => throw _privateConstructorUsedError;
|
||||||
|
List<String>? get genres => throw _privateConstructorUsedError;
|
||||||
|
int? get followers => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeFullArtistObject to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$SpotubeFullArtistObjectCopyWith<SpotubeFullArtistObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeFullArtistObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeFullArtistObjectCopyWith(SpotubeFullArtistObject value,
|
||||||
|
$Res Function(SpotubeFullArtistObject) then) =
|
||||||
|
_$SpotubeFullArtistObjectCopyWithImpl<$Res, SpotubeFullArtistObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
List<String>? genres,
|
||||||
|
int? followers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SpotubeFullArtistObjectCopyWithImpl<$Res,
|
||||||
|
$Val extends SpotubeFullArtistObject>
|
||||||
|
implements $SpotubeFullArtistObjectCopyWith<$Res> {
|
||||||
|
_$SpotubeFullArtistObjectCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? genres = freezed,
|
||||||
|
Object? followers = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
images: null == images
|
||||||
|
? _value.images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
genres: freezed == genres
|
||||||
|
? _value.genres
|
||||||
|
: genres // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>?,
|
||||||
|
followers: freezed == followers
|
||||||
|
? _value.followers
|
||||||
|
: followers // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$SpotubeFullArtistObjectImplCopyWith<$Res>
|
||||||
|
implements $SpotubeFullArtistObjectCopyWith<$Res> {
|
||||||
|
factory _$$SpotubeFullArtistObjectImplCopyWith(
|
||||||
|
_$SpotubeFullArtistObjectImpl value,
|
||||||
|
$Res Function(_$SpotubeFullArtistObjectImpl) then) =
|
||||||
|
__$$SpotubeFullArtistObjectImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
List<String>? genres,
|
||||||
|
int? followers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$SpotubeFullArtistObjectImplCopyWithImpl<$Res>
|
||||||
|
extends _$SpotubeFullArtistObjectCopyWithImpl<$Res,
|
||||||
|
_$SpotubeFullArtistObjectImpl>
|
||||||
|
implements _$$SpotubeFullArtistObjectImplCopyWith<$Res> {
|
||||||
|
__$$SpotubeFullArtistObjectImplCopyWithImpl(
|
||||||
|
_$SpotubeFullArtistObjectImpl _value,
|
||||||
|
$Res Function(_$SpotubeFullArtistObjectImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? genres = freezed,
|
||||||
|
Object? followers = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeFullArtistObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
images: null == images
|
||||||
|
? _value._images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
genres: freezed == genres
|
||||||
|
? _value._genres
|
||||||
|
: genres // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>?,
|
||||||
|
followers: freezed == followers
|
||||||
|
? _value.followers
|
||||||
|
: followers // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeFullArtistObjectImpl implements _SpotubeFullArtistObject {
|
||||||
|
const _$SpotubeFullArtistObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.externalUri,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
final List<String>? genres,
|
||||||
|
this.followers})
|
||||||
|
: _images = images,
|
||||||
|
_genres = genres;
|
||||||
|
|
||||||
|
factory _$SpotubeFullArtistObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeFullArtistObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
final List<SpotubeImageObject> _images;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images {
|
||||||
|
if (_images is EqualUnmodifiableListView) return _images;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String>? _genres;
|
||||||
|
@override
|
||||||
|
List<String>? get genres {
|
||||||
|
final value = _genres;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_genres is EqualUnmodifiableListView) return _genres;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final int? followers;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeFullArtistObject(typeName: $typeName, id: $id, name: $name, externalUri: $externalUri, images: $images, genres: $genres, followers: $followers)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeFullArtistObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images) &&
|
||||||
|
const DeepCollectionEquality().equals(other._genres, _genres) &&
|
||||||
|
(identical(other.followers, followers) ||
|
||||||
|
other.followers == followers));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
typeName,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
externalUri,
|
||||||
|
const DeepCollectionEquality().hash(_images),
|
||||||
|
const DeepCollectionEquality().hash(_genres),
|
||||||
|
followers);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$SpotubeFullArtistObjectImplCopyWith<_$SpotubeFullArtistObjectImpl>
|
||||||
|
get copyWith => __$$SpotubeFullArtistObjectImplCopyWithImpl<
|
||||||
|
_$SpotubeFullArtistObjectImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeFullArtistObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeFullArtistObject implements SpotubeFullArtistObject {
|
||||||
|
const factory _SpotubeFullArtistObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final String externalUri,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
final List<String>? genres,
|
||||||
|
final int? followers}) = _$SpotubeFullArtistObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeFullArtistObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeFullArtistObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images;
|
||||||
|
@override
|
||||||
|
List<String>? get genres;
|
||||||
|
@override
|
||||||
|
int? get followers;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$SpotubeFullArtistObjectImplCopyWith<_$SpotubeFullArtistObjectImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpotubeSimpleArtistObject _$SpotubeSimpleArtistObjectFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return _SpotubeSimpleArtistObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeSimpleArtistObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject>? get images => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeSimpleArtistObject to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$SpotubeSimpleArtistObjectCopyWith<SpotubeSimpleArtistObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeSimpleArtistObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeSimpleArtistObjectCopyWith(SpotubeSimpleArtistObject value,
|
||||||
|
$Res Function(SpotubeSimpleArtistObject) then) =
|
||||||
|
_$SpotubeSimpleArtistObjectCopyWithImpl<$Res, SpotubeSimpleArtistObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeImageObject>? images});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SpotubeSimpleArtistObjectCopyWithImpl<$Res,
|
||||||
|
$Val extends SpotubeSimpleArtistObject>
|
||||||
|
implements $SpotubeSimpleArtistObjectCopyWith<$Res> {
|
||||||
|
_$SpotubeSimpleArtistObjectCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? images = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
images: freezed == images
|
||||||
|
? _value.images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>?,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$SpotubeSimpleArtistObjectImplCopyWith<$Res>
|
||||||
|
implements $SpotubeSimpleArtistObjectCopyWith<$Res> {
|
||||||
|
factory _$$SpotubeSimpleArtistObjectImplCopyWith(
|
||||||
|
_$SpotubeSimpleArtistObjectImpl value,
|
||||||
|
$Res Function(_$SpotubeSimpleArtistObjectImpl) then) =
|
||||||
|
__$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeImageObject>? images});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>
|
||||||
|
extends _$SpotubeSimpleArtistObjectCopyWithImpl<$Res,
|
||||||
|
_$SpotubeSimpleArtistObjectImpl>
|
||||||
|
implements _$$SpotubeSimpleArtistObjectImplCopyWith<$Res> {
|
||||||
|
__$$SpotubeSimpleArtistObjectImplCopyWithImpl(
|
||||||
|
_$SpotubeSimpleArtistObjectImpl _value,
|
||||||
|
$Res Function(_$SpotubeSimpleArtistObjectImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? images = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeSimpleArtistObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
images: freezed == images
|
||||||
|
? _value._images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
||||||
|
const _$SpotubeSimpleArtistObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.externalUri,
|
||||||
|
final List<SpotubeImageObject>? images})
|
||||||
|
: _images = images;
|
||||||
|
|
||||||
|
factory _$SpotubeSimpleArtistObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeSimpleArtistObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
final List<SpotubeImageObject>? _images;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject>? get images {
|
||||||
|
final value = _images;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_images is EqualUnmodifiableListView) return _images;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeSimpleArtistObject(typeName: $typeName, id: $id, name: $name, externalUri: $externalUri, images: $images)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeSimpleArtistObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, typeName, id, name, externalUri,
|
||||||
|
const DeepCollectionEquality().hash(_images));
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$SpotubeSimpleArtistObjectImplCopyWith<_$SpotubeSimpleArtistObjectImpl>
|
||||||
|
get copyWith => __$$SpotubeSimpleArtistObjectImplCopyWithImpl<
|
||||||
|
_$SpotubeSimpleArtistObjectImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeSimpleArtistObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeSimpleArtistObject implements SpotubeSimpleArtistObject {
|
||||||
|
const factory _SpotubeSimpleArtistObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final String externalUri,
|
||||||
|
final List<SpotubeImageObject>? images}) =
|
||||||
|
_$SpotubeSimpleArtistObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeSimpleArtistObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeSimpleArtistObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject>? get images;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimpleArtistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$SpotubeSimpleArtistObjectImplCopyWith<_$SpotubeSimpleArtistObjectImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
58
lib/src/rust/api/plugin/models/artist.g.dart
Normal file
58
lib/src/rust/api/plugin/models/artist.g.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'artist.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeFullArtistObjectImpl _$$SpotubeFullArtistObjectImplFromJson(
|
||||||
|
Map json) =>
|
||||||
|
_$SpotubeFullArtistObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
images: (json['images'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeImageObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
genres:
|
||||||
|
(json['genres'] as List<dynamic>?)?.map((e) => e as String).toList(),
|
||||||
|
followers: (json['followers'] as num?)?.toInt(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeFullArtistObjectImplToJson(
|
||||||
|
_$SpotubeFullArtistObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||||
|
'genres': instance.genres,
|
||||||
|
'followers': instance.followers,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeSimpleArtistObjectImpl _$$SpotubeSimpleArtistObjectImplFromJson(
|
||||||
|
Map json) =>
|
||||||
|
_$SpotubeSimpleArtistObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
images: (json['images'] as List<dynamic>?)
|
||||||
|
?.map((e) =>
|
||||||
|
SpotubeImageObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeSimpleArtistObjectImplToJson(
|
||||||
|
_$SpotubeSimpleArtistObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
'images': instance.images?.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
114
lib/src/rust/api/plugin/models/audio_source.dart
Normal file
114
lib/src/rust/api/plugin/models/audio_source.dart
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
part 'audio_source.freezed.dart';
|
||||||
|
part 'audio_source.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeAudioLosslessContainerQuality
|
||||||
|
with _$SpotubeAudioLosslessContainerQuality {
|
||||||
|
const SpotubeAudioLosslessContainerQuality._();
|
||||||
|
const factory SpotubeAudioLosslessContainerQuality({
|
||||||
|
required int bitDepth,
|
||||||
|
required int sampleRate,
|
||||||
|
}) = _SpotubeAudioLosslessContainerQuality;
|
||||||
|
String toStringFmt() => RustLib.instance.api
|
||||||
|
.crateApiPluginModelsAudioSourceSpotubeAudioLosslessContainerQualityToStringFmt(
|
||||||
|
that: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
factory SpotubeAudioLosslessContainerQuality.fromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeAudioLosslessContainerQualityFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeAudioLossyContainerQuality
|
||||||
|
with _$SpotubeAudioLossyContainerQuality {
|
||||||
|
const SpotubeAudioLossyContainerQuality._();
|
||||||
|
const factory SpotubeAudioLossyContainerQuality({
|
||||||
|
required int bitrate,
|
||||||
|
}) = _SpotubeAudioLossyContainerQuality;
|
||||||
|
Future<String> toStringFmt() => RustLib.instance.api
|
||||||
|
.crateApiPluginModelsAudioSourceSpotubeAudioLossyContainerQualityToStringFmt(
|
||||||
|
that: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
factory SpotubeAudioLossyContainerQuality.fromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeAudioLossyContainerQualityFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeAudioSourceContainerPreset
|
||||||
|
with _$SpotubeAudioSourceContainerPreset {
|
||||||
|
const SpotubeAudioSourceContainerPreset._();
|
||||||
|
|
||||||
|
const factory SpotubeAudioSourceContainerPreset.lossy({
|
||||||
|
required SpotubeMediaCompressionType compressionType,
|
||||||
|
required String name,
|
||||||
|
required List<SpotubeAudioLossyContainerQuality> qualities,
|
||||||
|
}) = SpotubeAudioSourceContainerPreset_Lossy;
|
||||||
|
const factory SpotubeAudioSourceContainerPreset.lossless({
|
||||||
|
required SpotubeMediaCompressionType compressionType,
|
||||||
|
required String name,
|
||||||
|
required List<SpotubeAudioLosslessContainerQuality> qualities,
|
||||||
|
}) = SpotubeAudioSourceContainerPreset_Lossless;
|
||||||
|
|
||||||
|
factory SpotubeAudioSourceContainerPreset.fromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeAudioSourceContainerPresetFromJson(json);
|
||||||
|
|
||||||
|
String fileExtension() => RustLib.instance.api
|
||||||
|
.crateApiPluginModelsAudioSourceSpotubeAudioSourceContainerPresetFileExtension(
|
||||||
|
that: this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeAudioSourceMatchObject
|
||||||
|
with _$SpotubeAudioSourceMatchObject {
|
||||||
|
const factory SpotubeAudioSourceMatchObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String title,
|
||||||
|
required List<String> artists,
|
||||||
|
required BigInt duration,
|
||||||
|
String? thumbnail,
|
||||||
|
required String externalUri,
|
||||||
|
}) = _SpotubeAudioSourceMatchObject;
|
||||||
|
|
||||||
|
factory SpotubeAudioSourceMatchObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeAudioSourceMatchObjectFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeAudioSourceStreamObject
|
||||||
|
with _$SpotubeAudioSourceStreamObject {
|
||||||
|
const factory SpotubeAudioSourceStreamObject({
|
||||||
|
required String typeName,
|
||||||
|
required String url,
|
||||||
|
required String container,
|
||||||
|
required SpotubeMediaCompressionType compressionType,
|
||||||
|
String? codec,
|
||||||
|
double? bitrate,
|
||||||
|
int? bitDepth,
|
||||||
|
double? sampleRate,
|
||||||
|
}) = _SpotubeAudioSourceStreamObject;
|
||||||
|
|
||||||
|
factory SpotubeAudioSourceStreamObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeAudioSourceStreamObjectFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SpotubeMediaCompressionType {
|
||||||
|
lossy,
|
||||||
|
lossless,
|
||||||
|
;
|
||||||
|
}
|
||||||
1581
lib/src/rust/api/plugin/models/audio_source.freezed.dart
Normal file
1581
lib/src/rust/api/plugin/models/audio_source.freezed.dart
Normal file
File diff suppressed because it is too large
Load Diff
138
lib/src/rust/api/plugin/models/audio_source.g.dart
Normal file
138
lib/src/rust/api/plugin/models/audio_source.g.dart
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'audio_source.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeAudioLosslessContainerQualityImpl
|
||||||
|
_$$SpotubeAudioLosslessContainerQualityImplFromJson(Map json) =>
|
||||||
|
_$SpotubeAudioLosslessContainerQualityImpl(
|
||||||
|
bitDepth: (json['bitDepth'] as num).toInt(),
|
||||||
|
sampleRate: (json['sampleRate'] as num).toInt(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeAudioLosslessContainerQualityImplToJson(
|
||||||
|
_$SpotubeAudioLosslessContainerQualityImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'bitDepth': instance.bitDepth,
|
||||||
|
'sampleRate': instance.sampleRate,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeAudioLossyContainerQualityImpl
|
||||||
|
_$$SpotubeAudioLossyContainerQualityImplFromJson(Map json) =>
|
||||||
|
_$SpotubeAudioLossyContainerQualityImpl(
|
||||||
|
bitrate: (json['bitrate'] as num).toInt(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeAudioLossyContainerQualityImplToJson(
|
||||||
|
_$SpotubeAudioLossyContainerQualityImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'bitrate': instance.bitrate,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeAudioSourceContainerPreset_LossyImpl
|
||||||
|
_$$SpotubeAudioSourceContainerPreset_LossyImplFromJson(Map json) =>
|
||||||
|
_$SpotubeAudioSourceContainerPreset_LossyImpl(
|
||||||
|
compressionType: $enumDecode(
|
||||||
|
_$SpotubeMediaCompressionTypeEnumMap, json['compressionType']),
|
||||||
|
name: json['name'] as String,
|
||||||
|
qualities: (json['qualities'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeAudioLossyContainerQuality.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
$type: json['runtimeType'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeAudioSourceContainerPreset_LossyImplToJson(
|
||||||
|
_$SpotubeAudioSourceContainerPreset_LossyImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'compressionType':
|
||||||
|
_$SpotubeMediaCompressionTypeEnumMap[instance.compressionType]!,
|
||||||
|
'name': instance.name,
|
||||||
|
'qualities': instance.qualities.map((e) => e.toJson()).toList(),
|
||||||
|
'runtimeType': instance.$type,
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$SpotubeMediaCompressionTypeEnumMap = {
|
||||||
|
SpotubeMediaCompressionType.lossy: 'lossy',
|
||||||
|
SpotubeMediaCompressionType.lossless: 'lossless',
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeAudioSourceContainerPreset_LosslessImpl
|
||||||
|
_$$SpotubeAudioSourceContainerPreset_LosslessImplFromJson(Map json) =>
|
||||||
|
_$SpotubeAudioSourceContainerPreset_LosslessImpl(
|
||||||
|
compressionType: $enumDecode(
|
||||||
|
_$SpotubeMediaCompressionTypeEnumMap, json['compressionType']),
|
||||||
|
name: json['name'] as String,
|
||||||
|
qualities: (json['qualities'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeAudioLosslessContainerQuality.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
$type: json['runtimeType'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeAudioSourceContainerPreset_LosslessImplToJson(
|
||||||
|
_$SpotubeAudioSourceContainerPreset_LosslessImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'compressionType':
|
||||||
|
_$SpotubeMediaCompressionTypeEnumMap[instance.compressionType]!,
|
||||||
|
'name': instance.name,
|
||||||
|
'qualities': instance.qualities.map((e) => e.toJson()).toList(),
|
||||||
|
'runtimeType': instance.$type,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeAudioSourceMatchObjectImpl
|
||||||
|
_$$SpotubeAudioSourceMatchObjectImplFromJson(Map json) =>
|
||||||
|
_$SpotubeAudioSourceMatchObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
title: json['title'] as String,
|
||||||
|
artists: (json['artists'] as List<dynamic>)
|
||||||
|
.map((e) => e as String)
|
||||||
|
.toList(),
|
||||||
|
duration: BigInt.parse(json['duration'] as String),
|
||||||
|
thumbnail: json['thumbnail'] as String?,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeAudioSourceMatchObjectImplToJson(
|
||||||
|
_$SpotubeAudioSourceMatchObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'title': instance.title,
|
||||||
|
'artists': instance.artists,
|
||||||
|
'duration': instance.duration.toString(),
|
||||||
|
'thumbnail': instance.thumbnail,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeAudioSourceStreamObjectImpl
|
||||||
|
_$$SpotubeAudioSourceStreamObjectImplFromJson(Map json) =>
|
||||||
|
_$SpotubeAudioSourceStreamObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
url: json['url'] as String,
|
||||||
|
container: json['container'] as String,
|
||||||
|
compressionType: $enumDecode(
|
||||||
|
_$SpotubeMediaCompressionTypeEnumMap, json['compressionType']),
|
||||||
|
codec: json['codec'] as String?,
|
||||||
|
bitrate: (json['bitrate'] as num?)?.toDouble(),
|
||||||
|
bitDepth: (json['bitDepth'] as num?)?.toInt(),
|
||||||
|
sampleRate: (json['sampleRate'] as num?)?.toDouble(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeAudioSourceStreamObjectImplToJson(
|
||||||
|
_$SpotubeAudioSourceStreamObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'url': instance.url,
|
||||||
|
'container': instance.container,
|
||||||
|
'compressionType':
|
||||||
|
_$SpotubeMediaCompressionTypeEnumMap[instance.compressionType]!,
|
||||||
|
'codec': instance.codec,
|
||||||
|
'bitrate': instance.bitrate,
|
||||||
|
'bitDepth': instance.bitDepth,
|
||||||
|
'sampleRate': instance.sampleRate,
|
||||||
|
};
|
||||||
57
lib/src/rust/api/plugin/models/browse.dart
Normal file
57
lib/src/rust/api/plugin/models/browse.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'album.dart';
|
||||||
|
import 'artist.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
import 'playlist.dart';
|
||||||
|
import 'track.dart';
|
||||||
|
import 'user.dart';
|
||||||
|
part 'browse.freezed.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeBrowseSectionObject with _$SpotubeBrowseSectionObject {
|
||||||
|
const factory SpotubeBrowseSectionObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String title,
|
||||||
|
required String externalUri,
|
||||||
|
required bool browseMore,
|
||||||
|
required List<SpotubeBrowseSectionResponseObjectItem> items,
|
||||||
|
}) = _SpotubeBrowseSectionObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeBrowseSectionResponseObjectItem
|
||||||
|
with _$SpotubeBrowseSectionResponseObjectItem {
|
||||||
|
const SpotubeBrowseSectionResponseObjectItem._();
|
||||||
|
|
||||||
|
const factory SpotubeBrowseSectionResponseObjectItem.track(
|
||||||
|
SpotubeTrackObject field0,
|
||||||
|
) = SpotubeBrowseSectionResponseObjectItem_Track;
|
||||||
|
const factory SpotubeBrowseSectionResponseObjectItem.playlistFull(
|
||||||
|
SpotubeFullPlaylistObject field0,
|
||||||
|
) = SpotubeBrowseSectionResponseObjectItem_PlaylistFull;
|
||||||
|
const factory SpotubeBrowseSectionResponseObjectItem.playlistSimple(
|
||||||
|
SpotubeSimplePlaylistObject field0,
|
||||||
|
) = SpotubeBrowseSectionResponseObjectItem_PlaylistSimple;
|
||||||
|
const factory SpotubeBrowseSectionResponseObjectItem.albumSimple(
|
||||||
|
SpotubeSimpleAlbumObject field0,
|
||||||
|
) = SpotubeBrowseSectionResponseObjectItem_AlbumSimple;
|
||||||
|
const factory SpotubeBrowseSectionResponseObjectItem.albumFull(
|
||||||
|
SpotubeFullAlbumObject field0,
|
||||||
|
) = SpotubeBrowseSectionResponseObjectItem_AlbumFull;
|
||||||
|
const factory SpotubeBrowseSectionResponseObjectItem.artistFull(
|
||||||
|
SpotubeFullArtistObject field0,
|
||||||
|
) = SpotubeBrowseSectionResponseObjectItem_ArtistFull;
|
||||||
|
const factory SpotubeBrowseSectionResponseObjectItem.artistSimple(
|
||||||
|
SpotubeSimpleArtistObject field0,
|
||||||
|
) = SpotubeBrowseSectionResponseObjectItem_ArtistSimple;
|
||||||
|
}
|
||||||
2047
lib/src/rust/api/plugin/models/browse.freezed.dart
Normal file
2047
lib/src/rust/api/plugin/models/browse.freezed.dart
Normal file
File diff suppressed because it is too large
Load Diff
190
lib/src/rust/api/plugin/models/core.dart
Normal file
190
lib/src/rust/api/plugin/models/core.dart
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `cmp`, `cmp`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `partial_cmp`, `partial_cmp`
|
||||||
|
|
||||||
|
enum PluginAbility {
|
||||||
|
authentication,
|
||||||
|
scrobbling,
|
||||||
|
metadata,
|
||||||
|
audioSource,
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PluginApi {
|
||||||
|
webview,
|
||||||
|
localstorage,
|
||||||
|
timezone,
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginConfiguration {
|
||||||
|
final String name;
|
||||||
|
final String description;
|
||||||
|
final String version;
|
||||||
|
final String author;
|
||||||
|
final String entryPoint;
|
||||||
|
final String pluginApiVersion;
|
||||||
|
final List<PluginApi> apis;
|
||||||
|
final List<PluginAbility> abilities;
|
||||||
|
final String? repository;
|
||||||
|
|
||||||
|
const PluginConfiguration({
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
required this.version,
|
||||||
|
required this.author,
|
||||||
|
required this.entryPoint,
|
||||||
|
required this.pluginApiVersion,
|
||||||
|
required this.apis,
|
||||||
|
required this.abilities,
|
||||||
|
this.repository,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<String> slug() =>
|
||||||
|
RustLib.instance.api.crateApiPluginModelsCorePluginConfigurationSlug(
|
||||||
|
that: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
name.hashCode ^
|
||||||
|
description.hashCode ^
|
||||||
|
version.hashCode ^
|
||||||
|
author.hashCode ^
|
||||||
|
entryPoint.hashCode ^
|
||||||
|
pluginApiVersion.hashCode ^
|
||||||
|
apis.hashCode ^
|
||||||
|
abilities.hashCode ^
|
||||||
|
repository.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginConfiguration &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
name == other.name &&
|
||||||
|
description == other.description &&
|
||||||
|
version == other.version &&
|
||||||
|
author == other.author &&
|
||||||
|
entryPoint == other.entryPoint &&
|
||||||
|
pluginApiVersion == other.pluginApiVersion &&
|
||||||
|
apis == other.apis &&
|
||||||
|
abilities == other.abilities &&
|
||||||
|
repository == other.repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginUpdateAvailable {
|
||||||
|
final String downloadUrl;
|
||||||
|
final String version;
|
||||||
|
final String? changelog;
|
||||||
|
|
||||||
|
const PluginUpdateAvailable({
|
||||||
|
required this.downloadUrl,
|
||||||
|
required this.version,
|
||||||
|
this.changelog,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
downloadUrl.hashCode ^ version.hashCode ^ changelog.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginUpdateAvailable &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
downloadUrl == other.downloadUrl &&
|
||||||
|
version == other.version &&
|
||||||
|
changelog == other.changelog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScrobbleAlbum {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
const ScrobbleAlbum({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode ^ name.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is ScrobbleAlbum &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
id == other.id &&
|
||||||
|
name == other.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScrobbleArtist {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
const ScrobbleArtist({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode ^ name.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is ScrobbleArtist &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
id == other.id &&
|
||||||
|
name == other.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScrobbleDetails {
|
||||||
|
final String id;
|
||||||
|
final String title;
|
||||||
|
final List<ScrobbleArtist> artists;
|
||||||
|
final ScrobbleAlbum album;
|
||||||
|
final PlatformInt64? timestamp;
|
||||||
|
final int? durationMs;
|
||||||
|
final String? isrc;
|
||||||
|
|
||||||
|
const ScrobbleDetails({
|
||||||
|
required this.id,
|
||||||
|
required this.title,
|
||||||
|
required this.artists,
|
||||||
|
required this.album,
|
||||||
|
this.timestamp,
|
||||||
|
this.durationMs,
|
||||||
|
this.isrc,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
id.hashCode ^
|
||||||
|
title.hashCode ^
|
||||||
|
artists.hashCode ^
|
||||||
|
album.hashCode ^
|
||||||
|
timestamp.hashCode ^
|
||||||
|
durationMs.hashCode ^
|
||||||
|
isrc.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is ScrobbleDetails &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
id == other.id &&
|
||||||
|
title == other.title &&
|
||||||
|
artists == other.artists &&
|
||||||
|
album == other.album &&
|
||||||
|
timestamp == other.timestamp &&
|
||||||
|
durationMs == other.durationMs &&
|
||||||
|
isrc == other.isrc;
|
||||||
|
}
|
||||||
25
lib/src/rust/api/plugin/models/image.dart
Normal file
25
lib/src/rust/api/plugin/models/image.dart
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
part 'image.freezed.dart';
|
||||||
|
part 'image.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeImageObject with _$SpotubeImageObject {
|
||||||
|
const factory SpotubeImageObject({
|
||||||
|
required String typeName,
|
||||||
|
required String url,
|
||||||
|
int? width,
|
||||||
|
int? height,
|
||||||
|
}) = _SpotubeImageObject;
|
||||||
|
|
||||||
|
factory SpotubeImageObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeImageObjectFromJson(json);
|
||||||
|
}
|
||||||
219
lib/src/rust/api/plugin/models/image.freezed.dart
Normal file
219
lib/src/rust/api/plugin/models/image.freezed.dart
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
// 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 'image.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(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');
|
||||||
|
|
||||||
|
SpotubeImageObject _$SpotubeImageObjectFromJson(Map<String, dynamic> json) {
|
||||||
|
return _SpotubeImageObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeImageObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get url => throw _privateConstructorUsedError;
|
||||||
|
int? get width => throw _privateConstructorUsedError;
|
||||||
|
int? get height => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeImageObject to a JSON map.
|
||||||
|
Map<String, dynamic> 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<SpotubeImageObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeImageObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeImageObjectCopyWith(
|
||||||
|
SpotubeImageObject value, $Res Function(SpotubeImageObject) then) =
|
||||||
|
_$SpotubeImageObjectCopyWithImpl<$Res, SpotubeImageObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String typeName, 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? typeName = null,
|
||||||
|
Object? url = null,
|
||||||
|
Object? width = freezed,
|
||||||
|
Object? height = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
url: null == url
|
||||||
|
? _value.url
|
||||||
|
: url // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
width: freezed == width
|
||||||
|
? _value.width
|
||||||
|
: width // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
|
height: freezed == 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 typeName, 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? typeName = null,
|
||||||
|
Object? url = null,
|
||||||
|
Object? width = freezed,
|
||||||
|
Object? height = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeImageObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
url: null == url
|
||||||
|
? _value.url
|
||||||
|
: url // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
width: freezed == width
|
||||||
|
? _value.width
|
||||||
|
: width // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
|
height: freezed == height
|
||||||
|
? _value.height
|
||||||
|
: height // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeImageObjectImpl implements _SpotubeImageObject {
|
||||||
|
const _$SpotubeImageObjectImpl(
|
||||||
|
{required this.typeName, required this.url, this.width, this.height});
|
||||||
|
|
||||||
|
factory _$SpotubeImageObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeImageObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String url;
|
||||||
|
@override
|
||||||
|
final int? width;
|
||||||
|
@override
|
||||||
|
final int? height;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeImageObject(typeName: $typeName, url: $url, width: $width, height: $height)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeImageObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(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, typeName, 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<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeImageObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeImageObject implements SpotubeImageObject {
|
||||||
|
const factory _SpotubeImageObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String url,
|
||||||
|
final int? width,
|
||||||
|
final int? height}) = _$SpotubeImageObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeImageObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeImageObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@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;
|
||||||
|
}
|
||||||
24
lib/src/rust/api/plugin/models/image.g.dart
Normal file
24
lib/src/rust/api/plugin/models/image.g.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'image.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeImageObjectImpl _$$SpotubeImageObjectImplFromJson(Map json) =>
|
||||||
|
_$SpotubeImageObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
url: json['url'] as String,
|
||||||
|
width: (json['width'] as num?)?.toInt(),
|
||||||
|
height: (json['height'] as num?)?.toInt(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeImageObjectImplToJson(
|
||||||
|
_$SpotubeImageObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'url': instance.url,
|
||||||
|
'width': instance.width,
|
||||||
|
'height': instance.height,
|
||||||
|
};
|
||||||
61
lib/src/rust/api/plugin/models/pagination.dart
Normal file
61
lib/src/rust/api/plugin/models/pagination.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'album.dart';
|
||||||
|
import 'artist.dart';
|
||||||
|
import 'browse.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
import 'playlist.dart';
|
||||||
|
import 'track.dart';
|
||||||
|
import 'user.dart';
|
||||||
|
part 'pagination.freezed.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubePaginationResponseObject
|
||||||
|
with _$SpotubePaginationResponseObject {
|
||||||
|
const factory SpotubePaginationResponseObject({
|
||||||
|
required int limit,
|
||||||
|
int? nextOffset,
|
||||||
|
required int total,
|
||||||
|
required bool hasMore,
|
||||||
|
required List<SpotubePaginationResponseObjectItem> items,
|
||||||
|
}) = _SpotubePaginationResponseObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubePaginationResponseObjectItem
|
||||||
|
with _$SpotubePaginationResponseObjectItem {
|
||||||
|
const SpotubePaginationResponseObjectItem._();
|
||||||
|
|
||||||
|
const factory SpotubePaginationResponseObjectItem.track(
|
||||||
|
SpotubeTrackObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_Track;
|
||||||
|
const factory SpotubePaginationResponseObjectItem.playlistFull(
|
||||||
|
SpotubeFullPlaylistObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_PlaylistFull;
|
||||||
|
const factory SpotubePaginationResponseObjectItem.playlistSimple(
|
||||||
|
SpotubeSimplePlaylistObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_PlaylistSimple;
|
||||||
|
const factory SpotubePaginationResponseObjectItem.albumSimple(
|
||||||
|
SpotubeSimpleAlbumObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_AlbumSimple;
|
||||||
|
const factory SpotubePaginationResponseObjectItem.albumFull(
|
||||||
|
SpotubeFullAlbumObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_AlbumFull;
|
||||||
|
const factory SpotubePaginationResponseObjectItem.artistFull(
|
||||||
|
SpotubeFullArtistObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_ArtistFull;
|
||||||
|
const factory SpotubePaginationResponseObjectItem.artistSimple(
|
||||||
|
SpotubeSimpleArtistObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_ArtistSimple;
|
||||||
|
const factory SpotubePaginationResponseObjectItem.browseSection(
|
||||||
|
SpotubeBrowseSectionObject field0,
|
||||||
|
) = SpotubePaginationResponseObjectItem_BrowseSection;
|
||||||
|
}
|
||||||
2279
lib/src/rust/api/plugin/models/pagination.freezed.dart
Normal file
2279
lib/src/rust/api/plugin/models/pagination.freezed.dart
Normal file
File diff suppressed because it is too large
Load Diff
49
lib/src/rust/api/plugin/models/playlist.dart
Normal file
49
lib/src/rust/api/plugin/models/playlist.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
import 'user.dart';
|
||||||
|
part 'playlist.freezed.dart';
|
||||||
|
part 'playlist.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeFullPlaylistObject with _$SpotubeFullPlaylistObject {
|
||||||
|
const factory SpotubeFullPlaylistObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String description,
|
||||||
|
required String externalUri,
|
||||||
|
required SpotubeUserObject owner,
|
||||||
|
required List<SpotubeImageObject> images,
|
||||||
|
required List<SpotubeUserObject> collaborators,
|
||||||
|
required bool collaborative,
|
||||||
|
required bool public,
|
||||||
|
}) = _SpotubeFullPlaylistObject;
|
||||||
|
|
||||||
|
factory SpotubeFullPlaylistObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeFullPlaylistObjectFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeSimplePlaylistObject with _$SpotubeSimplePlaylistObject {
|
||||||
|
const factory SpotubeSimplePlaylistObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String description,
|
||||||
|
required String externalUri,
|
||||||
|
required SpotubeUserObject owner,
|
||||||
|
required List<SpotubeImageObject> images,
|
||||||
|
}) = _SpotubeSimplePlaylistObject;
|
||||||
|
|
||||||
|
factory SpotubeSimplePlaylistObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeSimplePlaylistObjectFromJson(json);
|
||||||
|
}
|
||||||
710
lib/src/rust/api/plugin/models/playlist.freezed.dart
Normal file
710
lib/src/rust/api/plugin/models/playlist.freezed.dart
Normal file
@ -0,0 +1,710 @@
|
|||||||
|
// 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 'playlist.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(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');
|
||||||
|
|
||||||
|
SpotubeFullPlaylistObject _$SpotubeFullPlaylistObjectFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return _SpotubeFullPlaylistObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeFullPlaylistObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
String get description => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
SpotubeUserObject get owner => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject> get images => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeUserObject> get collaborators =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
bool get collaborative => throw _privateConstructorUsedError;
|
||||||
|
bool get public => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeFullPlaylistObject to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullPlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$SpotubeFullPlaylistObjectCopyWith<SpotubeFullPlaylistObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeFullPlaylistObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeFullPlaylistObjectCopyWith(SpotubeFullPlaylistObject value,
|
||||||
|
$Res Function(SpotubeFullPlaylistObject) then) =
|
||||||
|
_$SpotubeFullPlaylistObjectCopyWithImpl<$Res, SpotubeFullPlaylistObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
String externalUri,
|
||||||
|
SpotubeUserObject owner,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
List<SpotubeUserObject> collaborators,
|
||||||
|
bool collaborative,
|
||||||
|
bool public});
|
||||||
|
|
||||||
|
$SpotubeUserObjectCopyWith<$Res> get owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SpotubeFullPlaylistObjectCopyWithImpl<$Res,
|
||||||
|
$Val extends SpotubeFullPlaylistObject>
|
||||||
|
implements $SpotubeFullPlaylistObjectCopyWith<$Res> {
|
||||||
|
_$SpotubeFullPlaylistObjectCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullPlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? owner = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? collaborators = null,
|
||||||
|
Object? collaborative = null,
|
||||||
|
Object? public = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
owner: null == owner
|
||||||
|
? _value.owner
|
||||||
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeUserObject,
|
||||||
|
images: null == images
|
||||||
|
? _value.images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
collaborators: null == collaborators
|
||||||
|
? _value.collaborators
|
||||||
|
: collaborators // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeUserObject>,
|
||||||
|
collaborative: null == collaborative
|
||||||
|
? _value.collaborative
|
||||||
|
: collaborative // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
public: null == public
|
||||||
|
? _value.public
|
||||||
|
: public // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullPlaylistObject
|
||||||
|
/// 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 _$$SpotubeFullPlaylistObjectImplCopyWith<$Res>
|
||||||
|
implements $SpotubeFullPlaylistObjectCopyWith<$Res> {
|
||||||
|
factory _$$SpotubeFullPlaylistObjectImplCopyWith(
|
||||||
|
_$SpotubeFullPlaylistObjectImpl value,
|
||||||
|
$Res Function(_$SpotubeFullPlaylistObjectImpl) then) =
|
||||||
|
__$$SpotubeFullPlaylistObjectImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
String externalUri,
|
||||||
|
SpotubeUserObject owner,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
List<SpotubeUserObject> collaborators,
|
||||||
|
bool collaborative,
|
||||||
|
bool public});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$SpotubeUserObjectCopyWith<$Res> get owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$SpotubeFullPlaylistObjectImplCopyWithImpl<$Res>
|
||||||
|
extends _$SpotubeFullPlaylistObjectCopyWithImpl<$Res,
|
||||||
|
_$SpotubeFullPlaylistObjectImpl>
|
||||||
|
implements _$$SpotubeFullPlaylistObjectImplCopyWith<$Res> {
|
||||||
|
__$$SpotubeFullPlaylistObjectImplCopyWithImpl(
|
||||||
|
_$SpotubeFullPlaylistObjectImpl _value,
|
||||||
|
$Res Function(_$SpotubeFullPlaylistObjectImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullPlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? owner = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? collaborators = null,
|
||||||
|
Object? collaborative = null,
|
||||||
|
Object? public = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeFullPlaylistObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
owner: null == owner
|
||||||
|
? _value.owner
|
||||||
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeUserObject,
|
||||||
|
images: null == images
|
||||||
|
? _value._images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
collaborators: null == collaborators
|
||||||
|
? _value._collaborators
|
||||||
|
: collaborators // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeUserObject>,
|
||||||
|
collaborative: null == collaborative
|
||||||
|
? _value.collaborative
|
||||||
|
: collaborative // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
public: null == public
|
||||||
|
? _value.public
|
||||||
|
: public // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeFullPlaylistObjectImpl implements _SpotubeFullPlaylistObject {
|
||||||
|
const _$SpotubeFullPlaylistObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
required this.externalUri,
|
||||||
|
required this.owner,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required final List<SpotubeUserObject> collaborators,
|
||||||
|
required this.collaborative,
|
||||||
|
required this.public})
|
||||||
|
: _images = images,
|
||||||
|
_collaborators = collaborators;
|
||||||
|
|
||||||
|
factory _$SpotubeFullPlaylistObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeFullPlaylistObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final String description;
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
@override
|
||||||
|
final SpotubeUserObject owner;
|
||||||
|
final List<SpotubeImageObject> _images;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images {
|
||||||
|
if (_images is EqualUnmodifiableListView) return _images;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SpotubeUserObject> _collaborators;
|
||||||
|
@override
|
||||||
|
List<SpotubeUserObject> get collaborators {
|
||||||
|
if (_collaborators is EqualUnmodifiableListView) return _collaborators;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_collaborators);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool collaborative;
|
||||||
|
@override
|
||||||
|
final bool public;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeFullPlaylistObject(typeName: $typeName, id: $id, name: $name, description: $description, externalUri: $externalUri, owner: $owner, images: $images, collaborators: $collaborators, collaborative: $collaborative, public: $public)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeFullPlaylistObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.description, description) ||
|
||||||
|
other.description == description) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri) &&
|
||||||
|
(identical(other.owner, owner) || other.owner == owner) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other._collaborators, _collaborators) &&
|
||||||
|
(identical(other.collaborative, collaborative) ||
|
||||||
|
other.collaborative == collaborative) &&
|
||||||
|
(identical(other.public, public) || other.public == public));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
typeName,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
externalUri,
|
||||||
|
owner,
|
||||||
|
const DeepCollectionEquality().hash(_images),
|
||||||
|
const DeepCollectionEquality().hash(_collaborators),
|
||||||
|
collaborative,
|
||||||
|
public);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullPlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$SpotubeFullPlaylistObjectImplCopyWith<_$SpotubeFullPlaylistObjectImpl>
|
||||||
|
get copyWith => __$$SpotubeFullPlaylistObjectImplCopyWithImpl<
|
||||||
|
_$SpotubeFullPlaylistObjectImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeFullPlaylistObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeFullPlaylistObject implements SpotubeFullPlaylistObject {
|
||||||
|
const factory _SpotubeFullPlaylistObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final String description,
|
||||||
|
required final String externalUri,
|
||||||
|
required final SpotubeUserObject owner,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required final List<SpotubeUserObject> collaborators,
|
||||||
|
required final bool collaborative,
|
||||||
|
required final bool public}) = _$SpotubeFullPlaylistObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeFullPlaylistObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeFullPlaylistObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
String get description;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
SpotubeUserObject get owner;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images;
|
||||||
|
@override
|
||||||
|
List<SpotubeUserObject> get collaborators;
|
||||||
|
@override
|
||||||
|
bool get collaborative;
|
||||||
|
@override
|
||||||
|
bool get public;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeFullPlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$SpotubeFullPlaylistObjectImplCopyWith<_$SpotubeFullPlaylistObjectImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpotubeSimplePlaylistObject _$SpotubeSimplePlaylistObjectFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return _SpotubeSimplePlaylistObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeSimplePlaylistObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
String get description => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
SpotubeUserObject get owner => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject> get images => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeSimplePlaylistObject to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimplePlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$SpotubeSimplePlaylistObjectCopyWith<SpotubeSimplePlaylistObject>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeSimplePlaylistObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeSimplePlaylistObjectCopyWith(
|
||||||
|
SpotubeSimplePlaylistObject value,
|
||||||
|
$Res Function(SpotubeSimplePlaylistObject) then) =
|
||||||
|
_$SpotubeSimplePlaylistObjectCopyWithImpl<$Res,
|
||||||
|
SpotubeSimplePlaylistObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
String externalUri,
|
||||||
|
SpotubeUserObject owner,
|
||||||
|
List<SpotubeImageObject> images});
|
||||||
|
|
||||||
|
$SpotubeUserObjectCopyWith<$Res> get owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SpotubeSimplePlaylistObjectCopyWithImpl<$Res,
|
||||||
|
$Val extends SpotubeSimplePlaylistObject>
|
||||||
|
implements $SpotubeSimplePlaylistObjectCopyWith<$Res> {
|
||||||
|
_$SpotubeSimplePlaylistObjectCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimplePlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? owner = null,
|
||||||
|
Object? images = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
owner: null == owner
|
||||||
|
? _value.owner
|
||||||
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeUserObject,
|
||||||
|
images: null == images
|
||||||
|
? _value.images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimplePlaylistObject
|
||||||
|
/// 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 _$$SpotubeSimplePlaylistObjectImplCopyWith<$Res>
|
||||||
|
implements $SpotubeSimplePlaylistObjectCopyWith<$Res> {
|
||||||
|
factory _$$SpotubeSimplePlaylistObjectImplCopyWith(
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl value,
|
||||||
|
$Res Function(_$SpotubeSimplePlaylistObjectImpl) then) =
|
||||||
|
__$$SpotubeSimplePlaylistObjectImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
String externalUri,
|
||||||
|
SpotubeUserObject owner,
|
||||||
|
List<SpotubeImageObject> images});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$SpotubeUserObjectCopyWith<$Res> get owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$SpotubeSimplePlaylistObjectImplCopyWithImpl<$Res>
|
||||||
|
extends _$SpotubeSimplePlaylistObjectCopyWithImpl<$Res,
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl>
|
||||||
|
implements _$$SpotubeSimplePlaylistObjectImplCopyWith<$Res> {
|
||||||
|
__$$SpotubeSimplePlaylistObjectImplCopyWithImpl(
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl _value,
|
||||||
|
$Res Function(_$SpotubeSimplePlaylistObjectImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimplePlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? owner = null,
|
||||||
|
Object? images = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeSimplePlaylistObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
owner: null == owner
|
||||||
|
? _value.owner
|
||||||
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeUserObject,
|
||||||
|
images: null == images
|
||||||
|
? _value._images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeSimplePlaylistObjectImpl
|
||||||
|
implements _SpotubeSimplePlaylistObject {
|
||||||
|
const _$SpotubeSimplePlaylistObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
required this.externalUri,
|
||||||
|
required this.owner,
|
||||||
|
required final List<SpotubeImageObject> images})
|
||||||
|
: _images = images;
|
||||||
|
|
||||||
|
factory _$SpotubeSimplePlaylistObjectImpl.fromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeSimplePlaylistObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final String description;
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
@override
|
||||||
|
final SpotubeUserObject owner;
|
||||||
|
final List<SpotubeImageObject> _images;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images {
|
||||||
|
if (_images is EqualUnmodifiableListView) return _images;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeSimplePlaylistObject(typeName: $typeName, id: $id, name: $name, description: $description, externalUri: $externalUri, owner: $owner, images: $images)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeSimplePlaylistObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.description, description) ||
|
||||||
|
other.description == description) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri) &&
|
||||||
|
(identical(other.owner, owner) || other.owner == owner) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, typeName, id, name, description,
|
||||||
|
externalUri, owner, const DeepCollectionEquality().hash(_images));
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimplePlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$SpotubeSimplePlaylistObjectImplCopyWith<_$SpotubeSimplePlaylistObjectImpl>
|
||||||
|
get copyWith => __$$SpotubeSimplePlaylistObjectImplCopyWithImpl<
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeSimplePlaylistObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeSimplePlaylistObject
|
||||||
|
implements SpotubeSimplePlaylistObject {
|
||||||
|
const factory _SpotubeSimplePlaylistObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final String description,
|
||||||
|
required final String externalUri,
|
||||||
|
required final SpotubeUserObject owner,
|
||||||
|
required final List<SpotubeImageObject> images}) =
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeSimplePlaylistObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
String get description;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
SpotubeUserObject get owner;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images;
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeSimplePlaylistObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$SpotubeSimplePlaylistObjectImplCopyWith<_$SpotubeSimplePlaylistObjectImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
72
lib/src/rust/api/plugin/models/playlist.g.dart
Normal file
72
lib/src/rust/api/plugin/models/playlist.g.dart
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'playlist.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeFullPlaylistObjectImpl _$$SpotubeFullPlaylistObjectImplFromJson(
|
||||||
|
Map json) =>
|
||||||
|
_$SpotubeFullPlaylistObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
description: json['description'] as String,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
owner: SpotubeUserObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(json['owner'] as Map)),
|
||||||
|
images: (json['images'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeImageObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
collaborators: (json['collaborators'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeUserObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
collaborative: json['collaborative'] as bool,
|
||||||
|
public: json['public'] as bool,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeFullPlaylistObjectImplToJson(
|
||||||
|
_$SpotubeFullPlaylistObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'description': instance.description,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
'owner': instance.owner.toJson(),
|
||||||
|
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||||
|
'collaborators': instance.collaborators.map((e) => e.toJson()).toList(),
|
||||||
|
'collaborative': instance.collaborative,
|
||||||
|
'public': instance.public,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl _$$SpotubeSimplePlaylistObjectImplFromJson(
|
||||||
|
Map json) =>
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
description: json['description'] as String,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
owner: SpotubeUserObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(json['owner'] as Map)),
|
||||||
|
images: (json['images'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeImageObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeSimplePlaylistObjectImplToJson(
|
||||||
|
_$SpotubeSimplePlaylistObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'description': instance.description,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
'owner': instance.owner.toJson(),
|
||||||
|
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
32
lib/src/rust/api/plugin/models/search.dart
Normal file
32
lib/src/rust/api/plugin/models/search.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'album.dart';
|
||||||
|
import 'artist.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
import 'playlist.dart';
|
||||||
|
import 'track.dart';
|
||||||
|
import 'user.dart';
|
||||||
|
part 'search.freezed.dart';
|
||||||
|
part 'search.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject {
|
||||||
|
const factory SpotubeSearchResponseObject({
|
||||||
|
required String typeName,
|
||||||
|
required List<SpotubeSimpleAlbumObject> albums,
|
||||||
|
required List<SpotubeFullArtistObject> artists,
|
||||||
|
required List<SpotubeSimplePlaylistObject> playlists,
|
||||||
|
required List<SpotubeTrackObject> tracks,
|
||||||
|
}) = _SpotubeSearchResponseObject;
|
||||||
|
|
||||||
|
factory SpotubeSearchResponseObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeSearchResponseObjectFromJson(json);
|
||||||
|
}
|
||||||
298
lib/src/rust/api/plugin/models/search.freezed.dart
Normal file
298
lib/src/rust/api/plugin/models/search.freezed.dart
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
// 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 'search.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(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');
|
||||||
|
|
||||||
|
SpotubeSearchResponseObject _$SpotubeSearchResponseObjectFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return _SpotubeSearchResponseObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeSearchResponseObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeSimpleAlbumObject> get albums =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeFullArtistObject> get artists =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeSimplePlaylistObject> get playlists =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeTrackObject> get tracks => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeSearchResponseObject to a JSON map.
|
||||||
|
Map<String, dynamic> 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<SpotubeSearchResponseObject>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeSearchResponseObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeSearchResponseObjectCopyWith(
|
||||||
|
SpotubeSearchResponseObject value,
|
||||||
|
$Res Function(SpotubeSearchResponseObject) then) =
|
||||||
|
_$SpotubeSearchResponseObjectCopyWithImpl<$Res,
|
||||||
|
SpotubeSearchResponseObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
List<SpotubeSimpleAlbumObject> albums,
|
||||||
|
List<SpotubeFullArtistObject> artists,
|
||||||
|
List<SpotubeSimplePlaylistObject> playlists,
|
||||||
|
List<SpotubeTrackObject> tracks});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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? typeName = null,
|
||||||
|
Object? albums = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? playlists = null,
|
||||||
|
Object? tracks = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
albums: null == albums
|
||||||
|
? _value.albums
|
||||||
|
: albums // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleAlbumObject>,
|
||||||
|
artists: null == artists
|
||||||
|
? _value.artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeFullArtistObject>,
|
||||||
|
playlists: null == playlists
|
||||||
|
? _value.playlists
|
||||||
|
: playlists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimplePlaylistObject>,
|
||||||
|
tracks: null == tracks
|
||||||
|
? _value.tracks
|
||||||
|
: tracks // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeTrackObject>,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$SpotubeSearchResponseObjectImplCopyWith<$Res>
|
||||||
|
implements $SpotubeSearchResponseObjectCopyWith<$Res> {
|
||||||
|
factory _$$SpotubeSearchResponseObjectImplCopyWith(
|
||||||
|
_$SpotubeSearchResponseObjectImpl value,
|
||||||
|
$Res Function(_$SpotubeSearchResponseObjectImpl) then) =
|
||||||
|
__$$SpotubeSearchResponseObjectImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
List<SpotubeSimpleAlbumObject> albums,
|
||||||
|
List<SpotubeFullArtistObject> artists,
|
||||||
|
List<SpotubeSimplePlaylistObject> playlists,
|
||||||
|
List<SpotubeTrackObject> tracks});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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? typeName = null,
|
||||||
|
Object? albums = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? playlists = null,
|
||||||
|
Object? tracks = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeSearchResponseObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
albums: null == albums
|
||||||
|
? _value._albums
|
||||||
|
: albums // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleAlbumObject>,
|
||||||
|
artists: null == artists
|
||||||
|
? _value._artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeFullArtistObject>,
|
||||||
|
playlists: null == playlists
|
||||||
|
? _value._playlists
|
||||||
|
: playlists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimplePlaylistObject>,
|
||||||
|
tracks: null == tracks
|
||||||
|
? _value._tracks
|
||||||
|
: tracks // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeTrackObject>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeSearchResponseObjectImpl
|
||||||
|
implements _SpotubeSearchResponseObject {
|
||||||
|
const _$SpotubeSearchResponseObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required final List<SpotubeSimpleAlbumObject> albums,
|
||||||
|
required final List<SpotubeFullArtistObject> artists,
|
||||||
|
required final List<SpotubeSimplePlaylistObject> playlists,
|
||||||
|
required final List<SpotubeTrackObject> tracks})
|
||||||
|
: _albums = albums,
|
||||||
|
_artists = artists,
|
||||||
|
_playlists = playlists,
|
||||||
|
_tracks = tracks;
|
||||||
|
|
||||||
|
factory _$SpotubeSearchResponseObjectImpl.fromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeSearchResponseObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
final List<SpotubeSimpleAlbumObject> _albums;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleAlbumObject> get albums {
|
||||||
|
if (_albums is EqualUnmodifiableListView) return _albums;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_albums);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SpotubeFullArtistObject> _artists;
|
||||||
|
@override
|
||||||
|
List<SpotubeFullArtistObject> get artists {
|
||||||
|
if (_artists is EqualUnmodifiableListView) return _artists;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_artists);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SpotubeSimplePlaylistObject> _playlists;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimplePlaylistObject> get playlists {
|
||||||
|
if (_playlists is EqualUnmodifiableListView) return _playlists;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_playlists);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SpotubeTrackObject> _tracks;
|
||||||
|
@override
|
||||||
|
List<SpotubeTrackObject> get tracks {
|
||||||
|
if (_tracks is EqualUnmodifiableListView) return _tracks;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeSearchResponseObject(typeName: $typeName, albums: $albums, artists: $artists, playlists: $playlists, tracks: $tracks)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeSearchResponseObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
const DeepCollectionEquality().equals(other._albums, _albums) &&
|
||||||
|
const DeepCollectionEquality().equals(other._artists, _artists) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other._playlists, _playlists) &&
|
||||||
|
const DeepCollectionEquality().equals(other._tracks, _tracks));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
typeName,
|
||||||
|
const DeepCollectionEquality().hash(_albums),
|
||||||
|
const DeepCollectionEquality().hash(_artists),
|
||||||
|
const DeepCollectionEquality().hash(_playlists),
|
||||||
|
const DeepCollectionEquality().hash(_tracks));
|
||||||
|
|
||||||
|
/// 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<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeSearchResponseObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeSearchResponseObject
|
||||||
|
implements SpotubeSearchResponseObject {
|
||||||
|
const factory _SpotubeSearchResponseObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final List<SpotubeSimpleAlbumObject> albums,
|
||||||
|
required final List<SpotubeFullArtistObject> artists,
|
||||||
|
required final List<SpotubeSimplePlaylistObject> playlists,
|
||||||
|
required final List<SpotubeTrackObject> tracks}) =
|
||||||
|
_$SpotubeSearchResponseObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeSearchResponseObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeSearchResponseObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleAlbumObject> get albums;
|
||||||
|
@override
|
||||||
|
List<SpotubeFullArtistObject> get artists;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimplePlaylistObject> get playlists;
|
||||||
|
@override
|
||||||
|
List<SpotubeTrackObject> get tracks;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
39
lib/src/rust/api/plugin/models/search.g.dart
Normal file
39
lib/src/rust/api/plugin/models/search.g.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'search.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeSearchResponseObjectImpl _$$SpotubeSearchResponseObjectImplFromJson(
|
||||||
|
Map json) =>
|
||||||
|
_$SpotubeSearchResponseObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
albums: (json['albums'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeSimpleAlbumObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
artists: (json['artists'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeFullArtistObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
playlists: (json['playlists'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeSimplePlaylistObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
tracks: (json['tracks'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeTrackObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeSearchResponseObjectImplToJson(
|
||||||
|
_$SpotubeSearchResponseObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'albums': instance.albums.map((e) => e.toJson()).toList(),
|
||||||
|
'artists': instance.artists.map((e) => e.toJson()).toList(),
|
||||||
|
'playlists': instance.playlists.map((e) => e.toJson()).toList(),
|
||||||
|
'tracks': instance.tracks.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
33
lib/src/rust/api/plugin/models/track.dart
Normal file
33
lib/src/rust/api/plugin/models/track.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'album.dart';
|
||||||
|
import 'artist.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
part 'track.freezed.dart';
|
||||||
|
part 'track.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeTrackObject with _$SpotubeTrackObject {
|
||||||
|
const factory SpotubeTrackObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String externalUri,
|
||||||
|
required List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required SpotubeSimpleAlbumObject album,
|
||||||
|
required BigInt durationMs,
|
||||||
|
required String isrc,
|
||||||
|
required bool explicit,
|
||||||
|
}) = _SpotubeTrackObject;
|
||||||
|
|
||||||
|
factory SpotubeTrackObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeTrackObjectFromJson(json);
|
||||||
|
}
|
||||||
366
lib/src/rust/api/plugin/models/track.freezed.dart
Normal file
366
lib/src/rust/api/plugin/models/track.freezed.dart
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
// 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 'track.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(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');
|
||||||
|
|
||||||
|
SpotubeTrackObject _$SpotubeTrackObjectFromJson(Map<String, dynamic> json) {
|
||||||
|
return _SpotubeTrackObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeTrackObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeSimpleArtistObject> get artists =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
SpotubeSimpleAlbumObject get album => throw _privateConstructorUsedError;
|
||||||
|
BigInt get durationMs => throw _privateConstructorUsedError;
|
||||||
|
String get isrc => throw _privateConstructorUsedError;
|
||||||
|
bool get explicit => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeTrackObject to a JSON map.
|
||||||
|
Map<String, dynamic> 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<SpotubeTrackObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeTrackObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeTrackObjectCopyWith(
|
||||||
|
SpotubeTrackObject value, $Res Function(SpotubeTrackObject) then) =
|
||||||
|
_$SpotubeTrackObjectCopyWithImpl<$Res, SpotubeTrackObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeSimpleArtistObject> artists,
|
||||||
|
SpotubeSimpleAlbumObject album,
|
||||||
|
BigInt durationMs,
|
||||||
|
String isrc,
|
||||||
|
bool explicit});
|
||||||
|
|
||||||
|
$SpotubeSimpleAlbumObjectCopyWith<$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? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? album = null,
|
||||||
|
Object? durationMs = null,
|
||||||
|
Object? isrc = null,
|
||||||
|
Object? explicit = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
artists: null == artists
|
||||||
|
? _value.artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleArtistObject>,
|
||||||
|
album: null == album
|
||||||
|
? _value.album
|
||||||
|
: album // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeSimpleAlbumObject,
|
||||||
|
durationMs: null == durationMs
|
||||||
|
? _value.durationMs
|
||||||
|
: durationMs // ignore: cast_nullable_to_non_nullable
|
||||||
|
as BigInt,
|
||||||
|
isrc: null == isrc
|
||||||
|
? _value.isrc
|
||||||
|
: isrc // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
explicit: null == explicit
|
||||||
|
? _value.explicit
|
||||||
|
: explicit // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SpotubeTrackObject
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SpotubeSimpleAlbumObjectCopyWith<$Res> get album {
|
||||||
|
return $SpotubeSimpleAlbumObjectCopyWith<$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 typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeSimpleArtistObject> artists,
|
||||||
|
SpotubeSimpleAlbumObject album,
|
||||||
|
BigInt durationMs,
|
||||||
|
String isrc,
|
||||||
|
bool explicit});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$SpotubeSimpleAlbumObjectCopyWith<$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? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
Object? artists = null,
|
||||||
|
Object? album = null,
|
||||||
|
Object? durationMs = null,
|
||||||
|
Object? isrc = null,
|
||||||
|
Object? explicit = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeTrackObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
artists: null == artists
|
||||||
|
? _value._artists
|
||||||
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeSimpleArtistObject>,
|
||||||
|
album: null == album
|
||||||
|
? _value.album
|
||||||
|
: album // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SpotubeSimpleAlbumObject,
|
||||||
|
durationMs: null == durationMs
|
||||||
|
? _value.durationMs
|
||||||
|
: durationMs // ignore: cast_nullable_to_non_nullable
|
||||||
|
as BigInt,
|
||||||
|
isrc: null == isrc
|
||||||
|
? _value.isrc
|
||||||
|
: isrc // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
explicit: null == explicit
|
||||||
|
? _value.explicit
|
||||||
|
: explicit // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeTrackObjectImpl implements _SpotubeTrackObject {
|
||||||
|
const _$SpotubeTrackObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.externalUri,
|
||||||
|
required final List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required this.album,
|
||||||
|
required this.durationMs,
|
||||||
|
required this.isrc,
|
||||||
|
required this.explicit})
|
||||||
|
: _artists = artists;
|
||||||
|
|
||||||
|
factory _$SpotubeTrackObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeTrackObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
final List<SpotubeSimpleArtistObject> _artists;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleArtistObject> get artists {
|
||||||
|
if (_artists is EqualUnmodifiableListView) return _artists;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_artists);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final SpotubeSimpleAlbumObject album;
|
||||||
|
@override
|
||||||
|
final BigInt durationMs;
|
||||||
|
@override
|
||||||
|
final String isrc;
|
||||||
|
@override
|
||||||
|
final bool explicit;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeTrackObject(typeName: $typeName, id: $id, name: $name, externalUri: $externalUri, artists: $artists, album: $album, durationMs: $durationMs, isrc: $isrc, explicit: $explicit)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeTrackObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri) &&
|
||||||
|
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.explicit, explicit) ||
|
||||||
|
other.explicit == explicit));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
typeName,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
externalUri,
|
||||||
|
const DeepCollectionEquality().hash(_artists),
|
||||||
|
album,
|
||||||
|
durationMs,
|
||||||
|
isrc,
|
||||||
|
explicit);
|
||||||
|
|
||||||
|
/// 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<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeTrackObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeTrackObject implements SpotubeTrackObject {
|
||||||
|
const factory _SpotubeTrackObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final String externalUri,
|
||||||
|
required final List<SpotubeSimpleArtistObject> artists,
|
||||||
|
required final SpotubeSimpleAlbumObject album,
|
||||||
|
required final BigInt durationMs,
|
||||||
|
required final String isrc,
|
||||||
|
required final bool explicit}) = _$SpotubeTrackObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeTrackObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeTrackObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
List<SpotubeSimpleArtistObject> get artists;
|
||||||
|
@override
|
||||||
|
SpotubeSimpleAlbumObject get album;
|
||||||
|
@override
|
||||||
|
BigInt get durationMs;
|
||||||
|
@override
|
||||||
|
String get isrc;
|
||||||
|
@override
|
||||||
|
bool get explicit;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
38
lib/src/rust/api/plugin/models/track.g.dart
Normal file
38
lib/src/rust/api/plugin/models/track.g.dart
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'track.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeTrackObjectImpl _$$SpotubeTrackObjectImplFromJson(Map json) =>
|
||||||
|
_$SpotubeTrackObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
artists: (json['artists'] as List<dynamic>)
|
||||||
|
.map((e) => SpotubeSimpleArtistObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
album: SpotubeSimpleAlbumObject.fromJson(
|
||||||
|
Map<String, dynamic>.from(json['album'] as Map)),
|
||||||
|
durationMs: BigInt.parse(json['durationMs'] as String),
|
||||||
|
isrc: json['isrc'] as String,
|
||||||
|
explicit: json['explicit'] as bool,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeTrackObjectImplToJson(
|
||||||
|
_$SpotubeTrackObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
'artists': instance.artists.map((e) => e.toJson()).toList(),
|
||||||
|
'album': instance.album.toJson(),
|
||||||
|
'durationMs': instance.durationMs.toString(),
|
||||||
|
'isrc': instance.isrc,
|
||||||
|
'explicit': instance.explicit,
|
||||||
|
};
|
||||||
27
lib/src/rust/api/plugin/models/user.dart
Normal file
27
lib/src/rust/api/plugin/models/user.dart
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../../frb_generated.dart';
|
||||||
|
import 'image.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||||
|
part 'user.freezed.dart';
|
||||||
|
part 'user.g.dart';
|
||||||
|
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt`
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SpotubeUserObject with _$SpotubeUserObject {
|
||||||
|
const factory SpotubeUserObject({
|
||||||
|
required String typeName,
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required List<SpotubeImageObject> images,
|
||||||
|
required String externalUri,
|
||||||
|
}) = _SpotubeUserObject;
|
||||||
|
|
||||||
|
factory SpotubeUserObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SpotubeUserObjectFromJson(json);
|
||||||
|
}
|
||||||
259
lib/src/rust/api/plugin/models/user.freezed.dart
Normal file
259
lib/src/rust/api/plugin/models/user.freezed.dart
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
// 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 'user.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(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');
|
||||||
|
|
||||||
|
SpotubeUserObject _$SpotubeUserObjectFromJson(Map<String, dynamic> json) {
|
||||||
|
return _SpotubeUserObject.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SpotubeUserObject {
|
||||||
|
String get typeName => throw _privateConstructorUsedError;
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject> get images => throw _privateConstructorUsedError;
|
||||||
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this SpotubeUserObject to a JSON map.
|
||||||
|
Map<String, dynamic> 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<SpotubeUserObject> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SpotubeUserObjectCopyWith<$Res> {
|
||||||
|
factory $SpotubeUserObjectCopyWith(
|
||||||
|
SpotubeUserObject value, $Res Function(SpotubeUserObject) then) =
|
||||||
|
_$SpotubeUserObjectCopyWithImpl<$Res, SpotubeUserObject>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
String externalUri});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // 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<SpotubeImageObject>,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // 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 typeName,
|
||||||
|
String id,
|
||||||
|
String name,
|
||||||
|
List<SpotubeImageObject> images,
|
||||||
|
String externalUri});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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? typeName = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? images = null,
|
||||||
|
Object? externalUri = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$SpotubeUserObjectImpl(
|
||||||
|
typeName: null == typeName
|
||||||
|
? _value.typeName
|
||||||
|
: typeName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // 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<SpotubeImageObject>,
|
||||||
|
externalUri: null == externalUri
|
||||||
|
? _value.externalUri
|
||||||
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$SpotubeUserObjectImpl implements _SpotubeUserObject {
|
||||||
|
const _$SpotubeUserObjectImpl(
|
||||||
|
{required this.typeName,
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required this.externalUri})
|
||||||
|
: _images = images;
|
||||||
|
|
||||||
|
factory _$SpotubeUserObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$SpotubeUserObjectImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String typeName;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
final List<SpotubeImageObject> _images;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images {
|
||||||
|
if (_images is EqualUnmodifiableListView) return _images;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String externalUri;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SpotubeUserObject(typeName: $typeName, id: $id, name: $name, images: $images, externalUri: $externalUri)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$SpotubeUserObjectImpl &&
|
||||||
|
(identical(other.typeName, typeName) ||
|
||||||
|
other.typeName == typeName) &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images) &&
|
||||||
|
(identical(other.externalUri, externalUri) ||
|
||||||
|
other.externalUri == externalUri));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, typeName, id, name,
|
||||||
|
const DeepCollectionEquality().hash(_images), externalUri);
|
||||||
|
|
||||||
|
/// 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<String, dynamic> toJson() {
|
||||||
|
return _$$SpotubeUserObjectImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SpotubeUserObject implements SpotubeUserObject {
|
||||||
|
const factory _SpotubeUserObject(
|
||||||
|
{required final String typeName,
|
||||||
|
required final String id,
|
||||||
|
required final String name,
|
||||||
|
required final List<SpotubeImageObject> images,
|
||||||
|
required final String externalUri}) = _$SpotubeUserObjectImpl;
|
||||||
|
|
||||||
|
factory _SpotubeUserObject.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$SpotubeUserObjectImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get typeName;
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject> get images;
|
||||||
|
@override
|
||||||
|
String get externalUri;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
29
lib/src/rust/api/plugin/models/user.g.dart
Normal file
29
lib/src/rust/api/plugin/models/user.g.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'user.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$SpotubeUserObjectImpl _$$SpotubeUserObjectImplFromJson(Map json) =>
|
||||||
|
_$SpotubeUserObjectImpl(
|
||||||
|
typeName: json['typeName'] as String,
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
images: (json['images'] as List<dynamic>)
|
||||||
|
.map((e) =>
|
||||||
|
SpotubeImageObject.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||||
|
.toList(),
|
||||||
|
externalUri: json['externalUri'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$SpotubeUserObjectImplToJson(
|
||||||
|
_$SpotubeUserObjectImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'typeName': instance.typeName,
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||||
|
'externalUri': instance.externalUri,
|
||||||
|
};
|
||||||
90
lib/src/rust/api/plugin/plugin.dart
Normal file
90
lib/src/rust/api/plugin/plugin.dart
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../frb_generated.dart';
|
||||||
|
import 'models/core.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'senders.dart';
|
||||||
|
|
||||||
|
// These functions are ignored because they are not marked as `pub`: `js_executor_thread`
|
||||||
|
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`
|
||||||
|
// These functions are ignored (category: IgnoreBecauseExplicitAttribute): `create_context`
|
||||||
|
|
||||||
|
// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<OpaqueSender>>
|
||||||
|
abstract class OpaqueSender implements RustOpaqueInterface {
|
||||||
|
SenderPluginCommand get sender;
|
||||||
|
|
||||||
|
set sender(SenderPluginCommand sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<Sender < PluginCommand >>>
|
||||||
|
abstract class SenderPluginCommand implements RustOpaqueInterface {}
|
||||||
|
|
||||||
|
class SpotubePlugin {
|
||||||
|
final PluginArtistSender artist;
|
||||||
|
final PluginAlbumSender album;
|
||||||
|
final PluginAudioSourceSender audioSource;
|
||||||
|
final PluginAuthSender auth;
|
||||||
|
final PluginBrowseSender browse;
|
||||||
|
final PluginCoreSender core;
|
||||||
|
final PluginPlaylistSender playlist;
|
||||||
|
final PluginSearchSender search;
|
||||||
|
final PluginTrackSender track;
|
||||||
|
final PluginUserSender user;
|
||||||
|
|
||||||
|
const SpotubePlugin.raw({
|
||||||
|
required this.artist,
|
||||||
|
required this.album,
|
||||||
|
required this.audioSource,
|
||||||
|
required this.auth,
|
||||||
|
required this.browse,
|
||||||
|
required this.core,
|
||||||
|
required this.playlist,
|
||||||
|
required this.search,
|
||||||
|
required this.track,
|
||||||
|
required this.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> dispose({required OpaqueSender tx}) => RustLib.instance.api
|
||||||
|
.crateApiPluginPluginSpotubePluginDispose(that: this, tx: tx);
|
||||||
|
|
||||||
|
factory SpotubePlugin() =>
|
||||||
|
RustLib.instance.api.crateApiPluginPluginSpotubePluginNew();
|
||||||
|
|
||||||
|
static OpaqueSender newContext(
|
||||||
|
{required String pluginScript,
|
||||||
|
required PluginConfiguration pluginConfig}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginPluginSpotubePluginNewContext(
|
||||||
|
pluginScript: pluginScript, pluginConfig: pluginConfig);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
artist.hashCode ^
|
||||||
|
album.hashCode ^
|
||||||
|
audioSource.hashCode ^
|
||||||
|
auth.hashCode ^
|
||||||
|
browse.hashCode ^
|
||||||
|
core.hashCode ^
|
||||||
|
playlist.hashCode ^
|
||||||
|
search.hashCode ^
|
||||||
|
track.hashCode ^
|
||||||
|
user.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is SpotubePlugin &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
artist == other.artist &&
|
||||||
|
album == other.album &&
|
||||||
|
audioSource == other.audioSource &&
|
||||||
|
auth == other.auth &&
|
||||||
|
browse == other.browse &&
|
||||||
|
core == other.core &&
|
||||||
|
playlist == other.playlist &&
|
||||||
|
search == other.search &&
|
||||||
|
track == other.track &&
|
||||||
|
user == other.user;
|
||||||
|
}
|
||||||
444
lib/src/rust/api/plugin/senders.dart
Normal file
444
lib/src/rust/api/plugin/senders.dart
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
// This file is automatically generated, so please do not edit it.
|
||||||
|
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||||
|
|
||||||
|
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||||
|
|
||||||
|
import '../../frb_generated.dart';
|
||||||
|
import 'models/album.dart';
|
||||||
|
import 'models/artist.dart';
|
||||||
|
import 'models/audio_source.dart';
|
||||||
|
import 'models/browse.dart';
|
||||||
|
import 'models/core.dart';
|
||||||
|
import 'models/image.dart';
|
||||||
|
import 'models/pagination.dart';
|
||||||
|
import 'models/playlist.dart';
|
||||||
|
import 'models/search.dart';
|
||||||
|
import 'models/track.dart';
|
||||||
|
import 'models/user.dart';
|
||||||
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||||
|
import 'plugin.dart';
|
||||||
|
|
||||||
|
// These functions are ignored (category: IgnoreBecauseExplicitAttribute): `new`, `new`, `new`, `new`, `new`, `new`, `new`, `new`, `new`, `new`
|
||||||
|
|
||||||
|
class PluginAlbumSender {
|
||||||
|
const PluginAlbumSender();
|
||||||
|
|
||||||
|
Future<SpotubeFullAlbumObject> getAlbum(
|
||||||
|
{required OpaqueSender mpscTx, required String id}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAlbumSenderGetAlbum(
|
||||||
|
that: this, mpscTx: mpscTx, id: id);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> releases(
|
||||||
|
{required OpaqueSender mpscTx, int? offset, int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAlbumSenderReleases(
|
||||||
|
that: this, mpscTx: mpscTx, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<void> save(
|
||||||
|
{required OpaqueSender mpscTx, required List<String> ids}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAlbumSenderSave(
|
||||||
|
that: this, mpscTx: mpscTx, ids: ids);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> tracks(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String id,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAlbumSenderTracks(
|
||||||
|
that: this, mpscTx: mpscTx, id: id, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<void> unsave(
|
||||||
|
{required OpaqueSender mpscTx, required List<String> ids}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAlbumSenderUnsave(
|
||||||
|
that: this, mpscTx: mpscTx, ids: ids);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginAlbumSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginArtistSender {
|
||||||
|
const PluginArtistSender();
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> albums(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String id,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginArtistSenderAlbums(
|
||||||
|
that: this, mpscTx: mpscTx, id: id, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<SpotubeFullArtistObject> getArtist(
|
||||||
|
{required OpaqueSender mpscTx, required String id}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginArtistSenderGetArtist(
|
||||||
|
that: this, mpscTx: mpscTx, id: id);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> related(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String id,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginArtistSenderRelated(
|
||||||
|
that: this, mpscTx: mpscTx, id: id, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<void> save(
|
||||||
|
{required OpaqueSender mpscTx, required List<String> ids}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginArtistSenderSave(
|
||||||
|
that: this, mpscTx: mpscTx, ids: ids);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> topTracks(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String id,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginArtistSenderTopTracks(
|
||||||
|
that: this, mpscTx: mpscTx, id: id, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<void> unsave(
|
||||||
|
{required OpaqueSender mpscTx, required List<String> ids}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginArtistSenderUnsave(
|
||||||
|
that: this, mpscTx: mpscTx, ids: ids);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginArtistSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginAudioSourceSender {
|
||||||
|
const PluginAudioSourceSender();
|
||||||
|
|
||||||
|
Future<List<SpotubeAudioSourceMatchObject>> matches(
|
||||||
|
{required OpaqueSender mpscTx, required SpotubeTrackObject track}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAudioSourceSenderMatches(
|
||||||
|
that: this, mpscTx: mpscTx, track: track);
|
||||||
|
|
||||||
|
Future<List<SpotubeAudioSourceStreamObject>> streams(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required SpotubeAudioSourceMatchObject matched}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAudioSourceSenderStreams(
|
||||||
|
that: this, mpscTx: mpscTx, matched: matched);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginAudioSourceSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginAuthSender {
|
||||||
|
const PluginAuthSender();
|
||||||
|
|
||||||
|
Future<void> authenticate({required OpaqueSender mpscTx}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAuthSenderAuthenticate(
|
||||||
|
that: this, mpscTx: mpscTx);
|
||||||
|
|
||||||
|
Future<bool> isAuthenticated({required OpaqueSender mpscTx}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginAuthSenderIsAuthenticated(
|
||||||
|
that: this, mpscTx: mpscTx);
|
||||||
|
|
||||||
|
Future<void> logout({required OpaqueSender mpscTx}) => RustLib.instance.api
|
||||||
|
.crateApiPluginSendersPluginAuthSenderLogout(that: this, mpscTx: mpscTx);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginAuthSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginBrowseSender {
|
||||||
|
const PluginBrowseSender();
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> sectionItems(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String id,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginBrowseSenderSectionItems(
|
||||||
|
that: this, mpscTx: mpscTx, id: id, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> sections(
|
||||||
|
{required OpaqueSender mpscTx, int? offset, int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginBrowseSenderSections(
|
||||||
|
that: this, mpscTx: mpscTx, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginBrowseSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginCoreSender {
|
||||||
|
const PluginCoreSender();
|
||||||
|
|
||||||
|
Future<PluginUpdateAvailable?> checkUpdate(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required PluginConfiguration pluginConfig}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginCoreSenderCheckUpdate(
|
||||||
|
that: this, mpscTx: mpscTx, pluginConfig: pluginConfig);
|
||||||
|
|
||||||
|
Future<void> scrobble(
|
||||||
|
{required OpaqueSender mpscTx, required ScrobbleDetails details}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginCoreSenderScrobble(
|
||||||
|
that: this, mpscTx: mpscTx, details: details);
|
||||||
|
|
||||||
|
Future<String> support({required OpaqueSender mpscTx}) => RustLib.instance.api
|
||||||
|
.crateApiPluginSendersPluginCoreSenderSupport(that: this, mpscTx: mpscTx);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginCoreSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginPlaylistSender {
|
||||||
|
const PluginPlaylistSender();
|
||||||
|
|
||||||
|
Future<void> addTracks(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String playlistId,
|
||||||
|
required List<String> trackIds,
|
||||||
|
int? position}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginPlaylistSenderAddTracks(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
playlistId: playlistId,
|
||||||
|
trackIds: trackIds,
|
||||||
|
position: position);
|
||||||
|
|
||||||
|
Future<SpotubeFullPlaylistObject?> createPlaylist(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String userId,
|
||||||
|
required String name,
|
||||||
|
String? description,
|
||||||
|
bool? public,
|
||||||
|
bool? collaborative}) =>
|
||||||
|
RustLib.instance.api
|
||||||
|
.crateApiPluginSendersPluginPlaylistSenderCreatePlaylist(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
userId: userId,
|
||||||
|
name: name,
|
||||||
|
description: description,
|
||||||
|
public: public,
|
||||||
|
collaborative: collaborative);
|
||||||
|
|
||||||
|
Future<void> deletePlaylist(
|
||||||
|
{required OpaqueSender mpscTx, required String playlistId}) =>
|
||||||
|
RustLib.instance.api
|
||||||
|
.crateApiPluginSendersPluginPlaylistSenderDeletePlaylist(
|
||||||
|
that: this, mpscTx: mpscTx, playlistId: playlistId);
|
||||||
|
|
||||||
|
Future<SpotubeFullPlaylistObject> getPlaylist(
|
||||||
|
{required OpaqueSender mpscTx, required String id}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginPlaylistSenderGetPlaylist(
|
||||||
|
that: this, mpscTx: mpscTx, id: id);
|
||||||
|
|
||||||
|
Future<void> removeTracks(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String playlistId,
|
||||||
|
required List<String> trackIds}) =>
|
||||||
|
RustLib.instance.api
|
||||||
|
.crateApiPluginSendersPluginPlaylistSenderRemoveTracks(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
playlistId: playlistId,
|
||||||
|
trackIds: trackIds);
|
||||||
|
|
||||||
|
Future<void> save(
|
||||||
|
{required OpaqueSender mpscTx, required String playlistId}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginPlaylistSenderSave(
|
||||||
|
that: this, mpscTx: mpscTx, playlistId: playlistId);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> tracks(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String id,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginPlaylistSenderTracks(
|
||||||
|
that: this, mpscTx: mpscTx, id: id, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<void> unsave(
|
||||||
|
{required OpaqueSender mpscTx, required String playlistId}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginPlaylistSenderUnsave(
|
||||||
|
that: this, mpscTx: mpscTx, playlistId: playlistId);
|
||||||
|
|
||||||
|
Future<void> updatePlaylist(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String playlistId,
|
||||||
|
String? name,
|
||||||
|
String? description,
|
||||||
|
bool? public,
|
||||||
|
bool? collaborative}) =>
|
||||||
|
RustLib.instance.api
|
||||||
|
.crateApiPluginSendersPluginPlaylistSenderUpdatePlaylist(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
playlistId: playlistId,
|
||||||
|
name: name,
|
||||||
|
description: description,
|
||||||
|
public: public,
|
||||||
|
collaborative: collaborative);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginPlaylistSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginSearchSender {
|
||||||
|
const PluginSearchSender();
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> albums(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String query,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginSearchSenderAlbums(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
query: query,
|
||||||
|
offset: offset,
|
||||||
|
limit: limit);
|
||||||
|
|
||||||
|
Future<SpotubeSearchResponseObject> all(
|
||||||
|
{required OpaqueSender mpscTx, required String query}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginSearchSenderAll(
|
||||||
|
that: this, mpscTx: mpscTx, query: query);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> artists(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String query,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginSearchSenderArtists(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
query: query,
|
||||||
|
offset: offset,
|
||||||
|
limit: limit);
|
||||||
|
|
||||||
|
Future<List<String>> chips({required OpaqueSender mpscTx}) => RustLib
|
||||||
|
.instance.api
|
||||||
|
.crateApiPluginSendersPluginSearchSenderChips(that: this, mpscTx: mpscTx);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> playlists(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String query,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginSearchSenderPlaylists(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
query: query,
|
||||||
|
offset: offset,
|
||||||
|
limit: limit);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> tracks(
|
||||||
|
{required OpaqueSender mpscTx,
|
||||||
|
required String query,
|
||||||
|
int? offset,
|
||||||
|
int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginSearchSenderTracks(
|
||||||
|
that: this,
|
||||||
|
mpscTx: mpscTx,
|
||||||
|
query: query,
|
||||||
|
offset: offset,
|
||||||
|
limit: limit);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginSearchSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginTrackSender {
|
||||||
|
const PluginTrackSender();
|
||||||
|
|
||||||
|
Future<SpotubeTrackObject> getTrack(
|
||||||
|
{required OpaqueSender mpscTx, required String id}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginTrackSenderGetTrack(
|
||||||
|
that: this, mpscTx: mpscTx, id: id);
|
||||||
|
|
||||||
|
Future<List<SpotubeTrackObject>> radio(
|
||||||
|
{required OpaqueSender mpscTx, required String id}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginTrackSenderRadio(
|
||||||
|
that: this, mpscTx: mpscTx, id: id);
|
||||||
|
|
||||||
|
Future<void> save(
|
||||||
|
{required OpaqueSender mpscTx, required List<String> ids}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginTrackSenderSave(
|
||||||
|
that: this, mpscTx: mpscTx, ids: ids);
|
||||||
|
|
||||||
|
Future<void> unsave(
|
||||||
|
{required OpaqueSender mpscTx, required List<String> ids}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginTrackSenderUnsave(
|
||||||
|
that: this, mpscTx: mpscTx, ids: ids);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginTrackSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginUserSender {
|
||||||
|
const PluginUserSender();
|
||||||
|
|
||||||
|
Future<SpotubeUserObject> me({required OpaqueSender mpscTx}) =>
|
||||||
|
RustLib.instance.api
|
||||||
|
.crateApiPluginSendersPluginUserSenderMe(that: this, mpscTx: mpscTx);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> savedAlbums(
|
||||||
|
{required OpaqueSender mpscTx, int? offset, int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginUserSenderSavedAlbums(
|
||||||
|
that: this, mpscTx: mpscTx, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> savedArtists(
|
||||||
|
{required OpaqueSender mpscTx, int? offset, int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginUserSenderSavedArtists(
|
||||||
|
that: this, mpscTx: mpscTx, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> savedPlaylists(
|
||||||
|
{required OpaqueSender mpscTx, int? offset, int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginUserSenderSavedPlaylists(
|
||||||
|
that: this, mpscTx: mpscTx, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject> savedTracks(
|
||||||
|
{required OpaqueSender mpscTx, int? offset, int? limit}) =>
|
||||||
|
RustLib.instance.api.crateApiPluginSendersPluginUserSenderSavedTracks(
|
||||||
|
that: this, mpscTx: mpscTx, offset: offset, limit: limit);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is PluginUserSender && runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
@ -1,10 +0,0 @@
|
|||||||
// This file is automatically generated, so please do not edit it.
|
|
||||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
|
||||||
|
|
||||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
|
||||||
|
|
||||||
import '../frb_generated.dart';
|
|
||||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
|
||||||
|
|
||||||
String greet({required String name}) =>
|
|
||||||
RustLib.instance.api.crateApiSimpleGreet(name: name);
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,84 +0,0 @@
|
|||||||
// This file is automatically generated, so please do not edit it.
|
|
||||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
|
||||||
|
|
||||||
// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field
|
|
||||||
|
|
||||||
// Static analysis wrongly picks the IO variant, thus ignore this
|
|
||||||
// ignore_for_file: argument_type_not_assignable
|
|
||||||
|
|
||||||
import 'api/simple.dart';
|
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:convert';
|
|
||||||
import 'frb_generated.dart';
|
|
||||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart';
|
|
||||||
|
|
||||||
abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
|
||||||
RustLibApiImplPlatform({
|
|
||||||
required super.handler,
|
|
||||||
required super.wire,
|
|
||||||
required super.generalizedFrbRustBinding,
|
|
||||||
required super.portManager,
|
|
||||||
});
|
|
||||||
|
|
||||||
@protected
|
|
||||||
String dco_decode_String(dynamic raw);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
int dco_decode_u_8(dynamic raw);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void dco_decode_unit(dynamic raw);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
String sse_decode_String(SseDeserializer deserializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
int sse_decode_u_8(SseDeserializer deserializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void sse_decode_unit(SseDeserializer deserializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
int sse_decode_i_32(SseDeserializer deserializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
bool sse_decode_bool(SseDeserializer deserializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void sse_encode_String(String self, SseSerializer serializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void sse_encode_list_prim_u_8_strict(
|
|
||||||
Uint8List self, SseSerializer serializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void sse_encode_u_8(int self, SseSerializer serializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void sse_encode_unit(void self, SseSerializer serializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void sse_encode_i_32(int self, SseSerializer serializer);
|
|
||||||
|
|
||||||
@protected
|
|
||||||
void sse_encode_bool(bool self, SseSerializer serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section: wire_class
|
|
||||||
|
|
||||||
class RustLibWire implements BaseWire {
|
|
||||||
RustLibWire.fromExternalLibrary(ExternalLibrary lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JS('wasm_bindgen')
|
|
||||||
external RustLibWasmModule get wasmModule;
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@anonymous
|
|
||||||
extension type RustLibWasmModule._(JSObject _) implements JSObject {}
|
|
||||||
@ -1392,7 +1392,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.7"
|
version: "0.6.7"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: json_annotation
|
name: json_annotation
|
||||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||||
|
|||||||
@ -156,6 +156,7 @@ dependencies:
|
|||||||
rust_lib_spotube:
|
rust_lib_spotube:
|
||||||
path: rust_builder
|
path: rust_builder
|
||||||
flutter_rust_bridge: 2.11.1
|
flutter_rust_bridge: 2.11.1
|
||||||
|
json_annotation: ^4.9.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.13
|
build_runner: ^2.4.13
|
||||||
|
|||||||
2505
rust/Cargo.lock
generated
2505
rust/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -6,8 +6,23 @@ edition = "2021"
|
|||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "staticlib"]
|
crate-type = ["cdylib", "staticlib"]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "spotube"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
flutter_rust_bridge = "=2.11.1"
|
flutter_rust_bridge = "=2.11.1"
|
||||||
|
boa_engine = "0.21.0"
|
||||||
|
boa_runtime = "0.21.0"
|
||||||
|
boa_gc = "0.21.0"
|
||||||
|
anyhow = "1"
|
||||||
|
reqwest = { version = "0.12.x" }
|
||||||
|
http = { version = "1.3.1" }
|
||||||
|
serde_json = "1"
|
||||||
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
futures = "0.3.x"
|
||||||
|
tokio = { version = "1.48.0", features = ["full"] }
|
||||||
|
heck = "0.5.0"
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] }
|
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] }
|
||||||
|
|||||||
@ -1 +1,7 @@
|
|||||||
pub mod simple;
|
pub mod plugin;
|
||||||
|
|
||||||
|
#[flutter_rust_bridge::frb(init)]
|
||||||
|
pub fn init_app() {
|
||||||
|
// Default utilities - feel free to customize
|
||||||
|
flutter_rust_bridge::setup_default_user_utils();
|
||||||
|
}
|
||||||
|
|||||||
271
rust/src/api/plugin/commands.rs
Normal file
271
rust/src/api/plugin/commands.rs
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use crate::api::plugin::models::album::SpotubeFullAlbumObject;
|
||||||
|
use crate::api::plugin::models::artist::SpotubeFullArtistObject;
|
||||||
|
use crate::api::plugin::models::audio_source::{
|
||||||
|
SpotubeAudioSourceMatchObject, SpotubeAudioSourceStreamObject,
|
||||||
|
};
|
||||||
|
use crate::api::plugin::models::core::{
|
||||||
|
PluginConfiguration, PluginUpdateAvailable, ScrobbleDetails,
|
||||||
|
};
|
||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
use crate::api::plugin::models::playlist::SpotubeFullPlaylistObject;
|
||||||
|
use crate::api::plugin::models::search::SpotubeSearchResponseObject;
|
||||||
|
use crate::api::plugin::models::track::SpotubeTrackObject;
|
||||||
|
use crate::api::plugin::models::user::SpotubeUserObject;
|
||||||
|
use tokio::sync::oneshot;
|
||||||
|
|
||||||
|
pub enum ArtistCommands {
|
||||||
|
GetArtist {
|
||||||
|
id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubeFullArtistObject>>,
|
||||||
|
},
|
||||||
|
TopTracks {
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Albums {
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Related {
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Save {
|
||||||
|
ids: Vec<String>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
Unsave {
|
||||||
|
ids: Vec<String>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AlbumCommands {
|
||||||
|
GetAlbum {
|
||||||
|
id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubeFullAlbumObject>>,
|
||||||
|
},
|
||||||
|
Tracks {
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Releases {
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Save {
|
||||||
|
ids: Vec<String>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
Unsave {
|
||||||
|
ids: Vec<String>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AudioSourceCommands {
|
||||||
|
Matches {
|
||||||
|
track: SpotubeTrackObject,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<Vec<SpotubeAudioSourceMatchObject>>>,
|
||||||
|
},
|
||||||
|
Streams {
|
||||||
|
matched: SpotubeAudioSourceMatchObject,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<Vec<SpotubeAudioSourceStreamObject>>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AuthCommands {
|
||||||
|
Authenticate {
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
Logout {
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
IsAuthenticated {
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<bool>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum BrowseCommands {
|
||||||
|
Sections {
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
SectionItems {
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum CoreCommands {
|
||||||
|
CheckUpdate {
|
||||||
|
plugin_config: PluginConfiguration,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<Option<PluginUpdateAvailable>>>,
|
||||||
|
},
|
||||||
|
Support {
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<String>>,
|
||||||
|
},
|
||||||
|
Scrobble {
|
||||||
|
details: ScrobbleDetails,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PlaylistCommands {
|
||||||
|
GetPlaylist {
|
||||||
|
id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubeFullPlaylistObject>>,
|
||||||
|
},
|
||||||
|
Tracks {
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
CreatePlaylist {
|
||||||
|
user_id: String,
|
||||||
|
name: String,
|
||||||
|
description: Option<String>,
|
||||||
|
public: Option<bool>,
|
||||||
|
collaborative: Option<bool>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<Option<SpotubeFullPlaylistObject>>>,
|
||||||
|
},
|
||||||
|
UpdatePlaylist {
|
||||||
|
playlist_id: String,
|
||||||
|
name: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
|
public: Option<bool>,
|
||||||
|
collaborative: Option<bool>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
DeletePlaylist {
|
||||||
|
playlist_id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
AddTracks {
|
||||||
|
playlist_id: String,
|
||||||
|
track_ids: Vec<String>,
|
||||||
|
position: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
RemoveTracks {
|
||||||
|
playlist_id: String,
|
||||||
|
track_ids: Vec<String>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
Save {
|
||||||
|
playlist_id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
Unsave {
|
||||||
|
playlist_id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum SearchCommands {
|
||||||
|
Chips {
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<Vec<String>>>,
|
||||||
|
},
|
||||||
|
All {
|
||||||
|
query: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubeSearchResponseObject>>,
|
||||||
|
},
|
||||||
|
Tracks {
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Albums {
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Artists {
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
Playlists {
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TrackCommands {
|
||||||
|
GetTrack {
|
||||||
|
id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubeTrackObject>>,
|
||||||
|
},
|
||||||
|
Save {
|
||||||
|
ids: Vec<String>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
Unsave {
|
||||||
|
ids: Vec<String>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<()>>,
|
||||||
|
},
|
||||||
|
Radio {
|
||||||
|
id: String,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<Vec<SpotubeTrackObject>>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum UserCommands {
|
||||||
|
Me {
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubeUserObject>>,
|
||||||
|
},
|
||||||
|
SavedTracks {
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
SavedAlbums {
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
SavedArtists {
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
SavedPlaylists {
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
response_tx: oneshot::Sender<anyhow::Result<SpotubePaginationResponseObject>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(unignore)]
|
||||||
|
pub enum PluginCommand {
|
||||||
|
Artist(ArtistCommands),
|
||||||
|
Album(AlbumCommands),
|
||||||
|
AudioSource(AudioSourceCommands),
|
||||||
|
Browse(BrowseCommands),
|
||||||
|
Track(TrackCommands),
|
||||||
|
User(UserCommands),
|
||||||
|
Playlist(PlaylistCommands),
|
||||||
|
Search(SearchCommands),
|
||||||
|
Core(CoreCommands),
|
||||||
|
Auth(AuthCommands),
|
||||||
|
Shutdown,
|
||||||
|
}
|
||||||
401
rust/src/api/plugin/executors.rs
Normal file
401
rust/src/api/plugin/executors.rs
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
use crate::api::plugin::commands::{
|
||||||
|
AlbumCommands, ArtistCommands, AudioSourceCommands, AuthCommands, BrowseCommands, CoreCommands,
|
||||||
|
PlaylistCommands, SearchCommands, TrackCommands, UserCommands,
|
||||||
|
};
|
||||||
|
use crate::internal::album::PluginAlbumEndpoint;
|
||||||
|
use crate::internal::artist::PluginArtistEndpoint;
|
||||||
|
use crate::internal::audio_source::PluginAudioSourceEndpoint;
|
||||||
|
use crate::internal::auth::PluginAuthEndpoint;
|
||||||
|
use crate::internal::browse::PluginBrowseEndpoint;
|
||||||
|
use crate::internal::core::PluginCoreEndpoint;
|
||||||
|
use crate::internal::playlist::PluginPlaylistEndpoint;
|
||||||
|
use crate::internal::search::PluginSearchEndpoint;
|
||||||
|
use crate::internal::track::PluginTrackEndpoint;
|
||||||
|
use crate::internal::user::PluginUserEndpoint;
|
||||||
|
use boa_engine::Context;
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use tokio::sync::oneshot;
|
||||||
|
|
||||||
|
fn send_response<T>(tx: oneshot::Sender<T>, response: T) -> anyhow::Result<()>
|
||||||
|
where
|
||||||
|
T: Debug,
|
||||||
|
{
|
||||||
|
tx.send(response)
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to send response: {:?}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_artists(command: ArtistCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut artist = PluginArtistEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
ArtistCommands::GetArtist { id, response_tx } => {
|
||||||
|
let artist = artist.get_artist(id).await;
|
||||||
|
send_response(response_tx, artist)
|
||||||
|
}
|
||||||
|
ArtistCommands::TopTracks {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let tracks = artist.top_tracks(id, offset, limit).await;
|
||||||
|
send_response(response_tx, tracks)
|
||||||
|
}
|
||||||
|
ArtistCommands::Albums {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let albums = artist.albums(id, offset, limit).await;
|
||||||
|
send_response(response_tx, albums)
|
||||||
|
}
|
||||||
|
ArtistCommands::Related {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let artists = artist.related(id, offset, limit).await;
|
||||||
|
send_response(response_tx, artists)
|
||||||
|
}
|
||||||
|
ArtistCommands::Save { ids, response_tx } => {
|
||||||
|
let res = artist.save(ids).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
ArtistCommands::Unsave { ids, response_tx } => {
|
||||||
|
let res = artist.unsave(ids).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_albums(command: AlbumCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut album = PluginAlbumEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
AlbumCommands::GetAlbum { id, response_tx } => {
|
||||||
|
let album = album.get_album(id).await;
|
||||||
|
send_response(response_tx, album)
|
||||||
|
}
|
||||||
|
AlbumCommands::Tracks {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let tracks = album.tracks(id, offset, limit).await;
|
||||||
|
send_response(response_tx, tracks)
|
||||||
|
}
|
||||||
|
AlbumCommands::Releases {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let releases = album.releases(offset, limit).await;
|
||||||
|
send_response(response_tx, releases)
|
||||||
|
}
|
||||||
|
AlbumCommands::Save { ids, response_tx } => {
|
||||||
|
let res = album.save(ids).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
AlbumCommands::Unsave { ids, response_tx } => {
|
||||||
|
let res = album.unsave(ids).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_audio_source(
|
||||||
|
command: AudioSourceCommands,
|
||||||
|
context: &mut Context,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let mut audio_source = PluginAudioSourceEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
AudioSourceCommands::Matches { track, response_tx } => {
|
||||||
|
let audio_source = audio_source.matches(track).await;
|
||||||
|
send_response(response_tx, audio_source)
|
||||||
|
}
|
||||||
|
AudioSourceCommands::Streams {
|
||||||
|
matched,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let audio_source = audio_source.streams(matched).await;
|
||||||
|
send_response(response_tx, audio_source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_auth(command: AuthCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut auth = PluginAuthEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
AuthCommands::Authenticate { response_tx } => {
|
||||||
|
let res = auth.authenticate().await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
AuthCommands::IsAuthenticated { response_tx } => {
|
||||||
|
let res = auth.is_authenticated();
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
AuthCommands::Logout { response_tx } => {
|
||||||
|
let res = auth.logout().await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_browse(command: BrowseCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut browse = PluginBrowseEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
BrowseCommands::Sections {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let sections = browse.sections(offset, limit).await;
|
||||||
|
send_response(response_tx, sections)
|
||||||
|
}
|
||||||
|
BrowseCommands::SectionItems {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let items = browse.section_items(id, offset, limit).await;
|
||||||
|
send_response(response_tx, items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_core(command: CoreCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut core = PluginCoreEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
CoreCommands::CheckUpdate {
|
||||||
|
response_tx,
|
||||||
|
plugin_config,
|
||||||
|
} => {
|
||||||
|
let res = core.check_update(plugin_config).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
CoreCommands::Scrobble {
|
||||||
|
details,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let res = core.scrobble(details).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
CoreCommands::Support { response_tx } => {
|
||||||
|
let res = core.support();
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_playlist(
|
||||||
|
command: PlaylistCommands,
|
||||||
|
context: &mut Context,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let mut playlist = PluginPlaylistEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
PlaylistCommands::GetPlaylist { id, response_tx } => {
|
||||||
|
let playlist = playlist.get_playlist(id).await;
|
||||||
|
send_response(response_tx, playlist)
|
||||||
|
}
|
||||||
|
PlaylistCommands::Tracks {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let tracks = playlist.tracks(id, offset, limit).await;
|
||||||
|
send_response(response_tx, tracks)
|
||||||
|
}
|
||||||
|
PlaylistCommands::CreatePlaylist {
|
||||||
|
user_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
public,
|
||||||
|
collaborative,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let playlist = playlist
|
||||||
|
.create(user_id, name, description, public, collaborative)
|
||||||
|
.await;
|
||||||
|
send_response(response_tx, playlist)
|
||||||
|
}
|
||||||
|
PlaylistCommands::UpdatePlaylist {
|
||||||
|
playlist_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
public,
|
||||||
|
collaborative,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let res = playlist
|
||||||
|
.update(playlist_id, name, description, public, collaborative)
|
||||||
|
.await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
PlaylistCommands::DeletePlaylist {
|
||||||
|
playlist_id,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let res = playlist.delete_playlist(playlist_id).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
PlaylistCommands::AddTracks {
|
||||||
|
playlist_id,
|
||||||
|
track_ids,
|
||||||
|
position,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let res = playlist.add_tracks(playlist_id, track_ids, position).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
PlaylistCommands::RemoveTracks {
|
||||||
|
playlist_id,
|
||||||
|
track_ids,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let res = playlist.remove_tracks(playlist_id, track_ids).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
PlaylistCommands::Save {
|
||||||
|
playlist_id,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let res = playlist.save(playlist_id).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
PlaylistCommands::Unsave {
|
||||||
|
playlist_id,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let res = playlist.unsave(playlist_id).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_search(command: SearchCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut search = PluginSearchEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
SearchCommands::Chips { response_tx } => {
|
||||||
|
let chips = search.chips();
|
||||||
|
send_response(response_tx, chips)
|
||||||
|
}
|
||||||
|
SearchCommands::All { query, response_tx } => {
|
||||||
|
let all = search.all(query).await;
|
||||||
|
send_response(response_tx, all)
|
||||||
|
}
|
||||||
|
SearchCommands::Tracks {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let tracks = search.tracks(query, offset, limit).await;
|
||||||
|
send_response(response_tx, tracks)
|
||||||
|
}
|
||||||
|
SearchCommands::Albums {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let albums = search.albums(query, offset, limit).await;
|
||||||
|
send_response(response_tx, albums)
|
||||||
|
}
|
||||||
|
SearchCommands::Artists {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let artists = search.artists(query, offset, limit).await;
|
||||||
|
send_response(response_tx, artists)
|
||||||
|
}
|
||||||
|
SearchCommands::Playlists {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let playlists = search.playlists(query, offset, limit).await;
|
||||||
|
send_response(response_tx, playlists)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_track(command: TrackCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut track = PluginTrackEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
TrackCommands::GetTrack { id, response_tx } => {
|
||||||
|
let res = track.get_track(id).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
TrackCommands::Save { ids, response_tx } => {
|
||||||
|
let res = track.save(ids).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
TrackCommands::Unsave { ids, response_tx } => {
|
||||||
|
let res = track.unsave(ids).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
TrackCommands::Radio { id, response_tx } => {
|
||||||
|
let res = track.radio(id).await;
|
||||||
|
send_response(response_tx, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub async fn execute_user(command: UserCommands, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
let mut user = PluginUserEndpoint::new(context);
|
||||||
|
match command {
|
||||||
|
UserCommands::Me { response_tx } => {
|
||||||
|
let me = user.me().await;
|
||||||
|
send_response(response_tx, me)
|
||||||
|
}
|
||||||
|
UserCommands::SavedTracks {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let tracks = user.saved_tracks(offset, limit).await;
|
||||||
|
send_response(response_tx, tracks)
|
||||||
|
}
|
||||||
|
UserCommands::SavedAlbums {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let albums = user.saved_albums(offset, limit).await;
|
||||||
|
send_response(response_tx, albums)
|
||||||
|
}
|
||||||
|
UserCommands::SavedArtists {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let artists = user.saved_artists(offset, limit).await;
|
||||||
|
send_response(response_tx, artists)
|
||||||
|
}
|
||||||
|
UserCommands::SavedPlaylists {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx,
|
||||||
|
} => {
|
||||||
|
let playlists = user.saved_playlists(offset, limit).await;
|
||||||
|
send_response(response_tx, playlists)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
rust/src/api/plugin/mod.rs
Normal file
5
rust/src/api/plugin/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub mod commands;
|
||||||
|
pub mod plugin;
|
||||||
|
pub mod executors;
|
||||||
|
pub mod senders;
|
||||||
|
pub mod models;
|
||||||
44
rust/src/api/plugin/models/album.rs
Normal file
44
rust/src/api/plugin/models/album.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::plugin::models::artist::SpotubeSimpleArtistObject;
|
||||||
|
use crate::api::plugin::models::image::SpotubeImageObject;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub enum SpotubeAlbumType {
|
||||||
|
Album,
|
||||||
|
Single,
|
||||||
|
Compilation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeSimpleAlbumObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
pub artists: Vec<SpotubeSimpleArtistObject>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub images: Vec<SpotubeImageObject>,
|
||||||
|
pub album_type: SpotubeAlbumType,
|
||||||
|
pub release_date: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeFullAlbumObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub artists: Vec<SpotubeSimpleArtistObject>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub images: Vec<SpotubeImageObject>,
|
||||||
|
pub release_date: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
pub total_tracks: i32,
|
||||||
|
pub album_type: SpotubeAlbumType,
|
||||||
|
pub record_label: Option<String>,
|
||||||
|
pub genres: Option<Vec<String>>,
|
||||||
|
}
|
||||||
28
rust/src/api/plugin/models/artist.rs
Normal file
28
rust/src/api/plugin/models/artist.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::plugin::models::image::SpotubeImageObject;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeSimpleArtistObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
pub images: Option<Vec<SpotubeImageObject>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeFullArtistObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub images: Vec<SpotubeImageObject>,
|
||||||
|
pub genres: Option<Vec<String>>,
|
||||||
|
pub followers: Option<i32>,
|
||||||
|
}
|
||||||
111
rust/src/api/plugin/models/audio_source.rs
Normal file
111
rust/src/api/plugin/models/audio_source.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum SpotubeMediaCompressionType {
|
||||||
|
Lossy,
|
||||||
|
Lossless,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeAudioLossyContainerQuality {
|
||||||
|
pub bitrate: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpotubeAudioLossyContainerQuality {
|
||||||
|
pub fn to_string_fmt(&self) -> String {
|
||||||
|
let kbps = self.bitrate as f64 / 1000.0;
|
||||||
|
if kbps.fract() == 0.0 {
|
||||||
|
format!("{}kbps", kbps as i32)
|
||||||
|
} else {
|
||||||
|
format!("{:.1}kbps", kbps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeAudioLosslessContainerQuality {
|
||||||
|
pub bit_depth: i32,
|
||||||
|
pub sample_rate: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpotubeAudioLosslessContainerQuality {
|
||||||
|
#[frb(sync)]
|
||||||
|
pub fn to_string_fmt(&self) -> String {
|
||||||
|
let khz = self.sample_rate as f64 / 1000.0;
|
||||||
|
if khz.fract() == 0.0 {
|
||||||
|
format!("{}bit • {}kHz", self.bit_depth, khz as i32)
|
||||||
|
} else {
|
||||||
|
format!("{}bit • {:.1}kHz", self.bit_depth, khz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
#[serde(tag = "type", content = "data")]
|
||||||
|
pub enum SpotubeAudioSourceContainerPreset {
|
||||||
|
#[serde(rename = "lossy")]
|
||||||
|
Lossy {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
compression_type: SpotubeMediaCompressionType,
|
||||||
|
name: String,
|
||||||
|
qualities: Vec<SpotubeAudioLossyContainerQuality>,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[serde(rename = "lossless")]
|
||||||
|
Lossless {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
compression_type: SpotubeMediaCompressionType,
|
||||||
|
name: String,
|
||||||
|
qualities: Vec<SpotubeAudioLosslessContainerQuality>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpotubeAudioSourceContainerPreset {
|
||||||
|
#[frb(sync)]
|
||||||
|
pub fn file_extension(&self) -> String {
|
||||||
|
let name = match self {
|
||||||
|
Self::Lossy { name, .. } => name,
|
||||||
|
Self::Lossless { name, .. } => name,
|
||||||
|
};
|
||||||
|
|
||||||
|
match name.as_str() {
|
||||||
|
"mp4" => "m4a".into(),
|
||||||
|
"webm" => "weba".into(),
|
||||||
|
other => other.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeAudioSourceMatchObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub title: String,
|
||||||
|
pub artists: Vec<String>,
|
||||||
|
pub duration: u64, // Duration in ms
|
||||||
|
|
||||||
|
pub thumbnail: Option<String>,
|
||||||
|
pub external_uri: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeAudioSourceStreamObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub url: String,
|
||||||
|
pub container: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub compression_type: SpotubeMediaCompressionType,
|
||||||
|
|
||||||
|
pub codec: Option<String>,
|
||||||
|
pub bitrate: Option<f64>,
|
||||||
|
pub bit_depth: Option<i32>,
|
||||||
|
pub sample_rate: Option<f64>,
|
||||||
|
}
|
||||||
37
rust/src/api/plugin/models/browse.rs
Normal file
37
rust/src/api/plugin/models/browse.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::plugin::models::album::{SpotubeFullAlbumObject, SpotubeSimpleAlbumObject};
|
||||||
|
use crate::api::plugin::models::artist::{SpotubeFullArtistObject, SpotubeSimpleArtistObject};
|
||||||
|
use crate::api::plugin::models::playlist::{SpotubeFullPlaylistObject, SpotubeSimplePlaylistObject};
|
||||||
|
use crate::api::plugin::models::track::SpotubeTrackObject;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"))]
|
||||||
|
pub struct SpotubeBrowseSectionObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub title: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
pub browse_more: bool,
|
||||||
|
pub items: Vec<SpotubeBrowseSectionResponseObjectItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase", tag = "type_name")]
|
||||||
|
pub enum SpotubeBrowseSectionResponseObjectItem {
|
||||||
|
#[serde(rename = "track")]
|
||||||
|
Track(SpotubeTrackObject),
|
||||||
|
#[serde(rename = "playlist_full")]
|
||||||
|
PlaylistFull(SpotubeFullPlaylistObject),
|
||||||
|
#[serde(rename = "playlist_simple")]
|
||||||
|
PlaylistSimple(SpotubeSimplePlaylistObject),
|
||||||
|
#[serde(rename = "album_simple")]
|
||||||
|
AlbumSimple(SpotubeSimpleAlbumObject),
|
||||||
|
#[serde(rename = "album_full")]
|
||||||
|
AlbumFull(SpotubeFullAlbumObject),
|
||||||
|
#[serde(rename = "artist_full")]
|
||||||
|
ArtistFull(SpotubeFullArtistObject),
|
||||||
|
#[serde(rename = "artist_simple")]
|
||||||
|
ArtistSimple(SpotubeSimpleArtistObject),
|
||||||
|
}
|
||||||
78
rust/src/api/plugin/models/core.rs
Normal file
78
rust/src/api/plugin/models/core.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use heck::ToKebabCase;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum PluginApi {
|
||||||
|
Webview,
|
||||||
|
Localstorage,
|
||||||
|
Timezone,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub enum PluginAbility {
|
||||||
|
#[serde(rename = "authentication")]
|
||||||
|
Authentication,
|
||||||
|
#[serde(rename = "scrobbling")]
|
||||||
|
Scrobbling,
|
||||||
|
#[serde(rename = "metadata")]
|
||||||
|
Metadata,
|
||||||
|
#[serde(rename = "audio-source")]
|
||||||
|
AudioSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PluginConfiguration {
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub version: String,
|
||||||
|
pub author: String,
|
||||||
|
pub entry_point: String,
|
||||||
|
pub plugin_api_version: String,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub apis: Vec<PluginApi>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub abilities: Vec<PluginAbility>,
|
||||||
|
|
||||||
|
pub repository: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginConfiguration {
|
||||||
|
pub fn slug(&self) -> String {
|
||||||
|
self.name.to_kebab_case()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PluginUpdateAvailable {
|
||||||
|
pub download_url: String,
|
||||||
|
pub version: String,
|
||||||
|
pub changelog: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct ScrobbleArtist {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct ScrobbleAlbum {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct ScrobbleDetails {
|
||||||
|
pub id: String,
|
||||||
|
pub title: String,
|
||||||
|
pub artists: Vec<ScrobbleArtist>,
|
||||||
|
pub album: ScrobbleAlbum,
|
||||||
|
pub timestamp: Option<i64>,
|
||||||
|
pub duration_ms: Option<u32>,
|
||||||
|
pub isrc: Option<String>,
|
||||||
|
}
|
||||||
11
rust/src/api/plugin/models/image.rs
Normal file
11
rust/src/api/plugin/models/image.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeImageObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub url: String,
|
||||||
|
pub width: Option<i32>,
|
||||||
|
pub height: Option<i32>,
|
||||||
|
}
|
||||||
11
rust/src/api/plugin/models/mod.rs
Normal file
11
rust/src/api/plugin/models/mod.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
pub mod audio_source;
|
||||||
|
pub mod album;
|
||||||
|
pub mod artist;
|
||||||
|
pub mod browse;
|
||||||
|
pub mod image;
|
||||||
|
pub mod search;
|
||||||
|
pub mod playlist;
|
||||||
|
pub mod track;
|
||||||
|
pub mod user;
|
||||||
|
pub mod pagination;
|
||||||
|
pub mod core;
|
||||||
39
rust/src/api/plugin/models/pagination.rs
Normal file
39
rust/src/api/plugin/models/pagination.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::plugin::models::album::{SpotubeFullAlbumObject, SpotubeSimpleAlbumObject};
|
||||||
|
use crate::api::plugin::models::artist::{SpotubeFullArtistObject, SpotubeSimpleArtistObject};
|
||||||
|
use crate::api::plugin::models::browse::SpotubeBrowseSectionObject;
|
||||||
|
use crate::api::plugin::models::playlist::{SpotubeFullPlaylistObject, SpotubeSimplePlaylistObject};
|
||||||
|
use crate::api::plugin::models::track::SpotubeTrackObject;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"))]
|
||||||
|
pub struct SpotubePaginationResponseObject {
|
||||||
|
pub limit: i32,
|
||||||
|
pub next_offset: Option<i32>,
|
||||||
|
pub total: i32,
|
||||||
|
pub has_more: bool,
|
||||||
|
pub items: Vec<SpotubePaginationResponseObjectItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase", tag = "type_name")]
|
||||||
|
pub enum SpotubePaginationResponseObjectItem {
|
||||||
|
#[serde(rename = "track")]
|
||||||
|
Track(SpotubeTrackObject),
|
||||||
|
#[serde(rename = "playlist_full")]
|
||||||
|
PlaylistFull(SpotubeFullPlaylistObject),
|
||||||
|
#[serde(rename = "playlist_simple")]
|
||||||
|
PlaylistSimple(SpotubeSimplePlaylistObject),
|
||||||
|
#[serde(rename = "album_simple")]
|
||||||
|
AlbumSimple(SpotubeSimpleAlbumObject),
|
||||||
|
#[serde(rename = "album_full")]
|
||||||
|
AlbumFull(SpotubeFullAlbumObject),
|
||||||
|
#[serde(rename = "artist_full")]
|
||||||
|
ArtistFull(SpotubeFullArtistObject),
|
||||||
|
#[serde(rename = "artist_simple")]
|
||||||
|
ArtistSimple(SpotubeSimpleArtistObject),
|
||||||
|
#[serde(rename = "browse_section")]
|
||||||
|
BrowseSection(SpotubeBrowseSectionObject),
|
||||||
|
}
|
||||||
38
rust/src/api/plugin/models/playlist.rs
Normal file
38
rust/src/api/plugin/models/playlist.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::plugin::models::image::SpotubeImageObject;
|
||||||
|
use crate::api::plugin::models::user::SpotubeUserObject;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeSimplePlaylistObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
pub owner: SpotubeUserObject,
|
||||||
|
#[serde(default)]
|
||||||
|
pub images: Vec<SpotubeImageObject>, // @Default([])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeFullPlaylistObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
pub owner: SpotubeUserObject,
|
||||||
|
#[serde(default)]
|
||||||
|
pub images: Vec<SpotubeImageObject>, // @Default([])
|
||||||
|
#[serde(default)]
|
||||||
|
pub collaborators: Vec<SpotubeUserObject>, // @Default([])
|
||||||
|
#[serde(default)]
|
||||||
|
pub collaborative: bool, // @Default(false)
|
||||||
|
#[serde(default)]
|
||||||
|
pub public: bool, // @Default(false)
|
||||||
|
}
|
||||||
17
rust/src/api/plugin/models/search.rs
Normal file
17
rust/src/api/plugin/models/search.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::plugin::models::album::SpotubeSimpleAlbumObject;
|
||||||
|
use crate::api::plugin::models::artist::SpotubeFullArtistObject;
|
||||||
|
use crate::api::plugin::models::playlist::SpotubeSimplePlaylistObject;
|
||||||
|
use crate::api::plugin::models::track::SpotubeTrackObject;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeSearchResponseObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub albums: Vec<SpotubeSimpleAlbumObject>,
|
||||||
|
pub artists: Vec<SpotubeFullArtistObject>,
|
||||||
|
pub playlists: Vec<SpotubeSimplePlaylistObject>,
|
||||||
|
pub tracks: Vec<SpotubeTrackObject>,
|
||||||
|
}
|
||||||
20
rust/src/api/plugin/models/track.rs
Normal file
20
rust/src/api/plugin/models/track.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use crate::api::plugin::models::album::SpotubeSimpleAlbumObject;
|
||||||
|
use crate::api::plugin::models::artist::SpotubeSimpleArtistObject;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeTrackObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub external_uri: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub artists: Vec<SpotubeSimpleArtistObject>,
|
||||||
|
pub album: SpotubeSimpleAlbumObject,
|
||||||
|
pub duration_ms: u64, // Duration in ms
|
||||||
|
pub isrc: String,
|
||||||
|
pub explicit: bool,
|
||||||
|
}
|
||||||
15
rust/src/api/plugin/models/user.rs
Normal file
15
rust/src/api/plugin/models/user.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::plugin::models::image::SpotubeImageObject;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[frb(dart_metadata=("freezed"),json_serializable)]
|
||||||
|
pub struct SpotubeUserObject {
|
||||||
|
pub type_name: String,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub images: Vec<SpotubeImageObject>, // @Default([])
|
||||||
|
pub external_uri: String,
|
||||||
|
}
|
||||||
137
rust/src/api/plugin/plugin.rs
Normal file
137
rust/src/api/plugin/plugin.rs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
use crate::api::plugin::commands::PluginCommand;
|
||||||
|
use crate::api::plugin::executors::{
|
||||||
|
execute_albums, execute_artists, execute_audio_source, execute_auth, execute_browse,
|
||||||
|
execute_core, execute_playlist, execute_search, execute_track, execute_user,
|
||||||
|
};
|
||||||
|
use crate::api::plugin::models::core::PluginConfiguration;
|
||||||
|
use crate::api::plugin::senders::{
|
||||||
|
PluginAlbumSender, PluginArtistSender, PluginAudioSourceSender, PluginAuthSender,
|
||||||
|
PluginBrowseSender, PluginCoreSender, PluginPlaylistSender, PluginSearchSender,
|
||||||
|
PluginTrackSender, PluginUserSender,
|
||||||
|
};
|
||||||
|
use crate::internal::apis::fetcher::ReqwestFetcher;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{Context, Source};
|
||||||
|
use boa_runtime::{fetch, interval, microtask, text, Console, DefaultLogger};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use std::thread;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[frb(opaque)]
|
||||||
|
pub struct OpaqueSender {
|
||||||
|
pub sender: Sender<PluginCommand>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
async fn js_executor_thread(
|
||||||
|
plugin_script: String,
|
||||||
|
plugin_config: PluginConfiguration,
|
||||||
|
mut rx: mpsc::Receiver<PluginCommand>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let mut context = create_context()?;
|
||||||
|
let injection = format!(
|
||||||
|
"const pluginInstance = new {}();",
|
||||||
|
plugin_config.entry_point
|
||||||
|
);
|
||||||
|
let script = format!("{}\n{}", plugin_script, injection);
|
||||||
|
|
||||||
|
context
|
||||||
|
.eval(Source::from_bytes(script.as_bytes()))
|
||||||
|
.map_err(|e| anyhow!("{}", e))?;
|
||||||
|
|
||||||
|
while let Some(command) = rx.blocking_recv() {
|
||||||
|
match command {
|
||||||
|
PluginCommand::Artist(commands) => execute_artists(commands, &mut context).await?,
|
||||||
|
PluginCommand::Album(commands) => execute_albums(commands, &mut context).await?,
|
||||||
|
PluginCommand::AudioSource(commands) => {
|
||||||
|
execute_audio_source(commands, &mut context).await?
|
||||||
|
}
|
||||||
|
PluginCommand::Auth(commands) => execute_auth(commands, &mut context).await?,
|
||||||
|
PluginCommand::Browse(commands) => execute_browse(commands, &mut context).await?,
|
||||||
|
PluginCommand::Core(commands) => execute_core(commands, &mut context).await?,
|
||||||
|
PluginCommand::Playlist(commands) => execute_playlist(commands, &mut context).await?,
|
||||||
|
PluginCommand::Search(commands) => execute_search(commands, &mut context).await?,
|
||||||
|
PluginCommand::Track(commands) => execute_track(commands, &mut context).await?,
|
||||||
|
PluginCommand::User(commands) => execute_user(commands, &mut context).await?,
|
||||||
|
PluginCommand::Shutdown => {
|
||||||
|
println!("JS Executor thread shutting down.");
|
||||||
|
// This command doesn't send a response; break the loop instead.
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn create_context() -> anyhow::Result<Context> {
|
||||||
|
let mut context = Context::default();
|
||||||
|
Console::register_with_logger(DefaultLogger, &mut context).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
fetch::register(ReqwestFetcher::new(), None, &mut context).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
interval::register(&mut context).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
microtask::register(None, &mut context).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
text::register(None, &mut context).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
interval::register(&mut context).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
microtask::register(None, &mut context).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
|
||||||
|
Ok(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SpotubePlugin {
|
||||||
|
pub artist: PluginArtistSender,
|
||||||
|
pub album: PluginAlbumSender,
|
||||||
|
pub audio_source: PluginAudioSourceSender,
|
||||||
|
pub auth: PluginAuthSender,
|
||||||
|
pub browse: PluginBrowseSender,
|
||||||
|
pub core: PluginCoreSender,
|
||||||
|
pub playlist: PluginPlaylistSender,
|
||||||
|
pub search: PluginSearchSender,
|
||||||
|
pub track: PluginTrackSender,
|
||||||
|
pub user: PluginUserSender,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpotubePlugin {
|
||||||
|
#[frb(sync)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
artist: PluginArtistSender::new(),
|
||||||
|
album: PluginAlbumSender::new(),
|
||||||
|
audio_source: PluginAudioSourceSender::new(),
|
||||||
|
auth: PluginAuthSender::new(),
|
||||||
|
browse: PluginBrowseSender::new(),
|
||||||
|
core: PluginCoreSender::new(),
|
||||||
|
playlist: PluginPlaylistSender::new(),
|
||||||
|
search: PluginSearchSender::new(),
|
||||||
|
track: PluginTrackSender::new(),
|
||||||
|
user: PluginUserSender::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[frb(sync)]
|
||||||
|
pub fn new_context(
|
||||||
|
plugin_script: String,
|
||||||
|
plugin_config: PluginConfiguration,
|
||||||
|
) -> anyhow::Result<OpaqueSender> {
|
||||||
|
let (command_tx, command_rx) = mpsc::channel(32);
|
||||||
|
|
||||||
|
let _thread_handle = thread::spawn(|| {
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
rt.block_on(async {
|
||||||
|
if let Err(e) = js_executor_thread(plugin_script, plugin_config, command_rx).await {
|
||||||
|
eprintln!("JS Executor thread encountered a fatal error: {:?}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(OpaqueSender { sender: command_tx })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn dispose(&self, tx: OpaqueSender) -> anyhow::Result<()> {
|
||||||
|
tx.sender.send(PluginCommand::Shutdown).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
886
rust/src/api/plugin/senders.rs
Normal file
886
rust/src/api/plugin/senders.rs
Normal file
@ -0,0 +1,886 @@
|
|||||||
|
use crate::api::plugin::commands::{
|
||||||
|
AlbumCommands, ArtistCommands, AudioSourceCommands, AuthCommands, BrowseCommands, CoreCommands,
|
||||||
|
PlaylistCommands, PluginCommand, SearchCommands, TrackCommands, UserCommands,
|
||||||
|
};
|
||||||
|
use crate::api::plugin::models::album::SpotubeFullAlbumObject;
|
||||||
|
use crate::api::plugin::models::artist::SpotubeFullArtistObject;
|
||||||
|
use crate::api::plugin::models::audio_source::{
|
||||||
|
SpotubeAudioSourceMatchObject, SpotubeAudioSourceStreamObject,
|
||||||
|
};
|
||||||
|
use crate::api::plugin::models::core::{
|
||||||
|
PluginConfiguration, PluginUpdateAvailable, ScrobbleDetails,
|
||||||
|
};
|
||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
use crate::api::plugin::models::playlist::SpotubeFullPlaylistObject;
|
||||||
|
use crate::api::plugin::models::search::SpotubeSearchResponseObject;
|
||||||
|
use crate::api::plugin::models::track::SpotubeTrackObject;
|
||||||
|
use crate::api::plugin::models::user::SpotubeUserObject;
|
||||||
|
use crate::api::plugin::plugin::OpaqueSender;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use tokio::sync::oneshot;
|
||||||
|
|
||||||
|
pub struct PluginArtistSender {}
|
||||||
|
|
||||||
|
impl PluginArtistSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_artist(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
) -> anyhow::Result<SpotubeFullArtistObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Artist(ArtistCommands::GetArtist {
|
||||||
|
id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn top_tracks(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Artist(ArtistCommands::TopTracks {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn albums(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Artist(ArtistCommands::Albums {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn related(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Artist(ArtistCommands::Related {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&self, mpsc_tx: OpaqueSender, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Artist(ArtistCommands::Save {
|
||||||
|
ids,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&self, mpsc_tx: OpaqueSender, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Artist(ArtistCommands::Unsave {
|
||||||
|
ids,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginAlbumSender {}
|
||||||
|
|
||||||
|
impl PluginAlbumSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_album(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
) -> anyhow::Result<SpotubeFullAlbumObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Album(AlbumCommands::GetAlbum {
|
||||||
|
id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tracks(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Album(AlbumCommands::Tracks {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn releases(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Album(AlbumCommands::Releases {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&self, mpsc_tx: OpaqueSender, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Album(AlbumCommands::Save {
|
||||||
|
ids,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&self, mpsc_tx: OpaqueSender, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Album(AlbumCommands::Unsave {
|
||||||
|
ids,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginAudioSourceSender {}
|
||||||
|
|
||||||
|
impl PluginAudioSourceSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn matches(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
track: SpotubeTrackObject,
|
||||||
|
) -> anyhow::Result<Vec<SpotubeAudioSourceMatchObject>> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::AudioSource(AudioSourceCommands::Matches {
|
||||||
|
track,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn streams(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
matched: SpotubeAudioSourceMatchObject,
|
||||||
|
) -> anyhow::Result<Vec<SpotubeAudioSourceStreamObject>> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::AudioSource(AudioSourceCommands::Streams {
|
||||||
|
matched,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginAuthSender {}
|
||||||
|
|
||||||
|
impl PluginAuthSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn authenticate(&self, mpsc_tx: OpaqueSender) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Auth(AuthCommands::Authenticate {
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn logout(&self, mpsc_tx: OpaqueSender) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Auth(AuthCommands::Logout {
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn is_authenticated(&self, mpsc_tx: OpaqueSender) -> anyhow::Result<bool> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Auth(AuthCommands::IsAuthenticated {
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginBrowseSender {}
|
||||||
|
|
||||||
|
impl PluginBrowseSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn sections(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Browse(BrowseCommands::Sections {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn section_items(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Browse(BrowseCommands::SectionItems {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginCoreSender {}
|
||||||
|
|
||||||
|
impl PluginCoreSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check_update(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
plugin_config: PluginConfiguration,
|
||||||
|
) -> anyhow::Result<Option<PluginUpdateAvailable>> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Core(CoreCommands::CheckUpdate {
|
||||||
|
plugin_config,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn support(&self, mpsc_tx: OpaqueSender) -> anyhow::Result<String> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Core(CoreCommands::Support {
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn scrobble(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
details: ScrobbleDetails,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Core(CoreCommands::Scrobble {
|
||||||
|
details,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginPlaylistSender {}
|
||||||
|
|
||||||
|
impl PluginPlaylistSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_playlist(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
) -> anyhow::Result<SpotubeFullPlaylistObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::GetPlaylist {
|
||||||
|
id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tracks(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::Tracks {
|
||||||
|
id,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_playlist(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
user_id: String,
|
||||||
|
name: String,
|
||||||
|
description: Option<String>,
|
||||||
|
public: Option<bool>,
|
||||||
|
collaborative: Option<bool>,
|
||||||
|
) -> anyhow::Result<Option<SpotubeFullPlaylistObject>> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::CreatePlaylist {
|
||||||
|
user_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
public,
|
||||||
|
collaborative,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_playlist(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
playlist_id: String,
|
||||||
|
name: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
|
public: Option<bool>,
|
||||||
|
collaborative: Option<bool>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::UpdatePlaylist {
|
||||||
|
playlist_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
public,
|
||||||
|
collaborative,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_playlist(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
playlist_id: String,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::DeletePlaylist {
|
||||||
|
playlist_id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_tracks(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
playlist_id: String,
|
||||||
|
track_ids: Vec<String>,
|
||||||
|
position: Option<u32>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::AddTracks {
|
||||||
|
playlist_id,
|
||||||
|
track_ids,
|
||||||
|
position,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn remove_tracks(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
playlist_id: String,
|
||||||
|
track_ids: Vec<String>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::RemoveTracks {
|
||||||
|
playlist_id,
|
||||||
|
track_ids,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&self, mpsc_tx: OpaqueSender, playlist_id: String) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::Save {
|
||||||
|
playlist_id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&self, mpsc_tx: OpaqueSender, playlist_id: String) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Playlist(PlaylistCommands::Unsave {
|
||||||
|
playlist_id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginSearchSender {}
|
||||||
|
|
||||||
|
impl PluginSearchSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn chips(&self, mpsc_tx: OpaqueSender) -> anyhow::Result<Vec<String>> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Search(SearchCommands::Chips {
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn all(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
query: String,
|
||||||
|
) -> anyhow::Result<SpotubeSearchResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Search(SearchCommands::All {
|
||||||
|
query,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tracks(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Search(SearchCommands::Tracks {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn albums(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Search(SearchCommands::Albums {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn artists(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Search(SearchCommands::Artists {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn playlists(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Search(SearchCommands::Playlists {
|
||||||
|
query,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginTrackSender {}
|
||||||
|
|
||||||
|
impl PluginTrackSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_track(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
) -> anyhow::Result<SpotubeTrackObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Track(TrackCommands::GetTrack {
|
||||||
|
id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&self, mpsc_tx: OpaqueSender, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Track(TrackCommands::Save {
|
||||||
|
ids,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&self, mpsc_tx: OpaqueSender, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Track(TrackCommands::Unsave {
|
||||||
|
ids,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn radio(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
id: String,
|
||||||
|
) -> anyhow::Result<Vec<SpotubeTrackObject>> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::Track(TrackCommands::Radio {
|
||||||
|
id,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginUserSender {}
|
||||||
|
|
||||||
|
impl PluginUserSender {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn me(&self, mpsc_tx: OpaqueSender) -> anyhow::Result<SpotubeUserObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::User(UserCommands::Me { response_tx: tx }))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_tracks(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::User(UserCommands::SavedTracks {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_albums(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::User(UserCommands::SavedAlbums {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_artists(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::User(UserCommands::SavedArtists {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_playlists(
|
||||||
|
&self,
|
||||||
|
mpsc_tx: OpaqueSender,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
mpsc_tx
|
||||||
|
.sender
|
||||||
|
.send(PluginCommand::User(UserCommands::SavedPlaylists {
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
response_tx: tx,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
rx.await.map_err(|e| anyhow!("{e}")).and_then(|o| o)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +0,0 @@
|
|||||||
#[flutter_rust_bridge::frb(sync)] // Synchronous mode for simplicity of the demo
|
|
||||||
pub fn greet(name: String) -> String {
|
|
||||||
format!("Hello, {name}!")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[flutter_rust_bridge::frb(init)]
|
|
||||||
pub fn init_app() {
|
|
||||||
// Default utilities - feel free to customize
|
|
||||||
flutter_rust_bridge::setup_default_user_utils();
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
148
rust/src/internal/album.rs
Normal file
148
rust/src/internal/album.rs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
use crate::api::plugin::models::album::SpotubeFullAlbumObject;
|
||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginAlbumEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginAlbumEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginAlbumEndpoint<'a> {
|
||||||
|
PluginAlbumEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn album_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("album"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("album not found: \n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_album(&mut self, id: String) -> anyhow::Result<SpotubeFullAlbumObject> {
|
||||||
|
let album_val = self.album_obj()?;
|
||||||
|
let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let get_album_fn = album_object
|
||||||
|
.get(js_string!("getAlbum"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing getAlbum: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("getAlbum is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(id))];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(get_album_fn.call(&album_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tracks(
|
||||||
|
&mut self,
|
||||||
|
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let album_val = self.album_obj()?;
|
||||||
|
let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let tracks_fn = album_object
|
||||||
|
.get(js_string!("tracks"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing tracks: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("tracks is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(id)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(tracks_fn.call(&album_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn releases(
|
||||||
|
&mut self,
|
||||||
|
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let album_val = self.album_obj()?;
|
||||||
|
let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let releases_fn = album_object
|
||||||
|
.get(js_string!("releases"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing releases: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("releases is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 2] = [
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(releases_fn.call(&album_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&mut self, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let album_val = self.album_obj()?;
|
||||||
|
let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let save_fn = album_object
|
||||||
|
.get(js_string!("save"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing save: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("save is not a function"))?;
|
||||||
|
|
||||||
|
let ids_val = utils::vec_string_to_js_array(ids, self.0)?;
|
||||||
|
let args = [ids_val.into()];
|
||||||
|
|
||||||
|
utils::js_call_to_void(save_fn.call(&album_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&mut self, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let album_val = self.album_obj()?;
|
||||||
|
let album_object = album_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let unsave_fn = album_object
|
||||||
|
.get(js_string!("unsave"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing save: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("save is not a function"))?;
|
||||||
|
|
||||||
|
let ids_val = utils::vec_string_to_js_array(ids, self.0)?;
|
||||||
|
let args = [ids_val.into()];
|
||||||
|
|
||||||
|
utils::js_call_to_void(unsave_fn.call(&album_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
59
rust/src/internal/apis/fetcher.rs
Normal file
59
rust/src/internal/apis/fetcher.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use boa_engine::{Context, Finalize, JsData, JsResult, Trace};
|
||||||
|
use boa_runtime::fetch::{request::JsRequest, response::JsResponse, Fetcher};
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Trace, Finalize, JsData)]
|
||||||
|
pub struct ReqwestFetcher {
|
||||||
|
#[unsafe_ignore_trace]
|
||||||
|
client: reqwest::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReqwestFetcher {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ReqwestFetcher {
|
||||||
|
client: reqwest::Client::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Fetcher for ReqwestFetcher {
|
||||||
|
async fn fetch(
|
||||||
|
self: Rc<Self>,
|
||||||
|
request: JsRequest,
|
||||||
|
_context: &RefCell<&mut Context>,
|
||||||
|
) -> JsResult<JsResponse> {
|
||||||
|
use boa_engine::{JsError, JsString};
|
||||||
|
|
||||||
|
let request = request.into_inner();
|
||||||
|
let method = request.method().clone();
|
||||||
|
let url = request.uri().to_string();
|
||||||
|
let req = self
|
||||||
|
.client
|
||||||
|
.request(method, &url)
|
||||||
|
.headers(request.headers().clone());
|
||||||
|
|
||||||
|
let req = req
|
||||||
|
.body(request.body().clone())
|
||||||
|
.build()
|
||||||
|
.map_err(JsError::from_rust)?;
|
||||||
|
|
||||||
|
let resp = self.client.execute(req).await.map_err(JsError::from_rust)?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let headers = resp.headers().clone();
|
||||||
|
let bytes = resp.bytes().await.map_err(JsError::from_rust)?;
|
||||||
|
let mut builder = http::Response::builder().status(status.as_u16());
|
||||||
|
|
||||||
|
for k in headers.keys() {
|
||||||
|
for v in headers.get_all(k) {
|
||||||
|
builder = builder.header(k.as_str(), v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.body(bytes.to_vec())
|
||||||
|
.map_err(JsError::from_rust)
|
||||||
|
.map(|request| JsResponse::basic(JsString::from(url), request))
|
||||||
|
}
|
||||||
|
}
|
||||||
1
rust/src/internal/apis/mod.rs
Normal file
1
rust/src/internal/apis/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod fetcher;
|
||||||
180
rust/src/internal/artist.rs
Normal file
180
rust/src/internal/artist.rs
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
use crate::api::plugin::models::artist::SpotubeFullArtistObject;
|
||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginArtistEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginArtistEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginArtistEndpoint<'a> {
|
||||||
|
PluginArtistEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn artist_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
return plugin_instance
|
||||||
|
.get(js_string!("artist"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("artist not found: \n{}", e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_artist(&mut self, id: String) -> anyhow::Result<SpotubeFullArtistObject> {
|
||||||
|
let artist_val = self.artist_obj()?;
|
||||||
|
let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let get_artist_fn = artist_object
|
||||||
|
.get(js_string!("getArtist"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing getArtist: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("getArtist is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(id))];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(get_artist_fn.call(&artist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn top_tracks(
|
||||||
|
&mut self,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let artist_val = self.artist_obj()?;
|
||||||
|
let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let top_tracks_fn = artist_object
|
||||||
|
.get(js_string!("topTracks"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing getArtist: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("getArtist is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(id)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(top_tracks_fn.call(&artist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn albums(
|
||||||
|
&mut self,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let artist_val = self.artist_obj()?;
|
||||||
|
let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let albums_fn = artist_object
|
||||||
|
.get(js_string!("albums"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing albums: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("albums is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(id)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(albums_fn.call(&artist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn related(
|
||||||
|
&mut self,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let artist_val = self.artist_obj()?;
|
||||||
|
let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let related_fn = artist_object
|
||||||
|
.get(js_string!("related"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing related: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("related is not a function"))?;
|
||||||
|
|
||||||
|
let args = [
|
||||||
|
JsValue::from(js_string!(id)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(related_fn.call(&artist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&mut self, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let artist_val = self.artist_obj()?;
|
||||||
|
let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let save_fn = artist_object
|
||||||
|
.get(js_string!("save"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing save: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("save is not a function"))?;
|
||||||
|
|
||||||
|
let ids_val = utils::vec_string_to_js_array(ids, self.0)?;
|
||||||
|
let args = [ids_val.into()];
|
||||||
|
|
||||||
|
utils::js_call_to_void(save_fn.call(&artist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&mut self, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let artist_val = self.artist_obj()?;
|
||||||
|
let artist_object = artist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let unsave_fn = artist_object
|
||||||
|
.get(js_string!("unsave"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing save: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("save is not a function"))?;
|
||||||
|
|
||||||
|
let ids_val = utils::vec_string_to_js_array(ids, self.0)?;
|
||||||
|
let args = [ids_val.into()];
|
||||||
|
|
||||||
|
utils::js_call_to_void(unsave_fn.call(&artist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
81
rust/src/internal/audio_source.rs
Normal file
81
rust/src/internal/audio_source.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use crate::api::plugin::models::audio_source::{
|
||||||
|
SpotubeAudioSourceMatchObject, SpotubeAudioSourceStreamObject,
|
||||||
|
};
|
||||||
|
use crate::api::plugin::models::track::SpotubeTrackObject;
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginAudioSourceEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginAudioSourceEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginAudioSourceEndpoint<'a> {
|
||||||
|
PluginAudioSourceEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn audio_source_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("audioSource"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("artist not found: \n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn matches(
|
||||||
|
&mut self,
|
||||||
|
track: SpotubeTrackObject,
|
||||||
|
) -> anyhow::Result<Vec<SpotubeAudioSourceMatchObject>> {
|
||||||
|
let audio_source_val = self.audio_source_obj()?;
|
||||||
|
let audio_source_object = audio_source_val
|
||||||
|
.as_object()
|
||||||
|
.ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let matches_fn = audio_source_object
|
||||||
|
.get(js_string!("matches"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing matches: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("matches is not a function"))?;
|
||||||
|
|
||||||
|
let value = serde_json::to_value(track)?;
|
||||||
|
let track_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let args = [track_val];
|
||||||
|
|
||||||
|
let res =
|
||||||
|
utils::js_call_to_json(matches_fn.call(&audio_source_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn streams(
|
||||||
|
&mut self,
|
||||||
|
matched: SpotubeAudioSourceMatchObject,
|
||||||
|
) -> anyhow::Result<Vec<SpotubeAudioSourceStreamObject>> {
|
||||||
|
let audio_source_val = self.audio_source_obj()?;
|
||||||
|
let audio_source_object = audio_source_val
|
||||||
|
.as_object()
|
||||||
|
.ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let matches_fn = audio_source_object
|
||||||
|
.get(js_string!("streams"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing matches: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("matches is not a function"))?;
|
||||||
|
|
||||||
|
let value = serde_json::to_value(matched)?;
|
||||||
|
let matched_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let args = [matched_val];
|
||||||
|
|
||||||
|
let res =
|
||||||
|
utils::js_call_to_json(matches_fn.call(&audio_source_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
74
rust/src/internal/auth.rs
Normal file
74
rust/src/internal/auth.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginAuthEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginAuthEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginAuthEndpoint<'a> {
|
||||||
|
PluginAuthEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn auth_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
return plugin_instance
|
||||||
|
.get(js_string!("auth"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("auth not found:\n{}", e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn authenticate(&mut self) -> anyhow::Result<()> {
|
||||||
|
let auth_val = self.auth_obj()?;
|
||||||
|
let auth_object = auth_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let authenticate_fn = auth_object
|
||||||
|
.get(js_string!("authenticate"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing authenticate: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("authenticate is not a function"))?;
|
||||||
|
|
||||||
|
let args = [];
|
||||||
|
|
||||||
|
utils::js_call_to_void(authenticate_fn.call(&auth_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_authenticated(&mut self) -> anyhow::Result<bool> {
|
||||||
|
let auth_val = self.auth_obj()?;
|
||||||
|
let auth_object = auth_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let authenticate_fn = auth_object
|
||||||
|
.get(js_string!("is_authenticated"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing authenticate: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("authenticate is not a function"))?;
|
||||||
|
|
||||||
|
authenticate_fn
|
||||||
|
.call(&auth_val, &[], self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_boolean()
|
||||||
|
.ok_or(anyhow!("Not a boolean"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn logout(&mut self) -> anyhow::Result<()> {
|
||||||
|
let auth_val = self.auth_obj()?;
|
||||||
|
let auth_object = auth_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let logout_fn = auth_object
|
||||||
|
.get(js_string!("logout"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing authenticate: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("authenticate is not a function"))?;
|
||||||
|
|
||||||
|
let args = [];
|
||||||
|
|
||||||
|
utils::js_call_to_void(logout_fn.call(&auth_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
91
rust/src/internal/browse.rs
Normal file
91
rust/src/internal/browse.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginBrowseEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginBrowseEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginBrowseEndpoint<'a> {
|
||||||
|
PluginBrowseEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn browse_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("browse"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("browse not found:\n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn sections(
|
||||||
|
&mut self,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let browse_val = self.browse_obj()?;
|
||||||
|
let browse_object = browse_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let sections_fn = browse_object
|
||||||
|
.get(js_string!("sections"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing sections: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("sections is not a function"))?;
|
||||||
|
|
||||||
|
let args = [
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res = utils::js_call_to_json(sections_fn.call(&browse_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn section_items(
|
||||||
|
&mut self,
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let browse_val = self.browse_obj()?;
|
||||||
|
let browse_object = browse_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let section_items_fn = browse_object
|
||||||
|
.get(js_string!("sectionItems"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing sectionItems: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("sectionItems is not a function"))?;
|
||||||
|
|
||||||
|
let args = [
|
||||||
|
JsValue::from(js_string!(id)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res =
|
||||||
|
utils::js_call_to_json(section_items_fn.call(&browse_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
86
rust/src/internal/core.rs
Normal file
86
rust/src/internal/core.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use crate::api::plugin::models::core::{PluginConfiguration, PluginUpdateAvailable, ScrobbleDetails};
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginCoreEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginCoreEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginCoreEndpoint<'a> {
|
||||||
|
PluginCoreEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn core_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("core"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("core not found:\n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check_update(
|
||||||
|
&mut self,
|
||||||
|
plugin_config: PluginConfiguration,
|
||||||
|
) -> anyhow::Result<Option<PluginUpdateAvailable>> {
|
||||||
|
let core_val = self.core_obj()?;
|
||||||
|
let core_object = core_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let check_update_fn = core_object
|
||||||
|
.get(js_string!("checkUpdate"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing checkUpdate: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("checkUpdate is not a function"))?;
|
||||||
|
|
||||||
|
let value = serde_json::to_value(plugin_config)?;
|
||||||
|
let config_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let args = [config_val];
|
||||||
|
|
||||||
|
let res = utils::js_call_to_json(check_update_fn.call(&core_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
if res.is_null() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
serde_json::from_value(res).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn support(&mut self) -> anyhow::Result<String> {
|
||||||
|
let core_val = self.core_obj()?;
|
||||||
|
let core_object = core_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let support_val = core_object
|
||||||
|
.get(js_string!("support"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing support: {}", e))?;
|
||||||
|
|
||||||
|
support_val
|
||||||
|
.as_string()
|
||||||
|
.ok_or(anyhow!("support is not a string"))?
|
||||||
|
.to_std_string()
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn scrobble(&mut self, details: ScrobbleDetails) -> anyhow::Result<()> {
|
||||||
|
let core_val = self.core_obj()?;
|
||||||
|
let core_object = core_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let scrobble_fn = core_object
|
||||||
|
.get(js_string!("scrobble"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing scrobble: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("scrobble is not a function"))?;
|
||||||
|
|
||||||
|
let value = serde_json::to_value(details)?;
|
||||||
|
let details_val = utils::json_value_to_js(&value, self.0).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let args = [details_val];
|
||||||
|
|
||||||
|
utils::js_call_to_void(scrobble_fn.call(&core_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
rust/src/internal/mod.rs
Normal file
13
rust/src/internal/mod.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pub mod album;
|
||||||
|
pub mod apis;
|
||||||
|
pub mod artist;
|
||||||
|
pub mod audio_source;
|
||||||
|
pub mod browse;
|
||||||
|
pub mod core;
|
||||||
|
pub mod playlist;
|
||||||
|
pub mod search;
|
||||||
|
pub mod track;
|
||||||
|
pub mod user;
|
||||||
|
pub mod auth;
|
||||||
|
mod utils;
|
||||||
|
// Export Context
|
||||||
268
rust/src/internal/playlist.rs
Normal file
268
rust/src/internal/playlist.rs
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
use crate::api::plugin::models::playlist::SpotubeFullPlaylistObject;
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginPlaylistEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginPlaylistEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginPlaylistEndpoint<'a> {
|
||||||
|
PluginPlaylistEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn playlist_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("playlist"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("playlist not found: \n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_playlist(&mut self, id: String) -> anyhow::Result<SpotubeFullPlaylistObject> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let get_playlist_fn = playlist_object
|
||||||
|
.get(js_string!("getPlaylist"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("getPlaylist is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(id))];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(get_playlist_fn.call(&playlist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tracks(
|
||||||
|
&mut self,
|
||||||
|
|
||||||
|
id: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let tracks_fn = playlist_object
|
||||||
|
.get(js_string!("tracks"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("tracks is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(id)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(tracks_fn.call(&playlist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create(
|
||||||
|
&mut self,
|
||||||
|
|
||||||
|
user_id: String,
|
||||||
|
name: String,
|
||||||
|
description: Option<String>,
|
||||||
|
public: Option<bool>,
|
||||||
|
collaborative: Option<bool>,
|
||||||
|
) -> anyhow::Result<Option<SpotubeFullPlaylistObject>> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let create_fn = playlist_object
|
||||||
|
.get(js_string!("create"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("create is not a function"))?;
|
||||||
|
|
||||||
|
let args = [
|
||||||
|
JsValue::from(js_string!(user_id)),
|
||||||
|
JsValue::from(js_string!(name)),
|
||||||
|
match description {
|
||||||
|
Some(o) => JsValue::from(js_string!(o)),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match public {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match collaborative {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(create_fn.call(&playlist_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
if res_json.is_null() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
serde_json::from_value(res_json)
|
||||||
|
.map(Some)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update(
|
||||||
|
&mut self,
|
||||||
|
|
||||||
|
playlist_id: String,
|
||||||
|
name: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
|
public: Option<bool>,
|
||||||
|
collaborative: Option<bool>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let update_fn = playlist_object
|
||||||
|
.get(js_string!("update"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("update is not a function"))?;
|
||||||
|
|
||||||
|
let args = [
|
||||||
|
JsValue::from(js_string!(playlist_id)),
|
||||||
|
match name {
|
||||||
|
Some(o) => JsValue::from(js_string!(o)),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match description {
|
||||||
|
Some(o) => JsValue::from(js_string!(o)),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match public {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match collaborative {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
utils::js_call_to_void(update_fn.call(&playlist_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_tracks(
|
||||||
|
&mut self,
|
||||||
|
|
||||||
|
playlist_id: String,
|
||||||
|
track_ids: Vec<String>,
|
||||||
|
position: Option<u32>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let add_tracks_fn = playlist_object
|
||||||
|
.get(js_string!("addTracks"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("addTracks is not a function"))?;
|
||||||
|
|
||||||
|
let args = [
|
||||||
|
JsValue::from(js_string!(playlist_id)),
|
||||||
|
utils::vec_string_to_js_array(track_ids, self.0)?,
|
||||||
|
match position {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
utils::js_call_to_void(add_tracks_fn.call(&playlist_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn remove_tracks(
|
||||||
|
&mut self,
|
||||||
|
|
||||||
|
playlist_id: String,
|
||||||
|
track_ids: Vec<String>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let remove_tracks_fn = playlist_object
|
||||||
|
.get(js_string!("removeTracks"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("removeTracks is not a function"))?;
|
||||||
|
|
||||||
|
let args = [
|
||||||
|
JsValue::from(js_string!(playlist_id)),
|
||||||
|
utils::vec_string_to_js_array(track_ids, self.0)?,
|
||||||
|
];
|
||||||
|
|
||||||
|
utils::js_call_to_void(remove_tracks_fn.call(&playlist_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&mut self, playlist_id: String) -> anyhow::Result<()> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let save_fn = playlist_object
|
||||||
|
.get(js_string!("save"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("save is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(playlist_id))];
|
||||||
|
|
||||||
|
utils::js_call_to_void(save_fn.call(&playlist_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&mut self, playlist_id: String) -> anyhow::Result<()> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let unsave_fn = playlist_object
|
||||||
|
.get(js_string!("unsave"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("unsave is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(playlist_id))];
|
||||||
|
|
||||||
|
utils::js_call_to_void(unsave_fn.call(&playlist_val, &args, self.0), self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_playlist(&mut self, playlist_id: String) -> anyhow::Result<()> {
|
||||||
|
let playlist_val = self.playlist_obj()?;
|
||||||
|
let playlist_object = playlist_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let delete_playlist_fn = playlist_object
|
||||||
|
.get(js_string!("deletePlaylist"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("deletePlaylist is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(playlist_id))];
|
||||||
|
|
||||||
|
utils::js_call_to_void(
|
||||||
|
delete_playlist_fn.call(&playlist_val, &args, self.0),
|
||||||
|
self.0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
201
rust/src/internal/search.rs
Normal file
201
rust/src/internal/search.rs
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
use crate::api::plugin::models::search::SpotubeSearchResponseObject;
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::object::builtins::JsArray;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginSearchEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginSearchEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginSearchEndpoint<'a> {
|
||||||
|
PluginSearchEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("search"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("search not found: \n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chips(&mut self) -> anyhow::Result<Vec<String>> {
|
||||||
|
let search_val = self.search_obj()?;
|
||||||
|
let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let chips_val = search_object
|
||||||
|
.get(js_string!("chips"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let chips_obj = chips_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
if !chips_obj.is_array() {
|
||||||
|
return Err(anyhow!("chips is not an array"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let chips_array = JsArray::from_object(chips_obj.clone()).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let length = chips_array.length(self.0).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let mut result = Vec::new();
|
||||||
|
for i in 0..length {
|
||||||
|
let item = chips_array.get(i, self.0).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
if let Some(s) = item.as_string() {
|
||||||
|
result.push(s.to_std_string().map_err(|e| anyhow!("{}", e))?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn all(&mut self, query: String) -> anyhow::Result<SpotubeSearchResponseObject> {
|
||||||
|
let search_val = self.search_obj()?;
|
||||||
|
let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let all_fn = search_object
|
||||||
|
.get(js_string!("all"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("all is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(query))];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(all_fn.call(&search_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn albums(
|
||||||
|
&mut self,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let search_val = self.search_obj()?;
|
||||||
|
let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let albums_fn = search_object
|
||||||
|
.get(js_string!("albums"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("albums is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(query)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(albums_fn.call(&search_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn artists(
|
||||||
|
&mut self,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let search_val = self.search_obj()?;
|
||||||
|
let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let artists_fn = search_object
|
||||||
|
.get(js_string!("artists"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("artists is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(query)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(artists_fn.call(&search_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn playlists(
|
||||||
|
&mut self,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let search_val = self.search_obj()?;
|
||||||
|
let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let playlists_fn = search_object
|
||||||
|
.get(js_string!("playlists"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("playlists is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(query)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(playlists_fn.call(&search_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tracks(
|
||||||
|
&mut self,
|
||||||
|
query: String,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let search_val = self.search_obj()?;
|
||||||
|
let search_object = search_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let tracks_fn = search_object
|
||||||
|
.get(js_string!("tracks"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("tracks is not a function"))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 3] = [
|
||||||
|
JsValue::from(js_string!(query)),
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(tracks_fn.call(&search_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
100
rust/src/internal/track.rs
Normal file
100
rust/src/internal/track.rs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
use crate::api::plugin::models::track::SpotubeTrackObject;
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginTrackEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginTrackEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginTrackEndpoint<'a> {
|
||||||
|
PluginTrackEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn track_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("track"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("track not found: \n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_track(&mut self, id: String) -> anyhow::Result<SpotubeTrackObject> {
|
||||||
|
let track_val = self.track_obj()?;
|
||||||
|
let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let get_track_fn = track_object
|
||||||
|
.get(js_string!("getTrack"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing getTrack: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("getTrack is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(id))];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(get_track_fn.call(&track_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&mut self, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let track_val = self.track_obj()?;
|
||||||
|
let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let save_fn = track_object
|
||||||
|
.get(js_string!("save"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing save: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("save is not a function"))?;
|
||||||
|
|
||||||
|
let ids_val = utils::vec_string_to_js_array(ids, self.0)?;
|
||||||
|
let args = [ids_val.into()];
|
||||||
|
|
||||||
|
utils::js_call_to_void(save_fn.call(&track_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn unsave(&mut self, ids: Vec<String>) -> anyhow::Result<()> {
|
||||||
|
let track_val = self.track_obj()?;
|
||||||
|
let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let unsave_fn = track_object
|
||||||
|
.get(js_string!("unsave"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing save: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("save is not a function"))?;
|
||||||
|
|
||||||
|
let ids_val = utils::vec_string_to_js_array(ids, self.0)?;
|
||||||
|
let args = [ids_val.into()];
|
||||||
|
|
||||||
|
utils::js_call_to_void(unsave_fn.call(&track_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn radio(&mut self, id: String) -> anyhow::Result<Vec<SpotubeTrackObject>> {
|
||||||
|
let track_val = self.track_obj()?;
|
||||||
|
let track_object = track_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let get_track_fn = track_object
|
||||||
|
.get(js_string!("radio"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing radio: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("radio is not a function"))?;
|
||||||
|
|
||||||
|
let args = [JsValue::from(js_string!(id))];
|
||||||
|
|
||||||
|
let res_json =
|
||||||
|
utils::js_call_to_json(get_track_fn.call(&track_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
107
rust/src/internal/user.rs
Normal file
107
rust/src/internal/user.rs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
use crate::api::plugin::models::pagination::SpotubePaginationResponseObject;
|
||||||
|
use crate::internal::utils;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::{js_string, Context, JsValue};
|
||||||
|
use flutter_rust_bridge::frb;
|
||||||
|
use crate::api::plugin::models::user::SpotubeUserObject;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PluginUserEndpoint<'a>(&'a mut Context);
|
||||||
|
|
||||||
|
impl<'a> PluginUserEndpoint<'a> {
|
||||||
|
#[frb(ignore)]
|
||||||
|
pub fn new(context: &'a mut Context) -> PluginUserEndpoint<'a> {
|
||||||
|
PluginUserEndpoint(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn user_obj(&mut self) -> anyhow::Result<JsValue> {
|
||||||
|
let global = self.0.global_object();
|
||||||
|
|
||||||
|
let plugin_instance = global
|
||||||
|
.get(js_string!("pluginInstance"), self.0)
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|a| a.as_object().ok_or(anyhow!("Not an object")))?;
|
||||||
|
|
||||||
|
plugin_instance
|
||||||
|
.get(js_string!("user"), self.0)
|
||||||
|
.or_else(|e| Err(anyhow!("user not found: \n{}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn me(&mut self) -> anyhow::Result<SpotubeUserObject> {
|
||||||
|
let user_val = self.user_obj()?;
|
||||||
|
let user_object = user_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let me_fn = user_object
|
||||||
|
.get(js_string!("me"), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing me: {}", e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("me is not a function"))?;
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(me_fn.call(&user_val, &[], self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_saved(
|
||||||
|
&mut self,
|
||||||
|
method: &str,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
let user_val = self.user_obj()?;
|
||||||
|
let user_object = user_val.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
let saved_fn = user_object
|
||||||
|
.get(js_string!(method), self.0)
|
||||||
|
.map_err(|e| anyhow!("JS error while accessing {}: {}", method, e))?
|
||||||
|
.as_function()
|
||||||
|
.ok_or(anyhow!("{} is not a function", method))?;
|
||||||
|
|
||||||
|
let args: [JsValue; 2] = [
|
||||||
|
match offset {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
match limit {
|
||||||
|
Some(o) => JsValue::from(o),
|
||||||
|
None => JsValue::undefined(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res_json = utils::js_call_to_json(saved_fn.call(&user_val, &args, self.0), self.0)?;
|
||||||
|
|
||||||
|
serde_json::from_value(res_json).map_err(|e| anyhow!("{}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_playlists(
|
||||||
|
&mut self,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
self.get_saved("savedPlaylists", offset, limit).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_tracks(
|
||||||
|
&mut self,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
self.get_saved("savedTracks", offset, limit).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_albums(
|
||||||
|
&mut self,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
self.get_saved("savedAlbums", offset, limit).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn saved_artists(
|
||||||
|
&mut self,
|
||||||
|
offset: Option<u32>,
|
||||||
|
limit: Option<u32>,
|
||||||
|
) -> anyhow::Result<SpotubePaginationResponseObject> {
|
||||||
|
self.get_saved("savedArtists", offset, limit).await
|
||||||
|
}
|
||||||
|
}
|
||||||
166
rust/src/internal/utils.rs
Normal file
166
rust/src/internal/utils.rs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
use boa_engine::property::PropertyKey;
|
||||||
|
use boa_engine::{
|
||||||
|
object::builtins::JsArray, Context, JsObject, JsResult, JsString, JsValue,
|
||||||
|
};
|
||||||
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
|
pub fn vec_string_to_js_array(
|
||||||
|
rust_vec: Vec<String>,
|
||||||
|
context: &mut Context,
|
||||||
|
) -> anyhow::Result<JsValue> {
|
||||||
|
let builder = JsArray::new(context);
|
||||||
|
|
||||||
|
for (index, rust_string) in rust_vec.into_iter().enumerate() {
|
||||||
|
let js_string_value = JsString::from(rust_string);
|
||||||
|
builder
|
||||||
|
.set(index as u32, js_string_value, true, context)
|
||||||
|
.map_err(|e| anyhow::anyhow!(e.to_string()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(builder.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn js_call_to_string(
|
||||||
|
result: JsResult<JsValue>,
|
||||||
|
context: &mut Context,
|
||||||
|
) -> anyhow::Result<String> {
|
||||||
|
let res = result
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|f| f.as_promise().ok_or(anyhow!("Not a promise")))?
|
||||||
|
.await_blocking(context)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?
|
||||||
|
.as_string()
|
||||||
|
.ok_or(anyhow!("No response string returned"))?
|
||||||
|
.to_std_string()
|
||||||
|
.map_err(|e| anyhow!("{}", e))?;
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn js_call_to_json(result: JsResult<JsValue>, context: &mut Context) -> anyhow::Result<Value> {
|
||||||
|
let res = result
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|f| f.as_promise().ok_or(anyhow!("Not a promise")))?
|
||||||
|
.await_blocking(context)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let ls = js_value_to_json(&res, context)?;
|
||||||
|
Ok(ls)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn js_call_to_void(result: JsResult<JsValue>, context: &mut Context) -> anyhow::Result<()> {
|
||||||
|
result
|
||||||
|
.map_err(|e| anyhow!("{}", e))
|
||||||
|
.and_then(|f| f.as_promise().ok_or(anyhow!("Not a promise")))?
|
||||||
|
.await_blocking(context)
|
||||||
|
.map_err(|e| anyhow!("{}", e))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a `serde_json::Value` into a Boa `JsValue`
|
||||||
|
pub fn json_value_to_js(value: &Value, ctx: &mut Context) -> JsResult<JsValue> {
|
||||||
|
match value {
|
||||||
|
Value::Null => Ok(JsValue::null()),
|
||||||
|
Value::Bool(b) => Ok(JsValue::from(*b)),
|
||||||
|
Value::Number(n) => {
|
||||||
|
if let Some(i) = n.as_i64() {
|
||||||
|
Ok(JsValue::new(i))
|
||||||
|
} else if let Some(f) = n.as_f64() {
|
||||||
|
Ok(JsValue::new(f))
|
||||||
|
} else {
|
||||||
|
Ok(JsValue::null()) // fallback (rare)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::String(s) => Ok(JsValue::from(JsString::from(s.as_str()))),
|
||||||
|
|
||||||
|
Value::Array(arr) => {
|
||||||
|
let js_arr = JsArray::new(ctx);
|
||||||
|
for (idx, item) in arr.iter().enumerate() {
|
||||||
|
let js_val = json_value_to_js(item, ctx)?;
|
||||||
|
js_arr.set(idx, js_val, false, ctx)?;
|
||||||
|
}
|
||||||
|
Ok(JsValue::from(js_arr))
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Object(obj) => {
|
||||||
|
let js_obj = JsObject::with_null_proto();
|
||||||
|
|
||||||
|
for (key, val) in obj {
|
||||||
|
let js_val = json_value_to_js(val, ctx)?;
|
||||||
|
js_obj.set(JsString::from(key.as_str()), js_val, true, ctx)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(JsValue::from(js_obj))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Boa `JsValue` into a `serde_json::Value`
|
||||||
|
pub fn js_value_to_json(value: &JsValue, ctx: &mut Context) -> anyhow::Result<Value> {
|
||||||
|
if value.is_null() || value.is_undefined() {
|
||||||
|
return Ok(Value::Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(b) = value.as_boolean() {
|
||||||
|
return Ok(Value::Bool(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(n) = value.as_number() {
|
||||||
|
let num = serde_json::Number::from_f64(n).ok_or(anyhow!("Invalid number"))?;
|
||||||
|
return Ok(Value::Number(num));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(s) = value.as_string() {
|
||||||
|
let s = s.to_std_string().map_err(|e| anyhow!("{}", e))?;
|
||||||
|
return Ok(Value::String(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.is_bigint() {
|
||||||
|
// BigInts are NOT JSON-compatible → store as string
|
||||||
|
return Ok(Value::String(value.display().to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.is_object() {
|
||||||
|
let obj = value.as_object().ok_or(anyhow!("Not an object"))?;
|
||||||
|
|
||||||
|
// Array?
|
||||||
|
if obj.is_array() {
|
||||||
|
let obj = JsArray::from_object(obj).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let length = obj.length(ctx).map_err(|e| anyhow!("{}", e))?;
|
||||||
|
let mut json_arr = Vec::<Value>::with_capacity(length as usize);
|
||||||
|
|
||||||
|
for i in 0..length {
|
||||||
|
let item = obj.get(i, ctx).unwrap_or(JsValue::null());
|
||||||
|
let item_json = js_value_to_json(&item, ctx)?;
|
||||||
|
json_arr.push(item_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Value::Array(json_arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular Object
|
||||||
|
let mut map = Map::<String, Value>::new();
|
||||||
|
|
||||||
|
for key in obj.own_property_keys(ctx).map_err(|e| anyhow!("{}", e))? {
|
||||||
|
let key_val: Option<String> = match key.clone() {
|
||||||
|
PropertyKey::String(s) => Some(s.to_std_string().map_err(|e| anyhow!("{}", e))?),
|
||||||
|
PropertyKey::Index(i) => Some(serde_json::Number::from(i.get()).to_string()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let v_js = obj.get(key, ctx).unwrap_or(JsValue::null());
|
||||||
|
let v_json = js_value_to_json(&v_js, ctx)?;
|
||||||
|
|
||||||
|
if let Some(key_val) = key_val {
|
||||||
|
map.insert(key_val, v_json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Value::Object(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback for unsupported JS types: functions, symbols, etc.
|
||||||
|
Ok(Value::Null)
|
||||||
|
}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
pub mod api;
|
pub mod api;
|
||||||
mod frb_generated;
|
mod frb_generated;
|
||||||
|
mod internal;
|
||||||
48
rust/src/main.rs
Normal file
48
rust/src/main.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
pub mod api;
|
||||||
|
pub mod internal;
|
||||||
|
pub mod frb_generated;
|
||||||
|
use api::plugin::models::core::{PluginAbility, PluginConfiguration};
|
||||||
|
use api::plugin::plugin::SpotubePlugin;
|
||||||
|
|
||||||
|
const PLUGIN_JS: &str = "\
|
||||||
|
class Core {
|
||||||
|
async checkUpdate() {
|
||||||
|
console.log('Core checkUpdate');
|
||||||
|
}
|
||||||
|
support() {
|
||||||
|
return 'Metadata';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestingPlugin {
|
||||||
|
constructor() {
|
||||||
|
this.core = new Core();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
let sp_plugin = SpotubePlugin::new();
|
||||||
|
let sender = SpotubePlugin::new_context(
|
||||||
|
PLUGIN_JS.to_string(),
|
||||||
|
PluginConfiguration {
|
||||||
|
entry_point: "TestingPlugin".to_string(),
|
||||||
|
abilities: vec![PluginAbility::Metadata],
|
||||||
|
apis: vec![],
|
||||||
|
author: "KRTirtho".to_string(),
|
||||||
|
description: "Testing Plugin".to_string(),
|
||||||
|
name: "Testing Plugin".to_string(),
|
||||||
|
plugin_api_version: "2.0.0".to_string(),
|
||||||
|
repository: None,
|
||||||
|
version: "0.1.0".to_string(),
|
||||||
|
}
|
||||||
|
)?;
|
||||||
|
let result = sp_plugin.core.support(sender.clone()).await?;
|
||||||
|
|
||||||
|
println!("Result: {:?}", result);
|
||||||
|
|
||||||
|
sp_plugin.dispose(sender.clone()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user