diff --git a/src/api/queries/artist/index.ts b/src/api/queries/artist/index.ts index 569e9880..b8389677 100644 --- a/src/api/queries/artist/index.ts +++ b/src/api/queries/artist/index.ts @@ -13,6 +13,8 @@ import { RefObject, useCallback, useRef } from 'react' import { useLibrarySortAndFilterContext } from '../../../providers/Library' import flattenInfiniteQueryPages from '../../../utils/query-selectors' import { useApi, useJellifyLibrary, useJellifyUser } from '../../../stores' +import { ArtistTopTracksQueryKey } from './keys' +import fetchTopArtistTracks from './utils/top-tracks' export const useArtistAlbums = (artist: BaseItemDto) => { const api = useApi() @@ -80,3 +82,14 @@ export const useAlbumArtists: () => [ return [artistPageParams, artistsInfiniteQuery] } + +export const useTopArtistTracks = (artistId: string | undefined) => { + const api = useApi() + const [library] = useJellifyLibrary() + + return useQuery({ + queryKey: ArtistTopTracksQueryKey(library?.musicLibraryId, artistId), + queryFn: () => fetchTopArtistTracks(api, library?.musicLibraryId, artistId), + enabled: !isUndefined(artistId), + }) +} diff --git a/src/api/queries/artist/keys.ts b/src/api/queries/artist/keys.ts new file mode 100644 index 00000000..2b03a45e --- /dev/null +++ b/src/api/queries/artist/keys.ts @@ -0,0 +1,8 @@ +enum ArtistQueryKeys { + TopTracks = 'TOP_ARTIST_TRACKS', +} + +export const ArtistTopTracksQueryKey = ( + libraryId: string | undefined, + artistId: string | undefined, +) => [ArtistQueryKeys.TopTracks, libraryId, artistId] diff --git a/src/api/queries/artist/utils/top-tracks.ts b/src/api/queries/artist/utils/top-tracks.ts new file mode 100644 index 00000000..32a5cf7f --- /dev/null +++ b/src/api/queries/artist/utils/top-tracks.ts @@ -0,0 +1,30 @@ +import { Api } from '@jellyfin/sdk/lib/api' +import { ItemSortBy, MediaType } from '@jellyfin/sdk/lib/generated-client' +import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto' +import { getItemsApi } from '@jellyfin/sdk/lib/utils/api' + +export default function fetchTopArtistTracks( + api: Api | undefined, + libraryId: string | undefined, + artistId: string | undefined, +): Promise { + if (!libraryId || !artistId || !api) return Promise.resolve([]) + + return new Promise((resolve, reject) => { + getItemsApi(api) + .getItems({ + artistIds: [artistId], + mediaTypes: [MediaType.Audio], + parentId: libraryId, + sortBy: [ItemSortBy.PlayCount, ItemSortBy.Name], + limit: 3, + }) + .then(({ data }) => { + resolve(data.Items || []) + }) + .catch((error) => { + console.error('Error fetching top artist tracks:', error) + reject(error) + }) + }) +} diff --git a/src/components/Artist/header.tsx b/src/components/Artist/header.tsx index 6efd802d..e723a1ad 100644 --- a/src/components/Artist/header.tsx +++ b/src/components/Artist/header.tsx @@ -19,6 +19,7 @@ import useStreamingDeviceProfile from '../../stores/device-profile' import { useApi } from '../../stores' import useIsLightMode from '../../hooks/use-is-light-mode' import Icon from '../Global/components/icon' +import { useTopArtistTracks } from '../../api/queries/artist' export default function ArtistHeader(): React.JSX.Element { const { width } = useSafeAreaFrame() @@ -27,6 +28,8 @@ export default function ArtistHeader(): React.JSX.Element { const { artist, albums } = useArtistContext() + const { data: topTracks } = useTopArtistTracks(artist.Id) + const [networkStatus] = useNetworkStatus() const streamingDeviceProfile = useStreamingDeviceProfile() @@ -119,7 +122,7 @@ export default function ArtistHeader(): React.JSX.Element { onPress={() => navigation.navigate('ArtistTracksTab')} > - View Tracks + Tracks