You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

185 lines
4.6 KiB

import React, { useState, useEffect } from "react";
import { StyleSheet, TouchableOpacity, View, Image, Text } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { Audio } from "expo-av";
const audioBookPlaylist = [
{
title: "Hamlet - Act I",
author: "William Shakespeare",
source: "Librivox",
uri: "",
imageSource:
"http://www.archive.org/download/LibrivoxCdCoverArt8/hamlet_1104.jpg",
},
];
const MusicPlayer = () => {
const [isPlaying, setIsPlaying] = useState(false);
const [playbackInstance, setPlaybackInstance] = useState(null);
const [currentIndex, setCurrentIndex] = useState(0);
const [volume, setVolume] = useState(1.0);
const [isBuffering, setIsBuffering] = useState(true);
useEffect( async () => {
try {
await Audio.setAudioModeAsync({
allowsRecordingIOS: false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
playsInSilentModeIOS: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
shouldDuckAndroid: true,
staysActiveInBackground: true,
playThroughEarpieceAndroid: true,
});
loadAudio();
} catch (e) {
console.log(e);
}
});
const loadAudio = async () => {
try {
const playbackInstance = new Audio.Sound();
const source = {
uri: audioBookPlaylist[currentIndex].uri,
};
const status = {
shouldPlay: isPlaying,
volume: volume,
};
playbackInstance.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate);
await playbackInstance.loadAsync(source, status, false);
setPlaybackInstance(playbackInstance);
} catch (e) {
console.log(e);
}
};
const onPlaybackStatusUpdate = (status) => {
setIsBuffering(status.isBuffering);
};
const handlePlayPause = async () => {
if(isPlaying) {
await playbackInstance.pauseAsync();
}else{
await playbackInstance.playAsync();
}
setIsPlaying(() => !isPlaying);
};
const handlePreviousTrack = async () => {
let { playbackInstance, currentIndex } = state;
if (playbackInstance) {
await playbackInstance.unloadAsync();
setCurrentIndex(
currentIndex === 0 ? audioBookPlaylist.length - 1 : currentIndex - 1
);
loadAudio();
}
};
const handleNextTrack = async () => {
if (playbackInstance) {
await playbackInstance.unloadAsync();
setCurrentIndex(
currentIndex + 1 > audioBookPlaylist.length - 1 ? 0 : currentIndex + 1
);
loadAudio();
}
};
const renderFileInfo = () => {
return playbackInstance ? (
<View style={styles.trackInfo}>
<Text style={[styles.trackInfoText, styles.largeText]}>
{audioBookPlaylist[currentIndex].title}
</Text>
<Text style={[styles.trackInfoText, styles.smallText]}>
{audioBookPlaylist[currentIndex].author}
</Text>
<Text style={[styles.trackInfoText, styles.smallText]}>
{audioBookPlaylist[currentIndex].source}
</Text>
</View>
) : null;
};
return (
<View style={styles.container}>
<Image
style={styles.albumCover}
source={{
uri: "http://www.archive.org/download/LibrivoxCdCoverArt8/hamlet_1104.jpg",
}}
/>
<View style={styles.controls}>
<TouchableOpacity
style={styles.control}
onPress={() => handlePreviousTrack()}
>
<Ionicons name="play-back" size={48} color="#444" />
</TouchableOpacity>
<TouchableOpacity
style={styles.control}
onPress={() => handlePlayPause()}
>
{isPlaying ? (
<Ionicons name="ios-pause" size={48} color="#444" />
) : (
<Ionicons name="ios-play-circle" size={48} color="#444" />
)}
</TouchableOpacity>
<TouchableOpacity
style={styles.control}
onPress={() => handleNextTrack()}
>
<Ionicons name="play-forward" size={48} color="#444" />
</TouchableOpacity>
</View>
{renderFileInfo()}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
albumCover: {
width: 250,
height: 250,
},
trackInfo: {
padding: 40,
backgroundColor: "#fff",
},
trackInfoText: {
textAlign: "center",
flexWrap: "wrap",
color: "#550088",
},
largeText: {
fontSize: 22,
},
smallText: {
fontSize: 16,
},
control: {
margin: 20,
},
controls: {
flexDirection: "row",
},
});
export default MusicPlayer;