From 0145a58c9582c535d439d278cb830705b2de9f44 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 8 Jul 2026 10:03:10 -0400 Subject: [PATCH] Refactor useMovieRecommendations hook --- .../components/SuggestionsSectionView.tsx | 18 +++++--- .../hooks/api/useMovieRecommendations.ts | 43 +++++++++++++++++++ src/hooks/useFetchItems.ts | 36 ---------------- 3 files changed, 56 insertions(+), 41 deletions(-) create mode 100644 src/apps/modern/features/libraries/hooks/api/useMovieRecommendations.ts diff --git a/src/apps/modern/features/libraries/components/SuggestionsSectionView.tsx b/src/apps/modern/features/libraries/components/SuggestionsSectionView.tsx index 8322b22326..3e9abc04ed 100644 --- a/src/apps/modern/features/libraries/components/SuggestionsSectionView.tsx +++ b/src/apps/modern/features/libraries/components/SuggestionsSectionView.tsx @@ -1,13 +1,11 @@ +import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields'; import type { RecommendationDto } from '@jellyfin/sdk/lib/generated-client/models/recommendation-dto'; import { RecommendationType } from '@jellyfin/sdk/lib/generated-client/models/recommendation-type'; import React, { type FC } from 'react'; import { CardShape } from 'components/cardbuilder/utils/shape'; import { useApi } from 'hooks/useApi'; -import { - useGetMovieRecommendations, - useGetSuggestionSectionsWithItems -} from 'hooks/useFetchItems'; +import { useGetSuggestionSectionsWithItems } from 'hooks/useFetchItems'; import { appRouter } from 'components/router/appRouter'; import globalize from 'lib/globalize'; import Loading from 'components/loading/LoadingComponent'; @@ -17,6 +15,8 @@ import type { ParentId } from 'types/library'; import type { Section, SectionType } from 'types/sections'; import type { ItemDto } from 'types/base/models/item-dto'; +import { useMovieRecommendations } from '../hooks/api/useMovieRecommendations'; + interface SuggestionsSectionViewProps { parentId: ParentId; sectionType: SectionType[]; @@ -35,7 +35,15 @@ const SuggestionsSectionView: FC = ({ const { isLoading: isRecommendationsLoading, data: movieRecommendationsItems - } = useGetMovieRecommendations(isMovieRecommendationEnabled, parentId); + } = useMovieRecommendations({ + parentId: parentId || undefined, + fields: [ + ItemFields.PrimaryImageAspectRatio, + ItemFields.MediaSourceCount + ], + categoryLimit: 6, + itemLimit: 20 + }, isMovieRecommendationEnabled); if (isLoading || isRecommendationsLoading) { return ; diff --git a/src/apps/modern/features/libraries/hooks/api/useMovieRecommendations.ts b/src/apps/modern/features/libraries/hooks/api/useMovieRecommendations.ts new file mode 100644 index 0000000000..1e281bb86b --- /dev/null +++ b/src/apps/modern/features/libraries/hooks/api/useMovieRecommendations.ts @@ -0,0 +1,43 @@ +import type { Api } from '@jellyfin/sdk/lib/api'; +import type { MovieApiGetMovieRecommendationsRequest } from '@jellyfin/sdk/lib/generated-client/api/movie-api'; +import { getMovieApi } from '@jellyfin/sdk/lib/utils/api/movie-api'; +import { queryOptions, useQuery } from '@tanstack/react-query'; +import type { AxiosRequestConfig } from 'axios'; + +import { useApi } from 'hooks/useApi'; + +const fetchGetMovieRecommendations = async ( + api: Api, + params: MovieApiGetMovieRecommendationsRequest, + options?: AxiosRequestConfig +) => { + const response = await getMovieApi(api).getMovieRecommendations(params, options); + return response.data; +}; + +/** Query options for fetching movie recommendations. */ +export const getMovieRecommendationsQuery = ( + api?: Api, + params: MovieApiGetMovieRecommendationsRequest = {}, + enabled = true +) => queryOptions({ + queryKey: ['MovieRecommendations', params?.parentId], + queryFn: ({ signal }) => fetchGetMovieRecommendations(api!, params, { signal }), + enabled: !!api && enabled +}); + +/** Hook for fetching movie recommendations. */ +export const useMovieRecommendations = ( + params?: MovieApiGetMovieRecommendationsRequest, + enabled?: boolean +) => { + const { api, user } = useApi(); + return useQuery(getMovieRecommendationsQuery( + api, + { + ...params, + userId: params?.userId || user?.Id + }, + enabled + )); +}; diff --git a/src/hooks/useFetchItems.ts b/src/hooks/useFetchItems.ts index a55381f57a..caea795600 100644 --- a/src/hooks/useFetchItems.ts +++ b/src/hooks/useFetchItems.ts @@ -11,7 +11,6 @@ import { SortOrder } from '@jellyfin/sdk/lib/generated-client/models/sort-order' import { getArtistApi } from '@jellyfin/sdk/lib/utils/api/artist-api'; import { getFilterApi } from '@jellyfin/sdk/lib/utils/api/filter-api'; import { getGenreApi } from '@jellyfin/sdk/lib/utils/api/genre-api'; -import { getMovieApi } from '@jellyfin/sdk/lib/utils/api/movie-api'; import { getPersonApi } from '@jellyfin/sdk/lib/utils/api/person-api'; import { getStudioApi } from '@jellyfin/sdk/lib/utils/api/studio-api'; import { getShowApi } from '@jellyfin/sdk/lib/utils/api/show-api'; @@ -74,41 +73,6 @@ export const useGetItems = (parametersOptions: LibraryApiGetItemsRequest) => { }); }; -const fetchGetMovieRecommendations = async ( - currentApi: JellyfinApiContext, - parentId: ParentId, - options?: AxiosRequestConfig -) => { - const { api, user } = currentApi; - if (api && user?.Id) { - const response = await getMovieApi(api).getMovieRecommendations( - { - userId: user.Id, - fields: [ - ItemFields.PrimaryImageAspectRatio, - ItemFields.MediaSourceCount - ], - parentId: parentId ?? undefined, - categoryLimit: 6, - itemLimit: 20 - }, - { - signal: options?.signal - } - ); - return response.data; - } -}; - -export const useGetMovieRecommendations = (isMovieRecommendationEnabled: boolean, parentId: ParentId) => { - const currentApi = useApi(); - return useQuery({ - queryKey: ['MovieRecommendations', isMovieRecommendationEnabled, parentId], - queryFn: ({ signal }) => fetchGetMovieRecommendations(currentApi, parentId, { signal }), - enabled: !!currentApi.api && !!currentApi.user?.Id && isMovieRecommendationEnabled - }); -}; - const fetchGetGenres = async ( currentApi: JellyfinApiContext, itemType: BaseItemKind[],