mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
fixed useTrackReaction & usePlaylistReaction mutation bugs... handleSpotifyError bug fixed
This commit is contained in:
parent
5a1da660a1
commit
2d42bbd23d
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -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;
|
@ -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));
|
||||
},
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user