Merge pull request #5085 from grafixeyehero/Convert-played-and-ratingbuttons-to-react

Convert playstatebutton and ratingbuttons to react
This commit is contained in:
Bill Thornton 2024-01-12 10:04:04 -05:00 committed by GitHub
commit 3a120011c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 205 additions and 1 deletions

View file

@ -0,0 +1,72 @@
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client';
import React, { FC, useCallback } from 'react';
import CheckIcon from '@mui/icons-material/Check';
import { IconButton } from '@mui/material';
import classNames from 'classnames';
import globalize from 'scripts/globalize';
import { useTogglePlayedMutation } from 'hooks/useFetchItems';
interface PlayedButtonProps {
className?: string;
isPlayed : boolean | undefined;
itemId: string | null | undefined;
itemType: string | null | undefined
}
const PlayedButton: FC<PlayedButtonProps> = ({
className,
isPlayed = false,
itemId,
itemType
}) => {
const { mutateAsync: togglePlayedMutation } = useTogglePlayedMutation();
const [playedState, setPlayedState] = React.useState<boolean>(isPlayed);
const getTitle = useCallback(() => {
let buttonTitle;
if (itemType !== BaseItemKind.AudioBook) {
buttonTitle = playedState ? globalize.translate('Watched') : globalize.translate('MarkPlayed');
} else {
buttonTitle = playedState ? globalize.translate('Played') : globalize.translate('MarkPlayed');
}
return buttonTitle;
}, [playedState, itemType]);
const onClick = useCallback(async () => {
try {
if (!itemId) {
throw new Error('Item has no Id');
}
const _isPlayed = await togglePlayedMutation({
itemId,
playedState
});
setPlayedState(!!_isPlayed);
} catch (e) {
console.error(e);
}
}, [playedState, itemId, togglePlayedMutation]);
const btnClass = classNames(
className,
{ 'playstatebutton-played': playedState }
);
const iconClass = classNames(
{ 'playstatebutton-icon-played': playedState }
);
return (
<IconButton
title={getTitle()}
className={btnClass}
size='small'
onClick={onClick}
>
<CheckIcon className={iconClass} />
</IconButton>
);
};
export default PlayedButton;

View file

@ -0,0 +1,59 @@
import React, { FC, useCallback } from 'react';
import FavoriteIcon from '@mui/icons-material/Favorite';
import { IconButton } from '@mui/material';
import classNames from 'classnames';
import { useToggleFavoriteMutation } from 'hooks/useFetchItems';
import globalize from 'scripts/globalize';
interface FavoriteButtonProps {
className?: string;
isFavorite: boolean | undefined;
itemId: string | null | undefined
}
const FavoriteButton: FC<FavoriteButtonProps> = ({
className,
isFavorite = false,
itemId
}) => {
const { mutateAsync: toggleFavoriteMutation } = useToggleFavoriteMutation();
const [favoriteState, setFavoriteState] = React.useState<boolean>(isFavorite);
const onClick = useCallback(async () => {
try {
if (!itemId) {
throw new Error('Item has no Id');
}
const _isFavorite = await toggleFavoriteMutation({
itemId,
favoriteState
});
setFavoriteState(!!_isFavorite);
} catch (e) {
console.error(e);
}
}, [favoriteState, itemId, toggleFavoriteMutation]);
const btnClass = classNames(
className,
{ 'ratingbutton-withrating': favoriteState }
);
const iconClass = classNames(
{ 'ratingbutton-icon-withrating': favoriteState }
);
return (
<IconButton
title={favoriteState ? globalize.translate('Favorite') : globalize.translate('AddToFavorites')}
className={btnClass}
size='small'
onClick={onClick}
>
<FavoriteIcon className={iconClass} />
</IconButton>
);
};
export default FavoriteButton;

View file

@ -15,6 +15,7 @@ import { getStudiosApi } from '@jellyfin/sdk/lib/utils/api/studios-api';
import { getTvShowsApi } from '@jellyfin/sdk/lib/utils/api/tv-shows-api';
import { getUserLibraryApi } from '@jellyfin/sdk/lib/utils/api/user-library-api';
import { getPlaylistsApi } from '@jellyfin/sdk/lib/utils/api/playlists-api';
import { getPlaystateApi } from '@jellyfin/sdk/lib/utils/api/playstate-api';
import { useMutation, useQuery } from '@tanstack/react-query';
import datetime from 'scripts/datetime';
import globalize from 'scripts/globalize';
@ -166,7 +167,7 @@ const fetchGetItemsBySuggestionsType = async (
response = (
await getItemsApi(api).getResumeItems(
{
userId: user?.Id,
userId: user.Id,
parentId: parentId ?? undefined,
fields: [
ItemFields.PrimaryImageAspectRatio,
@ -617,3 +618,75 @@ export const useGetGroupsUpcomingEpisodes = (parentId: ParentId) => {
enabled: !!parentId
});
};
interface ToggleFavoriteMutationProp {
itemId: string;
favoriteState: boolean
}
const fetchUpdateFavoriteStatus = async (
currentApi: JellyfinApiContext,
itemId: string,
favoriteState: boolean
) => {
const { api, user } = currentApi;
if (api && user?.Id) {
if (favoriteState) {
const response = await getUserLibraryApi(api).unmarkFavoriteItem({
userId: user.Id,
itemId: itemId
});
return response.data.IsFavorite;
} else {
const response = await getUserLibraryApi(api).markFavoriteItem({
userId: user.Id,
itemId: itemId
});
return response.data.IsFavorite;
}
}
};
export const useToggleFavoriteMutation = () => {
const currentApi = useApi();
return useMutation({
mutationFn: ({ itemId, favoriteState }: ToggleFavoriteMutationProp) =>
fetchUpdateFavoriteStatus(currentApi, itemId, favoriteState )
});
};
interface TogglePlayedMutationProp {
itemId: string;
playedState: boolean
}
const fetchUpdatePlayedState = async (
currentApi: JellyfinApiContext,
itemId: string,
playedState: boolean
) => {
const { api, user } = currentApi;
if (api && user?.Id) {
if (playedState) {
const response = await getPlaystateApi(api).markUnplayedItem({
userId: user.Id,
itemId: itemId
});
return response.data.Played;
} else {
const response = await getPlaystateApi(api).markPlayedItem({
userId: user.Id,
itemId: itemId
});
return response.data.Played;
}
}
};
export const useTogglePlayedMutation = () => {
const currentApi = useApi();
return useMutation({
mutationFn: ({ itemId, playedState }: TogglePlayedMutationProp) =>
fetchUpdatePlayedState(currentApi, itemId, playedState )
});
};