updates to how frequent artists are retrieved so that it's more accurate

better display support on home screen for larger displays (iPad, Mac)
This commit is contained in:
Violet Caulfield
2025-05-24 10:03:49 -05:00
parent 2a2b1f0e46
commit 4fe19005f8
6 changed files with 58 additions and 26 deletions
+33 -17
View File
@@ -8,6 +8,7 @@ import { getItemsApi } from '@jellyfin/sdk/lib/utils/api'
import { Api } from '@jellyfin/sdk'
import { isUndefined } from 'lodash'
import { JellifyLibrary } from '../../types/JellifyLibrary'
import { fetchItem } from './item'
/**
* Fetches the 100 most frequently played items from the user's library
@@ -66,26 +67,41 @@ export function fetchFrequentlyPlayedArtists(
if (isUndefined(api)) return reject('Client instance not set')
if (isUndefined(library)) return reject('Library instance not set')
getItemsApi(api!)
.getItems({
includeItemTypes: [BaseItemKind.MusicArtist],
parentId: library!.musicLibraryId,
recursive: true,
limit: 100,
startIndex: page * 100,
sortBy: [ItemSortBy.PlayCount],
sortOrder: [SortOrder.Descending],
fetchFrequentlyPlayed(api, library, 0)
.then((frequentTracks) => {
return frequentTracks
.filter((track) => !isUndefined(track.AlbumArtists))
.map((track) => {
return {
artistId: track.AlbumArtists![0].Id!,
playCount: track.UserData?.PlayCount ?? 0,
}
})
})
.then(({ data }) => {
if (data.Items) return data.Items
else return []
.then((albumArtistsWithPlayCounts) => {
return albumArtistsWithPlayCounts.reduce(
(acc, { artistId, playCount }) => {
const existing = acc.find((a) => a.artistId === artistId)
if (existing) {
existing.playCount += playCount
} else {
acc.push({ artistId, playCount })
}
return acc
},
[] as { artistId: string; playCount: number }[],
)
})
.then((artistsWithPlayCounts) => {
console.debug('Fetching artists', artistsWithPlayCounts)
const artists = artistsWithPlayCounts.map((artist) => {
return fetchItem(api, artist.artistId)
})
return Promise.all(artists)
})
.then((artists) => {
resolve(
artists.filter((item, index, artists) => {
return index === artists.findIndex((artist) => artist.Id === item.Id)
}),
)
return resolve(artists.filter((artist) => !isUndefined(artist)))
})
.catch((error) => {
reject(error)
@@ -1,13 +1,14 @@
import HorizontalCardList from '../../../components/Global/components/horizontal-list'
import { StackParamList } from '../../../components/types'
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
import React from 'react'
import React, { useEffect } from 'react'
import { ItemCard } from '../../../components/Global/components/item-card'
import { View, XStack } from 'tamagui'
import { H2, H4, Text } from '../../../components/Global/helpers/text'
import Icon from '../../Global/components/icon'
import { useHomeContext } from '../../../providers/Home'
import { ActivityIndicator } from 'react-native'
import { useDisplayContext } from '../../../providers/Display/display-provider'
export default function FrequentArtists({
navigation,
@@ -21,6 +22,8 @@ export default function FrequentArtists({
isFetchingFrequentArtists,
} = useHomeContext()
const { horizontalItems } = useDisplayContext()
return (
<View>
<XStack
@@ -39,7 +42,7 @@ export default function FrequentArtists({
</XStack>
<HorizontalCardList
data={frequentArtists?.slice(0, 10) ?? []}
data={frequentArtists?.slice(0, horizontalItems) ?? []}
renderItem={({ item: artist }) => (
<ItemCard
item={artist}
@@ -10,6 +10,7 @@ import Icon from '../../Global/components/icon'
import { useQueueContext } from '../../../providers/Player/queue'
import { usePlayerContext } from '../../../providers/Player'
import { H4 } from '../../../components/Global/helpers/text'
import { useDisplayContext } from '../../../providers/Display/display-provider'
export default function FrequentlyPlayedTracks({
navigation,
}: {
@@ -24,6 +25,7 @@ export default function FrequentlyPlayedTracks({
const { useStartPlayback } = usePlayerContext()
const { useLoadNewQueue } = useQueueContext()
const { horizontalItems } = useDisplayContext()
return (
<View>
@@ -44,8 +46,8 @@ export default function FrequentlyPlayedTracks({
<HorizontalCardList
data={
(frequentlyPlayed?.pages.flatMap((page) => page).length ?? 0 > 10)
? frequentlyPlayed?.pages.flatMap((page) => page).slice(0, 10)
(frequentlyPlayed?.pages.flatMap((page) => page).length ?? 0 > horizontalItems)
? frequentlyPlayed?.pages.flatMap((page) => page).slice(0, horizontalItems)
: frequentlyPlayed?.pages.flatMap((page) => page)
}
renderItem={({ item: track, index }) => (
@@ -1,12 +1,13 @@
import React from 'react'
import { View, XStack } from 'tamagui'
import { useHomeContext } from '../../../providers/Home'
import { H2, H4 } from '../../Global/helpers/text'
import { H4 } from '../../Global/helpers/text'
import { StackParamList } from '../../types'
import { ItemCard } from '../../Global/components/item-card'
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
import HorizontalCardList from '../../../components/Global/components/horizontal-list'
import Icon from '../../Global/components/icon'
import { useDisplayContext } from '../../../providers/Display/display-provider'
export default function RecentArtists({
navigation,
@@ -16,6 +17,7 @@ export default function RecentArtists({
const { recentArtists, fetchNextRecentArtists, hasNextRecentArtists, isFetchingRecentArtists } =
useHomeContext()
const { horizontalItems } = useDisplayContext()
return (
<View>
<XStack
@@ -34,7 +36,7 @@ export default function RecentArtists({
</XStack>
<HorizontalCardList
data={recentArtists?.slice(0, 10) ?? []}
data={recentArtists?.slice(0, horizontalItems) ?? []}
renderItem={({ item: recentArtist }) => (
<ItemCard
item={recentArtist}
@@ -1,7 +1,7 @@
import React, { useMemo } from 'react'
import { View, XStack } from 'tamagui'
import { useHomeContext } from '../../../providers/Home'
import { H2, H4 } from '../../Global/helpers/text'
import { H4 } from '../../Global/helpers/text'
import { ItemCard } from '../../Global/components/item-card'
import { usePlayerContext } from '../../../providers/Player'
import { StackParamList } from '../../../components/types'
@@ -11,6 +11,7 @@ import { QueuingType } from '../../../enums/queuing-type'
import HorizontalCardList from '../../../components/Global/components/horizontal-list'
import Icon from '../../Global/components/icon'
import { useQueueContext } from '../../../providers/Player/queue'
import { useDisplayContext } from '../../../providers/Display/display-provider'
export default function RecentlyPlayed({
navigation,
@@ -18,10 +19,13 @@ export default function RecentlyPlayed({
navigation: NativeStackNavigationProp<StackParamList>
}): React.JSX.Element {
const { nowPlaying, useStartPlayback } = usePlayerContext()
const { useLoadNewQueue } = useQueueContext()
const { recentTracks, fetchNextRecentTracks, hasNextRecentTracks, isFetchingRecentTracks } =
useHomeContext()
const { horizontalItems } = useDisplayContext()
return useMemo(() => {
return (
<View>
@@ -42,8 +46,8 @@ export default function RecentlyPlayed({
<HorizontalCardList
data={
(recentTracks?.pages.flatMap((page) => page).length ?? 0 > 10)
? recentTracks?.pages.flatMap((page) => page).slice(0, 10)
(recentTracks?.pages.flatMap((page) => page).length ?? 0 > horizontalItems)
? recentTracks?.pages.flatMap((page) => page).slice(0, horizontalItems)
: recentTracks?.pages.flatMap((page) => page)
}
renderItem={({ index, item: recentlyPlayedTrack }) => (
@@ -4,6 +4,7 @@ import { getTokens } from 'tamagui'
interface DisplayContext {
numberOfColumns: number
horizontalItems: number
display: 'grid' | 'list'
@@ -19,8 +20,11 @@ const DisplayContextInitializer = () => {
const [display, setDisplay] = useState<'grid' | 'list'>('grid')
const [horizontalItems, setHorizontalItems] = useState<number>(width > 800 ? 30 : 15)
return {
numberOfColumns,
horizontalItems,
display,
setDisplay,
}
@@ -28,6 +32,7 @@ const DisplayContextInitializer = () => {
const DisplayContext = createContext<DisplayContext>({
numberOfColumns: 0,
horizontalItems: 0,
display: 'grid',
setDisplay: () => {},
})