Refactor various components to improve code clarity and maintainability. Update ListUsersQueryHandler to utilize UserListFilter for parameter handling. Refactor BumperSpecFactory and related classes to encapsulate input parameters into dedicated records, enhancing readability. Adjust MediaAsset and Slot classes to streamline content updates with new content models. Improve BumperRenderBackgroundService and MediaProcessingBackgroundService to use MediaReadyInfo for asset readiness, ensuring consistent parameter management across the application.
This commit is contained in:
@@ -14,6 +14,29 @@ function formatTime(iso: string) {
|
||||
return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
|
||||
/** Кадр серии, если он есть; иначе постер шоу (он вертикальный, отсюда другая ширина). */
|
||||
function EntryThumb({ entry }: { entry: PublicEpgEntryDto | undefined }) {
|
||||
if (entry?.episodeStillImageId)
|
||||
return (
|
||||
<img
|
||||
src={imageUrl(entry.episodeStillImageId)}
|
||||
alt=""
|
||||
className="hidden h-24 w-40 shrink-0 rounded object-cover sm:block"
|
||||
/>
|
||||
)
|
||||
|
||||
if (entry?.showPosterImageId)
|
||||
return (
|
||||
<img
|
||||
src={imageUrl(entry.showPosterImageId)}
|
||||
alt=""
|
||||
className="hidden h-24 w-16 shrink-0 rounded object-cover sm:block"
|
||||
/>
|
||||
)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function AirPage() {
|
||||
const { t } = useTranslation()
|
||||
const [selected, setSelected] = useState<string | null>(null)
|
||||
@@ -194,49 +217,38 @@ export function AirPage() {
|
||||
</aside>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
{selected && watchReady ? (
|
||||
playerError ? (
|
||||
<div className="crt-panel flex aspect-video w-full flex-col items-center justify-center gap-3 rounded-md text-center">
|
||||
<Radio className="h-10 w-10 text-muted-foreground" strokeWidth={1} />
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="font-medium">{t('air.offline')}</p>
|
||||
<p className="text-sm text-muted-foreground">{t('air.offlineHint')}</p>
|
||||
</div>
|
||||
<Button size="sm" variant="outline" onClick={retry}>
|
||||
<RotateCw className="h-4 w-4" />
|
||||
{t('air.retry')}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<ChannelPlayer
|
||||
key={`${selected}-${attempt}`}
|
||||
slug={selected}
|
||||
channel={currentChannel}
|
||||
nextUp={nextUp}
|
||||
flash={flash}
|
||||
onUnavailable={handleUnavailable}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
{/* До выдачи cookie tw_stream плеер грузить нечем — держим место заглушкой. */}
|
||||
{(!selected || !watchReady) && (
|
||||
<div className="aspect-video w-full animate-pulse rounded-md border border-border bg-black" />
|
||||
)}
|
||||
{selected && watchReady && playerError && (
|
||||
<div className="crt-panel flex aspect-video w-full flex-col items-center justify-center gap-3 rounded-md text-center">
|
||||
<Radio className="h-10 w-10 text-muted-foreground" strokeWidth={1} />
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="font-medium">{t('air.offline')}</p>
|
||||
<p className="text-sm text-muted-foreground">{t('air.offlineHint')}</p>
|
||||
</div>
|
||||
<Button size="sm" variant="outline" onClick={retry}>
|
||||
<RotateCw className="h-4 w-4" />
|
||||
{t('air.retry')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{selected && watchReady && !playerError && (
|
||||
<ChannelPlayer
|
||||
key={`${selected}-${attempt}`}
|
||||
slug={selected}
|
||||
channel={currentChannel}
|
||||
nextUp={nextUp}
|
||||
flash={flash}
|
||||
onUnavailable={handleUnavailable}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
{current && (
|
||||
<div className="crt-panel flex gap-3 rounded-md p-3">
|
||||
{currentEntry?.episodeStillImageId ? (
|
||||
<img
|
||||
src={imageUrl(currentEntry.episodeStillImageId)}
|
||||
alt=""
|
||||
className="hidden h-24 w-40 shrink-0 rounded object-cover sm:block"
|
||||
/>
|
||||
) : currentEntry?.showPosterImageId ? (
|
||||
<img
|
||||
src={imageUrl(currentEntry.showPosterImageId)}
|
||||
alt=""
|
||||
className="hidden h-24 w-16 shrink-0 rounded object-cover sm:block"
|
||||
/>
|
||||
) : null}
|
||||
<EntryThumb entry={currentEntry} />
|
||||
<div className="flex min-w-0 flex-col gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge>{t('air.now')}</Badge>
|
||||
|
||||
Reference in New Issue
Block a user