artist view + moved components
This commit is contained in:
@@ -5,7 +5,7 @@ import { translate } from '../i18n/i18n';
|
||||
import { SearchContext } from '../views/SearchView';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
export type Filter = 'artist' | 'song' | 'genre' | 'all';
|
||||
export type Filter = 'artist' | 'song' | 'genre' | 'all' | 'favorite';
|
||||
|
||||
type FilterButton = {
|
||||
name: string;
|
||||
@@ -16,7 +16,7 @@ type FilterButton = {
|
||||
const SearchBar = () => {
|
||||
const { filter, updateFilter } = React.useContext(SearchContext);
|
||||
const { stringQuery, updateStringQuery } = React.useContext(SearchContext);
|
||||
const [barText, updateBarText] = React.useState(stringQuery);
|
||||
const [ barText, updateBarText ] = React.useState(stringQuery);
|
||||
|
||||
const debouncedUpdateStringQuery = debounce(updateStringQuery, 500);
|
||||
|
||||
@@ -42,6 +42,11 @@ const SearchBar = () => {
|
||||
callback: () => updateFilter('all'),
|
||||
id: 'all',
|
||||
},
|
||||
{
|
||||
name: translate('favoriteFilter'),
|
||||
callback: () => updateFilter('favorite'),
|
||||
id: 'favorite',
|
||||
},
|
||||
{
|
||||
name: translate('artistFilter'),
|
||||
callback: () => updateFilter('artist'),
|
||||
|
||||
@@ -29,6 +29,8 @@ import SearchHistoryCard from './HistoryCard';
|
||||
import Song, { SongWithArtist } from '../models/Song';
|
||||
import { useNavigation } from '../Navigation';
|
||||
import Artist from '../models/Artist';
|
||||
import SongRow from '../components/SongRow';
|
||||
|
||||
|
||||
const swaToSongCardProps = (song: SongWithArtist) => ({
|
||||
songId: song.id,
|
||||
@@ -66,67 +68,67 @@ const RowCustom = (props: Parameters<typeof Box>[0] & { onPress?: () => void })
|
||||
);
|
||||
};
|
||||
|
||||
type SongRowProps = {
|
||||
song: Song | SongWithArtist; // TODO: remove Song
|
||||
onPress: () => void;
|
||||
};
|
||||
// type SongRowProps = {
|
||||
// song: Song | SongWithArtist; // TODO: remove Song
|
||||
// onPress: () => void;
|
||||
// };
|
||||
|
||||
const SongRow = ({ song, onPress }: SongRowProps) => {
|
||||
return (
|
||||
<RowCustom width={'100%'}>
|
||||
<HStack px={2} space={5} justifyContent={'space-between'}>
|
||||
<Image
|
||||
flexShrink={0}
|
||||
flexGrow={0}
|
||||
pl={10}
|
||||
style={{ zIndex: 0, aspectRatio: 1, borderRadius: 5 }}
|
||||
source={{ uri: song.cover }}
|
||||
alt={song.name}
|
||||
/>
|
||||
<HStack
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexShrink: 1,
|
||||
flexGrow: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
}}
|
||||
space={6}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
flexShrink: 1,
|
||||
}}
|
||||
isTruncated
|
||||
pl={10}
|
||||
maxW={'100%'}
|
||||
bold
|
||||
fontSize="md"
|
||||
>
|
||||
{song.name}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
}}
|
||||
fontSize={'sm'}
|
||||
>
|
||||
{song.artistId ?? 'artist'}
|
||||
</Text>
|
||||
</HStack>
|
||||
<TextButton
|
||||
flexShrink={0}
|
||||
flexGrow={0}
|
||||
translate={{ translationKey: 'playBtn' }}
|
||||
colorScheme="primary"
|
||||
variant={'outline'}
|
||||
size="sm"
|
||||
onPress={onPress}
|
||||
/>
|
||||
</HStack>
|
||||
</RowCustom>
|
||||
);
|
||||
};
|
||||
// const SongRow = ({ song, onPress }: SongRowProps) => {
|
||||
// return (
|
||||
// <RowCustom width={'100%'}>
|
||||
// <HStack px={2} space={5} justifyContent={'space-between'}>
|
||||
// <Image
|
||||
// flexShrink={0}
|
||||
// flexGrow={0}
|
||||
// pl={10}
|
||||
// style={{ zIndex: 0, aspectRatio: 1, borderRadius: 5 }}
|
||||
// source={{ uri: song.cover }}
|
||||
// alt={song.name}
|
||||
// />
|
||||
// <HStack
|
||||
// style={{
|
||||
// display: 'flex',
|
||||
// flexShrink: 1,
|
||||
// flexGrow: 1,
|
||||
// alignItems: 'center',
|
||||
// justifyContent: 'flex-start',
|
||||
// }}
|
||||
// space={6}
|
||||
// >
|
||||
// <Text
|
||||
// style={{
|
||||
// flexShrink: 1,
|
||||
// }}
|
||||
// isTruncated
|
||||
// pl={10}
|
||||
// maxW={'100%'}
|
||||
// bold
|
||||
// fontSize="md"
|
||||
// >
|
||||
// {song.name}
|
||||
// </Text>
|
||||
// <Text
|
||||
// style={{
|
||||
// flexShrink: 0,
|
||||
// }}
|
||||
// fontSize={'sm'}
|
||||
// >
|
||||
// {song.artistId ?? 'artist'}
|
||||
// </Text>
|
||||
// </HStack>
|
||||
// <TextButton
|
||||
// flexShrink={0}
|
||||
// flexGrow={0}
|
||||
// translate={{ translationKey: 'playBtn' }}
|
||||
// colorScheme="primary"
|
||||
// variant={'outline'}
|
||||
// size="sm"
|
||||
// onPress={onPress}
|
||||
// />
|
||||
// </HStack>
|
||||
// </RowCustom>
|
||||
// );
|
||||
// };
|
||||
|
||||
SongRow.defaultProps = {
|
||||
onPress: () => {},
|
||||
@@ -299,6 +301,35 @@ const GenreSearchComponent = (props: ItemSearchComponentProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const FavoriteSearchComponent = (props: SongsSearchComponentProps) => {
|
||||
const { favoriteData } = React.useContext(SearchContext);
|
||||
const navigation = useNavigation();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Text fontSize="xl" fontWeight="bold" mt={4}>
|
||||
{translate('favoriteFilter')}
|
||||
</Text>
|
||||
<Box>
|
||||
{favoriteData?.length ? (
|
||||
favoriteData.slice(0, props.maxRows).map((comp, index) => (
|
||||
<SongRow
|
||||
key={index}
|
||||
song={comp}
|
||||
onPress={() => {
|
||||
API.createSearchHistoryEntry(comp.name, 'song');
|
||||
navigation.navigate('Song', { songId: comp.id });
|
||||
}}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Text>{translate('errNoResults')}</Text>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const AllComponent = () => {
|
||||
const screenSize = useBreakpointValue({ base: 'small', md: 'big' });
|
||||
const isMobileView = screenSize == 'small';
|
||||
@@ -344,6 +375,8 @@ const FilterSwitch = () => {
|
||||
return <ArtistSearchComponent />;
|
||||
case 'genre':
|
||||
return <GenreSearchComponent />;
|
||||
case 'favorite':
|
||||
return <FavoriteSearchComponent />;
|
||||
default:
|
||||
return <Text>Something very bad happened: {currentFilter}</Text>;
|
||||
}
|
||||
@@ -351,7 +384,8 @@ const FilterSwitch = () => {
|
||||
|
||||
export const SearchResultComponent = () => {
|
||||
const { stringQuery } = React.useContext(SearchContext);
|
||||
const shouldOutput = !!stringQuery.trim();
|
||||
const { filter } = React.useContext(SearchContext);
|
||||
const shouldOutput = !!stringQuery.trim() || filter == "favorite";
|
||||
|
||||
return shouldOutput ? (
|
||||
<Box p={5}>
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import { HStack, Image, Text } from "native-base";
|
||||
import { HStack, IconButton, Image, Text } from "native-base";
|
||||
import Song, { SongWithArtist } from "../models/Song";
|
||||
import RowCustom from "./RowCustom";
|
||||
import TextButton from "./TextButton";
|
||||
import { MaterialIcons } from "@expo/vector-icons";
|
||||
import API from "../API";
|
||||
|
||||
|
||||
type SongRowProps = {
|
||||
liked: boolean;
|
||||
song: Song | SongWithArtist; // TODO: remove Song
|
||||
onPress: () => void;
|
||||
};
|
||||
|
||||
const SongRow = ({ song, onPress }: SongRowProps) => {
|
||||
const handleLikeButton = {
|
||||
}
|
||||
|
||||
const SongRow = ({ song, onPress, liked }: SongRowProps) => {
|
||||
return (
|
||||
<RowCustom width={"100%"}>
|
||||
<HStack px={2} space={5} justifyContent={"space-between"}>
|
||||
@@ -23,6 +29,10 @@ const SongRow = ({ song, onPress }: SongRowProps) => {
|
||||
borderColor={'white'}
|
||||
borderWidth={1}
|
||||
/>
|
||||
<IconButton size={'sm'} variant="ghost" _icon={{
|
||||
as: MaterialIcons,
|
||||
name: !liked ? "favorite-outline" : 'favorite',
|
||||
}} />
|
||||
<HStack
|
||||
style={{
|
||||
display: "flex",
|
||||
|
||||
@@ -139,38 +139,28 @@ const ArtistDetailsView = ({ artistId }: any) => {
|
||||
return (
|
||||
<ScrollView>
|
||||
<ImageBackground
|
||||
style={{width : '100%', height: isMobileView ? 200 : 300}}
|
||||
source={{uri : "https://picsum.photos/720"}}>
|
||||
<LinearGradient
|
||||
colors={['#00000000', '#000000']}
|
||||
style={{height : '100%', width : '100%'}}/>
|
||||
</ImageBackground>
|
||||
{/* <Box>
|
||||
<Image
|
||||
source={{ uri: 'https://picsum.photos/720' }}
|
||||
alt={artistData?.name}
|
||||
size={'100%'}
|
||||
height={isMobileView ? 200 : 300}
|
||||
width={'100%'}
|
||||
resizeMode='cover'
|
||||
/> */}
|
||||
<Box>
|
||||
<Heading mt={-20} ml={3} fontSize={50}>{artistData?.name}</Heading>
|
||||
<ScrollView mt={3}>
|
||||
{songs.map((comp: Song | SongWithArtist, index: Key | null | undefined) => (
|
||||
<SongRow
|
||||
key={index}
|
||||
song={comp}
|
||||
onPress={() => {
|
||||
API.createSearchHistoryEntry(comp.name, "song", Date.now());
|
||||
navigation.navigate("Song", { songId: comp.id });
|
||||
}}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollView>
|
||||
</Box>
|
||||
{/* </Box> */}
|
||||
style={{width : '100%', height: isMobileView ? 200 : 300}}
|
||||
source={{uri : "https://picsum.photos/720"}}>
|
||||
<LinearGradient
|
||||
colors={['#00000000', '#000000']}
|
||||
style={{height : '100%', width : '100%'}}/>
|
||||
</ImageBackground>
|
||||
<Box>
|
||||
<Heading mt={-20} ml={3} fontSize={50}>{artistData?.name}</Heading>
|
||||
<ScrollView mt={3}>
|
||||
{songs.map((comp: Song | SongWithArtist, index: Key | null | undefined) => (
|
||||
<SongRow
|
||||
key={index}
|
||||
song={comp}
|
||||
onPress={() => {
|
||||
API.createSearchHistoryEntry(comp.name, "song", Date.now());
|
||||
navigation.navigate("Song", { songId: comp.id });
|
||||
}}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollView>
|
||||
</Box>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,13 +12,14 @@ import { ScrollView } from 'native-base';
|
||||
import { RouteProps } from '../Navigation';
|
||||
|
||||
interface SearchContextType {
|
||||
filter: 'artist' | 'song' | 'genre' | 'all';
|
||||
updateFilter: (newData: 'artist' | 'song' | 'genre' | 'all') => void;
|
||||
filter: 'artist' | 'song' | 'genre' | 'all' | 'favorite';
|
||||
updateFilter: (newData: 'artist' | 'song' | 'genre' | 'all' | 'favorite') => void;
|
||||
stringQuery: string;
|
||||
updateStringQuery: (newData: string) => void;
|
||||
songData: Song[];
|
||||
artistData: Artist[];
|
||||
genreData: Genre[];
|
||||
favoriteData: Song[];
|
||||
isLoadingSong: boolean;
|
||||
isLoadingArtist: boolean;
|
||||
isLoadingGenre: boolean;
|
||||
@@ -32,6 +33,7 @@ export const SearchContext = React.createContext<SearchContextType>({
|
||||
songData: [],
|
||||
artistData: [],
|
||||
genreData: [],
|
||||
favoriteData: [],
|
||||
isLoadingSong: false,
|
||||
isLoadingArtist: false,
|
||||
isLoadingGenre: false,
|
||||
@@ -60,6 +62,11 @@ const SearchView = (props: RouteProps<SearchViewProps>) => {
|
||||
{ enabled: !!stringQuery }
|
||||
);
|
||||
|
||||
const { isLoading: isLoadingFavorite, data: favoriteData = [] } = useQuery(
|
||||
API.getFavorites(),
|
||||
{ enabled: true }
|
||||
)
|
||||
|
||||
const updateFilter = (newData: Filter) => {
|
||||
// called when the filter is changed
|
||||
setFilter(newData);
|
||||
@@ -80,6 +87,7 @@ const SearchView = (props: RouteProps<SearchViewProps>) => {
|
||||
songData,
|
||||
artistData,
|
||||
genreData,
|
||||
favoriteData,
|
||||
isLoadingSong,
|
||||
isLoadingArtist,
|
||||
isLoadingGenre,
|
||||
|
||||
Reference in New Issue
Block a user