diff --git a/src/api/albums.ts b/src/api/albums.ts index 445101d..0472eed 100644 --- a/src/api/albums.ts +++ b/src/api/albums.ts @@ -83,6 +83,28 @@ export const useFetchAlbumSongs = ( return albumSongs; }; +export const useFetchArtistSongs = (api: Api, artistId: string) => { + // TODO: would be nicer to fetch by album so the cache can be shared with useFetchAlbumSongs + const user = useFetchUser(api); + const artistSongs = useQuery({ + queryKey: ["artistSongs", artistId], + queryFn: async () => { + const result = await getItemsApi(api).getItems({ + userId: user?.data?.Id, + parentId: artistId, + includeItemTypes: [BaseItemKind.Audio], + sortBy: [ItemSortBy.ProductionYear, ItemSortBy.SortName], + sortOrder: [SortOrder.Ascending], + recursive: true, + }); + return result.data; + }, + enabled: !!user.isSuccess, + }); + + return artistSongs; +}; + export const useFetchMoreArtistAlbums = ( api: Api, artistId: string, diff --git a/src/components/AlbumDetails/Footer.tsx b/src/components/AlbumDetails/Footer.tsx index 3446232..703b58f 100644 --- a/src/components/AlbumDetails/Footer.tsx +++ b/src/components/AlbumDetails/Footer.tsx @@ -16,13 +16,12 @@ import { AlbumCard } from "../AlbumCard"; import { Separator } from "../Separator"; import { Text } from "../Themed"; -export const AlbumFooter = ({ - albumDetails, - albumSongs, -}: { +type AlbumFooterProps = { albumDetails?: BaseItemDto; albumSongs?: BaseItemDto[]; -}) => { +}; + +export const AlbumFooter = ({ albumDetails, albumSongs }: AlbumFooterProps) => { const { styles } = useStyles(stylesheet); const api = useApi((state) => state.api); const moreAlbums = useFetchMoreArtistAlbums( diff --git a/src/components/ArtistDetails/Header.tsx b/src/components/ArtistDetails/Header.tsx index 6126df2..3446817 100644 --- a/src/components/ArtistDetails/Header.tsx +++ b/src/components/ArtistDetails/Header.tsx @@ -1,20 +1,43 @@ import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client"; import { Image } from "expo-image"; import { View } from "react-native"; -import { useStyles, createStyleSheet } from "react-native-unistyles"; +import { createStyleSheet, useStyles } from "react-native-unistyles"; +import { useFetchUser } from "../../api/user"; +import { usePlayTracks } from "../../hooks/usePlayTracks"; import { useApi } from "../../store/useJelloAuth"; import { extractPrimaryHash } from "../../util/extractPrimaryHash"; import { generateTrackArtworkUrl } from "../../util/generateTrackArtworkUrl"; +import { MusicButton } from "../MusicButton"; import { Text } from "../Themed"; +type ArtistHeaderProps = { + artistDetails: BaseItemDto; + artistSongs: BaseItemDto[]; +}; + export const ArtistHeader = ({ artistDetails, -}: { - artistDetails: BaseItemDto; -}) => { + artistSongs, +}: ArtistHeaderProps) => { const { styles } = useStyles(stylesheet); const api = useApi((state) => state.api); + const playTracks = usePlayTracks(); + const user = useFetchUser(api); + + const onPressPlayArtist = () => { + playTracks({ tracks: artistSongs, api, userId: user.data?.Id }); + }; + + const onPressShuffleArtist = () => { + playTracks({ + tracks: artistSongs, + api, + userId: user.data?.Id, + shuffle: true, + }); + }; + return ( @@ -28,8 +51,8 @@ export const ArtistHeader = ({ {artistDetails?.Name} - {/* - */} + + ); diff --git a/src/navigation/screens/LibraryTab/ArtistDetails.tsx b/src/navigation/screens/LibraryTab/ArtistDetails.tsx index 60f3277..916a08b 100644 --- a/src/navigation/screens/LibraryTab/ArtistDetails.tsx +++ b/src/navigation/screens/LibraryTab/ArtistDetails.tsx @@ -5,6 +5,7 @@ import { useCallback } from "react"; import { Animated, SafeAreaView, View } from "react-native"; import { createStyleSheet, useStyles } from "react-native-unistyles"; +import { useFetchArtistSongs } from "../../../api/albums"; import { useFetchArtistAlbums, useFetchArtistDetails, @@ -27,6 +28,8 @@ export const ArtistDetailsScreen = ({ route, navigation }: Props) => { const api = useApi((state) => state.api); const artistDetails = useFetchArtistDetails(api, artistId); const artistAlbums = useFetchArtistAlbums(api, artistId); + const artistSongs = useFetchArtistSongs(api, artistId); + const headerHeight = useHeaderHeight(); const onPressArtistItem = useCallback( @@ -51,7 +54,11 @@ export const ArtistDetailsScreen = ({ route, navigation }: Props) => { const opacity = useFadeIn([artistDetails, artistAlbums]); - if (artistDetails.isPending || artistAlbums.isPending) { + if ( + artistDetails.isPending || + artistAlbums.isPending || + artistSongs.isPending + ) { return ; } @@ -59,7 +66,10 @@ export const ArtistDetailsScreen = ({ route, navigation }: Props) => { + } ListFooterComponent={} data={artistAlbums.data?.Items} diff --git a/src/navigation/screens/Modals/NowPlaying.tsx b/src/navigation/screens/Modals/NowPlaying.tsx index c860530..7f66213 100644 --- a/src/navigation/screens/Modals/NowPlaying.tsx +++ b/src/navigation/screens/Modals/NowPlaying.tsx @@ -7,7 +7,6 @@ import { Slider } from "react-native-awesome-slider"; import { ContextMenuButton, MenuActionConfig, - OnPressMenuItemEvent, } from "react-native-ios-context-menu"; import LinearGradient from "react-native-linear-gradient"; import { useDerivedValue, useSharedValue } from "react-native-reanimated";