diff --git a/src/renderer/components/virtual-table/hooks/use-rating.ts b/src/renderer/components/virtual-table/hooks/use-rating.ts index 3f7ff1f7..0d284c6f 100644 --- a/src/renderer/components/virtual-table/hooks/use-rating.ts +++ b/src/renderer/components/virtual-table/hooks/use-rating.ts @@ -5,36 +5,31 @@ import { NDAlbumDetail, NDAlbumArtistDetail } from '/@/renderer/api/navidrome.ty import { queryKeys } from '/@/renderer/api/query-keys'; import { SSAlbumDetail, SSAlbumArtistDetail } from '/@/renderer/api/subsonic.types'; import { - RawRatingResponse, - RatingArgs, + SetRatingArgs, Album, AlbumArtist, LibraryItem, AnyLibraryItems, + RatingResponse, } from '/@/renderer/api/types'; -import { - useCurrentServer, - useSetAlbumListItemDataById, - useSetQueueRating, - useAuthStore, -} from '/@/renderer/store'; +import { useSetAlbumListItemDataById, useSetQueueRating, getServerById } from '/@/renderer/store'; import { ServerType } from '/@/renderer/types'; export const useUpdateRating = () => { const queryClient = useQueryClient(); - const currentServer = useCurrentServer(); const setAlbumListData = useSetAlbumListItemDataById(); const setQueueRating = useSetQueueRating(); return useMutation< - RawRatingResponse, + RatingResponse, HTTPError, - Omit, + Omit, { previous: { items: AnyLibraryItems } | undefined } >({ mutationFn: (args) => { - const server = useAuthStore.getState().actions.getServer(args._serverId) || currentServer; - return api.controller.updateRating({ ...args, server }); + const server = getServerById(args.serverId); + if (!server) throw new Error('Server not found'); + return api.controller.updateRating({ ...args, apiClientProps: { server } }); }, onError: (_error, _variables, context) => { for (const item of context?.previous?.items || []) { diff --git a/src/renderer/features/artists/queries/album-artist-list-query.ts b/src/renderer/features/artists/queries/album-artist-list-query.ts index bc50f338..37f0a8cb 100644 --- a/src/renderer/features/artists/queries/album-artist-list-query.ts +++ b/src/renderer/features/artists/queries/album-artist-list-query.ts @@ -13,7 +13,7 @@ export const useAlbumArtistList = (args: QueryHookArgs) => enabled: !!server?.id, queryFn: ({ signal }) => { if (!server) throw new Error('Server not found'); - api.controller.getAlbumArtistList({ apiClientProps: { server, signal }, query }); + return api.controller.getAlbumArtistList({ apiClientProps: { server, signal }, query }); }, queryKey: queryKeys.albumArtists.list(server?.id || '', query), ...options, diff --git a/src/renderer/features/genres/queries/genre-list-query.ts b/src/renderer/features/genres/queries/genre-list-query.ts index 41179b8a..317e6bff 100644 --- a/src/renderer/features/genres/queries/genre-list-query.ts +++ b/src/renderer/features/genres/queries/genre-list-query.ts @@ -1,24 +1,22 @@ -import { useCallback } from 'react'; import { useQuery } from '@tanstack/react-query'; import { controller } from '/@/renderer/api/controller'; import { queryKeys } from '/@/renderer/api/query-keys'; -import type { GenreListQuery, RawGenreListResponse } from '/@/renderer/api/types'; -import type { QueryOptions } from '/@/renderer/lib/react-query'; -import { useCurrentServer } from '/@/renderer/store'; -import { api } from '/@/renderer/api'; +import type { GenreListQuery } from '/@/renderer/api/types'; +import type { QueryHookArgs } from '/@/renderer/lib/react-query'; +import { getServerById } from '/@/renderer/store'; -export const useGenreList = (query: GenreListQuery, options?: QueryOptions) => { - const server = useCurrentServer(); +export const useGenreList = (args: QueryHookArgs) => { + const { options, query, serverId } = args || {}; + const server = getServerById(serverId); return useQuery({ cacheTime: 1000 * 60 * 60 * 2, - enabled: !!server?.id, - queryFn: ({ signal }) => controller.getGenreList({ query, server, signal }), + enabled: !!server, + queryFn: ({ signal }) => { + if (!server) throw new Error('Server not found'); + return controller.getGenreList({ apiClientProps: { server, signal }, query }); + }, queryKey: queryKeys.genres.list(server?.id || ''), - select: useCallback( - (data: RawGenreListResponse | undefined) => api.normalize.genreList(data, server), - [server], - ), staleTime: 1000 * 60 * 60, ...options, }); diff --git a/src/renderer/features/player/mutations/scrobble-mutation.ts b/src/renderer/features/player/mutations/scrobble-mutation.ts index c6232570..413782f3 100644 --- a/src/renderer/features/player/mutations/scrobble-mutation.ts +++ b/src/renderer/features/player/mutations/scrobble-mutation.ts @@ -8,7 +8,12 @@ import { getServerById, useIncrementQueuePlayCount } from '/@/renderer/store'; export const useSendScrobble = (options?: MutationOptions) => { const incrementPlayCount = useIncrementQueuePlayCount(); - return useMutation, null>({ + return useMutation< + ScrobbleResponse, + HTTPError, + Omit, + null + >({ mutationFn: (args) => { const server = getServerById(args.serverId); if (!server) throw new Error('Server not found'); diff --git a/src/renderer/features/playlists/mutations/add-to-playlist-mutation.ts b/src/renderer/features/playlists/mutations/add-to-playlist-mutation.ts index e991bac9..8945374e 100644 --- a/src/renderer/features/playlists/mutations/add-to-playlist-mutation.ts +++ b/src/renderer/features/playlists/mutations/add-to-playlist-mutation.ts @@ -23,6 +23,9 @@ export const useAddToPlaylist = (args: MutationHookArgs) => { }, onSuccess: (_data, variables) => { const { serverId } = variables; + + if (!serverId) return; + queryClient.invalidateQueries(queryKeys.playlists.list(serverId), { exact: false }); queryClient.invalidateQueries(queryKeys.playlists.detail(serverId, variables.query.id)); queryClient.invalidateQueries( diff --git a/src/renderer/features/playlists/mutations/create-playlist-mutation.ts b/src/renderer/features/playlists/mutations/create-playlist-mutation.ts index d7aac6e7..3116a165 100644 --- a/src/renderer/features/playlists/mutations/create-playlist-mutation.ts +++ b/src/renderer/features/playlists/mutations/create-playlist-mutation.ts @@ -1,14 +1,12 @@ -import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useMutation } from '@tanstack/react-query'; import { HTTPError } from 'ky'; import { api } from '/@/renderer/api'; -import { queryKeys } from '/@/renderer/api/query-keys'; import { CreatePlaylistArgs, CreatePlaylistResponse } from '/@/renderer/api/types'; import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById } from '/@/renderer/store'; export const useCreatePlaylist = (args: MutationHookArgs) => { const { options } = args || {}; - const queryClient = useQueryClient(); return useMutation< CreatePlaylistResponse, @@ -21,10 +19,6 @@ export const useCreatePlaylist = (args: MutationHookArgs) => { if (!server) throw new Error('Server not found'); return api.controller.createPlaylist({ ...args, apiClientProps: { server } }); }, - onSuccess: (_data, variables) => { - const serverId = variables.serverId; - queryClient.invalidateQueries(queryKeys.playlists.list(serverId), { exact: false }); - }, ...options, }); }; diff --git a/src/renderer/features/playlists/mutations/remove-from-playlist-mutation.ts b/src/renderer/features/playlists/mutations/remove-from-playlist-mutation.ts index 76e373ea..51c71124 100644 --- a/src/renderer/features/playlists/mutations/remove-from-playlist-mutation.ts +++ b/src/renderer/features/playlists/mutations/remove-from-playlist-mutation.ts @@ -22,6 +22,9 @@ export const useRemoveFromPlaylist = (options?: MutationOptions) => { }, onSuccess: (_data, variables) => { const { serverId } = variables; + + if (!serverId) return; + queryClient.invalidateQueries(queryKeys.playlists.list(serverId), { exact: false }); queryClient.invalidateQueries(queryKeys.playlists.detail(serverId, variables.query.id)); queryClient.invalidateQueries( diff --git a/src/renderer/features/playlists/mutations/update-playlist-mutation.ts b/src/renderer/features/playlists/mutations/update-playlist-mutation.ts index f6af55a1..58f0afd5 100644 --- a/src/renderer/features/playlists/mutations/update-playlist-mutation.ts +++ b/src/renderer/features/playlists/mutations/update-playlist-mutation.ts @@ -10,7 +10,12 @@ export const useUpdatePlaylist = (args: MutationHookArgs) => { const { options } = args || {}; const queryClient = useQueryClient(); - return useMutation, null>({ + return useMutation< + UpdatePlaylistResponse, + HTTPError, + Omit, + null + >({ mutationFn: (args) => { const server = getServerById(args.serverId); if (!server) throw new Error('Server not found'); @@ -18,6 +23,9 @@ export const useUpdatePlaylist = (args: MutationHookArgs) => { }, onSuccess: (_data, variables) => { const { query, serverId } = variables; + + if (!serverId) return; + queryClient.invalidateQueries(queryKeys.playlists.list(serverId)); if (query?.id) { diff --git a/src/renderer/features/playlists/queries/playlist-song-list-query.ts b/src/renderer/features/playlists/queries/playlist-song-list-query.ts index 796c66b3..a18010e0 100644 --- a/src/renderer/features/playlists/queries/playlist-song-list-query.ts +++ b/src/renderer/features/playlists/queries/playlist-song-list-query.ts @@ -1,6 +1,6 @@ import { useQuery, useInfiniteQuery } from '@tanstack/react-query'; import { queryKeys } from '/@/renderer/api/query-keys'; -import type { PlaylistSongListQuery, SongListResponse } from '/@/renderer/api/types'; +import type { PlaylistSongListQuery, PlaylistSongListResponse } from '/@/renderer/api/types'; import type { QueryHookArgs } from '/@/renderer/lib/react-query'; import { getServerById } from '/@/renderer/store'; import { api } from '/@/renderer/api'; @@ -10,10 +10,10 @@ export const usePlaylistSongList = (args: QueryHookArgs) const server = getServerById(serverId); return useQuery({ - enabled: !!server?.id, + enabled: !!server, queryFn: ({ signal }) => { if (!server) throw new Error('Server not found'); - api.controller.getPlaylistSongList({ apiClientProps: { server, signal }, query }); + return api.controller.getPlaylistSongList({ apiClientProps: { server, signal }, query }); }, queryKey: queryKeys.playlists.songList(server?.id || '', query.id, query), ...options, @@ -25,24 +25,22 @@ export const usePlaylistSongListInfinite = (args: QueryHookArgs { + enabled: !!server, + getNextPageParam: (lastPage: PlaylistSongListResponse | undefined, pages) => { if (!lastPage?.items) return undefined; if (lastPage?.items?.length >= (query?.limit || 50)) { - return allPages?.length; + return pages?.length; } return undefined; }, queryFn: ({ pageParam = 0, signal }) => { return api.controller.getPlaylistSongList({ + apiClientProps: { server, signal }, query: { ...query, limit: query.limit || 50, startIndex: pageParam * (query.limit || 50) }, - server, - signal, }); }, queryKey: queryKeys.playlists.detailSongList(server?.id || '', query.id, query), - ...options, }); }; diff --git a/src/renderer/features/shared/mutations/create-favorite-mutation.ts b/src/renderer/features/shared/mutations/create-favorite-mutation.ts index 33957bf0..8eb38b62 100644 --- a/src/renderer/features/shared/mutations/create-favorite-mutation.ts +++ b/src/renderer/features/shared/mutations/create-favorite-mutation.ts @@ -1,4 +1,4 @@ -import { useMutation } from '@tanstack/react-query'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; import { HTTPError } from 'ky'; import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; @@ -9,11 +9,12 @@ import { FavoriteResponse, LibraryItem, } from '/@/renderer/api/types'; -import { MutationHookArgs, queryClient } from '/@/renderer/lib/react-query'; +import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById, useSetAlbumListItemDataById, useSetQueueFavorite } from '/@/renderer/store'; -export const useCreateFavorite = (args?: MutationHookArgs) => { +export const useCreateFavorite = (args: MutationHookArgs) => { const { options } = args || {}; + const queryClient = useQueryClient(); const setAlbumListData = useSetAlbumListItemDataById(); const setQueueFavorite = useSetQueueFavorite(); @@ -30,6 +31,9 @@ export const useCreateFavorite = (args?: MutationHookArgs) => { }, onSuccess: (_data, variables) => { const { serverId } = variables; + + if (!serverId) return; + for (const id of variables.query.id) { // Set the userFavorite property to true for the album in the album list data store if (variables.query.type === LibraryItem.ALBUM) { diff --git a/src/renderer/features/shared/mutations/delete-favorite-mutation.ts b/src/renderer/features/shared/mutations/delete-favorite-mutation.ts index b4e6b780..f386f3dc 100644 --- a/src/renderer/features/shared/mutations/delete-favorite-mutation.ts +++ b/src/renderer/features/shared/mutations/delete-favorite-mutation.ts @@ -1,4 +1,4 @@ -import { useMutation } from '@tanstack/react-query'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; import { HTTPError } from 'ky'; import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; @@ -9,12 +9,12 @@ import { FavoriteResponse, LibraryItem, } from '/@/renderer/api/types'; -import { MutationHookArgs, queryClient } from '/@/renderer/lib/react-query'; +import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById, useSetAlbumListItemDataById, useSetQueueFavorite } from '/@/renderer/store'; export const useDeleteFavorite = (args: MutationHookArgs) => { const { options } = args || {}; - // const queryClient = useQueryClient(); + const queryClient = useQueryClient(); const setAlbumListData = useSetAlbumListItemDataById(); const setQueueFavorite = useSetQueueFavorite(); @@ -31,6 +31,9 @@ export const useDeleteFavorite = (args: MutationHookArgs) => { }, onSuccess: (_data, variables) => { const { serverId } = variables; + + if (!serverId) return; + for (const id of variables.query.id) { // Set the userFavorite property to false for the album in the album list data store if (variables.query.type === LibraryItem.ALBUM) { diff --git a/src/renderer/features/shared/mutations/set-rating-mutation.ts b/src/renderer/features/shared/mutations/set-rating-mutation.ts index 372a96f5..6f77a70a 100644 --- a/src/renderer/features/shared/mutations/set-rating-mutation.ts +++ b/src/renderer/features/shared/mutations/set-rating-mutation.ts @@ -1,9 +1,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { HTTPError } from 'ky'; import { api } from '/@/renderer/api'; -import { NDAlbumArtistDetail, NDAlbumDetail } from '/@/renderer/api/navidrome.types'; import { queryKeys } from '/@/renderer/api/query-keys'; -import { SSAlbumArtistDetail, SSAlbumDetail } from '/@/renderer/api/subsonic.types'; import { Album, AlbumArtist, @@ -11,7 +9,8 @@ import { LibraryItem, SetRatingArgs, RatingResponse, - ServerType, + AlbumDetailResponse, + AlbumArtistDetailResponse, } from '/@/renderer/api/types'; import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById, useSetAlbumListItemDataById, useSetQueueRating } from '/@/renderer/store'; @@ -65,61 +64,35 @@ export const useSetRating = (args: MutationHookArgs) => { variables.query.item.length === 1 && variables.query.item[0].itemType === LibraryItem.ALBUM; if (isAlbumDetailPage) { - const { serverType, id: albumId, serverId } = variables.query.item[0] as Album; + const { id: albumId, serverId } = variables.query.item[0] as Album; const queryKey = queryKeys.albums.detail(serverId || '', { id: albumId }); - const previous = queryClient.getQueryData(queryKey); + const previous = queryClient.getQueryData(queryKey); if (previous) { - switch (serverType) { - case ServerType.NAVIDROME: - queryClient.setQueryData(queryKey, { - ...previous, - rating: variables.query.rating, - }); - break; - case ServerType.SUBSONIC: - queryClient.setQueryData(queryKey, { - ...previous, - userRating: variables.query.rating, - }); - break; - case ServerType.JELLYFIN: - // Jellyfin does not support ratings - break; - } + queryClient.setQueryData(queryKey, { + ...previous, + userRating: variables.query.rating, + }); } } - // We only need to set if we're already on the album detail page + // We only need to set if we're already on the album artist detail page const isAlbumArtistDetailPage = variables.query.item.length === 1 && variables.query.item[0].itemType === LibraryItem.ALBUM_ARTIST; if (isAlbumArtistDetailPage) { - const { serverType, id: albumArtistId, serverId } = variables.query.item[0] as AlbumArtist; + const { id: albumArtistId, serverId } = variables.query.item[0] as AlbumArtist; const queryKey = queryKeys.albumArtists.detail(serverId || '', { id: albumArtistId, }); - const previous = queryClient.getQueryData(queryKey); + const previous = queryClient.getQueryData(queryKey); if (previous) { - switch (serverType) { - case ServerType.NAVIDROME: - queryClient.setQueryData(queryKey, { - ...previous, - rating: variables.query.rating, - }); - break; - case ServerType.SUBSONIC: - queryClient.setQueryData(queryKey, { - ...previous, - userRating: variables.query.rating, - }); - break; - case ServerType.JELLYFIN: - // Jellyfin does not support ratings - break; - } + queryClient.setQueryData(queryKey, { + ...previous, + userRating: variables.query.rating, + }); } } }, diff --git a/src/renderer/features/shared/queries/music-folders-query.ts b/src/renderer/features/shared/queries/music-folders-query.ts index cca19f03..dff73a0e 100644 --- a/src/renderer/features/shared/queries/music-folders-query.ts +++ b/src/renderer/features/shared/queries/music-folders-query.ts @@ -1,23 +1,22 @@ -import { useCallback } from 'react'; import { useQuery } from '@tanstack/react-query'; import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; -import { useCurrentServer } from '/@/renderer/store'; -import { RawMusicFolderListResponse } from '/@/renderer/api/types'; +import { getServerById } from '/@/renderer/store'; +import { MusicFolderListQuery } from '../../../api/types'; +import { QueryHookArgs } from '../../../lib/react-query'; -export const useMusicFolders = () => { - const server = useCurrentServer(); +export const useMusicFolders = (args: QueryHookArgs) => { + const { options, serverId } = args || {}; + const server = getServerById(serverId); const query = useQuery({ - enabled: !!server?.id, - queryFn: ({ signal }) => api.controller.getMusicFolderList({ server, signal }), + enabled: !!server, + queryFn: ({ signal }) => { + if (!server) throw new Error('Server not found'); + return api.controller.getMusicFolderList({ apiClientProps: { server, signal } }); + }, queryKey: queryKeys.musicFolders.list(server?.id || ''), - select: useCallback( - (data: RawMusicFolderListResponse | undefined) => { - return api.normalize.musicFolderList(data, server); - }, - [server], - ), + ...options, }); return query; diff --git a/src/renderer/features/songs/queries/song-list-query.ts b/src/renderer/features/songs/queries/song-list-query.ts index fc691f54..43826ea3 100644 --- a/src/renderer/features/songs/queries/song-list-query.ts +++ b/src/renderer/features/songs/queries/song-list-query.ts @@ -13,7 +13,7 @@ export const useSongList = (args: QueryHookArgs) => { enabled: !!server?.id, queryFn: ({ signal }) => { if (!server) throw new Error('Server not found'); - controller.getSongList({ apiClientProps: { server, signal }, query }); + return controller.getSongList({ apiClientProps: { server, signal }, query }); }, queryKey: queryKeys.songs.list(server?.id || '', query), ...options, diff --git a/src/renderer/lib/react-query.ts b/src/renderer/lib/react-query.ts index a5db0882..e5233761 100644 --- a/src/renderer/lib/react-query.ts +++ b/src/renderer/lib/react-query.ts @@ -5,7 +5,7 @@ import type { UseInfiniteQueryOptions, } from '@tanstack/react-query'; import { QueryClient, QueryCache } from '@tanstack/react-query'; -import { toast } from '/@/renderer/components'; +import { toast } from '/@/renderer/components/toast/index'; const queryCache = new QueryCache({ onError: (error: any, query) => { @@ -39,7 +39,7 @@ export const queryClient = new QueryClient({ export type QueryHookArgs = { options?: QueryOptions; query: T; - serverId?: string; + serverId: string | undefined; }; export type MutationHookArgs = {