Update search list implementation

This commit is contained in:
jeffvli 2023-07-20 00:37:05 -07:00
parent 6dd9333dbb
commit 287f1dc0e1
3 changed files with 54 additions and 264 deletions

View file

@ -1,86 +1,36 @@
import { MutableRefObject, useMemo, useCallback } from 'react';
import {
ColDef,
GridReadyEvent,
RowDoubleClickedEvent,
IDatasource,
} from '@ag-grid-community/core';
import { RowDoubleClickedEvent } from '@ag-grid-community/core';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { Stack } from '@mantine/core';
import { MutableRefObject } from 'react';
import { generatePath, useNavigate } from 'react-router';
import { useParams, useSearchParams } from 'react-router-dom';
import { AppRoute } from '../../../router/routes';
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 { VirtualTable } from '/@/renderer/components/virtual-table';
import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles';
import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-virtual-table';
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';
import { useCurrentServer, usePlayButtonBehavior } from '/@/renderer/store';
interface SearchContentProps {
getDatasource: (searchQuery: string, itemType: LibraryItem) => IDatasource | undefined;
tableRef: MutableRefObject<AgGridReactType | null>;
}
export const SearchContent = ({ tableRef, getDatasource }: SearchContentProps) => {
export const SearchContent = ({ tableRef }: 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 pageKey = itemType;
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:
@ -94,8 +44,6 @@ export const SearchContent = ({ tableRef, getDatasource }: SearchContentProps) =
}
};
const handleContextMenu = useHandleTableContextMenu(itemType, contextMenuItems());
const handleRowDoubleClick = (e: RowDoubleClickedEvent<QueueSong>) => {
if (!e.data) return;
switch (itemType) {
@ -118,39 +66,35 @@ export const SearchContent = ({ tableRef, getDatasource }: SearchContentProps) =
}
};
const customFilters = {
searchTerm: searchParams.get('query') || '',
};
const { rowClassRules } = useCurrentSongRowStyles({ tableRef });
const tableProps = useVirtualTable({
contextMenu: contextMenuItems(),
customFilters,
itemType,
pageKey,
server,
tableRef,
});
return (
<Stack
h="100%"
spacing={0}
>
<VirtualGridAutoSizerContainer>
<VirtualTable
// https://github.com/ag-grid/ag-grid/issues/5284
// Key is used to force remount of table when display, rowHeight, or server changes
key={`table-${itemType}-${table.rowHeight}-${server?.id}`}
ref={tableRef}
alwaysShowHorizontalScroll
suppressRowDrag
autoFitColumns={table.autoFit}
blockLoadDebounceMillis={200}
cacheBlockSize={25}
cacheOverflowSize={1}
columnDefs={columnDefs}
context={{
query: searchParams.get('query'),
}}
getRowId={(data) => data.data.id}
infiniteInitialRowCount={25}
rowBuffer={20}
rowHeight={table.rowHeight || 40}
rowModelType="infinite"
rowSelection="multiple"
onCellContextMenu={handleContextMenu}
onGridReady={onGridReady}
onGridSizeChanged={handleGridSizeChange}
onRowDoubleClicked={handleRowDoubleClick}
/>
</VirtualGridAutoSizerContainer>
</Stack>
<VirtualGridAutoSizerContainer>
<VirtualTable
{...tableProps}
key={`table-${itemType}-${tableProps.rowHeight}-${server?.id}`}
ref={tableRef}
context={{
query: searchParams.get('query'),
}}
getRowId={(data) => data.data.id}
infiniteInitialRowCount={25}
rowClassRules={rowClassRules}
onRowDoubleClicked={handleRowDoubleClick}
/>
</VirtualGridAutoSizerContainer>
);
};