Created
May 8, 2024 05:30
-
-
Save Karthik-B-06/f9a203c9bccb1f949dbb41c678446798 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect, useMemo, useState } from 'react'; | |
import { Pressable, View } from 'react-native'; | |
import { PlayBackType } from 'react-native-audio-recorder-player'; | |
import Animated, { FadeIn, FadeOut, useSharedValue } from 'react-native-reanimated'; | |
import { Slider } from '~/components/Slider'; | |
import { Spinner } from '~/components/Spinner'; | |
import { useAudioPlayer } from '~/store/useAudioPlayer'; | |
import { PauseIcon, PlayIcon } from '~/svg'; | |
import { tailwind } from '~/theme/tailwind'; | |
import { | |
isPlayerPresent, | |
pausePlayer, | |
resumePlayer, | |
seekTo, | |
startPlayer, | |
stopPlayer, | |
} from '~/utils/audio-manager'; | |
type AudioPlayerProps = { audioSrc: string }; | |
export const AudioPlayer = (props: AudioPlayerProps) => { | |
const { audioSrc } = props; | |
const [isSoundLoading, setIsSoundLoading] = useState(false); | |
const [isAudioPlaying, setAudioPlaying] = useState(false); | |
const { setCurrentPlayingAudioSrc, currentPlayingAudioSrc } = useAudioPlayer(); | |
const currentPosition = useSharedValue(0); | |
const totalDuration = useSharedValue(0); | |
const audioPlayBackStatus = (data: any) => { | |
const playBackData = data.data as PlayBackType; | |
if (playBackData) { | |
currentPosition.value = playBackData.currentPosition; | |
totalDuration.value = playBackData.duration; | |
if (playBackData.currentPosition === playBackData.duration) { | |
seekTo(0).then((value) => { | |
currentPosition.value = 0; | |
totalDuration.value = 0; | |
setAudioPlaying(false); | |
}); | |
} | |
} | |
}; | |
const togglePlayback = async () => { | |
setIsSoundLoading(true); | |
const isPlayerReady = await isPlayerPresent(audioSrc); | |
if (isPlayerReady) { | |
// The current playing audio file is same as the component audio src so | |
// we will have to just toggle the audio playing | |
if (isAudioPlaying) { | |
pausePlayer(); | |
} else { | |
resumePlayer(); | |
} | |
setAudioPlaying(!isAudioPlaying); | |
} else { | |
startPlayer(audioSrc, audioPlayBackStatus).then(() => { | |
setIsSoundLoading(false); | |
setAudioPlaying(true); | |
setCurrentPlayingAudioSrc(audioSrc); | |
}); | |
} | |
}; | |
const manualSeekTo = async (manualSeekPosition: number) => { | |
seekTo(manualSeekPosition).then(() => { | |
resumePlayer(); | |
}); | |
}; | |
const pauseAudio = async () => { | |
await pausePlayer(); | |
}; | |
const isCurrentAudioSrcPlaying = useMemo( | |
() => currentPlayingAudioSrc === audioSrc && isAudioPlaying, | |
[audioSrc, currentPlayingAudioSrc, isAudioPlaying] | |
); | |
useEffect(() => { | |
if (currentPlayingAudioSrc !== audioSrc) { | |
currentPosition.value = 0; | |
totalDuration.value = 0; | |
} | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, [currentPlayingAudioSrc]); | |
useEffect(() => { | |
const setupPlayer = () => { | |
setIsSoundLoading(true); | |
startPlayer(audioSrc, audioPlayBackStatus).then(() => { | |
setIsSoundLoading(false); | |
setAudioPlaying(true); | |
setCurrentPlayingAudioSrc(audioSrc); | |
}); | |
}; | |
setupPlayer(); | |
return () => { | |
stopPlayer() | |
.then() | |
.finally(() => { | |
setAudioPlaying(false); | |
setCurrentPlayingAudioSrc(''); | |
}); | |
}; | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, []); | |
return ( | |
<View style={[tailwind.style('flex flex-row items-center py-4 px-3 rounded-xl')]}> | |
<Pressable disabled={isSoundLoading} hitSlop={4} onPress={togglePlayback}> | |
{isSoundLoading ? ( | |
<Animated.View style={tailwind.style('h-6 w-6 justify-center items-center')}> | |
<Spinner size={18} /> | |
</Animated.View> | |
) : isCurrentAudioSrcPlaying ? ( | |
<Animated.View | |
style={tailwind.style('h-6 w-6 justify-center items-center')} | |
entering={FadeIn} | |
exiting={FadeOut}> | |
<PauseIcon fillOpacity="1" fill="#171717" /> | |
</Animated.View> | |
) : ( | |
<Animated.View | |
style={tailwind.style('h-6 w-6 justify-center items-center')} | |
entering={FadeIn} | |
exiting={FadeOut}> | |
<PlayIcon fillOpacity="1" fill="#171717" /> | |
</Animated.View> | |
)} | |
</Pressable> | |
<Slider | |
trackColor="bg-gray-100" | |
filledTrackColor="bg-gray-300" | |
knobStyle="border-[#171717]" | |
{...{ manualSeekTo, currentPosition, totalDuration, pauseAudio }} | |
/> | |
</View> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment