music player 3/4 done
continuous-integration/drone/push Build is passing Details

pull/11/head
David D'ALMEIDA 2 years ago
parent 752e40b29f
commit dfe944faff

@ -1,14 +1,14 @@
export default class Music {
private id : string;
private name : string;
private artist : string;
private linkCover : string; // Image.source
// export default class Music {
// private id : string;
// private name : string;
// private artist : string;
// private linkCover : string; // Image.source
constructor(id : string, name : string, artist : string, linkCover : string){
this.id = id;
this.name = name;
this.artist = artist;
this.linkCover = linkCover;
}
// constructor(id : string, name : string, artist : string, linkCover : string){
// this.id = id;
// this.name = name;
// this.artist = artist;
// this.linkCover = linkCover;
// }
}
// }

@ -4,7 +4,7 @@ import { StyleSheet, Text, View , Image } from 'react-native';
import normalize from '../components/Normalize';
type CustomCardMusic = { //Props
image: ImageSource;
image: string;
title: string;
description: string;
}

@ -1,12 +1,16 @@
export default class Music {
private _id : string;
private _title: string;
private _bio: string;
private _image: ImageSource;
private _image: string;
private _trackPreviewUrl : string;
constructor(title: string, bio: string, image: ImageSource) {
constructor(id : string,title: string, bio: string, image: string, trackPreviewUrl: string) {
this._title = title;
this._bio = bio;
this._image = image;
this._id = id;
this._trackPreviewUrl = trackPreviewUrl;
}
get title(): string {
@ -25,11 +29,27 @@ export default class Music {
this._bio = value;
}
get image(): ImageSource {
get image(): string {
return this._image;
}
set image(value: ImageSource) {
set image(value: string) {
this._image = value;
}
get id(): string {
return this._id;
}
set id(value: string) {
this._id = value;
}
get trackPreviewUrl(): string {
return this._trackPreviewUrl;
}
set trackPreviewUrl(value: string) {
this._trackPreviewUrl = value;
}
}

@ -2,6 +2,7 @@ import React from 'react';
import Favorite from '../screens/Favorite';
import { createStackNavigator } from '@react-navigation/stack';
import { ArtistLayout } from '../components/Genre';
import MusicDetail from '../screens/MusicDetail';
export default function MusicNavigation() {
const Stack = createStackNavigator();
@ -12,6 +13,11 @@ export default function MusicNavigation() {
component={Favorite}
options={{ headerShown: false }}
/>
<Stack.Screen
name="MusicDetail"
component={MusicDetail}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Genre"
component={ArtistLayout}

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
import FavoriteNavigation from './FavoriteNavigation';
@ -10,6 +10,9 @@ import FontAwesome from 'react-native-vector-icons/FontAwesome';
import SpotNavigation from './SpotNavigation';
import Login from '../screens/login';
import FladLoading from '../components/FladLoadingScreen';
import { useDispatch, useSelector } from 'react-redux';
import { getFavoritesMusic } from '../redux/actions/appActions';
// import { fetchFavoritesMusic } from '../redux/thunk/spotThunk';
export default function Navigation() {
const BottomTabNavigator = createBottomTabNavigator();
@ -22,6 +25,15 @@ export default function Navigation() {
text: 'rgb(138, 138, 138)',
}
};
//@ts-ignore
const favoritesMusicLength : number = useSelector(state => state.appReducer.favoriteMusic.length);
// const dispatch = useDispatch();
// useEffect(() => {
// const loadFavoritesMusics = async () => {
// await dispatch(fetchFavoritesMusic());
// };
// loadFavoritesMusics();
// }, [dispatch]);
return (
// @ts-ignore
<NavigationContainer theme={MyTheme}>
@ -41,8 +53,8 @@ export default function Navigation() {
<BottomTabNavigator.Screen name="Favorites" component={FavoriteNavigation}
options={{
// use Selector state redux badgeCount ? badgeCount : undefined
tabBarBadge : 2,
tabBarBadge : favoritesMusicLength,
tabBarBadgeStyle : {backgroundColor : 'yellow'},
headerShown: false,
tabBarIcon: ({color}) => <TabBarIcon name="heart" color={color}/>,

@ -1,5 +1,5 @@
import React, {Component} from 'react';
import FavoritePage from '../screens/favoritePage';
import FavoritePage from '../screens/favorite';
import { createStackNavigator } from '@react-navigation/stack';
import Spot from '../screens/spot'
import { createSharedElementStackNavigator } from "react-navigation-shared-element";

@ -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,
};
}

@ -4,15 +4,27 @@ import { discoveriesTypes } from "../types/discoverieTypes";
import { favoritesTypes } from "../types/favoritesTypes";
import { spotifyTypes } from "../types/spotifyTypes";
import { spotTypes } from "../types/spotTypes";
const tmpMusic: Music[] = [
// new Music("La pharmacie", "Jul",require("../assets/images/jul.png")),
// new Music("Deux frères", "PNL", require("../assets/images/pnl.png")),
new Music("6npyDB4mn8MO1A1h666FTk","Bambina", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png","https://p.scdn.co/mp3-preview/d38052978a79adced2187cd8b6497bb10bedc452?cid=774b29d4f13844c495f206cafdad9c86"),
// new Music("0qwxx9ouUc5kGmMWHglDpq","Stratos", "Kekra", "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png",""),
new Music("03o8WSqd2K5rkGvn9IsLy2","Autobahn", "Sch", "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg","https://p.scdn.co/mp3-preview/c55f95de81b8c3d0df04148da1b03bd38db56e8f?cid=774b29d4f13844c495f206cafdad9c86"),
new Music("6DPrYPPGYK218iVIZDix3i","Freeze Raël", "Freeze Corleone", "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png","https://p.scdn.co/mp3-preview/a9f9cb19ac1fe6db0d06b67decf8edbb25895a33?cid=774b29d4f13844c495f206cafdad9c86"),
// new Music("Blanka", "PNL", require("../assets/images/pnl.png")),
new Music("5GFHFEASZeJF0gyWuDDjGE","Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png","https://p.scdn.co/mp3-preview/9e854f4905c1228482e390169eb76d8520076b8f?cid=774b29d4f13844c495f206cafdad9c86"),
] ;
const initialState = {
spot: [] as Spot[],
favoriteMusic: [] as Music [],
favoriteMusic: tmpMusic,
userCurrentMusic : null
}
const appReducer = (state = initialState, action : any) => {
switch (action.type) {
case favoritesTypes.GET_FAVORITE_MUSICS:
return {...state, favoriteMusic: action.playload};
case favoritesTypes.ADD_FAVORITE_MUSICS:
return {...state, favoriteMusic: state.favoriteMusic.push(action.payload)};
case favoritesTypes.REMOVE_FAVORITE_MUSICS:

@ -4,7 +4,7 @@ import userReducer from './reducers/userReducer';
// Reference here all your application reducers
const reducer = {
// appReducer: appReducer,
appReducer: appReducer,
userReducer: userReducer
}

@ -8,6 +8,8 @@ import { Spot } from "../../Model/Spot";
import SpotifyService from "../../services/spotify/spotify.service";
import * as Location from 'expo-location';
import { setSpotList, setUserCurrentMusic } from "../actions/spotActions";
import Music from "../../Model/Music";
import { getFavoritesMusic } from "../actions/appActions";
const key = 'userToken';
export type CreateSpotReqBody = {
@ -91,6 +93,24 @@ export const getCurrentUserMusic = (resuestHandler : SpotifyService)=> {
}
}
}
// export const fetchFavoritesMusic = () => {
// //@ts-ignore
// return async dispatch => {
// const MovieList: Music[] = [
// // new Music("La pharmacie", "Jul",require("../assets/images/jul.png")),
// // new Music("Deux frères", "PNL", require("../assets/images/pnl.png")),
// new Music("Bambina", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
// new Music("Stratos", "Kekra", "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png"),
// new Music("Autobahn", "Sch", "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg"),
// new Music("Freeze Raël", "Freeze Corleone", "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png"),
// // new Music("Blanka", "PNL", require("../assets/images/pnl.png")),
// new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
// ] ;
// dispatch(getFavoritesMusic(MovieList));
// }
// }
// export const getSpotList = () => {
// return async dispatch => {
// try {

@ -1,6 +1,7 @@
export const favoritesTypes = {
GET_FAVORITE_MUSICS : 'GET_FAVORITE_MUSICS',
ADD_FAVORITE_MUSICS : 'ADD_FAVORITE_MUSICS',
REMOVE_FAVORITE_MUSICS : 'REMOVE_FAVORITE_MUSICS',
}

@ -1,29 +1,27 @@
import React, { useState} from 'react';
import { Image,StyleSheet, Text, View, FlatList, ScrollView, TouchableOpacity } from 'react-native';
import React, { useEffect, useState} from 'react';
import { Image,StyleSheet, Text, View, FlatList, ScrollView, TouchableOpacity, TouchableHighlight } from 'react-native';
import CardMusic from '../components/CardMusic';
import normalize from '../components/Normalize';
import Music from '../Model/Music'
import {useNavigation} from "@react-navigation/native";
import { useDispatch, useSelector } from 'react-redux';
import { getFavoritesMusic } from '../redux/actions/appActions';
export default function favoritePage() {
const navigation = useNavigation();
const MUSIC_LIST : Music[] = [
new Music("La pharmacie", "Jul",require("../assets/images/jul.png")),
new Music("Deux frères", "PNL", require("../assets/images/pnl.png")),
new Music("Bambina", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
new Music("Stratos", "Kekra", "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png"),
new Music("Autobahn", "Sch", "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg"),
new Music("Freeze Raël", "Freeze Corleone", "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png"),
new Music("Blanka", "PNL", require("../assets/images/pnl.png")),
new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
]
//@ts-ignore
const favoritesMusic = useSelector(state => state.appReducer.favoriteMusic);
const dispatch = useDispatch();
const navigueToDetail = (music : any) => {
navigation.navigate("MusicDetail", {"music": music})
};
// to do
const [filteredDataSource, setFilteredDataSource] = useState<Music[]>([]);
const [search, setSearch] = useState('');
const searchMusic = (text: string) => {
if (text) {
const newData = MUSIC_LIST.filter(function (item: Music) {
const newData = favoritesMusic.filter(function (item: Music) {
const search = item.title
? item.title.toUpperCase() : ''.toUpperCase();
const textsearch = text.toUpperCase();
@ -46,11 +44,11 @@ export default function favoritePage() {
<ScrollView>
<View>
<FlatList style={{marginBottom: 80}}
data={MUSIC_LIST}
data={favoritesMusic}
renderItem={({ item }) => (
//<TouchableHighlight onPress={() => navigation.navigate("")}>
<TouchableHighlight onPress={() => {navigueToDetail(item)}}>
<CardMusic image={item.image} title={item.title} description={item.bio}/>
//</TouchableHighlight>
</TouchableHighlight>
)}
keyExtractor={(item: Music) => item.title }
/>

@ -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;

@ -113,8 +113,8 @@ export default function Spot() {
}, [])
// function addWatchLater(props: Movie) {
// dispatch(addMovieToWatchLater(props));
// function addLike(props: Movie) {
// dispatch(addFavoriteMu(props));
// dispatch(removeMovieTrending(props));
// if (displayIndex == trendingMovies.length - 1) {
// setdisplayIndex(0);
@ -122,14 +122,6 @@ export default function Spot() {
// }
// }
// function addFavourite(props: Movie) {
// dispatch(addMovieToFavourite(props));
// dispatch(removeMovieTrending(props));
// if (displayIndex == trendingMovies.length - 1) {
// setdisplayIndex(0);
// swiper.swipeLeft();
// }
// }
// const hapti = (() => {

Loading…
Cancel
Save