YesPlayMusic/packages/web/api/hooks/useUserLikedTracksIDs.ts

93 lines
2.9 KiB
TypeScript
Raw Normal View History

2022-05-12 02:45:43 +08:00
import { likeATrack } from '@/web/api/track'
2022-04-05 02:30:07 +08:00
import useUser from './useUser'
2022-08-03 23:48:39 +08:00
import { useMutation, useQueryClient } from '@tanstack/react-query'
2022-04-16 21:14:03 +08:00
import { IpcChannels } from '@/shared/IpcChannels'
2023-01-28 11:54:57 +08:00
import { CacheAPIs } from '@/shared/CacheAPIs'
2022-05-29 17:53:27 +08:00
import { fetchUserLikedTracksIDs } from '../user'
2023-01-28 11:54:57 +08:00
import { FetchUserLikedTracksIDsResponse, UserApiNames } from '@/shared/api/User'
2022-08-03 23:48:39 +08:00
import { useQuery } from '@tanstack/react-query'
2022-05-12 02:45:43 +08:00
import toast from 'react-hot-toast'
2022-08-03 23:48:39 +08:00
import reactQueryClient from '@/web/utils/reactQueryClient'
2022-04-05 02:30:07 +08:00
export default function useUserLikedTracksIDs() {
const { data: user } = useUser()
const uid = user?.account?.id ?? 0
2022-10-28 20:29:04 +08:00
const key = [UserApiNames.FetchUserLikedTracksIds, uid]
2022-04-05 02:30:07 +08:00
return useQuery(
2022-10-28 20:29:04 +08:00
key,
() => {
const existsQueryData = reactQueryClient.getQueryData(key)
if (!existsQueryData) {
window.ipcRenderer
?.invoke(IpcChannels.GetApiCache, {
2023-01-28 11:54:57 +08:00
api: CacheAPIs.Likelist,
2022-10-28 20:29:04 +08:00
query: {
uid,
},
})
.then(cache => {
if (cache) reactQueryClient.setQueryData(key, cache)
})
}
return fetchUserLikedTracksIDs({ uid })
},
2022-04-05 02:30:07 +08:00
{
enabled: !!(uid && uid !== 0),
refetchOnWindowFocus: true,
}
)
}
export const useMutationLikeATrack = () => {
const { data: user } = useUser()
const { data: userLikedSongs } = useUserLikedTracksIDs()
const uid = user?.account?.id ?? 0
const key = [UserApiNames.FetchUserLikedTracksIds, uid]
2022-04-05 02:30:07 +08:00
return useMutation(
2022-04-05 21:23:55 +08:00
async (trackID: number) => {
2022-04-05 02:30:07 +08:00
if (!trackID || userLikedSongs?.ids === undefined) {
throw new Error('trackID is required or userLikedSongs is undefined')
}
2022-04-05 21:23:55 +08:00
const response = await likeATrack({
2022-04-05 02:30:07 +08:00
id: trackID,
like: !userLikedSongs.ids.includes(trackID),
})
2022-04-05 21:23:55 +08:00
if (response.code !== 200) throw new Error((response as any).msg)
return response
2022-04-05 02:30:07 +08:00
},
{
onMutate: async trackID => {
// Cancel any outgoing refetches (so they don't overwrite our optimistic update)
2022-08-03 23:48:39 +08:00
await reactQueryClient.cancelQueries(key)
2022-04-05 02:30:07 +08:00
// Snapshot the previous value
2022-08-03 23:48:39 +08:00
const previousData = reactQueryClient.getQueryData(key)
2022-04-05 02:30:07 +08:00
// Optimistically update to the new value
2022-08-03 23:48:39 +08:00
reactQueryClient.setQueryData(key, old => {
2022-04-05 02:30:07 +08:00
const likedSongs = old as FetchUserLikedTracksIDsResponse
const ids = likedSongs.ids
const newIds = ids.includes(trackID)
? ids.filter(id => id !== trackID)
: [...ids, trackID]
return {
...likedSongs,
ids: newIds,
}
})
// Return a context object with the snapshotted value
return { previousData }
},
// If the mutation fails, use the context returned from onMutate to roll back
onError: (err, trackID, context) => {
2022-08-03 23:48:39 +08:00
reactQueryClient.setQueryData(key, (context as any).previousData)
2022-04-05 21:23:55 +08:00
toast((err as any).toString())
2022-04-05 02:30:07 +08:00
},
}
)
}