import clsx from 'clsx'; import { CSSProperties, useState } from 'react'; import { Link } from 'react-router'; import styles from './title-combined-column.module.css'; import { ItemImage } from '/@/renderer/components/item-image/item-image'; import { getTitlePath } from '/@/renderer/components/item-list/helpers/get-title-path'; import { ColumnNullFallback, ColumnSkeletonVariable, ItemTableListInnerColumn, TableColumnContainer, } from '/@/renderer/components/item-list/item-table-list/item-table-list-column'; import { useIsActiveRow } from '/@/renderer/components/item-list/item-table-list/item-table-list-context'; import { JoinedArtists } from '/@/renderer/features/albums/components/joined-artists'; 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 { ExplicitIndicator } from '/@/shared/components/explicit-indicator/explicit-indicator'; import { ExternalSongIndicator } from '/@/shared/components/external-song-indicator/external-song-indicator'; import { Icon } from '/@/shared/components/icon/icon'; import { Text } from '/@/shared/components/text/text'; import { Folder, LibraryItem, QueueSong, ServerType } from '/@/shared/types/domain-types'; import { Play } from '/@/shared/types/types'; export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => { const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex]; const row: object | undefined = (rowItem as any)?.id; const item = rowItem as any; const internalState = (props as any).internalState; const playButtonBehavior = usePlayButtonBehavior(); const [isHovered, setIsHovered] = useState(false); const handlePlay = (playType: Play, event: React.MouseEvent) => { if (!item) { return; } // For SONG items, use double click behavior if ( (props.itemType === LibraryItem.SONG || props.itemType === LibraryItem.PLAYLIST_SONG || item._itemType === LibraryItem.SONG) && props.controls?.onDoubleClick ) { // Calculate the index based on rowIndex, accounting for header if enabled const isHeaderEnabled = !!props.enableHeader; const index = isHeaderEnabled ? props.rowIndex - 1 : props.rowIndex; props.controls.onDoubleClick({ event: null, index, internalState, item, itemType: props.itemType, meta: { playType, }, }); return; } // For other item types, use regular onPlay if (!props.controls?.onPlay) { return; } props.controls.onPlay({ event, item, itemType: props.itemType, playType, }); }; if (item && 'name' in item && 'imageUrl' in item && 'artists' in item) { const rowHeight = props.getRowHeight(props.rowIndex, props); const path = getTitlePath(props.itemType, (rowItem as any).id as string); const align = props.columns[props.columnIndex]?.align || 'start'; const item = rowItem as any; const titleLinkProps = path ? { component: Link, isLink: true, state: { item }, to: path, } : {}; return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {isHovered && (
handlePlay(playButtonBehavior, e)} onLongPress={(e) => handlePlay(LONG_PRESS_PLAY_BEHAVIOR[playButtonBehavior], e) } />
)}
{item.name as string}
); } if (row === null) { return ; } return ; }; export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) => { const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex]; const row: object | undefined = rowItem as any; const song = rowItem as QueueSong; const item = rowItem as any; const internalState = (props as any).internalState; const playButtonBehavior = usePlayButtonBehavior(); const [isHovered, setIsHovered] = useState(false); const isActive = useIsActiveRow(song?.id, song?._uniqueId); const handlePlay = (playType: Play, event: React.MouseEvent) => { if (!item) { return; } // For SONG items, use double click behavior if ( (props.itemType === LibraryItem.SONG || props.itemType === LibraryItem.PLAYLIST_SONG || item._itemType === LibraryItem.SONG) && props.controls?.onDoubleClick ) { // Calculate the index based on rowIndex, accounting for header if enabled const isHeaderEnabled = !!props.enableHeader; const index = isHeaderEnabled ? props.rowIndex - 1 : props.rowIndex; props.controls.onDoubleClick({ event: null, index, internalState, item, itemType: props.itemType, meta: { playType, }, }); return; } // For other item types, use regular onPlay if (!props.controls?.onPlay) { return; } props.controls.onPlay({ event, item, itemType: props.itemType, playType, }); }; if (row && 'name' in row && 'imageUrl' in row && 'artists' in row) { const rowHeight = props.getRowHeight(props.rowIndex, props); const path = getTitlePath(props.itemType, (rowItem as any).id as string); const align = props.columns[props.columnIndex]?.align || 'start'; const item = rowItem as any; const titleLinkProps = path ? { component: Link, isLink: true, state: { item }, to: path, } : {}; return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {isHovered && (
handlePlay(playButtonBehavior, e)} onLongPress={(e) => handlePlay(LONG_PRESS_PLAY_BEHAVIOR[playButtonBehavior], e) } />
)}
{row.name as string} {song?.trackSubtitle && props.itemType !== LibraryItem.QUEUE_SONG && ( {' ('} {song.trackSubtitle} {')'} )}
); } if ((rowItem as unknown as Folder)?._itemType === LibraryItem.FOLDER) { const rowHeight = props.getRowHeight(props.rowIndex, props); const path = getTitlePath(props.itemType, (rowItem as any).id as string); const item = rowItem as any; const textStyles = isActive ? { color: 'var(--theme-colors-primary)' } : {}; const titleLinkProps = path ? { component: Link, isLink: true, state: { item }, to: path, } : {}; const title = (rowItem as unknown as Folder)?.name; return ( {title} ); } if (row === null) { return ; } return ; }; const TitleCombinedColumnBase = (props: ItemTableListInnerColumn) => { const { itemType } = props; switch (itemType) { case LibraryItem.FOLDER: case LibraryItem.PLAYLIST_SONG: case LibraryItem.QUEUE_SONG: case LibraryItem.SONG: return ; default: return ; } }; export const TitleCombinedColumn = TitleCombinedColumnBase;