YesPlayMusic/packages/web/api/hooks/useUserAlbums.ts
2022-08-03 23:48:39 +08:00

124 lines
4.0 KiB
TypeScript

import { likeAAlbum } from '@/web/api/album'
import { useMutation, useQuery } from '@tanstack/react-query'
import useUser from './useUser'
import { IpcChannels } from '@/shared/IpcChannels'
import { APIs } from '@/shared/CacheAPIs'
import {
FetchUserAlbumsParams,
UserApiNames,
FetchUserAlbumsResponse,
} from '@/shared/api/User'
import { fetchUserAlbums } from '../user'
import toast from 'react-hot-toast'
import reactQueryClient from '@/web/utils/reactQueryClient'
import { cloneDeep } from 'lodash-es'
import { AlbumApiNames, FetchAlbumResponse } from '@/shared/api/Album'
export default function useUserAlbums(params: FetchUserAlbumsParams = {}) {
const { data: user } = useUser()
const uid = user?.profile?.userId ?? 0
return useQuery(
[UserApiNames.FetchUserAlbums, uid],
() => fetchUserAlbums(params),
{
refetchOnWindowFocus: true,
placeholderData: (): FetchUserAlbumsResponse | undefined =>
window.ipcRenderer?.sendSync(IpcChannels.GetApiCacheSync, {
api: APIs.UserAlbums,
query: params,
}),
}
)
}
export const useMutationLikeAAlbum = () => {
const { data: user } = useUser()
const { data: userAlbums } = useUserAlbums({ limit: 2000 })
const uid = user?.profile?.userId ?? 0
const key = [UserApiNames.FetchUserAlbums, uid]
return useMutation(
async (albumID: number) => {
if (!albumID || userAlbums?.data === undefined) {
throw new Error('album id is required or userAlbums is undefined')
}
const response = await likeAAlbum({
id: albumID,
t: userAlbums?.data.findIndex(a => a.id === albumID) > -1 ? 2 : 1,
})
if (response.code !== 200) throw new Error((response as any).msg)
return response
},
{
onMutate: async albumID => {
// Cancel any outgoing refetches (so they don't overwrite our optimistic update)
await reactQueryClient.cancelQueries(key)
console.log(reactQueryClient.getQueryData(key))
// 如果还未获取用户收藏的专辑列表,则获取一次
if (!reactQueryClient.getQueryData(key)) {
await reactQueryClient.fetchQuery(key)
}
// Snapshot the previous value
const previousData = reactQueryClient.getQueryData(
key
) as FetchUserAlbumsResponse
const isLiked = !!previousData?.data.find(a => a.id === albumID)
const newAlbums = cloneDeep(previousData!)
console.log({ isLiked })
if (isLiked) {
newAlbums.data = previousData.data.filter(a => a.id !== albumID)
} else {
// 从react-query缓存获取专辑
console.log({ albumID })
const albumFromCache: FetchAlbumResponse | undefined =
reactQueryClient.getQueryData([
AlbumApiNames.FetchAlbum,
{ id: albumID },
])
console.log({ albumFromCache })
// 从api获取专辑
const album: FetchAlbumResponse | undefined = albumFromCache
? albumFromCache
: await reactQueryClient.fetchQuery([
AlbumApiNames.FetchAlbum,
{ id: albumID },
])
if (!album?.album) {
toast.error('Failed to like album: unable to fetch album info')
throw new Error('unable to fetch album info')
}
newAlbums.data.unshift(album.album)
// Optimistically update to the new value
reactQueryClient.setQueriesData(key, newAlbums)
}
reactQueryClient.setQueriesData(key, newAlbums)
console.log({ newAlbums })
// Return a context object with the snapshotted value
return { previousData }
},
// If the mutation fails, use the context returned from onMutate to roll back
onSettled: (data, error, albumID, context) => {
if (data?.code !== 200) {
reactQueryClient.setQueryData(key, (context as any).previousData)
toast((error as any).toString())
}
},
}
)
}