mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-29 17:39:27 +01:00
impl starring everywhere
This commit is contained in:
parent
0a3d542156
commit
075286e939
@ -1,5 +1,8 @@
|
|||||||
import PressableOpacity from '@app/components/PressableOpacity'
|
import PressableOpacity from '@app/components/PressableOpacity'
|
||||||
|
import { useStarred } from '@app/hooks/music'
|
||||||
import { AlbumListItem, Artist, Song } from '@app/models/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 colors from '@app/styles/colors'
|
||||||
import font from '@app/styles/font'
|
import font from '@app/styles/font'
|
||||||
import { NavigationProp, useNavigation } from '@react-navigation/native'
|
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 IconFA5 from 'react-native-vector-icons/FontAwesome5'
|
||||||
import IconMat from 'react-native-vector-icons/MaterialIcons'
|
import IconMat from 'react-native-vector-icons/MaterialIcons'
|
||||||
import CoverArt from './CoverArt'
|
import CoverArt from './CoverArt'
|
||||||
|
import Star from './Star'
|
||||||
|
|
||||||
const { SlideInMenu } = renderers
|
const { SlideInMenu } = renderers
|
||||||
|
|
||||||
@ -20,7 +24,7 @@ type ContextMenuProps = {
|
|||||||
triggerWrapperStyle?: StyleProp<ViewStyle>
|
triggerWrapperStyle?: StyleProp<ViewStyle>
|
||||||
triggerOuterWrapperStyle?: StyleProp<ViewStyle>
|
triggerOuterWrapperStyle?: StyleProp<ViewStyle>
|
||||||
triggerTouchableStyle?: StyleProp<ViewStyle>
|
triggerTouchableStyle?: StyleProp<ViewStyle>
|
||||||
onPress?: () => void
|
onPress?: () => any
|
||||||
}
|
}
|
||||||
|
|
||||||
type InternalContextMenuProps = ContextMenuProps & {
|
type InternalContextMenuProps = ContextMenuProps & {
|
||||||
@ -70,7 +74,7 @@ const ContextMenu: React.FC<InternalContextMenuProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ContextMenuOptionProps = {
|
type ContextMenuOptionProps = {
|
||||||
onSelect?: () => void
|
onSelect?: () => any
|
||||||
}
|
}
|
||||||
|
|
||||||
const ContextMenuOption: React.FC<ContextMenuOptionProps> = ({ onSelect, children }) => (
|
const ContextMenuOption: React.FC<ContextMenuOptionProps> = ({ onSelect, children }) => (
|
||||||
@ -80,22 +84,31 @@ const ContextMenuOption: React.FC<ContextMenuOptionProps> = ({ onSelect, childre
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ContextMenuIconTextOptionProps = ContextMenuOptionProps & {
|
type ContextMenuIconTextOptionProps = ContextMenuOptionProps & {
|
||||||
IconComponent: ReactComponentLike
|
IconComponent?: ReactComponentLike
|
||||||
name: string
|
IconComponentRaw?: React.ReactNode
|
||||||
size: number
|
name?: string
|
||||||
|
size?: number
|
||||||
color?: string
|
color?: string
|
||||||
text: string
|
text: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const ContextMenuIconTextOption = React.memo<ContextMenuIconTextOptionProps>(
|
const ContextMenuIconTextOption = React.memo<ContextMenuIconTextOptionProps>(
|
||||||
({ onSelect, IconComponent, name, color, size, text }) => (
|
({ 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}>
|
<ContextMenuOption onSelect={onSelect}>
|
||||||
<View style={styles.icon}>
|
<View style={styles.icon}>{Icon}</View>
|
||||||
<IconComponent name={name} size={size} color={color || colors.text.primary} />
|
|
||||||
</View>
|
|
||||||
<Text style={styles.optionText}>{text}</Text>
|
<Text style={styles.optionText}>{text}</Text>
|
||||||
</ContextMenuOption>
|
</ContextMenuOption>
|
||||||
),
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const MenuHeader = React.memo<{
|
const MenuHeader = React.memo<{
|
||||||
@ -121,9 +134,21 @@ const MenuHeader = React.memo<{
|
|||||||
</View>
|
</View>
|
||||||
))
|
))
|
||||||
|
|
||||||
const OptionStar = React.memo(() => (
|
const OptionStar = React.memo<{
|
||||||
<ContextMenuIconTextOption IconComponent={IconFA} name="star-o" size={26} text="Star" />
|
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<{
|
const OptionViewArtist = React.memo<{
|
||||||
navigation: NavigationProp<any>
|
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} />}
|
menuHeader={<MenuHeader title={album.name} subtitle={album.artist} coverArt={album.coverArt} />}
|
||||||
menuOptions={
|
menuOptions={
|
||||||
<>
|
<>
|
||||||
<OptionStar />
|
<OptionStar id={album.id} type={album.itemType} />
|
||||||
<OptionViewArtist artist={album.artist} artistId={album.artistId} navigation={navigation} />
|
<OptionViewArtist artist={album.artist} artistId={album.artistId} navigation={navigation} />
|
||||||
<OptionDownload itemType={album.itemType} />
|
<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} />}
|
menuHeader={<MenuHeader title={song.title} subtitle={song.artist} coverArt={song.coverArt} />}
|
||||||
menuOptions={
|
menuOptions={
|
||||||
<>
|
<>
|
||||||
<OptionStar />
|
<OptionStar id={song.id} type={song.itemType} />
|
||||||
<OptionViewArtist artist={song.artist} artistId={song.artistId} navigation={navigation} />
|
<OptionViewArtist artist={song.artist} artistId={song.artistId} navigation={navigation} />
|
||||||
<OptionViewAlbum album={song.album} albumId={song.albumId} navigation={navigation} />
|
<OptionViewAlbum album={song.album} albumId={song.albumId} navigation={navigation} />
|
||||||
<OptionDownload itemType={song.itemType} />
|
<OptionDownload itemType={song.itemType} />
|
||||||
@ -233,7 +258,7 @@ export const ArtistContextPressable: React.FC<ArtistContextPressableProps> = pro
|
|||||||
menuHeader={<MenuHeader title={artist.name} artistId={artist.id} />}
|
menuHeader={<MenuHeader title={artist.name} artistId={artist.id} />}
|
||||||
menuOptions={
|
menuOptions={
|
||||||
<>
|
<>
|
||||||
<OptionStar />
|
<OptionStar id={artist.id} type={artist.itemType} />
|
||||||
<OptionDownload itemType={artist.itemType} />
|
<OptionDownload itemType={artist.itemType} />
|
||||||
</>
|
</>
|
||||||
}>
|
}>
|
||||||
|
|||||||
@ -9,12 +9,12 @@ import { useNavigation } from '@react-navigation/native'
|
|||||||
import React, { useCallback } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
import { StyleSheet, Text, View } from 'react-native'
|
import { StyleSheet, Text, View } from 'react-native'
|
||||||
import FastImage from 'react-native-fast-image'
|
import FastImage from 'react-native-fast-image'
|
||||||
import IconFA from 'react-native-vector-icons/FontAwesome'
|
|
||||||
import IconFA5 from 'react-native-vector-icons/FontAwesome5'
|
import IconFA5 from 'react-native-vector-icons/FontAwesome5'
|
||||||
import IconMat from 'react-native-vector-icons/MaterialIcons'
|
import IconMat from 'react-native-vector-icons/MaterialIcons'
|
||||||
import { AlbumContextPressable, ArtistContextPressable, SongContextPressable } from './ContextMenu'
|
import { AlbumContextPressable, ArtistContextPressable, SongContextPressable } from './ContextMenu'
|
||||||
import CoverArt from './CoverArt'
|
import CoverArt from './CoverArt'
|
||||||
import PressableOpacity from './PressableOpacity'
|
import PressableOpacity from './PressableOpacity'
|
||||||
|
import Star from './Star'
|
||||||
|
|
||||||
const TitleTextSong = React.memo<{
|
const TitleTextSong = React.memo<{
|
||||||
id: string
|
id: string
|
||||||
@ -171,11 +171,7 @@ const ListItem: React.FC<{
|
|||||||
<View style={styles.controls}>
|
<View style={styles.controls}>
|
||||||
{showStar ? (
|
{showStar ? (
|
||||||
<PressableOpacity onPress={toggleStarred} style={styles.controlItem}>
|
<PressableOpacity onPress={toggleStarred} style={styles.controlItem}>
|
||||||
{starred ? (
|
<Star size={26} starred={starred} />
|
||||||
<IconFA name="star" size={26} color={colors.accent} />
|
|
||||||
) : (
|
|
||||||
<IconFA name="star-o" size={26} color={colors.text.secondary} />
|
|
||||||
)}
|
|
||||||
</PressableOpacity>
|
</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
|
||||||
@ -39,18 +39,23 @@ export const usePlaylistWithSongs = (id: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useStarred = (id: string, type: string) => {
|
export const useStarred = (id: string, type: string) => {
|
||||||
const starred = useStore(
|
return useStore(
|
||||||
useCallback(
|
useCallback(
|
||||||
(state: Store) => {
|
(state: Store) => {
|
||||||
if (!(type in state.starred)) {
|
switch (type) {
|
||||||
|
case 'song':
|
||||||
|
return state.starredSongs[id]
|
||||||
|
case 'album':
|
||||||
|
return state.starredAlbums[id]
|
||||||
|
case 'artist':
|
||||||
|
return state.starredArtists[id]
|
||||||
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return !!state.starred[type][id]
|
|
||||||
},
|
},
|
||||||
[type, id],
|
[type, id],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
return starred
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCoverArtUri = () => {
|
export const useCoverArtUri = () => {
|
||||||
|
|||||||
@ -18,6 +18,9 @@ import { useFocusEffect } from '@react-navigation/native'
|
|||||||
import { useStore } from '@app/state/store'
|
import { useStore } from '@app/state/store'
|
||||||
import { selectTrackPlayer } from '@app/state/trackplayer'
|
import { selectTrackPlayer } from '@app/state/trackplayer'
|
||||||
import { useNext, usePause, usePlay, usePrevious, useToggleRepeat, useToggleShuffle } from '@app/hooks/trackplayer'
|
import { useNext, usePause, usePlay, usePrevious, useToggleRepeat, useToggleShuffle } from '@app/hooks/trackplayer'
|
||||||
|
import Star from '@app/components/Star'
|
||||||
|
import { useStarred } from '@app/hooks/music'
|
||||||
|
import { selectMusic } from '@app/state/music'
|
||||||
|
|
||||||
const NowPlayingHeader = React.memo<{
|
const NowPlayingHeader = React.memo<{
|
||||||
backHandler: () => void
|
backHandler: () => void
|
||||||
@ -85,6 +88,10 @@ const coverArtStyles = StyleSheet.create({
|
|||||||
|
|
||||||
const SongInfo = () => {
|
const SongInfo = () => {
|
||||||
const track = useStore(selectTrackPlayer.currentTrack)
|
const track = useStore(selectTrackPlayer.currentTrack)
|
||||||
|
const id = track?.id || '-1'
|
||||||
|
const type = 'song'
|
||||||
|
const starred = useStarred(id, type)
|
||||||
|
const setStarred = useStore(selectMusic.starItem)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={infoStyles.container}>
|
<View style={infoStyles.container}>
|
||||||
@ -97,8 +104,8 @@ const SongInfo = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={infoStyles.controls}>
|
<View style={infoStyles.controls}>
|
||||||
<PressableOpacity onPress={undefined}>
|
<PressableOpacity onPress={() => setStarred(id, type, starred)}>
|
||||||
<IconFA name="star-o" size={32} color={colors.text.secondary} />
|
<Star size={32} starred={starred} />
|
||||||
</PressableOpacity>
|
</PressableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@ -58,7 +58,9 @@ export type MusicSlice = {
|
|||||||
fetchHomeLists: () => Promise<void>
|
fetchHomeLists: () => Promise<void>
|
||||||
clearHomeLists: () => void
|
clearHomeLists: () => void
|
||||||
|
|
||||||
starred: { [type: string]: { [id: string]: boolean } }
|
starredSongs: { [id: string]: boolean }
|
||||||
|
starredAlbums: { [id: string]: boolean }
|
||||||
|
starredArtists: { [id: string]: boolean }
|
||||||
starItem: (id: string, type: string, unstar?: boolean) => Promise<void>
|
starItem: (id: string, type: string, unstar?: boolean) => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +96,7 @@ export const selectMusic = {
|
|||||||
|
|
||||||
function reduceStarred(
|
function reduceStarred(
|
||||||
starredType: { [id: string]: boolean },
|
starredType: { [id: string]: boolean },
|
||||||
items: { id: string; starred?: Date }[],
|
items: { id: string; starred?: Date | boolean }[],
|
||||||
): { [id: string]: boolean } {
|
): { [id: string]: boolean } {
|
||||||
return {
|
return {
|
||||||
...starredType,
|
...starredType,
|
||||||
@ -130,9 +132,9 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
set(
|
set(
|
||||||
produce<MusicSlice>(state => {
|
produce<MusicSlice>(state => {
|
||||||
state.artistInfo[id] = artistInfo
|
state.artistInfo[id] = artistInfo
|
||||||
state.starred.song = reduceStarred(state.starred.song, artistInfo.topSongs)
|
state.starredSongs = reduceStarred(state.starredSongs, artistInfo.topSongs)
|
||||||
state.starred.artist = reduceStarred(state.starred.artist, [artistInfo])
|
state.starredArtists = reduceStarred(state.starredArtists, [artistInfo])
|
||||||
state.starred.album = reduceStarred(state.starred.album, artistInfo.albums)
|
state.starredAlbums = reduceStarred(state.starredAlbums, artistInfo.albums)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
return artistInfo
|
return artistInfo
|
||||||
@ -156,8 +158,8 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
set(
|
set(
|
||||||
produce<MusicSlice>(state => {
|
produce<MusicSlice>(state => {
|
||||||
state.albumsWithSongs[id] = album
|
state.albumsWithSongs[id] = album
|
||||||
state.starred.song = reduceStarred(state.starred.song, album.songs)
|
state.starredSongs = reduceStarred(state.starredSongs, album.songs)
|
||||||
state.starred.album = reduceStarred(state.starred.album, [album])
|
state.starredAlbums = reduceStarred(state.starredAlbums, [album])
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
return album
|
return album
|
||||||
@ -181,7 +183,7 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
set(
|
set(
|
||||||
produce<MusicSlice>(state => {
|
produce<MusicSlice>(state => {
|
||||||
state.playlistsWithSongs[id] = playlist
|
state.playlistsWithSongs[id] = playlist
|
||||||
state.starred.song = reduceStarred(state.starred.song, playlist.songs)
|
state.starredSongs = reduceStarred(state.starredSongs, playlist.songs)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
return playlist
|
return playlist
|
||||||
@ -209,7 +211,7 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
set(
|
set(
|
||||||
produce<MusicSlice>(state => {
|
produce<MusicSlice>(state => {
|
||||||
state.artists = response.data.artists.map(mapArtistID3toArtist)
|
state.artists = response.data.artists.map(mapArtistID3toArtist)
|
||||||
state.starred.artist = reduceStarred(state.starred.artist, state.artists)
|
state.starredArtists = reduceStarred(state.starredArtists, state.artists)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
@ -258,7 +260,7 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
set(
|
set(
|
||||||
produce<MusicSlice>(state => {
|
produce<MusicSlice>(state => {
|
||||||
state.albums = response.data.albums.map(mapAlbumID3toAlbumListItem)
|
state.albums = response.data.albums.map(mapAlbumID3toAlbumListItem)
|
||||||
state.starred.albums = reduceStarred(state.starred.albums, state.albums)
|
state.starredAlbums = reduceStarred(state.starredAlbums, state.albums)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
@ -298,9 +300,9 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
albums: response.data.albums.map(mapAlbumID3toAlbumListItem),
|
albums: response.data.albums.map(mapAlbumID3toAlbumListItem),
|
||||||
songs: response.data.songs.map(a => mapChildToSong(a, client)),
|
songs: response.data.songs.map(a => mapChildToSong(a, client)),
|
||||||
}
|
}
|
||||||
state.starred.song = reduceStarred(state.starred.song, state.searchResults.songs)
|
state.starredSongs = reduceStarred(state.starredSongs, state.searchResults.songs)
|
||||||
state.starred.artist = reduceStarred(state.starred.artist, state.searchResults.artists)
|
state.starredArtists = reduceStarred(state.starredArtists, state.searchResults.artists)
|
||||||
state.starred.album = reduceStarred(state.starred.album, state.searchResults.albums)
|
state.starredAlbums = reduceStarred(state.starredAlbums, state.searchResults.albums)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
@ -341,7 +343,7 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
set(
|
set(
|
||||||
produce<MusicSlice>(state => {
|
produce<MusicSlice>(state => {
|
||||||
state.homeLists[type] = response.data.albums.map(mapAlbumID3toAlbumListItem)
|
state.homeLists[type] = response.data.albums.map(mapAlbumID3toAlbumListItem)
|
||||||
state.starred.album = reduceStarred(state.starred.album, state.homeLists[type])
|
state.starredAlbums = reduceStarred(state.starredAlbums, state.homeLists[type])
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
@ -357,11 +359,9 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
set({ homeLists: {} })
|
set({ homeLists: {} })
|
||||||
},
|
},
|
||||||
|
|
||||||
starred: {
|
starredSongs: {},
|
||||||
song: {},
|
starredAlbums: {},
|
||||||
album: {},
|
starredArtists: {},
|
||||||
artist: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
starItem: async (id, type, unstar = false) => {
|
starItem: async (id, type, unstar = false) => {
|
||||||
const client = get().client
|
const client = get().client
|
||||||
@ -370,31 +370,43 @@ export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): Mu
|
|||||||
}
|
}
|
||||||
|
|
||||||
let params: StarParams
|
let params: StarParams
|
||||||
|
let setStarred: (starred: boolean) => void
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'song':
|
case 'song':
|
||||||
params = { id }
|
params = { id }
|
||||||
|
setStarred = starred => {
|
||||||
|
set(
|
||||||
|
produce<MusicSlice>(state => {
|
||||||
|
state.starredSongs = reduceStarred(state.starredSongs, [{ id, starred }])
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'album':
|
case 'album':
|
||||||
params = { albumId: id }
|
params = { albumId: id }
|
||||||
|
setStarred = starred => {
|
||||||
|
set(
|
||||||
|
produce<MusicSlice>(state => {
|
||||||
|
state.starredAlbums = reduceStarred(state.starredAlbums, [{ id, starred }])
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'artist':
|
case 'artist':
|
||||||
params = { artistId: id }
|
params = { artistId: id }
|
||||||
|
setStarred = starred => {
|
||||||
|
set(
|
||||||
|
produce<MusicSlice>(state => {
|
||||||
|
state.starredArtists = reduceStarred(state.starredArtists, [{ id, starred }])
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const setStarred = (starred: boolean) => {
|
|
||||||
set(
|
|
||||||
produce<MusicSlice>(state => {
|
|
||||||
state.starred[type] = {
|
|
||||||
...state.starred[type],
|
|
||||||
[id]: starred,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setStarred(!unstar)
|
setStarred(!unstar)
|
||||||
if (unstar) {
|
if (unstar) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user