Use search params for artist-specific lists
This commit is contained in:
parent
8a367b00a3
commit
3aec139f58
4 changed files with 89 additions and 30 deletions
|
@ -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,21 +202,34 @@ export const useVirtualTable = <TFilter>({
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTablePagination({
|
if (isSearchParams) {
|
||||||
data: {
|
setSearchParams(
|
||||||
itemsPerPage: event.api.paginationGetPageSize(),
|
{
|
||||||
totalItems: event.api.paginationGetRowCount(),
|
itemsPerPage: String(event.api.paginationGetPageSize()),
|
||||||
totalPages: event.api.paginationGetTotalPages() + 1,
|
totalItems: String(event.api.paginationGetRowCount()),
|
||||||
},
|
totalPages: String(event.api.paginationGetTotalPages() + 1),
|
||||||
key: pageKey,
|
},
|
||||||
});
|
{ replace: true },
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setTablePagination({
|
||||||
|
data: {
|
||||||
|
itemsPerPage: event.api.paginationGetPageSize(),
|
||||||
|
totalItems: event.api.paginationGetRowCount(),
|
||||||
|
totalPages: event.api.paginationGetTotalPages() + 1,
|
||||||
|
},
|
||||||
|
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));
|
||||||
setTable({ data: { scrollOffset }, key: pageKey });
|
|
||||||
|
if (isSearchParams) {
|
||||||
|
setSearchParams({ scrollOffset: String(scrollOffset) }, { replace: true });
|
||||||
|
} else {
|
||||||
|
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,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -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) => {
|
||||||
setGrid({ data: { scrollOffset: e.scrollOffset }, key: pageKey });
|
if (id) {
|
||||||
|
setSearchParams({ scrollOffset: String(e.scrollOffset) });
|
||||||
|
} else {
|
||||||
|
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}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Reference in a new issue