mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 15:48:05 +00:00
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
|
|
import { getUserLibraryApi } from "@jellyfin/sdk/lib/utils/api";
|
|
import { useMutation } from "@tanstack/react-query";
|
|
import { useAtom } from "jotai";
|
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
import { useNetworkAwareQueryClient } from "@/hooks/useNetworkAwareQueryClient";
|
|
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
|
|
|
export const useFavorite = (item: BaseItemDto) => {
|
|
const queryClient = useNetworkAwareQueryClient();
|
|
const [api] = useAtom(apiAtom);
|
|
const [user] = useAtom(userAtom);
|
|
const [isFavorite, setIsFavorite] = useState<boolean | undefined>(
|
|
item.UserData?.IsFavorite,
|
|
);
|
|
|
|
useEffect(() => {
|
|
setIsFavorite(item.UserData?.IsFavorite);
|
|
}, [item.UserData?.IsFavorite]);
|
|
|
|
const itemQueryKeyPrefix = useMemo(
|
|
() => ["item", item.Id] as const,
|
|
[item.Id],
|
|
);
|
|
|
|
const updateItemInQueries = useCallback(
|
|
(newData: Partial<BaseItemDto>) => {
|
|
queryClient.setQueriesData<BaseItemDto | null | undefined>(
|
|
{ queryKey: itemQueryKeyPrefix },
|
|
(old) => {
|
|
if (!old) return old;
|
|
return {
|
|
...old,
|
|
...newData,
|
|
UserData: { ...old.UserData, ...newData.UserData },
|
|
};
|
|
},
|
|
);
|
|
},
|
|
[itemQueryKeyPrefix, queryClient],
|
|
);
|
|
|
|
const favoriteMutation = useMutation({
|
|
mutationFn: async (nextIsFavorite: boolean) => {
|
|
if (!api || !user || !item.Id) return;
|
|
if (nextIsFavorite) {
|
|
await getUserLibraryApi(api).markFavoriteItem({
|
|
userId: user.Id,
|
|
itemId: item.Id,
|
|
});
|
|
return;
|
|
}
|
|
await getUserLibraryApi(api).unmarkFavoriteItem({
|
|
userId: user.Id,
|
|
itemId: item.Id,
|
|
});
|
|
},
|
|
onMutate: async (nextIsFavorite: boolean) => {
|
|
await queryClient.cancelQueries({ queryKey: itemQueryKeyPrefix });
|
|
|
|
const previousIsFavorite = isFavorite;
|
|
const previousQueries = queryClient.getQueriesData<BaseItemDto | null>({
|
|
queryKey: itemQueryKeyPrefix,
|
|
});
|
|
|
|
setIsFavorite(nextIsFavorite);
|
|
updateItemInQueries({ UserData: { IsFavorite: nextIsFavorite } });
|
|
|
|
return { previousIsFavorite, previousQueries };
|
|
},
|
|
onError: (_err, _nextIsFavorite, context) => {
|
|
if (context?.previousQueries) {
|
|
for (const [queryKey, data] of context.previousQueries) {
|
|
queryClient.setQueryData(queryKey, data);
|
|
}
|
|
}
|
|
setIsFavorite(context?.previousIsFavorite);
|
|
},
|
|
onSettled: () => {
|
|
queryClient.invalidateQueries({ queryKey: itemQueryKeyPrefix });
|
|
queryClient.invalidateQueries({ queryKey: ["home", "favorites"] });
|
|
},
|
|
});
|
|
|
|
const toggleFavorite = useCallback(() => {
|
|
favoriteMutation.mutate(!isFavorite);
|
|
}, [favoriteMutation, isFavorite]);
|
|
|
|
return {
|
|
isFavorite,
|
|
toggleFavorite,
|
|
favoriteMutation,
|
|
};
|
|
};
|