diff --git a/src/apps/experimental/components/library/ProgramsSectionView.tsx b/src/apps/experimental/components/library/ProgramsSectionView.tsx index ac39d899b7..b15f319789 100644 --- a/src/apps/experimental/components/library/ProgramsSectionView.tsx +++ b/src/apps/experimental/components/library/ProgramsSectionView.tsx @@ -18,7 +18,7 @@ const ProgramsSectionView: FC = ({ sectionType, isUpcomingRecordingsEnabled = false }) => { - const { isLoading, data: sectionsWithItems } = useGetProgramsSectionsWithItems(parentId, sectionType); + const { isLoading, data: sectionsWithItems, refetch } = useGetProgramsSectionsWithItems(parentId, sectionType); const { isLoading: isUpcomingRecordingsLoading, data: upcomingRecordings @@ -60,8 +60,10 @@ const ProgramsSectionView: FC = ({ sectionTitle={globalize.translate(section.name)} items={items ?? []} url={getRouteUrl(section)} + reloadItems={refetch} cardOptions={{ - ...section.cardOptions + ...section.cardOptions, + queryKey: ['ProgramSectionWithItems'] }} /> @@ -73,6 +75,7 @@ const ProgramsSectionView: FC = ({ sectionTitle={group.name} items={group.timerInfo ?? []} cardOptions={{ + queryKey: ['Timers'], shape: 'overflowBackdrop', showTitle: true, showParentTitleOrTitle: true, diff --git a/src/apps/experimental/components/library/SuggestionsSectionView.tsx b/src/apps/experimental/components/library/SuggestionsSectionView.tsx index 039f49e4c6..d41270e4a6 100644 --- a/src/apps/experimental/components/library/SuggestionsSectionView.tsx +++ b/src/apps/experimental/components/library/SuggestionsSectionView.tsx @@ -102,6 +102,7 @@ const SuggestionsSectionView: FC = ({ url={getRouteUrl(section)} cardOptions={{ ...section.cardOptions, + queryKey: ['SuggestionSectionWithItems'], showTitle: true, centerText: true, cardLayout: false, @@ -117,6 +118,7 @@ const SuggestionsSectionView: FC = ({ sectionTitle={getRecommendationTittle(recommendation)} items={recommendation.Items ?? []} cardOptions={{ + queryKey: ['MovieRecommendations'], shape: 'overflowPortrait', showYear: true, scalable: true, diff --git a/src/elements/emby-playstatebutton/PlayedButton.tsx b/src/elements/emby-playstatebutton/PlayedButton.tsx index 89f4052b11..687953fb91 100644 --- a/src/elements/emby-playstatebutton/PlayedButton.tsx +++ b/src/elements/emby-playstatebutton/PlayedButton.tsx @@ -1,4 +1,5 @@ import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client'; +import { useQueryClient } from '@tanstack/react-query'; import React, { FC, useCallback } from 'react'; import CheckIcon from '@mui/icons-material/Check'; import { IconButton } from '@mui/material'; @@ -10,28 +11,30 @@ interface PlayedButtonProps { className?: string; isPlayed : boolean | undefined; itemId: string | null | undefined; - itemType: string | null | undefined + itemType: string | null | undefined, + queryKey?: string[] } const PlayedButton: FC = ({ className, isPlayed = false, itemId, - itemType + itemType, + queryKey }) => { + const queryClient = useQueryClient(); const { mutateAsync: togglePlayedMutation } = useTogglePlayedMutation(); - const [playedState, setPlayedState] = React.useState(isPlayed); const getTitle = useCallback(() => { let buttonTitle; if (itemType !== BaseItemKind.AudioBook) { - buttonTitle = playedState ? globalize.translate('Watched') : globalize.translate('MarkPlayed'); + buttonTitle = isPlayed ? globalize.translate('Watched') : globalize.translate('MarkPlayed'); } else { - buttonTitle = playedState ? globalize.translate('Played') : globalize.translate('MarkPlayed'); + buttonTitle = isPlayed ? globalize.translate('Played') : globalize.translate('MarkPlayed'); } return buttonTitle; - }, [playedState, itemType]); + }, [itemType, isPlayed]); const onClick = useCallback(async () => { try { @@ -39,23 +42,29 @@ const PlayedButton: FC = ({ throw new Error('Item has no Id'); } - const _isPlayed = await togglePlayedMutation({ + await togglePlayedMutation({ itemId, - playedState - }); - setPlayedState(!!_isPlayed); + isPlayed + }, + { onSuccess: async() => { + await queryClient.invalidateQueries({ + queryKey: queryKey, + type: 'all', + refetchType: 'active' + }); + } }); } catch (e) { console.error(e); } - }, [playedState, itemId, togglePlayedMutation]); + }, [itemId, togglePlayedMutation, isPlayed, queryClient, queryKey]); const btnClass = classNames( className, - { 'playstatebutton-played': playedState } + { 'playstatebutton-played': isPlayed } ); const iconClass = classNames( - { 'playstatebutton-icon-played': playedState } + { 'playstatebutton-icon-played': isPlayed } ); return ( = ({ className, isFavorite = false, - itemId + itemId, + queryKey }) => { + const queryClient = useQueryClient(); const { mutateAsync: toggleFavoriteMutation } = useToggleFavoriteMutation(); - const [favoriteState, setFavoriteState] = React.useState(isFavorite); const onClick = useCallback(async () => { try { @@ -25,28 +28,34 @@ const FavoriteButton: FC = ({ throw new Error('Item has no Id'); } - const _isFavorite = await toggleFavoriteMutation({ + await toggleFavoriteMutation({ itemId, - favoriteState - }); - setFavoriteState(!!_isFavorite); + isFavorite + }, + { onSuccess: async() => { + await queryClient.invalidateQueries({ + queryKey: queryKey, + type: 'all', + refetchType: 'active' + }); + } }); } catch (e) { console.error(e); } - }, [favoriteState, itemId, toggleFavoriteMutation]); + }, [isFavorite, itemId, queryClient, queryKey, toggleFavoriteMutation]); const btnClass = classNames( className, - { 'ratingbutton-withrating': favoriteState } + { 'ratingbutton-withrating': isFavorite } ); const iconClass = classNames( - { 'ratingbutton-icon-withrating': favoriteState } + { 'ratingbutton-icon-withrating': isFavorite } ); return ( fetchGetItemsViewByType( @@ -526,17 +528,17 @@ export const useGetGroupsUpcomingEpisodes = (parentId: ParentId) => { interface ToggleFavoriteMutationProp { itemId: string; - favoriteState: boolean + isFavorite: boolean } const fetchUpdateFavoriteStatus = async ( currentApi: JellyfinApiContext, itemId: string, - favoriteState: boolean + isFavorite: boolean ) => { const { api, user } = currentApi; if (api && user?.Id) { - if (favoriteState) { + if (isFavorite) { const response = await getUserLibraryApi(api).unmarkFavoriteItem({ userId: user.Id, itemId: itemId @@ -555,24 +557,24 @@ const fetchUpdateFavoriteStatus = async ( export const useToggleFavoriteMutation = () => { const currentApi = useApi(); return useMutation({ - mutationFn: ({ itemId, favoriteState }: ToggleFavoriteMutationProp) => - fetchUpdateFavoriteStatus(currentApi, itemId, favoriteState ) + mutationFn: ({ itemId, isFavorite }: ToggleFavoriteMutationProp) => + fetchUpdateFavoriteStatus(currentApi, itemId, isFavorite ) }); }; interface TogglePlayedMutationProp { itemId: string; - playedState: boolean + isPlayed: boolean } const fetchUpdatePlayedState = async ( currentApi: JellyfinApiContext, itemId: string, - playedState: boolean + isPlayed: boolean ) => { const { api, user } = currentApi; if (api && user?.Id) { - if (playedState) { + if (isPlayed) { const response = await getPlaystateApi(api).markUnplayedItem({ userId: user.Id, itemId: itemId @@ -591,8 +593,8 @@ const fetchUpdatePlayedState = async ( export const useTogglePlayedMutation = () => { const currentApi = useApi(); return useMutation({ - mutationFn: ({ itemId, playedState }: TogglePlayedMutationProp) => - fetchUpdatePlayedState(currentApi, itemId, playedState ) + mutationFn: ({ itemId, isPlayed }: TogglePlayedMutationProp) => + fetchUpdatePlayedState(currentApi, itemId, isPlayed ) }); }; @@ -676,7 +678,7 @@ const fetchGetTimers = async ( export const useGetTimers = (isUpcomingRecordingsEnabled: boolean, indexByDate?: boolean) => { const currentApi = useApi(); return useQuery({ - queryKey: ['Timers', isUpcomingRecordingsEnabled, indexByDate], + queryKey: ['Timers', { isUpcomingRecordingsEnabled, indexByDate }], queryFn: ({ signal }) => isUpcomingRecordingsEnabled ? fetchGetTimers(currentApi, indexByDate, { signal }) : [] }); @@ -830,7 +832,7 @@ const fetchGetSectionItems = async ( ], parentId: parentId ?? undefined, imageTypeLimit: 1, - enableImageTypes: [ImageType.Primary], + enableImageTypes: [ImageType.Primary, ImageType.Thumb], ...section.parametersOptions }, { @@ -882,19 +884,15 @@ const getSectionsWithItems = async ( const updatedSectionWithItems: SectionWithItems[] = []; for (const section of sections) { - try { - const items = await fetchGetSectionItems( - currentApi, parentId, section, options - ); + const items = await fetchGetSectionItems( + currentApi, parentId, section, options + ); - if (items && items.length > 0) { - updatedSectionWithItems.push({ - section, - items - }); - } - } catch (error) { - console.error(`Error occurred for section ${section.type}: ${error}`); + if (items && items.length > 0) { + updatedSectionWithItems.push({ + section, + items + }); } } @@ -908,7 +906,7 @@ export const useGetSuggestionSectionsWithItems = ( const currentApi = useApi(); const sections = getSuggestionSections(); return useQuery({ - queryKey: ['SuggestionSectionWithItems', suggestionSectionType], + queryKey: ['SuggestionSectionWithItems', { suggestionSectionType }], queryFn: ({ signal }) => getSectionsWithItems(currentApi, parentId, sections, suggestionSectionType, { signal }), enabled: !!parentId @@ -922,9 +920,8 @@ export const useGetProgramsSectionsWithItems = ( const currentApi = useApi(); const sections = getProgramSections(); return useQuery({ - queryKey: ['ProgramSectionWithItems', programSectionType], - queryFn: ({ signal }) => - getSectionsWithItems(currentApi, parentId, sections, programSectionType, { signal }) + queryKey: ['ProgramSectionWithItems', { programSectionType }], + queryFn: ({ signal }) => getSectionsWithItems(currentApi, parentId, sections, programSectionType, { signal }) + }); }; -