mirror of
https://github.com/Jellify-Music/App.git
synced 2026-01-05 18:40:01 -06:00
rendering fiixes to playlist and albums
bump react native sortables
This commit is contained in:
4
bun.lock
4
bun.lock
@@ -51,7 +51,7 @@
|
||||
"react-native-reanimated": "4.1.5",
|
||||
"react-native-safe-area-context": "5.6.2",
|
||||
"react-native-screens": "4.18.0",
|
||||
"react-native-sortables": "^1.9.3",
|
||||
"react-native-sortables": "1.9.4",
|
||||
"react-native-text-ticker": "^1.15.0",
|
||||
"react-native-toast-message": "^2.3.3",
|
||||
"react-native-track-player": "5.0.0-alpha0",
|
||||
@@ -1942,7 +1942,7 @@
|
||||
|
||||
"react-native-screens": ["react-native-screens@4.18.0", "", { "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-mRTLWL7Uc1p/RFNveEIIrhP22oxHduC2ZnLr/2iHwBeYpGXR0rJZ7Bgc0ktxQSHRjWTPT70qc/7yd4r9960PBQ=="],
|
||||
|
||||
"react-native-sortables": ["react-native-sortables@1.9.3", "", { "optionalDependencies": { "react-native-haptic-feedback": ">=2.0.0" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.0.0", "react-native-reanimated": ">=3.0.0" } }, "sha512-VLhW9+3AVEaJNwwQSgN+n/Qe+YRB0C0mNWTjHhyzcZ+YjY4BmJao4bZxl5lD6EsfqZ1Ij6B2ZdxjNlSkUXrvow=="],
|
||||
"react-native-sortables": ["react-native-sortables@1.9.4", "", { "optionalDependencies": { "react-native-haptic-feedback": ">=2.0.0" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.0.0", "react-native-reanimated": ">=3.0.0" } }, "sha512-a6hxT+gl14HA5Sm8UiLXJqF8KMEQVa+mUJd75OnzoVsmrxUDtjAatlMdV0kI9qTQDT/ZSFLPRmdUhOR762IA4g=="],
|
||||
|
||||
"react-native-tab-view": ["react-native-tab-view@4.2.0", "", { "dependencies": { "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-pager-view": ">= 6.0.0" } }, "sha512-TUbh7Yr0tE/99t1pJQLbQ+4/Px67xkT7/r3AhfV+93Q3WoUira0Lx7yuKUP2C118doqxub8NCLERwcqsHr29nQ=="],
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
"react-native-reanimated": "4.1.5",
|
||||
"react-native-safe-area-context": "5.6.2",
|
||||
"react-native-screens": "4.18.0",
|
||||
"react-native-sortables": "^1.9.3",
|
||||
"react-native-sortables": "1.9.4",
|
||||
"react-native-text-ticker": "^1.15.0",
|
||||
"react-native-toast-message": "^2.3.3",
|
||||
"react-native-track-player": "5.0.0-alpha0",
|
||||
|
||||
@@ -17,7 +17,6 @@ import { useNetworkContext } from '../../providers/Network'
|
||||
import { useNetworkStatus } from '../../stores/network'
|
||||
import { useLoadNewQueue } from '../../providers/Player/hooks/mutations'
|
||||
import { QueuingType } from '../../enums/queuing-type'
|
||||
import { useAlbumContext } from '../../providers/Album'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import HomeStackParamList from '../../screens/Home/types'
|
||||
import LibraryStackParamList from '../../screens/Library/types'
|
||||
@@ -26,6 +25,9 @@ import { BaseStackParamList } from '../../screens/types'
|
||||
import useStreamingDeviceProfile, { useDownloadingDeviceProfile } from '../../stores/device-profile'
|
||||
import { closeAllSwipeableRows } from '../Global/components/swipeable-row-registry'
|
||||
import { useApi } from '../../stores'
|
||||
import { QueryKeys } from '../../enums/query-keys'
|
||||
import { fetchAlbumDiscs } from '../../api/queries/item'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
/**
|
||||
* The screen for an Album's track list
|
||||
@@ -35,12 +37,16 @@ import { useApi } from '../../stores'
|
||||
*
|
||||
* @returns A React component
|
||||
*/
|
||||
export function Album(): React.JSX.Element {
|
||||
export function Album({ album }: { album: BaseItemDto }): React.JSX.Element {
|
||||
const navigation = useNavigation<NativeStackNavigationProp<BaseStackParamList>>()
|
||||
|
||||
const { album, discs, isPending } = useAlbumContext()
|
||||
|
||||
const api = useApi()
|
||||
|
||||
const { data: discs, isPending } = useQuery({
|
||||
queryKey: [QueryKeys.ItemTracks, album.Id],
|
||||
queryFn: () => fetchAlbumDiscs(api, album),
|
||||
})
|
||||
|
||||
const { addToDownloadQueue, pendingDownloads } = useNetworkContext()
|
||||
const downloadingDeviceProfile = useDownloadingDeviceProfile()
|
||||
|
||||
@@ -92,7 +98,7 @@ export function Album(): React.JSX.Element {
|
||||
</XStack>
|
||||
) : null
|
||||
}}
|
||||
ListHeaderComponent={AlbumTrackListHeader}
|
||||
ListHeaderComponent={() => <AlbumTrackListHeader album={album} />}
|
||||
renderItem={({ item: track, index }) => (
|
||||
<Track
|
||||
navigation={navigation}
|
||||
@@ -102,7 +108,7 @@ export function Album(): React.JSX.Element {
|
||||
queue={album}
|
||||
/>
|
||||
)}
|
||||
ListFooterComponent={AlbumTrackListFooter}
|
||||
ListFooterComponent={() => <AlbumTrackListFooter album={album} />}
|
||||
ListEmptyComponent={() => (
|
||||
<YStack flex={1} alignContent='center'>
|
||||
{isPending ? <Spinner color={'$primary'} /> : <Text>No tracks found</Text>}
|
||||
@@ -120,7 +126,7 @@ export function Album(): React.JSX.Element {
|
||||
* @param playAlbum The function to call to play the album
|
||||
* @returns A React component
|
||||
*/
|
||||
function AlbumTrackListHeader(): React.JSX.Element {
|
||||
function AlbumTrackListHeader({ album }: { album: BaseItemDto }): React.JSX.Element {
|
||||
const api = useApi()
|
||||
|
||||
const { width } = useSafeAreaFrame()
|
||||
@@ -130,7 +136,10 @@ function AlbumTrackListHeader(): React.JSX.Element {
|
||||
|
||||
const loadNewQueue = useLoadNewQueue()
|
||||
|
||||
const { album, discs } = useAlbumContext()
|
||||
const { data: discs, isPending } = useQuery({
|
||||
queryKey: [QueryKeys.ItemTracks, album.Id],
|
||||
queryFn: () => fetchAlbumDiscs(api, album),
|
||||
})
|
||||
|
||||
const navigation = useNavigation<NativeStackNavigationProp<BaseStackParamList>>()
|
||||
|
||||
@@ -235,8 +244,7 @@ function AlbumTrackListHeader(): React.JSX.Element {
|
||||
)
|
||||
}
|
||||
|
||||
function AlbumTrackListFooter(): React.JSX.Element {
|
||||
const { album } = useAlbumContext()
|
||||
function AlbumTrackListFooter({ album }: { album: BaseItemDto }): React.JSX.Element {
|
||||
const navigation =
|
||||
useNavigation<
|
||||
NativeStackNavigationProp<
|
||||
|
||||
@@ -3,7 +3,6 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
||||
import { H5, Spacer, XStack, YStack } from 'tamagui'
|
||||
import InstantMixButton from '../../Global/components/instant-mix-button'
|
||||
import Icon from '../../Global/components/icon'
|
||||
import { usePlaylistContext } from '../../../providers/Playlist'
|
||||
import { useNetworkStatus } from '../../../../src/stores/network'
|
||||
import { useNetworkContext } from '../../../../src/providers/Network'
|
||||
import { ActivityIndicator } from 'react-native'
|
||||
@@ -19,15 +18,21 @@ import ItemImage from '../../Global/components/image'
|
||||
import { useApi } from '../../../stores'
|
||||
import Input from '../../Global/helpers/input'
|
||||
import Animated, { FadeInDown, FadeOutDown } from 'react-native-reanimated'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
|
||||
export default function PlaylistTracklistHeader({
|
||||
canEdit,
|
||||
playlist,
|
||||
playlistTracks,
|
||||
editing,
|
||||
newName,
|
||||
setNewName,
|
||||
}: {
|
||||
canEdit?: boolean
|
||||
playlist: BaseItemDto
|
||||
playlistTracks: BaseItemDto[] | undefined
|
||||
editing: boolean
|
||||
newName: string
|
||||
setNewName: Dispatch<SetStateAction<string>>
|
||||
}): React.JSX.Element {
|
||||
const { playlist, playlistTracks, editing, setEditing, newName, setNewName } =
|
||||
usePlaylistContext()
|
||||
|
||||
return (
|
||||
<YStack justifyContent='center' alignItems='center' paddingTop={'$1'} marginBottom={'$2'}>
|
||||
<YStack justifyContent='center' alignContent='center' padding={'$2'}>
|
||||
@@ -68,10 +73,8 @@ export default function PlaylistTracklistHeader({
|
||||
<Animated.View entering={FadeInDown} exiting={FadeOutDown}>
|
||||
<PlaylistHeaderControls
|
||||
editing={editing}
|
||||
setEditing={setEditing}
|
||||
playlist={playlist}
|
||||
playlistTracks={playlistTracks ?? []}
|
||||
canEdit={canEdit}
|
||||
/>
|
||||
</Animated.View>
|
||||
) : (
|
||||
@@ -83,16 +86,12 @@ export default function PlaylistTracklistHeader({
|
||||
|
||||
function PlaylistHeaderControls({
|
||||
editing,
|
||||
setEditing,
|
||||
playlist,
|
||||
playlistTracks,
|
||||
canEdit,
|
||||
}: {
|
||||
editing: boolean
|
||||
setEditing: (editing: boolean) => void
|
||||
playlist: BaseItemDto
|
||||
playlistTracks: BaseItemDto[]
|
||||
canEdit: boolean | undefined
|
||||
}): React.JSX.Element {
|
||||
const { addToDownloadQueue, pendingDownloads } = useNetworkContext()
|
||||
const streamingDeviceProfile = useStreamingDeviceProfile()
|
||||
@@ -133,18 +132,7 @@ function PlaylistHeaderControls({
|
||||
return (
|
||||
<XStack justifyContent='center' marginVertical={'$1'} gap={'$2'} flexWrap='wrap'>
|
||||
<YStack justifyContent='center' alignContent='center'>
|
||||
{editing && canEdit ? (
|
||||
<Icon
|
||||
color={'$danger'}
|
||||
name='delete-sweep-outline' // otherwise use "delete-circle"
|
||||
onPress={() => {
|
||||
navigation.push('DeletePlaylist', { playlist })
|
||||
}}
|
||||
small
|
||||
/>
|
||||
) : (
|
||||
<InstantMixButton item={playlist} navigation={navigation} />
|
||||
)}
|
||||
<InstantMixButton item={playlist} navigation={navigation} />
|
||||
</YStack>
|
||||
|
||||
<YStack justifyContent='center' alignContent='center'>
|
||||
@@ -155,16 +143,6 @@ function PlaylistHeaderControls({
|
||||
<Icon name='shuffle' onPress={() => playPlaylist(true)} small />
|
||||
</YStack>
|
||||
|
||||
{canEdit && (
|
||||
<YStack justifyContent='center' alignContent='center'>
|
||||
<Icon
|
||||
color={'$borderColor'}
|
||||
name={editing ? 'content-save-outline' : 'pencil'}
|
||||
onPress={() => setEditing(!editing)}
|
||||
small
|
||||
/>
|
||||
</YStack>
|
||||
)}
|
||||
<YStack justifyContent='center' alignContent='center'>
|
||||
{!isDownloading ? (
|
||||
<Icon
|
||||
|
||||
@@ -2,12 +2,10 @@ import { ScrollView, Spinner, useTheme, XStack } from 'tamagui'
|
||||
import Track from '../Global/components/track'
|
||||
import Icon from '../Global/components/icon'
|
||||
import { PlaylistProps } from './interfaces'
|
||||
import { usePlaylistContext } from '../../providers/Playlist'
|
||||
import { StackActions, useNavigation } from '@react-navigation/native'
|
||||
import { RootStackParamList } from '../../screens/types'
|
||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
||||
import Sortable from 'react-native-sortables'
|
||||
import { useLayoutEffect } from 'react'
|
||||
import { useReducedHapticsSetting } from '../../stores/settings/app'
|
||||
import { RenderItemInfo } from 'react-native-sortables/dist/typescript/types'
|
||||
import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client'
|
||||
@@ -19,6 +17,12 @@ import { QueuingType } from '../../enums/queuing-type'
|
||||
import { useApi } from '../../stores'
|
||||
import useStreamingDeviceProfile from '../../stores/device-profile'
|
||||
import { RefreshControl } from 'react-native-gesture-handler'
|
||||
import { useEffect, useLayoutEffect, useState } from 'react'
|
||||
import { updatePlaylist } from '../../../src/api/mutations/playlists'
|
||||
import { usePlaylistTracks } from '../../../src/api/queries/playlist'
|
||||
import useHapticFeedback from '../../hooks/use-haptic-feedback'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import Animated, { SlideInLeft, SlideOutRight } from 'react-native-reanimated'
|
||||
|
||||
export default function Playlist({
|
||||
playlist,
|
||||
@@ -29,18 +33,62 @@ export default function Playlist({
|
||||
|
||||
const theme = useTheme()
|
||||
|
||||
const {
|
||||
playlistTracks,
|
||||
isPending,
|
||||
refetch,
|
||||
editing,
|
||||
setEditing,
|
||||
isUpdating,
|
||||
newName,
|
||||
setPlaylistTracks,
|
||||
useUpdatePlaylist,
|
||||
handleCancel,
|
||||
} = usePlaylistContext()
|
||||
const [editing, setEditing] = useState<boolean>(false)
|
||||
|
||||
const [newName, setNewName] = useState<string>(playlist.Name ?? '')
|
||||
|
||||
const [playlistTracks, setPlaylistTracks] = useState<BaseItemDto[] | undefined>(undefined)
|
||||
|
||||
const trigger = useHapticFeedback()
|
||||
|
||||
const { data: tracks, isPending, refetch, isSuccess } = usePlaylistTracks(playlist)
|
||||
|
||||
const { mutate: useUpdatePlaylist, isPending: isUpdating } = useMutation({
|
||||
mutationFn: ({
|
||||
playlist,
|
||||
tracks,
|
||||
newName,
|
||||
}: {
|
||||
playlist: BaseItemDto
|
||||
tracks: BaseItemDto[]
|
||||
newName: string
|
||||
}) => {
|
||||
return updatePlaylist(
|
||||
api,
|
||||
playlist.Id!,
|
||||
newName,
|
||||
tracks.map((track) => track.Id!),
|
||||
)
|
||||
},
|
||||
onSuccess: () => {
|
||||
trigger('notificationSuccess')
|
||||
|
||||
// Refresh playlist component data
|
||||
refetch()
|
||||
},
|
||||
onError: () => {
|
||||
trigger('notificationError')
|
||||
setNewName(playlist.Name ?? '')
|
||||
setPlaylistTracks(tracks ?? [])
|
||||
},
|
||||
onSettled: () => {
|
||||
setEditing(false)
|
||||
},
|
||||
})
|
||||
|
||||
const handleCancel = () => {
|
||||
setEditing(false)
|
||||
setNewName(playlist.Name ?? '')
|
||||
setPlaylistTracks(tracks)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isPending && isSuccess) setPlaylistTracks(tracks)
|
||||
}, [tracks, isPending, isSuccess])
|
||||
|
||||
useEffect(() => {
|
||||
if (!editing) refetch()
|
||||
}, [editing])
|
||||
|
||||
const loadNewQueue = useLoadNewQueue()
|
||||
|
||||
@@ -128,9 +176,11 @@ export default function Playlist({
|
||||
return (
|
||||
<XStack alignItems='center' key={`${index}-${track.Id}`} flex={1}>
|
||||
{editing && (
|
||||
<Sortable.Handle>
|
||||
<Icon name='drag' />
|
||||
</Sortable.Handle>
|
||||
<Animated.View entering={SlideInLeft} exiting={SlideOutRight}>
|
||||
<Sortable.Handle>
|
||||
<Icon name='drag' />
|
||||
</Sortable.Handle>
|
||||
</Animated.View>
|
||||
)}
|
||||
|
||||
<Sortable.Touchable
|
||||
@@ -181,7 +231,13 @@ export default function Playlist({
|
||||
/>
|
||||
}
|
||||
>
|
||||
<PlaylistTracklistHeader />
|
||||
<PlaylistTracklistHeader
|
||||
setNewName={setNewName}
|
||||
newName={newName}
|
||||
editing={editing}
|
||||
playlist={playlist}
|
||||
playlistTracks={playlistTracks}
|
||||
/>
|
||||
|
||||
<Sortable.Grid
|
||||
data={playlistTracks ?? []}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models'
|
||||
import { QueryKeys } from '../../enums/query-keys'
|
||||
import { fetchAlbumDiscs } from '../../api/queries/item'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { createContext, ReactNode, useContext } from 'react'
|
||||
import { useApi } from '../../stores'
|
||||
|
||||
interface AlbumContext {
|
||||
album: BaseItemDto
|
||||
discs: { title: string; data: BaseItemDto[] }[] | undefined
|
||||
isPending: boolean
|
||||
}
|
||||
|
||||
function AlbumContextInitializer(album: BaseItemDto): AlbumContext {
|
||||
const api = useApi()
|
||||
|
||||
const { data: discs, isPending } = useQuery({
|
||||
queryKey: [QueryKeys.ItemTracks, album.Id],
|
||||
queryFn: () => fetchAlbumDiscs(api, album),
|
||||
})
|
||||
|
||||
return {
|
||||
album,
|
||||
discs,
|
||||
isPending,
|
||||
}
|
||||
}
|
||||
|
||||
const AlbumContext = createContext<AlbumContext>({
|
||||
album: {},
|
||||
discs: undefined,
|
||||
isPending: false,
|
||||
})
|
||||
|
||||
export const AlbumProvider: ({
|
||||
album,
|
||||
children,
|
||||
}: {
|
||||
album: BaseItemDto
|
||||
children: ReactNode
|
||||
}) => React.JSX.Element = ({ album, children }) => {
|
||||
const context = AlbumContextInitializer(album)
|
||||
|
||||
return <AlbumContext.Provider value={context}>{children}</AlbumContext.Provider>
|
||||
}
|
||||
|
||||
export const useAlbumContext = () => useContext(AlbumContext)
|
||||
@@ -1,138 +0,0 @@
|
||||
import { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models'
|
||||
import { UseMutateFunction, useMutation } from '@tanstack/react-query'
|
||||
import { createContext, ReactNode, useContext, useEffect, useState } from 'react'
|
||||
import { updatePlaylist } from '../../api/mutations/playlists'
|
||||
import { SharedValue, useSharedValue } from 'react-native-reanimated'
|
||||
import useHapticFeedback from '../../hooks/use-haptic-feedback'
|
||||
import { useApi } from '../../stores'
|
||||
import { usePlaylistTracks } from '../../api/queries/playlist'
|
||||
|
||||
interface PlaylistContext {
|
||||
playlist: BaseItemDto
|
||||
playlistTracks: BaseItemDto[] | undefined
|
||||
refetch: () => void
|
||||
isPending: boolean
|
||||
editing: boolean
|
||||
setEditing: (editing: boolean) => void
|
||||
newName: string
|
||||
setNewName: (name: string) => void
|
||||
setPlaylistTracks: (tracks: BaseItemDto[]) => void
|
||||
useUpdatePlaylist: UseMutateFunction<
|
||||
void,
|
||||
Error,
|
||||
{
|
||||
playlist: BaseItemDto
|
||||
tracks: BaseItemDto[]
|
||||
newName: string
|
||||
},
|
||||
unknown
|
||||
>
|
||||
isUpdating?: boolean
|
||||
handleCancel: () => void
|
||||
}
|
||||
|
||||
const PlaylistContextInitializer = (playlist: BaseItemDto) => {
|
||||
const api = useApi()
|
||||
|
||||
const canEdit = playlist.CanDelete
|
||||
const [editing, setEditing] = useState<boolean>(false)
|
||||
|
||||
const [newName, setNewName] = useState<string>(playlist.Name ?? '')
|
||||
|
||||
const [playlistTracks, setPlaylistTracks] = useState<BaseItemDto[] | undefined>(undefined)
|
||||
|
||||
const trigger = useHapticFeedback()
|
||||
|
||||
const { data: tracks, isPending, refetch, isSuccess } = usePlaylistTracks(playlist)
|
||||
|
||||
const { mutate: useUpdatePlaylist, isPending: isUpdating } = useMutation({
|
||||
mutationFn: ({
|
||||
playlist,
|
||||
tracks,
|
||||
newName,
|
||||
}: {
|
||||
playlist: BaseItemDto
|
||||
tracks: BaseItemDto[]
|
||||
newName: string
|
||||
}) => {
|
||||
return updatePlaylist(
|
||||
api,
|
||||
playlist.Id!,
|
||||
newName,
|
||||
tracks.map((track) => track.Id!),
|
||||
)
|
||||
},
|
||||
onSuccess: () => {
|
||||
trigger('notificationSuccess')
|
||||
|
||||
// Refresh playlist component data
|
||||
refetch()
|
||||
},
|
||||
onError: () => {
|
||||
trigger('notificationError')
|
||||
setNewName(playlist.Name ?? '')
|
||||
setPlaylistTracks(tracks ?? [])
|
||||
},
|
||||
onSettled: () => {
|
||||
setEditing(false)
|
||||
},
|
||||
})
|
||||
|
||||
const handleCancel = () => {
|
||||
setEditing(false)
|
||||
setNewName(playlist.Name ?? '')
|
||||
setPlaylistTracks(tracks)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isPending && isSuccess) setPlaylistTracks(tracks)
|
||||
}, [tracks, isPending, isSuccess])
|
||||
|
||||
useEffect(() => {
|
||||
if (!editing) refetch()
|
||||
}, [editing])
|
||||
|
||||
return {
|
||||
playlist,
|
||||
playlistTracks,
|
||||
refetch,
|
||||
isPending,
|
||||
editing,
|
||||
setEditing,
|
||||
newName,
|
||||
setNewName,
|
||||
setPlaylistTracks,
|
||||
useUpdatePlaylist,
|
||||
handleCancel,
|
||||
isUpdating,
|
||||
}
|
||||
}
|
||||
|
||||
const PlaylistContext = createContext<PlaylistContext>({
|
||||
playlist: {},
|
||||
playlistTracks: undefined,
|
||||
refetch: () => {},
|
||||
isPending: false,
|
||||
editing: false,
|
||||
setEditing: () => {},
|
||||
newName: '',
|
||||
setNewName: () => {},
|
||||
setPlaylistTracks: () => {},
|
||||
useUpdatePlaylist: () => {},
|
||||
handleCancel: () => {},
|
||||
isUpdating: false,
|
||||
})
|
||||
|
||||
export const PlaylistProvider = ({
|
||||
playlist,
|
||||
children,
|
||||
}: {
|
||||
playlist: BaseItemDto
|
||||
children: ReactNode
|
||||
}) => {
|
||||
const context = PlaylistContextInitializer(playlist)
|
||||
|
||||
return <PlaylistContext.Provider value={context}>{children}</PlaylistContext.Provider>
|
||||
}
|
||||
|
||||
export const usePlaylistContext = () => useContext(PlaylistContext)
|
||||
@@ -1,13 +1,8 @@
|
||||
import { Album } from '../../components/Album'
|
||||
import { AlbumProps } from '../types'
|
||||
import { AlbumProvider } from '../../providers/Album'
|
||||
|
||||
export default function AlbumScreen({ route, navigation }: AlbumProps): React.JSX.Element {
|
||||
const { album } = route.params
|
||||
|
||||
return (
|
||||
<AlbumProvider album={album}>
|
||||
<Album />
|
||||
</AlbumProvider>
|
||||
)
|
||||
return <Album album={album} />
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { BaseStackParamList, RootStackParamList } from '../types'
|
||||
import { BaseStackParamList } from '../types'
|
||||
import { RouteProp } from '@react-navigation/native'
|
||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
||||
import React from 'react'
|
||||
import Playlist from '../../components/Playlist/index'
|
||||
import { PlaylistProvider } from '../../providers/Playlist'
|
||||
|
||||
export function PlaylistScreen({
|
||||
route,
|
||||
@@ -13,12 +12,10 @@ export function PlaylistScreen({
|
||||
navigation: NativeStackNavigationProp<BaseStackParamList>
|
||||
}): React.JSX.Element {
|
||||
return (
|
||||
<PlaylistProvider playlist={route.params.playlist}>
|
||||
<Playlist
|
||||
playlist={route.params.playlist}
|
||||
navigation={navigation}
|
||||
canEdit={route.params.canEdit}
|
||||
/>
|
||||
</PlaylistProvider>
|
||||
<Playlist
|
||||
playlist={route.params.playlist}
|
||||
navigation={navigation}
|
||||
canEdit={route.params.canEdit}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user