mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 00:59:28 +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 { GestureResponderEvent, StyleSheet, Text, View } from 'react-native'
|
||||
import IconFA from 'react-native-vector-icons/FontAwesome'
|
||||
import IconMat from 'react-native-vector-icons/MaterialIcons'
|
||||
import CoverArt from './CoverArt'
|
||||
import PressableOpacity from './PressableOpacity'
|
||||
|
||||
@ -33,10 +32,7 @@ const SongItem: React.FC<{
|
||||
</PressableOpacity>
|
||||
<View style={styles.controls}>
|
||||
<PressableOpacity onPress={undefined}>
|
||||
<IconFA name="star-o" size={26} color={colors.text.primary} />
|
||||
</PressableOpacity>
|
||||
<PressableOpacity onPress={undefined} style={styles.more}>
|
||||
<IconMat name="more-vert" size={32} color="white" />
|
||||
<IconFA name="star-o" size={26} color={colors.text.secondary} />
|
||||
</PressableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
@ -76,7 +72,7 @@ const styles = StyleSheet.create({
|
||||
controls: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginLeft: 10,
|
||||
marginLeft: 16,
|
||||
},
|
||||
more: {
|
||||
marginLeft: 8,
|
||||
|
||||
@ -2,6 +2,7 @@ import Button from '@app/components/Button'
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import GradientBackground from '@app/components/GradientBackground'
|
||||
import ImageGradientScrollView from '@app/components/ImageGradientScrollView'
|
||||
import NothingHere from '@app/components/NothingHere'
|
||||
import SongItem from '@app/components/SongItem'
|
||||
import { albumAtomFamily } from '@app/state/music'
|
||||
import { useSetQueue } from '@app/state/trackplayer'
|
||||
@ -22,6 +23,27 @@ const AlbumDetails: React.FC<{
|
||||
return <></>
|
||||
}
|
||||
|
||||
const Songs = () => (
|
||||
<>
|
||||
<View style={styles.controls}>
|
||||
<Button title="Play Album" onPress={() => setQueue(album.songs, album.name, album.songs[0].id)} />
|
||||
</View>
|
||||
<View style={styles.songs}>
|
||||
{album.songs
|
||||
.sort((a, b) => {
|
||||
if (b.track && a.track) {
|
||||
return a.track - b.track
|
||||
} else {
|
||||
return a.title.localeCompare(b.title)
|
||||
}
|
||||
})
|
||||
.map(s => (
|
||||
<SongItem key={s.id} song={s} onPress={() => setQueue(album.songs, album.name, s.id)} />
|
||||
))}
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<ImageGradientScrollView
|
||||
imageUri={album.coverArtThumbUri}
|
||||
@ -34,22 +56,7 @@ const AlbumDetails: React.FC<{
|
||||
{album.artist}
|
||||
{album.year ? ` • ${album.year}` : ''}
|
||||
</Text>
|
||||
<View style={styles.controls}>
|
||||
<Button title="Play Album" onPress={() => setQueue(album.songs, album.name, album.songs[0].id)} />
|
||||
</View>
|
||||
<View style={styles.songs}>
|
||||
{album.songs
|
||||
.sort((a, b) => {
|
||||
if (b.track && a.track) {
|
||||
return a.track - b.track
|
||||
} else {
|
||||
return a.title.localeCompare(b.title)
|
||||
}
|
||||
})
|
||||
.map(s => (
|
||||
<SongItem key={s.id} song={s} onPress={() => setQueue(album.songs, album.name, s.id)} />
|
||||
))}
|
||||
</View>
|
||||
{album.songs.length > 0 ? <Songs /> : <NothingHere height={300} width={250} />}
|
||||
</View>
|
||||
</ImageGradientScrollView>
|
||||
)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import GradientScrollView from '@app/components/GradientScrollView'
|
||||
import NothingHere from '@app/components/NothingHere'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
import { AlbumListItem } from '@app/models/music'
|
||||
import { homeListsAtom, homeListsUpdatingAtom, useUpdateHomeLists } from '@app/state/music'
|
||||
@ -44,19 +45,29 @@ const Category = React.memo<{
|
||||
name?: string
|
||||
data: AlbumListItem[]
|
||||
}>(({ name, data }) => {
|
||||
const Albums = () => (
|
||||
<ScrollView
|
||||
horizontal={true}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
overScrollMode={'never'}
|
||||
style={styles.artScroll}
|
||||
contentContainerStyle={styles.artScrollContent}>
|
||||
{data.map(album => (
|
||||
<AlbumItem key={album.id} album={album} />
|
||||
))}
|
||||
</ScrollView>
|
||||
)
|
||||
|
||||
const Nothing = () => (
|
||||
<View style={styles.nothingHereContent}>
|
||||
<NothingHere height={styles.nothingHereContent.height} />
|
||||
</View>
|
||||
)
|
||||
|
||||
return (
|
||||
<View style={styles.category}>
|
||||
<Text style={styles.categoryHeader}>{name}</Text>
|
||||
<ScrollView
|
||||
horizontal={true}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
overScrollMode={'never'}
|
||||
style={styles.artScroll}
|
||||
contentContainerStyle={styles.artScrollContent}>
|
||||
{data.map(album => (
|
||||
<AlbumItem key={album.id} album={album} />
|
||||
))}
|
||||
</ScrollView>
|
||||
{data.length > 0 ? <Albums /> : <Nothing />}
|
||||
</View>
|
||||
)
|
||||
})
|
||||
@ -110,6 +121,12 @@ const styles = StyleSheet.create({
|
||||
paddingHorizontal: 20,
|
||||
marginTop: 4,
|
||||
},
|
||||
nothingHereContent: {
|
||||
width: '100%',
|
||||
height: 190,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
artScroll: {
|
||||
marginTop: 10,
|
||||
height: 190,
|
||||
|
||||
@ -2,6 +2,7 @@ import Button from '@app/components/Button'
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import GradientBackground from '@app/components/GradientBackground'
|
||||
import ImageGradientScrollView from '@app/components/ImageGradientScrollView'
|
||||
import NothingHere from '@app/components/NothingHere'
|
||||
import SongItem from '@app/components/SongItem'
|
||||
import { playlistAtomFamily } from '@app/state/music'
|
||||
import { useSetQueue } from '@app/state/trackplayer'
|
||||
@ -22,6 +23,19 @@ const PlaylistDetails: React.FC<{
|
||||
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 (
|
||||
<ImageGradientScrollView
|
||||
imageUri={playlist.coverArtThumbUri}
|
||||
@ -31,19 +45,7 @@ const PlaylistDetails: React.FC<{
|
||||
<CoverArt coverArtUri={playlist.coverArtUri} style={styles.cover} />
|
||||
<Text style={styles.title}>{playlist.name}</Text>
|
||||
{playlist.comment ? <Text style={styles.subtitle}>{playlist.comment}</Text> : <></>}
|
||||
<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>
|
||||
{playlist.songs.length > 0 ? <Songs /> : <NothingHere height={350} width={250} />}
|
||||
</View>
|
||||
</ImageGradientScrollView>
|
||||
)
|
||||
@ -99,9 +101,14 @@ const styles = StyleSheet.create({
|
||||
height: 160,
|
||||
width: 160,
|
||||
},
|
||||
controls: {
|
||||
songsContainer: {
|
||||
width: '100%',
|
||||
marginTop: 18,
|
||||
alignItems: 'center',
|
||||
},
|
||||
controls: {
|
||||
flexDirection: 'row',
|
||||
marginTop: 20,
|
||||
},
|
||||
songs: {
|
||||
marginTop: 26,
|
||||
@ -112,6 +119,12 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
paddingTop: 100,
|
||||
},
|
||||
nothingContainer: {
|
||||
height: 400,
|
||||
backgroundColor: 'green',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
})
|
||||
|
||||
export default React.memo(PlaylistView)
|
||||
|
||||
@ -2,6 +2,7 @@ enum font {
|
||||
regular = 'Metropolis-Regular',
|
||||
semiBold = 'Metropolis-SemiBold',
|
||||
bold = 'Metropolis-Bold',
|
||||
lightItalic = 'Metropolis-SemiBoldItalic',
|
||||
}
|
||||
|
||||
export default font
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user