Refactor ChannelPlayer component: remove play/pause functionality and related state management, update comments for clarity, and streamline audio control features for a live streaming experience.

This commit is contained in:
Leonid Pershin
2026-07-25 10:03:11 +03:00
parent 8ca585a5be
commit 9a17715d0f
@@ -1,7 +1,7 @@
import Hls from 'hls.js' import Hls from 'hls.js'
import { useCallback, useEffect, useRef, useState } from 'react' import { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Maximize, Pause, Play, Volume2, VolumeX } from 'lucide-react' import { Maximize, Volume2, VolumeX } from 'lucide-react'
const STORAGE_KEY = 'tw:player' const STORAGE_KEY = 'tw:player'
@@ -23,8 +23,8 @@ function readStoredAudio(): { volume: number; muted: boolean } {
} }
/** /**
* HLS-плеер линейного канала. Перемотка невозможна: своя минимальная панель без таймлайна, а на * HLS-плеер линейного канала. Это живой эфир: ни перемотки, ни паузы — только звук, громкость и
* play/после ошибки плеер прыгает к живому краю. Cookie tw_stream уже выдана к монтированию. * полноэкранный режим. Cookie tw_stream уже выдана к монтированию.
*/ */
export function ChannelPlayer({ export function ChannelPlayer({
slug, slug,
@@ -37,7 +37,6 @@ export function ChannelPlayer({
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const videoRef = useRef<HTMLVideoElement>(null) const videoRef = useRef<HTMLVideoElement>(null)
const hlsRef = useRef<Hls | null>(null) const hlsRef = useRef<Hls | null>(null)
const [playing, setPlaying] = useState(false)
const [muted, setMuted] = useState(() => readStoredAudio().muted) const [muted, setMuted] = useState(() => readStoredAudio().muted)
const [volume, setVolume] = useState(() => readStoredAudio().volume) const [volume, setVolume] = useState(() => readStoredAudio().volume)
@@ -79,17 +78,6 @@ export function ChannelPlayer({
useEffect(() => clearHideTimer, [clearHideTimer]) useEffect(() => clearHideTimer, [clearHideTimer])
const seekToLiveEdge = useCallback(() => {
const video = videoRef.current
if (!video) return
const live = hlsRef.current?.liveSyncPosition
if (typeof live === 'number' && Number.isFinite(live)) {
video.currentTime = live
} else if (video.seekable.length > 0) {
video.currentTime = video.seekable.end(video.seekable.length - 1)
}
}, [])
useEffect(() => { useEffect(() => {
const video = videoRef.current const video = videoRef.current
if (!video) return if (!video) return
@@ -137,17 +125,6 @@ export function ChannelPlayer({
} }
}, [slug, onUnavailable]) }, [slug, onUnavailable])
const togglePlay = () => {
const video = videoRef.current
if (!video) return
if (video.paused) {
seekToLiveEdge()
void video.play().catch(() => undefined)
} else {
video.pause()
}
}
// Установить громкость (0..1); 0 = mute, >0 запоминаем как последний уровень для «размьютить». // Установить громкость (0..1); 0 = mute, >0 запоминаем как последний уровень для «размьютить».
const applyVolume = (value: number) => { const applyVolume = (value: number) => {
const video = videoRef.current const video = videoRef.current
@@ -194,14 +171,9 @@ export function ChannelPlayer({
playsInline playsInline
muted muted
className="h-full w-full" className="h-full w-full"
onClick={togglePlay}
onDoubleClick={toggleFullscreen} onDoubleClick={toggleFullscreen}
onPlay={() => { onPlay={scheduleHide}
setPlaying(true)
scheduleHide()
}}
onPause={() => { onPause={() => {
setPlaying(false)
clearHideTimer() clearHideTimer()
setControlsVisible(true) setControlsVisible(true)
}} }}
@@ -221,9 +193,6 @@ export function ChannelPlayer({
controlsVisible ? 'opacity-100' : 'pointer-events-none opacity-0' controlsVisible ? 'opacity-100' : 'pointer-events-none opacity-0'
}`} }`}
> >
<button type="button" onClick={togglePlay} aria-label="play/pause">
{playing ? <Pause className="h-5 w-5" /> : <Play className="h-5 w-5" />}
</button>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button type="button" onClick={toggleMute} aria-label="mute"> <button type="button" onClick={toggleMute} aria-label="mute">
{muted ? <VolumeX className="h-5 w-5" /> : <Volume2 className="h-5 w-5" />} {muted ? <VolumeX className="h-5 w-5" /> : <Volume2 className="h-5 w-5" />}