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 name,
|
||||
required String externalUri,
|
||||
List<SpotubeImageObject>? images,
|
||||
}) = _SpotubeSimpleArtistObject;
|
||||
|
||||
factory SpotubeSimpleArtistObject.fromJson(Map<String, dynamic> json) =>
|
||||
|
@ -994,6 +994,7 @@ mixin _$SpotubeSimpleArtistObject {
|
||||
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;
|
||||
@ -1011,7 +1012,11 @@ abstract class $SpotubeSimpleArtistObjectCopyWith<$Res> {
|
||||
$Res Function(SpotubeSimpleArtistObject) then) =
|
||||
_$SpotubeSimpleArtistObjectCopyWithImpl<$Res, SpotubeSimpleArtistObject>;
|
||||
@useResult
|
||||
$Res call({String id, String name, String externalUri});
|
||||
$Res call(
|
||||
{String id,
|
||||
String name,
|
||||
String externalUri,
|
||||
List<SpotubeImageObject>? images});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -1033,6 +1038,7 @@ class _$SpotubeSimpleArtistObjectCopyWithImpl<$Res,
|
||||
Object? id = null,
|
||||
Object? name = null,
|
||||
Object? externalUri = null,
|
||||
Object? images = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
id: null == id
|
||||
@ -1047,6 +1053,10 @@ class _$SpotubeSimpleArtistObjectCopyWithImpl<$Res,
|
||||
? _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);
|
||||
}
|
||||
}
|
||||
@ -1060,7 +1070,11 @@ abstract class _$$SpotubeSimpleArtistObjectImplCopyWith<$Res>
|
||||
__$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String id, String name, String externalUri});
|
||||
$Res call(
|
||||
{String id,
|
||||
String name,
|
||||
String externalUri,
|
||||
List<SpotubeImageObject>? images});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -1081,6 +1095,7 @@ class __$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>
|
||||
Object? id = null,
|
||||
Object? name = null,
|
||||
Object? externalUri = null,
|
||||
Object? images = freezed,
|
||||
}) {
|
||||
return _then(_$SpotubeSimpleArtistObjectImpl(
|
||||
id: null == id
|
||||
@ -1095,6 +1110,10 @@ class __$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>
|
||||
? _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>?,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -1103,7 +1122,11 @@ class __$$SpotubeSimpleArtistObjectImplCopyWithImpl<$Res>
|
||||
@JsonSerializable()
|
||||
class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
||||
_$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) =>
|
||||
_$$SpotubeSimpleArtistObjectImplFromJson(json);
|
||||
@ -1114,10 +1137,19 @@ class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
||||
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(id: $id, name: $name, externalUri: $externalUri)';
|
||||
return 'SpotubeSimpleArtistObject(id: $id, name: $name, externalUri: $externalUri, images: $images)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1128,12 +1160,14 @@ class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.name, name) || other.name == name) &&
|
||||
(identical(other.externalUri, externalUri) ||
|
||||
other.externalUri == externalUri));
|
||||
other.externalUri == externalUri) &&
|
||||
const DeepCollectionEquality().equals(other._images, _images));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@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
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@ -1154,9 +1188,11 @@ class _$SpotubeSimpleArtistObjectImpl implements _SpotubeSimpleArtistObject {
|
||||
|
||||
abstract class _SpotubeSimpleArtistObject implements SpotubeSimpleArtistObject {
|
||||
factory _SpotubeSimpleArtistObject(
|
||||
{required final String id,
|
||||
required final String name,
|
||||
required final String externalUri}) = _$SpotubeSimpleArtistObjectImpl;
|
||||
{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;
|
||||
@ -1167,6 +1203,8 @@ abstract class _SpotubeSimpleArtistObject implements SpotubeSimpleArtistObject {
|
||||
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.
|
||||
@ -2529,7 +2567,7 @@ SpotubeSearchResponseObject _$SpotubeSearchResponseObjectFromJson(
|
||||
mixin _$SpotubeSearchResponseObject {
|
||||
List<SpotubeSimpleAlbumObject> get albums =>
|
||||
throw _privateConstructorUsedError;
|
||||
List<SpotubeSimpleArtistObject> get artists =>
|
||||
List<SpotubeFullArtistObject> get artists =>
|
||||
throw _privateConstructorUsedError;
|
||||
List<SpotubeSimplePlaylistObject> get playlists =>
|
||||
throw _privateConstructorUsedError;
|
||||
@ -2556,7 +2594,7 @@ abstract class $SpotubeSearchResponseObjectCopyWith<$Res> {
|
||||
@useResult
|
||||
$Res call(
|
||||
{List<SpotubeSimpleAlbumObject> albums,
|
||||
List<SpotubeSimpleArtistObject> artists,
|
||||
List<SpotubeFullArtistObject> artists,
|
||||
List<SpotubeSimplePlaylistObject> playlists,
|
||||
List<SpotubeSimpleTrackObject> tracks});
|
||||
}
|
||||
@ -2590,7 +2628,7 @@ class _$SpotubeSearchResponseObjectCopyWithImpl<$Res,
|
||||
artists: null == artists
|
||||
? _value.artists
|
||||
: artists // ignore: cast_nullable_to_non_nullable
|
||||
as List<SpotubeSimpleArtistObject>,
|
||||
as List<SpotubeFullArtistObject>,
|
||||
playlists: null == playlists
|
||||
? _value.playlists
|
||||
: playlists // ignore: cast_nullable_to_non_nullable
|
||||
@ -2614,7 +2652,7 @@ abstract class _$$SpotubeSearchResponseObjectImplCopyWith<$Res>
|
||||
@useResult
|
||||
$Res call(
|
||||
{List<SpotubeSimpleAlbumObject> albums,
|
||||
List<SpotubeSimpleArtistObject> artists,
|
||||
List<SpotubeFullArtistObject> artists,
|
||||
List<SpotubeSimplePlaylistObject> playlists,
|
||||
List<SpotubeSimpleTrackObject> tracks});
|
||||
}
|
||||
@ -2647,7 +2685,7 @@ class __$$SpotubeSearchResponseObjectImplCopyWithImpl<$Res>
|
||||
artists: null == artists
|
||||
? _value._artists
|
||||
: artists // ignore: cast_nullable_to_non_nullable
|
||||
as List<SpotubeSimpleArtistObject>,
|
||||
as List<SpotubeFullArtistObject>,
|
||||
playlists: null == playlists
|
||||
? _value._playlists
|
||||
: playlists // ignore: cast_nullable_to_non_nullable
|
||||
@ -2666,7 +2704,7 @@ class _$SpotubeSearchResponseObjectImpl
|
||||
implements _SpotubeSearchResponseObject {
|
||||
_$SpotubeSearchResponseObjectImpl(
|
||||
{required final List<SpotubeSimpleAlbumObject> albums,
|
||||
required final List<SpotubeSimpleArtistObject> artists,
|
||||
required final List<SpotubeFullArtistObject> artists,
|
||||
required final List<SpotubeSimplePlaylistObject> playlists,
|
||||
required final List<SpotubeSimpleTrackObject> tracks})
|
||||
: _albums = albums,
|
||||
@ -2686,9 +2724,9 @@ class _$SpotubeSearchResponseObjectImpl
|
||||
return EqualUnmodifiableListView(_albums);
|
||||
}
|
||||
|
||||
final List<SpotubeSimpleArtistObject> _artists;
|
||||
final List<SpotubeFullArtistObject> _artists;
|
||||
@override
|
||||
List<SpotubeSimpleArtistObject> get artists {
|
||||
List<SpotubeFullArtistObject> get artists {
|
||||
if (_artists is EqualUnmodifiableListView) return _artists;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_artists);
|
||||
@ -2757,7 +2795,7 @@ abstract class _SpotubeSearchResponseObject
|
||||
implements SpotubeSearchResponseObject {
|
||||
factory _SpotubeSearchResponseObject(
|
||||
{required final List<SpotubeSimpleAlbumObject> albums,
|
||||
required final List<SpotubeSimpleArtistObject> artists,
|
||||
required final List<SpotubeFullArtistObject> artists,
|
||||
required final List<SpotubeSimplePlaylistObject> playlists,
|
||||
required final List<SpotubeSimpleTrackObject> tracks}) =
|
||||
_$SpotubeSearchResponseObjectImpl;
|
||||
@ -2768,7 +2806,7 @@ abstract class _SpotubeSearchResponseObject
|
||||
@override
|
||||
List<SpotubeSimpleAlbumObject> get albums;
|
||||
@override
|
||||
List<SpotubeSimpleArtistObject> get artists;
|
||||
List<SpotubeFullArtistObject> get artists;
|
||||
@override
|
||||
List<SpotubeSimplePlaylistObject> get playlists;
|
||||
@override
|
||||
|
@ -113,6 +113,10 @@ _$SpotubeSimpleArtistObjectImpl _$$SpotubeSimpleArtistObjectImplFromJson(
|
||||
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(
|
||||
@ -121,6 +125,7 @@ Map<String, dynamic> _$$SpotubeSimpleArtistObjectImplToJson(
|
||||
'id': instance.id,
|
||||
'name': instance.name,
|
||||
'externalUri': instance.externalUri,
|
||||
'images': instance.images?.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
_$SpotubeBrowseSectionObjectImpl<T>
|
||||
@ -260,7 +265,7 @@ _$SpotubeSearchResponseObjectImpl _$$SpotubeSearchResponseObjectImplFromJson(
|
||||
Map<String, dynamic>.from(e as Map)))
|
||||
.toList(),
|
||||
artists: (json['artists'] as List<dynamic>)
|
||||
.map((e) => SpotubeSimpleArtistObject.fromJson(
|
||||
.map((e) => SpotubeFullArtistObject.fromJson(
|
||||
Map<String, dynamic>.from(e as Map)))
|
||||
.toList(),
|
||||
playlists: (json['playlists'] as List<dynamic>)
|
||||
|
@ -4,7 +4,7 @@ part of 'metadata.dart';
|
||||
class SpotubeSearchResponseObject with _$SpotubeSearchResponseObject {
|
||||
factory SpotubeSearchResponseObject({
|
||||
required List<SpotubeSimpleAlbumObject> albums,
|
||||
required List<SpotubeSimpleArtistObject> artists,
|
||||
required List<SpotubeFullArtistObject> artists,
|
||||
required List<SpotubeSimplePlaylistObject> playlists,
|
||||
required List<SpotubeSimpleTrackObject> tracks,
|
||||
}) = _SpotubeSearchResponseObject;
|
||||
|
@ -2,7 +2,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_undraw/flutter_undraw.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:fuzzywuzzy/fuzzywuzzy.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/artists.dart';
|
||||
import 'package:spotube/pages/search/sections/playlists.dart';
|
||||
import 'package:spotube/pages/search/sections/tracks.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
@ -39,17 +38,11 @@ class SearchPage extends HookConsumerWidget {
|
||||
final controller = useShadcnTextEditingController();
|
||||
final focusNode = useFocusNode();
|
||||
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
|
||||
final searchTerm = ref.watch(searchTermStateProvider);
|
||||
final searchTrack = ref.watch(searchProvider(SearchType.track));
|
||||
final searchAlbum = ref.watch(searchProvider(SearchType.album));
|
||||
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);
|
||||
final searchSnapshot =
|
||||
ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||
|
||||
useEffect(() {
|
||||
controller.text = searchTerm;
|
||||
@ -82,7 +75,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
if (kTitlebarVisible)
|
||||
const TitleBar(automaticallyImplyLeading: false, height: 30)
|
||||
],
|
||||
child: auth.asData?.value == null
|
||||
child: authenticated.asData?.value != true
|
||||
? const AnonymousFallback()
|
||||
: Column(
|
||||
children: [
|
||||
@ -174,7 +167,10 @@ class SearchPage extends HookConsumerWidget {
|
||||
Expanded(
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: switch ((searchTerm.isEmpty, isFetching)) {
|
||||
child: switch ((
|
||||
searchTerm.isEmpty,
|
||||
searchSnapshot.isLoading
|
||||
)) {
|
||||
(true, false) => Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
@ -228,7 +224,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
SearchTracksSection(),
|
||||
// SearchTracksSection(),
|
||||
SearchPlaylistsSection(),
|
||||
Gap(20),
|
||||
SearchArtistsSection(),
|
||||
|
@ -1,11 +1,9 @@
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.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/extensions/album_simple.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
class SearchAlbumsSection extends HookConsumerWidget {
|
||||
@ -15,23 +13,15 @@ class SearchAlbumsSection extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final query = ref.watch(searchProvider(SearchType.album));
|
||||
final notifier = ref.watch(searchProvider(SearchType.album).notifier);
|
||||
final albums = useMemoized(
|
||||
() =>
|
||||
query.asData?.value.items
|
||||
.cast<AlbumSimple>()
|
||||
.map((e) => e.toAlbum())
|
||||
.toList() ??
|
||||
[],
|
||||
[query.asData?.value],
|
||||
);
|
||||
final searchTerm = ref.watch(searchTermStateProvider);
|
||||
final search = ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||
final albums = search.asData?.value.albums ?? [];
|
||||
|
||||
return HorizontalPlaybuttonCardView(
|
||||
isLoadingNextPage: query.isLoadingNextPage,
|
||||
hasNextPage: query.asData?.value.hasMore == true,
|
||||
isLoadingNextPage: false,
|
||||
hasNextPage: false,
|
||||
items: albums,
|
||||
onFetchMore: notifier.fetchMore,
|
||||
onFetchMore: () {},
|
||||
title: Text(context.l10n.albums),
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.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/extensions/context.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
class SearchArtistsSection extends HookConsumerWidget {
|
||||
@ -13,16 +13,16 @@ class SearchArtistsSection extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final query = ref.watch(searchProvider(SearchType.artist));
|
||||
final notifier = ref.watch(searchProvider(SearchType.artist).notifier);
|
||||
final searchTerm = ref.watch(searchTermStateProvider);
|
||||
final search = ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||
|
||||
final artists = query.asData?.value.items.cast<Artist>() ?? [];
|
||||
final artists = search.asData?.value.artists ?? [];
|
||||
|
||||
return HorizontalPlaybuttonCardView<Artist>(
|
||||
isLoadingNextPage: query.isLoadingNextPage,
|
||||
hasNextPage: query.asData?.value.hasMore == true,
|
||||
return HorizontalPlaybuttonCardView(
|
||||
isLoadingNextPage: false,
|
||||
hasNextPage: false,
|
||||
items: artists,
|
||||
onFetchMore: notifier.fetchMore,
|
||||
onFetchMore: () {},
|
||||
title: Text(context.l10n.artists),
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.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/extensions/context.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
class SearchPlaylistsSection extends HookConsumerWidget {
|
||||
@ -12,17 +12,16 @@ class SearchPlaylistsSection extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final playlistsQuery = ref.watch(searchProvider(SearchType.playlist));
|
||||
final playlistsQueryNotifier =
|
||||
ref.watch(searchProvider(SearchType.playlist).notifier);
|
||||
final playlists =
|
||||
playlistsQuery.asData?.value.items.cast<PlaylistSimple>() ?? [];
|
||||
final searchTerm = ref.watch(searchTermStateProvider);
|
||||
final playlistsQuery =
|
||||
ref.watch(metadataPluginSearchAllProvider(searchTerm));
|
||||
final playlists = playlistsQuery.asData?.value.playlists ?? [];
|
||||
|
||||
return HorizontalPlaybuttonCardView(
|
||||
isLoadingNextPage: playlistsQuery.isLoadingNextPage,
|
||||
hasNextPage: playlistsQuery.asData?.value.hasMore == true,
|
||||
isLoadingNextPage: false,
|
||||
hasNextPage: false,
|
||||
items: playlists,
|
||||
onFetchMore: playlistsQueryNotifier.fetchMore,
|
||||
onFetchMore: () {},
|
||||
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/browse.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';
|
||||
|
||||
const defaultMetadataLimit = "20";
|
||||
@ -80,6 +81,7 @@ class MetadataPlugin {
|
||||
late final MetadataPluginAlbumEndpoint album;
|
||||
late final MetadataPluginArtistEndpoint artist;
|
||||
late final MetadataPluginBrowseEndpoint browse;
|
||||
late final MetadataPluginSearchEndpoint search;
|
||||
late final MetadataPluginPlaylistEndpoint playlist;
|
||||
late final MetadataPluginUserEndpoint user;
|
||||
|
||||
@ -89,6 +91,7 @@ class MetadataPlugin {
|
||||
artist = MetadataPluginArtistEndpoint(hetu);
|
||||
album = MetadataPluginAlbumEndpoint(hetu);
|
||||
browse = MetadataPluginBrowseEndpoint(hetu);
|
||||
search = MetadataPluginSearchEndpoint(hetu);
|
||||
playlist = MetadataPluginPlaylistEndpoint(hetu);
|
||||
user = MetadataPluginUserEndpoint(hetu);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user