1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-26 22:56:23 -04:00

Use react-query for series

This commit is contained in:
Mark McDowall
2025-11-28 19:37:17 -08:00
parent 49db4a1d76
commit 0521a6c390
91 changed files with 1961 additions and 2173 deletions
+35 -55
View File
@@ -1,15 +1,7 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import QueueDetailsProvider from 'Activity/Queue/Details/QueueDetailsProvider';
import { SelectProvider } from 'App/Select/SelectContext';
import ClientSideCollectionAppState from 'App/State/ClientSideCollectionAppState';
import SeriesAppState, { SeriesIndexAppState } from 'App/State/SeriesAppState';
import { RSS_SYNC } from 'Commands/commandNames';
import Alert from 'Components/Alert';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
@@ -27,18 +19,17 @@ import { align, icons, kinds } from 'Helpers/Props';
import { DESCENDING } from 'Helpers/Props/sortDirections';
import ParseToolbarButton from 'Parse/ParseToolbarButton';
import NoSeries from 'Series/NoSeries';
import { executeCommand } from 'Store/Actions/commandActions';
import { fetchSeries } from 'Store/Actions/seriesActions';
import {
setSeriesFilter,
setSeriesOption,
setSeriesSort,
setSeriesTableOption,
setSeriesView,
} from 'Store/Actions/seriesIndexActions';
setSeriesTableOptions,
useSeriesOptions,
} from 'Series/seriesOptionsStore';
import { FILTERS, useSeriesIndex } from 'Series/useSeries';
import { executeCommand } from 'Store/Actions/commandActions';
import scrollPositions from 'Store/scrollPositions';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createSeriesClientSideCollectionItemsSelector from 'Store/Selectors/createSeriesClientSideCollectionItemsSelector';
import translate from 'Utilities/String/translate';
import SeriesIndexFilterMenu from './Menus/SeriesIndexFilterMenu';
import SeriesIndexSortMenu from './Menus/SeriesIndexSortMenu';
@@ -76,19 +67,16 @@ interface SeriesIndexProps {
const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
const {
isFetching,
isPopulated,
error,
isLoading: isFetching,
isFetched,
isError: error,
data,
totalItems,
items,
columns,
selectedFilterKey,
filters,
sortKey,
sortDirection,
view,
}: SeriesAppState & SeriesIndexAppState & ClientSideCollectionAppState =
useSelector(createSeriesClientSideCollectionItemsSelector('seriesIndex'));
} = useSeriesIndex();
const { selectedFilterKey, sortKey, sortDirection, view, columns } =
useSeriesOptions();
const filters = FILTERS;
const customFilters = useCustomFiltersList('series');
@@ -104,10 +92,6 @@ const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
);
const [isSelectMode, setIsSelectMode] = useState(false);
useEffect(() => {
dispatch(fetchSeries());
}, [dispatch]);
const onRssSyncPress = useCallback(() => {
dispatch(
executeCommand({
@@ -120,37 +104,33 @@ const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
setIsSelectMode(!isSelectMode);
}, [isSelectMode, setIsSelectMode]);
const onTableOptionChange = useCallback(
(payload: unknown) => {
dispatch(setSeriesTableOption(payload));
},
[dispatch]
);
const onTableOptionChange = useCallback((payload: unknown) => {
setSeriesTableOptions(
payload as Partial<{ showBanners: boolean; showSearchAction: boolean }>
);
}, []);
const onViewSelect = useCallback(
(value: string) => {
dispatch(setSeriesView({ view: value }));
setSeriesOption('view', value);
if (scrollerRef.current) {
scrollerRef.current.scrollTo(0, 0);
}
},
[scrollerRef, dispatch]
[scrollerRef]
);
const onSortSelect = useCallback(
(value: string) => {
dispatch(setSeriesSort({ sortKey: value }));
setSeriesSort({ sortKey: value, sortDirection });
},
[dispatch]
[sortDirection]
);
const onFilterSelect = useCallback(
(value: string | number) => {
dispatch(setSeriesFilter({ selectedFilterKey: value }));
},
[dispatch]
);
const onFilterSelect = useCallback((value: string | number) => {
setSeriesOption('selectedFilterKey', value);
}, []);
const onOptionsPress = useCallback(() => {
setIsOptionsModalOpen(true);
@@ -184,7 +164,7 @@ const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
};
}
const characters = items.reduce((acc: Record<string, number>, item) => {
const characters = data.reduce((acc: Record<string, number>, item) => {
let char = item.sortTitle.charAt(0);
if (!isNaN(Number(char))) {
@@ -211,15 +191,15 @@ const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
characters,
order,
};
}, [items, sortKey, sortDirection]);
}, [data, sortKey, sortDirection]);
const ViewComponent = useMemo(() => getViewComponent(view), [view]);
const isLoaded = !!(!error && isPopulated && items.length);
const isLoaded = !!(!error && isFetched && data.length);
const hasNoSeries = !totalItems;
return (
<QueueDetailsProvider all={true}>
<SelectProvider items={items}>
<SelectProvider items={data}>
<PageContent>
<PageToolbar>
<PageToolbarSection>
@@ -318,7 +298,7 @@ const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
initialScrollTop={props.initialScrollTop}
onScroll={onScroll}
>
{isFetching && !isPopulated ? <LoadingIndicator /> : null}
{isFetching && !isFetched ? <LoadingIndicator /> : null}
{!isFetching && !!error ? (
<Alert kind={kinds.DANGER}>
@@ -330,7 +310,7 @@ const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
<div className={styles.contentBodyContainer}>
<ViewComponent
scrollerRef={scrollerRef}
items={items}
items={data}
sortKey={sortKey}
sortDirection={sortDirection}
jumpToCharacter={jumpToCharacter}
@@ -342,7 +322,7 @@ const SeriesIndex = withScrollPosition((props: SeriesIndexProps) => {
</div>
) : null}
{!error && isPopulated && !items.length ? (
{!error && isFetched && !data.length ? (
<NoSeries totalItems={totalItems} />
) : null}
</PageContentBody>