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
|
|
|
);
|
|
|
|
|
};
|