feishin/src/renderer/features/search/components/library-command-item.tsx

184 lines
4.2 KiB
TypeScript
Raw Normal View History

2023-05-19 00:21:36 -07:00
import { Center, Flex } from '@mantine/core';
import { useCallback, MouseEvent } from 'react';
import {
RiAddBoxFill,
RiAddCircleFill,
RiAlbumFill,
RiPlayFill,
RiPlayListFill,
RiUserVoiceFill,
} from 'react-icons/ri';
import styled from 'styled-components';
import { LibraryItem } from '/@/renderer/api/types';
2023-05-19 22:24:15 -07:00
import { Button, Text } from '/@/renderer/components';
2023-05-19 00:21:36 -07:00
import { Play, PlayQueueAddOptions } from '/@/renderer/types';
2023-05-19 22:24:15 -07:00
const Item = styled(Flex)``;
2023-05-19 00:21:36 -07:00
const ItemGrid = styled.div<{ height: number }>`
display: grid;
grid-auto-columns: 1fr;
grid-template-areas: 'image info';
grid-template-rows: 1fr;
grid-template-columns: ${(props) => props.height}px minmax(0, 1fr);
gap: 0.5rem;
width: 100%;
max-width: 100%;
height: 100%;
letter-spacing: 0.5px;
`;
const ImageWrapper = styled.div`
display: flex;
grid-area: image;
align-items: center;
justify-content: center;
height: 100%;
`;
const MetadataWrapper = styled.div`
display: flex;
flex-direction: column;
grid-area: info;
justify-content: center;
width: 100%;
`;
const StyledImage = styled.img`
object-fit: cover;
border-radius: 4px;
`;
2023-05-19 22:24:15 -07:00
const ActionsContainer = styled(Flex)``;
2023-05-19 00:21:36 -07:00
interface LibraryCommandItemProps {
handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void;
id: string;
imageUrl: string | null;
itemType: LibraryItem;
subtitle?: string;
title?: string;
}
export const LibraryCommandItem = ({
id,
imageUrl,
subtitle,
title,
itemType,
handlePlayQueueAdd,
}: LibraryCommandItemProps) => {
let Placeholder = RiAlbumFill;
switch (itemType) {
case LibraryItem.ALBUM:
Placeholder = RiAlbumFill;
break;
case LibraryItem.ARTIST:
Placeholder = RiUserVoiceFill;
break;
case LibraryItem.ALBUM_ARTIST:
Placeholder = RiUserVoiceFill;
break;
case LibraryItem.PLAYLIST:
Placeholder = RiPlayListFill;
break;
default:
Placeholder = RiAlbumFill;
break;
}
const handlePlay = useCallback(
2023-05-20 14:55:08 -07:00
(e: MouseEvent, id: string, playType: Play) => {
2023-05-19 00:21:36 -07:00
e.stopPropagation();
handlePlayQueueAdd?.({
byItemType: {
2023-05-20 23:22:43 -07:00
id: [id],
2023-05-19 00:21:36 -07:00
type: itemType,
},
2023-05-20 14:55:08 -07:00
playType,
2023-05-19 00:21:36 -07:00
});
},
[handlePlayQueueAdd, itemType],
);
return (
2023-05-19 22:24:15 -07:00
<Item
2023-05-19 00:21:36 -07:00
gap="xl"
justify="space-between"
style={{ height: '40px', width: '100%' }}
>
<ItemGrid height={40}>
<ImageWrapper>
{imageUrl ? (
<StyledImage
alt="cover"
height={40}
placeholder="var(--placeholder-bg)"
src={imageUrl}
style={{}}
width={40}
/>
) : (
<Center
style={{
background: 'var(--placeholder-bg)',
borderRadius: 'var(--card-default-radius)',
height: `${40}px`,
width: `${40}px`,
}}
>
<Placeholder
color="var(--placeholder-fg)"
size={35}
/>
</Center>
)}
</ImageWrapper>
<MetadataWrapper>
<Text overflow="hidden">{title}</Text>
<Text
$secondary
overflow="hidden"
>
{subtitle}
</Text>
</MetadataWrapper>
</ItemGrid>
2023-05-19 22:24:15 -07:00
<ActionsContainer
2023-05-19 00:21:36 -07:00
align="center"
gap="sm"
justify="flex-end"
>
<Button
compact
size="md"
tooltip={{ label: 'Play', openDelay: 500 }}
variant="default"
onClick={(e) => handlePlay(e, id, Play.NOW)}
>
<RiPlayFill />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Add to queue', openDelay: 500 }}
variant="default"
onClick={(e) => handlePlay(e, id, Play.LAST)}
>
<RiAddBoxFill />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Play next', openDelay: 500 }}
variant="default"
onClick={(e) => handlePlay(e, id, Play.NEXT)}
>
<RiAddCircleFill />
</Button>
2023-05-19 22:24:15 -07:00
</ActionsContainer>
</Item>
2023-05-19 00:21:36 -07:00
);
};