import {DialogTrigger} from '@common/ui/overlays/dialog/dialog-trigger'; import {IconButton} from '@common/ui/buttons/icon-button'; import {Dialog} from '@common/ui/overlays/dialog/dialog'; import {DialogBody} from '@common/ui/overlays/dialog/dialog-body'; import {List, ListItem} from '@common/ui/list/list'; import {Trans} from '@common/i18n/trans'; import {ReactNode, useState} from 'react'; import {usePlayerStore} from '@common/player/hooks/use-player-store'; import {Button, ButtonProps} from '@common/ui/buttons/button'; import {AnimatePresence, m} from 'framer-motion'; import {usePlayerActions} from '@common/player/hooks/use-player-actions'; import {ArrowRightIcon} from '@common/icons/material/ArrowRight'; import {useDarkThemeVariables} from '@common/ui/themes/use-dark-theme-variables'; import {MediaSettingsIcon} from '@common/icons/media/media-settings'; import {MediaPlaybackSpeedCircleIcon} from '@common/icons/media/media-playback-speed-circle'; import {MediaSettingsMenuIcon} from '@common/icons/media/media-settings-menu'; import {MediaClosedCaptionsIcon} from '@common/icons/media/media-closed-captions'; import {MediaArrowLeftIcon} from '@common/icons/media/media-arrow-left'; import {MediaLanguageIcon} from '@common/icons/media/media-language'; import {useIsMobileMediaQuery} from '@common/utils/hooks/is-mobile-media-query'; type OptionsPanel = 'rate' | 'quality' | 'captions' | 'options' | 'language'; const Panels = { rate: PlaybackRatePanel, quality: PlaybackQualityPanel, options: OptionsListPanel, captions: CaptionsPanel, language: LanguagePanel, }; interface Props { color?: ButtonProps['color']; size?: ButtonProps['size']; iconSize?: ButtonProps['size']; className?: string; } export function PlaybackOptionsButton({ color, size, iconSize, className, }: Props) { const darkThemeVars = useDarkThemeVariables(); const isMobile = useIsMobileMediaQuery(); return ( ); } function PlaybackOptionsPanel() { const [activePanel, setActivePanel] = useState('options'); const PanelComponent = Panels[activePanel]; return ( ); } interface OptionsPanelProps { activePanel: OptionsPanel; onActivePanelChange: (panel: OptionsPanel) => void; } function OptionsListPanel({onActivePanelChange}: OptionsPanelProps) { const activeRate = usePlayerStore(s => s.playbackRate); const availableQualities = usePlayerStore(s => s.playbackQualities); const activeQuality = usePlayerStore(s => s.playbackQuality); const availableTextTracks = usePlayerStore(s => s.textTracks); const textTrackId = usePlayerStore(s => s.currentTextTrack); const currentTextTrack = availableTextTracks[textTrackId]; const availableAudioTracks = usePlayerStore(s => s.audioTracks); const audioTrackId = usePlayerStore(s => s.currentAudioTrack); const currentAudioTrack = availableAudioTracks[audioTrackId]; return ( } endSection={
{activeRate}x
} onSelected={() => onActivePanelChange('rate')} >
} endSection={
{activeQuality ? activeQuality : }
} onSelected={() => onActivePanelChange('quality')} >
} endSection={
{currentTextTrack ? ( currentTextTrack.label ) : ( )}
} onSelected={() => onActivePanelChange('captions')} >
{availableAudioTracks.length > 1 && ( } endSection={
{currentAudioTrack ? ( currentAudioTrack.label ) : ( )}
} onSelected={() => onActivePanelChange('language')} >
)}
); } function PlaybackRatePanel({ activePanel, onActivePanelChange, }: OptionsPanelProps) { const activeRate = usePlayerStore(s => s.playbackRate); const availableRates = usePlayerStore(s => s.playbackRates); const player = usePlayerActions(); return ( } > {availableRates.map(rate => ( { player.setPlaybackRate(rate); onActivePanelChange('options'); }} > {rate}x ))} ); } function PlaybackQualityPanel({ activePanel, onActivePanelChange, }: OptionsPanelProps) { const activeQuality = usePlayerStore(s => s.playbackQuality); const availableQualities = usePlayerStore(s => s.playbackQualities); const player = usePlayerActions(); return ( } > {availableQualities.map(quality => ( { player.setPlaybackQuality(quality); onActivePanelChange('options'); }} > {quality} ))} ); } function CaptionsPanel({activePanel, onActivePanelChange}: OptionsPanelProps) { const currentTextTrack = usePlayerStore(s => s.currentTextTrack); const textTracks = usePlayerStore(s => s.textTracks); const player = usePlayerActions(); return ( } > { player.setCurrentTextTrack(-1); onActivePanelChange('options'); }} > {textTracks.map((track, index) => ( { player.setCurrentTextTrack(index); onActivePanelChange('options'); }} > {track.label} ))} ); } function LanguagePanel({activePanel, onActivePanelChange}: OptionsPanelProps) { const currentAudioTrack = usePlayerStore(s => s.currentAudioTrack); const audioTracks = usePlayerStore(s => s.audioTracks); const player = usePlayerActions(); return ( } > {audioTracks.map((track, index) => ( { player.setCurrentAudioTrack(index); onActivePanelChange('options'); }} > {track.label} ))} ); } interface PanelLayoutProps extends OptionsPanelProps { children: ReactNode; title: ReactNode; } function PanelLayout({onActivePanelChange, children, title}: PanelLayoutProps) { return (
{children}
); }