music player 3/4 done
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
752e40b29f
commit
dfe944faff
@ -1,14 +1,14 @@
|
|||||||
export default class Music {
|
// export default class Music {
|
||||||
private id : string;
|
// private id : string;
|
||||||
private name : string;
|
// private name : string;
|
||||||
private artist : string;
|
// private artist : string;
|
||||||
private linkCover : string; // Image.source
|
// private linkCover : string; // Image.source
|
||||||
|
|
||||||
constructor(id : string, name : string, artist : string, linkCover : string){
|
// constructor(id : string, name : string, artist : string, linkCover : string){
|
||||||
this.id = id;
|
// this.id = id;
|
||||||
this.name = name;
|
// this.name = name;
|
||||||
this.artist = artist;
|
// this.artist = artist;
|
||||||
this.linkCover = linkCover;
|
// this.linkCover = linkCover;
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
import Music from "../../Model/Music";
|
||||||
|
import { Spot } from "../../Model/Spot";
|
||||||
|
import { favoritesTypes } from "../types/favoritesTypes";
|
||||||
|
import {spotTypes} from "../types/spotTypes";
|
||||||
|
|
||||||
|
export const getFavoritesMusic = (favoritesMusic: Music[]) => {
|
||||||
|
return {
|
||||||
|
type: favoritesTypes.GET_FAVORITE_MUSICS,
|
||||||
|
playload: favoritesMusic,
|
||||||
|
};
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
export const favoritesTypes = {
|
export const favoritesTypes = {
|
||||||
|
GET_FAVORITE_MUSICS : 'GET_FAVORITE_MUSICS',
|
||||||
ADD_FAVORITE_MUSICS : 'ADD_FAVORITE_MUSICS',
|
ADD_FAVORITE_MUSICS : 'ADD_FAVORITE_MUSICS',
|
||||||
REMOVE_FAVORITE_MUSICS : 'REMOVE_FAVORITE_MUSICS',
|
REMOVE_FAVORITE_MUSICS : 'REMOVE_FAVORITE_MUSICS',
|
||||||
}
|
}
|
@ -0,0 +1,295 @@
|
|||||||
|
import { SharedElement } from "react-navigation-shared-element";
|
||||||
|
import { NavigationProp, RouteProp } from "@react-navigation/native";
|
||||||
|
import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity } from "react-native";
|
||||||
|
import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, useDerivedValue, useSharedValue, Value, withSpring, withTiming } from "react-native-reanimated";
|
||||||
|
import { BlurView } from 'expo-blur';
|
||||||
|
import qs from "qs";
|
||||||
|
import axios from "axios";
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
import { Audio } from 'expo-av';
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { State, TapGestureHandler } from "react-native-gesture-handler";
|
||||||
|
import { RequestHandler } from "../services/spotify/spotifyRequestHandler/utils";
|
||||||
|
import { FetchRequest } from "expo-auth-session/build/Fetch";
|
||||||
|
import Music from "../Model/Music";
|
||||||
|
|
||||||
|
interface SpotProps {
|
||||||
|
spot: { name: string, sourceUrl: string, index : number };
|
||||||
|
}
|
||||||
|
const halfPi = Math.PI/2;
|
||||||
|
|
||||||
|
// const {width : wWidht} = Dimensions.get("window");
|
||||||
|
//@ts-ignore
|
||||||
|
const MusicDetail = ({ route }) => {
|
||||||
|
const {width, height} = useWindowDimensions();
|
||||||
|
console.log(route);
|
||||||
|
|
||||||
|
const music : Music = route.params.music;
|
||||||
|
const [currentspot, setCurrentspot] = useState(music);
|
||||||
|
const [sound, setSound] = useState(null);
|
||||||
|
|
||||||
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
|
const loader = useSharedValue(0);
|
||||||
|
useEffect(() => {
|
||||||
|
loader.value = isPlaying ? 1 : 0
|
||||||
|
}, [isPlaying,loader ]);
|
||||||
|
|
||||||
|
const transition = useDerivedValue(()=>{
|
||||||
|
return withTiming(loader.value, {duration : 1000})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// const styleAniamatedButton = useAnimatedStyle(() => {
|
||||||
|
// const verticalAxis =interpolate(
|
||||||
|
// transition.value,
|
||||||
|
// [0,1],
|
||||||
|
// [circumference, 0]
|
||||||
|
// )
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// top : withSpring( verticalAxis),
|
||||||
|
// left : withSpring(horizontalAxis),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
const trackPreviewUrl = 'https://p.scdn.co/mp3-preview/08ef3b9d6dbd6bab233f5e9ca564091902767f71?cid=774b29d4f13844c495f206cafdad9c86';
|
||||||
|
const playTrackPreview = async () => {
|
||||||
|
console.log("===============================================================================================================");
|
||||||
|
|
||||||
|
console.log('get in Sound');
|
||||||
|
|
||||||
|
const { sound } = await Audio.Sound.createAsync({uri :music.trackPreviewUrl});
|
||||||
|
//@ts-ignore
|
||||||
|
setSound(sound);
|
||||||
|
console.log('Playing Sound');
|
||||||
|
await sound.playAsync();
|
||||||
|
setIsPlaying(true);
|
||||||
|
|
||||||
|
|
||||||
|
// const soundObject = new Audio.Sound();
|
||||||
|
// try {
|
||||||
|
// await soundObject.loadAsync({ uri: trackPreviewUrl });
|
||||||
|
// await soundObject.playAsync();
|
||||||
|
// setIsPlaying(true);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.log('Error loading sound:', error);
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePlaySound = async () => {
|
||||||
|
if (sound === null) {
|
||||||
|
const { sound: newSound } = await Audio.Sound.createAsync(
|
||||||
|
{ uri: music.trackPreviewUrl },
|
||||||
|
{ shouldPlay: true }
|
||||||
|
);
|
||||||
|
setSound(newSound);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//@ts-ignore
|
||||||
|
await sound.playAsync();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStopSound = async () => {
|
||||||
|
if (sound !== null) {
|
||||||
|
//@ts-ignore
|
||||||
|
await sound.stopAsync();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setIsPlaying(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
return sound ? () => {
|
||||||
|
console.log('Unloading Sound');
|
||||||
|
//@ts-ignore
|
||||||
|
sound.unloadAsync();
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
}, [sound]);
|
||||||
|
// useEffect(() => {
|
||||||
|
// if(isPlaying){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
console.log(music);
|
||||||
|
const sensor = useAnimatedSensor(SensorType.ROTATION);
|
||||||
|
const styleAniamatedImage = useAnimatedStyle(() => {
|
||||||
|
const {yaw, pitch, roll} = sensor.sensor.value;
|
||||||
|
const verticalAxis =interpolate(
|
||||||
|
pitch,
|
||||||
|
[-halfPi,halfPi],
|
||||||
|
[-45, 45]
|
||||||
|
)
|
||||||
|
const horizontalAxis =interpolate(
|
||||||
|
roll,
|
||||||
|
[-halfPi,halfPi],
|
||||||
|
[-45, 45]
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
top : withSpring( verticalAxis),
|
||||||
|
left : withSpring(horizontalAxis),
|
||||||
|
};
|
||||||
|
|
||||||
|
})
|
||||||
|
// const CLIENT_ID = "1f1e34e4b6ba48b388469dba80202b10";
|
||||||
|
// const CLIENT_SECRET = "779371c6d4994a68b8dd6e84b0873c82";
|
||||||
|
// const spotify = "BQA2IAFZ-7ta4-_4_Uqdcdrqi_peE6Hlf1jwxFqjXTbwes0z8xgVGx0rE3zv4cQlusd1ILJhRwkxzPsL1YakzSvCxaTI1P7kOzBrrMqlkDgk4vlFvzLjScB0hBLULbpZyn3ylgx4RyZBEWfmc24wZPQOsrJU58AYCveA52UxYVSIc_Frr7LZyRmwjzGB68MPZeBD"
|
||||||
|
// var authOptions = {
|
||||||
|
// method: 'GET',
|
||||||
|
// url: 'https://api.spotify.com/v1/me/player/currently-playing',
|
||||||
|
|
||||||
|
// headers: {
|
||||||
|
// 'Authorization': 'Bearer ' + spotify,
|
||||||
|
// 'Content-Type' : 'application/json',
|
||||||
|
// 'market' : 'FR',
|
||||||
|
// },
|
||||||
|
// json: true
|
||||||
|
// };
|
||||||
|
|
||||||
|
// var id = '0cFS3AMF9Lhj3CNoFvwjvY'
|
||||||
|
// const requestor = new RequestHandler()
|
||||||
|
|
||||||
|
// const getCurrentTrack = async () => {
|
||||||
|
// try {
|
||||||
|
// const opt : FetchRequest ={headers : Record}
|
||||||
|
// requestor.spotifyFetch(`tracks${id}`,)
|
||||||
|
|
||||||
|
// // var GetTrackOptions = {
|
||||||
|
// // method: 'GET',
|
||||||
|
// // url: 'https://api.spotify.com/v1/tracks/'+id,
|
||||||
|
|
||||||
|
// // headers: {
|
||||||
|
// // 'Authorization': 'Bearer ' + spotify,
|
||||||
|
// // 'Content-Type' : 'application/json',
|
||||||
|
// // 'market' : 'FR',
|
||||||
|
// // },
|
||||||
|
// // json: true
|
||||||
|
// // };
|
||||||
|
// // const resp = await axios(GetTrackOptions)
|
||||||
|
// // console.log("============");
|
||||||
|
// // console.log(resp.data.href);
|
||||||
|
// // console.log("================================"+resp.data.album.images[0].url+ "================================");
|
||||||
|
// // var tmp = currentspot;
|
||||||
|
|
||||||
|
// // tmp.sourceUrl = resp.data.album.images[0].url;
|
||||||
|
// // setCurrentspot(tmp);
|
||||||
|
// // await axios(authOptions).then(async (response) =>{
|
||||||
|
// // console.log(response.data.item.preview_url);
|
||||||
|
// // const id = response.data.item.id;
|
||||||
|
// // var GetTrackOptions = {
|
||||||
|
// // method: 'GET',
|
||||||
|
// // url: 'https://api.spotify.com/v1/tracks/'+id,
|
||||||
|
|
||||||
|
// // headers: {
|
||||||
|
// // 'Authorization': 'Bearer ' + spotify,
|
||||||
|
// // 'Content-Type' : 'application/json',
|
||||||
|
// // 'market' : 'FR',
|
||||||
|
// // },
|
||||||
|
// // json: true
|
||||||
|
// // };
|
||||||
|
// // console.log("============");
|
||||||
|
// // const music = await axios(GetTrackOptions);
|
||||||
|
// // console.log("================================"+music.data+ "================================");
|
||||||
|
// // currentspot.sourceUrl = music.data.images[0];
|
||||||
|
// // setCurrentspot(currentspot);
|
||||||
|
// // })
|
||||||
|
|
||||||
|
// // const response = await fetch('https://api.spotify.com/v1/me', {
|
||||||
|
// // method: 'GET',
|
||||||
|
// // headers: {
|
||||||
|
// // Authorization: 'Bearer ' + spotify,
|
||||||
|
// // 'Content-Type': 'application/json',
|
||||||
|
// // },
|
||||||
|
// // });
|
||||||
|
// // response.json()
|
||||||
|
|
||||||
|
// // destructure the response and rename the properties to be in camelCase to satisfy my linter ;)
|
||||||
|
|
||||||
|
// } catch (err) {
|
||||||
|
// console.error(err);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
const animationState = new Value(State.UNDETERMINED);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
|
||||||
|
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
|
||||||
|
<View style={{borderWidth : 1, borderColor : 'red'}}>
|
||||||
|
|
||||||
|
<Animated.Image
|
||||||
|
source={{
|
||||||
|
uri:currentspot.image ,
|
||||||
|
}}
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
|
||||||
|
width: 370,
|
||||||
|
height: 370,
|
||||||
|
borderRadius : 24,
|
||||||
|
resizeMode: 'stretch',
|
||||||
|
},styleAniamatedImage
|
||||||
|
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Button title="Current Track"
|
||||||
|
onPress={() => {
|
||||||
|
getCurrentTrack()
|
||||||
|
// promptAsync();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{/* Button */}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* <TapGestureHandler {...gestureHandler}> */}
|
||||||
|
<Animated.View>
|
||||||
|
<TouchableOpacity style={{
|
||||||
|
backgroundColor: '#1DB954',
|
||||||
|
paddingVertical: 12,
|
||||||
|
paddingHorizontal: 24,
|
||||||
|
borderRadius: 24,
|
||||||
|
}} onPressIn={handlePlaySound}
|
||||||
|
onPressOut={handleStopSound}
|
||||||
|
onLongPress={handlePlaySound}
|
||||||
|
delayLongPress={1000}>
|
||||||
|
|
||||||
|
<Text style={ {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',}}>
|
||||||
|
{isPlaying ? 'Playing...' : 'Play'}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Animated.View>
|
||||||
|
|
||||||
|
{/* </TapGestureHandler> */}
|
||||||
|
|
||||||
|
{/* Button */}
|
||||||
|
|
||||||
|
|
||||||
|
{/* <View style={detailRadicalStyle.container}>
|
||||||
|
<Text style={detailRadicalStyle.radicalText}>{props.character}</Text>
|
||||||
|
<SvgXml
|
||||||
|
xml={props.icon
|
||||||
|
.replace(/fill="#[0-9a-f]{6}"/g, `fill=${detailRadicalStyle.svg.color}`)}
|
||||||
|
width="30"
|
||||||
|
height="30"
|
||||||
|
opacity={0.5}
|
||||||
|
style={detailRadicalStyle.radicalIcon}
|
||||||
|
|
||||||
|
/>
|
||||||
|
</View> */}
|
||||||
|
{/* </SharedElement> */}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MusicDetail;
|
Loading…
Reference in new issue