import { MutedOutlined, SoundOutlined, CaretDownOutlined, ControlOutlined } from '@ant-design/icons'; import { Button, Popover, InputNumber } from 'antd'; import { Slider } from 'antd'; import { observer } from 'mobx-react-lite'; import React, { useRef, useState } from 'react'; import { PlayerContext } from '../../playerContext'; function DropdownAudioPlayer({ url }: { url: string }) { const { store } = React.useContext(PlayerContext); const [isVisible, setIsVisible] = useState(false); const [volume, setVolume] = useState(0); const [delta, setDelta] = useState(0); const [deltaInputValue, setDeltaInputValue] = useState(0); const [isMuted, setIsMuted] = useState(true); const lastPlayerTime = React.useRef(0); const audioRef = useRef(null); const { time = 0, speed = 1, playing } = store?.get() ?? {}; const toggleMute = () => { if (audioRef.current) { if (audioRef.current?.paused && playing) { audioRef.current?.play(); } audioRef.current.muted = !audioRef.current.muted; if (isMuted) { onVolumeChange(35) } else { onVolumeChange(0) } } }; const toggleVisible = () => { setIsVisible(!isVisible); }; const handleDelta = (value: any) => { setDeltaInputValue(parseFloat(value)) } const onSync = () => { setDelta(deltaInputValue) handleSeek(time + deltaInputValue * 1000) } const onCancel = () => { setDeltaInputValue(0) setIsVisible(false) } const onReset = () => { setDelta(0) setDeltaInputValue(0) handleSeek(time) } const onVolumeChange = (value: number) => { if (audioRef.current) { audioRef.current.volume = value / 100; } if (value === 0) { setIsMuted(true); } if (value > 0) { setIsMuted(false); } setVolume(value); }; const handleSeek = (timeMs: number) => { if (audioRef.current) { audioRef.current.currentTime = (timeMs + delta * 1000) / 1000; } }; const changePlaybackSpeed = (speed: number) => { if (audioRef.current) { audioRef.current.playbackRate = speed; } }; React.useEffect(() => { const deltaMs = delta * 1000; if (Math.abs(lastPlayerTime.current - time - deltaMs) >= 250) { handleSeek(time); } if (audioRef.current) { if (audioRef.current.paused && playing) { audioRef.current?.play(); } if (audioRef.current.muted !== isMuted) { audioRef.current.muted = isMuted; } } lastPlayerTime.current = time + deltaMs; }, [time, delta]); React.useEffect(() => { changePlaybackSpeed(speed); }, [speed]); React.useEffect(() => { if (playing) { audioRef.current?.play(); } else { audioRef.current?.pause(); } const volume = audioRef.current?.volume ?? 0 const shouldBeMuted = audioRef.current?.muted ?? isMuted setVolume(shouldBeMuted ? 0 : volume * 100); }, [playing]); return (
} >
{isMuted ? : }
{isVisible ? (
Audio Track Synchronization
`${value}s`} parser={(value) => value?.replace('s', '') as unknown as number} stringMode onChange={handleDelta} />
) : null}
); } export default observer(DropdownAudioPlayer);