Split key pagination in central handler
This commit is contained in:
parent
1cb0a1d72a
commit
6821735f65
4 changed files with 91 additions and 103 deletions
|
@ -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;
|
||||||
},
|
},
|
||||||
|
|
|
@ -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,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 }) => {
|
||||||
|
|
Reference in a new issue