Updated the BumpersPanel, ChannelsPanel, CollectionsPanel, GroupsPanel, ClipGroupPanel, and ShowsPanel components to replace direct input fields with a CreateNameDialog for creating new items. This change enhances user experience by centralizing the creation process and improving UI consistency. Localization strings were also updated to reflect new dialog titles and labels in both English and Russian.
62 lines
2.5 KiB
TypeScript
62 lines
2.5 KiB
TypeScript
import Hls from 'hls.js'
|
|
import { useEffect, useRef } from 'react'
|
|
import { getAccessToken } from '@/shared/api/client'
|
|
import { cn } from '@/shared/lib/cn'
|
|
|
|
/**
|
|
* Мини-плеер HLS для админки: плейлист и сегменты лежат под admin-роутами (JWT), поэтому запросы
|
|
* идут через hls.js с Bearer-заголовком. Нативный путь (Safari) — только там, где hls.js не нужен.
|
|
*/
|
|
export function HlsVideo({
|
|
src,
|
|
className,
|
|
autoPlay = false,
|
|
}: Readonly<{ src: string; className?: string; autoPlay?: boolean }>) {
|
|
const videoRef = useRef<HTMLVideoElement>(null)
|
|
|
|
useEffect(() => {
|
|
const video = videoRef.current
|
|
if (!video) return
|
|
|
|
// Атрибута autoplay мало: к моменту вставки <video> у него нет источника — плейлист доедет
|
|
// позже, и браузер стартовать будет уже нечему. Поэтому запускаем руками по готовности.
|
|
// Отказ глотаем: политика автовоспроизведения может не пустить, и это не ошибка — у плеера
|
|
// есть кнопка.
|
|
const start = () => void video.play().catch(() => undefined)
|
|
|
|
let hls: Hls | null = null
|
|
if (Hls.isSupported()) {
|
|
hls = new Hls({
|
|
xhrSetup: (xhr) => {
|
|
const token = getAccessToken()
|
|
if (token) xhr.setRequestHeader('Authorization', `Bearer ${token}`)
|
|
},
|
|
})
|
|
hls.loadSource(src)
|
|
hls.attachMedia(video)
|
|
if (autoPlay) hls.on(Hls.Events.MANIFEST_PARSED, start)
|
|
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
|
video.src = src
|
|
if (autoPlay) video.addEventListener('loadedmetadata', start, { once: true })
|
|
}
|
|
|
|
return () => {
|
|
video.removeEventListener('loadedmetadata', start)
|
|
hls?.destroy()
|
|
}
|
|
}, [src, autoPlay])
|
|
|
|
return (
|
|
<video
|
|
ref={videoRef}
|
|
controls
|
|
playsInline
|
|
className={cn('aspect-video w-full rounded-md border border-border bg-black', className)}
|
|
>
|
|
{/* Субтитров пайплайн не производит: ffmpeg режет видео и звук, дорожек с текстом нет.
|
|
Пустой track объявляет это явно, вместо молчаливого отсутствия. */}
|
|
<track kind="captions" />
|
|
</video>
|
|
)
|
|
}
|