@ -1,10 +1,12 @@
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 type { DownloadingItem } from '@server/lib/downloadtracker' ;
import { defineMessages , useIntl } from 'react-intl' ;
const messages = defineMessages ( {
@ -13,26 +15,31 @@ const messages = defineMessages({
playonplex : 'Play on Plex' ,
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 ( ) ;
@ -41,6 +48,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 &&
@ -85,21 +96,87 @@ const StatusBadge = ({
}
}
const tooltipContent = downloadItem ? (
< 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 >
) : (
mediaLinkDescription
) ;
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 }
className = { ` ${
inProgress && 'hidden max-h-96 w-96 overflow-scroll sm:block'
} ` }
tooltipConfig = { { 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 >
@ -107,20 +184,50 @@ const StatusBadge = ({
case MediaStatus . PARTIALLY_AVAILABLE :
return (
< Tooltip content = { mediaLinkDescription } >
< Badge badgeType = "success" href = { mediaLink } >
< div className = "flex items-center" >
< Tooltip
content = { inProgress && tooltipContent }
className = { ` ${
inProgress && 'hidden max-h-96 w-96 overflow-scroll sm:block'
} ` }
tooltipConfig = { { 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 : in Progress
? 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 >
@ -128,9 +235,27 @@ const StatusBadge = ({
case MediaStatus . PROCESSING :
return (
< Tooltip content = { mediaLinkDescription } >
< Badge badgeType = "primary" href = { mediaLink } >
< div className = "flex items-center" >
< Tooltip
content = { inProgress && tooltipContent }
className = { ` ${
inProgress && 'hidden max-h-96 w-96 overflow-scroll sm:block'
} ` }
tooltipConfig = { { 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 ,
@ -141,7 +266,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 >