fixed useTrackReaction & usePlaylistReaction mutation bugs... handleSpotifyError bug fixed

This commit is contained in:
KRTirtho 2021-03-20 11:59:38 +06:00
parent 5a1da660a1
commit 2d42bbd23d
5 changed files with 109 additions and 56 deletions

View File

@ -5,10 +5,11 @@ import { QueryCacheKeys } from "../conf";
import playerContext from "../context/playerContext";
import useSpotifyInfiniteQuery from "../hooks/useSpotifyInfiniteQuery";
import useSpotifyQuery from "../hooks/useSpotifyQuery";
import { GenreView } from "./PlaylistGenreView";
import { PlaylistSimpleControls, TrackTableIndex } from "./PlaylistView";
import PlaceholderApplet from "./shared/PlaceholderApplet";
import PlaylistCard from "./shared/PlaylistCard";
import { TrackButton } from "./shared/TrackButton";
import { TrackButton, TrackButtonPlaylistObject } from "./shared/TrackButton";
import { TabMenuItem } from "./TabMenu";
function Library() {
@ -32,21 +33,36 @@ function Library() {
export default Library;
function UserPlaylists() {
const { data: userPlaylists, isError, isLoading, refetch } = useSpotifyQuery<SpotifyApi.PlaylistObjectSimplified[]>(QueryCacheKeys.userPlaylists, (spotifyApi) =>
spotifyApi.getUserPlaylists().then((userPlaylists) => {
return userPlaylists.body.items;
})
const { data: userPagedPlaylists, isError, isLoading, refetch, isFetchingNextPage, hasNextPage, fetchNextPage } = useSpotifyInfiniteQuery<SpotifyApi.ListOfUsersPlaylistsResponse>(
QueryCacheKeys.userPlaylists,
(spotifyApi, { pageParam }) =>
spotifyApi.getUserPlaylists({ limit: 20, offset: pageParam }).then((userPlaylists) => {
return userPlaylists.body;
}),
{
getNextPageParam(lastPage) {
if (lastPage.next) {
return lastPage.offset + lastPage.limit;
}
},
}
);
const userPlaylists = userPagedPlaylists?.pages
?.map((playlist) => playlist.items)
.filter(Boolean)
.flat(1) as SpotifyApi.PlaylistObjectSimplified[];
return (
<ScrollArea style="flex: 1; border: none;">
<View style="flex: 1; flex-direction: 'row'; flex-wrap: 'wrap'; justify-content: 'space-evenly'; width: 330px; align-items: 'center';">
<PlaceholderApplet error={isError} loading={isLoading} message="Failed querying spotify" reload={refetch} />
{userPlaylists?.map((playlist, index) => (
<PlaylistCard key={index + playlist.id} playlist={playlist} />
))}
</View>
</ScrollArea>
<GenreView
heading="User Playlists"
isError={isError}
isLoading={isLoading}
playlists={userPlaylists ?? []}
isLoadable={!isFetchingNextPage}
refetch={refetch}
loadMore={hasNextPage ? ()=>fetchNextPage() : undefined}
/>
);
}
@ -80,19 +96,11 @@ function UserSavedTracks() {
}
}
const playlist: SpotifyApi.PlaylistObjectFull = {
const playlist: TrackButtonPlaylistObject = {
collaborative: false,
description: "User Playlist",
tracks: {
items: [userTracks ?? []].map(
(userTrack) =>
(({
...userTrack,
added_by: "Me",
is_local: false,
added_at: Date.now(),
} as unknown) as SpotifyApi.PlaylistTrackObject)
),
items: userTracks ?? [],
limit: 20,
href: "",
next: "",
@ -101,10 +109,9 @@ function UserSavedTracks() {
total: 20,
},
external_urls: { spotify: "" },
followers: { href: null, total: 2 },
href: "",
id: userSavedPlaylistId,
images: [],
images: [{ url: "https://facebook.com/img.jpeg" }],
name: "User saved track",
owner: { external_urls: { spotify: "" }, href: "", id: "Me", type: "user", uri: "spotify:user:me", display_name: "User", followers: { href: null, total: 0 } },
public: false,

View File

@ -5,26 +5,27 @@ import playerContext from "../../context/playerContext";
import { msToMinAndSec } from "../../helpers/msToMin:sec";
import useTrackReaction from "../../hooks/useTrackReaction";
import { heart, heartRegular, pause, play } from "../../icons";
import { audioPlayer } from "../Player";
import IconButton from "./IconButton";
export interface TrackButtonPlaylistObject extends SpotifyApi.PlaylistBaseObject {
follower?: SpotifyApi.FollowersObject;
tracks: SpotifyApi.PagingObject<SpotifyApi.SavedTrackObject | SpotifyApi.PlaylistTrackObject>;
}
export interface TrackButtonProps {
track: SpotifyApi.TrackObjectFull;
playlist?: SpotifyApi.PlaylistObjectFull;
playlist?: TrackButtonPlaylistObject;
index: number;
}
export const TrackButton: FC<TrackButtonProps> = ({ track, index, playlist }) => {
const { reactToTrack, isFavorite } = useTrackReaction();
const { currentPlaylist, setCurrentPlaylist, setCurrentTrack, currentTrack } = useContext(playerContext);
const handlePlaylistPlayPause = (index?: number) => {
if (currentPlaylist?.id !== playlist?.id && playlist?.tracks) {
setCurrentPlaylist({ id: playlist.id, name: playlist.name, thumbnail: playlist.images[0].url, tracks: playlist.tracks.items });
setCurrentTrack(playlist.tracks.items[index ?? 0].track);
} else {
audioPlayer.stop().catch((error) => console.error("Failed to stop audio player: ", error));
setCurrentTrack(undefined);
setCurrentPlaylist(undefined);
const handlePlaylistPlayPause = (index: number) => {
if (playlist && currentPlaylist?.id !== playlist.id) {
const globalPlaylistObj = { id: playlist.id, name: playlist.name, thumbnail: playlist.images[0].url, tracks: playlist.tracks.items };
setCurrentPlaylist(globalPlaylistObj);
setCurrentTrack(playlist.tracks.items[index].track);
}
};

View File

@ -1,21 +1,44 @@
import { useQueryClient } from "react-query";
import { InfiniteData, useQueryClient } from "react-query";
import { QueryCacheKeys } from "../conf";
import useSpotifyInfiniteQuery from "./useSpotifyInfiniteQuery";
import useSpotifyMutation from "./useSpotifyMutation";
import useSpotifyQuery from "./useSpotifyQuery";
function usePlaylistReaction() {
const queryClient = useQueryClient();
const { data: favoritePlaylists } = useSpotifyQuery<SpotifyApi.PlaylistObjectSimplified[]>(QueryCacheKeys.userPlaylists, (spotifyApi) =>
spotifyApi.getUserPlaylists().then((userPlaylists) => userPlaylists.body.items)
const { data: favoritePagedPlaylists } = useSpotifyInfiniteQuery<SpotifyApi.ListOfUsersPlaylistsResponse>(QueryCacheKeys.userPlaylists, (spotifyApi, { pageParam }) =>
spotifyApi.getUserPlaylists({ limit: 20, offset: pageParam }).then((userPlaylists) => {
return userPlaylists.body;
})
);
const favoritePlaylists = favoritePagedPlaylists?.pages
.map((playlist) => playlist.items)
.filter(Boolean)
.flat(1) as SpotifyApi.PlaylistObjectSimplified[];
function updateFunction(playlist: SpotifyApi.PlaylistObjectSimplified, old?: InfiniteData<SpotifyApi.ListOfUsersPlaylistsResponse>): InfiniteData<SpotifyApi.ListOfUsersPlaylistsResponse> {
const obj: typeof old = {
pageParams: old?.pageParams ?? [],
pages:
old?.pages.map(
(oldPage, index): SpotifyApi.ListOfUsersPlaylistsResponse => {
const isPlaylistFavorite = isFavorite(playlist.id);
if (index === 0 && !isPlaylistFavorite) {
return { ...oldPage, items: [...oldPage.items, playlist] };
} else if (isPlaylistFavorite) {
return { ...oldPage, items: oldPage.items.filter((oldPlaylist) => oldPlaylist.id !== playlist.id) };
}
return oldPage;
}
) ?? [],
};
return obj;
}
const { mutate: reactToPlaylist } = useSpotifyMutation<{}, SpotifyApi.PlaylistObjectSimplified>(
(spotifyApi, { id }) => spotifyApi[isFavorite(id) ? "unfollowPlaylist" : "followPlaylist"](id).then((res) => res.body),
{
onSuccess(_, playlist) {
queryClient.setQueryData<SpotifyApi.PlaylistObjectSimplified[]>(
QueryCacheKeys.userPlaylists,
isFavorite(playlist.id) ? (old) => (old ?? []).filter((oldPlaylist) => oldPlaylist.id !== playlist.id) : (old) => [...(old ?? []), playlist]
);
queryClient.setQueryData<InfiniteData<SpotifyApi.ListOfUsersPlaylistsResponse>>(QueryCacheKeys.userPlaylists, (old) => updateFunction(playlist, old));
},
}
);

View File

@ -7,17 +7,23 @@ import showError from "../helpers/showError";
function useSpotifyApiError(spotifyApi: SpotifyWebApi) {
const { setAccess_token, isLoggedIn } = useContext(authContext);
return async (error: any | Error | TypeError) => {
if ((error.message === "Unauthorized" && error.status === 401 && isLoggedIn) || (error.body.error.message === "No token provided" && error.body.error.status===401)) {
const isUnauthorized = error.message === "Unauthorized";
const status401 = error.status === 401;
const bodyStatus401 = error.body.error.status === 401;
const noToken = error.body.error.message === "No token provided";
const expiredToken = error.body.error.message === "The access token expired";
if ((isUnauthorized && isLoggedIn && status401) || ((noToken || expiredToken) && bodyStatus401)) {
try {
console.log(chalk.bgYellow.blackBright("Refreshing Access token"))
const { body:{access_token: refreshedAccessToken}} = await spotifyApi.refreshAccessToken();
console.log(chalk.bgYellow.blackBright("Refreshing Access token"));
const {
body: { access_token: refreshedAccessToken },
} = await spotifyApi.refreshAccessToken();
setAccess_token(refreshedAccessToken);
} catch (error) {
showError(error, "[Authorization Failure]: ")
showError(error, "[Authorization Failure]: ");
}
}
};
}
export default useSpotifyApiError;

View File

@ -1,8 +1,7 @@
import { useQueryClient } from "react-query";
import { InfiniteData, useQueryClient } from "react-query";
import { QueryCacheKeys } from "../conf";
import useSpotifyInfiniteQuery from "./useSpotifyInfiniteQuery";
import useSpotifyMutation from "./useSpotifyMutation";
import useSpotifyQuery from "./useSpotifyQuery";
function useTrackReaction() {
const queryClient = useQueryClient();
@ -13,14 +12,31 @@ function useTrackReaction() {
?.map((page) => page.items)
.filter(Boolean)
.flat(1) as SpotifyApi.SavedTrackObject[] | undefined;
function updateFunction(track: SpotifyApi.SavedTrackObject, old?: InfiniteData<SpotifyApi.UsersSavedTracksResponse>): InfiniteData<SpotifyApi.UsersSavedTracksResponse> {
const obj: typeof old = {
pageParams: old?.pageParams ?? [],
pages:
old?.pages.map(
(oldPage, index): SpotifyApi.UsersSavedTracksResponse => {
const isTrackFavorite = isFavorite(track.track.id);
if (index === 0 && !isTrackFavorite) {
return { ...oldPage, items: [...oldPage.items, track] };
} else if (isTrackFavorite) {
return { ...oldPage, items: oldPage.items.filter((oldTrack) => oldTrack.track.id !== track.track.id) };
}
return oldPage;
}
) ?? [],
};
return obj;
}
const { mutate: reactToTrack } = useSpotifyMutation<{}, SpotifyApi.SavedTrackObject>(
(spotifyApi, { track }) => spotifyApi[isFavorite(track.id) ? "removeFromMySavedTracks" : "addToMySavedTracks"]([track.id]).then((res) => res.body),
{
onSuccess(_, track) {
queryClient.setQueryData<SpotifyApi.SavedTrackObject[]>(
QueryCacheKeys.userSavedTracks,
isFavorite(track.track.id) ? (old) => (old ?? []).filter((oldTrack) => oldTrack.track.id !== track.track.id) : (old) => [...(old ?? []), track]
);
queryClient.setQueryData<InfiniteData<SpotifyApi.UsersSavedTracksResponse>>(QueryCacheKeys.userSavedTracks, (old) => updateFunction(track, old));
},
}
);