Split key pagination in central handler

This commit is contained in:
jeffvli 2023-07-20 01:55:49 -07:00
parent 1cb0a1d72a
commit 6821735f65
4 changed files with 91 additions and 103 deletions

View file

@ -20,14 +20,21 @@ import type {
} from './types'; } from './types';
export const splitPaginatedQuery = (key: any) => { export const splitPaginatedQuery = (key: any) => {
const { startIndex, limit, ...query } = key; const { startIndex, limit, ...filter } = key;
if (startIndex === undefined || limit === undefined) {
return {
filter,
pagination: {
limit,
startIndex,
},
};
}
return { return {
pagination: { filter,
limit, pagination: undefined,
startIndex,
},
query,
}; };
}; };
@ -45,14 +52,12 @@ export const queryKeys: Record<
if (query) return [serverId, 'albumArtists', 'detail', query] as const; if (query) return [serverId, 'albumArtists', 'detail', query] as const;
return [serverId, 'albumArtists', 'detail'] as const; return [serverId, 'albumArtists', 'detail'] as const;
}, },
list: ( list: (serverId: string, query?: AlbumArtistListQuery) => {
serverId: string, if (query) {
query?: Omit<AlbumArtistListQuery, 'startIndex' | 'limit'>, const { pagination, filter } = splitPaginatedQuery(query);
pagination?: QueryPagination, return [serverId, 'albumArtists', 'list', filter, pagination] as const;
) => { }
if (query && pagination)
return [serverId, 'albumArtists', 'list', query, pagination] as const;
if (query) return [serverId, 'albumArtists', 'list', query] as const;
return [serverId, 'albumArtists', 'list'] as const; return [serverId, 'albumArtists', 'list'] as const;
}, },
root: (serverId: string) => [serverId, 'albumArtists'] as const, root: (serverId: string) => [serverId, 'albumArtists'] as const,
@ -64,13 +69,11 @@ export const queryKeys: Record<
albums: { albums: {
detail: (serverId: string, query?: AlbumDetailQuery) => detail: (serverId: string, query?: AlbumDetailQuery) =>
[serverId, 'albums', 'detail', query] as const, [serverId, 'albums', 'detail', query] as const,
list: ( list: (serverId: string, query?: AlbumListQuery) => {
serverId: string, if (query) {
query?: Omit<AlbumListQuery, 'startIndex' | 'limit'>, const { pagination, filter } = splitPaginatedQuery(query);
pagination?: QueryPagination, return [serverId, 'albums', 'list', filter, pagination] as const;
) => { }
if (query && pagination)
return [serverId, 'albums', 'list', query, pagination] as const;
if (query) return [serverId, 'albums', 'list', query] as const; if (query) return [serverId, 'albums', 'list', query] as const;
return [serverId, 'albums', 'list'] as const; return [serverId, 'albums', 'list'] as const;
}, },
@ -80,14 +83,11 @@ export const queryKeys: Record<
[serverId, 'albums', 'songs', query] as const, [serverId, 'albums', 'songs', query] as const,
}, },
artists: { artists: {
list: ( list: (serverId: string, query?: ArtistListQuery) => {
serverId: string, if (query) {
query?: Omit<ArtistListQuery, 'startIndex' | 'limit'>, const { pagination, filter } = splitPaginatedQuery(query);
pagination?: QueryPagination, return [serverId, 'artists', 'list', filter, pagination] as const;
) => { }
if (query && pagination)
return [serverId, 'artists', 'list', query, pagination] as const;
if (query) return [serverId, 'artists', 'list', query] as const;
return [serverId, 'artists', 'list'] as const; return [serverId, 'artists', 'list'] as const;
}, },
root: (serverId: string) => [serverId, 'artists'] as const, root: (serverId: string) => [serverId, 'artists'] as const,
@ -100,26 +100,19 @@ export const queryKeys: Record<
list: (serverId: string) => [serverId, 'musicFolders', 'list'] as const, list: (serverId: string) => [serverId, 'musicFolders', 'list'] as const,
}, },
playlists: { playlists: {
detail: ( detail: (serverId: string, id?: string, query?: PlaylistDetailQuery) => {
serverId: string, if (query) {
id?: string, const { pagination, filter } = splitPaginatedQuery(query);
query?: Omit<PlaylistDetailQuery, 'startIndex' | 'limit'>, return [serverId, 'playlists', id, 'detail', filter, pagination] as const;
pagination?: QueryPagination, }
) => {
if (query && pagination)
return [serverId, 'playlists', id, 'detail', query, pagination] as const;
if (query) return [serverId, 'playlists', id, 'detail', query] as const;
if (id) return [serverId, 'playlists', id, 'detail'] as const; if (id) return [serverId, 'playlists', id, 'detail'] as const;
return [serverId, 'playlists', 'detail'] as const; return [serverId, 'playlists', 'detail'] as const;
}, },
detailSongList: ( detailSongList: (serverId: string, id: string, query?: PlaylistSongListQuery) => {
serverId: string, if (query) {
id: string, const { pagination, filter } = splitPaginatedQuery(query);
query?: Omit<PlaylistSongListQuery, 'startIndex' | 'limit'>, return [serverId, 'playlists', id, 'detailSongList', filter, pagination] as const;
pagination?: QueryPagination, }
) => {
if (query && pagination)
return [serverId, 'playlists', id, 'detailSongList', query, pagination] as const;
if (query && id) return [serverId, 'playlists', id, 'detailSongList', query] as const; if (query && id) return [serverId, 'playlists', id, 'detailSongList', query] as const;
if (id) return [serverId, 'playlists', id, 'detailSongList'] as const; if (id) return [serverId, 'playlists', id, 'detailSongList'] as const;
return [serverId, 'playlists', 'detailSongList'] as const; return [serverId, 'playlists', 'detailSongList'] as const;
@ -129,15 +122,11 @@ export const queryKeys: Record<
return [serverId, 'playlists', 'list'] as const; return [serverId, 'playlists', 'list'] as const;
}, },
root: (serverId: string) => [serverId, 'playlists'] as const, root: (serverId: string) => [serverId, 'playlists'] as const,
songList: ( songList: (serverId: string, id?: string, query?: PlaylistSongListQuery) => {
serverId: string, if (query && id) {
id?: string, const { pagination, filter } = splitPaginatedQuery(query);
query?: Omit<PlaylistSongListQuery, 'startIndex' | 'limit'>, return [serverId, 'playlists', id, 'songList', filter, pagination] as const;
pagination?: QueryPagination, }
) => {
if (query && id && pagination)
return [serverId, 'playlists', id, 'songList', query, pagination] as const;
if (query && id) return [serverId, 'playlists', id, 'songList', query] as const;
if (id) return [serverId, 'playlists', id, 'songList'] as const; if (id) return [serverId, 'playlists', id, 'songList'] as const;
return [serverId, 'playlists', 'songList'] as const; return [serverId, 'playlists', 'songList'] as const;
}, },
@ -157,12 +146,11 @@ export const queryKeys: Record<
if (query) return [serverId, 'songs', 'detail', query] as const; if (query) return [serverId, 'songs', 'detail', query] as const;
return [serverId, 'songs', 'detail'] as const; return [serverId, 'songs', 'detail'] as const;
}, },
list: ( list: (serverId: string, query?: SongListQuery) => {
serverId: string, if (query) {
query?: Omit<SongListQuery, 'startIndex' | 'limit'>, const { pagination, filter } = splitPaginatedQuery(query);
pagination?: QueryPagination, return [serverId, 'songs', 'list', filter, pagination] as const;
) => { }
if (query && pagination) return [serverId, 'songs', 'list', query, pagination] as const;
if (query) return [serverId, 'songs', 'list', query] as const; if (query) return [serverId, 'songs', 'list', query] as const;
return [serverId, 'songs', 'list'] as const; return [serverId, 'songs', 'list'] as const;
}, },

View file

@ -3,7 +3,7 @@ import { useCallback, useMemo } from 'react';
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';
import { queryKeys, splitPaginatedQuery } from '/@/renderer/api/query-keys'; import { queryKeys } from '/@/renderer/api/query-keys';
import { import {
Album, Album,
AlbumListQuery, AlbumListQuery,
@ -169,16 +169,14 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
return []; return [];
} }
const listQuery: AlbumListQuery = { const query: AlbumListQuery = {
limit: take, limit: take,
startIndex: skip, startIndex: skip,
...filter, ...filter,
...customFilters, ...customFilters,
}; };
const { query, pagination } = splitPaginatedQuery(listQuery); const queryKey = queryKeys.albums.list(server?.id || '', query);
const queryKey = queryKeys.albums.list(server?.id || '', query, pagination);
const albums = await queryClient.fetchQuery(queryKey, async ({ signal }) => const albums = await queryClient.fetchQuery(queryKey, async ({ signal }) =>
controller.getAlbumList({ controller.getAlbumList({
@ -186,7 +184,7 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
server, server,
signal, signal,
}, },
query: listQuery, query,
}), }),
); );

View file

@ -7,7 +7,7 @@ import {
RiAddBoxFill, RiAddBoxFill,
RiAddCircleFill, RiAddCircleFill,
RiFilterFill, RiFilterFill,
RiFolder2Line, RiFolder2Fill,
RiMoreFill, RiMoreFill,
RiPlayFill, RiPlayFill,
RiRefreshLine, RiRefreshLine,
@ -275,6 +275,10 @@ export const AlbumListHeaderFilters = ({ gridRef, tableRef }: AlbumListHeaderFil
return isNavidromeFilterApplied || isJellyfinFilterApplied; return isNavidromeFilterApplied || isJellyfinFilterApplied;
}, [filter?._custom?.jellyfin, filter?._custom?.navidrome, server?.type]); }, [filter?._custom?.jellyfin, filter?._custom?.navidrome, server?.type]);
const isFolderFilterApplied = useMemo(() => {
return filter.musicFolderId !== undefined;
}, [filter.musicFolderId]);
return ( return (
<Flex justify="space-between"> <Flex justify="space-between">
<Group <Group
@ -320,9 +324,16 @@ export const AlbumListHeaderFilters = ({ gridRef, tableRef }: AlbumListHeaderFil
compact compact
fw={600} fw={600}
size="md" size="md"
sx={{
svg: {
fill: isFolderFilterApplied
? 'var(--primary-color) !important'
: undefined,
},
}}
variant="subtle" variant="subtle"
> >
{cq.isSm ? 'Folder' : <RiFolder2Line size="1.3rem" />} <RiFolder2Fill size="1.3rem" />
</Button> </Button>
</DropdownMenu.Target> </DropdownMenu.Target>
<DropdownMenu.Dropdown> <DropdownMenu.Dropdown>

View file

@ -1,11 +1,11 @@
import { MutableRefObject, useCallback, useMemo } from 'react';
import { IDatasource } from '@ag-grid-community/core'; import { IDatasource } from '@ag-grid-community/core';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { api } from '/@/renderer/api';
import { queryKeys, QueryPagination } from '/@/renderer/api/query-keys';
import { LibraryItem, ServerListItem, BasePaginatedResponse } from '/@/renderer/api/types';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { QueryKey, useQueryClient } from '@tanstack/react-query'; import { QueryKey, useQueryClient } from '@tanstack/react-query';
import { MutableRefObject, useCallback, useMemo } from 'react';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { BasePaginatedResponse, LibraryItem, ServerListItem } from '/@/renderer/api/types';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
interface UseHandleListFilterChangeProps { interface UseHandleListFilterChangeProps {
itemType: LibraryItem; itemType: LibraryItem;
@ -15,24 +15,23 @@ interface UseHandleListFilterChangeProps {
export const useListFilterRefresh = ({ server, itemType }: UseHandleListFilterChangeProps) => { export const useListFilterRefresh = ({ server, itemType }: UseHandleListFilterChangeProps) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const queryKeyFn: const queryKeyFn: ((serverId: string, query: Record<any, any>) => QueryKey) | null =
| ((serverId: string, query: Record<any, any>, pagination: QueryPagination) => QueryKey) useMemo(() => {
| null = useMemo(() => { if (itemType === LibraryItem.ALBUM) {
if (itemType === LibraryItem.ALBUM) { return queryKeys.albums.list;
return queryKeys.albums.list; }
} if (itemType === LibraryItem.ALBUM_ARTIST) {
if (itemType === LibraryItem.ALBUM_ARTIST) { return queryKeys.albumArtists.list;
return queryKeys.albumArtists.list; }
} if (itemType === LibraryItem.PLAYLIST) {
if (itemType === LibraryItem.PLAYLIST) { return queryKeys.playlists.list;
return queryKeys.playlists.list; }
} if (itemType === LibraryItem.SONG) {
if (itemType === LibraryItem.SONG) { return queryKeys.songs.list;
return queryKeys.songs.list; }
}
return null; return null;
}, [itemType]); }, [itemType]);
const queryFn: ((args: any) => Promise<BasePaginatedResponse<any> | null | undefined>) | null = const queryFn: ((args: any) => Promise<BasePaginatedResponse<any> | null | undefined>) | null =
useMemo(() => { useMemo(() => {
@ -63,13 +62,9 @@ export const useListFilterRefresh = ({ server, itemType }: UseHandleListFilterCh
const limit = params.endRow - params.startRow; const limit = params.endRow - params.startRow;
const startIndex = params.startRow; const startIndex = params.startRow;
const query = filter; const query = { ...filter, limit, startIndex };
const pagination = {
limit,
startIndex,
};
const queryKey = queryKeyFn(server?.id || '', query, pagination); const queryKey = queryKeyFn(server?.id || '', query);
const res = await queryClient.fetchQuery({ const res = await queryClient.fetchQuery({
queryFn: async ({ signal }) => { queryFn: async ({ signal }) => {
@ -107,13 +102,9 @@ export const useListFilterRefresh = ({ server, itemType }: UseHandleListFilterCh
gridRef.current?.resetLoadMoreItemsCache(); gridRef.current?.resetLoadMoreItemsCache();
gridRef.current?.setItemData([]); gridRef.current?.setItemData([]);
const query = filter; const query = { ...filter, limit: 200, startIndex: 0 };
const pagination = {
limit: 200,
startIndex: 0,
};
const queryKey = queryKeyFn(server?.id || '', query, pagination); const queryKey = queryKeyFn(server?.id || '', query);
const res = await queryClient.fetchQuery({ const res = await queryClient.fetchQuery({
queryFn: async ({ signal }) => { queryFn: async ({ signal }) => {