impl starring everywhere

This commit is contained in:
austinried
2021-08-10 09:42:20 +09:00
parent 0a3d542156
commit 075286e939
6 changed files with 121 additions and 62 deletions

View File

@@ -1,5 +1,8 @@
import PressableOpacity from '@app/components/PressableOpacity'
import { useStarred } from '@app/hooks/music'
import { AlbumListItem, Artist, Song } 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'
@@ -12,6 +15,7 @@ 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
@@ -20,7 +24,7 @@ type ContextMenuProps = {
triggerWrapperStyle?: StyleProp<ViewStyle>
triggerOuterWrapperStyle?: StyleProp<ViewStyle>
triggerTouchableStyle?: StyleProp<ViewStyle>
onPress?: () => void
onPress?: () => any
}
type InternalContextMenuProps = ContextMenuProps & {
@@ -70,7 +74,7 @@ const ContextMenu: React.FC<InternalContextMenuProps> = ({
}
type ContextMenuOptionProps = {
onSelect?: () => void
onSelect?: () => any
}
const ContextMenuOption: React.FC<ContextMenuOptionProps> = ({ onSelect, children }) => (
@@ -80,22 +84,31 @@ const ContextMenuOption: React.FC<ContextMenuOptionProps> = ({ onSelect, childre
)
type ContextMenuIconTextOptionProps = ContextMenuOptionProps & {
IconComponent: ReactComponentLike
name: string
size: number
IconComponent?: ReactComponentLike
IconComponentRaw?: React.ReactNode
name?: string
size?: number
color?: string
text: string
}
const ContextMenuIconTextOption = React.memo<ContextMenuIconTextOptionProps>(
({ onSelect, IconComponent, name, color, size, text }) => (
<ContextMenuOption onSelect={onSelect}>
<View style={styles.icon}>
<IconComponent name={name} size={size} color={color || colors.text.primary} />
</View>
<Text style={styles.optionText}>{text}</Text>
</ContextMenuOption>
),
({ onSelect, IconComponent, IconComponentRaw, name, color, size, text }) => {
let Icon: React.ReactNode
if (IconComponentRaw) {
Icon = IconComponentRaw
} else if (IconComponent) {
Icon = <IconComponent name={name} size={size} color={color || colors.text.primary} />
} else {
Icon = <></>
}
return (
<ContextMenuOption onSelect={onSelect}>
<View style={styles.icon}>{Icon}</View>
<Text style={styles.optionText}>{text}</Text>
</ContextMenuOption>
)
},
)
const MenuHeader = React.memo<{
@@ -121,9 +134,21 @@ const MenuHeader = React.memo<{
</View>
))
const OptionStar = React.memo(() => (
<ContextMenuIconTextOption IconComponent={IconFA} name="star-o" size={26} text="Star" />
))
const OptionStar = React.memo<{
id: string
type: string
}>(({ id, type }) => {
const starred = useStarred(id, type)
const setStarred = useStore(selectMusic.starItem)
return (
<ContextMenuIconTextOption
IconComponentRaw={<Star starred={starred} size={26} />}
text={starred ? 'Unstar' : 'Star'}
onSelect={() => setStarred(id, type, starred)}
/>
)
})
const OptionViewArtist = React.memo<{
navigation: NavigationProp<any>
@@ -185,7 +210,7 @@ export const AlbumContextPressable: React.FC<AlbumContextPressableProps> = props
menuHeader={<MenuHeader title={album.name} subtitle={album.artist} coverArt={album.coverArt} />}
menuOptions={
<>
<OptionStar />
<OptionStar id={album.id} type={album.itemType} />
<OptionViewArtist artist={album.artist} artistId={album.artistId} navigation={navigation} />
<OptionDownload itemType={album.itemType} />
</>
@@ -209,7 +234,7 @@ export const SongContextPressable: React.FC<SongContextPressableProps> = props =
menuHeader={<MenuHeader title={song.title} subtitle={song.artist} coverArt={song.coverArt} />}
menuOptions={
<>
<OptionStar />
<OptionStar id={song.id} type={song.itemType} />
<OptionViewArtist artist={song.artist} artistId={song.artistId} navigation={navigation} />
<OptionViewAlbum album={song.album} albumId={song.albumId} navigation={navigation} />
<OptionDownload itemType={song.itemType} />
@@ -233,7 +258,7 @@ export const ArtistContextPressable: React.FC<ArtistContextPressableProps> = pro
menuHeader={<MenuHeader title={artist.name} artistId={artist.id} />}
menuOptions={
<>
<OptionStar />
<OptionStar id={artist.id} type={artist.itemType} />
<OptionDownload itemType={artist.itemType} />
</>
}>

View File

@@ -9,12 +9,12 @@ import { useNavigation } from '@react-navigation/native'
import React, { useCallback } from 'react'
import { StyleSheet, Text, View } from 'react-native'
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, ArtistContextPressable, SongContextPressable } from './ContextMenu'
import CoverArt from './CoverArt'
import PressableOpacity from './PressableOpacity'
import Star from './Star'
const TitleTextSong = React.memo<{
id: string
@@ -171,11 +171,7 @@ const ListItem: React.FC<{
<View style={styles.controls}>
{showStar ? (
<PressableOpacity onPress={toggleStarred} style={styles.controlItem}>
{starred ? (
<IconFA name="star" size={26} color={colors.accent} />
) : (
<IconFA name="star-o" size={26} color={colors.text.secondary} />
)}
<Star size={26} starred={starred} />
</PressableOpacity>
) : (
<></>

14
app/components/Star.tsx Normal file
View File

@@ -0,0 +1,14 @@
import colors from '@app/styles/colors'
import React from 'react'
import IconFA from 'react-native-vector-icons/FontAwesome'
const Star = React.memo<{
starred: boolean
size: number
}>(({ starred, size }) => {
return (
<IconFA name={starred ? 'star' : 'star-o'} color={starred ? colors.accent : colors.text.secondary} size={size} />
)
})
export default Star