added nothing here message for empty lists

This commit is contained in:
austinried 2021-07-19 22:23:33 +09:00
parent 9d835f04aa
commit a1b6aa6732
6 changed files with 113 additions and 46 deletions

View File

@ -0,0 +1,33 @@
import font from '@app/styles/font'
import React from 'react'
import { Text, View, StyleSheet } from 'react-native'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
const NothingHere = React.memo<{
height?: number
width?: number
}>(({ height, width }) => {
height = height || 200
width = width || 200
return (
<View style={[styles.container, { height, width }]}>
<Icon name="music-note-outline" color={styles.text.color} size={width / 2} />
<Text style={[styles.text, { fontSize: width / 8 }]}>Nothing here...</Text>
</View>
)
})
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
opacity: 0.25,
},
text: {
fontFamily: font.lightItalic,
color: 'white',
},
})
export default NothingHere

View File

@ -6,7 +6,6 @@ import { useAtomValue } from 'jotai/utils'
import React from 'react' import React from 'react'
import { GestureResponderEvent, StyleSheet, Text, View } from 'react-native' import { GestureResponderEvent, StyleSheet, Text, View } from 'react-native'
import IconFA from 'react-native-vector-icons/FontAwesome' import IconFA from 'react-native-vector-icons/FontAwesome'
import IconMat from 'react-native-vector-icons/MaterialIcons'
import CoverArt from './CoverArt' import CoverArt from './CoverArt'
import PressableOpacity from './PressableOpacity' import PressableOpacity from './PressableOpacity'
@ -33,10 +32,7 @@ const SongItem: React.FC<{
</PressableOpacity> </PressableOpacity>
<View style={styles.controls}> <View style={styles.controls}>
<PressableOpacity onPress={undefined}> <PressableOpacity onPress={undefined}>
<IconFA name="star-o" size={26} color={colors.text.primary} /> <IconFA name="star-o" size={26} color={colors.text.secondary} />
</PressableOpacity>
<PressableOpacity onPress={undefined} style={styles.more}>
<IconMat name="more-vert" size={32} color="white" />
</PressableOpacity> </PressableOpacity>
</View> </View>
</View> </View>
@ -76,7 +72,7 @@ const styles = StyleSheet.create({
controls: { controls: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
marginLeft: 10, marginLeft: 16,
}, },
more: { more: {
marginLeft: 8, marginLeft: 8,

View File

@ -2,6 +2,7 @@ import Button from '@app/components/Button'
import CoverArt from '@app/components/CoverArt' import CoverArt from '@app/components/CoverArt'
import GradientBackground from '@app/components/GradientBackground' import GradientBackground from '@app/components/GradientBackground'
import ImageGradientScrollView from '@app/components/ImageGradientScrollView' import ImageGradientScrollView from '@app/components/ImageGradientScrollView'
import NothingHere from '@app/components/NothingHere'
import SongItem from '@app/components/SongItem' import SongItem from '@app/components/SongItem'
import { albumAtomFamily } from '@app/state/music' import { albumAtomFamily } from '@app/state/music'
import { useSetQueue } from '@app/state/trackplayer' import { useSetQueue } from '@app/state/trackplayer'
@ -22,18 +23,8 @@ const AlbumDetails: React.FC<{
return <></> return <></>
} }
return ( const Songs = () => (
<ImageGradientScrollView <>
imageUri={album.coverArtThumbUri}
imageKey={`${album.name}${album.artist}`}
style={styles.container}>
<View style={styles.content}>
<CoverArt coverArtUri={album.coverArtUri} style={styles.cover} />
<Text style={styles.title}>{album.name}</Text>
<Text style={styles.subtitle}>
{album.artist}
{album.year ? `${album.year}` : ''}
</Text>
<View style={styles.controls}> <View style={styles.controls}>
<Button title="Play Album" onPress={() => setQueue(album.songs, album.name, album.songs[0].id)} /> <Button title="Play Album" onPress={() => setQueue(album.songs, album.name, album.songs[0].id)} />
</View> </View>
@ -50,6 +41,22 @@ const AlbumDetails: React.FC<{
<SongItem key={s.id} song={s} onPress={() => setQueue(album.songs, album.name, s.id)} /> <SongItem key={s.id} song={s} onPress={() => setQueue(album.songs, album.name, s.id)} />
))} ))}
</View> </View>
</>
)
return (
<ImageGradientScrollView
imageUri={album.coverArtThumbUri}
imageKey={`${album.name}${album.artist}`}
style={styles.container}>
<View style={styles.content}>
<CoverArt coverArtUri={album.coverArtUri} style={styles.cover} />
<Text style={styles.title}>{album.name}</Text>
<Text style={styles.subtitle}>
{album.artist}
{album.year ? `${album.year}` : ''}
</Text>
{album.songs.length > 0 ? <Songs /> : <NothingHere height={300} width={250} />}
</View> </View>
</ImageGradientScrollView> </ImageGradientScrollView>
) )

View File

@ -1,5 +1,6 @@
import CoverArt from '@app/components/CoverArt' import CoverArt from '@app/components/CoverArt'
import GradientScrollView from '@app/components/GradientScrollView' import GradientScrollView from '@app/components/GradientScrollView'
import NothingHere from '@app/components/NothingHere'
import PressableOpacity from '@app/components/PressableOpacity' import PressableOpacity from '@app/components/PressableOpacity'
import { AlbumListItem } from '@app/models/music' import { AlbumListItem } from '@app/models/music'
import { homeListsAtom, homeListsUpdatingAtom, useUpdateHomeLists } from '@app/state/music' import { homeListsAtom, homeListsUpdatingAtom, useUpdateHomeLists } from '@app/state/music'
@ -44,9 +45,7 @@ const Category = React.memo<{
name?: string name?: string
data: AlbumListItem[] data: AlbumListItem[]
}>(({ name, data }) => { }>(({ name, data }) => {
return ( const Albums = () => (
<View style={styles.category}>
<Text style={styles.categoryHeader}>{name}</Text>
<ScrollView <ScrollView
horizontal={true} horizontal={true}
showsHorizontalScrollIndicator={false} showsHorizontalScrollIndicator={false}
@ -57,6 +56,18 @@ const Category = React.memo<{
<AlbumItem key={album.id} album={album} /> <AlbumItem key={album.id} album={album} />
))} ))}
</ScrollView> </ScrollView>
)
const Nothing = () => (
<View style={styles.nothingHereContent}>
<NothingHere height={styles.nothingHereContent.height} />
</View>
)
return (
<View style={styles.category}>
<Text style={styles.categoryHeader}>{name}</Text>
{data.length > 0 ? <Albums /> : <Nothing />}
</View> </View>
) )
}) })
@ -110,6 +121,12 @@ const styles = StyleSheet.create({
paddingHorizontal: 20, paddingHorizontal: 20,
marginTop: 4, marginTop: 4,
}, },
nothingHereContent: {
width: '100%',
height: 190,
justifyContent: 'center',
alignItems: 'center',
},
artScroll: { artScroll: {
marginTop: 10, marginTop: 10,
height: 190, height: 190,

View File

@ -2,6 +2,7 @@ import Button from '@app/components/Button'
import CoverArt from '@app/components/CoverArt' import CoverArt from '@app/components/CoverArt'
import GradientBackground from '@app/components/GradientBackground' import GradientBackground from '@app/components/GradientBackground'
import ImageGradientScrollView from '@app/components/ImageGradientScrollView' import ImageGradientScrollView from '@app/components/ImageGradientScrollView'
import NothingHere from '@app/components/NothingHere'
import SongItem from '@app/components/SongItem' import SongItem from '@app/components/SongItem'
import { playlistAtomFamily } from '@app/state/music' import { playlistAtomFamily } from '@app/state/music'
import { useSetQueue } from '@app/state/trackplayer' import { useSetQueue } from '@app/state/trackplayer'
@ -22,6 +23,19 @@ const PlaylistDetails: React.FC<{
return <></> return <></>
} }
const Songs = () => (
<>
<View style={styles.controls}>
<Button title="Play Playlist" onPress={() => setQueue(playlist.songs, playlist.name, playlist.songs[0].id)} />
</View>
<View style={styles.songs}>
{playlist.songs.map((s, index) => (
<SongItem key={index} song={s} showArt={true} onPress={() => setQueue(playlist.songs, playlist.name, s.id)} />
))}
</View>
</>
)
return ( return (
<ImageGradientScrollView <ImageGradientScrollView
imageUri={playlist.coverArtThumbUri} imageUri={playlist.coverArtThumbUri}
@ -31,19 +45,7 @@ const PlaylistDetails: React.FC<{
<CoverArt coverArtUri={playlist.coverArtUri} style={styles.cover} /> <CoverArt coverArtUri={playlist.coverArtUri} style={styles.cover} />
<Text style={styles.title}>{playlist.name}</Text> <Text style={styles.title}>{playlist.name}</Text>
{playlist.comment ? <Text style={styles.subtitle}>{playlist.comment}</Text> : <></>} {playlist.comment ? <Text style={styles.subtitle}>{playlist.comment}</Text> : <></>}
<View style={styles.controls}> {playlist.songs.length > 0 ? <Songs /> : <NothingHere height={350} width={250} />}
<Button title="Play Playlist" onPress={() => setQueue(playlist.songs, playlist.name, playlist.songs[0].id)} />
</View>
<View style={styles.songs}>
{playlist.songs.map((s, index) => (
<SongItem
key={index}
song={s}
showArt={true}
onPress={() => setQueue(playlist.songs, playlist.name, s.id)}
/>
))}
</View>
</View> </View>
</ImageGradientScrollView> </ImageGradientScrollView>
) )
@ -99,9 +101,14 @@ const styles = StyleSheet.create({
height: 160, height: 160,
width: 160, width: 160,
}, },
controls: { songsContainer: {
width: '100%',
marginTop: 18, marginTop: 18,
alignItems: 'center',
},
controls: {
flexDirection: 'row', flexDirection: 'row',
marginTop: 20,
}, },
songs: { songs: {
marginTop: 26, marginTop: 26,
@ -112,6 +119,12 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
paddingTop: 100, paddingTop: 100,
}, },
nothingContainer: {
height: 400,
backgroundColor: 'green',
justifyContent: 'center',
alignItems: 'center',
},
}) })
export default React.memo(PlaylistView) export default React.memo(PlaylistView)

View File

@ -2,6 +2,7 @@ enum font {
regular = 'Metropolis-Regular', regular = 'Metropolis-Regular',
semiBold = 'Metropolis-SemiBold', semiBold = 'Metropolis-SemiBold',
bold = 'Metropolis-Bold', bold = 'Metropolis-Bold',
lightItalic = 'Metropolis-SemiBoldItalic',
} }
export default font export default font