mirror of
https://github.com/anultravioletaurora/Jellify.git
synced 2025-12-21 05:20:06 -06:00
refactor: Implement optimistic updates for adding tracks to playlists, remove usePlaylistTracks, and display playlist.ChildCount.
This commit is contained in:
@@ -23,7 +23,7 @@ import TextTicker from 'react-native-text-ticker'
|
|||||||
import { TextTickerConfig } from '../Player/component.config'
|
import { TextTickerConfig } from '../Player/component.config'
|
||||||
import { getItemName } from '../../utils/text'
|
import { getItemName } from '../../utils/text'
|
||||||
import useHapticFeedback from '../../hooks/use-haptic-feedback'
|
import useHapticFeedback from '../../hooks/use-haptic-feedback'
|
||||||
import { usePlaylistTracks, useUserPlaylists } from '../../api/queries/playlist'
|
import { useUserPlaylists } from '../../api/queries/playlist'
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||||
import { useApi, useJellifyUser } from '../../stores'
|
import { useApi, useJellifyUser } from '../../stores'
|
||||||
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'
|
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'
|
||||||
@@ -105,11 +105,7 @@ function AddToPlaylistRow({
|
|||||||
|
|
||||||
const trigger = useHapticFeedback()
|
const trigger = useHapticFeedback()
|
||||||
|
|
||||||
const {
|
const [isInPlaylist, setIsInPlaylist] = useState<boolean>(false)
|
||||||
data: playlistTracks,
|
|
||||||
isPending: fetchingPlaylistTracks,
|
|
||||||
refetch: refetchPlaylistTracks,
|
|
||||||
} = usePlaylistTracks(playlist)
|
|
||||||
|
|
||||||
const useAddToPlaylist = useMutation({
|
const useAddToPlaylist = useMutation({
|
||||||
mutationFn: ({
|
mutationFn: ({
|
||||||
@@ -124,14 +120,17 @@ function AddToPlaylistRow({
|
|||||||
|
|
||||||
return addToPlaylist(api, user, track!, playlist)
|
return addToPlaylist(api, user, track!, playlist)
|
||||||
},
|
},
|
||||||
onSuccess: (data, { playlist }) => {
|
onMutate: () => {
|
||||||
trigger('notificationSuccess')
|
// Optimistic update - show success state immediately
|
||||||
|
|
||||||
setIsInPlaylist(true)
|
setIsInPlaylist(true)
|
||||||
|
},
|
||||||
refetchPlaylistTracks()
|
onSuccess: () => {
|
||||||
|
trigger('notificationSuccess')
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
|
// Rollback on error
|
||||||
|
setIsInPlaylist(false)
|
||||||
|
|
||||||
Toast.show({
|
Toast.show({
|
||||||
text1: 'Unable to add',
|
text1: 'Unable to add',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -141,22 +140,16 @@ function AddToPlaylistRow({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const [isInPlaylist, setIsInPlaylist] = useState<boolean>(
|
|
||||||
tracks.filter((track) =>
|
|
||||||
playlistTracks?.map((playlistTrack) => playlistTrack.Id).includes(track.Id),
|
|
||||||
).length > 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<YGroup.Item key={playlist.Id!}>
|
<YGroup.Item key={playlist.Id!}>
|
||||||
<ListItem
|
<ListItem
|
||||||
animation={'quick'}
|
animation={'quick'}
|
||||||
disabled={isInPlaylist}
|
disabled={isInPlaylist || useAddToPlaylist.isPending}
|
||||||
hoverTheme
|
hoverTheme
|
||||||
opacity={isInPlaylist ? 0.5 : 1}
|
opacity={isInPlaylist ? 0.5 : 1}
|
||||||
pressStyle={{ opacity: 0.6 }}
|
pressStyle={{ opacity: 0.6 }}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (!isInPlaylist) {
|
if (!isInPlaylist && !useAddToPlaylist.isPending) {
|
||||||
useAddToPlaylist.mutate({
|
useAddToPlaylist.mutate({
|
||||||
track: undefined,
|
track: undefined,
|
||||||
tracks,
|
tracks,
|
||||||
@@ -172,14 +165,14 @@ function AddToPlaylistRow({
|
|||||||
<Text bold>{playlist.Name ?? 'Untitled Playlist'}</Text>
|
<Text bold>{playlist.Name ?? 'Untitled Playlist'}</Text>
|
||||||
|
|
||||||
<Text color={getTokens().color.amethyst.val}>{`${
|
<Text color={getTokens().color.amethyst.val}>{`${
|
||||||
playlistTracks?.length ?? 0
|
playlist.ChildCount ?? 0
|
||||||
} tracks`}</Text>
|
} tracks`}</Text>
|
||||||
</YStack>
|
</YStack>
|
||||||
|
|
||||||
<Animated.View entering={FadeIn} exiting={FadeOut}>
|
<Animated.View entering={FadeIn} exiting={FadeOut}>
|
||||||
{isInPlaylist ? (
|
{isInPlaylist ? (
|
||||||
<Icon flex={1} name='check-circle-outline' color={'$success'} />
|
<Icon flex={1} name='check-circle-outline' color={'$success'} />
|
||||||
) : fetchingPlaylistTracks ? (
|
) : useAddToPlaylist.isPending ? (
|
||||||
<Spinner color={'$primary'} />
|
<Spinner color={'$primary'} />
|
||||||
) : (
|
) : (
|
||||||
<Spacer flex={1} />
|
<Spacer flex={1} />
|
||||||
|
|||||||
Reference in New Issue
Block a user