1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-28 23:16:32 -04:00

Use react-query for Media Management settings

This commit is contained in:
Mark McDowall
2026-02-01 13:23:17 -08:00
parent 1d8da79172
commit bbb4c6714c
7 changed files with 85 additions and 135 deletions
@@ -24,7 +24,6 @@ import IndexerFlag from 'typings/IndexerFlag';
import DownloadClientOptions from 'typings/Settings/DownloadClientOptions';
import General from 'typings/Settings/General';
import IndexerOptions from 'typings/Settings/IndexerOptions';
import MediaManagement from 'typings/Settings/MediaManagement';
type Presets<T> = T & {
presets: T[];
@@ -62,10 +61,6 @@ export interface GeneralAppState
extends AppSectionItemState<General>,
AppSectionSaveState {}
export interface MediaManagementAppState
extends AppSectionItemState<MediaManagement>,
AppSectionSaveState {}
export interface NamingAppState
extends AppSectionItemState<NamingSettingsModel>,
AppSectionSaveState {}
@@ -134,7 +129,6 @@ interface SettingsAppState {
indexerOptions: IndexerOptionsAppState;
indexers: IndexerAppState;
languages: LanguageSettingsAppState;
mediaManagement: MediaManagementAppState;
naming: NamingAppState;
namingExamples: NamingExamplesAppState;
}
@@ -1,5 +1,4 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import React, { useCallback, useRef, useState } from 'react';
import Alert from 'Components/Alert';
import FieldSet from 'Components/FieldSet';
import Form from 'Components/Form/Form';
@@ -14,21 +13,16 @@ import { inputTypes, kinds, sizes } from 'Helpers/Props';
import RootFolders from 'RootFolder/RootFolders';
import { useShowAdvancedSettings } from 'Settings/advancedSettingsStore';
import SettingsToolbar from 'Settings/SettingsToolbar';
import { clearPendingChanges } from 'Store/Actions/baseActions';
import {
fetchMediaManagementSettings,
saveMediaManagementSettings,
setMediaManagementSettingsValue,
} from 'Store/Actions/settingsActions';
import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
import { useIsWindows } from 'System/Status/useSystemStatus';
import { InputChanged } from 'typings/inputs';
import { SettingsStateChange } from 'typings/Settings/SettingsState';
import translate from 'Utilities/String/translate';
import Naming from './Naming/Naming';
import AddRootFolder from './RootFolder/AddRootFolder';
const SECTION = 'mediaManagement';
import {
MediaManagementSettingsModel,
useManageMediaManagementSettings,
} from './useMediaManagementSettings';
const episodeTitleRequiredOptions: EnhancedSelectInputValue<string>[] = [
{
@@ -136,14 +130,12 @@ const seasonPackUpgradeOptions: EnhancedSelectInputValue<string>[] = [
];
function MediaManagement() {
const dispatch = useDispatch();
const showAdvancedSettings = useShowAdvancedSettings();
const isWindows = useIsWindows();
const {
isFetching,
isPopulated,
isFetched: isPopulated,
isSaving,
error,
settings,
@@ -151,7 +143,9 @@ function MediaManagement() {
hasPendingChanges,
validationErrors,
validationWarnings,
} = useSelector(createSettingsSectionSelector(SECTION));
saveSettings: saveMediaManagementSettings,
updateSetting,
} = useManageMediaManagementSettings();
const [naming, setNaming] = useState<SettingsStateChange>({
isSaving: false,
@@ -169,26 +163,20 @@ function MediaManagement() {
}, []);
const handleSavePress = useCallback(() => {
dispatch(saveMediaManagementSettings());
saveMediaManagementSettings();
saveSettings.current.naming();
}, [dispatch]);
}, [saveMediaManagementSettings]);
const handleInputChange = useCallback(
(change: InputChanged) => {
// @ts-expect-error - actions are not typed
dispatch(setMediaManagementSettingsValue(change));
updateSetting(
change.name as keyof MediaManagementSettingsModel,
change.value as MediaManagementSettingsModel[keyof MediaManagementSettingsModel]
);
},
[dispatch]
[updateSetting]
);
useEffect(() => {
dispatch(fetchMediaManagementSettings());
return () => {
dispatch(clearPendingChanges({ section: `settings.${SECTION}` }));
};
}, [dispatch]);
return (
<PageContent title={translate('MediaManagementSettings')}>
<SettingsToolbar
@@ -0,0 +1,65 @@
import { useCallback } from 'react';
import {
useManageSettings,
useSaveSettings,
useSettings,
} from 'Settings/useSettings';
export interface MediaManagementSettingsModel {
createEmptySeriesFolders: boolean;
deleteEmptyFolders: boolean;
episodeTitleRequired: string;
skipFreeSpaceCheckWhenImporting: boolean;
minimumFreeSpaceWhenImporting: number;
copyUsingHardlinks: boolean;
useScriptImport: boolean;
scriptImportPath: string;
importExtraFiles: boolean;
extraFileExtensions: string;
userRejectedExtensions: string;
autoUnmonitorPreviouslyDownloadedEpisodes: boolean;
downloadPropersAndRepacks: string;
enableMediaInfo: boolean;
rescanAfterRefresh: string;
setPermissionsLinux: boolean;
chmodFolder: string;
chownGroup: string;
fileDate: string;
recycleBin: string;
recycleBinCleanupDays: number;
allowFingerprinting: string;
seasonPackUpgrade: string;
seasonPackUpgradeThreshold: number;
}
const PATH = '/settings/mediamanagement';
export const useMediaManagementSettingsValues = () => {
const { data } = useSettings<MediaManagementSettingsModel>(PATH);
return data;
};
export const useMediaManagementSettings = () => {
return useSettings<MediaManagementSettingsModel>(PATH);
};
export const useManageMediaManagementSettings = () => {
return useManageSettings<MediaManagementSettingsModel>(PATH);
};
export const useSaveMediaManagementSettings = () => {
const { data } = useSettings<MediaManagementSettingsModel>(PATH);
const { save } = useSaveSettings<MediaManagementSettingsModel>(PATH);
const saveSettings = useCallback(
(changes: Partial<MediaManagementSettingsModel>) => {
const updatedSettings = { ...data, ...changes };
save(updatedSettings);
},
[data, save]
);
return saveSettings;
};
+1 -4
View File
@@ -40,10 +40,7 @@ export const useSaveUiSettings = () => {
const saveSettings = useCallback(
(changes: Partial<UiSettingsModel>) => {
const updatedSettings = {
...data,
...changes,
};
const updatedSettings = { ...data, ...changes };
save(updatedSettings);
},
@@ -1,64 +0,0 @@
import { createAction } from 'redux-actions';
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
import { createThunk } from 'Store/thunks';
//
// Variables
const section = 'settings.mediaManagement';
//
// Actions Types
export const FETCH_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/fetchMediaManagementSettings';
export const SAVE_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/saveMediaManagementSettings';
export const SET_MEDIA_MANAGEMENT_SETTINGS_VALUE = 'settings/mediaManagement/setMediaManagementSettingsValue';
//
// Action Creators
export const fetchMediaManagementSettings = createThunk(FETCH_MEDIA_MANAGEMENT_SETTINGS);
export const saveMediaManagementSettings = createThunk(SAVE_MEDIA_MANAGEMENT_SETTINGS);
export const setMediaManagementSettingsValue = createAction(SET_MEDIA_MANAGEMENT_SETTINGS_VALUE, (payload) => {
return {
section,
...payload
};
});
//
// Details
export default {
//
// State
defaultState: {
isFetching: false,
isPopulated: false,
error: null,
pendingChanges: {},
isSaving: false,
saveError: null,
item: {}
},
//
// Action Handlers
actionHandlers: {
[FETCH_MEDIA_MANAGEMENT_SETTINGS]: createFetchHandler(section, '/config/mediamanagement'),
[SAVE_MEDIA_MANAGEMENT_SETTINGS]: createSaveHandler(section, '/config/mediamanagement')
},
//
// Reducers
reducers: {
[SET_MEDIA_MANAGEMENT_SETTINGS_VALUE]: createSetSettingValueReducer(section)
}
};
@@ -15,7 +15,6 @@ import indexerFlags from './Settings/indexerFlags';
import indexerOptions from './Settings/indexerOptions';
import indexers from './Settings/indexers';
import languages from './Settings/languages';
import mediaManagement from './Settings/mediaManagement';
export * from './Settings/autoTaggingSpecifications';
export * from './Settings/autoTaggings';
@@ -32,7 +31,6 @@ export * from './Settings/indexerFlags';
export * from './Settings/indexerOptions';
export * from './Settings/indexers';
export * from './Settings/languages';
export * from './Settings/mediaManagement';
//
// Variables
@@ -58,8 +56,7 @@ export const defaultState = {
indexerFlags: indexerFlags.defaultState,
indexerOptions: indexerOptions.defaultState,
indexers: indexers.defaultState,
languages: languages.defaultState,
mediaManagement: mediaManagement.defaultState
languages: languages.defaultState
};
export const persistState = [
@@ -84,8 +81,7 @@ export const actionHandlers = handleThunks({
...indexerFlags.actionHandlers,
...indexerOptions.actionHandlers,
...indexers.actionHandlers,
...languages.actionHandlers,
...mediaManagement.actionHandlers
...languages.actionHandlers
});
//
@@ -106,7 +102,6 @@ export const reducers = createHandleActions({
...indexerFlags.reducers,
...indexerOptions.reducers,
...indexers.reducers,
...languages.reducers,
...mediaManagement.reducers
...languages.reducers
}, defaultState, section);
@@ -1,25 +0,0 @@
export default interface MediaManagement {
autoUnmonitorPreviouslyDownloadedEpisodes: boolean;
recycleBin: string;
recycleBinCleanupDays: number;
downloadPropersAndRepacks: string;
createEmptySeriesFolders: boolean;
deleteEmptyFolders: boolean;
fileDate: string;
rescanAfterRefresh: string;
setPermissionsLinux: boolean;
chmodFolder: string;
chownGroup: string;
episodeTitleRequired: string;
skipFreeSpaceCheckWhenImporting: boolean;
minimumFreeSpaceWhenImporting: number;
copyUsingHardlinks: boolean;
useScriptImport: boolean;
scriptImportPath: string;
importExtraFiles: boolean;
extraFileExtensions: string;
userRejectedExtensions: string;
enableMediaInfo: boolean;
seasonPackUpgrade: string;
seasonPackUpgradeThreshold: number;
}