Skip to content

Commit

Permalink
feat(user-library): search for user playlists
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho committed Jan 5, 2023
1 parent e158dd0 commit af4d56f
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 255 deletions.
8 changes: 7 additions & 1 deletion lib/components/album/album_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import 'package:spotube/utils/type_conversion_utils.dart';

class AlbumCard extends HookConsumerWidget {
final Album album;
const AlbumCard(this.album, {Key? key}) : super(key: key);
final PlaybuttonCardViewType viewType;
const AlbumCard(
this.album, {
Key? key,
this.viewType = PlaybuttonCardViewType.square,
}) : super(key: key);

@override
Widget build(BuildContext context, ref) {
Expand All @@ -25,6 +30,7 @@ class AlbumCard extends HookConsumerWidget {
album.images,
placeholder: ImagePlaceholder.collection,
),
viewType: viewType,
margin: EdgeInsets.symmetric(horizontal: marginH.toDouble()),
isPlaying: isPlaylistPlaying && playback.isPlaying,
isLoading: playback.status == PlaybackStatus.loading &&
Expand Down
12 changes: 10 additions & 2 deletions lib/components/library/user_local_tracks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import 'package:spotube/utils/platform.dart';
import 'package:spotube/utils/primitive_utils.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:spotube/utils/type_conversion_utils.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge.dart' show FfiException;

const supportedAudioTypes = [
"audio/webm",
Expand Down Expand Up @@ -88,8 +89,15 @@ final localTracksProvider = FutureProvider<List<Track>>((ref) async {
}

return {"metadata": metadata, "file": f, "art": imageFile.path};
} catch (e, stack) {
getLogger(FutureProvider).e("[Fetching metadata]", e, stack);
} on FfiException catch (e) {
if (e.message == "NoTag: reader does not contain an id3 tag") {
getLogger(FutureProvider<List<Track>>)
.w("[Fetching metadata]", e.message);
}
return {};
} on Exception catch (e, stack) {
getLogger(FutureProvider<List<Track>>)
.e("[Fetching metadata]", e, stack);
return {};
}
},
Expand Down
81 changes: 66 additions & 15 deletions lib/components/library/user_playlists.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
import 'package:fl_query_hooks/fl_query_hooks.dart';
import 'package:flutter/material.dart' hide Image;
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
import 'package:collection/collection.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/playlist/playlist_create_dialog.dart';
import 'package:spotube/components/shared/playbutton_card.dart';
import 'package:spotube/components/shared/shimmers/shimmer_playbutton_card.dart';
import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart';
import 'package:spotube/components/playlist/playlist_card.dart';
import 'package:spotube/components/playlist/playlist_create_dialog.dart';
import 'package:spotube/hooks/use_breakpoint_value.dart';
import 'package:spotube/hooks/use_breakpoints.dart';
import 'package:spotube/provider/auth_provider.dart';
import 'package:spotube/provider/spotify_provider.dart';
import 'package:spotube/services/queries/queries.dart';
import 'package:tuple/tuple.dart';

class UserPlaylists extends HookConsumerWidget {
const UserPlaylists({Key? key}) : super(key: key);

@override
Widget build(BuildContext context, ref) {
final searchText = useState('');
final breakpoint = useBreakpoints();
final spacing = useBreakpointValue<double>(
sm: 0,
others: 20,
);
final viewType = MediaQuery.of(context).size.width < 480
? PlaybuttonCardViewType.list
: PlaybuttonCardViewType.square;
final auth = ref.watch(authProvider);
if (auth.isAnonymous) {
return const AnonymousFallback();
}

final playlistsQuery = useQuery(
job: Queries.playlist.ofMine,
externalData: ref.watch(spotifyProvider),
);

Image image = Image();
image.height = 300;
image.width = 300;
Expand All @@ -37,27 +51,64 @@ class UserPlaylists extends HookConsumerWidget {
image.url = "https://t.scdn.co/images/3099b3803ad9496896c43f22fe9be8c4.png";
likedTracksPlaylist.images = [image];

final playlists = useMemoized(
() => [
likedTracksPlaylist,
...?playlistsQuery.data,
]
.map((e) => Tuple2(
searchText.value.isEmpty
? 100
: weightedRatio(e.name!, searchText.value),
e,
))
.sorted((a, b) => b.item1.compareTo(a.item1))
.where((e) => e.item1 > 50)
.map((e) => e.item2)
.toList(),
[playlistsQuery.data, searchText.value],
);

if (auth.isAnonymous) {
return const AnonymousFallback();
}
if (playlistsQuery.isLoading || !playlistsQuery.hasData) {
return const Center(child: ShimmerPlaybuttonCard(count: 7));
}

final children = [
const PlaylistCreateDialog(),
...playlists
.map((playlist) => PlaylistCard(
playlist,
viewType: viewType,
))
.toList(),
];
return SingleChildScrollView(
child: Material(
type: MaterialType.transparency,
textStyle: PlatformTheme.of(context).textTheme!.body!,
child: Container(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 20, // gap between adjacent chips
runSpacing: 20, // gap between lines
alignment: WrapAlignment.center,
child: Column(
children: [
const PlaylistCreateDialog(),
PlaylistCard(likedTracksPlaylist),
...playlistsQuery.data!
.map((playlist) => PlaylistCard(playlist))
.toList(),
PlatformTextField(
onChanged: (value) => searchText.value = value,
placeholder: "Search your playlists...",
prefixIcon: Icons.search,
),
const SizedBox(height: 20),
Center(
child: Wrap(
spacing: spacing, // gap between adjacent chips
runSpacing: 20, // gap between lines
alignment: breakpoint.isSm
? WrapAlignment.center
: WrapAlignment.start,
children: children,
),
),
],
),
),
Expand Down
8 changes: 7 additions & 1 deletion lib/components/playlist/playlist_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import 'package:spotube/utils/type_conversion_utils.dart';

class PlaylistCard extends HookConsumerWidget {
final PlaylistSimple playlist;
const PlaylistCard(this.playlist, {Key? key}) : super(key: key);
final PlaybuttonCardViewType viewType;
const PlaylistCard(
this.playlist, {
Key? key,
this.viewType = PlaybuttonCardViewType.square,
}) : super(key: key);
@override
Widget build(BuildContext context, ref) {
Playback playback = ref.watch(playbackProvider);
Expand All @@ -21,6 +26,7 @@ class PlaylistCard extends HookConsumerWidget {
final int marginH =
useBreakpointValue(sm: 10, md: 15, lg: 20, xl: 20, xxl: 20);
return PlaybuttonCard(
viewType: viewType,
margin: EdgeInsets.symmetric(horizontal: marginH.toDouble()),
title: playlist.name!,
imageUrl: TypeConversionUtils.image_X_UrlString(
Expand Down
Loading

0 comments on commit af4d56f

Please sign in to comment.