mirror of
https://github.com/sct/overseerr.git
synced 2025-12-30 01:32:38 +01:00
Merge remote-tracking branch 'overseerr/develop' into develop
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import Spinner from '@app/assets/spinner.svg';
|
||||
import Badge from '@app/components/Common/Badge';
|
||||
import Tooltip from '@app/components/Common/Tooltip';
|
||||
import DownloadBlock from '@app/components/DownloadBlock';
|
||||
import useSettings from '@app/hooks/useSettings';
|
||||
import { Permission, useUser } from '@app/hooks/useUser';
|
||||
import globalMessages from '@app/i18n/globalMessages';
|
||||
import { MediaStatus } from '@server/constants/media';
|
||||
import { MediaServerType } from '@server/constants/server';
|
||||
import type { DownloadingItem } from '@server/lib/downloadtracker';
|
||||
import getConfig from 'next/config';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
@@ -15,26 +17,31 @@ const messages = defineMessages({
|
||||
playonplex: 'Play on {mediaServerName}',
|
||||
openinarr: 'Open in {arr}',
|
||||
managemedia: 'Manage {mediaType}',
|
||||
seasonepisodenumber: 'S{seasonNumber}E{episodeNumber}',
|
||||
});
|
||||
|
||||
interface StatusBadgeProps {
|
||||
status?: MediaStatus;
|
||||
downloadItem?: DownloadingItem[];
|
||||
is4k?: boolean;
|
||||
inProgress?: boolean;
|
||||
plexUrl?: string;
|
||||
serviceUrl?: string;
|
||||
tmdbId?: number;
|
||||
mediaType?: 'movie' | 'tv';
|
||||
title?: string | string[];
|
||||
}
|
||||
|
||||
const StatusBadge = ({
|
||||
status,
|
||||
downloadItem = [],
|
||||
is4k = false,
|
||||
inProgress = false,
|
||||
plexUrl,
|
||||
serviceUrl,
|
||||
tmdbId,
|
||||
mediaType,
|
||||
title,
|
||||
}: StatusBadgeProps) => {
|
||||
const intl = useIntl();
|
||||
const { hasPermission } = useUser();
|
||||
@@ -44,6 +51,10 @@ const StatusBadge = ({
|
||||
let mediaLink: string | undefined;
|
||||
let mediaLinkDescription: string | undefined;
|
||||
|
||||
const calculateDownloadProgress = (media: DownloadingItem) => {
|
||||
return Math.round(((media?.size - media?.sizeLeft) / media?.size) * 100);
|
||||
};
|
||||
|
||||
if (
|
||||
mediaType &&
|
||||
plexUrl &&
|
||||
@@ -95,21 +106,87 @@ const StatusBadge = ({
|
||||
}
|
||||
}
|
||||
|
||||
const tooltipContent = (
|
||||
<ul>
|
||||
{downloadItem.map((status, index) => (
|
||||
<li
|
||||
key={`dl-status-${status.externalId}-${index}`}
|
||||
className="border-b border-gray-700 last:border-b-0"
|
||||
>
|
||||
<DownloadBlock
|
||||
downloadItem={status}
|
||||
title={Array.isArray(title) ? title[index] : title}
|
||||
is4k={is4k}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
|
||||
const badgeDownloadProgress = (
|
||||
<div
|
||||
className={`
|
||||
absolute top-0 left-0 z-10 flex h-full ${
|
||||
status === MediaStatus.PROCESSING ? 'bg-indigo-500' : 'bg-green-500'
|
||||
} transition-all duration-200 ease-in-out
|
||||
`}
|
||||
style={{
|
||||
width: `${
|
||||
downloadItem ? calculateDownloadProgress(downloadItem[0]) : 0
|
||||
}%`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
switch (status) {
|
||||
case MediaStatus.AVAILABLE:
|
||||
return (
|
||||
<Tooltip content={mediaLinkDescription}>
|
||||
<Badge badgeType="success" href={mediaLink}>
|
||||
<div className="flex items-center">
|
||||
<Tooltip
|
||||
content={inProgress ? tooltipContent : mediaLinkDescription}
|
||||
className={`${
|
||||
inProgress && 'hidden max-h-96 w-96 overflow-y-auto sm:block'
|
||||
}`}
|
||||
tooltipConfig={{
|
||||
...(inProgress && { interactive: true, delayHide: 100 }),
|
||||
}}
|
||||
>
|
||||
<Badge
|
||||
badgeType="success"
|
||||
href={mediaLink}
|
||||
className={`${
|
||||
inProgress &&
|
||||
'relative !bg-gray-700 !bg-opacity-80 !px-0 hover:!bg-gray-700'
|
||||
} overflow-hidden`}
|
||||
>
|
||||
{inProgress && badgeDownloadProgress}
|
||||
<div
|
||||
className={`relative z-20 flex items-center ${
|
||||
inProgress && 'px-2'
|
||||
}`}
|
||||
>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
is4k ? messages.status4k : messages.status,
|
||||
{
|
||||
status: intl.formatMessage(globalMessages.available),
|
||||
status: inProgress
|
||||
? intl.formatMessage(globalMessages.processing)
|
||||
: intl.formatMessage(globalMessages.available),
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
{inProgress && <Spinner className="ml-1 h-3 w-3" />}
|
||||
{inProgress && (
|
||||
<>
|
||||
{mediaType === 'tv' && (
|
||||
<span className="ml-1">
|
||||
{intl.formatMessage(messages.seasonepisodenumber, {
|
||||
seasonNumber: downloadItem[0].episode?.seasonNumber,
|
||||
episodeNumber: downloadItem[0].episode?.episodeNumber,
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
<Spinner className="ml-1 h-3 w-3" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
@@ -117,20 +194,52 @@ const StatusBadge = ({
|
||||
|
||||
case MediaStatus.PARTIALLY_AVAILABLE:
|
||||
return (
|
||||
<Tooltip content={mediaLinkDescription}>
|
||||
<Badge badgeType="success" href={mediaLink}>
|
||||
<div className="flex items-center">
|
||||
<Tooltip
|
||||
content={inProgress ? tooltipContent : mediaLinkDescription}
|
||||
className={`${
|
||||
inProgress && 'hidden max-h-96 w-96 overflow-y-auto sm:block'
|
||||
}`}
|
||||
tooltipConfig={{
|
||||
...(inProgress && { interactive: true, delayHide: 100 }),
|
||||
}}
|
||||
>
|
||||
<Badge
|
||||
badgeType="success"
|
||||
href={mediaLink}
|
||||
className={`${
|
||||
inProgress &&
|
||||
'relative !bg-gray-700 !bg-opacity-80 !px-0 hover:!bg-gray-700'
|
||||
} overflow-hidden`}
|
||||
>
|
||||
{inProgress && badgeDownloadProgress}
|
||||
<div
|
||||
className={`relative z-20 flex items-center ${
|
||||
inProgress && 'px-2'
|
||||
}`}
|
||||
>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
is4k ? messages.status4k : messages.status,
|
||||
{
|
||||
status: intl.formatMessage(
|
||||
globalMessages.partiallyavailable
|
||||
),
|
||||
status: inProgress
|
||||
? intl.formatMessage(globalMessages.processing)
|
||||
: intl.formatMessage(globalMessages.partiallyavailable),
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
{inProgress && <Spinner className="ml-1 h-3 w-3" />}
|
||||
{inProgress && (
|
||||
<>
|
||||
{mediaType === 'tv' && (
|
||||
<span className="ml-1">
|
||||
{intl.formatMessage(messages.seasonepisodenumber, {
|
||||
seasonNumber: downloadItem[0].episode?.seasonNumber,
|
||||
episodeNumber: downloadItem[0].episode?.episodeNumber,
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
<Spinner className="ml-1 h-3 w-3" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
@@ -138,9 +247,29 @@ const StatusBadge = ({
|
||||
|
||||
case MediaStatus.PROCESSING:
|
||||
return (
|
||||
<Tooltip content={mediaLinkDescription}>
|
||||
<Badge badgeType="primary" href={mediaLink}>
|
||||
<div className="flex items-center">
|
||||
<Tooltip
|
||||
content={inProgress ? tooltipContent : mediaLinkDescription}
|
||||
className={`${
|
||||
inProgress && 'hidden max-h-96 w-96 overflow-y-auto sm:block'
|
||||
}`}
|
||||
tooltipConfig={{
|
||||
...(inProgress && { interactive: true, delayHide: 100 }),
|
||||
}}
|
||||
>
|
||||
<Badge
|
||||
badgeType="primary"
|
||||
href={mediaLink}
|
||||
className={`${
|
||||
inProgress &&
|
||||
'relative !bg-gray-700 !bg-opacity-80 !px-0 hover:!bg-gray-700'
|
||||
} overflow-hidden`}
|
||||
>
|
||||
{inProgress && badgeDownloadProgress}
|
||||
<div
|
||||
className={`relative z-20 flex items-center ${
|
||||
inProgress && 'px-2'
|
||||
}`}
|
||||
>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
is4k ? messages.status4k : messages.status,
|
||||
@@ -151,7 +280,19 @@ const StatusBadge = ({
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
{inProgress && <Spinner className="ml-1 h-3 w-3" />}
|
||||
{inProgress && (
|
||||
<>
|
||||
{mediaType === 'tv' && (
|
||||
<span className="ml-1">
|
||||
{intl.formatMessage(messages.seasonepisodenumber, {
|
||||
seasonNumber: downloadItem[0].episode?.seasonNumber,
|
||||
episodeNumber: downloadItem[0].episode?.episodeNumber,
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
<Spinner className="ml-1 h-3 w-3" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
|
||||
Reference in New Issue
Block a user