mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-29 17:39:27 +01:00
added nothing here message for empty lists
This commit is contained in:
parent
9d835f04aa
commit
a1b6aa6732
33
app/components/NothingHere.tsx
Normal file
33
app/components/NothingHere.tsx
Normal 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
|
||||||
@ -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,
|
||||||
|
|||||||
@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user