import PressableOpacity from '@app/components/PressableOpacity' import { useStarred } from '@app/hooks/music' import { AlbumListItem, Artist, Song, StarrableItemType } from '@app/models/music' import { selectMusic } from '@app/state/music' import { useStore } from '@app/state/store' import colors from '@app/styles/colors' import font from '@app/styles/font' 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 { 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' import Star from './Star' const { SlideInMenu } = renderers type ContextMenuProps = { menuStyle?: StyleProp triggerWrapperStyle?: StyleProp triggerOuterWrapperStyle?: StyleProp triggerTouchableStyle?: StyleProp onPress?: () => any triggerOnLongPress?: boolean } type InternalContextMenuProps = ContextMenuProps & { menuHeader: React.ReactNode menuOptions: React.ReactNode } const ContextMenu: React.FC = ({ menuStyle, triggerWrapperStyle, triggerOuterWrapperStyle, triggerTouchableStyle, onPress, menuHeader, menuOptions, children, triggerOnLongPress, }) => { menuStyle = menuStyle || { flex: 1 } triggerWrapperStyle = triggerWrapperStyle || { flex: 1 } triggerOuterWrapperStyle = triggerOuterWrapperStyle || { flex: 1 } triggerTouchableStyle = triggerTouchableStyle || { flex: 1 } return ( {children} ( {menuHeader} {options} )}> {menuOptions} ) } type ContextMenuOptionProps = { onSelect?: () => any } const ContextMenuOption: React.FC = ({ onSelect, children }) => ( {children} ) type ContextMenuIconTextOptionProps = ContextMenuOptionProps & { IconComponent?: ReactComponentLike IconComponentRaw?: React.ReactNode name?: string size?: number color?: string text: string } const ContextMenuIconTextOption = React.memo( ({ onSelect, IconComponent, IconComponentRaw, name, color, size, text }) => { let Icon: React.ReactNode if (IconComponentRaw) { Icon = IconComponentRaw } else if (IconComponent) { Icon = } else { Icon = <> } return ( {Icon} {text} ) }, ) const MenuHeader = React.memo<{ coverArt?: string artistId?: string title: string subtitle?: string }>(({ coverArt, artistId, title, subtitle }) => ( {artistId ? ( ) : ( )} {title} {subtitle ? ( {subtitle} ) : ( <> )} )) const OptionStar = React.memo<{ id: string type: StarrableItemType additionalText?: string }>(({ id, type, additionalText: text }) => { const starred = useStarred(id, type) const setStarred = useStore(selectMusic.starItem) return ( } text={(starred ? 'Unstar' : 'Star') + (text ? ` ${text}` : '')} onSelect={() => setStarred(id, type, starred)} /> ) }) 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 = props => { const navigation = useNavigation() const { album, children } = props return ( } menuOptions={ <> {/* */} }> {children} ) } export type SongContextPressableProps = ContextMenuProps & { song: Song } export const SongContextPressable: React.FC = props => { const navigation = useNavigation() const { song, children } = props return ( } menuOptions={ <> {/* */} }> {children} ) } export type ArtistContextPressableProps = ContextMenuProps & { artist: Artist } export const ArtistContextPressable: React.FC = props => { const { artist, children } = props return ( } menuOptions={ <> {/* */} }> {children} ) } export type NowPlayingContextPressableProps = ContextMenuProps & { song: Song } export const NowPlayingContextPressable: React.FC = props => { const navigation = useNavigation() const { song, children } = props return ( } menuOptions={ <> }> {children} ) } const styles = StyleSheet.create({ optionsContainer: { backgroundColor: 'rgba(45, 45, 45, 0.95)', maxHeight: 365, }, optionsWrapper: { // marginBottom: 10, }, menuHeader: { paddingTop: 14, paddingBottom: 10, paddingHorizontal: 20, flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, coverArt: { width: 42, height: 42, }, menuHeaderText: { flex: 1, marginLeft: 10, }, menuTitle: { fontFamily: font.semiBold, fontSize: 16, color: colors.text.primary, }, menuSubtitle: { fontFamily: font.regular, fontSize: 14, color: colors.text.secondary, }, option: { paddingVertical: 8, paddingHorizontal: 20, flexDirection: 'row', alignItems: 'center', }, icon: { marginRight: 10, width: 32, height: 32, justifyContent: 'center', alignItems: 'center', // backgroundColor: 'red', }, optionText: { fontFamily: font.semiBold, fontSize: 16, color: colors.text.primary, // backgroundColor: 'green', }, })