Skip to content

Instantly share code, notes, and snippets.

@Karthik-B-06
Created May 8, 2024 05:30
Show Gist options
  • Save Karthik-B-06/f9a203c9bccb1f949dbb41c678446798 to your computer and use it in GitHub Desktop.
Save Karthik-B-06/f9a203c9bccb1f949dbb41c678446798 to your computer and use it in GitHub Desktop.
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