|
|
@ -6,6 +6,7 @@ import RequestModal from '@app/components/RequestModal';
|
|
|
|
import ErrorCard from '@app/components/TitleCard/ErrorCard';
|
|
|
|
import ErrorCard from '@app/components/TitleCard/ErrorCard';
|
|
|
|
import Placeholder from '@app/components/TitleCard/Placeholder';
|
|
|
|
import Placeholder from '@app/components/TitleCard/Placeholder';
|
|
|
|
import { useIsTouch } from '@app/hooks/useIsTouch';
|
|
|
|
import { useIsTouch } from '@app/hooks/useIsTouch';
|
|
|
|
|
|
|
|
import useSettings from '@app/hooks/useSettings';
|
|
|
|
import { Permission, useUser } from '@app/hooks/useUser';
|
|
|
|
import { Permission, useUser } from '@app/hooks/useUser';
|
|
|
|
import globalMessages from '@app/i18n/globalMessages';
|
|
|
|
import globalMessages from '@app/i18n/globalMessages';
|
|
|
|
import { withProperties } from '@app/utils/typeHelpers';
|
|
|
|
import { withProperties } from '@app/utils/typeHelpers';
|
|
|
@ -26,6 +27,7 @@ interface TitleCardProps {
|
|
|
|
userScore?: number;
|
|
|
|
userScore?: number;
|
|
|
|
mediaType: MediaType;
|
|
|
|
mediaType: MediaType;
|
|
|
|
status?: MediaStatus;
|
|
|
|
status?: MediaStatus;
|
|
|
|
|
|
|
|
status4k?: MediaStatus;
|
|
|
|
canExpand?: boolean;
|
|
|
|
canExpand?: boolean;
|
|
|
|
inProgress?: boolean;
|
|
|
|
inProgress?: boolean;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -37,6 +39,7 @@ const TitleCard = ({
|
|
|
|
year,
|
|
|
|
year,
|
|
|
|
title,
|
|
|
|
title,
|
|
|
|
status,
|
|
|
|
status,
|
|
|
|
|
|
|
|
status4k,
|
|
|
|
mediaType,
|
|
|
|
mediaType,
|
|
|
|
inProgress = false,
|
|
|
|
inProgress = false,
|
|
|
|
canExpand = false,
|
|
|
|
canExpand = false,
|
|
|
@ -46,8 +49,11 @@ const TitleCard = ({
|
|
|
|
const { hasPermission } = useUser();
|
|
|
|
const { hasPermission } = useUser();
|
|
|
|
const [isUpdating, setIsUpdating] = useState(false);
|
|
|
|
const [isUpdating, setIsUpdating] = useState(false);
|
|
|
|
const [currentStatus, setCurrentStatus] = useState(status);
|
|
|
|
const [currentStatus, setCurrentStatus] = useState(status);
|
|
|
|
|
|
|
|
const [currentStatus4k, setCurrentStatus4k] = useState(status4k);
|
|
|
|
const [showDetail, setShowDetail] = useState(false);
|
|
|
|
const [showDetail, setShowDetail] = useState(false);
|
|
|
|
const [showRequestModal, setShowRequestModal] = useState(false);
|
|
|
|
const [showRequestModal, setShowRequestModal] = useState(false);
|
|
|
|
|
|
|
|
const [showRequestModal4k, setShowRequestModal4k] = useState(false);
|
|
|
|
|
|
|
|
const settings = useSettings();
|
|
|
|
|
|
|
|
|
|
|
|
// Just to get the year from the date
|
|
|
|
// Just to get the year from the date
|
|
|
|
if (year) {
|
|
|
|
if (year) {
|
|
|
@ -56,7 +62,8 @@ const TitleCard = ({
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
useEffect(() => {
|
|
|
|
setCurrentStatus(status);
|
|
|
|
setCurrentStatus(status);
|
|
|
|
}, [status]);
|
|
|
|
setCurrentStatus4k(status4k);
|
|
|
|
|
|
|
|
}, [status, status4k]);
|
|
|
|
|
|
|
|
|
|
|
|
const requestComplete = useCallback((newStatus: MediaStatus) => {
|
|
|
|
const requestComplete = useCallback((newStatus: MediaStatus) => {
|
|
|
|
setCurrentStatus(newStatus);
|
|
|
|
setCurrentStatus(newStatus);
|
|
|
@ -70,7 +77,15 @@ const TitleCard = ({
|
|
|
|
|
|
|
|
|
|
|
|
const closeModal = useCallback(() => setShowRequestModal(false), []);
|
|
|
|
const closeModal = useCallback(() => setShowRequestModal(false), []);
|
|
|
|
|
|
|
|
|
|
|
|
const showRequestButton = hasPermission(
|
|
|
|
const requestComplete4k = useCallback((newStatus: MediaStatus) => {
|
|
|
|
|
|
|
|
setCurrentStatus4k(newStatus);
|
|
|
|
|
|
|
|
setShowRequestModal4k(false);
|
|
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const closeModal4k = useCallback(() => setShowRequestModal4k(false), []);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const showRequestButton =
|
|
|
|
|
|
|
|
hasPermission(
|
|
|
|
[
|
|
|
|
[
|
|
|
|
Permission.REQUEST,
|
|
|
|
Permission.REQUEST,
|
|
|
|
mediaType === 'movie' || mediaType === 'collection'
|
|
|
|
mediaType === 'movie' || mediaType === 'collection'
|
|
|
@ -78,7 +93,28 @@ const TitleCard = ({
|
|
|
|
: Permission.REQUEST_TV,
|
|
|
|
: Permission.REQUEST_TV,
|
|
|
|
],
|
|
|
|
],
|
|
|
|
{ type: 'or' }
|
|
|
|
{ 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 (
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
<div
|
|
|
@ -99,6 +135,21 @@ const TitleCard = ({
|
|
|
|
onUpdating={requestUpdating}
|
|
|
|
onUpdating={requestUpdating}
|
|
|
|
onCancel={closeModal}
|
|
|
|
onCancel={closeModal}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
<RequestModal
|
|
|
|
|
|
|
|
tmdbId={id}
|
|
|
|
|
|
|
|
show={showRequestModal4k}
|
|
|
|
|
|
|
|
type={
|
|
|
|
|
|
|
|
mediaType === 'movie'
|
|
|
|
|
|
|
|
? 'movie'
|
|
|
|
|
|
|
|
: mediaType === 'collection'
|
|
|
|
|
|
|
|
? 'collection'
|
|
|
|
|
|
|
|
: 'tv'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
onComplete={requestComplete4k}
|
|
|
|
|
|
|
|
onUpdating={requestUpdating}
|
|
|
|
|
|
|
|
onCancel={closeModal4k}
|
|
|
|
|
|
|
|
is4k
|
|
|
|
|
|
|
|
/>
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
className={`relative transform-gpu cursor-default overflow-hidden rounded-xl bg-gray-800 bg-cover outline-none ring-1 transition duration-300 ${
|
|
|
|
className={`relative transform-gpu cursor-default overflow-hidden rounded-xl bg-gray-800 bg-cover outline-none ring-1 transition duration-300 ${
|
|
|
|
showDetail
|
|
|
|
showDetail
|
|
|
@ -151,16 +202,25 @@ const TitleCard = ({
|
|
|
|
: intl.formatMessage(globalMessages.tvshow)}
|
|
|
|
: intl.formatMessage(globalMessages.tvshow)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</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
|
|
|
|
<StatusBadgeMini
|
|
|
|
status={currentStatus}
|
|
|
|
status={currentStatus}
|
|
|
|
inProgress={inProgress}
|
|
|
|
inProgress={inProgress}
|
|
|
|
shrink
|
|
|
|
shrink
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
|
|
|
|
currentStatus4k &&
|
|
|
|
|
|
|
|
currentStatus4k !== MediaStatus.UNKNOWN && (
|
|
|
|
|
|
|
|
<StatusBadgeMini
|
|
|
|
|
|
|
|
status={currentStatus4k}
|
|
|
|
|
|
|
|
inProgress={inProgress}
|
|
|
|
|
|
|
|
shrink
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<Transition
|
|
|
|
<Transition
|
|
|
|
as={Fragment}
|
|
|
|
as={Fragment}
|
|
|
|
show={isUpdating}
|
|
|
|
show={isUpdating}
|
|
|
@ -178,7 +238,9 @@ const TitleCard = ({
|
|
|
|
|
|
|
|
|
|
|
|
<Transition
|
|
|
|
<Transition
|
|
|
|
as={Fragment}
|
|
|
|
as={Fragment}
|
|
|
|
show={!image || showDetail || showRequestModal}
|
|
|
|
show={
|
|
|
|
|
|
|
|
!image || showDetail || showRequestModal || showRequestModal4k
|
|
|
|
|
|
|
|
}
|
|
|
|
enter="transition-opacity"
|
|
|
|
enter="transition-opacity"
|
|
|
|
enterFrom="opacity-0"
|
|
|
|
enterFrom="opacity-0"
|
|
|
|
enterTo="opacity-100"
|
|
|
|
enterTo="opacity-100"
|
|
|
@ -206,10 +268,7 @@ const TitleCard = ({
|
|
|
|
<div className="flex h-full w-full items-end">
|
|
|
|
<div className="flex h-full w-full items-end">
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
className={`px-2 text-white ${
|
|
|
|
className={`px-2 text-white ${
|
|
|
|
!showRequestButton ||
|
|
|
|
!isRequestable ? 'pb-2' : 'pb-11'
|
|
|
|
(currentStatus && currentStatus !== MediaStatus.UNKNOWN)
|
|
|
|
|
|
|
|
? 'pb-2'
|
|
|
|
|
|
|
|
: 'pb-11'
|
|
|
|
|
|
|
|
}`}
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{year && (
|
|
|
|
{year && (
|
|
|
@ -232,12 +291,7 @@ const TitleCard = ({
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
className="whitespace-normal text-xs"
|
|
|
|
className="whitespace-normal text-xs"
|
|
|
|
style={{
|
|
|
|
style={{
|
|
|
|
WebkitLineClamp:
|
|
|
|
WebkitLineClamp: !isRequestable ? 5 : 3,
|
|
|
|
!showRequestButton ||
|
|
|
|
|
|
|
|
(currentStatus &&
|
|
|
|
|
|
|
|
currentStatus !== MediaStatus.UNKNOWN)
|
|
|
|
|
|
|
|
? 5
|
|
|
|
|
|
|
|
: 3,
|
|
|
|
|
|
|
|
display: '-webkit-box',
|
|
|
|
display: '-webkit-box',
|
|
|
|
overflow: 'hidden',
|
|
|
|
overflow: 'hidden',
|
|
|
|
WebkitBoxOrient: 'vertical',
|
|
|
|
WebkitBoxOrient: 'vertical',
|
|
|
@ -253,7 +307,7 @@ const TitleCard = ({
|
|
|
|
|
|
|
|
|
|
|
|
<div className="absolute bottom-0 left-0 right-0 flex justify-between px-2 py-2">
|
|
|
|
<div className="absolute bottom-0 left-0 right-0 flex justify-between px-2 py-2">
|
|
|
|
{showRequestButton &&
|
|
|
|
{showRequestButton &&
|
|
|
|
(!currentStatus || currentStatus === MediaStatus.UNKNOWN) && (
|
|
|
|
(!currentStatus || currentStatus === MediaStatus.UNKNOWN) ? (
|
|
|
|
<Button
|
|
|
|
<Button
|
|
|
|
buttonType="primary"
|
|
|
|
buttonType="primary"
|
|
|
|
buttonSize="sm"
|
|
|
|
buttonSize="sm"
|
|
|
@ -266,6 +320,25 @@ const TitleCard = ({
|
|
|
|
<ArrowDownTrayIcon />
|
|
|
|
<ArrowDownTrayIcon />
|
|
|
|
<span>{intl.formatMessage(globalMessages.request)}</span>
|
|
|
|
<span>{intl.formatMessage(globalMessages.request)}</span>
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
) : (
|
|
|
|
|
|
|
|
showRequestButton4k &&
|
|
|
|
|
|
|
|
(!currentStatus4k ||
|
|
|
|
|
|
|
|
currentStatus4k === MediaStatus.UNKNOWN) && (
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
|
|
|
buttonType="primary"
|
|
|
|
|
|
|
|
buttonSize="sm"
|
|
|
|
|
|
|
|
onClick={(e) => {
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
setShowRequestModal4k(true);
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
className="h-7 w-full"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<ArrowDownTrayIcon />
|
|
|
|
|
|
|
|
<span>
|
|
|
|
|
|
|
|
{intl.formatMessage(globalMessages.request4k)}
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|