From dfe944faff3ac8721eeb6855d583060c5ff7a3ec Mon Sep 17 00:00:00 2001 From: dadalmeida1 Date: Sun, 5 Mar 2023 18:16:49 +0100 Subject: [PATCH] music player 3/4 done --- src/FLAD/Model/Music.tsx | 24 +- src/FLAD/components/CardMusic.tsx | 2 +- src/FLAD/model/Music.ts | 28 +- src/FLAD/navigation/FavoriteNavigation.tsx | 6 + src/FLAD/navigation/Navigation.tsx | 18 +- src/FLAD/navigation/SpotNavigation.tsx | 2 +- src/FLAD/redux/actions/appActions.ts | 11 + src/FLAD/redux/reducers/appReducer.tsx | 16 +- src/FLAD/redux/store.tsx | 2 +- src/FLAD/redux/thunk/spotThunk.tsx | 20 ++ src/FLAD/redux/types/favoritesTypes.tsx | 1 + src/FLAD/screens/Favorite.tsx | 32 ++- src/FLAD/screens/MusicDetail.tsx | 295 +++++++++++++++++++++ src/FLAD/screens/spot.tsx | 12 +- 14 files changed, 418 insertions(+), 51 deletions(-) create mode 100644 src/FLAD/redux/actions/appActions.ts create mode 100644 src/FLAD/screens/MusicDetail.tsx diff --git a/src/FLAD/Model/Music.tsx b/src/FLAD/Model/Music.tsx index cc20984..d2b1715 100644 --- a/src/FLAD/Model/Music.tsx +++ b/src/FLAD/Model/Music.tsx @@ -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; +// } -} +// } diff --git a/src/FLAD/components/CardMusic.tsx b/src/FLAD/components/CardMusic.tsx index 7cf3393..32bdf59 100644 --- a/src/FLAD/components/CardMusic.tsx +++ b/src/FLAD/components/CardMusic.tsx @@ -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; } diff --git a/src/FLAD/model/Music.ts b/src/FLAD/model/Music.ts index db657b8..2d21e6a 100644 --- a/src/FLAD/model/Music.ts +++ b/src/FLAD/model/Music.ts @@ -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; + } } diff --git a/src/FLAD/navigation/FavoriteNavigation.tsx b/src/FLAD/navigation/FavoriteNavigation.tsx index a2f92d0..14b77b8 100644 --- a/src/FLAD/navigation/FavoriteNavigation.tsx +++ b/src/FLAD/navigation/FavoriteNavigation.tsx @@ -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 }} /> + state.appReducer.favoriteMusic.length); + // const dispatch = useDispatch(); + // useEffect(() => { + // const loadFavoritesMusics = async () => { + // await dispatch(fetchFavoritesMusic()); + // }; + // loadFavoritesMusics(); + // }, [dispatch]); return ( // @ts-ignore @@ -41,8 +53,8 @@ export default function Navigation() { , diff --git a/src/FLAD/navigation/SpotNavigation.tsx b/src/FLAD/navigation/SpotNavigation.tsx index 158e177..43be131 100644 --- a/src/FLAD/navigation/SpotNavigation.tsx +++ b/src/FLAD/navigation/SpotNavigation.tsx @@ -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"; diff --git a/src/FLAD/redux/actions/appActions.ts b/src/FLAD/redux/actions/appActions.ts new file mode 100644 index 0000000..4e2f47f --- /dev/null +++ b/src/FLAD/redux/actions/appActions.ts @@ -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, + }; +} diff --git a/src/FLAD/redux/reducers/appReducer.tsx b/src/FLAD/redux/reducers/appReducer.tsx index c08cc64..73955e7 100644 --- a/src/FLAD/redux/reducers/appReducer.tsx +++ b/src/FLAD/redux/reducers/appReducer.tsx @@ -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: diff --git a/src/FLAD/redux/store.tsx b/src/FLAD/redux/store.tsx index 9595adf..79b0b19 100644 --- a/src/FLAD/redux/store.tsx +++ b/src/FLAD/redux/store.tsx @@ -4,7 +4,7 @@ import userReducer from './reducers/userReducer'; // Reference here all your application reducers const reducer = { - // appReducer: appReducer, + appReducer: appReducer, userReducer: userReducer } diff --git a/src/FLAD/redux/thunk/spotThunk.tsx b/src/FLAD/redux/thunk/spotThunk.tsx index 907a329..31cb8f9 100644 --- a/src/FLAD/redux/thunk/spotThunk.tsx +++ b/src/FLAD/redux/thunk/spotThunk.tsx @@ -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 { diff --git a/src/FLAD/redux/types/favoritesTypes.tsx b/src/FLAD/redux/types/favoritesTypes.tsx index 3634534..e9c066d 100644 --- a/src/FLAD/redux/types/favoritesTypes.tsx +++ b/src/FLAD/redux/types/favoritesTypes.tsx @@ -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', } \ No newline at end of file diff --git a/src/FLAD/screens/Favorite.tsx b/src/FLAD/screens/Favorite.tsx index ae5965f..0809c99 100644 --- a/src/FLAD/screens/Favorite.tsx +++ b/src/FLAD/screens/Favorite.tsx @@ -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([]); 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() { ( - // navigation.navigate("")}> + {navigueToDetail(item)}}> - // + )} keyExtractor={(item: Music) => item.title } /> diff --git a/src/FLAD/screens/MusicDetail.tsx b/src/FLAD/screens/MusicDetail.tsx new file mode 100644 index 0000000..cafa936 --- /dev/null +++ b/src/FLAD/screens/MusicDetail.tsx @@ -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 ( + + {/* */} + + + +