parent
b9f3a35cd0
commit
47a08eda39
28 changed files with 301 additions and 286 deletions
After Width: | Height: | Size: 816 B |
After Width: | Height: | Size: 843 B |
@ -1,185 +1,31 @@ |
|||||||
import React, { useState, useEffect } from "react"; |
import * as React from 'react'; |
||||||
import { StyleSheet, TouchableOpacity, View, Image, Text } from "react-native"; |
import { View, Button } from 'react-native'; |
||||||
import { Ionicons } from "@expo/vector-icons"; |
import { Audio } from 'expo-av'; |
||||||
import { Audio } from "expo-av"; |
|
||||||
|
export default function VoicePlayer({fileIds}) { |
||||||
|
const [sound, setSound] = React.useState(); |
||||||
|
|
||||||
|
async function playSound() { |
||||||
|
console.log('Loading Sound'); |
||||||
|
const { sound } = await Audio.Sound.createAsync( |
||||||
|
{uri : `https://dnvn.ir/api/v1/file/${fileIds}`} |
||||||
|
); |
||||||
|
setSound(sound); |
||||||
|
|
||||||
|
console.log('Playing Sound'); |
||||||
|
await sound.playAsync(); } |
||||||
|
|
||||||
|
React.useEffect(() => { |
||||||
|
return sound |
||||||
|
? () => { |
||||||
|
console.log('Unloading Sound'); |
||||||
|
sound.unloadAsync(); } |
||||||
|
: undefined; |
||||||
|
}, [sound]); |
||||||
|
|
||||||
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 ( |
return ( |
||||||
<View style={styles.container}> |
<View style={styles.container}> |
||||||
<Image |
<Button title="Play Sound" onPress={playSound} /> |
||||||
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> |
</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; |
|
@ -0,0 +1,26 @@ |
|||||||
|
import { View, Text, Image, Dimensions } from "react-native"; |
||||||
|
import React from "react"; |
||||||
|
import tw from "tailwind-rn"; |
||||||
|
import fontSize from '../../../constants/fontSize'; |
||||||
|
import Colors from '../../../constants/Colors'; |
||||||
|
|
||||||
|
const { width } = Dimensions.get("window"); |
||||||
|
|
||||||
|
const Book = ({ book }) => { |
||||||
|
return ( |
||||||
|
<View |
||||||
|
style={[tw("w-full flex flex-row-reverse rounded-md p-2 my-2"), {backgroundColor : Colors.theme1.light.blue3}]} |
||||||
|
> |
||||||
|
<Image |
||||||
|
source={{ uri: `https://dnvn.ir/api/v1/file/${book.fileId}` }} |
||||||
|
style={[ |
||||||
|
tw("rounded-md"), |
||||||
|
{ width: width / 5.5, height: ((width / 5.5) * 3) / 2 }, |
||||||
|
]} |
||||||
|
/> |
||||||
|
<Text style={[{fontFamily: "regular", fontSize: fontSize.base, marginRight : 10 }]}>{book.title}</Text> |
||||||
|
</View> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default Book; |
@ -1,13 +1,76 @@ |
|||||||
import React from 'react' |
import React, { useState, useEffect } from "react"; |
||||||
import { View, Text } from 'react-native'; |
import { |
||||||
import {connect} from 'react-redux'; |
SafeAreaView, |
||||||
|
ScrollView, |
||||||
|
StatusBar, |
||||||
|
LayoutAnimation, |
||||||
|
Platform, |
||||||
|
Dimensions, |
||||||
|
} from "react-native"; |
||||||
|
import { connect } from "react-redux"; |
||||||
|
import { publicApi } from "../../redux/actions"; |
||||||
|
|
||||||
|
import Navbar from "../../components/Navbar"; |
||||||
|
import Drawer from "../../components/Drawer"; |
||||||
|
import Book from "./components/Book"; |
||||||
|
|
||||||
|
const { height } = Dimensions.get("window"); |
||||||
|
|
||||||
|
function AR({ getArList, arList }) { |
||||||
|
const [position, setPosition] = useState("100%"); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
getArList(); |
||||||
|
}, []); |
||||||
|
|
||||||
|
const setBoxPosition = () => { |
||||||
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); |
||||||
|
setPosition(position === "100%" ? "0%" : "100%"); |
||||||
|
}; |
||||||
|
|
||||||
function AR({}) { |
|
||||||
return ( |
return ( |
||||||
<View> |
<SafeAreaView |
||||||
<Text></Text> |
style={{ |
||||||
</View> |
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0, |
||||||
) |
position: "relative", |
||||||
|
// minHeight: height,
|
||||||
|
backgroundColor: "white", |
||||||
|
}} |
||||||
|
> |
||||||
|
<Navbar |
||||||
|
setBoxPosition={setBoxPosition} |
||||||
|
headerOptions={{ |
||||||
|
logo: false, |
||||||
|
menu: false, |
||||||
|
hamburgerMenu: false, |
||||||
|
title: "واقعیت افزوده", |
||||||
|
bookmark: false, |
||||||
|
qr: false, |
||||||
|
back: true, |
||||||
|
}} |
||||||
|
/> |
||||||
|
<Drawer setBoxPosition={setBoxPosition} position={position} /> |
||||||
|
<ScrollView |
||||||
|
style={{ |
||||||
|
paddingHorizontal: 16, |
||||||
|
height: height, |
||||||
|
backgroundColor: "white", |
||||||
|
}} |
||||||
|
contentContainerStyle={{ paddingBottom: 100 }} |
||||||
|
> |
||||||
|
{arList.length > 0 && |
||||||
|
arList.map((book, index) => <Book book={book} key={index} />)} |
||||||
|
</ScrollView> |
||||||
|
</SafeAreaView> |
||||||
|
); |
||||||
} |
} |
||||||
|
|
||||||
export default AR; |
const mapStateToProps = (state) => ({ |
||||||
|
arList: state.publicApi.arList, |
||||||
|
}); |
||||||
|
|
||||||
|
const mapDispatchToProps = { |
||||||
|
getArList: publicApi.getArList, |
||||||
|
}; |
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(AR); |
||||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 175 KiB |
@ -1,23 +1,37 @@ |
|||||||
import React from "react"; |
import React from "react"; |
||||||
import { View, Text, Dimensions } from "react-native"; |
import { View, Text, Dimensions } from "react-native"; |
||||||
import tw from "tailwind-rn"; |
import tw from "tailwind-rn"; |
||||||
|
import { Video } from "expo-av"; |
||||||
|
|
||||||
const {width} = Dimensions.get("window"); |
const {width} = Dimensions.get("window"); |
||||||
|
|
||||||
export default function Video({ name, file }) { |
export default function VideoContent({ data }) { |
||||||
|
const [status, setStatus] = React.useState({}); |
||||||
|
const video = React.useRef(null); |
||||||
return ( |
return ( |
||||||
<View style={tw("w-full flex-col mt-5")}> |
<View style={tw("w-full flex-col mt-5")}> |
||||||
<Text |
<Text |
||||||
style={[ |
style={[ |
||||||
tw("w-full text-right text-green-900 mb-2"), |
tw("w-full text-right text-green-900 mb-4"), |
||||||
{ fontSize: width / 34, fontFamily: "bold" }, |
{ fontSize: width / 34, fontFamily: "bold" }, |
||||||
]} |
]} |
||||||
> |
> |
||||||
{name} |
{'موضوع:' + ' ' + data.name} |
||||||
</Text> |
</Text> |
||||||
<View |
<View style={tw("flex flex-col")}> |
||||||
style={[tw("w-full bg-blue-200 rounded-md"), { minHeight: 200 }]} |
<Video |
||||||
></View> |
ref={video} |
||||||
|
style={{ width: "100%", height: (width * 9) / 16 - 16 }} |
||||||
|
source={{ |
||||||
|
uri: `https://dnvn.ir/api/v1/file/${data.fileIds}`, |
||||||
|
}} |
||||||
|
useNativeControls |
||||||
|
resizeMode="cover" |
||||||
|
// onFullscreenUpdate={setOrientation}
|
||||||
|
isLooping |
||||||
|
onPlaybackStatusUpdate={(status) => setStatus(() => status)} |
||||||
|
/> |
||||||
|
</View> |
||||||
</View> |
</View> |
||||||
); |
); |
||||||
} |
} |
||||||
|
@ -0,0 +1,12 @@ |
|||||||
|
import { View, Text } from 'react-native'; |
||||||
|
import React from 'react'; |
||||||
|
|
||||||
|
const Tests = () => { |
||||||
|
return ( |
||||||
|
<View> |
||||||
|
<Text></Text> |
||||||
|
</View> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default Tests; |
Loading…
Reference in new issue