import { useQuery } from '@tanstack/react-query'; import { useMemo, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { FeatureCarousel } from '/@/renderer/components/feature-carousel/feature-carousel'; import { MemoizedSwiperGridCarousel } from '/@/renderer/components/grid-carousel/grid-carousel'; import { NativeScrollArea } from '/@/renderer/components/native-scroll-area/native-scroll-area'; import { albumQueries } from '/@/renderer/features/albums/api/album-api'; import { homeQueries } from '/@/renderer/features/home/api/home-api'; import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared'; import { songsQueries } from '/@/renderer/features/songs/api/songs-api'; import { AppRoute } from '/@/renderer/router/routes'; import { HomeItem, useCurrentServer, useGeneralSettings, useWindowSettings, } from '/@/renderer/store'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { Group } from '/@/shared/components/group/group'; import { Icon } from '/@/shared/components/icon/icon'; import { Spinner } from '/@/shared/components/spinner/spinner'; import { Stack } from '/@/shared/components/stack/stack'; import { TextTitle } from '/@/shared/components/text-title/text-title'; import { AlbumListSort, LibraryItem, ServerType, SongListSort, SortOrder, } from '/@/shared/types/domain-types'; import { Platform } from '/@/shared/types/types'; const BASE_QUERY_ARGS = { limit: 15, sortOrder: SortOrder.DESC, startIndex: 0, }; const HomeRoute = () => { const { t } = useTranslation(); const scrollAreaRef = useRef(null); const server = useCurrentServer(); const { windowBarStyle } = useWindowSettings(); const { homeFeature, homeItems } = useGeneralSettings(); const feature = useQuery( albumQueries.list({ options: { enabled: homeFeature, gcTime: 1000 * 60, staleTime: 1000 * 60, }, query: { limit: 20, sortBy: AlbumListSort.RANDOM, sortOrder: SortOrder.DESC, startIndex: 0, }, serverId: server?.id, }), ); const isJellyfin = server?.type === ServerType.JELLYFIN; const featureItemsWithImage = useMemo(() => { return feature.data?.items?.filter((item) => item.imageUrl) ?? []; }, [feature.data?.items]); const queriesEnabled = useMemo(() => { return homeItems.reduce( (previous: Record, current) => ({ ...previous, [current.id]: !current.disabled, }), {} as Record, ); }, [homeItems]); const random = useQuery( albumQueries.list({ options: { staleTime: 1000 * 60 * 5, }, query: { ...BASE_QUERY_ARGS, sortBy: AlbumListSort.RANDOM, sortOrder: SortOrder.ASC, startIndex: 0, }, serverId: server?.id, }), ); const recentlyPlayed = useQuery( homeQueries.recentlyPlayed({ options: { staleTime: 0, }, query: { ...BASE_QUERY_ARGS, sortBy: AlbumListSort.RECENTLY_PLAYED, sortOrder: SortOrder.DESC, startIndex: 0, }, serverId: server?.id, }), ); const recentlyAdded = useQuery( albumQueries.list({ options: { staleTime: 1000 * 60 * 5, }, query: { ...BASE_QUERY_ARGS, sortBy: AlbumListSort.RECENTLY_ADDED, sortOrder: SortOrder.DESC, startIndex: 0, }, serverId: server?.id, }), ); const mostPlayedAlbums = useQuery( albumQueries.list({ options: { enabled: server?.type === ServerType.SUBSONIC || server?.type === ServerType.NAVIDROME, staleTime: 1000 * 60 * 5, }, query: { ...BASE_QUERY_ARGS, sortBy: AlbumListSort.PLAY_COUNT, sortOrder: SortOrder.DESC, startIndex: 0, }, serverId: server?.id, }), ); const mostPlayedSongs = useQuery( songsQueries.list( { options: { enabled: server?.type === ServerType.JELLYFIN, staleTime: 1000 * 60 * 5, }, query: { ...BASE_QUERY_ARGS, sortBy: SongListSort.PLAY_COUNT, sortOrder: SortOrder.DESC, startIndex: 0, }, serverId: server?.id, }, 300, ), ); const recentlyReleased = useQuery( albumQueries.list({ options: { enabled: queriesEnabled[HomeItem.RECENTLY_RELEASED], staleTime: 1000 * 60 * 5, }, query: { ...BASE_QUERY_ARGS, sortBy: AlbumListSort.RELEASE_DATE, }, serverId: server?.id, }), ); const isLoading = (random.isLoading && queriesEnabled[HomeItem.RANDOM]) || (recentlyPlayed.isLoading && queriesEnabled[HomeItem.RECENTLY_PLAYED] && !isJellyfin) || (recentlyAdded.isLoading && queriesEnabled[HomeItem.RECENTLY_ADDED]) || (recentlyReleased.isLoading && queriesEnabled[HomeItem.RECENTLY_RELEASED]) || (((isJellyfin && mostPlayedSongs.isLoading) || (!isJellyfin && mostPlayedAlbums.isLoading)) && queriesEnabled[HomeItem.MOST_PLAYED]); if (isLoading) { return ; } const carousels = { [HomeItem.MOST_PLAYED]: { data: isJellyfin ? mostPlayedSongs?.data?.items : mostPlayedAlbums?.data?.items, itemType: isJellyfin ? LibraryItem.SONG : LibraryItem.ALBUM, query: isJellyfin ? mostPlayedSongs : mostPlayedAlbums, title: t('page.home.mostPlayed', { postProcess: 'sentenceCase' }), }, [HomeItem.RANDOM]: { data: random?.data?.items, itemType: LibraryItem.ALBUM, query: random, title: t('page.home.explore', { postProcess: 'sentenceCase' }), }, [HomeItem.RECENTLY_ADDED]: { data: recentlyAdded?.data?.items, itemType: LibraryItem.ALBUM, query: recentlyAdded, title: t('page.home.newlyAdded', { postProcess: 'sentenceCase' }), }, [HomeItem.RECENTLY_PLAYED]: { data: recentlyPlayed?.data?.items, itemType: LibraryItem.ALBUM, query: recentlyPlayed, title: t('page.home.recentlyPlayed', { postProcess: 'sentenceCase' }), }, [HomeItem.RECENTLY_RELEASED]: { data: recentlyReleased?.data?.items, itemType: LibraryItem.ALBUM, query: recentlyReleased, title: t('page.home.recentlyReleased', { postProcess: 'sentenceCase' }), }, }; const sortedCarousel = homeItems .filter((item) => { if (item.disabled) { return false; } if (isJellyfin && item.id === HomeItem.RECENTLY_PLAYED) { return false; } return true; }) .map((item) => ({ ...carousels[item.id], uniqueId: item.id, })); return ( {t('page.home.title', { postProcess: 'titleCase' })} ), offset: 200, }} ref={scrollAreaRef} > {homeFeature && } {sortedCarousel.map((carousel) => ( {carousel.title} carousel.query.refetch()} variant="transparent" > ), }} uniqueId={carousel.uniqueId} /> ))} ); }; export default HomeRoute;