mirror of
https://github.com/austinried/subtracks.git
synced 2026-02-10 23:02:43 +01:00
redid cover art (again...) and impl a ListItem
This commit is contained in:
@@ -3,8 +3,8 @@ import GradientBackground from '@app/components/GradientBackground'
|
||||
import ImageGradientScrollView from '@app/components/ImageGradientScrollView'
|
||||
import ListPlayerControls from '@app/components/ListPlayerControls'
|
||||
import NothingHere from '@app/components/NothingHere'
|
||||
import SongItem from '@app/components/SongItem'
|
||||
import { albumAtomFamily } from '@app/state/music'
|
||||
import ListItem from '@app/components/ListItem'
|
||||
import { albumAtomFamily, useCoverArtUri } from '@app/state/music'
|
||||
import { useSetQueue } from '@app/state/trackplayer'
|
||||
import colors from '@app/styles/colors'
|
||||
import font from '@app/styles/font'
|
||||
@@ -17,6 +17,7 @@ const AlbumDetails: React.FC<{
|
||||
id: string
|
||||
}> = ({ id }) => {
|
||||
const album = useAtomValue(albumAtomFamily(id))
|
||||
const coverArtUri = useCoverArtUri()
|
||||
const setQueue = useSetQueue()
|
||||
|
||||
if (!album) {
|
||||
@@ -36,7 +37,7 @@ const AlbumDetails: React.FC<{
|
||||
}
|
||||
})
|
||||
.map((s, i) => (
|
||||
<SongItem key={i} song={s} onPress={() => setQueue(album.songs, album.name, i)} />
|
||||
<ListItem key={i} item={s} subtitle={s.artist} onPress={() => setQueue(album.songs, album.name, i)} />
|
||||
))}
|
||||
</View>
|
||||
</>
|
||||
@@ -44,11 +45,11 @@ const AlbumDetails: React.FC<{
|
||||
|
||||
return (
|
||||
<ImageGradientScrollView
|
||||
imageUri={album.coverArtThumbUri}
|
||||
imageUri={coverArtUri(album.coverArt)}
|
||||
imageKey={`${album.name}${album.artist}`}
|
||||
style={styles.container}>
|
||||
<View style={styles.content}>
|
||||
<CoverArt coverArtUri={album.coverArtUri} style={styles.cover} />
|
||||
<CoverArt coverArt={album.coverArt} style={styles.cover} imageSize="original" />
|
||||
<Text style={styles.title}>{album.name}</Text>
|
||||
<Text style={styles.subtitle}>
|
||||
{album.artist}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import ArtistArt from '@app/components/ArtistArt'
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import GradientScrollView from '@app/components/GradientScrollView'
|
||||
import Header from '@app/components/Header'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
import SongItem from '@app/components/SongItem'
|
||||
import ListItem from '@app/components/ListItem'
|
||||
import { Album } from '@app/models/music'
|
||||
import { artistInfoAtomFamily } from '@app/state/music'
|
||||
import { useSetQueue } from '@app/state/trackplayer'
|
||||
@@ -26,7 +26,7 @@ const AlbumItem = React.memo<{
|
||||
<PressableOpacity
|
||||
onPress={() => navigation.navigate('AlbumView', { id: album.id, title: album.name })}
|
||||
style={[styles.albumItem, { width }]}>
|
||||
<CoverArt coverArtUri={album.coverArtThumbUri} style={{ height, width }} />
|
||||
<CoverArt coverArt={album.coverArt} style={{ height, width }} />
|
||||
<Text style={styles.albumTitle}>{album.name}</Text>
|
||||
<Text style={styles.albumYear}> {album.year ? album.year : ''}</Text>
|
||||
</PressableOpacity>
|
||||
@@ -47,25 +47,19 @@ const ArtistDetails: React.FC<{ id: string }> = ({ id }) => {
|
||||
|
||||
const TopSongs = () => (
|
||||
<>
|
||||
<Text style={styles.header}>Top Songs</Text>
|
||||
<Header>Top Songs</Header>
|
||||
{artist.topSongs.map((s, i) => (
|
||||
<SongItem
|
||||
<ListItem
|
||||
key={i}
|
||||
song={s}
|
||||
item={s}
|
||||
showArt={true}
|
||||
subtitle="album"
|
||||
subtitle={s.album}
|
||||
onPress={() => setQueue(artist.topSongs, `Top Songs: ${artist.name}`, i)}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
|
||||
const ArtistCoverFallback = () => (
|
||||
<View style={styles.artistCover}>
|
||||
<ArtistArt id={artist.id} round={false} height={artistCoverHeight} width={coverLayout.width} />
|
||||
</View>
|
||||
)
|
||||
|
||||
return (
|
||||
<GradientScrollView
|
||||
onLayout={coverLayout.onLayout}
|
||||
@@ -73,17 +67,18 @@ const ArtistDetails: React.FC<{ id: string }> = ({ id }) => {
|
||||
style={styles.scroll}
|
||||
contentContainerStyle={styles.scrollContent}>
|
||||
<CoverArt
|
||||
FallbackComponent={ArtistCoverFallback}
|
||||
coverArtUri={artist.largeImageUrl}
|
||||
artistId={artist.id}
|
||||
style={styles.artistCover}
|
||||
resizeMode={FastImage.resizeMode.cover}
|
||||
round={false}
|
||||
imageSize="original"
|
||||
/>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={styles.title}>{artist.name}</Text>
|
||||
</View>
|
||||
<View style={styles.container}>
|
||||
{artist.topSongs.length > 0 ? <TopSongs /> : <></>}
|
||||
<Text style={styles.header}>Albums</Text>
|
||||
<Header>Albums</Header>
|
||||
<View style={styles.albums} onLayout={albumsLayout.onLayout}>
|
||||
{artist.albums.map(a => (
|
||||
<AlbumItem key={a.id} album={a} height={albumSize} width={albumSize} />
|
||||
@@ -140,13 +135,6 @@ const styles = StyleSheet.create({
|
||||
paddingHorizontal: 10,
|
||||
marginBottom: 10,
|
||||
},
|
||||
header: {
|
||||
fontFamily: font.bold,
|
||||
fontSize: 24,
|
||||
color: colors.text.primary,
|
||||
marginTop: 20,
|
||||
marginBottom: 14,
|
||||
},
|
||||
artistCover: {
|
||||
position: 'absolute',
|
||||
height: artistCoverHeight,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import GradientScrollView from '@app/components/GradientScrollView'
|
||||
import Header from '@app/components/Header'
|
||||
import NothingHere from '@app/components/NothingHere'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
import { AlbumListItem } from '@app/models/music'
|
||||
@@ -30,7 +31,7 @@ const AlbumItem = React.memo<{
|
||||
onPress={() => navigation.navigate('AlbumView', { id: album.id, title: album.name })}
|
||||
key={album.id}
|
||||
style={styles.item}>
|
||||
<CoverArt coverArtUri={album.coverArtThumbUri} style={{ height: styles.item.width, width: styles.item.width }} />
|
||||
<CoverArt coverArt={album.coverArt} style={{ height: styles.item.width, width: styles.item.width }} />
|
||||
<Text style={styles.title} numberOfLines={1}>
|
||||
{album.name}
|
||||
</Text>
|
||||
@@ -66,7 +67,7 @@ const Category = React.memo<{
|
||||
|
||||
return (
|
||||
<View style={styles.category}>
|
||||
<Text style={styles.categoryHeader}>{name}</Text>
|
||||
<Header style={styles.header}>{name}</Header>
|
||||
{data.length > 0 ? <Albums /> : <Nothing />}
|
||||
</View>
|
||||
)
|
||||
@@ -111,24 +112,19 @@ const styles = StyleSheet.create({
|
||||
content: {
|
||||
paddingBottom: 20,
|
||||
},
|
||||
category: {
|
||||
marginTop: 12,
|
||||
},
|
||||
categoryHeader: {
|
||||
fontFamily: font.bold,
|
||||
fontSize: 24,
|
||||
color: colors.text.primary,
|
||||
header: {
|
||||
paddingHorizontal: 20,
|
||||
marginTop: 4,
|
||||
},
|
||||
category: {
|
||||
// marginTop: 12,
|
||||
},
|
||||
nothingHereContent: {
|
||||
width: '100%',
|
||||
height: 200,
|
||||
height: 190,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
artScroll: {
|
||||
marginTop: 10,
|
||||
height: 190,
|
||||
},
|
||||
artScrollContent: {
|
||||
|
||||
@@ -17,15 +17,15 @@ const AlbumItem = React.memo<{
|
||||
size: number
|
||||
height: number
|
||||
artist?: string
|
||||
coverArtUri?: string
|
||||
}>(({ id, name, artist, size, height, coverArtUri }) => {
|
||||
coverArt?: string
|
||||
}>(({ id, name, artist, size, height, coverArt }) => {
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
<PressableOpacity
|
||||
style={[styles.item, { maxWidth: size, height }]}
|
||||
onPress={() => navigation.navigate('AlbumView', { id, title: name })}>
|
||||
<CoverArt coverArtUri={coverArtUri} style={{ height: size, width: size }} />
|
||||
<CoverArt coverArt={coverArt} style={{ height: size, width: size }} />
|
||||
<View style={styles.itemDetails}>
|
||||
<Text style={styles.title} numberOfLines={1}>
|
||||
{name}
|
||||
@@ -43,7 +43,7 @@ const AlbumListRenderItem: React.FC<{
|
||||
}> = ({ item }) => (
|
||||
<AlbumItem
|
||||
id={item.album.id}
|
||||
coverArtUri={item.album.coverArtThumbUri}
|
||||
coverArt={item.album.coverArt}
|
||||
name={item.album.name}
|
||||
artist={item.album.artist}
|
||||
size={item.size}
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
import ArtistArt from '@app/components/ArtistArt'
|
||||
import GradientFlatList from '@app/components/GradientFlatList'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
import ListItem from '@app/components/ListItem'
|
||||
import { Artist } from '@app/models/music'
|
||||
import { artistsAtom, artistsUpdatingAtom, useUpdateArtists } from '@app/state/music'
|
||||
import colors from '@app/styles/colors'
|
||||
import font from '@app/styles/font'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import React, { useEffect } from 'react'
|
||||
import { StyleSheet, Text } from 'react-native'
|
||||
import { StyleSheet } from 'react-native'
|
||||
|
||||
const ArtistItem = React.memo<{ item: Artist }>(({ item }) => {
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
<PressableOpacity
|
||||
style={styles.item}
|
||||
onPress={() => navigation.navigate('ArtistView', { id: item.id, title: item.name })}>
|
||||
<ArtistArt id={item.id} width={styles.art.width} height={styles.art.height} />
|
||||
<Text style={styles.title}>{item.name}</Text>
|
||||
</PressableOpacity>
|
||||
<ListItem
|
||||
item={item}
|
||||
showArt={true}
|
||||
showStar={false}
|
||||
listStyle="big"
|
||||
onPress={() => navigation.navigate('ArtistView', { id: item.id, title: item.name })}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -52,23 +50,8 @@ const ArtistsList = () => {
|
||||
const styles = StyleSheet.create({
|
||||
listContent: {
|
||||
minHeight: '100%',
|
||||
},
|
||||
item: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
marginVertical: 6,
|
||||
marginLeft: 10,
|
||||
},
|
||||
title: {
|
||||
fontFamily: font.semiBold,
|
||||
fontSize: 16,
|
||||
color: colors.text.primary,
|
||||
marginLeft: 10,
|
||||
},
|
||||
art: {
|
||||
height: 70,
|
||||
width: 70,
|
||||
paddingHorizontal: 10,
|
||||
paddingTop: 6,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1,36 +1,24 @@
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import GradientFlatList from '@app/components/GradientFlatList'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
import ListItem from '@app/components/ListItem'
|
||||
import { PlaylistListItem } from '@app/models/music'
|
||||
import { playlistsAtom, playlistsUpdatingAtom, useUpdatePlaylists } from '@app/state/music'
|
||||
import colors from '@app/styles/colors'
|
||||
import font from '@app/styles/font'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import React, { useEffect } from 'react'
|
||||
import { StyleSheet, Text, View } from 'react-native'
|
||||
import { StyleSheet } from 'react-native'
|
||||
|
||||
const PlaylistItem = React.memo<{ item: PlaylistListItem }>(({ item }) => {
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
<PressableOpacity
|
||||
style={styles.item}
|
||||
onPress={() => navigation.navigate('PlaylistView', { id: item.id, title: item.name })}>
|
||||
<CoverArt coverArtUri={item.coverArtThumbUri} style={styles.art} />
|
||||
<View style={styles.text}>
|
||||
<Text style={styles.title} numberOfLines={1}>
|
||||
{item.name}
|
||||
</Text>
|
||||
{item.comment ? (
|
||||
<Text style={styles.subtitle} numberOfLines={1}>
|
||||
{item.comment}
|
||||
</Text>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</View>
|
||||
</PressableOpacity>
|
||||
<ListItem
|
||||
item={item}
|
||||
showArt={true}
|
||||
showStar={false}
|
||||
listStyle="big"
|
||||
subtitle={item.comment}
|
||||
onPress={() => navigation.navigate('PlaylistView', { id: item.id, title: item.name })}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -63,30 +51,8 @@ const PlaylistsList = () => {
|
||||
const styles = StyleSheet.create({
|
||||
listContent: {
|
||||
minHeight: '100%',
|
||||
},
|
||||
item: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
marginVertical: 6,
|
||||
marginLeft: 10,
|
||||
},
|
||||
text: {
|
||||
marginLeft: 10,
|
||||
},
|
||||
title: {
|
||||
fontFamily: font.semiBold,
|
||||
fontSize: 16,
|
||||
color: colors.text.primary,
|
||||
},
|
||||
subtitle: {
|
||||
fontFamily: font.regular,
|
||||
fontSize: 14,
|
||||
color: colors.text.secondary,
|
||||
},
|
||||
art: {
|
||||
height: 70,
|
||||
width: 70,
|
||||
paddingHorizontal: 10,
|
||||
paddingTop: 6,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ const SongCoverArt = () => {
|
||||
|
||||
return (
|
||||
<View style={coverArtStyles.container}>
|
||||
<CoverArt coverArtUri={track?.artwork as string} style={coverArtStyles.image} />
|
||||
<CoverArt coverArt={track?.coverArt} style={coverArtStyles.image} imageSize="original" />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -318,7 +318,7 @@ const NowPlayingLayout: React.FC<NowPlayingProps> = ({ navigation }) => {
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ImageGradientBackground imageUri={track?.artworkThumb as string} imageKey={`${track?.album}${track?.artist}`} />
|
||||
<ImageGradientBackground imageUri={track?.artwork as string} imageKey={`${track?.album}${track?.artist}`} />
|
||||
<NowPlayingHeader />
|
||||
<View style={styles.content}>
|
||||
<SongCoverArt />
|
||||
|
||||
@@ -3,8 +3,8 @@ import GradientBackground from '@app/components/GradientBackground'
|
||||
import ImageGradientScrollView from '@app/components/ImageGradientScrollView'
|
||||
import ListPlayerControls from '@app/components/ListPlayerControls'
|
||||
import NothingHere from '@app/components/NothingHere'
|
||||
import SongItem from '@app/components/SongItem'
|
||||
import { playlistAtomFamily } from '@app/state/music'
|
||||
import ListItem from '@app/components/ListItem'
|
||||
import { playlistAtomFamily, useCoverArtUri } from '@app/state/music'
|
||||
import { useSetQueue } from '@app/state/trackplayer'
|
||||
import colors from '@app/styles/colors'
|
||||
import font from '@app/styles/font'
|
||||
@@ -18,6 +18,7 @@ const PlaylistDetails: React.FC<{
|
||||
}> = ({ id }) => {
|
||||
const playlist = useAtomValue(playlistAtomFamily(id))
|
||||
const setQueue = useSetQueue()
|
||||
const coverArtUri = useCoverArtUri()
|
||||
|
||||
if (!playlist) {
|
||||
return <></>
|
||||
@@ -33,7 +34,13 @@ const PlaylistDetails: React.FC<{
|
||||
/>
|
||||
<View style={styles.songs}>
|
||||
{playlist.songs.map((s, i) => (
|
||||
<SongItem key={i} song={s} showArt={true} onPress={() => setQueue(playlist.songs, playlist.name, i)} />
|
||||
<ListItem
|
||||
key={i}
|
||||
item={s}
|
||||
subtitle={s.artist}
|
||||
showArt={true}
|
||||
onPress={() => setQueue(playlist.songs, playlist.name, i)}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</>
|
||||
@@ -41,11 +48,11 @@ const PlaylistDetails: React.FC<{
|
||||
|
||||
return (
|
||||
<ImageGradientScrollView
|
||||
imageUri={playlist.coverArtThumbUri}
|
||||
imageUri={coverArtUri(playlist.coverArt)}
|
||||
imageKey={`${playlist.id}${playlist.name}`}
|
||||
style={styles.container}>
|
||||
<View style={styles.content}>
|
||||
<CoverArt coverArtUri={playlist.coverArtUri} style={styles.cover} />
|
||||
<CoverArt coverArt={playlist.coverArt} style={styles.cover} imageSize="original" />
|
||||
<Text style={styles.title}>{playlist.name}</Text>
|
||||
{playlist.comment ? <Text style={styles.subtitle}>{playlist.comment}</Text> : <></>}
|
||||
{playlist.songs.length > 0 ? <Songs /> : <NothingHere height={350} width={250} />}
|
||||
|
||||
75
app/screens/Search.tsx
Normal file
75
app/screens/Search.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import GradientScrollView from '@app/components/GradientScrollView'
|
||||
import Header from '@app/components/Header'
|
||||
import ListItem from '@app/components/ListItem'
|
||||
import { searchResultsAtom, useUpdateSearchResults } from '@app/state/music'
|
||||
import colors from '@app/styles/colors'
|
||||
import font from '@app/styles/font'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import React, { useState } from 'react'
|
||||
import { StatusBar, StyleSheet, View, TextInput } from 'react-native'
|
||||
|
||||
const Search = () => {
|
||||
const [text, setText] = useState('')
|
||||
const updateSearch = useUpdateSearchResults()
|
||||
const results = useAtomValue(searchResultsAtom)
|
||||
|
||||
const onSubmitEditing = () => {
|
||||
console.log(text)
|
||||
updateSearch(text)
|
||||
}
|
||||
|
||||
return (
|
||||
<GradientScrollView style={styles.scroll} contentContainerStyle={styles.scrollContentContainer}>
|
||||
<View style={styles.content}>
|
||||
<TextInput
|
||||
style={styles.textInput}
|
||||
placeholder="Search"
|
||||
placeholderTextColor="grey"
|
||||
selectionColor={colors.text.secondary}
|
||||
value={text}
|
||||
onChangeText={setText}
|
||||
onSubmitEditing={onSubmitEditing}
|
||||
/>
|
||||
<Header>Artists</Header>
|
||||
{results.artists.map(a => (
|
||||
<ListItem key={a.id} item={a} showArt={true} showStar={false} />
|
||||
))}
|
||||
<Header>Albums</Header>
|
||||
{results.albums.map(a => (
|
||||
<ListItem key={a.id} item={a} showArt={true} showStar={false} subtitle={a.artist} />
|
||||
))}
|
||||
<Header>Songs</Header>
|
||||
{results.songs.map(a => (
|
||||
<ListItem key={a.id} item={a} showArt={true} showStar={false} subtitle={a.artist} />
|
||||
))}
|
||||
</View>
|
||||
</GradientScrollView>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scroll: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollContentContainer: {
|
||||
paddingTop: StatusBar.currentHeight,
|
||||
},
|
||||
content: {
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
textInput: {
|
||||
backgroundColor: '#515151',
|
||||
fontFamily: font.regular,
|
||||
fontSize: 18,
|
||||
color: colors.text.primary,
|
||||
marginTop: 20,
|
||||
paddingHorizontal: 12,
|
||||
},
|
||||
itemText: {
|
||||
color: colors.text.primary,
|
||||
fontFamily: font.regular,
|
||||
fontSize: 14,
|
||||
},
|
||||
})
|
||||
|
||||
export default Search
|
||||
Reference in New Issue
Block a user