components RowCustom & SongRow + artist banner
This commit is contained in:
@@ -26,6 +26,7 @@ import { createReadStream, existsSync } from 'fs';
|
||||
import { ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger';
|
||||
import { HistoryService } from 'src/history/history.service';
|
||||
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
|
||||
import { IsDefined } from 'class-validator';
|
||||
|
||||
@Controller('song')
|
||||
@ApiTags('song')
|
||||
@@ -107,6 +108,7 @@ export class SongController {
|
||||
@Query() filter: Prisma.SongWhereInput,
|
||||
@Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number,
|
||||
@Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number,
|
||||
// @Query('artistId') artistId: number,
|
||||
): Promise<Plage<Song>> {
|
||||
try {
|
||||
const ret = await this.songService.songs({
|
||||
@@ -115,6 +117,7 @@ export class SongController {
|
||||
where: {
|
||||
...filter,
|
||||
id: filter.id ? +filter.id : undefined,
|
||||
// artistId: artistId ? +artistId : undefined,
|
||||
},
|
||||
});
|
||||
return new Plage(ret, req);
|
||||
|
||||
36
front/components/RowCustom.tsx
Normal file
36
front/components/RowCustom.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useColorScheme } from "react-native";
|
||||
import { RootState, useSelector } from "../state/Store";
|
||||
import { Box, Pressable } from "native-base";
|
||||
|
||||
const RowCustom = (
|
||||
props: Parameters<typeof Box>[0] & { onPress?: () => void }
|
||||
) => {
|
||||
const settings = useSelector((state: RootState) => state.settings.local);
|
||||
const systemColorMode = useColorScheme();
|
||||
const colorScheme = settings.colorScheme;
|
||||
|
||||
return (
|
||||
<Pressable onPress={props.onPress}>
|
||||
{({ isHovered, isPressed }) => (
|
||||
<Box
|
||||
{...props}
|
||||
py={3}
|
||||
my={1}
|
||||
bg={
|
||||
(colorScheme == "system" ? systemColorMode : colorScheme) == "dark"
|
||||
? isHovered || isPressed
|
||||
? "gray.800"
|
||||
: undefined
|
||||
: isHovered || isPressed
|
||||
? "coolGray.200"
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{props.children}
|
||||
</Box>
|
||||
)}
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
||||
export default RowCustom;
|
||||
69
front/components/SongRow.tsx
Normal file
69
front/components/SongRow.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { HStack, Image, Text } from "native-base";
|
||||
import Song, { SongWithArtist } from "../models/Song";
|
||||
import RowCustom from "./RowCustom";
|
||||
import TextButton from "./TextButton";
|
||||
|
||||
|
||||
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>
|
||||
);
|
||||
};
|
||||
|
||||
export default SongRow;
|
||||
@@ -1,40 +1,53 @@
|
||||
import { VStack, Text, Image, Heading, IconButton, Icon, Container } from 'native-base';
|
||||
import { VStack, Text, Box, Image, Heading, IconButton, Icon, Container, Center, useBreakpointValue } from 'native-base';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { SafeAreaView } from 'react-native';
|
||||
import { useQuery } from 'react-query';
|
||||
import LoadingComponent from '../components/Loading';
|
||||
import API from '../API';
|
||||
|
||||
const handleFavorite = () => {
|
||||
|
||||
};
|
||||
import Song from '../models/Song';
|
||||
import SongRow from '../components/SongRow';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
|
||||
const ArtistDetailsView = ({ artistId }: any) => {
|
||||
const { isLoading, data: artistData, error } = useQuery(['artist', artistId], () => API.getArtist(artistId));
|
||||
const screenSize = useBreakpointValue({ base: "small", md: "big" });
|
||||
const isMobileView = screenSize == "small";
|
||||
let songData = [] as Song[];
|
||||
const navigation = useNavigation();
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingComponent />;
|
||||
return <Center m={10} ><LoadingComponent /></Center>;
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Container m={3}>
|
||||
<Image
|
||||
source={{ uri: 'https://picsum.photos/200' }}
|
||||
alt={artistData?.name}
|
||||
size={20}
|
||||
borderRadius="full"
|
||||
/>
|
||||
<VStack space={3}>
|
||||
<Heading>{artistData?.name}</Heading>
|
||||
<IconButton
|
||||
icon={<Icon as={Ionicons} name="heart" size={6} color="red.500" />}
|
||||
onPress={() => handleFavorite()}
|
||||
variant="unstyled"
|
||||
_pressed={{ opacity: 0.6 }}
|
||||
/>
|
||||
</VStack>
|
||||
</Container>
|
||||
<Box>
|
||||
<Image
|
||||
source={{ uri: 'https://picsum.photos/200' }}
|
||||
alt={artistData?.name}
|
||||
size={'100%'}
|
||||
height={isMobileView ? 200 : 300}
|
||||
width={'100%'}
|
||||
resizeMode='cover'
|
||||
/>
|
||||
<Box>
|
||||
<Heading m={3} >Abba</Heading>
|
||||
<Box>
|
||||
{songData.map((comp, index) => (
|
||||
<SongRow
|
||||
key={index}
|
||||
song={comp}
|
||||
onPress={() => {
|
||||
API.createSearchHistoryEntry(comp.name, "song", Date.now());
|
||||
navigation.navigate("Song", { songId: comp.id });
|
||||
}}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Box>
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user