import { MutableRefObject, useMemo, useCallback } from 'react'; import { ColDef, GridReadyEvent, RowDoubleClickedEvent, IDatasource, } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import { Stack } from '@mantine/core'; import { generatePath, useNavigate } from 'react-router'; import { useParams, useSearchParams } from 'react-router-dom'; import { LibraryItem, QueueSong } from '/@/renderer/api/types'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { VirtualTable, getColumnDefs } from '/@/renderer/components/virtual-table'; import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { ALBUM_CONTEXT_MENU_ITEMS, ARTIST_CONTEXT_MENU_ITEMS, SONG_CONTEXT_MENU_ITEMS, } from '/@/renderer/features/context-menu/context-menu-items'; import { usePlayQueueAdd } from '/@/renderer/features/player'; import { AppRoute } from '../../../router/routes'; import { useCurrentServer, useSongListStore, usePlayButtonBehavior, useAlbumListStore, useAlbumArtistListStore, } from '/@/renderer/store'; interface SearchContentProps { getDatasource: (searchQuery: string, itemType: LibraryItem) => IDatasource | undefined; tableRef: MutableRefObject; } export const SearchContent = ({ tableRef, getDatasource }: SearchContentProps) => { const navigate = useNavigate(); const server = useCurrentServer(); const { itemType } = useParams() as { itemType: LibraryItem }; const [searchParams] = useSearchParams(); const songListStore = useSongListStore(); const albumListStore = useAlbumListStore(); const albumArtistListStore = useAlbumArtistListStore(); const handlePlayQueueAdd = usePlayQueueAdd(); const playButtonBehavior = usePlayButtonBehavior(); const getTable = useCallback( (itemType: string) => { switch (itemType) { case LibraryItem.SONG: return songListStore.table; case LibraryItem.ALBUM: return albumListStore.table; case LibraryItem.ALBUM_ARTIST: return albumArtistListStore.table; default: return undefined; } }, [albumArtistListStore.table, albumListStore.table, songListStore.table], ); const table = getTable(itemType)!; const columnDefs: ColDef[] = useMemo(() => getColumnDefs(table.columns), [table.columns]); const onGridReady = useCallback( (params: GridReadyEvent) => { const datasource = getDatasource(searchParams.get('query') || '', itemType); if (!datasource) return; params.api.setDatasource(datasource); params.api.ensureIndexVisible(table.scrollOffset, 'top'); }, [getDatasource, itemType, searchParams, table.scrollOffset], ); const handleGridSizeChange = () => { if (table.autoFit) { tableRef?.current?.api.sizeColumnsToFit(); } }; const contextMenuItems = () => { switch (itemType) { case LibraryItem.ALBUM: return ALBUM_CONTEXT_MENU_ITEMS; case LibraryItem.ALBUM_ARTIST: return ARTIST_CONTEXT_MENU_ITEMS; case LibraryItem.SONG: return SONG_CONTEXT_MENU_ITEMS; default: return []; } }; const handleContextMenu = useHandleTableContextMenu(itemType, contextMenuItems()); const handleRowDoubleClick = (e: RowDoubleClickedEvent) => { if (!e.data) return; switch (itemType) { case LibraryItem.ALBUM: navigate(generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, { albumId: e.data.id })); break; case LibraryItem.ALBUM_ARTIST: navigate( generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, { albumArtistId: e.data.id, }), ); break; case LibraryItem.SONG: handlePlayQueueAdd?.({ byData: [e.data], playType: playButtonBehavior, }); break; } }; return ( data.data.id} infiniteInitialRowCount={25} rowBuffer={20} rowHeight={table.rowHeight || 40} rowModelType="infinite" rowSelection="multiple" onCellContextMenu={handleContextMenu} onGridReady={onGridReady} onGridSizeChanged={handleGridSizeChange} onRowDoubleClicked={handleRowDoubleClick} /> ); };