diff --git a/app/components/ContextMenu.tsx b/app/components/ContextMenu.tsx index 604071c..68c5a8b 100644 --- a/app/components/ContextMenu.tsx +++ b/app/components/ContextMenu.tsx @@ -1,14 +1,15 @@ import PressableOpacity from '@app/components/PressableOpacity' -import { AlbumListItem } from '@app/models/music' +import { AlbumListItem, Song } from '@app/models/music' import colors from '@app/styles/colors' import font from '@app/styles/font' -import { useNavigation } from '@react-navigation/native' +import { NavigationProp, useNavigation } from '@react-navigation/native' import { ReactComponentLike } from 'prop-types' import React from 'react' import { ScrollView, StyleProp, StyleSheet, Text, View, ViewStyle } from 'react-native' import FastImage from 'react-native-fast-image' import { Menu, MenuOption, MenuOptions, MenuTrigger, renderers } from 'react-native-popup-menu' import IconFA from 'react-native-vector-icons/FontAwesome' +import IconFA5 from 'react-native-vector-icons/FontAwesome5' import IconMat from 'react-native-vector-icons/MaterialIcons' import CoverArt from './CoverArt' @@ -97,56 +98,124 @@ const ContextMenuIconTextOption = React.memo( ), ) +const MenuHeader = React.memo<{ + coverArt?: string + title: string + subtitle?: string +}>(({ coverArt, title, subtitle }) => ( + + {coverArt ? ( + + ) : ( + <> + )} + + + {title} + + {subtitle ? ( + + {subtitle} + + ) : ( + <> + )} + + +)) + +const OptionStar = React.memo(() => ( + +)) + +const OptionViewArtist = React.memo<{ + navigation: NavigationProp + artist?: string + artistId?: string +}>(({ navigation, artist, artistId }) => { + if (!artist || !artistId) { + return <> + } + + return ( + navigation.navigate('artist', { id: artistId, title: artist })} + /> + ) +}) + +const OptionViewAlbum = React.memo<{ + navigation: NavigationProp + album?: string + albumId?: string +}>(({ navigation, album, albumId }) => { + if (!album || !albumId) { + return <> + } + + return ( + navigation.navigate('album', { id: albumId, title: album })} + /> + ) +}) + +const OptionDownload = React.memo<{ + itemType: string +}>(({ itemType }) => ( + +)) + export type AlbumContextPressableProps = ContextMenuProps & { album: AlbumListItem } -export const AlbumContextPressable: React.FC = ({ - menuStyle, - triggerWrapperStyle, - triggerOuterWrapperStyle, - triggerTouchableStyle, - onPress, - album, - children, -}) => { +export const AlbumContextPressable: React.FC = props => { const navigation = useNavigation() + const { album, children } = props return ( - - - - {album.name} - - {album.artist ? ( - - {album.artist} - - ) : ( - <> - )} - - - } + {...props} + menuHeader={} menuOptions={ <> - - navigation.navigate('artist', { id: album.artistId, title: album.artist })} - /> - + + + + + }> + {children} + + ) +} + +export type SongContextPressableProps = ContextMenuProps & { + song: Song +} + +export const SongContextPressable: React.FC = props => { + const navigation = useNavigation() + const { song, children } = props + + return ( + } + menuOptions={ + <> + + + + }> {children} @@ -190,7 +259,7 @@ const styles = StyleSheet.create({ color: colors.text.secondary, }, option: { - paddingVertical: 10, + paddingVertical: 8, paddingHorizontal: 20, flexDirection: 'row', alignItems: 'center', diff --git a/app/components/ListItem.tsx b/app/components/ListItem.tsx index a3ad1ba..874f6b1 100644 --- a/app/components/ListItem.tsx +++ b/app/components/ListItem.tsx @@ -1,4 +1,4 @@ -import { AlbumListItem, ListableItem } from '@app/models/music' +import { AlbumListItem, ListableItem, Song } from '@app/models/music' import { useStore } from '@app/state/store' import { selectTrackPlayer } from '@app/state/trackplayer' import colors from '@app/styles/colors' @@ -10,7 +10,7 @@ import FastImage from 'react-native-fast-image' import IconFA from 'react-native-vector-icons/FontAwesome' import IconFA5 from 'react-native-vector-icons/FontAwesome5' import IconMat from 'react-native-vector-icons/MaterialIcons' -import { AlbumContextPressable } from './ContextMenu' +import { AlbumContextPressable, SongContextPressable } from './ContextMenu' import CoverArt from './CoverArt' import PressableOpacity from './PressableOpacity' @@ -98,10 +98,20 @@ const ListItem: React.FC<{ ), [item, onPress], ) + const songPressable = useCallback( + ({ children }) => ( + + {children} + + ), + [item, onPress], + ) let PressableComponent = itemPressable if (item.itemType === 'album') { PressableComponent = albumPressable + } else if (item.itemType === 'song') { + PressableComponent = songPressable } return ( diff --git a/app/models/music.ts b/app/models/music.ts index b69c89e..e16e43b 100644 --- a/app/models/music.ts +++ b/app/models/music.ts @@ -69,7 +69,9 @@ export interface Song { itemType: 'song' id: string album?: string + albumId?: string artist?: string + artistId?: string title: string track?: number duration?: number @@ -168,7 +170,9 @@ export function mapChildToSong(child: ChildElement, client: SubsonicApiClient): itemType: 'song', id: child.id, album: child.album, + albumId: child.albumId, artist: child.artist, + artistId: child.artistId, title: child.title, track: child.track, duration: child.duration,