mirror of
https://github.com/austinried/subtracks.git
synced 2026-02-10 15:02:42 +01:00
impl starring everywhere
This commit is contained in:
@@ -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} />
|
||||
</>
|
||||
}>
|
||||
|
||||
@@ -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
14
app/components/Star.tsx
Normal 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
|
||||
Reference in New Issue
Block a user