mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
refactor: search to use metadata plugin
This commit is contained in:
parent
7569c37739
commit
fcc05a4243
@ -21,6 +21,7 @@ class SpotubeSimpleArtistObject with _$SpotubeSimpleArtistObject {
|
|||||||
required String id,
|
required String id,
|
||||||
required String name,
|
required String name,
|
||||||
required String externalUri,
|
required String externalUri,
|
||||||
|
List<SpotubeImageObject>? images,
|
||||||
}) = _SpotubeSimpleArtistObject;
|
}) = _SpotubeSimpleArtistObject;
|
||||||
|
|
||||||
factory SpotubeSimpleArtistObject.fromJson(Map<String, dynamic> json) =>
|
factory SpotubeSimpleArtistObject.fromJson(Map<String, dynamic> json) =>
|
||||||
|
@ -994,6 +994,7 @@ mixin _$SpotubeSimpleArtistObject {
|
|||||||
String get id => throw _privateConstructorUsedError;
|
String get id => throw _privateConstructorUsedError;
|
||||||
String get name => throw _privateConstructorUsedError;
|
String get name => throw _privateConstructorUsedError;
|
||||||
String get externalUri => throw _privateConstructorUsedError;
|
String get externalUri => throw _privateConstructorUsedError;
|
||||||
|
List<SpotubeImageObject>? get images => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this SpotubeSimpleArtistObject to a JSON map.
|
/// Serializes this SpotubeSimpleArtistObject to a JSON map.
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@ -1011,7 +1012,11 @@ abstract class $SpotubeSimpleArtistObjectCopyWith<$Res> {
|
|||||||
$Res Function(SpotubeSimpleArtistObject) then) =
|
$Res Function(SpotubeSimpleArtistObject) then) =
|
||||||
_$SpotubeSimpleArtistObjectCopyWithImpl<$Res, SpotubeSimpleArtistObject>;
|
_$SpotubeSimpleArtistObjectCopyWithImpl<$Res, SpotubeSimpleArtistObject>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({String id, String name, String externalUri});
|
$Res call(
|
||||||
|
{String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeImageObject>? images});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -1033,6 +1038,7 @@ class _$SpotubeSimpleArtistObjectCopyWithImpl<$Res,
|
|||||||
Object? id = null,
|
Object? id = null,
|
||||||
Object? name = null,
|
Object? name = null,
|
||||||
Object? externalUri = null,
|
Object? externalUri = null,
|
||||||
|
Object? images = freezed,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
id: null == id
|
id: null == id
|
||||||
@ -1047,6 +1053,10 @@ class _$SpotubeSimpleArtistObjectCopyWithImpl<$Res,
|
|||||||
? _value.externalUri
|
? _value.externalUri
|
||||||
: externalUri // ignore: cast_nullable_to_non_nullable
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
|
images: freezed == images
|
||||||
|
? _value.images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>?,
|
||||||
) as $Val);
|
) as $Val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1060,7 +1070,11 @@ abstract class _$$SpotubeSimpleArtistObjectImplCopyWith<$Res>
|
|||||||
__$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>;
|
__$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>;
|
||||||
@override
|
@override
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({String id, String name, String externalUri});
|
$Res call(
|
||||||
|
{String id,
|
||||||
|
String name,
|
||||||
|
String externalUri,
|
||||||
|
List<SpotubeImageObject>? images});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -1081,6 +1095,7 @@ class __$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>
|
|||||||
Object? id = null,
|
Object? id = null,
|
||||||
Object? name = null,
|
Object? name = null,
|
||||||
Object? externalUri = null,
|
Object? externalUri = null,
|
||||||
|
Object? images = freezed,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$SpotubeSimpleArtistObjectImpl(
|
return _then(_$SpotubeSimpleArtistObjectImpl(
|
||||||
id: null == id
|
id: null == id
|
||||||
@ -1095,6 +1110,10 @@ class __$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>
|
|||||||
? _value.externalUri
|
? _value.externalUri
|
||||||
: externalUri // ignore: cast_nullable_to_non_nullable
|
: externalUri // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
|
images: freezed == images
|
||||||
|
? _value._images
|
||||||
|
: images // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SpotubeImageObject>?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1103,7 +1122,11 @@ class __$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
||||||
_$SpotubeSimpleArtistObjectImpl(
|
_$SpotubeSimpleArtistObjectImpl(
|
||||||
{required this.id, required this.name, required this.externalUri});
|
{required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.externalUri,
|
||||||
|
final List<SpotubeImageObject>? images})
|
||||||
|
: _images = images;
|
||||||
|
|
||||||
factory _$SpotubeSimpleArtistObjectImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$SpotubeSimpleArtistObjectImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$SpotubeSimpleArtistObjectImplFromJson(json);
|
_$$SpotubeSimpleArtistObjectImplFromJson(json);
|
||||||
@ -1114,10 +1137,19 @@ class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
|||||||
final String name;
|
final String name;
|
||||||
@override
|
@override
|
||||||
final String externalUri;
|
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
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SpotubeSimpleArtistObject(id: $id, name: $name, externalUri: $externalUri)';
|
return 'SpotubeSimpleArtistObject(id: $id, name: $name, externalUri: $externalUri, images: $images)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -1128,12 +1160,14 @@ class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
|||||||
(identical(other.id, id) || other.id == id) &&
|
(identical(other.id, id) || other.id == id) &&
|
||||||
(identical(other.name, name) || other.name == name) &&
|
(identical(other.name, name) || other.name == name) &&
|
||||||
(identical(other.externalUri, externalUri) ||
|
(identical(other.externalUri, externalUri) ||
|
||||||
other.externalUri == externalUri));
|
other.externalUri == externalUri) &&
|
||||||
|
const DeepCollectionEquality().equals(other._images, _images));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, id, name, externalUri);
|
int get hashCode => Object.hash(runtimeType, id, name, externalUri,
|
||||||
|
const DeepCollectionEquality().hash(_images));
|
||||||
|
|
||||||
/// Create a copy of SpotubeSimpleArtistObject
|
/// Create a copy of SpotubeSimpleArtistObject
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@ -1154,9 +1188,11 @@ class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
|||||||
|
|
||||||
abstract class _SpotubeSimpleArtistObject implements SpotubeSimpleArtistObject {
|
abstract class _SpotubeSimpleArtistObject implements SpotubeSimpleArtistObject {
|
||||||
factory _SpotubeSimpleArtistObject(
|
factory _SpotubeSimpleArtistObject(
|
||||||
{required final String id,
|
{required final String id,
|
||||||
required final String name,
|
required final String name,
|
||||||
required final String externalUri}) = _$SpotubeSimpleArtistObjectImpl;
|
required final String externalUri,
|
||||||
|
final List<SpotubeImageObject>? images}) =
|
||||||
|
_$SpotubeSimpleArtistObjectImpl;
|
||||||
|
|
||||||
factory _SpotubeSimpleArtistObject.fromJson(Map<String, dynamic> json) =
|
factory _SpotubeSimpleArtistObject.fromJson(Map<String, dynamic> json) =
|
||||||
_$SpotubeSimpleArtistObjectImpl.fromJson;
|
_$SpotubeSimpleArtistObjectImpl.fromJson;
|
||||||
@ -1167,6 +1203,8 @@ abstract class _SpotubeSimpleArtistObject implements SpotubeSimpleArtistObject {
|
|||||||
String get name;
|
String get name;
|
||||||
@override
|
@override
|
||||||
String get externalUri;
|
String get externalUri;
|
||||||
|
@override
|
||||||
|
List<SpotubeImageObject>? get images;
|
||||||
|
|
||||||
/// Create a copy of SpotubeSimpleArtistObject
|
/// Create a copy of SpotubeSimpleArtistObject
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@ -2529,7 +2567,7 @@ SpotubeSearchResponseObject _$SpotubeSearchResponseObjectFromJson(
|
|||||||
mixin _$SpotubeSearchResponseObject {
|
mixin _$SpotubeSearchResponseObject {
|
||||||
List<SpotubeSimpleAlbumObject> get albums =>
|
List<SpotubeSimpleAlbumObject> get albums =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
List<SpotubeSimpleArtistObject> get artists =>
|
List<SpotubeFullArtistObject> get artists =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
List<SpotubeSimplePlaylistObject> get playlists =>
|
List<SpotubeSimplePlaylistObject> get playlists =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@ -2556,7 +2594,7 @@ abstract class $SpotubeSearchResponseObjectCopyWith<$Res> {
|
|||||||
@useResult
|
@useResult
|
||||||
$Res call(
|
$Res call(
|
||||||
{List<SpotubeSimpleAlbumObject> albums,
|
{List<SpotubeSimpleAlbumObject> albums,
|
||||||
List<SpotubeSimpleArtistObject> artists,
|
List<SpotubeFullArtistObject> artists,
|
||||||
List<SpotubeSimplePlaylistObject> playlists,
|
List<SpotubeSimplePlaylistObject> playlists,
|
||||||
List<SpotubeSimpleTrackObject> tracks});
|
List<SpotubeSimpleTrackObject> tracks});
|
||||||
}
|
}
|
||||||
@ -2590,7 +2628,7 @@ class _$SpotubeSearchResponseObjectCopyWithImpl<$Res,
|
|||||||
artists: null == artists
|
artists: null == artists
|
||||||
? _value.artists
|
? _value.artists
|
||||||
: artists // ignore: cast_nullable_to_non_nullable
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SpotubeSimpleArtistObject>,
|
as List<SpotubeFullArtistObject>,
|
||||||
playlists: null == playlists
|
playlists: null == playlists
|
||||||
? _value.playlists
|
? _value.playlists
|
||||||
: playlists // ignore: cast_nullable_to_non_nullable
|
: playlists // ignore: cast_nullable_to_non_nullable
|
||||||
@ -2614,7 +2652,7 @@ abstract class _$$SpotubeSearchResponseObjectImplCopyWith<$Res>
|
|||||||
@useResult
|
@useResult
|
||||||
$Res call(
|
$Res call(
|
||||||
{List<SpotubeSimpleAlbumObject> albums,
|
{List<SpotubeSimpleAlbumObject> albums,
|
||||||
List<SpotubeSimpleArtistObject> artists,
|
List<SpotubeFullArtistObject> artists,
|
||||||
List<SpotubeSimplePlaylistObject> playlists,
|
List<SpotubeSimplePlaylistObject> playlists,
|
||||||
List<SpotubeSimpleTrackObject> tracks});
|
List<SpotubeSimpleTrackObject> tracks});
|
||||||
}
|
}
|
||||||
@ -2647,7 +2685,7 @@ class __$$SpotubeSearchResponseObjectImplCopyWithImpl<$Res>
|
|||||||
artists: null == artists
|
artists: null == artists
|
||||||
? _value._artists
|
? _value._artists
|
||||||
: artists // ignore: cast_nullable_to_non_nullable
|
: artists // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SpotubeSimpleArtistObject>,
|
as List<SpotubeFullArtistObject>,
|
||||||
playlists: null == playlists
|
playlists: null == playlists
|
||||||
? _value._playlists
|
? _value._playlists
|
||||||
: playlists // ignore: cast_nullable_to_non_nullable
|
: playlists // ignore: cast_nullable_to_non_nullable
|
||||||
@ -2666,7 +2704,7 @@ class _$SpotubeSearchResponseObjectImpl
|
|||||||
implements _SpotubeSearchResponseObject {
|
implements _SpotubeSearchResponseObject {
|
||||||
_$SpotubeSearchResponseObjectImpl(
|
_$SpotubeSearchResponseObjectImpl(
|
||||||
{required final List<SpotubeSimpleAlbumObject> albums,
|
{required final List<SpotubeSimpleAlbumObject> albums,
|
||||||
required final List<SpotubeSimpleArtistObject> artists,
|
required final List<SpotubeFullArtistObject> artists,
|
||||||
required final List<SpotubeSimplePlaylistObject> playlists,
|
required final List<SpotubeSimplePlaylistObject> playlists,
|
||||||
required final List<SpotubeSimpleTrackObject> tracks})
|
required final List<SpotubeSimpleTrackObject> tracks})
|
||||||
: _albums = albums,
|
: _albums = albums,
|
||||||
@ -2686,9 +2724,9 @@ class _$SpotubeSearchResponseObjectImpl
|
|||||||
return EqualUnmodifiableListView(_albums);
|
return EqualUnmodifiableListView(_albums);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<SpotubeSimpleArtistObject> _artists;
|
final List<SpotubeFullArtistObject> _artists;
|
||||||
@override
|
@override
|
||||||
List<SpotubeSimpleArtistObject> get artists {
|
List<SpotubeFullArtistObject> get artists {
|
||||||
if (_artists is EqualUnmodifiableListView) return _artists;
|
if (_artists is EqualUnmodifiableListView) return _artists;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_artists);
|
return EqualUnmodifiableListView(_artists);
|
||||||
@ -2757,7 +2795,7 @@ abstract class _SpotubeSearchResponseObject
|
|||||||
implements SpotubeSearchResponseObject {
|
implements SpotubeSearchResponseObject {
|
||||||
factory _SpotubeSearchResponseObject(
|
factory _SpotubeSearchResponseObject(
|
||||||
{required final List<SpotubeSimpleAlbumObject> albums,
|
{required final List<SpotubeSimpleAlbumObject> albums,
|
||||||
required final List<SpotubeSimpleArtistObject> artists,
|
required final List<SpotubeFullArtistObject> artists,
|
||||||
required final List<SpotubeSimplePlaylistObject> playlists,
|
required final List<SpotubeSimplePlaylistObject> playlists,
|
||||||
required final List<SpotubeSimpleTrackObject> tracks}) =
|
required final List<SpotubeSimpleTrackObject> tracks}) =
|
||||||
_$SpotubeSearchResponseObjectImpl;
|
_$SpotubeSearchResponseObjectImpl;
|
||||||
@ -2768,7 +2806,7 @@ abstract class _SpotubeSearchResponseObject
|
|||||||
@override
|
@override
|
||||||
List<SpotubeSimpleAlbumObject> get albums;
|
List<SpotubeSimpleAlbumObject> get albums;
|
||||||
@override
|
@override
|
||||||
List<SpotubeSimpleArtistObject> get artists;
|
List<SpotubeFullArtistObject> get artists;
|
||||||
@override
|
@override
|
||||||
List<SpotubeSimplePlaylistObject> get playlists;
|
List<SpotubeSimplePlaylistObject> get playlists;
|
||||||
@override
|
@override
|
||||||
|
@ -113,6 +113,10 @@ _$SpotubeSimpleArtistObjectImpl _$$SpotubeSimpleArtistObjectImplFromJson(
|
|||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
externalUri: json['externalUri'] 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(
|
Map<String, dynamic> _$$SpotubeSimpleArtistObjectImplToJson(
|
||||||
@ -121,6 +125,7 @@ Map<String, dynamic> _$$SpotubeSimpleArtistObjectImplToJson(
|
|||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'externalUri': instance.externalUri,
|
'externalUri': instance.externalUri,
|
||||||
|
'images': instance.images?.map((e) => e.toJson()).toList(),
|
||||||
};
|
};
|
||||||
|
|
||||||
_$SpotubeBrowseSectionObjectImpl<T>
|
_$SpotubeBrowseSectionObjectImpl<T>
|
||||||
@ -260,7 +265,7 @@ _$SpotubeSearchResponseObjectImpl _$$SpotubeSearchResponseObjectImplFromJson(
|
|||||||
Map<String, dynamic>.from(e as Map)))
|
Map<String, dynamic>.from(e as Map)))
|
||||||
.toList(),
|
.toList(),
|
||||||
artists: (json['artists'] as List<dynamic>)
|
artists: (json['artists'] as List<dynamic>)
|
||||||
.map((e) => SpotubeSimpleArtistObject.fromJson(
|
.map((e) => SpotubeFullArtistObject.fromJson(
|
||||||
Map<String, dynamic>.from(e as Map)))
|
Map<String, dynamic>.from(e as Map)))
|
||||||
.toList(),
|
.toList(),
|
||||||
playlists: (json['playlists'] as List<dynamic>)
|
playlists: (json['playlists'] as List<dynamic>)
|
||||||
|
@ -4,7 +4,7 @@ part of 'metadata.dart';
|
|||||||
class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject {
|
class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject {
|
||||||
factory SpotubeSearchResponseObject({
|
factory SpotubeSearchResponseObject({
|
||||||
required List<SpotubeSimpleAlbumObject> albums,
|
required List<SpotubeSimpleAlbumObject> albums,
|
||||||
required List<SpotubeSimpleArtistObject> artists,
|
required List<SpotubeFullArtistObject> artists,
|
||||||
required List<SpotubeSimplePlaylistObject> playlists,
|
required List<SpotubeSimplePlaylistObject> playlists,
|
||||||
required List<SpotubeSimpleTrackObject> tracks,
|
required List<SpotubeSimpleTrackObject> tracks,
|
||||||
}) = _SpotubeSearchResponseObject;
|
}) = _SpotubeSearchResponseObject;
|
||||||
|
@ -2,7 +2,6 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_undraw/flutter_undraw.dart';
|
import 'package:flutter_undraw/flutter_undraw.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
|
|
||||||
import 'package:spotify/spotify.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
|
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@ -18,8 +17,8 @@ import 'package:spotube/hooks/controllers/use_shadcn_text_editing_controller.dar
|
|||||||
import 'package:spotube/pages/search/sections/albums.dart';
|
import 'package:spotube/pages/search/sections/albums.dart';
|
||||||
import 'package:spotube/pages/search/sections/artists.dart';
|
import 'package:spotube/pages/search/sections/artists.dart';
|
||||||
import 'package:spotube/pages/search/sections/playlists.dart';
|
import 'package:spotube/pages/search/sections/playlists.dart';
|
||||||
import 'package:spotube/pages/search/sections/tracks.dart';
|
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||||
import 'package:spotube/provider/authentication/authentication.dart';
|
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||||
import 'package:spotube/provider/spotify/spotify.dart';
|
import 'package:spotube/provider/spotify/spotify.dart';
|
||||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
@ -39,17 +38,11 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
final controller = useShadcnTextEditingController();
|
final controller = useShadcnTextEditingController();
|
||||||
final focusNode = useFocusNode();
|
final focusNode = useFocusNode();
|
||||||
|
|
||||||
final auth = ref.watch(authenticationProvider);
|
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
|
|
||||||
final searchTerm = ref.watch(searchTermStateProvider);
|
final searchTerm = ref.watch(searchTermStateProvider);
|
||||||
final searchTrack = ref.watch(searchProvider(SearchType.track));
|
final searchSnapshot =
|
||||||
final searchAlbum = ref.watch(searchProvider(SearchType.album));
|
ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||||
final searchPlaylist = ref.watch(searchProvider(SearchType.playlist));
|
|
||||||
final searchArtist = ref.watch(searchProvider(SearchType.artist));
|
|
||||||
|
|
||||||
final queries = [searchTrack, searchAlbum, searchPlaylist, searchArtist];
|
|
||||||
|
|
||||||
final isFetching = queries.every((s) => s.isLoading);
|
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
controller.text = searchTerm;
|
controller.text = searchTerm;
|
||||||
@ -82,7 +75,7 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
if (kTitlebarVisible)
|
if (kTitlebarVisible)
|
||||||
const TitleBar(automaticallyImplyLeading: false, height: 30)
|
const TitleBar(automaticallyImplyLeading: false, height: 30)
|
||||||
],
|
],
|
||||||
child: auth.asData?.value == null
|
child: authenticated.asData?.value != true
|
||||||
? const AnonymousFallback()
|
? const AnonymousFallback()
|
||||||
: Column(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -174,7 +167,10 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
child: switch ((searchTerm.isEmpty, isFetching)) {
|
child: switch ((
|
||||||
|
searchTerm.isEmpty,
|
||||||
|
searchSnapshot.isLoading
|
||||||
|
)) {
|
||||||
(true, false) => Column(
|
(true, false) => Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -228,7 +224,7 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SearchTracksSection(),
|
// SearchTracksSection(),
|
||||||
SearchPlaylistsSection(),
|
SearchPlaylistsSection(),
|
||||||
Gap(20),
|
Gap(20),
|
||||||
SearchArtistsSection(),
|
SearchArtistsSection(),
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
|
|
||||||
import 'package:spotify/spotify.dart';
|
|
||||||
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
||||||
import 'package:spotube/extensions/album_simple.dart';
|
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
|
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||||
import 'package:spotube/provider/spotify/spotify.dart';
|
import 'package:spotube/provider/spotify/spotify.dart';
|
||||||
|
|
||||||
class SearchAlbumsSection extends HookConsumerWidget {
|
class SearchAlbumsSection extends HookConsumerWidget {
|
||||||
@ -15,23 +13,15 @@ class SearchAlbumsSection extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final query = ref.watch(searchProvider(SearchType.album));
|
final searchTerm = ref.watch(searchTermStateProvider);
|
||||||
final notifier = ref.watch(searchProvider(SearchType.album).notifier);
|
final search = ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||||
final albums = useMemoized(
|
final albums = search.asData?.value.albums ?? [];
|
||||||
() =>
|
|
||||||
query.asData?.value.items
|
|
||||||
.cast<AlbumSimple>()
|
|
||||||
.map((e) => e.toAlbum())
|
|
||||||
.toList() ??
|
|
||||||
[],
|
|
||||||
[query.asData?.value],
|
|
||||||
);
|
|
||||||
|
|
||||||
return HorizontalPlaybuttonCardView(
|
return HorizontalPlaybuttonCardView(
|
||||||
isLoadingNextPage: query.isLoadingNextPage,
|
isLoadingNextPage: false,
|
||||||
hasNextPage: query.asData?.value.hasMore == true,
|
hasNextPage: false,
|
||||||
items: albums,
|
items: albums,
|
||||||
onFetchMore: notifier.fetchMore,
|
onFetchMore: () {},
|
||||||
title: Text(context.l10n.albums),
|
title: Text(context.l10n.albums),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
|
|
||||||
import 'package:spotify/spotify.dart';
|
|
||||||
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
|
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||||
import 'package:spotube/provider/spotify/spotify.dart';
|
import 'package:spotube/provider/spotify/spotify.dart';
|
||||||
|
|
||||||
class SearchArtistsSection extends HookConsumerWidget {
|
class SearchArtistsSection extends HookConsumerWidget {
|
||||||
@ -13,16 +13,16 @@ class SearchArtistsSection extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final query = ref.watch(searchProvider(SearchType.artist));
|
final searchTerm = ref.watch(searchTermStateProvider);
|
||||||
final notifier = ref.watch(searchProvider(SearchType.artist).notifier);
|
final search = ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||||
|
|
||||||
final artists = query.asData?.value.items.cast<Artist>() ?? [];
|
final artists = search.asData?.value.artists ?? [];
|
||||||
|
|
||||||
return HorizontalPlaybuttonCardView<Artist>(
|
return HorizontalPlaybuttonCardView(
|
||||||
isLoadingNextPage: query.isLoadingNextPage,
|
isLoadingNextPage: false,
|
||||||
hasNextPage: query.asData?.value.hasMore == true,
|
hasNextPage: false,
|
||||||
items: artists,
|
items: artists,
|
||||||
onFetchMore: notifier.fetchMore,
|
onFetchMore: () {},
|
||||||
title: Text(context.l10n.artists),
|
title: Text(context.l10n.artists),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
|
||||||
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
|
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||||
import 'package:spotube/provider/spotify/spotify.dart';
|
import 'package:spotube/provider/spotify/spotify.dart';
|
||||||
|
|
||||||
class SearchPlaylistsSection extends HookConsumerWidget {
|
class SearchPlaylistsSection extends HookConsumerWidget {
|
||||||
@ -12,17 +12,16 @@ class SearchPlaylistsSection extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final playlistsQuery = ref.watch(searchProvider(SearchType.playlist));
|
final searchTerm = ref.watch(searchTermStateProvider);
|
||||||
final playlistsQueryNotifier =
|
final playlistsQuery =
|
||||||
ref.watch(searchProvider(SearchType.playlist).notifier);
|
ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||||
final playlists =
|
final playlists = playlistsQuery.asData?.value.playlists ?? [];
|
||||||
playlistsQuery.asData?.value.items.cast<PlaylistSimple>() ?? [];
|
|
||||||
|
|
||||||
return HorizontalPlaybuttonCardView(
|
return HorizontalPlaybuttonCardView(
|
||||||
isLoadingNextPage: playlistsQuery.isLoadingNextPage,
|
isLoadingNextPage: false,
|
||||||
hasNextPage: playlistsQuery.asData?.value.hasMore == true,
|
hasNextPage: false,
|
||||||
items: playlists,
|
items: playlists,
|
||||||
onFetchMore: playlistsQueryNotifier.fetchMore,
|
onFetchMore: () {},
|
||||||
title: Text(context.l10n.playlists),
|
title: Text(context.l10n.playlists),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
19
lib/provider/metadata_plugin/search/all.dart
Normal file
19
lib/provider/metadata_plugin/search/all.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
|
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||||
|
import 'package:spotube/services/metadata/endpoints/error.dart';
|
||||||
|
|
||||||
|
final metadataPluginSearchAllProvider =
|
||||||
|
FutureProvider.autoDispose.family<SpotubeSearchResponseObject, String>(
|
||||||
|
(ref, query) async {
|
||||||
|
final metadataPlugin = await ref.watch(metadataPluginProvider.future);
|
||||||
|
|
||||||
|
if (metadataPlugin == null) {
|
||||||
|
throw MetadataPluginException.noDefaultPlugin(
|
||||||
|
"No default metadata plugin found",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadataPlugin.search.all(query);
|
||||||
|
},
|
||||||
|
);
|
@ -0,0 +1,156 @@
|
|||||||
|
import 'package:hetu_script/hetu_script.dart';
|
||||||
|
import 'package:hetu_script/values.dart';
|
||||||
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
|
|
||||||
|
class MetadataPluginSearchEndpoint {
|
||||||
|
final Hetu hetu;
|
||||||
|
MetadataPluginSearchEndpoint(this.hetu);
|
||||||
|
|
||||||
|
HTInstance get hetuMetadataSearch =>
|
||||||
|
(hetu.fetch("metadataPlugin") as HTInstance).memberGet("search")
|
||||||
|
as HTInstance;
|
||||||
|
|
||||||
|
Future<SpotubeSearchResponseObject> all(String query) async {
|
||||||
|
if (query.isEmpty) {
|
||||||
|
return SpotubeSearchResponseObject(
|
||||||
|
albums: [],
|
||||||
|
artists: [],
|
||||||
|
playlists: [],
|
||||||
|
tracks: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final raw = await hetuMetadataSearch.invoke(
|
||||||
|
"all",
|
||||||
|
positionalArgs: [query],
|
||||||
|
) as Map;
|
||||||
|
|
||||||
|
return SpotubeSearchResponseObject.fromJson(raw.cast<String, dynamic>());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject<SpotubeSimpleAlbumObject>> albums(
|
||||||
|
String query, {
|
||||||
|
int? limit,
|
||||||
|
int? offset,
|
||||||
|
}) async {
|
||||||
|
if (query.isEmpty) {
|
||||||
|
return SpotubePaginationResponseObject<SpotubeSimpleAlbumObject>(
|
||||||
|
items: [],
|
||||||
|
total: 0,
|
||||||
|
limit: limit ?? 20,
|
||||||
|
hasMore: false,
|
||||||
|
nextOffset: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final raw = await hetuMetadataSearch.invoke(
|
||||||
|
"albums",
|
||||||
|
positionalArgs: [query],
|
||||||
|
namedArgs: {
|
||||||
|
"limit": limit,
|
||||||
|
"offset": offset,
|
||||||
|
}..removeWhere((key, value) => value == null),
|
||||||
|
) as Map;
|
||||||
|
|
||||||
|
return SpotubePaginationResponseObject<SpotubeSimpleAlbumObject>.fromJson(
|
||||||
|
raw.cast<String, dynamic>(),
|
||||||
|
(json) => SpotubeSimpleAlbumObject.fromJson(json.cast<String, dynamic>()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject<SpotubeFullArtistObject>> artists(
|
||||||
|
String query, {
|
||||||
|
int? limit,
|
||||||
|
int? offset,
|
||||||
|
}) async {
|
||||||
|
if (query.isEmpty) {
|
||||||
|
return SpotubePaginationResponseObject<SpotubeFullArtistObject>(
|
||||||
|
items: [],
|
||||||
|
total: 0,
|
||||||
|
limit: limit ?? 20,
|
||||||
|
hasMore: false,
|
||||||
|
nextOffset: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final raw = await hetuMetadataSearch.invoke(
|
||||||
|
"artists",
|
||||||
|
positionalArgs: [query],
|
||||||
|
namedArgs: {
|
||||||
|
"limit": limit,
|
||||||
|
"offset": offset,
|
||||||
|
}..removeWhere((key, value) => value == null),
|
||||||
|
) as Map;
|
||||||
|
|
||||||
|
return SpotubePaginationResponseObject<SpotubeFullArtistObject>.fromJson(
|
||||||
|
raw.cast<String, dynamic>(),
|
||||||
|
(json) => SpotubeFullArtistObject.fromJson(
|
||||||
|
json.cast<String, dynamic>(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject<SpotubeSimplePlaylistObject>>
|
||||||
|
playlists(
|
||||||
|
String query, {
|
||||||
|
int? limit,
|
||||||
|
int? offset,
|
||||||
|
}) async {
|
||||||
|
if (query.isEmpty) {
|
||||||
|
return SpotubePaginationResponseObject<SpotubeSimplePlaylistObject>(
|
||||||
|
items: [],
|
||||||
|
total: 0,
|
||||||
|
limit: limit ?? 20,
|
||||||
|
hasMore: false,
|
||||||
|
nextOffset: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final raw = await hetuMetadataSearch.invoke(
|
||||||
|
"playlists",
|
||||||
|
positionalArgs: [query],
|
||||||
|
namedArgs: {
|
||||||
|
"limit": limit,
|
||||||
|
"offset": offset,
|
||||||
|
}..removeWhere((key, value) => value == null),
|
||||||
|
) as Map;
|
||||||
|
|
||||||
|
return SpotubePaginationResponseObject<
|
||||||
|
SpotubeSimplePlaylistObject>.fromJson(
|
||||||
|
raw.cast<String, dynamic>(),
|
||||||
|
(json) => SpotubeSimplePlaylistObject.fromJson(
|
||||||
|
json.cast<String, dynamic>(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SpotubePaginationResponseObject<SpotubeSimpleTrackObject>> tracks(
|
||||||
|
String query, {
|
||||||
|
int? limit,
|
||||||
|
int? offset,
|
||||||
|
}) async {
|
||||||
|
if (query.isEmpty) {
|
||||||
|
return SpotubePaginationResponseObject<SpotubeSimpleTrackObject>(
|
||||||
|
items: [],
|
||||||
|
total: 0,
|
||||||
|
limit: limit ?? 20,
|
||||||
|
hasMore: false,
|
||||||
|
nextOffset: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final raw = await hetuMetadataSearch.invoke(
|
||||||
|
"tracks",
|
||||||
|
positionalArgs: [query],
|
||||||
|
namedArgs: {
|
||||||
|
"limit": limit,
|
||||||
|
"offset": offset,
|
||||||
|
}..removeWhere((key, value) => value == null),
|
||||||
|
) as Map;
|
||||||
|
|
||||||
|
return SpotubePaginationResponseObject<SpotubeSimpleTrackObject>.fromJson(
|
||||||
|
raw.cast<String, dynamic>(),
|
||||||
|
(json) => SpotubeSimpleTrackObject.fromJson(json.cast<String, dynamic>()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ import 'package:spotube/services/metadata/endpoints/artist.dart';
|
|||||||
import 'package:spotube/services/metadata/endpoints/auth.dart';
|
import 'package:spotube/services/metadata/endpoints/auth.dart';
|
||||||
import 'package:spotube/services/metadata/endpoints/browse.dart';
|
import 'package:spotube/services/metadata/endpoints/browse.dart';
|
||||||
import 'package:spotube/services/metadata/endpoints/playlist.dart';
|
import 'package:spotube/services/metadata/endpoints/playlist.dart';
|
||||||
|
import 'package:spotube/services/metadata/endpoints/search.dart';
|
||||||
import 'package:spotube/services/metadata/endpoints/user.dart';
|
import 'package:spotube/services/metadata/endpoints/user.dart';
|
||||||
|
|
||||||
const defaultMetadataLimit = "20";
|
const defaultMetadataLimit = "20";
|
||||||
@ -80,6 +81,7 @@ class MetadataPlugin {
|
|||||||
late final MetadataPluginAlbumEndpoint album;
|
late final MetadataPluginAlbumEndpoint album;
|
||||||
late final MetadataPluginArtistEndpoint artist;
|
late final MetadataPluginArtistEndpoint artist;
|
||||||
late final MetadataPluginBrowseEndpoint browse;
|
late final MetadataPluginBrowseEndpoint browse;
|
||||||
|
late final MetadataPluginSearchEndpoint search;
|
||||||
late final MetadataPluginPlaylistEndpoint playlist;
|
late final MetadataPluginPlaylistEndpoint playlist;
|
||||||
late final MetadataPluginUserEndpoint user;
|
late final MetadataPluginUserEndpoint user;
|
||||||
|
|
||||||
@ -89,6 +91,7 @@ class MetadataPlugin {
|
|||||||
artist = MetadataPluginArtistEndpoint(hetu);
|
artist = MetadataPluginArtistEndpoint(hetu);
|
||||||
album = MetadataPluginAlbumEndpoint(hetu);
|
album = MetadataPluginAlbumEndpoint(hetu);
|
||||||
browse = MetadataPluginBrowseEndpoint(hetu);
|
browse = MetadataPluginBrowseEndpoint(hetu);
|
||||||
|
search = MetadataPluginSearchEndpoint(hetu);
|
||||||
playlist = MetadataPluginPlaylistEndpoint(hetu);
|
playlist = MetadataPluginPlaylistEndpoint(hetu);
|
||||||
user = MetadataPluginUserEndpoint(hetu);
|
user = MetadataPluginUserEndpoint(hetu);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user