mirror of
https://github.com/Jellify-Music/App.git
synced 2026-04-21 09:08:56 -05:00
add on this day to discover
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { useRecentlyAddedAlbums } from '../../queries/album'
|
||||
import { useAlbumsOnThisDay, useRecentlyAddedAlbums } from '../../queries/album'
|
||||
import { usePublicPlaylists } from '../../queries/playlist'
|
||||
import { useDiscoverArtists } from '../../queries/suggestions'
|
||||
|
||||
@@ -10,12 +10,15 @@ const useDiscoverQueries = () => {
|
||||
|
||||
const { refetch: refetchArtistSuggestions } = useDiscoverArtists()
|
||||
|
||||
const { refetch: refetchOnThisDay } = useAlbumsOnThisDay()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async () =>
|
||||
await Promise.allSettled([
|
||||
refetchRecentlyAdded(),
|
||||
refetchPublicPlaylists(),
|
||||
refetchArtistSuggestions(),
|
||||
refetchOnThisDay(),
|
||||
]),
|
||||
networkMode: 'online',
|
||||
})
|
||||
|
||||
@@ -2,15 +2,18 @@ import { QueryKeys } from '../../../enums/query-keys'
|
||||
import { InfiniteData, useInfiniteQuery, UseInfiniteQueryResult } from '@tanstack/react-query'
|
||||
import { ItemSortBy } from '@jellyfin/sdk/lib/generated-client/models/item-sort-by'
|
||||
import { SortOrder } from '@jellyfin/sdk/lib/generated-client/models/sort-order'
|
||||
import { fetchAlbums } from './utils/album'
|
||||
import { fetchAlbums, fetchAlbumsOnThisDay } from './utils/album'
|
||||
import { RefObject, useCallback, useRef } from 'react'
|
||||
import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client'
|
||||
import { BaseItemDto, BaseItemKind } from '@jellyfin/sdk/lib/generated-client'
|
||||
import flattenInfiniteQueryPages from '../../../utils/query-selectors'
|
||||
import { ApiLimits, MaxPages } from '../../../configs/query.config'
|
||||
import { fetchRecentlyAdded } from '../recents/utils'
|
||||
import { queryClient } from '../../../constants/query-client'
|
||||
import { useApi, useJellifyLibrary, useJellifyUser } from '../../../stores'
|
||||
import useLibraryStore from '../../../stores/library'
|
||||
import { AlbumsOnthisDayQueryKey, RecentlyAddedAlbumsQueryKey } from './keys'
|
||||
import { fetchItems } from '../item'
|
||||
import { getItemsApi } from '@jellyfin/sdk/lib/utils/api'
|
||||
|
||||
const useAlbums: () => [
|
||||
RefObject<Set<string>>,
|
||||
@@ -64,7 +67,7 @@ export const useRecentlyAddedAlbums = () => {
|
||||
const [library] = useJellifyLibrary()
|
||||
|
||||
return useInfiniteQuery({
|
||||
queryKey: [QueryKeys.RecentlyAddedAlbums, library?.musicLibraryId],
|
||||
queryKey: RecentlyAddedAlbumsQueryKey(library),
|
||||
queryFn: ({ pageParam }) => fetchRecentlyAdded(api, library, pageParam),
|
||||
select: (data) => data.pages.flatMap((page) => page),
|
||||
getNextPageParam: (lastPage, allPages, lastPageParam) =>
|
||||
@@ -78,6 +81,30 @@ export const useRefetchRecentlyAdded: () => () => void = () => {
|
||||
|
||||
return () =>
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [QueryKeys.RecentlyAddedAlbums, library?.musicLibraryId],
|
||||
queryKey: RecentlyAddedAlbumsQueryKey(library),
|
||||
})
|
||||
}
|
||||
|
||||
export const useAlbumsOnThisDay = () => {
|
||||
const api = useApi()
|
||||
|
||||
const [library] = useJellifyLibrary()
|
||||
|
||||
return useInfiniteQuery({
|
||||
queryKey: AlbumsOnthisDayQueryKey(library),
|
||||
queryFn: ({ queryKey, pageParam }) =>
|
||||
fetchAlbumsOnThisDay(
|
||||
api,
|
||||
library,
|
||||
queryKey[2] as number,
|
||||
queryKey[3] as number,
|
||||
pageParam,
|
||||
),
|
||||
select: (data) => data.pages.flatMap((page) => page),
|
||||
enabled: !!api,
|
||||
maxPages: MaxPages.Discover,
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage, allPages, lastPageParam) =>
|
||||
lastPage.length > 0 ? lastPageParam + 1 : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { JellifyLibrary } from '@/src/types/JellifyLibrary'
|
||||
|
||||
enum AlbumQueryKeys {
|
||||
RecentlyAdded = 'RECENTLY_ADDED',
|
||||
OnThisDay = 'ON_THIS_DAY',
|
||||
InfiniteAlbums = 'INFINITE_ALBUMS',
|
||||
}
|
||||
|
||||
/**
|
||||
* A query key for an infinite query of albums
|
||||
*
|
||||
* @param isFavorites Whether the albums are filtered to favorites
|
||||
* @param library The {@link JellifyLibrary} set in the store
|
||||
* @returns
|
||||
*/
|
||||
export const InfiniteAlbumsQueryKey = (
|
||||
isFavorites: boolean | undefined,
|
||||
library: JellifyLibrary | undefined,
|
||||
) => [AlbumQueryKeys.InfiniteAlbums, isFavorites, library?.musicLibraryId]
|
||||
|
||||
/**
|
||||
* A query key for an infinite query of recent albums
|
||||
*
|
||||
* @param library The {@link JellifyLibrary} set in the store
|
||||
* @returns
|
||||
*/
|
||||
export const RecentlyAddedAlbumsQueryKey = (library: JellifyLibrary | undefined) => [
|
||||
AlbumQueryKeys.RecentlyAdded,
|
||||
library?.musicLibraryId,
|
||||
]
|
||||
|
||||
/**
|
||||
* A query key for an infinite query of albums released on this day
|
||||
*
|
||||
* @param library The {@link JellifyLibrary} set in the store
|
||||
* @returns
|
||||
*/
|
||||
export const AlbumsOnthisDayQueryKey = (library: JellifyLibrary | undefined) => {
|
||||
const date = new Date()
|
||||
|
||||
return [AlbumQueryKeys.OnThisDay, library?.musicLibraryId, date.getMonth(), date.getDay()]
|
||||
}
|
||||
@@ -55,3 +55,27 @@ export function fetchAlbumById(api: Api | undefined, albumId: string): Promise<B
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchAlbumsOnThisDay(
|
||||
api: Api | undefined,
|
||||
library: JellifyLibrary | undefined,
|
||||
month: number,
|
||||
day: number,
|
||||
page: number,
|
||||
): Promise<BaseItemDto[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!api || !library) return reject('Api or Library instance not set')
|
||||
else
|
||||
nitroFetch<{ Items: BaseItemDto[] }>(api, '/Items', {
|
||||
ParentId: library.musicLibraryId,
|
||||
IncludeItemTypes: [BaseItemKind.MusicAlbum],
|
||||
EnableUserData: true, // This will populate the user data query later down the line
|
||||
SortBy: [ItemSortBy.ProductionYear],
|
||||
SortOrder: [SortOrder.Descending],
|
||||
StartIndex: page * ApiLimits.Library,
|
||||
Limit: ApiLimits.Library,
|
||||
Fields: [ItemFields.SortName],
|
||||
Recursive: true,
|
||||
}).then(({ Items }) => resolve(Items))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import useDiscoverQueries from '../../api/mutations/discover'
|
||||
import { useIsRestoring } from '@tanstack/react-query'
|
||||
import { useRecentlyAddedAlbums } from '../../api/queries/album'
|
||||
import { RefreshControl } from 'react-native'
|
||||
import OnThisDay from './helpers/on-this-day'
|
||||
|
||||
export default function Index(): React.JSX.Element {
|
||||
const { mutateAsync: refreshAsync, isPending: refreshing } = useDiscoverQueries()
|
||||
@@ -44,6 +45,8 @@ function DiscoverContent() {
|
||||
<YStack gap={'$3'}>
|
||||
<RecentlyAdded />
|
||||
|
||||
<OnThisDay />
|
||||
|
||||
<PublicPlaylists />
|
||||
|
||||
<SuggestedArtists />
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { useAlbumsOnThisDay } from '../../../api/queries/album'
|
||||
import Animated, { FadeIn, FadeOut, LinearTransition } from 'react-native-reanimated'
|
||||
import { H5, XStack } from 'tamagui'
|
||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
||||
import DiscoverStackParamList from '@/src/screens/Discover/types'
|
||||
import Icon from '../../Global/components/icon'
|
||||
import HorizontalCardList from '../../Global/components/horizontal-list'
|
||||
import { ItemCard } from '../../Global/components/item-card'
|
||||
import navigationRef from '../../../../navigation'
|
||||
|
||||
export default function OnThisDay(): React.JSX.Element | null {
|
||||
const { data: albumsOnThisDay } = useAlbumsOnThisDay()
|
||||
|
||||
const albumsOnThisDayExist = albumsOnThisDay && albumsOnThisDay.length > 0
|
||||
|
||||
const navigation = useNavigation<NativeStackNavigationProp<DiscoverStackParamList>>()
|
||||
|
||||
return albumsOnThisDayExist ? (
|
||||
<Animated.View
|
||||
entering={FadeIn.springify()}
|
||||
exiting={FadeOut.springify()}
|
||||
layout={LinearTransition.springify()}
|
||||
testID='discover-public-playlists'
|
||||
style={{
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
<XStack alignItems='center'>
|
||||
<H5 marginLeft={'$2'} lineBreakStrategyIOS='standard'>
|
||||
On this day
|
||||
</H5>
|
||||
<Icon name='arrow-right' />
|
||||
</XStack>
|
||||
<HorizontalCardList
|
||||
data={albumsOnThisDay.slice(0, 10) ?? []}
|
||||
renderItem={({ item }) => (
|
||||
<ItemCard
|
||||
caption={item.Name}
|
||||
subCaption={`${item.Artists?.join(', ')}`}
|
||||
squared
|
||||
size={'$11'}
|
||||
item={item}
|
||||
onPress={() => {
|
||||
navigation.navigate('Album', {
|
||||
album: item,
|
||||
})
|
||||
}}
|
||||
onLongPress={() => {
|
||||
navigationRef.navigate('Context', {
|
||||
item,
|
||||
navigation,
|
||||
})
|
||||
}}
|
||||
marginHorizontal={'$1'}
|
||||
captionAlign='left'
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Animated.View>
|
||||
) : null
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import DiscoverStackParamList from '../../../screens/Discover/types'
|
||||
import navigationRef from '../../../../navigation'
|
||||
import { useJellifyServer } from '../../../stores'
|
||||
import { usePublicPlaylists } from '../../../api/queries/playlist'
|
||||
import Animated, { FadeIn, LinearTransition } from 'react-native-reanimated'
|
||||
import Animated, { FadeIn, FadeOut, LinearTransition } from 'react-native-reanimated'
|
||||
|
||||
export default function PublicPlaylists(): React.JSX.Element | null {
|
||||
const {
|
||||
@@ -31,7 +31,7 @@ export default function PublicPlaylists(): React.JSX.Element | null {
|
||||
return publicPlaylistsExist ? (
|
||||
<Animated.View
|
||||
entering={FadeIn.springify()}
|
||||
exiting={FadeIn.springify()}
|
||||
exiting={FadeOut.springify()}
|
||||
layout={LinearTransition.springify()}
|
||||
testID='discover-public-playlists'
|
||||
style={{
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { ImageFormat } from '@jellyfin/sdk/lib/generated-client/models'
|
||||
|
||||
export enum MaxPages {
|
||||
Home = 2,
|
||||
Home = 3,
|
||||
Library = 5,
|
||||
Discover = 2,
|
||||
}
|
||||
|
||||
export enum ApiLimits {
|
||||
|
||||
Reference in New Issue
Block a user