mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-01 18:33:33 +00:00
Add play button to song table album cover, like it is in grid (#772)
* Add play button to song table album cover, like it is in grid * Fix: play button caused error for albums and artists tables
This commit is contained in:
parent
a89b6640a9
commit
ad34d8553e
4 changed files with 103 additions and 2 deletions
|
|
@ -0,0 +1,84 @@
|
||||||
|
import React, { MouseEvent } from 'react';
|
||||||
|
import type { UnstyledButtonProps } from '@mantine/core';
|
||||||
|
import { RiPlayFill } from 'react-icons/ri';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Play } from '/@/renderer/types';
|
||||||
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
|
import { LibraryItem } from '/@/renderer/api/types';
|
||||||
|
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||||
|
|
||||||
|
type PlayButtonType = UnstyledButtonProps & React.ComponentPropsWithoutRef<'button'>;
|
||||||
|
|
||||||
|
const PlayButton = styled.button<PlayButtonType>`
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
background-color: rgb(255 255 255);
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
opacity: 0.8;
|
||||||
|
transition: scale 0.1s ease-in-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
scale: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 1;
|
||||||
|
scale: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: rgb(0 0 0);
|
||||||
|
stroke: rgb(0 0 0);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ListConverControlsContainer = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ListCoverControls = ({
|
||||||
|
itemData,
|
||||||
|
itemType,
|
||||||
|
}: {
|
||||||
|
itemData: any;
|
||||||
|
itemType: LibraryItem;
|
||||||
|
}) => {
|
||||||
|
const playButtonBehavior = usePlayButtonBehavior();
|
||||||
|
const handlePlayQueueAdd = usePlayQueueAdd();
|
||||||
|
|
||||||
|
const handlePlay = async (e: MouseEvent<HTMLButtonElement>, playType?: Play) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
handlePlayQueueAdd?.({
|
||||||
|
byItemType: {
|
||||||
|
id: [itemData.id],
|
||||||
|
type: itemType,
|
||||||
|
},
|
||||||
|
playType: playType || playButtonBehavior,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListConverControlsContainer className="card-controls">
|
||||||
|
<PlayButton onClick={handlePlay}>
|
||||||
|
<RiPlayFill size={20} />
|
||||||
|
</PlayButton>
|
||||||
|
</ListConverControlsContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -7,11 +7,12 @@ import { generatePath } from 'react-router';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { SimpleImg } from 'react-simple-img';
|
import { SimpleImg } from 'react-simple-img';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import type { AlbumArtist, Artist } from '/@/renderer/api/types';
|
import { AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||||
import { Text } from '/@/renderer/components/text';
|
import { Text } from '/@/renderer/components/text';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||||
import { SEPARATOR_STRING } from '/@/renderer/api/utils';
|
import { SEPARATOR_STRING } from '/@/renderer/api/utils';
|
||||||
|
import { ListCoverControls } from '/@/renderer/components/virtual-table/cells/combined-title-cell-controls';
|
||||||
|
|
||||||
const CellContainer = styled(motion.div)<{ height: number }>`
|
const CellContainer = styled(motion.div)<{ height: number }>`
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
@ -24,6 +25,16 @@ const CellContainer = styled(motion.div)<{ height: number }>`
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
|
|
||||||
|
.card-controls {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.card-controls {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ImageWrapper = styled.div`
|
const ImageWrapper = styled.div`
|
||||||
|
|
@ -48,7 +59,7 @@ const StyledImage = styled(SimpleImg)`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const CombinedTitleCell = ({ value, rowIndex, node }: ICellRendererParams) => {
|
export const CombinedTitleCell = ({ value, rowIndex, node, context }: ICellRendererParams) => {
|
||||||
const artists = useMemo(() => {
|
const artists = useMemo(() => {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
return value.artists?.length ? value.artists : value.albumArtists;
|
return value.artists?.length ? value.artists : value.albumArtists;
|
||||||
|
|
@ -102,6 +113,10 @@ export const CombinedTitleCell = ({ value, rowIndex, node }: ICellRendererParams
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
)}
|
)}
|
||||||
|
<ListCoverControls
|
||||||
|
itemData={value}
|
||||||
|
itemType={context.itemType}
|
||||||
|
/>
|
||||||
</ImageWrapper>
|
</ImageWrapper>
|
||||||
<MetadataWrapper>
|
<MetadataWrapper>
|
||||||
<Text
|
<Text
|
||||||
|
|
|
||||||
|
|
@ -334,6 +334,7 @@ export const useVirtualTable = <TFilter extends BaseQuery<any>>({
|
||||||
const onCellContextMenu = useHandleTableContextMenu(itemType, contextMenu);
|
const onCellContextMenu = useHandleTableContextMenu(itemType, contextMenu);
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
|
itemType,
|
||||||
onCellContextMenu,
|
onCellContextMenu,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -361,6 +361,7 @@ const tableColumns: { [key: string]: ColDef } = {
|
||||||
? {
|
? {
|
||||||
albumArtists: params.data?.albumArtists,
|
albumArtists: params.data?.albumArtists,
|
||||||
artists: params.data?.artists,
|
artists: params.data?.artists,
|
||||||
|
id: params.data?.id,
|
||||||
imagePlaceholderUrl: params.data?.imagePlaceholderUrl,
|
imagePlaceholderUrl: params.data?.imagePlaceholderUrl,
|
||||||
imageUrl: params.data?.imageUrl,
|
imageUrl: params.data?.imageUrl,
|
||||||
name: params.data?.name,
|
name: params.data?.name,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue