add image column playback, revert to single song playback on song list click

This commit is contained in:
jeffvli
2026-02-09 21:42:59 -08:00
parent 946d9d92f9
commit b44e16708d
5 changed files with 100 additions and 13 deletions
@@ -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 ||
@@ -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%;
@@ -1,10 +1,49 @@
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 (
<div
className={styles.imageContainer}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<ItemImage
className={styles.compactImage}
containerClassName={styles.compactContainer}
@@ -14,4 +53,19 @@ export const ImageColumn = ({ song }: ItemDetailListCellProps) => (
serverId={song._serverId}
type="table"
/>
);
{isHovered && (
<div className={clsx(styles.playButtonOverlay)}>
<PlayTooltip disabled={false} type={playButtonBehavior}>
<PlayButton
fill
onClick={() => handlePlay(playButtonBehavior)}
onLongPress={() =>
handlePlay(LONG_PRESS_PLAY_BEHAVIOR[playButtonBehavior])
}
/>
</PlayTooltip>
</div>
)}
</div>
);
};
@@ -54,6 +54,7 @@ const ImageColumnBase = (props: ItemTableListInnerColumn) => {
itemType: props.itemType,
meta: {
playType,
singleSongOnly: true,
},
});
return;
@@ -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;