diff --git a/server/interfaces/api/settingsInterfaces.ts b/server/interfaces/api/settingsInterfaces.ts index 0cd2f171a..e5ec544d2 100644 --- a/server/interfaces/api/settingsInterfaces.ts +++ b/server/interfaces/api/settingsInterfaces.ts @@ -26,6 +26,8 @@ export interface PublicSettingsResponse { applicationUrl: string; hideAvailable: boolean; localLogin: boolean; + movieEnabled: boolean; + seriesEnabled: boolean; movie4kEnabled: boolean; series4kEnabled: boolean; region: string; diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 082e733fc..9fd83a1dc 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -115,6 +115,8 @@ interface FullPublicSettings extends PublicSettings { applicationUrl: string; hideAvailable: boolean; localLogin: boolean; + movieEnabled: boolean; + seriesEnabled: boolean; movie4kEnabled: boolean; series4kEnabled: boolean; region: string; @@ -491,6 +493,12 @@ class Settings { applicationUrl: this.data.main.applicationUrl, hideAvailable: this.data.main.hideAvailable, localLogin: this.data.main.localLogin, + movieEnabled: this.data.radarr.some( + (radarr) => !radarr.is4k && radarr.isDefault + ), + seriesEnabled: this.data.sonarr.some( + (sonarr) => !sonarr.is4k && sonarr.isDefault + ), movie4kEnabled: this.data.radarr.some( (radarr) => radarr.is4k && radarr.isDefault ), diff --git a/src/components/MediaSlider/index.tsx b/src/components/MediaSlider/index.tsx index 54b5cc801..020a25158 100644 --- a/src/components/MediaSlider/index.tsx +++ b/src/components/MediaSlider/index.tsx @@ -98,6 +98,7 @@ const MediaSlider = ({ id={title.id} image={title.posterPath} status={title.mediaInfo?.status} + status4k={title.mediaInfo?.status4k} summary={title.overview} title={title.title} userScore={title.voteAverage} @@ -112,6 +113,7 @@ const MediaSlider = ({ id={title.id} image={title.posterPath} status={title.mediaInfo?.status} + status4k={title.mediaInfo?.status4k} summary={title.overview} title={title.name} userScore={title.voteAverage} diff --git a/src/components/PersonDetails/index.tsx b/src/components/PersonDetails/index.tsx index f4d489d52..7d758679a 100644 --- a/src/components/PersonDetails/index.tsx +++ b/src/components/PersonDetails/index.tsx @@ -185,6 +185,7 @@ const PersonDetails = () => { summary={media.overview} mediaType={media.mediaType as 'movie' | 'tv'} status={media.mediaInfo?.status} + status4k={media.mediaInfo?.status} canExpand /> {media.job && ( diff --git a/src/components/TitleCard/TmdbTitleCard.tsx b/src/components/TitleCard/TmdbTitleCard.tsx index f031c9977..50b348a49 100644 --- a/src/components/TitleCard/TmdbTitleCard.tsx +++ b/src/components/TitleCard/TmdbTitleCard.tsx @@ -59,6 +59,7 @@ const TmdbTitleCard = ({ id={title.id} image={title.posterPath} status={title.mediaInfo?.status} + status4k={title.mediaInfo?.status4k} summary={title.overview} title={title.title} userScore={title.voteAverage} @@ -71,6 +72,7 @@ const TmdbTitleCard = ({ id={title.id} image={title.posterPath} status={title.mediaInfo?.status} + status4k={title.mediaInfo?.status4k} summary={title.overview} title={title.name} userScore={title.voteAverage} diff --git a/src/components/TitleCard/index.tsx b/src/components/TitleCard/index.tsx index 9056fd57e..6cc7eea97 100644 --- a/src/components/TitleCard/index.tsx +++ b/src/components/TitleCard/index.tsx @@ -6,6 +6,7 @@ import RequestModal from '@app/components/RequestModal'; import ErrorCard from '@app/components/TitleCard/ErrorCard'; import Placeholder from '@app/components/TitleCard/Placeholder'; import { useIsTouch } from '@app/hooks/useIsTouch'; +import useSettings from '@app/hooks/useSettings'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import { withProperties } from '@app/utils/typeHelpers'; @@ -26,6 +27,7 @@ interface TitleCardProps { userScore?: number; mediaType: MediaType; status?: MediaStatus; + status4k?: MediaStatus; canExpand?: boolean; inProgress?: boolean; } @@ -37,6 +39,7 @@ const TitleCard = ({ year, title, status, + status4k, mediaType, inProgress = false, canExpand = false, @@ -46,8 +49,11 @@ const TitleCard = ({ const { hasPermission } = useUser(); const [isUpdating, setIsUpdating] = useState(false); const [currentStatus, setCurrentStatus] = useState(status); + const [currentStatus4k, setCurrentStatus4k] = useState(status4k); const [showDetail, setShowDetail] = useState(false); const [showRequestModal, setShowRequestModal] = useState(false); + const [showRequestModal4k, setShowRequestModal4k] = useState(false); + const settings = useSettings(); // Just to get the year from the date if (year) { @@ -56,7 +62,8 @@ const TitleCard = ({ useEffect(() => { setCurrentStatus(status); - }, [status]); + setCurrentStatus4k(status4k); + }, [status, status4k]); const requestComplete = useCallback((newStatus: MediaStatus) => { setCurrentStatus(newStatus); @@ -70,15 +77,44 @@ const TitleCard = ({ const closeModal = useCallback(() => setShowRequestModal(false), []); - const showRequestButton = hasPermission( - [ - Permission.REQUEST, - mediaType === 'movie' || mediaType === 'collection' - ? Permission.REQUEST_MOVIE - : Permission.REQUEST_TV, - ], - { type: 'or' } - ); + const requestComplete4k = useCallback((newStatus: MediaStatus) => { + setCurrentStatus4k(newStatus); + setShowRequestModal4k(false); + }, []); + + const closeModal4k = useCallback(() => setShowRequestModal4k(false), []); + + const showRequestButton = + hasPermission( + [ + Permission.REQUEST, + mediaType === 'movie' || mediaType === 'collection' + ? Permission.REQUEST_MOVIE + : Permission.REQUEST_TV, + ], + { type: 'or' } + ) && + ((settings.currentSettings.movieEnabled && mediaType === 'movie') || + (settings.currentSettings.seriesEnabled && mediaType === 'tv')); + + const showRequestButton4k = + hasPermission( + [ + Permission.REQUEST_4K, + mediaType === 'movie' || mediaType === 'collection' + ? Permission.REQUEST_4K_MOVIE + : Permission.REQUEST_4K_TV, + ], + { type: 'or' } + ) && + ((settings.currentSettings.movie4kEnabled && mediaType === 'movie') || + (settings.currentSettings.series4kEnabled && mediaType === 'tv')); + + const isRequestable = + (showRequestButton && + (!currentStatus || currentStatus === MediaStatus.UNKNOWN)) || + (showRequestButton4k && + (!currentStatus4k || currentStatus4k === MediaStatus.UNKNOWN)); return (
+