diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index eb98c01a..00000000 --- a/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ce109e38..76c58588 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -13,6 +13,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" + android:usesCleartextTraffic="${usesCleartextTraffic}" android:supportsRtl="true"> { if (!api) return @@ -54,29 +51,6 @@ export function Album(): React.JSX.Element { addToDownloadQueue(jellifyTracks) } - const playAlbum = useCallback( - (shuffled: boolean = false) => { - if (!discs || discs.length === 0) return - - const allTracks = discs.flatMap((disc) => disc.data) ?? [] - if (allTracks.length === 0) return - - loadNewQueue({ - api, - networkStatus, - deviceProfile: streamingDeviceProfile, - track: allTracks[0], - index: 0, - tracklist: allTracks, - queue: album, - queuingType: QueuingType.FromSelection, - shuffled, - startPlayback: true, - }) - }, - [discs, loadNewQueue], - ) - const sections = useMemo( () => (Array.isArray(discs) ? discs : []).map(({ title, data }) => ({ @@ -123,7 +97,7 @@ export function Album(): React.JSX.Element { ) : null }} - ListHeaderComponent={() => AlbumTrackListHeader(album, playAlbum, navigation)} + ListHeaderComponent={AlbumTrackListHeader} renderItem={({ item: track, index }) => ( )} - ListFooterComponent={() => AlbumTrackListFooter(album)} + ListFooterComponent={AlbumTrackListFooter} ListEmptyComponent={() => ( {isPending ? ( @@ -154,13 +128,43 @@ export function Album(): React.JSX.Element { * @param playAlbum The function to call to play the album * @returns A React component */ -function AlbumTrackListHeader( - album: BaseItemDto, - playAlbum: (shuffled?: boolean) => void, - navigation: Pick, 'navigate' | 'dispatch'>, -): React.JSX.Element { +function AlbumTrackListHeader(): React.JSX.Element { + const { api } = useJellifyContext() + const { width } = useSafeAreaFrame() + const [networkStatus] = useNetworkStatus() + const streamingDeviceProfile = useStreamingDeviceProfile() + + const { mutate: loadNewQueue } = useLoadNewQueue() + + const { album, discs } = useAlbumContext() + + const navigation = useNavigation>() + + const playAlbum = useCallback( + (shuffled: boolean = false) => { + if (!discs || discs.length === 0) return + + const allTracks = discs.flatMap((disc) => disc.data) ?? [] + if (allTracks.length === 0) return + + loadNewQueue({ + api, + networkStatus, + deviceProfile: streamingDeviceProfile, + track: allTracks[0], + index: 0, + tracklist: allTracks, + queue: album, + queuingType: QueuingType.FromSelection, + shuffled, + startPlayback: true, + }) + }, + [discs, loadNewQueue], + ) + return ( @@ -239,7 +243,8 @@ function AlbumTrackListHeader( ) } -function AlbumTrackListFooter(album: BaseItemDto): React.JSX.Element { +function AlbumTrackListFooter(): React.JSX.Element { + const { album } = useAlbumContext() const navigation = useNavigation< NativeStackNavigationProp< diff --git a/src/components/Artist/index.tsx b/src/components/Artist/index.tsx index 5dfadf7d..93e67063 100644 --- a/src/components/Artist/index.tsx +++ b/src/components/Artist/index.tsx @@ -7,6 +7,7 @@ import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client' import ItemRow from '../Global/components/item-row' import ArtistHeader from './header' import { Text } from '../Global/helpers/text' +import SimilarArtists from './similar' export default function ArtistNavigation({ navigation, @@ -36,6 +37,10 @@ export default function ArtistNavigation({ title: '', data: albums?.filter(({ ChildCount }) => typeof ChildCount !== 'number') ?? [], }, + { + title: 'Featured On', + data: featuredOn ?? [], + }, ] }, [artist, albums?.map(({ Id }) => Id)]) @@ -56,6 +61,7 @@ export default function ArtistNavigation({ ListHeaderComponent={ArtistHeader} renderSectionHeader={renderSectionHeader} renderItem={({ item }) => } + ListFooterComponent={SimilarArtists} /> ) } diff --git a/src/components/Artist/similar.tsx b/src/components/Artist/similar.tsx index 0009a9db..cfa6165e 100644 --- a/src/components/Artist/similar.tsx +++ b/src/components/Artist/similar.tsx @@ -4,57 +4,54 @@ import { BaseStackParamList } from '../../screens/types' import { useNavigation } from '@react-navigation/native' import { Text } from '../Global/helpers/text' import { useArtistContext } from '../../providers/Artist' -import Animated, { useAnimatedScrollHandler } from 'react-native-reanimated' import { ActivityIndicator } from 'react-native' import navigationRef from '../../../navigation' +import HorizontalCardList from '../Global/components/horizontal-list' +import { H6, YStack } from 'tamagui' export default function SimilarArtists(): React.JSX.Element { const navigation = useNavigation>() - const { similarArtists, fetchingSimilarArtists, scroll } = useArtistContext() - const scrollHandler = useAnimatedScrollHandler({ - onScroll: (event) => { - 'worklet' - scroll.value = event.contentOffset.y - }, - }) + const { artist, similarArtists, fetchingSimilarArtists } = useArtistContext() + return ( - ( - { - navigation.push('Artist', { - artist, - }) - }} - onLongPress={() => { - navigationRef.navigate('Context', { - item: artist, - navigation, - }) - }} - /> - )} - ListEmptyComponent={ - fetchingSimilarArtists ? ( - - ) : ( - - No similar artists - - ) - } - onScroll={scrollHandler} - removeClippedSubviews - /> + + {`Similar to ${artist.Name ?? 'Unknown Artist'}`} + + ( + { + navigation.push('Artist', { + artist, + }) + }} + onLongPress={() => { + navigationRef.navigate('Context', { + item: artist, + navigation, + }) + }} + /> + )} + ListEmptyComponent={ + fetchingSimilarArtists ? ( + + ) : ( + + No similar artists + + ) + } + removeClippedSubviews + /> + ) } diff --git a/src/components/Global/components/horizontal-list.tsx b/src/components/Global/components/horizontal-list.tsx index d40c8312..1530169d 100644 --- a/src/components/Global/components/horizontal-list.tsx +++ b/src/components/Global/components/horizontal-list.tsx @@ -13,6 +13,7 @@ interface HorizontalCardListProps extends FlashListProps {} export default function HorizontalCardList({ data, renderItem, + ...props }: HorizontalCardListProps): React.JSX.Element { return ( ) } diff --git a/src/components/Library/component.tsx b/src/components/Library/component.tsx index 723e9f01..915caa50 100644 --- a/src/components/Library/component.tsx +++ b/src/components/Library/component.tsx @@ -54,7 +54,7 @@ export default function LibraryScreen({ options={{ tabBarIcon: ({ focused, color }) => ( diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 8ebc4e06..0fc35e08 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -7,9 +7,8 @@ import { QueryKeys } from '../../enums/query-keys' import { fetchSearchResults } from '../../api/queries/search' import { useQuery } from '@tanstack/react-query' import { FlatList } from 'react-native' -import { H3 } from '../Global/helpers/text' import { fetchSearchSuggestions } from '../../api/queries/suggestions' -import { getToken, Separator, Spinner, YStack } from 'tamagui' +import { getToken, H3, Separator, Spinner, YStack } from 'tamagui' import Suggestions from './suggestions' import { isEmpty } from 'lodash' import HorizontalCardList from '../Global/components/horizontal-list' diff --git a/src/components/Search/suggestions.tsx b/src/components/Search/suggestions.tsx index 9400649e..e0856488 100644 --- a/src/components/Search/suggestions.tsx +++ b/src/components/Search/suggestions.tsx @@ -1,6 +1,6 @@ import ItemRow from '../Global/components/item-row' -import { H3, Text } from '../Global/helpers/text' -import { Separator, YStack } from 'tamagui' +import { Text } from '../Global/helpers/text' +import { H3, Separator, YStack } from 'tamagui' import { ItemCard } from '../Global/components/item-card' import HorizontalCardList from '../Global/components/horizontal-list' import { FlashList } from '@shopify/flash-list' diff --git a/src/components/Settings/component.tsx b/src/components/Settings/component.tsx index ca4e5e48..9008db02 100644 --- a/src/components/Settings/component.tsx +++ b/src/components/Settings/component.tsx @@ -39,7 +39,7 @@ export default function Settings(): React.JSX.Element { title: 'App', tabBarIcon: ({ focused, color }) => ( @@ -97,7 +97,7 @@ export default function Settings(): React.JSX.Element { options={{ tabBarIcon: ({ focused, color }) => ( diff --git a/src/screens/Discover/index.tsx b/src/screens/Discover/index.tsx index 8b1a9244..e222f63c 100644 --- a/src/screens/Discover/index.tsx +++ b/src/screens/Discover/index.tsx @@ -19,7 +19,7 @@ export function Discover(): React.JSX.Element { return ( - + ()