mirror of
https://github.com/Jellify-Music/App.git
synced 2026-03-03 08:29:15 -06:00
Tightening up Favorite button functionality
This commit is contained in:
@@ -1,18 +1,13 @@
|
||||
import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Icon from '../helpers/icon'
|
||||
import { getUserLibraryApi } from '@jellyfin/sdk/lib/utils/api'
|
||||
import { useMutation, useQuery } from '@tanstack/react-query'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { isUndefined } from 'lodash'
|
||||
import { getTokens, Spinner } from 'tamagui'
|
||||
import Client from '../../../api/client'
|
||||
import { usePlayerContext } from '../../..//player/provider'
|
||||
import { queryClient } from '../../../constants/query-client'
|
||||
import { QueryKeys } from '../../../enums/query-keys'
|
||||
import { trigger } from 'react-native-haptic-feedback'
|
||||
import { fetchUserData } from '../../../api/queries/functions/favorites'
|
||||
|
||||
import * as Burnt from 'burnt'
|
||||
import { useJellifyUserDataContext } from '../../../components/user-data-provider'
|
||||
|
||||
interface SetFavoriteMutation {
|
||||
item: BaseItemDto
|
||||
@@ -25,73 +20,38 @@ export default function FavoriteButton({
|
||||
item: BaseItemDto
|
||||
onToggle?: () => void
|
||||
}): React.JSX.Element {
|
||||
const { nowPlaying, nowPlayingIsFavorite } = usePlayerContext()
|
||||
usePlayerContext()
|
||||
|
||||
const [isFavorite, setIsFavorite] = useState<boolean>(isFavoriteItem(item))
|
||||
const [isFavorite, setFavorite] = useState<boolean>(isFavoriteItem(item))
|
||||
|
||||
const { data, isFetching, isFetched, refetch } = useQuery({
|
||||
const { toggleFavorite } = useJellifyUserDataContext()
|
||||
|
||||
const { data, isFetching, refetch } = useQuery({
|
||||
queryKey: [QueryKeys.UserData, item.Id!],
|
||||
queryFn: () => fetchUserData(item.Id!),
|
||||
})
|
||||
|
||||
const useSetFavorite = useMutation({
|
||||
mutationFn: async (mutation: SetFavoriteMutation) => {
|
||||
return getUserLibraryApi(Client.api!).markFavoriteItem({
|
||||
itemId: mutation.item.Id!,
|
||||
})
|
||||
},
|
||||
onSuccess: () => {
|
||||
Burnt.alert({
|
||||
title: `Added favorite`,
|
||||
duration: 1,
|
||||
preset: 'heart',
|
||||
})
|
||||
|
||||
trigger('notificationSuccess')
|
||||
|
||||
setIsFavorite(true)
|
||||
onToggle ? onToggle() : {}
|
||||
|
||||
// Force refresh of track user data
|
||||
queryClient.invalidateQueries({ queryKey: [QueryKeys.UserData, item.Id] })
|
||||
},
|
||||
})
|
||||
|
||||
const useRemoveFavorite = useMutation({
|
||||
mutationFn: async (mutation: SetFavoriteMutation) => {
|
||||
return getUserLibraryApi(Client.api!).unmarkFavoriteItem({
|
||||
itemId: mutation.item.Id!,
|
||||
})
|
||||
},
|
||||
onSuccess: () => {
|
||||
Burnt.alert({
|
||||
title: `Removed favorite`,
|
||||
duration: 1,
|
||||
preset: 'done',
|
||||
})
|
||||
|
||||
trigger('notificationSuccess')
|
||||
setIsFavorite(false)
|
||||
onToggle ? onToggle() : {}
|
||||
},
|
||||
})
|
||||
|
||||
const toggleFavorite = () => {
|
||||
if (isFavorite) useRemoveFavorite.mutate({ item })
|
||||
else useSetFavorite.mutate({ item })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
refetch()
|
||||
}, [item])
|
||||
|
||||
useEffect(() => {
|
||||
if (data) setFavorite(data.IsFavorite ?? false)
|
||||
}, [data])
|
||||
|
||||
return isFetching && isUndefined(item.UserData) ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<Icon
|
||||
name={data?.IsFavorite ?? isFavorite ? 'heart' : 'heart-outline'}
|
||||
name={isFavorite ? 'heart' : 'heart-outline'}
|
||||
color={getTokens().color.telemagenta.val}
|
||||
onPress={toggleFavorite}
|
||||
onPress={() =>
|
||||
toggleFavorite(isFavorite, {
|
||||
item,
|
||||
setFavorite,
|
||||
onToggle,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useColorScheme } from 'react-native'
|
||||
import { PortalProvider } from '@tamagui/portal'
|
||||
import { JellifyProvider, useJellifyContext } from './provider'
|
||||
import { ToastProvider } from '@tamagui/toast'
|
||||
import { JellifyUserDataProvider } from './user-data-provider'
|
||||
|
||||
export default function Jellify(): React.JSX.Element {
|
||||
return (
|
||||
@@ -26,9 +27,11 @@ function App(): React.JSX.Element {
|
||||
const { loggedIn } = useJellifyContext()
|
||||
|
||||
return loggedIn ? (
|
||||
<PlayerProvider>
|
||||
<Navigation />
|
||||
</PlayerProvider>
|
||||
<JellifyUserDataProvider>
|
||||
<PlayerProvider>
|
||||
<Navigation />
|
||||
</PlayerProvider>
|
||||
</JellifyUserDataProvider>
|
||||
) : (
|
||||
<JellyfinAuthenticationProvider>
|
||||
<Login />
|
||||
|
||||
99
components/user-data-provider.tsx
Normal file
99
components/user-data-provider.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import Client from '../api/client'
|
||||
import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models'
|
||||
import { getUserLibraryApi } from '@jellyfin/sdk/lib/utils/api'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { createContext, ReactNode, SetStateAction, useContext } from 'react'
|
||||
|
||||
import * as Burnt from 'burnt'
|
||||
import { trigger } from 'react-native-haptic-feedback'
|
||||
import { queryClient } from '../constants/query-client'
|
||||
import { QueryKeys } from '../enums/query-keys'
|
||||
|
||||
interface SetFavoriteMutation {
|
||||
item: BaseItemDto
|
||||
setFavorite: React.Dispatch<SetStateAction<boolean>>
|
||||
onToggle?: () => void
|
||||
}
|
||||
|
||||
interface JellifyUserDataContext {
|
||||
toggleFavorite: (isFavorite: boolean, mutation: SetFavoriteMutation) => void
|
||||
}
|
||||
|
||||
const JellifyUserDataContextInitializer = () => {
|
||||
const useSetFavorite = useMutation({
|
||||
mutationFn: async (mutation: SetFavoriteMutation) => {
|
||||
return getUserLibraryApi(Client.api!).markFavoriteItem({
|
||||
itemId: mutation.item.Id!,
|
||||
})
|
||||
},
|
||||
onSuccess: ({ data }, { item, setFavorite, onToggle }) => {
|
||||
Burnt.alert({
|
||||
title: `Added favorite`,
|
||||
duration: 1,
|
||||
preset: 'heart',
|
||||
})
|
||||
|
||||
trigger('notificationSuccess')
|
||||
|
||||
setFavorite(true)
|
||||
if (onToggle) onToggle()
|
||||
|
||||
// Force refresh of track user data
|
||||
queryClient.invalidateQueries({ queryKey: [QueryKeys.UserData, item.Id] })
|
||||
},
|
||||
})
|
||||
|
||||
const useRemoveFavorite = useMutation({
|
||||
mutationFn: async (mutation: SetFavoriteMutation) => {
|
||||
return getUserLibraryApi(Client.api!).unmarkFavoriteItem({
|
||||
itemId: mutation.item.Id!,
|
||||
})
|
||||
},
|
||||
onSuccess: ({ data }, { item, setFavorite, onToggle }) => {
|
||||
Burnt.alert({
|
||||
title: `Removed favorite`,
|
||||
duration: 1,
|
||||
preset: 'done',
|
||||
})
|
||||
|
||||
trigger('notificationSuccess')
|
||||
setFavorite(false)
|
||||
|
||||
if (onToggle) onToggle()
|
||||
|
||||
// Force refresh of track user data
|
||||
queryClient.invalidateQueries({ queryKey: [QueryKeys.UserData, item.Id] })
|
||||
},
|
||||
})
|
||||
|
||||
const toggleFavorite = (isFavorite: boolean, mutation: SetFavoriteMutation) =>
|
||||
(isFavorite ? useRemoveFavorite : useSetFavorite).mutate(mutation)
|
||||
|
||||
return {
|
||||
toggleFavorite,
|
||||
}
|
||||
}
|
||||
|
||||
const JellifyUserDataContext = createContext<JellifyUserDataContext>({
|
||||
toggleFavorite: () => {},
|
||||
})
|
||||
|
||||
export const JellifyUserDataProvider: ({
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode
|
||||
}) => React.JSX.Element = ({ children }: { children: ReactNode }) => {
|
||||
const { toggleFavorite } = JellifyUserDataContextInitializer()
|
||||
|
||||
return (
|
||||
<JellifyUserDataContext.Provider
|
||||
value={{
|
||||
toggleFavorite,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</JellifyUserDataContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useJellifyUserDataContext = () => useContext(JellifyUserDataContext)
|
||||
Reference in New Issue
Block a user