import { forwardRef, useMemo } from 'react'; import { useEffect } from 'react'; import { useItemListColumnReorder } from '/@/renderer/components/item-list/helpers/use-item-list-column-reorder'; import { useItemListColumnResize } from '/@/renderer/components/item-list/helpers/use-item-list-column-resize'; import { useItemListScrollPersist } from '/@/renderer/components/item-list/helpers/use-item-list-scroll-persist'; import { ItemListWithPagination } from '/@/renderer/components/item-list/item-list-pagination/item-list-pagination'; import { ItemTableList } from '/@/renderer/components/item-list/item-table-list/item-table-list'; import { ItemTableListColumn } from '/@/renderer/components/item-list/item-table-list/item-table-list-column'; import { ItemControls, ItemListTableComponentProps } from '/@/renderer/components/item-list/types'; import { useListContext } from '/@/renderer/context/list-context'; import { usePlayer } from '/@/renderer/features/player/context/player-context'; import { usePlaylistSongListFilters } from '/@/renderer/features/playlists/hooks/use-playlist-song-list-filters'; import { useSearchTermFilter } from '/@/renderer/features/shared/hooks/use-search-term-filter'; import { searchLibraryItems } from '/@/renderer/features/shared/utils'; import { usePlayerSong } from '/@/renderer/store'; import { sortSongList } from '/@/shared/api/utils'; import { LibraryItem, PlaylistSongListQuery, PlaylistSongListResponse, Song, } from '/@/shared/types/domain-types'; import { ItemListKey, Play, TableColumn } from '/@/shared/types/types'; interface PlaylistDetailSongListTableProps extends Omit, 'query'> { currentPage?: number; data: PlaylistSongListResponse; items?: Song[]; itemsPerPage?: number; onPageChange?: (page: number) => void; } export const PlaylistDetailSongListTable = forwardRef( ( { autoFitColumns = false, columns, currentPage, data, enableAlternateRowColors = false, enableHeader = true, enableHorizontalBorders = false, enableRowHoverHighlight = true, enableSelection = true, enableVerticalBorders = false, items: itemsProp, itemsPerPage, onPageChange, saveScrollOffset = true, size = 'default', }, ref, ) => { const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({ enabled: saveScrollOffset, }); const { handleColumnReordered } = useItemListColumnReorder({ itemListKey: ItemListKey.PLAYLIST_SONG, }); const { handleColumnResized } = useItemListColumnResize({ itemListKey: ItemListKey.PLAYLIST_SONG, }); const { searchTerm } = useSearchTermFilter(); const { query } = usePlaylistSongListFilters(); const albumGroupingEnabled = columns.some( (col) => col.id === TableColumn.ALBUM_GROUP && col.isEnabled, ); const songDataFromData = useMemo(() => { let list = data?.items || []; if (searchTerm) { list = searchLibraryItems(list, searchTerm, LibraryItem.SONG); return list; } return sortSongList(list, query.sortBy, query.sortOrder); }, [data?.items, searchTerm, query.sortBy, query.sortOrder]); const { setListData } = useListContext(); const songData = itemsProp ?? songDataFromData; useEffect(() => { if (itemsProp == null && setListData) { setListData(songDataFromData); } }, [itemsProp, songDataFromData, setListData]); const player = usePlayer(); const currentSong = usePlayerSong(); const overrideControls: Partial = useMemo(() => { return { onDoubleClick: ({ index, internalState, item, meta }) => { if (!item) { return; } const playType = (meta?.playType as Play) || Play.NOW; const items = internalState?.getData() as Song[]; if (index !== undefined) { player.addToQueueByData(items, playType, item.id); } }, }; }, [player]); const getRowId = useMemo(() => { return (item: unknown) => { if (!item || typeof item !== 'object') { return 'id'; } const song = item as Song; return song.playlistItemId || song.id; }; }, []); const effectiveColumns = useMemo(() => { if (albumGroupingEnabled) return columns; return columns.filter((col) => col.id !== TableColumn.ALBUM_GROUP); }, [columns, albumGroupingEnabled]); const isPaginated = typeof currentPage === 'number' && typeof itemsPerPage === 'number' && typeof onPageChange === 'function'; const totalCount = songData.length; const pageCount = Math.max(1, Math.ceil(totalCount / (itemsPerPage ?? 1))); const paginatedData = useMemo(() => { if (!isPaginated || currentPage == null || itemsPerPage == null) return songData; const start = currentPage * itemsPerPage; return songData.slice(start, start + itemsPerPage); }, [isPaginated, currentPage, itemsPerPage, songData]); const dataToRender = isPaginated ? paginatedData : songData; const table = ( ); if (isPaginated && itemsPerPage != null) { return ( {table} ); } return table; }, ); export const PlaylistDetailSongListEditTable = forwardRef( ( { autoFitColumns = false, columns, data, enableAlternateRowColors = false, enableHeader = true, enableHorizontalBorders = false, enableRowHoverHighlight = true, enableSelection = true, enableVerticalBorders = false, saveScrollOffset = true, size = 'default', }, ref, ) => { const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({ enabled: saveScrollOffset, }); const { handleColumnReordered } = useItemListColumnReorder({ itemListKey: ItemListKey.PLAYLIST_SONG, }); const { handleColumnResized } = useItemListColumnResize({ itemListKey: ItemListKey.PLAYLIST_SONG, }); const player = usePlayer(); const currentSong = usePlayerSong(); const overrideControls: Partial = useMemo(() => { return { onDoubleClick: ({ index, internalState, item, meta }) => { if (!item) { return; } const playType = (meta?.playType as Play) || Play.NOW; const items = internalState?.getData() as Song[]; if (index !== undefined) { player.addToQueueByData(items, playType, item.id); } }, }; }, [player]); const getRowId = useMemo(() => { return (item: unknown) => { if (!item || typeof item !== 'object') { return 'id'; } const song = item as Song; return song.playlistItemId || song.id; }; }, []); return ( ); }, );