mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-18 01:14:22 +02:00
optimize list refresh functions
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
|||||||
UseSuspenseQueryOptions,
|
UseSuspenseQueryOptions,
|
||||||
} from '@tanstack/react-query';
|
} from '@tanstack/react-query';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
import { useCallback, useEffect, useMemo } from 'react';
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
|
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { useListContext } from '/@/renderer/context/list-context';
|
import { useListContext } from '/@/renderer/context/list-context';
|
||||||
@@ -61,6 +61,8 @@ export const useItemListInfiniteLoader = ({
|
|||||||
serverId,
|
serverId,
|
||||||
}: UseItemListInfiniteLoaderProps) => {
|
}: UseItemListInfiniteLoaderProps) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const lastFetchedPageRef = useRef<number>(-1);
|
||||||
|
const currentVisibleRangeRef = useRef<null | { startIndex: number; stopIndex: number }>(null);
|
||||||
|
|
||||||
const { data: totalItemCount } = useSuspenseQuery<number, any, number, any>(listCountQuery);
|
const { data: totalItemCount } = useSuspenseQuery<number, any, number, any>(listCountQuery);
|
||||||
|
|
||||||
@@ -88,6 +90,8 @@ export const useItemListInfiniteLoader = ({
|
|||||||
pagesLoaded: {},
|
pagesLoaded: {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
lastFetchedPageRef.current = -1;
|
||||||
|
currentVisibleRangeRef.current = null;
|
||||||
}, [query, queryClient, dataQueryKey]);
|
}, [query, queryClient, dataQueryKey]);
|
||||||
|
|
||||||
const { data } = useQuery<{ data: unknown[]; pagesLoaded: Record<string, boolean> }>({
|
const { data } = useQuery<{ data: unknown[]; pagesLoaded: Record<string, boolean> }>({
|
||||||
@@ -144,12 +148,18 @@ export const useItemListInfiniteLoader = ({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Track the last fetched page
|
||||||
|
lastFetchedPageRef.current = Math.max(lastFetchedPageRef.current, pageNumber);
|
||||||
},
|
},
|
||||||
[itemsPerPage, query, queryClient, serverId, dataQueryKey, listQueryFn, itemType],
|
[itemsPerPage, query, queryClient, serverId, dataQueryKey, listQueryFn, itemType],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onRangeChangedBase = useCallback(
|
const onRangeChangedBase = useCallback(
|
||||||
async (range: { startIndex: number; stopIndex: number }) => {
|
async (range: { startIndex: number; stopIndex: number }) => {
|
||||||
|
// Track the current visible range
|
||||||
|
currentVisibleRangeRef.current = range;
|
||||||
|
|
||||||
const pageNumber = Math.floor(range.startIndex / itemsPerPage);
|
const pageNumber = Math.floor(range.startIndex / itemsPerPage);
|
||||||
|
|
||||||
const currentData = queryClient.getQueryData<{
|
const currentData = queryClient.getQueryData<{
|
||||||
@@ -204,18 +214,54 @@ export const useItemListInfiniteLoader = ({
|
|||||||
|
|
||||||
const refresh = useCallback(
|
const refresh = useCallback(
|
||||||
async (force?: boolean) => {
|
async (force?: boolean) => {
|
||||||
|
// Invalidate all queries to ensure fresh data
|
||||||
await queryClient.invalidateQueries();
|
await queryClient.invalidateQueries();
|
||||||
|
|
||||||
if (force) {
|
// Reset the infinite list data
|
||||||
await queryClient.setQueryData(dataQueryKey, getInitialData(totalItemCount));
|
const currentData = queryClient.getQueryData<{
|
||||||
|
data: unknown[];
|
||||||
|
pagesLoaded: Record<string, boolean>;
|
||||||
|
}>(dataQueryKey);
|
||||||
|
|
||||||
|
if (force || currentData) {
|
||||||
|
// Reset data to initial state and clear all loaded pages
|
||||||
|
await queryClient.setQueryData(dataQueryKey, (oldData: any) => {
|
||||||
|
if (!oldData) return getInitialData(totalItemCount);
|
||||||
|
return {
|
||||||
|
...oldData,
|
||||||
|
data: Array.from({ length: totalItemCount }, () => undefined),
|
||||||
|
pagesLoaded: {},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
lastFetchedPageRef.current = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// await onRangeChanged({
|
// Add a delay to make the refresh visually clear
|
||||||
// endIndex: currentPageRef.current * itemsPerPage,
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||||
// startIndex: currentPageRef.current * itemsPerPage,
|
|
||||||
// });
|
// Determine which page to refetch based on current visible range
|
||||||
|
let pageToFetch = 0;
|
||||||
|
if (currentVisibleRangeRef.current) {
|
||||||
|
// Calculate the page from the current visible range
|
||||||
|
pageToFetch = Math.floor(currentVisibleRangeRef.current.startIndex / itemsPerPage);
|
||||||
|
} else if (lastFetchedPageRef.current >= 0) {
|
||||||
|
// Fallback to last fetched page if no visible range is tracked
|
||||||
|
pageToFetch = lastFetchedPageRef.current;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refetch the current page
|
||||||
|
await fetchPage(pageToFetch);
|
||||||
|
|
||||||
|
// Trigger range changed to ensure adjacent pages are prefetched if needed
|
||||||
|
const startIndex = pageToFetch * itemsPerPage;
|
||||||
|
const stopIndex = Math.min((pageToFetch + 1) * itemsPerPage, totalItemCount);
|
||||||
|
|
||||||
|
await onRangeChangedBase({
|
||||||
|
startIndex,
|
||||||
|
stopIndex,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[queryClient, totalItemCount, dataQueryKey],
|
[queryClient, itemsPerPage, onRangeChangedBase, dataQueryKey, totalItemCount, fetchPage],
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateItems = useCallback(
|
const updateItems = useCallback(
|
||||||
|
|||||||
@@ -98,9 +98,22 @@ export const useItemListPaginatedLoader = ({
|
|||||||
staleTime: 1000 * 15,
|
staleTime: 1000 * 15,
|
||||||
});
|
});
|
||||||
|
|
||||||
const refresh = useCallback(() => {
|
const refresh = useCallback(
|
||||||
return queryRefetch();
|
async (force?: boolean) => {
|
||||||
}, [queryRefetch]);
|
const queryKey = queryKeys[getQueryKeyName(itemType)].list(serverId, queryParams);
|
||||||
|
|
||||||
|
await queryClient.invalidateQueries();
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
queryClient.setQueryData(queryKey, {
|
||||||
|
items: getInitialData(itemsPerPage),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryRefetch();
|
||||||
|
},
|
||||||
|
[queryClient, queryRefetch, queryParams, serverId, itemType, itemsPerPage],
|
||||||
|
);
|
||||||
|
|
||||||
const updateItems = useCallback(
|
const updateItems = useCallback(
|
||||||
(indexes: number[], value: object) => {
|
(indexes: number[], value: object) => {
|
||||||
@@ -140,7 +153,7 @@ export const useItemListPaginatedLoader = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return refresh();
|
return refresh(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFavorite = (payload: UserFavoriteEventPayload) => {
|
const handleFavorite = (payload: UserFavoriteEventPayload) => {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export const AlbumListPaginatedGrid = forwardRef<any, AlbumListPaginatedGridProp
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.ALBUM,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.ALBUM,
|
itemType: LibraryItem.ALBUM,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export const AlbumListPaginatedTable = forwardRef<any, AlbumListPaginatedTablePr
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.ALBUM,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.ALBUM,
|
itemType: LibraryItem.ALBUM,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export const AlbumArtistListPaginatedGrid = forwardRef<any, AlbumArtistListPagin
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.ALBUM_ARTIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.ALBUM_ARTIST,
|
itemType: LibraryItem.ALBUM_ARTIST,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export const AlbumArtistListPaginatedTable = forwardRef<any, AlbumArtistListPagi
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.ALBUM_ARTIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.ALBUM_ARTIST,
|
itemType: LibraryItem.ALBUM_ARTIST,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export const ArtistListPaginatedGrid = forwardRef<any, ArtistListPaginatedGridPr
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.ARTIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.ARTIST,
|
itemType: LibraryItem.ARTIST,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export const ArtistListPaginatedTable = forwardRef<any, ArtistListPaginatedTable
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.ARTIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.ARTIST,
|
itemType: LibraryItem.ARTIST,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export const GenreListPaginatedGrid = forwardRef<any, GenreListPaginatedGridProp
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.GENRE,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.GENRE,
|
itemType: LibraryItem.GENRE,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export const GenreListPaginatedTable = forwardRef<any, GenreListPaginatedTablePr
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.GENRE,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.GENRE,
|
itemType: LibraryItem.GENRE,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useLocation, useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
|
|
||||||
import { ListContext } from '/@/renderer/context/list-context';
|
import { ListContext } from '/@/renderer/context/list-context';
|
||||||
import { useGenreList } from '/@/renderer/features/genres/api/genres-api';
|
import { useGenreList } from '/@/renderer/features/genres/api/genres-api';
|
||||||
@@ -30,9 +30,6 @@ const GenreDetailRoute = () => {
|
|||||||
return genres?.items.find((g) => g.id === genreId)?.name || '—';
|
return genres?.items.find((g) => g.id === genreId)?.name || '—';
|
||||||
}, [genreId, genres]);
|
}, [genreId, genres]);
|
||||||
|
|
||||||
const location = useLocation();
|
|
||||||
console.log('location', location.pathname);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatedPage>
|
<AnimatedPage>
|
||||||
<ListContext.Provider value={providerValue}>
|
<ListContext.Provider value={providerValue}>
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export const PlaylistListPaginatedGrid = forwardRef<any, PlaylistListPaginatedGr
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.PLAYLIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.PLAYLIST,
|
itemType: LibraryItem.PLAYLIST,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export const PlaylistListPaginatedTable = forwardRef<any, PlaylistListPaginatedT
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.PLAYLIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.PLAYLIST,
|
itemType: LibraryItem.PLAYLIST,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export const SongListPaginatedGrid = forwardRef<any, SongListPaginatedGridProps>
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.SONG,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.SONG,
|
itemType: LibraryItem.SONG,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export const SongListPaginatedTable = forwardRef<any, SongListPaginatedTableProp
|
|||||||
|
|
||||||
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
const { data, pageCount, totalItemCount } = useItemListPaginatedLoader({
|
||||||
currentPage,
|
currentPage,
|
||||||
|
eventKey: ItemListKey.SONG,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
itemType: LibraryItem.SONG,
|
itemType: LibraryItem.SONG,
|
||||||
listCountQuery,
|
listCountQuery,
|
||||||
|
|||||||
Reference in New Issue
Block a user