import { SyntheticEvent, useEffect, useRef, useState } from 'react'; import { Box, Button, Flex, IconButton, Slider, SliderFilledTrack, SliderThumb, SliderTrack, Text, position, } from '@chakra-ui/react'; import { MdCheck, MdFastForward, MdFastRewind, MdGraphicEq, MdLooksOne, MdNavigateBefore, MdNavigateNext, MdOutlinePlayArrow, MdPause, MdPlayArrow, MdRepeat, MdRepeatOne, MdStop, MdTrendingFlat, } from 'react-icons/md'; import { useActivePlaylistService } from '@/service/ActivePlaylist'; import { useSpecificAlbum } from '@/service/Album'; import { useSpecificArtists } from '@/service/Artist'; import { useSpecificGender } from '@/service/Gender'; import { useSpecificTrack } from '@/service/Track'; import { DataUrlAccess } from '@/utils/data-url-access'; import { useThemeMode } from '@/utils/theme-tools'; import { isNullOrUndefined } from '@/utils/validator'; export enum PlayMode { PLAY_ONE, PLAY_ALL, PLAY_ONE_LOOP, PLAY_ALL_LOOP, } const playModeIcon = { [PlayMode.PLAY_ONE]: , [PlayMode.PLAY_ALL]: , [PlayMode.PLAY_ONE_LOOP]: , [PlayMode.PLAY_ALL_LOOP]: , }; export type AudioPlayerProps = {}; const formatTime = (time) => { if (time && !isNaN(time)) { const minutes = Math.floor(time / 60); const formatMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`; const seconds = Math.floor(time % 60); const formatSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`; return `${formatMinutes}:${formatSeconds}`; } return '00:00'; }; export const AudioPlayer = ({}: AudioPlayerProps) => { const { mode } = useThemeMode(); const { playTrackList, trackOffset, previous, next, first } = useActivePlaylistService(); const audioRef = useRef(null); const [isPlaying, setIsPlaying] = useState(false); const [timeProgress, setTimeProgress] = useState(0); const [playingMode, setPlayingMode] = useState(PlayMode.PLAY_ALL); const [duration, setDuration] = useState(0); const { dataTrack } = useSpecificTrack( trackOffset !== undefined ? playTrackList[trackOffset] : undefined ); const { dataAlbum } = useSpecificAlbum(dataTrack?.albumId); const { dataGender } = useSpecificGender(dataTrack?.genderId); const { dataArtists } = useSpecificArtists(dataTrack?.artists); const [mediaSource, setMediaSource] = useState(''); useEffect(() => { setMediaSource( dataTrack && dataTrack?.dataId ? DataUrlAccess.getUrl(dataTrack?.dataId) : '' ); }, [dataTrack, setMediaSource]); const backColor = mode('back.100', 'back.800'); const configButton = { borderRadius: 'full', backgroundColor: '#00000000', _hover: { boxShadow: 'outline-over', bgColor: 'brand.500', }, }; useEffect(() => { if (!audioRef || !audioRef.current) { return; } if (isPlaying) { audioRef.current.play(); } else { audioRef.current.pause(); } }, [isPlaying, audioRef]); const onAudioEnded = () => { if (playTrackList.length === 0 || isNullOrUndefined(trackOffset)) { return; } if (playingMode === PlayMode.PLAY_ALL_LOOP) { if (playTrackList.length == trackOffset + 1) { first(); } else { next(); } } else if (playingMode === PlayMode.PLAY_ALL) { next(); } else if (playingMode === PlayMode.PLAY_ONE_LOOP) { onSeek(0); onPlay(); } }; const onSeek = (newValue) => { console.log(`onSeek: ${newValue}`); if (!audioRef || !audioRef.current) { return; } audioRef.current.currentTime = newValue; }; const onPlay = () => { if (!audioRef || !audioRef.current) { return; } if (isPlaying) { audioRef.current.pause(); } else { audioRef.current.play(); } }; const onStop = () => { if (!audioRef || !audioRef.current) { return; } if (audioRef.current.currentTime == 0 && audioRef.current.paused) { // TODO remove curent playing value } else { audioRef.current.pause(); audioRef.current.currentTime = 0; } }; const onNavigatePrevious = () => { previous(); }; const onFastRewind = () => { if (!audioRef || !audioRef.current) { return; } audioRef.current.currentTime -= 10; }; const onFastForward = () => { if (!audioRef || !audioRef.current) { return; } audioRef.current.currentTime += 10; }; const onNavigateNext = () => { next(); }; const onTypePlay = () => { setPlayingMode((value: PlayMode) => { if (value === PlayMode.PLAY_ONE) { return PlayMode.PLAY_ALL; } else if (value === PlayMode.PLAY_ALL) { return PlayMode.PLAY_ONE_LOOP; } else if (value === PlayMode.PLAY_ONE_LOOP) { return PlayMode.PLAY_ALL_LOOP; } else { return PlayMode.PLAY_ONE; } }); }; /** * Call when meta-data is updated */ function onChangeMetadata(): void { const seconds = audioRef.current?.duration; if (seconds !== undefined) { setDuration(seconds); } } const onTimeUpdate = () => { if (!audioRef || !audioRef.current) { return; } console.log(`onTimeUpdate ${audioRef.current.currentTime}`); setTimeProgress(audioRef.current.currentTime); }; const onDurationChange = (event) => {}; const onChangeStateToPlay = () => { setIsPlaying(true); }; const onChangeStateToPause = () => { setIsPlaying(false); }; return ( <> {!isNullOrUndefined(trackOffset) && ( {dataTrack?.name ?? '???'} {dataArtists.map((data) => data.name).join(', ')} /{' '} {dataAlbum && dataAlbum?.name} {dataGender && ` / ${dataGender.name}`} {formatTime(timeProgress)} {formatTime(duration)} ) : ( ) } onClick={onPlay} /> } onClick={onStop} /> } onClick={onNavigatePrevious} marginLeft="auto" /> } onClick={onFastRewind} /> } onClick={onFastForward} /> } marginRight="auto" onClick={onNavigateNext} /> )}