/* eslint-disable react-hooks/exhaustive-deps */ import { Listbox, Transition } from '@headlessui/react'; import React, { useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; import type { ServiceCommonServer, ServiceCommonServerWithDetails, } from '../../../../server/interfaces/api/serviceInterfaces'; import type { UserResultsResponse } from '../../../../server/interfaces/api/userInterfaces'; import { Permission, User, useUser } from '../../../hooks/useUser'; import globalMessages from '../../../i18n/globalMessages'; import { formatBytes } from '../../../utils/numberHelpers'; import { SmallLoadingSpinner } from '../../Common/LoadingSpinner'; const messages = defineMessages({ advancedoptions: 'Advanced Options', destinationserver: 'Destination Server', qualityprofile: 'Quality Profile', rootfolder: 'Root Folder', animenote: '* This series is an anime.', default: '{name} (Default)', folder: '{path} ({space})', requestas: 'Request As', languageprofile: 'Language Profile', }); export type RequestOverrides = { server?: number; profile?: number; folder?: string; language?: number; user?: User; }; interface AdvancedRequesterProps { type: 'movie' | 'tv'; is4k: boolean; isAnime?: boolean; defaultOverrides?: RequestOverrides; requestUser?: User; onChange: (overrides: RequestOverrides) => void; } const AdvancedRequester: React.FC = ({ type, is4k = false, isAnime = false, defaultOverrides, requestUser, onChange, }) => { const intl = useIntl(); const { user, hasPermission } = useUser(); const { data, error } = useSWR( `/api/v1/service/${type === 'movie' ? 'radarr' : 'sonarr'}`, { refreshInterval: 0, refreshWhenHidden: false, revalidateOnFocus: false, revalidateOnMount: true, } ); const [selectedServer, setSelectedServer] = useState( defaultOverrides?.server !== undefined && defaultOverrides?.server >= 0 ? defaultOverrides?.server : null ); const [selectedProfile, setSelectedProfile] = useState( defaultOverrides?.profile ?? -1 ); const [selectedFolder, setSelectedFolder] = useState( defaultOverrides?.folder ?? '' ); const [selectedLanguage, setSelectedLanguage] = useState( defaultOverrides?.language ?? -1 ); const { data: serverData, isValidating, } = useSWR( selectedServer !== null ? `/api/v1/service/${ type === 'movie' ? 'radarr' : 'sonarr' }/${selectedServer}` : null, { refreshInterval: 0, refreshWhenHidden: false, revalidateOnFocus: false, } ); const [selectedUser, setSelectedUser] = useState( requestUser ?? null ); const { data: userData } = useSWR( hasPermission([Permission.MANAGE_REQUESTS, Permission.MANAGE_USERS]) ? '/api/v1/user?take=1000' : null ); useEffect(() => { if (userData?.results && !requestUser) { setSelectedUser(userData.results.find((u) => u.id === user?.id) ?? null); } }, [userData?.results]); useEffect(() => { let defaultServer = data?.find( (server) => server.isDefault && is4k === server.is4k ); if (!defaultServer && (data ?? []).length > 0) { defaultServer = data?.[0]; } if ( defaultServer && defaultServer.id !== selectedServer && (!defaultOverrides || defaultOverrides.server === null) ) { setSelectedServer(defaultServer.id); } }, [data]); useEffect(() => { if (serverData) { const defaultProfile = serverData.profiles.find( (profile) => profile.id === (isAnime ? serverData.server.activeAnimeProfileId : serverData.server.activeProfileId) ); const defaultFolder = serverData.rootFolders.find( (folder) => folder.path === (isAnime ? serverData.server.activeAnimeDirectory : serverData.server.activeDirectory) ); const defaultLanguage = serverData.languageProfiles?.find( (language) => language.id === (isAnime ? serverData.server.activeAnimeLanguageProfileId : serverData.server.activeLanguageProfileId) ); if ( defaultProfile && defaultProfile.id !== selectedProfile && (!defaultOverrides || defaultOverrides.profile === null) ) { setSelectedProfile(defaultProfile.id); } if ( defaultFolder && defaultFolder.path !== selectedFolder && (!defaultOverrides || defaultOverrides.folder === null) ) { setSelectedFolder(defaultFolder.path ?? ''); } if ( defaultLanguage && defaultLanguage.id !== selectedLanguage && (!defaultOverrides || defaultOverrides.language === null) ) { setSelectedLanguage(defaultLanguage.id); } } }, [serverData]); useEffect(() => { if ( defaultOverrides && defaultOverrides.server !== null && defaultOverrides.server !== undefined ) { setSelectedServer(defaultOverrides.server); } if ( defaultOverrides && defaultOverrides.profile !== null && defaultOverrides.profile !== undefined ) { setSelectedProfile(defaultOverrides.profile); } if ( defaultOverrides && defaultOverrides.folder !== null && defaultOverrides.folder !== undefined ) { setSelectedFolder(defaultOverrides.folder); } if ( defaultOverrides && defaultOverrides.language !== null && defaultOverrides.language !== undefined ) { setSelectedLanguage(defaultOverrides.language); } }, [ defaultOverrides?.server, defaultOverrides?.folder, defaultOverrides?.profile, defaultOverrides?.language, ]); useEffect(() => { if (selectedServer !== null || selectedUser) { onChange({ folder: selectedFolder !== '' ? selectedFolder : undefined, profile: selectedProfile !== -1 ? selectedProfile : undefined, server: selectedServer ?? undefined, user: selectedUser ?? undefined, language: selectedLanguage ?? undefined, }); } }, [ selectedFolder, selectedServer, selectedProfile, selectedUser, selectedLanguage, ]); if (!data && !error) { return (
); } if ((!data || selectedServer === null) && !selectedUser) { return null; } return ( <>
{intl.formatMessage(messages.advancedoptions)}
{!!data && selectedServer !== null && ( <>
{type === 'tv' && (
)}
)} {hasPermission([Permission.MANAGE_REQUESTS, Permission.MANAGE_USERS]) && selectedUser && (
setSelectedUser(value)} className="space-y-1" > {({ open }) => ( <> {intl.formatMessage(messages.requestas)}
{selectedUser.displayName} ({selectedUser.email}) {userData?.results.map((user) => ( {({ selected, active }) => (
{user.displayName} ({user.email}) {selected && ( )}
)}
))}
)}
)} {isAnime && (
{intl.formatMessage(messages.animenote)}
)}
); }; export default AdvancedRequester;