Use search params for artist-specific lists

This commit is contained in:
jeffvli 2023-07-22 05:05:33 -07:00
parent 8a367b00a3
commit 3aec139f58
4 changed files with 89 additions and 30 deletions

View file

@ -20,8 +20,9 @@ import { getColumnDefs, VirtualTableProps } from '/@/renderer/components/virtual
import { SetContextMenuItems, useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { SetContextMenuItems, useHandleTableContextMenu } from '/@/renderer/features/context-menu';
import { AppRoute } from '/@/renderer/router/routes'; import { AppRoute } from '/@/renderer/router/routes';
import { useListStoreActions } from '/@/renderer/store'; import { useListStoreActions } from '/@/renderer/store';
import { ListDisplayType, ServerListItem } from '/@/renderer/types'; import { ListDisplayType, ServerListItem, TablePagination } from '/@/renderer/types';
import { useListStoreByKey } from '../../../store/list.store'; import { useSearchParams } from 'react-router-dom';
import { ListKey, useListStoreByKey } from '../../../store/list.store';
export type AgGridFetchFn<TResponse, TFilter> = ( export type AgGridFetchFn<TResponse, TFilter> = (
args: { filter: TFilter; limit: number; startIndex: number }, args: { filter: TFilter; limit: number; startIndex: number },
@ -31,6 +32,7 @@ export type AgGridFetchFn<TResponse, TFilter> = (
interface UseAgGridProps<TFilter> { interface UseAgGridProps<TFilter> {
contextMenu: SetContextMenuItems; contextMenu: SetContextMenuItems;
customFilters?: Partial<TFilter>; customFilters?: Partial<TFilter>;
isSearchParams?: boolean;
itemCount?: number; itemCount?: number;
itemType: LibraryItem; itemType: LibraryItem;
pageKey: string; pageKey: string;
@ -46,11 +48,26 @@ export const useVirtualTable = <TFilter>({
contextMenu, contextMenu,
itemCount, itemCount,
customFilters, customFilters,
isSearchParams,
}: UseAgGridProps<TFilter>) => { }: UseAgGridProps<TFilter>) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const navigate = useNavigate(); const navigate = useNavigate();
const { setTable, setTablePagination } = useListStoreActions(); const { setTable, setTablePagination } = useListStoreActions();
const properties = useListStoreByKey({ filter: customFilters, key: pageKey }); const properties = useListStoreByKey({ filter: customFilters, key: pageKey });
const [searchParams, setSearchParams] = useSearchParams();
const scrollOffset = searchParams.get('scrollOffset');
const pagination = useMemo(() => {
return {
currentPage: Number(searchParams.get('currentPage')),
itemsPerPage: Number(searchParams.get('itemsPerPage')),
totalItems: Number(searchParams.get('totalItems')),
totalPages: Number(searchParams.get('totalPages')),
};
}, [searchParams]);
const initialTableIndex =
Number(isSearchParams ? scrollOffset : properties.table.scrollOffset) || 0;
const isPaginationEnabled = properties.display === ListDisplayType.TABLE_PAGINATED; const isPaginationEnabled = properties.display === ListDisplayType.TABLE_PAGINATED;
@ -149,16 +166,26 @@ export const useVirtualTable = <TFilter>({
}; };
params.api.setDatasource(dataSource); params.api.setDatasource(dataSource);
params.api.ensureIndexVisible(properties.table.scrollOffset || 0, 'top'); params.api.ensureIndexVisible(initialTableIndex, 'top');
}, },
[ [initialTableIndex, queryKeyFn, server, properties.filter, queryClient, queryFn],
properties.table.scrollOffset, );
properties.filter,
queryKeyFn, const setParamsTablePagination = useCallback(
server, (args: { data: Partial<TablePagination>; key: ListKey }) => {
queryClient, const { data } = args;
queryFn,
], setSearchParams(
{
...(data.currentPage && { currentPage: String(data.currentPage) }),
...(data.itemsPerPage && { itemsPerPage: String(data.itemsPerPage) }),
...(data.totalItems && { totalItems: String(data.totalItems) }),
...(data.totalPages && { totalPages: String(data.totalPages) }),
},
{ replace: true },
);
},
[setSearchParams],
); );
const onPaginationChanged = useCallback( const onPaginationChanged = useCallback(
@ -175,6 +202,16 @@ export const useVirtualTable = <TFilter>({
console.log(err); console.log(err);
} }
if (isSearchParams) {
setSearchParams(
{
itemsPerPage: String(event.api.paginationGetPageSize()),
totalItems: String(event.api.paginationGetRowCount()),
totalPages: String(event.api.paginationGetTotalPages() + 1),
},
{ replace: true },
);
} else {
setTablePagination({ setTablePagination({
data: { data: {
itemsPerPage: event.api.paginationGetPageSize(), itemsPerPage: event.api.paginationGetPageSize(),
@ -183,13 +220,16 @@ export const useVirtualTable = <TFilter>({
}, },
key: pageKey, key: pageKey,
}); });
}
}, },
[ [
isPaginationEnabled, isPaginationEnabled,
setTablePagination, isSearchParams,
pageKey,
properties.table.pagination.currentPage, properties.table.pagination.currentPage,
properties.table.pagination.itemsPerPage, properties.table.pagination.itemsPerPage,
setSearchParams,
setTablePagination,
pageKey,
], ],
); );
@ -223,7 +263,12 @@ export const useVirtualTable = <TFilter>({
const onBodyScrollEnd = (e: BodyScrollEvent) => { const onBodyScrollEnd = (e: BodyScrollEvent) => {
const scrollOffset = Number((e.top / properties.table.rowHeight).toFixed(0)); const scrollOffset = Number((e.top / properties.table.rowHeight).toFixed(0));
if (isSearchParams) {
setSearchParams({ scrollOffset: String(scrollOffset) }, { replace: true });
} else {
setTable({ data: { scrollOffset }, key: pageKey }); setTable({ data: { scrollOffset }, key: pageKey });
}
}; };
const onCellContextMenu = useHandleTableContextMenu(itemType, contextMenu); const onCellContextMenu = useHandleTableContextMenu(itemType, contextMenu);
@ -245,8 +290,8 @@ export const useVirtualTable = <TFilter>({
paginationProps: isPaginationEnabled paginationProps: isPaginationEnabled
? { ? {
pageKey, pageKey,
pagination: properties.table.pagination, pagination: isSearchParams ? pagination : properties.table.pagination,
setPagination: setTablePagination, setPagination: isSearchParams ? setParamsTablePagination : setTablePagination,
} }
: undefined, : undefined,
rowBuffer: 20, rowBuffer: 20,
@ -256,11 +301,14 @@ export const useVirtualTable = <TFilter>({
}; };
}, [ }, [
isPaginationEnabled, isPaginationEnabled,
isSearchParams,
itemCount, itemCount,
pageKey, pageKey,
pagination,
properties.table.autoFit, properties.table.autoFit,
properties.table.pagination, properties.table.pagination,
properties.table.rowHeight, properties.table.rowHeight,
setParamsTablePagination,
setTablePagination, setTablePagination,
]); ]);

View file

@ -1,5 +1,6 @@
import { QueryKey, useQueryClient } from '@tanstack/react-query'; import { QueryKey, useQueryClient } from '@tanstack/react-query';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import AutoSizer from 'react-virtualized-auto-sizer'; import AutoSizer from 'react-virtualized-auto-sizer';
import { ListOnScrollProps } from 'react-window'; import { ListOnScrollProps } from 'react-window';
import { controller } from '/@/renderer/api/controller'; import { controller } from '/@/renderer/api/controller';
@ -27,10 +28,14 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const server = useCurrentServer(); const server = useCurrentServer();
const handlePlayQueueAdd = usePlayQueueAdd(); const handlePlayQueueAdd = usePlayQueueAdd();
const { pageKey, customFilters } = useListContext(); const { pageKey, customFilters, id } = useListContext();
const { grid, display, filter } = useListStoreByKey({ key: pageKey }); const { grid, display, filter } = useListStoreByKey({ key: pageKey });
const { setGrid } = useListStoreActions(); const { setGrid } = useListStoreActions();
const [searchParams, setSearchParams] = useSearchParams();
const scrollOffset = searchParams.get('scrollOffset');
const initialScrollOffset = Number(id ? scrollOffset : grid?.scrollOffset) || 0;
const createFavoriteMutation = useCreateFavorite({}); const createFavoriteMutation = useCreateFavorite({});
const deleteFavoriteMutation = useDeleteFavorite({}); const deleteFavoriteMutation = useDeleteFavorite({});
@ -124,9 +129,13 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
const handleGridScroll = useCallback( const handleGridScroll = useCallback(
(e: ListOnScrollProps) => { (e: ListOnScrollProps) => {
if (id) {
setSearchParams({ scrollOffset: String(e.scrollOffset) });
} else {
setGrid({ data: { scrollOffset: e.scrollOffset }, key: pageKey }); setGrid({ data: { scrollOffset: e.scrollOffset }, key: pageKey });
}
}, },
[pageKey, setGrid], [id, pageKey, setGrid, setSearchParams],
); );
const fetchInitialData = useCallback(() => { const fetchInitialData = useCallback(() => {
@ -207,7 +216,7 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
handleFavorite={handleFavorite} handleFavorite={handleFavorite}
handlePlayQueueAdd={handlePlayQueueAdd} handlePlayQueueAdd={handlePlayQueueAdd}
height={height} height={height}
initialScrollOffset={grid?.scrollOffset || 0} initialScrollOffset={initialScrollOffset}
itemCount={itemCount || 0} itemCount={itemCount || 0}
itemGap={20} itemGap={20}
itemSize={grid?.itemsPerRow || 5} itemSize={grid?.itemsPerRow || 5}

View file

@ -8,11 +8,12 @@ import { useCurrentServer } from '/@/renderer/store';
export const AlbumListTableView = ({ tableRef, itemCount }: any) => { export const AlbumListTableView = ({ tableRef, itemCount }: any) => {
const server = useCurrentServer(); const server = useCurrentServer();
const { pageKey, customFilters } = useListContext(); const { pageKey, customFilters, id } = useListContext();
const tableProps = useVirtualTable({ const tableProps = useVirtualTable({
contextMenu: ALBUM_CONTEXT_MENU_ITEMS, contextMenu: ALBUM_CONTEXT_MENU_ITEMS,
customFilters, customFilters,
isSearchParams: Boolean(id),
itemCount, itemCount,
itemType: LibraryItem.ALBUM, itemType: LibraryItem.ALBUM,
pageKey, pageKey,

View file

@ -17,13 +17,14 @@ interface SongListTableViewProps {
export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProps) => { export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProps) => {
const server = useCurrentServer(); const server = useCurrentServer();
const { pageKey, handlePlay, customFilters } = useListContext(); const { pageKey, id, handlePlay, customFilters } = useListContext();
const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); const { rowClassRules } = useCurrentSongRowStyles({ tableRef });
const tableProps = useVirtualTable<SongListQuery>({ const tableProps = useVirtualTable<SongListQuery>({
contextMenu: SONG_CONTEXT_MENU_ITEMS, contextMenu: SONG_CONTEXT_MENU_ITEMS,
customFilters, customFilters,
isSearchParams: Boolean(id),
itemCount, itemCount,
itemType: LibraryItem.SONG, itemType: LibraryItem.SONG,
pageKey, pageKey,