mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-08 11:40:03 +02:00
fix list select all hotkey (#2195)
This commit is contained in:
@@ -6,7 +6,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, useRef, useState } 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';
|
||||||
@@ -86,7 +86,6 @@ export const useItemListInfiniteLoader = ({
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const lastFetchedPageRef = useRef<number>(-1);
|
const lastFetchedPageRef = useRef<number>(-1);
|
||||||
const currentVisibleRangeRef = useRef<null | { startIndex: number; stopIndex: number }>(null);
|
const currentVisibleRangeRef = useRef<null | { startIndex: number; stopIndex: number }>(null);
|
||||||
const [isRefetching, setIsRefetching] = useState(false);
|
|
||||||
const refetchPromiseRef = useRef<null | Promise<void>>(null);
|
const refetchPromiseRef = useRef<null | Promise<void>>(null);
|
||||||
const previousDataQueryKeyRef = useRef<string>('');
|
const previousDataQueryKeyRef = useRef<string>('');
|
||||||
const isRefetchingRef = useRef<boolean>(false);
|
const isRefetchingRef = useRef<boolean>(false);
|
||||||
@@ -213,7 +212,6 @@ export const useItemListInfiniteLoader = ({
|
|||||||
const countQueryKey = listCountQuery.queryKey;
|
const countQueryKey = listCountQuery.queryKey;
|
||||||
|
|
||||||
// Set refetching state and create a promise to suspend
|
// Set refetching state and create a promise to suspend
|
||||||
setIsRefetching(true);
|
|
||||||
const refetchPromise = (async () => {
|
const refetchPromise = (async () => {
|
||||||
try {
|
try {
|
||||||
// Reset the loaded pages
|
// Reset the loaded pages
|
||||||
@@ -239,7 +237,6 @@ export const useItemListInfiniteLoader = ({
|
|||||||
// Fetch the first page after count is refetched
|
// Fetch the first page after count is refetched
|
||||||
await fetchPage(pageToFetch);
|
await fetchPage(pageToFetch);
|
||||||
} finally {
|
} finally {
|
||||||
setIsRefetching(false);
|
|
||||||
isRefetchingRef.current = false;
|
isRefetchingRef.current = false;
|
||||||
refetchPromiseRef.current = null;
|
refetchPromiseRef.current = null;
|
||||||
}
|
}
|
||||||
@@ -248,7 +245,6 @@ export const useItemListInfiniteLoader = ({
|
|||||||
refetchPromiseRef.current = refetchPromise;
|
refetchPromiseRef.current = refetchPromise;
|
||||||
|
|
||||||
refetchPromise.catch(() => {
|
refetchPromise.catch(() => {
|
||||||
setIsRefetching(false);
|
|
||||||
isRefetchingRef.current = false;
|
isRefetchingRef.current = false;
|
||||||
refetchPromiseRef.current = null;
|
refetchPromiseRef.current = null;
|
||||||
});
|
});
|
||||||
@@ -266,7 +262,7 @@ export const useItemListInfiniteLoader = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Suspend if refetching
|
// Suspend if refetching
|
||||||
if (isRefetching && refetchPromiseRef.current) {
|
if (isRefetchingRef.current && refetchPromiseRef.current) {
|
||||||
throw refetchPromiseRef.current;
|
throw refetchPromiseRef.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,10 +490,20 @@ export const useItemListInfiniteLoader = ({
|
|||||||
.map(([, v]) => v);
|
.map(([, v]) => v);
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
|
const getLoadedItems = useCallback(() => {
|
||||||
|
const cacheData = queryClient.getQueryData<InfiniteLoaderCacheData>(dataQueryKey);
|
||||||
|
const map = cacheData?.dataMap;
|
||||||
|
if (!map || map.size === 0) return [];
|
||||||
|
return Array.from(map.entries())
|
||||||
|
.sort(([a], [b]) => a - b)
|
||||||
|
.map(([, v]) => v);
|
||||||
|
}, [dataQueryKey, queryClient]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dataVersion: (data as any).version ?? 0,
|
dataVersion: (data as any).version ?? 0,
|
||||||
getItem,
|
getItem,
|
||||||
getItemIndex,
|
getItemIndex,
|
||||||
|
getLoadedItems,
|
||||||
itemCount,
|
itemCount,
|
||||||
loadedItems,
|
loadedItems,
|
||||||
onRangeChanged,
|
onRangeChanged,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { type RefObject, useRef } from 'react';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
|
|
||||||
import { getTitlePath } from '/@/renderer/components/item-list/helpers/get-title-path';
|
import { getTitlePath } from '/@/renderer/components/item-list/helpers/get-title-path';
|
||||||
@@ -13,12 +14,14 @@ import { Play } from '/@/shared/types/types';
|
|||||||
|
|
||||||
export const useListHotkeys = ({
|
export const useListHotkeys = ({
|
||||||
controls,
|
controls,
|
||||||
|
focusContainerRef,
|
||||||
focused,
|
focused,
|
||||||
internalState,
|
internalState,
|
||||||
itemType,
|
itemType,
|
||||||
onShowPlayingSong,
|
onShowPlayingSong,
|
||||||
}: {
|
}: {
|
||||||
controls: ItemControls;
|
controls: ItemControls;
|
||||||
|
focusContainerRef?: RefObject<HTMLElement | null>;
|
||||||
focused: boolean;
|
focused: boolean;
|
||||||
internalState: ItemListStateActions;
|
internalState: ItemListStateActions;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
@@ -27,6 +30,19 @@ export const useListHotkeys = ({
|
|||||||
const { bindings } = useHotkeySettings();
|
const { bindings } = useHotkeySettings();
|
||||||
const playButtonBehavior = usePlayButtonBehavior();
|
const playButtonBehavior = usePlayButtonBehavior();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const focusedRef = useRef(focused);
|
||||||
|
focusedRef.current = focused;
|
||||||
|
const internalStateRef = useRef(internalState);
|
||||||
|
internalStateRef.current = internalState;
|
||||||
|
|
||||||
|
const isListFocused = () => {
|
||||||
|
const container = focusContainerRef?.current;
|
||||||
|
if (container) {
|
||||||
|
return container.contains(document.activeElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return focusedRef.current;
|
||||||
|
};
|
||||||
|
|
||||||
// Helper to check if item has required properties
|
// Helper to check if item has required properties
|
||||||
const hasRequiredStateItemProperties = (
|
const hasRequiredStateItemProperties = (
|
||||||
@@ -48,19 +64,20 @@ export const useListHotkeys = ({
|
|||||||
[
|
[
|
||||||
'mod+a',
|
'mod+a',
|
||||||
() => {
|
() => {
|
||||||
if (focused) {
|
if (!isListFocused()) return;
|
||||||
if (internalState.isAllSelected()) {
|
|
||||||
internalState.deselectAll();
|
const state = internalStateRef.current;
|
||||||
} else {
|
if (state.isAllSelected()) {
|
||||||
internalState.selectAll();
|
state.deselectAll();
|
||||||
}
|
} else {
|
||||||
|
state.selectAll();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
bindings.listPlayDefault.hotkey,
|
bindings.listPlayDefault.hotkey,
|
||||||
() => {
|
() => {
|
||||||
if (!focused) return;
|
if (!isListFocused()) return;
|
||||||
const selected = internalState.getSelected();
|
const selected = internalState.getSelected();
|
||||||
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
||||||
if (validSelected.length === 0) return;
|
if (validSelected.length === 0) return;
|
||||||
@@ -73,7 +90,7 @@ export const useListHotkeys = ({
|
|||||||
[
|
[
|
||||||
bindings.listPlayNow.hotkey,
|
bindings.listPlayNow.hotkey,
|
||||||
() => {
|
() => {
|
||||||
if (!focused) return;
|
if (!isListFocused()) return;
|
||||||
const selected = internalState.getSelected();
|
const selected = internalState.getSelected();
|
||||||
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
||||||
if (validSelected.length === 0) return;
|
if (validSelected.length === 0) return;
|
||||||
@@ -85,7 +102,7 @@ export const useListHotkeys = ({
|
|||||||
[
|
[
|
||||||
bindings.listPlayNext.hotkey,
|
bindings.listPlayNext.hotkey,
|
||||||
() => {
|
() => {
|
||||||
if (!focused) return;
|
if (!isListFocused()) return;
|
||||||
const selected = internalState.getSelected();
|
const selected = internalState.getSelected();
|
||||||
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
||||||
if (validSelected.length === 0) return;
|
if (validSelected.length === 0) return;
|
||||||
@@ -97,7 +114,7 @@ export const useListHotkeys = ({
|
|||||||
[
|
[
|
||||||
bindings.listPlayLast.hotkey,
|
bindings.listPlayLast.hotkey,
|
||||||
() => {
|
() => {
|
||||||
if (!focused) return;
|
if (!isListFocused()) return;
|
||||||
const selected = internalState.getSelected();
|
const selected = internalState.getSelected();
|
||||||
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
||||||
if (validSelected.length === 0) return;
|
if (validSelected.length === 0) return;
|
||||||
@@ -109,7 +126,7 @@ export const useListHotkeys = ({
|
|||||||
[
|
[
|
||||||
bindings.listNavigateToPage.hotkey,
|
bindings.listNavigateToPage.hotkey,
|
||||||
() => {
|
() => {
|
||||||
if (!focused) return;
|
if (!isListFocused()) return;
|
||||||
const selected = internalState.getSelected();
|
const selected = internalState.getSelected();
|
||||||
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
const validSelected = selected.filter(hasRequiredStateItemProperties);
|
||||||
if (validSelected.length === 0) return;
|
if (validSelected.length === 0) return;
|
||||||
|
|||||||
@@ -1463,6 +1463,7 @@ export const ItemDetailList = ({
|
|||||||
|
|
||||||
useListHotkeys({
|
useListHotkeys({
|
||||||
controls,
|
controls,
|
||||||
|
focusContainerRef: containerRef,
|
||||||
focused,
|
focused,
|
||||||
internalState,
|
internalState,
|
||||||
itemType: LibraryItem.SONG,
|
itemType: LibraryItem.SONG,
|
||||||
|
|||||||
@@ -343,6 +343,7 @@ export interface ItemGridListProps {
|
|||||||
gap?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
|
gap?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
|
||||||
getItem?: (index: number) => ItemCardProps['data'];
|
getItem?: (index: number) => ItemCardProps['data'];
|
||||||
getItemIndex?: (rowId: string) => number | undefined;
|
getItemIndex?: (rowId: string) => number | undefined;
|
||||||
|
getLoadedItems?: () => unknown[];
|
||||||
getRowId?: ((item: unknown) => string) | string;
|
getRowId?: ((item: unknown) => string) | string;
|
||||||
initialTop?: {
|
initialTop?: {
|
||||||
to: number;
|
to: number;
|
||||||
@@ -372,6 +373,7 @@ const BaseItemGridList = ({
|
|||||||
gap = 'sm',
|
gap = 'sm',
|
||||||
getItem,
|
getItem,
|
||||||
getItemIndex,
|
getItemIndex,
|
||||||
|
getLoadedItems,
|
||||||
getRowId,
|
getRowId,
|
||||||
initialTop,
|
initialTop,
|
||||||
itemCount,
|
itemCount,
|
||||||
@@ -401,9 +403,18 @@ const BaseItemGridList = ({
|
|||||||
[data, getItem],
|
[data, getItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const dataRef = useRef(data);
|
||||||
|
const getLoadedItemsRef = useRef(getLoadedItems);
|
||||||
|
dataRef.current = data;
|
||||||
|
getLoadedItemsRef.current = getLoadedItems;
|
||||||
|
|
||||||
const getDataFn = useCallback(() => {
|
const getDataFn = useCallback(() => {
|
||||||
return data;
|
const loadedItems = getLoadedItemsRef.current?.();
|
||||||
}, [data]);
|
if (loadedItems?.length) {
|
||||||
|
return loadedItems;
|
||||||
|
}
|
||||||
|
return dataRef.current ?? [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
const extractRowId = useMemo(() => createExtractRowId(getRowId), [getRowId]);
|
const extractRowId = useMemo(() => createExtractRowId(getRowId), [getRowId]);
|
||||||
|
|
||||||
@@ -782,6 +793,7 @@ const BaseItemGridList = ({
|
|||||||
|
|
||||||
useListHotkeys({
|
useListHotkeys({
|
||||||
controls,
|
controls,
|
||||||
|
focusContainerRef: rootRef,
|
||||||
focused,
|
focused,
|
||||||
internalState,
|
internalState,
|
||||||
itemType,
|
itemType,
|
||||||
|
|||||||
@@ -827,6 +827,7 @@ interface ItemTableListProps {
|
|||||||
enableVerticalBorders?: boolean;
|
enableVerticalBorders?: boolean;
|
||||||
getItem?: (index: number) => undefined | unknown;
|
getItem?: (index: number) => undefined | unknown;
|
||||||
getItemIndex?: (rowId: string) => number | undefined;
|
getItemIndex?: (rowId: string) => number | undefined;
|
||||||
|
getLoadedItems?: () => unknown[];
|
||||||
getRowId?: ((item: unknown) => string) | string;
|
getRowId?: ((item: unknown) => string) | string;
|
||||||
groups?: TableGroupHeader[];
|
groups?: TableGroupHeader[];
|
||||||
headerHeight?: number;
|
headerHeight?: number;
|
||||||
@@ -1264,6 +1265,7 @@ const BaseItemTableList = ({
|
|||||||
enableVerticalBorders = false,
|
enableVerticalBorders = false,
|
||||||
getItem,
|
getItem,
|
||||||
getItemIndex,
|
getItemIndex,
|
||||||
|
getLoadedItems,
|
||||||
getRowId,
|
getRowId,
|
||||||
groups,
|
groups,
|
||||||
headerHeight = 40,
|
headerHeight = 40,
|
||||||
@@ -1498,9 +1500,18 @@ const BaseItemTableList = ({
|
|||||||
[enableHeader, headerHeight, rowHeight, pinnedRowCount, size],
|
[enableHeader, headerHeight, rowHeight, pinnedRowCount, size],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const dataRef = useRef(data);
|
||||||
|
const getLoadedItemsRef = useRef(getLoadedItems);
|
||||||
|
dataRef.current = data;
|
||||||
|
getLoadedItemsRef.current = getLoadedItems;
|
||||||
|
|
||||||
const getDataFn = useCallback(() => {
|
const getDataFn = useCallback(() => {
|
||||||
return data;
|
const loadedItems = getLoadedItemsRef.current?.();
|
||||||
}, [data]);
|
if (loadedItems?.length) {
|
||||||
|
return loadedItems;
|
||||||
|
}
|
||||||
|
return dataRef.current ?? [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
const extractRowId = useMemo(() => createExtractRowId(getRowId), [getRowId]);
|
const extractRowId = useMemo(() => createExtractRowId(getRowId), [getRowId]);
|
||||||
|
|
||||||
@@ -1646,6 +1657,7 @@ const BaseItemTableList = ({
|
|||||||
|
|
||||||
useListHotkeys({
|
useListHotkeys({
|
||||||
controls,
|
controls,
|
||||||
|
focusContainerRef: containerRef,
|
||||||
focused,
|
focused,
|
||||||
internalState,
|
internalState,
|
||||||
itemType,
|
itemType,
|
||||||
|
|||||||
@@ -40,16 +40,23 @@ export const AlbumListInfiniteGrid = ({
|
|||||||
|
|
||||||
const { pageKey } = useListContext();
|
const { pageKey } = useListContext();
|
||||||
|
|
||||||
const { dataVersion, getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const {
|
||||||
useItemListInfiniteLoader({
|
dataVersion,
|
||||||
eventKey: pageKey || ItemListKey.ALBUM,
|
getItem,
|
||||||
itemsPerPage,
|
getItemIndex,
|
||||||
itemType: LibraryItem.ALBUM,
|
getLoadedItems,
|
||||||
listCountQuery,
|
itemCount,
|
||||||
listQueryFn,
|
loadedItems,
|
||||||
query,
|
onRangeChanged,
|
||||||
serverId,
|
} = useItemListInfiniteLoader({
|
||||||
});
|
eventKey: pageKey || ItemListKey.ALBUM,
|
||||||
|
itemsPerPage,
|
||||||
|
itemType: LibraryItem.ALBUM,
|
||||||
|
listCountQuery,
|
||||||
|
listQueryFn,
|
||||||
|
query,
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
||||||
enabled: saveScrollOffset,
|
enabled: saveScrollOffset,
|
||||||
@@ -67,6 +74,7 @@ export const AlbumListInfiniteGrid = ({
|
|||||||
gap={gap}
|
gap={gap}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export const AlbumListInfiniteTable = ({
|
|||||||
const listQueryFn = api.controller.getAlbumList;
|
const listQueryFn = api.controller.getAlbumList;
|
||||||
const { pageKey } = useListContext();
|
const { pageKey } = useListContext();
|
||||||
|
|
||||||
const { getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const { getItem, getItemIndex, getLoadedItems, itemCount, loadedItems, onRangeChanged } =
|
||||||
useItemListInfiniteLoader({
|
useItemListInfiniteLoader({
|
||||||
eventKey: pageKey || ItemListKey.ALBUM,
|
eventKey: pageKey || ItemListKey.ALBUM,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
@@ -83,6 +83,7 @@ export const AlbumListInfiniteTable = ({
|
|||||||
enableVerticalBorders={enableVerticalBorders}
|
enableVerticalBorders={enableVerticalBorders}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -37,16 +37,23 @@ export const AlbumArtistListInfiniteGrid = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getAlbumArtistList;
|
const listQueryFn = api.controller.getAlbumArtistList;
|
||||||
|
|
||||||
const { dataVersion, getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const {
|
||||||
useItemListInfiniteLoader({
|
dataVersion,
|
||||||
eventKey: ItemListKey.ALBUM_ARTIST,
|
getItem,
|
||||||
itemsPerPage,
|
getItemIndex,
|
||||||
itemType: LibraryItem.ALBUM_ARTIST,
|
getLoadedItems,
|
||||||
listCountQuery,
|
itemCount,
|
||||||
listQueryFn,
|
loadedItems,
|
||||||
query,
|
onRangeChanged,
|
||||||
serverId,
|
} = useItemListInfiniteLoader({
|
||||||
});
|
eventKey: ItemListKey.ALBUM_ARTIST,
|
||||||
|
itemsPerPage,
|
||||||
|
itemType: LibraryItem.ALBUM_ARTIST,
|
||||||
|
listCountQuery,
|
||||||
|
listQueryFn,
|
||||||
|
query,
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
||||||
enabled: saveScrollOffset,
|
enabled: saveScrollOffset,
|
||||||
@@ -63,6 +70,7 @@ export const AlbumArtistListInfiniteGrid = ({
|
|||||||
gap={gap}
|
gap={gap}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const AlbumArtistListInfiniteTable = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getAlbumArtistList;
|
const listQueryFn = api.controller.getAlbumArtistList;
|
||||||
|
|
||||||
const { getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const { getItem, getItemIndex, getLoadedItems, itemCount, loadedItems, onRangeChanged } =
|
||||||
useItemListInfiniteLoader({
|
useItemListInfiniteLoader({
|
||||||
eventKey: ItemListKey.ALBUM_ARTIST,
|
eventKey: ItemListKey.ALBUM_ARTIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
@@ -82,6 +82,7 @@ export const AlbumArtistListInfiniteTable = ({
|
|||||||
enableVerticalBorders={enableVerticalBorders}
|
enableVerticalBorders={enableVerticalBorders}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -37,16 +37,23 @@ export const ArtistListInfiniteGrid = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getArtistList;
|
const listQueryFn = api.controller.getArtistList;
|
||||||
|
|
||||||
const { dataVersion, getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const {
|
||||||
useItemListInfiniteLoader({
|
dataVersion,
|
||||||
eventKey: ItemListKey.ARTIST,
|
getItem,
|
||||||
itemsPerPage,
|
getItemIndex,
|
||||||
itemType: LibraryItem.ARTIST,
|
getLoadedItems,
|
||||||
listCountQuery,
|
itemCount,
|
||||||
listQueryFn,
|
loadedItems,
|
||||||
query,
|
onRangeChanged,
|
||||||
serverId,
|
} = useItemListInfiniteLoader({
|
||||||
});
|
eventKey: ItemListKey.ARTIST,
|
||||||
|
itemsPerPage,
|
||||||
|
itemType: LibraryItem.ARTIST,
|
||||||
|
listCountQuery,
|
||||||
|
listQueryFn,
|
||||||
|
query,
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
||||||
enabled: saveScrollOffset,
|
enabled: saveScrollOffset,
|
||||||
@@ -63,6 +70,7 @@ export const ArtistListInfiniteGrid = ({
|
|||||||
gap={gap}
|
gap={gap}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const ArtistListInfiniteTable = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getArtistList;
|
const listQueryFn = api.controller.getArtistList;
|
||||||
|
|
||||||
const { getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const { getItem, getItemIndex, getLoadedItems, itemCount, loadedItems, onRangeChanged } =
|
||||||
useItemListInfiniteLoader({
|
useItemListInfiniteLoader({
|
||||||
eventKey: ItemListKey.ARTIST,
|
eventKey: ItemListKey.ARTIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
@@ -82,6 +82,7 @@ export const ArtistListInfiniteTable = ({
|
|||||||
enableVerticalBorders={enableVerticalBorders}
|
enableVerticalBorders={enableVerticalBorders}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -37,16 +37,23 @@ export const GenreListInfiniteGrid = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getGenreList;
|
const listQueryFn = api.controller.getGenreList;
|
||||||
|
|
||||||
const { dataVersion, getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const {
|
||||||
useItemListInfiniteLoader({
|
dataVersion,
|
||||||
eventKey: ItemListKey.GENRE,
|
getItem,
|
||||||
itemsPerPage,
|
getItemIndex,
|
||||||
itemType: LibraryItem.GENRE,
|
getLoadedItems,
|
||||||
listCountQuery,
|
itemCount,
|
||||||
listQueryFn,
|
loadedItems,
|
||||||
query,
|
onRangeChanged,
|
||||||
serverId,
|
} = useItemListInfiniteLoader({
|
||||||
});
|
eventKey: ItemListKey.GENRE,
|
||||||
|
itemsPerPage,
|
||||||
|
itemType: LibraryItem.GENRE,
|
||||||
|
listCountQuery,
|
||||||
|
listQueryFn,
|
||||||
|
query,
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
||||||
enabled: saveScrollOffset,
|
enabled: saveScrollOffset,
|
||||||
@@ -63,6 +70,7 @@ export const GenreListInfiniteGrid = ({
|
|||||||
gap={gap}
|
gap={gap}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const GenreListInfiniteTable = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getGenreList;
|
const listQueryFn = api.controller.getGenreList;
|
||||||
|
|
||||||
const { getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const { getItem, getItemIndex, getLoadedItems, itemCount, loadedItems, onRangeChanged } =
|
||||||
useItemListInfiniteLoader({
|
useItemListInfiniteLoader({
|
||||||
eventKey: ItemListKey.GENRE,
|
eventKey: ItemListKey.GENRE,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
@@ -82,6 +82,7 @@ export const GenreListInfiniteTable = ({
|
|||||||
enableVerticalBorders={enableVerticalBorders}
|
enableVerticalBorders={enableVerticalBorders}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -37,16 +37,23 @@ export const PlaylistListInfiniteGrid = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getPlaylistList;
|
const listQueryFn = api.controller.getPlaylistList;
|
||||||
|
|
||||||
const { dataVersion, getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const {
|
||||||
useItemListInfiniteLoader({
|
dataVersion,
|
||||||
eventKey: ItemListKey.PLAYLIST,
|
getItem,
|
||||||
itemsPerPage,
|
getItemIndex,
|
||||||
itemType: LibraryItem.PLAYLIST,
|
getLoadedItems,
|
||||||
listCountQuery,
|
itemCount,
|
||||||
listQueryFn,
|
loadedItems,
|
||||||
query,
|
onRangeChanged,
|
||||||
serverId,
|
} = useItemListInfiniteLoader({
|
||||||
});
|
eventKey: ItemListKey.PLAYLIST,
|
||||||
|
itemsPerPage,
|
||||||
|
itemType: LibraryItem.PLAYLIST,
|
||||||
|
listCountQuery,
|
||||||
|
listQueryFn,
|
||||||
|
query,
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
||||||
enabled: saveScrollOffset,
|
enabled: saveScrollOffset,
|
||||||
@@ -63,6 +70,7 @@ export const PlaylistListInfiniteGrid = ({
|
|||||||
gap={gap}
|
gap={gap}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const PlaylistListInfiniteTable = ({
|
|||||||
|
|
||||||
const listQueryFn = api.controller.getPlaylistList;
|
const listQueryFn = api.controller.getPlaylistList;
|
||||||
|
|
||||||
const { getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const { getItem, getItemIndex, getLoadedItems, itemCount, loadedItems, onRangeChanged } =
|
||||||
useItemListInfiniteLoader({
|
useItemListInfiniteLoader({
|
||||||
eventKey: ItemListKey.PLAYLIST,
|
eventKey: ItemListKey.PLAYLIST,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
@@ -82,6 +82,7 @@ export const PlaylistListInfiniteTable = ({
|
|||||||
enableVerticalBorders={enableVerticalBorders}
|
enableVerticalBorders={enableVerticalBorders}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -34,16 +34,23 @@ export const SongListInfiniteGrid = ({
|
|||||||
const listQueryFn = api.controller.getSongList;
|
const listQueryFn = api.controller.getSongList;
|
||||||
const { pageKey } = useListContext();
|
const { pageKey } = useListContext();
|
||||||
|
|
||||||
const { dataVersion, getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const {
|
||||||
useItemListInfiniteLoader({
|
dataVersion,
|
||||||
eventKey: pageKey || ItemListKey.SONG,
|
getItem,
|
||||||
itemsPerPage,
|
getItemIndex,
|
||||||
itemType: LibraryItem.SONG,
|
getLoadedItems,
|
||||||
listCountQuery,
|
itemCount,
|
||||||
listQueryFn,
|
loadedItems,
|
||||||
query,
|
onRangeChanged,
|
||||||
serverId,
|
} = useItemListInfiniteLoader({
|
||||||
});
|
eventKey: pageKey || ItemListKey.SONG,
|
||||||
|
itemsPerPage,
|
||||||
|
itemType: LibraryItem.SONG,
|
||||||
|
listCountQuery,
|
||||||
|
listQueryFn,
|
||||||
|
query,
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
|
||||||
enabled: saveScrollOffset,
|
enabled: saveScrollOffset,
|
||||||
@@ -60,6 +67,7 @@ export const SongListInfiniteGrid = ({
|
|||||||
gap={gap}
|
gap={gap}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const SongListInfiniteTable = ({
|
|||||||
const listQueryFn = api.controller.getSongList;
|
const listQueryFn = api.controller.getSongList;
|
||||||
const { pageKey } = useListContext();
|
const { pageKey } = useListContext();
|
||||||
|
|
||||||
const { getItem, getItemIndex, itemCount, loadedItems, onRangeChanged } =
|
const { getItem, getItemIndex, getLoadedItems, itemCount, loadedItems, onRangeChanged } =
|
||||||
useItemListInfiniteLoader({
|
useItemListInfiniteLoader({
|
||||||
eventKey: pageKey || ItemListKey.SONG,
|
eventKey: pageKey || ItemListKey.SONG,
|
||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
@@ -83,6 +83,7 @@ export const SongListInfiniteTable = ({
|
|||||||
enableVerticalBorders={enableVerticalBorders}
|
enableVerticalBorders={enableVerticalBorders}
|
||||||
getItem={getItem}
|
getItem={getItem}
|
||||||
getItemIndex={getItemIndex}
|
getItemIndex={getItemIndex}
|
||||||
|
getLoadedItems={getLoadedItems}
|
||||||
initialTop={{
|
initialTop={{
|
||||||
to: scrollOffset ?? 0,
|
to: scrollOffset ?? 0,
|
||||||
type: 'offset',
|
type: 'offset',
|
||||||
|
|||||||
Reference in New Issue
Block a user