feat: added the ability to request 4k media on the titlecard
This commit is contained in:
@@ -26,6 +26,8 @@ export interface PublicSettingsResponse {
|
||||
applicationUrl: string;
|
||||
hideAvailable: boolean;
|
||||
localLogin: boolean;
|
||||
movieEnabled: boolean;
|
||||
seriesEnabled: boolean;
|
||||
movie4kEnabled: boolean;
|
||||
series4kEnabled: boolean;
|
||||
region: string;
|
||||
|
||||
@@ -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
|
||||
),
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 (
|
||||
<div
|
||||
@@ -99,6 +135,21 @@ const TitleCard = ({
|
||||
onUpdating={requestUpdating}
|
||||
onCancel={closeModal}
|
||||
/>
|
||||
<RequestModal
|
||||
tmdbId={id}
|
||||
show={showRequestModal4k}
|
||||
type={
|
||||
mediaType === 'movie'
|
||||
? 'movie'
|
||||
: mediaType === 'collection'
|
||||
? 'collection'
|
||||
: 'tv'
|
||||
}
|
||||
onComplete={requestComplete4k}
|
||||
onUpdating={requestUpdating}
|
||||
onCancel={closeModal4k}
|
||||
is4k
|
||||
/>
|
||||
<div
|
||||
className={`relative transform-gpu cursor-default overflow-hidden rounded-xl bg-gray-800 bg-cover outline-none ring-1 transition duration-300 ${
|
||||
showDetail
|
||||
@@ -151,15 +202,24 @@ const TitleCard = ({
|
||||
: intl.formatMessage(globalMessages.tvshow)}
|
||||
</div>
|
||||
</div>
|
||||
{currentStatus && currentStatus !== MediaStatus.UNKNOWN && (
|
||||
<div className="pointer-events-none z-40 flex items-center">
|
||||
<div className="pointer-events-none z-40 flex items-center">
|
||||
{currentStatus && currentStatus !== MediaStatus.UNKNOWN ? (
|
||||
<StatusBadgeMini
|
||||
status={currentStatus}
|
||||
inProgress={inProgress}
|
||||
shrink
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
) : (
|
||||
currentStatus4k &&
|
||||
currentStatus4k !== MediaStatus.UNKNOWN && (
|
||||
<StatusBadgeMini
|
||||
status={currentStatus4k}
|
||||
inProgress={inProgress}
|
||||
shrink
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
@@ -178,7 +238,9 @@ const TitleCard = ({
|
||||
|
||||
<Transition
|
||||
as={Fragment}
|
||||
show={!image || showDetail || showRequestModal}
|
||||
show={
|
||||
!image || showDetail || showRequestModal || showRequestModal4k
|
||||
}
|
||||
enter="transition-opacity"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
@@ -206,10 +268,7 @@ const TitleCard = ({
|
||||
<div className="flex h-full w-full items-end">
|
||||
<div
|
||||
className={`px-2 text-white ${
|
||||
!showRequestButton ||
|
||||
(currentStatus && currentStatus !== MediaStatus.UNKNOWN)
|
||||
? 'pb-2'
|
||||
: 'pb-11'
|
||||
!isRequestable ? 'pb-2' : 'pb-11'
|
||||
}`}
|
||||
>
|
||||
{year && (
|
||||
@@ -232,12 +291,7 @@ const TitleCard = ({
|
||||
<div
|
||||
className="whitespace-normal text-xs"
|
||||
style={{
|
||||
WebkitLineClamp:
|
||||
!showRequestButton ||
|
||||
(currentStatus &&
|
||||
currentStatus !== MediaStatus.UNKNOWN)
|
||||
? 5
|
||||
: 3,
|
||||
WebkitLineClamp: !isRequestable ? 5 : 3,
|
||||
display: '-webkit-box',
|
||||
overflow: 'hidden',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
@@ -253,20 +307,39 @@ const TitleCard = ({
|
||||
|
||||
<div className="absolute bottom-0 left-0 right-0 flex justify-between px-2 py-2">
|
||||
{showRequestButton &&
|
||||
(!currentStatus || currentStatus === MediaStatus.UNKNOWN) && (
|
||||
(!currentStatus || currentStatus === MediaStatus.UNKNOWN) ? (
|
||||
<Button
|
||||
buttonType="primary"
|
||||
buttonSize="sm"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setShowRequestModal(true);
|
||||
}}
|
||||
className="h-7 w-full"
|
||||
>
|
||||
<ArrowDownTrayIcon />
|
||||
<span>{intl.formatMessage(globalMessages.request)}</span>
|
||||
</Button>
|
||||
) : (
|
||||
showRequestButton4k &&
|
||||
(!currentStatus4k ||
|
||||
currentStatus4k === MediaStatus.UNKNOWN) && (
|
||||
<Button
|
||||
buttonType="primary"
|
||||
buttonSize="sm"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setShowRequestModal(true);
|
||||
setShowRequestModal4k(true);
|
||||
}}
|
||||
className="h-7 w-full"
|
||||
>
|
||||
<ArrowDownTrayIcon />
|
||||
<span>{intl.formatMessage(globalMessages.request)}</span>
|
||||
<span>
|
||||
{intl.formatMessage(globalMessages.request4k)}
|
||||
</span>
|
||||
</Button>
|
||||
)}
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
@@ -13,6 +13,8 @@ const defaultSettings = {
|
||||
applicationUrl: '',
|
||||
hideAvailable: false,
|
||||
localLogin: true,
|
||||
movieEnabled: false,
|
||||
seriesEnabled: false,
|
||||
movie4kEnabled: false,
|
||||
series4kEnabled: false,
|
||||
region: '',
|
||||
|
||||
@@ -174,6 +174,8 @@ CoreApp.getInitialProps = async (initialProps) => {
|
||||
applicationTitle: '',
|
||||
applicationUrl: '',
|
||||
hideAvailable: false,
|
||||
movieEnabled: false,
|
||||
seriesEnabled: false,
|
||||
movie4kEnabled: false,
|
||||
series4kEnabled: false,
|
||||
localLogin: true,
|
||||
|
||||
Reference in New Issue
Block a user