diff --git a/src/renderer/components/item-list/helpers/item-list-controls.ts b/src/renderer/components/item-list/helpers/item-list-controls.ts index 946667215..458063589 100644 --- a/src/renderer/components/item-list/helpers/item-list-controls.ts +++ b/src/renderer/components/item-list/helpers/item-list-controls.ts @@ -242,11 +242,13 @@ export const useDefaultItemListControls = (args?: UseDefaultItemListControlsArgs } const playType = (meta?.playType as Play) || Play.NOW; + const singleSongOnly = meta?.singleSongOnly === true; - // For NEXT, LAST, NEXT_SHUFFLE, and LAST_SHUFFLE, only add the clicked song - // For NOW and SHUFFLE, add a range of songs around the clicked song + // For single-song actions (e.g. image play button), or NEXT/LAST/..., only add the clicked song + // For row double-click with NOW/SHUFFLE, add a range of songs around the clicked song let songsToAdd: Song[]; if ( + singleSongOnly || playType === Play.NEXT || playType === Play.LAST || playType === Play.NEXT_SHUFFLE || diff --git a/src/renderer/components/item-list/item-detail-list/columns/image-column.module.css b/src/renderer/components/item-list/item-detail-list/columns/image-column.module.css index e9fe65ef1..3256d3d15 100644 --- a/src/renderer/components/item-list/item-detail-list/columns/image-column.module.css +++ b/src/renderer/components/item-list/item-detail-list/columns/image-column.module.css @@ -1,3 +1,12 @@ +.image-container { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; +} + .compact-container { flex: 1 1 0; width: 100%; @@ -12,6 +21,25 @@ border-radius: var(--theme-radius-md); } +.play-button-overlay { + position: absolute; + top: 50%; + left: 50%; + z-index: 10; + opacity: 0.6; + transform: translate(-50%, -50%); + transition: opacity 0.2s ease-in-out; +} + +.play-button-overlay:hover { + opacity: 1; +} + +.play-button-overlay button { + width: 24px; + height: 24px; +} + .compact-image { display: block; width: 100%; diff --git a/src/renderer/components/item-list/item-detail-list/columns/image-column.tsx b/src/renderer/components/item-list/item-detail-list/columns/image-column.tsx index 046e4a5a1..96ce777b7 100644 --- a/src/renderer/components/item-list/item-detail-list/columns/image-column.tsx +++ b/src/renderer/components/item-list/item-detail-list/columns/image-column.tsx @@ -1,17 +1,71 @@ +import clsx from 'clsx'; +import { useState } from 'react'; + import styles from './image-column.module.css'; import { ItemDetailListCellProps } from './types'; import { ItemImage } from '/@/renderer/components/item-image/item-image'; +import { PlayButton } from '/@/renderer/features/shared/components/play-button'; +import { + LONG_PRESS_PLAY_BEHAVIOR, + PlayTooltip, +} from '/@/renderer/features/shared/components/play-button-group'; +import { usePlayButtonBehavior } from '/@/renderer/store'; import { LibraryItem } from '/@/shared/types/domain-types'; +import { Play } from '/@/shared/types/types'; -export const ImageColumn = ({ song }: ItemDetailListCellProps) => ( - -); +export const ImageColumn = ({ + controls, + internalState, + rowIndex = 0, + song, +}: ItemDetailListCellProps) => { + const playButtonBehavior = usePlayButtonBehavior(); + const [isHovered, setIsHovered] = useState(false); + + const handlePlay = (playType: Play) => { + if (!song || !controls?.onDoubleClick) { + return; + } + + controls.onDoubleClick({ + event: null, + index: rowIndex, + internalState, + item: song, + itemType: LibraryItem.SONG, + meta: { playType, singleSongOnly: true }, + }); + }; + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > + + {isHovered && ( +
+ + handlePlay(playButtonBehavior)} + onLongPress={() => + handlePlay(LONG_PRESS_PLAY_BEHAVIOR[playButtonBehavior]) + } + /> + +
+ )} +
+ ); +}; diff --git a/src/renderer/components/item-list/item-table-list/columns/image-column.tsx b/src/renderer/components/item-list/item-table-list/columns/image-column.tsx index 4b8b36670..d38d41ae7 100644 --- a/src/renderer/components/item-list/item-table-list/columns/image-column.tsx +++ b/src/renderer/components/item-list/item-table-list/columns/image-column.tsx @@ -54,6 +54,7 @@ const ImageColumnBase = (props: ItemTableListInnerColumn) => { itemType: props.itemType, meta: { playType, + singleSongOnly: true, }, }); return; diff --git a/src/renderer/components/item-list/item-table-list/columns/title-combined-column.tsx b/src/renderer/components/item-list/item-table-list/columns/title-combined-column.tsx index 2acb9e032..2dea51347 100644 --- a/src/renderer/components/item-list/item-table-list/columns/title-combined-column.tsx +++ b/src/renderer/components/item-list/item-table-list/columns/title-combined-column.tsx @@ -58,6 +58,7 @@ export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => { itemType: props.itemType, meta: { playType, + singleSongOnly: true, }, }); return; @@ -200,6 +201,7 @@ export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) => itemType: props.itemType, meta: { playType, + singleSongOnly: true, }, }); return;