diff --git a/src/Api/src/controller/spotify-controller/spotifyCtrl.ts b/src/Api/src/controller/spotify-controller/spotifyCtrl.ts index a26f33b..204c815 100644 --- a/src/Api/src/controller/spotify-controller/spotifyCtrl.ts +++ b/src/Api/src/controller/spotify-controller/spotifyCtrl.ts @@ -22,7 +22,7 @@ class SpotifyController implements Controller { this.router.get(`${this.path}/exchange`,this.login); this.router.get(`${this.path}/callback`,this.getAccessToken); // this.router.post(`${this.path}/refresh`,this.getRefreshToken); - this.router.get(`${this.path}/play/:musicId`, this.getMusic); + // this.router.get(`${this.path}/play/:musicId`, this.getMusic); this.router.get(`${this.path}/spot`, this.getSpot); } @@ -137,10 +137,6 @@ class SpotifyController implements Controller { } - public getMusic(){ - - return null; - } public getSpot = async ( req: Request, diff --git a/src/Api/src/controller/user-controller/userCtrl.ts b/src/Api/src/controller/user-controller/userCtrl.ts index 9f5c740..2479abb 100644 --- a/src/Api/src/controller/user-controller/userCtrl.ts +++ b/src/Api/src/controller/user-controller/userCtrl.ts @@ -219,8 +219,9 @@ class UserController implements Controller { console.log('Impossible de convertir la chaîne en nombre'); } //} + const currentMusicId = req.body.currentMusicId; const userId = req.user.idFlad; - const data = await this.locationService.getNearUser(userId,latitude,longitude); + const data = await this.locationService.getNearUser(userId,latitude,longitude, currentMusicId); console.log(data); res.status(201).send(data); diff --git a/src/Api/src/database/schema/LocationSchema.ts b/src/Api/src/database/schema/LocationSchema.ts index 37d37b4..b055d2b 100644 --- a/src/Api/src/database/schema/LocationSchema.ts +++ b/src/Api/src/database/schema/LocationSchema.ts @@ -18,6 +18,9 @@ const locationSchema = new Schema( type: Number, required: true, }, + currentMusicId : { + type: String, + } }, diff --git a/src/Api/src/model/locationModel.ts b/src/Api/src/model/locationModel.ts index 99fb3ca..37341b1 100644 --- a/src/Api/src/model/locationModel.ts +++ b/src/Api/src/model/locationModel.ts @@ -32,10 +32,12 @@ export class UserLocation { uuid: string; latitude : number; longitude: number; - constructor(uuid: string, latitude: number, longitude: number){ + currentMusicId : string; + constructor(uuid: string, latitude: number, longitude: number, currentMusicId : string) { this.uuid = uuid; this.latitude = latitude; this.longitude = longitude; + this.currentMusicId = currentMusicId; } } diff --git a/src/Api/src/service/LocationService.ts b/src/Api/src/service/LocationService.ts index 077c0a5..6b09c4a 100644 --- a/src/Api/src/service/LocationService.ts +++ b/src/Api/src/service/LocationService.ts @@ -6,11 +6,11 @@ import LocationSchema from "../database/schema/LocationSchema"; class LocationService { private locationCollection = LocationSchema; // private API_KEY : string = "AIzaSyBFCEAtmhZ8jvw84UTQvX3Aqpr66GVqB_A"; - public async getNearUser(idFlad : string, latitude : number, longitude : number) + public async getNearUser(idFlad : string, latitude : number, longitude : number, currentMusicId: string) { await this.locationCollection.findOneAndUpdate( { idFlad }, - { idFlad, latitude, longitude }, + { idFlad, latitude, longitude, currentMusicId }, { upsert: true } ); @@ -22,18 +22,18 @@ class LocationService { let dbUsersList:UserLocation[] = []; snapshot.forEach(doc => { - dbUsersList.push(new UserLocation(doc.idFlad,doc.latitude,doc.longitude)); + dbUsersList.push(new UserLocation(doc.idFlad,doc.latitude,doc.longitude, doc.currentMusicId)); console.log(doc.idFlad, '=>', doc); }); // missing the curent music - let listUser: string[] = []; + let listUser: {userid: string, music : string}[] = []; dbUsersList.forEach(user => { console.log(user); const dist = this.distanceBetween(latitude , longitude , user.latitude, user.longitude); console.log(user.uuid,dist); if (dist <= 100) { - listUser.push(user.uuid); + listUser.push({userid : user.uuid, music : user.currentMusicId}); } }); 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/Model/Spot.tsx b/src/FLAD/Model/Spot.tsx index 46a6f9d..6212dca 100644 --- a/src/FLAD/Model/Spot.tsx +++ b/src/FLAD/Model/Spot.tsx @@ -2,7 +2,7 @@ import Music from "./Music"; export class Spot { private _userId : string; - public _music : Music; + private _music : Music; constructor(userId : string, music : Music){ this._userId = userId; this._music = music; @@ -10,8 +10,13 @@ export class Spot { get userSpotifyId(): string { return this._userId; } - get idSpotify(): Music { - return this._music; - } - + set userSpotifyId(value: string) { + this._userId = value; + } + get music(): Music { + return this._music; + } + set music(value: Music) { + this._music = value; + } } \ No newline at end of file diff --git a/src/FLAD/Model/factory/MusicFactory.ts b/src/FLAD/Model/factory/MusicFactory.ts index 1e813c2..e1d9973 100644 --- a/src/FLAD/Model/factory/MusicFactory.ts +++ b/src/FLAD/Model/factory/MusicFactory.ts @@ -5,7 +5,9 @@ export default class MusicFactory { const music = new Music( jsonMusic.id, jsonMusic.name, - jsonMusic.album.images[0].url + "", + jsonMusic.album.images[0].url, + jsonMusic.preview_url ); return music; } diff --git a/src/FLAD/app.json b/src/FLAD/app.json index 1cdc675..8db8416 100644 --- a/src/FLAD/app.json +++ b/src/FLAD/app.json @@ -7,7 +7,7 @@ "icon": "./assets/icons/icon.png", "userInterfaceStyle": "light", "splash": { - "image": "./assets/images/RedFlady.png", + "image": "./assets/icons/splash.png", "resizeMode": "contain", "backgroundColor": "#1d2129" }, diff --git a/src/FLAD/components/Card.tsx b/src/FLAD/components/Card.tsx index 40c8002..1e70aa7 100644 --- a/src/FLAD/components/Card.tsx +++ b/src/FLAD/components/Card.tsx @@ -11,7 +11,7 @@ const SCREEN_WIDTH = Dimensions.get('window').width interface CardProps { title: string; image: any; - onSwipe: (direction: "left" | "right") => void; + onSwipe: (direction: "left" | "right" | "down") => void; } type ContextType = { translateX: number; @@ -47,7 +47,12 @@ const Card = ({ title, image, onSwipe } : CardProps) => { } else if (translateX.value < -160) { runOnJS(onSwipe)("left"); // onSwipe("left"); - } else { + }else if (translateY.value > 250) { + runOnJS(onSwipe)("down"); + // onSwipe("left"); + } + + else { translateX.value = withSpring(0); translateY.value = withSpring(0); } diff --git a/src/FLAD/components/CardMusic.tsx b/src/FLAD/components/CardMusic.tsx index 7cf3393..89b1602 100644 --- a/src/FLAD/components/CardMusic.tsx +++ b/src/FLAD/components/CardMusic.tsx @@ -1,24 +1,33 @@ import React from 'react'; import { StyleSheet, Text, View , Image } from 'react-native'; +import { SharedElement } from 'react-navigation-shared-element'; +import { useSelector } from 'react-redux'; import normalize from '../components/Normalize'; type CustomCardMusic = { //Props - image: ImageSource; + image: string; title: string; description: string; + id : string; } + export default function CardMusic(CBP: CustomCardMusic) { + +const currentMusic = useSelector(state => state.appReducer.currentMusic); + const source = typeof CBP.image === 'string' ? { uri: CBP.image } : CBP.image; return ( + - {CBP.title} - {CBP.description} + {/* currentMusic.id === CBP.id && styles.currentMusic */} + {CBP.title} + {CBP.description} ); @@ -59,5 +68,8 @@ const styles = StyleSheet.create({ description: { color: 'white', fontSize: normalize(18) + }, + currentMusic: { + color: 'red' } }); \ No newline at end of file diff --git a/src/FLAD/components/CurrentMusic.tsx b/src/FLAD/components/CurrentMusic.tsx new file mode 100644 index 0000000..09e2ac3 --- /dev/null +++ b/src/FLAD/components/CurrentMusic.tsx @@ -0,0 +1,145 @@ +// import React, { useEffect, useRef } from 'react'; +// import { StyleSheet, Text, View , Image } from 'react-native'; +// import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'; +// import { SharedElement } from 'react-navigation-shared-element'; +// import { useSelector } from 'react-redux'; + +// import normalize from '../components/Normalize'; +// import SpotifyService from '../services/spotify/spotify.service'; + + + +// export default function CurrentMusic() { +// const animatedStyle = useAnimatedStyle(() => { +// return { +// transform: [ +// { scale: withTiming(139.929, { duration: 1000 }) } +// ] +// } +// }); +// const centerX = useSharedValue(0); +// const centerY = useSharedValue(0); +// const scale = useSharedValue(0); +// const width = useSharedValue(0); +// const height = useSharedValue(0); +// const rippleOpacity = useSharedValue(1); +// const rStyle = useAnimatedStyle(() => { +// const circleRadius = Math.sqrt(width.value ** 2 + height.value ** 2); + +// const translateX = centerX.value - circleRadius; +// const translateY = centerY.value - circleRadius; + +// return { +// width: circleRadius * 2, +// height: circleRadius * 2, +// borderRadius: circleRadius, +// opacity: rippleOpacity.value, +// backgroundColor: 'rgba(0,0,0,0.2)', +// position: 'absolute', +// top: 0, +// left: 0, +// transform: [ +// { translateX }, +// { translateY }, +// { +// scale: scale.value, +// }, +// ], +// }; +// }); + +// useEffect(() => { +// // withTiming, withSpring +// rippleOpacity.value = 1; +// scale.value = withTiming(1, { duration: 1000 }); +// }, [rippleOpacity,scale]); +// return ( + +// +// +// +// +// +// ); +// } + + +import React, { useEffect, useRef } from 'react'; +import { StyleSheet, Text, View , Image } from 'react-native'; +import Animated, { useAnimatedStyle, useDerivedValue, useSharedValue, withSpring, withTiming } from 'react-native-reanimated'; +import { SharedElement } from 'react-navigation-shared-element'; +import { useSelector } from 'react-redux'; + +import normalize from '../components/Normalize'; +import SpotifyService from '../services/spotify/spotify.service'; + + + +export default function CurrentMusic() { + const transition = useDerivedValue(() => { + return withSpring(value.value); + }); + + + return ( + + + + + + + ); +} + diff --git a/src/FLAD/components/HorizontalFlatList.tsx b/src/FLAD/components/HorizontalFlatList.tsx new file mode 100644 index 0000000..e14d26d --- /dev/null +++ b/src/FLAD/components/HorizontalFlatList.tsx @@ -0,0 +1,52 @@ +import { View, StyleSheet, Dimensions,Text, Image, Pressable, TouchableWithoutFeedback, TouchableOpacity, TouchableHighlight, FlatList } from "react-native"; +import Animated, { + Layout, + Transition, + ZoomIn, + ZoomOut, + } from "react-native-reanimated"; + +const { width } = Dimensions.get("window"); +const SIZE = width / 3; +import { Feather as Icon } from "@expo/vector-icons"; +import Music from "../Model/Music"; +import { State, TapGestureHandler } from "react-native-gesture-handler"; +import { useRef, useState } from "react"; + + +interface HorizontalFlatListProps { + // React.ReactNode; + renderCell: (image: string, titre : string) => React.ReactElement + title : string; + data : any[]; + } +export const HorizontalFlatList = ({ title, data, renderCell}: HorizontalFlatListProps) => { + + + return ( + + {title} + item.id} + renderItem={({item}) =>{ + return renderCell(item.image, image.titre); + }} + /> + ); + }; + const styles = StyleSheet.create({ + similarSection: { + paddingTop: 30 + }, + similarTitle: { + color: "#2998FD", + paddingLeft: 35, + fontSize: 17, + fontWeight: "600", + paddingBottom: 20 + } + + }); \ No newline at end of file diff --git a/src/FLAD/components/SelectedCard.tsx b/src/FLAD/components/SelectedCard.tsx new file mode 100644 index 0000000..8a05ce5 --- /dev/null +++ b/src/FLAD/components/SelectedCard.tsx @@ -0,0 +1,74 @@ +import { View, StyleSheet, Dimensions, Image, Pressable, TouchableWithoutFeedback, TouchableOpacity, TouchableHighlight } from "react-native"; +import Animated, { + Layout, + Transition, + ZoomIn, + ZoomOut, + } from "react-native-reanimated"; + +const { width } = Dimensions.get("window"); +const SIZE = width / 3; +import { Feather as Icon } from "@expo/vector-icons"; +import Music from "../Model/Music"; +import { State, TapGestureHandler } from "react-native-gesture-handler"; +import { useRef, useState } from "react"; + + +interface SelectedCardProps { + artist: Music; + onPress: () => void; + // cheepPosition: string ;(direction: "left" | "right" | "down") + } +export const SelectedCard = ({ artist, onPress }: SelectedCardProps) => { + const [selected,setSeleted] = useState(false); + const onS = () => { + setSeleted(!selected); + onPress(); + }; + + return ( + + + + + { selected && ( + + + + )} + + + + + ); + }; + const styles = StyleSheet.create({ + container: { + width: SIZE, + height: SIZE, + padding: 8, + }, + card: { + flex: 1, + padding: 8, + alignItems: "flex-end", + }, + image: { + borderRadius: 8, + ...StyleSheet.absoluteFillObject, + width: undefined, + height: undefined, + }, + cheked : { + backgroundColor : "white", + borderRadius : 100, + alignItems : "center", + + + } + }); \ No newline at end of file diff --git a/src/FLAD/components/littleCard.tsx b/src/FLAD/components/littleCard.tsx new file mode 100644 index 0000000..362cd47 --- /dev/null +++ b/src/FLAD/components/littleCard.tsx @@ -0,0 +1,29 @@ +import {TouchableOpacity, ScrollView, View, Text, StyleSheet, Image, SafeAreaView, FlatList, Animated} from 'react-native'; + + +export default function littleCard ({image,titre}){ + return ( + + + {titre} + + + ) +} +const styles = StyleSheet.create({ + + similarContainer: { + width: 90, + marginHorizontal: 7 + }, + similarTitleFilm: { + color: "#DADADA", + paddingTop: 5, + fontWeight: "300" + }, + similarPoster: { + height: 130, + width: 90, + borderRadius: 8 + } +}) diff --git a/src/FLAD/data/data.ts b/src/FLAD/data/data.ts index 4b92177..96fe6e1 100644 --- a/src/FLAD/data/data.ts +++ b/src/FLAD/data/data.ts @@ -1,6 +1,8 @@ -export const cards = [{ - musicName : "Je bibi", - name : "Kaaris", +import Music from "../Model/Music"; +import { Spot } from "../Model/Spot"; + +export const cards= [{ + name : "blue", sourceUrl : "https://th.bing.com/th/id/R.dbf87f0d8cbfd078ab6a589a5d921994?rik=1%2f6KliMpOAeh8A&pid=ImgRaw&r=0", index : 4 }, @@ -42,3 +44,43 @@ export const cards = [{ }, ] + +const spotArray: Spot[] = [ + new Spot("1", new Music("1", "Title 1", "Bio 1", "Image 1", "TrackPreviewUrl 1")), + new Spot("2", new Music("2", "Title 2", "Bio 2", "Image 2", "TrackPreviewUrl 2")), + new Spot("3", new Music("3", "Title 3", "Bio 3", "Image 3", "TrackPreviewUrl 3")), + new Spot("4", new Music("4", "Title 4", "Bio 4", "Image 4", "TrackPreviewUrl 4")), + new Spot("5", new Music("5", "Title 5", "Bio 5", "Image 5", "TrackPreviewUrl 5")), +]; +export const spotArray2: Spot[] = [ + new Spot("1", new Music("6KNw3UKRp3QRsO7Cf4ASVE", + "MOLLY - A COLORS SHOW", + "Tame Impala", + "https://i.scdn.co/image/ab67616d0000b2734299eb40408fc73ce8bf490a", + "https://p.scdn.co/mp3-preview/4faf99856f15e03a09d50b91006efd3205606866?cid=774b29d4f13844c495f206cafdad9c86") + ), + new Spot("2", new Music("5yHoANSze7sGzhn9MUarH3", + "Passat", + "Silk Sonic, Bruno Mars, Anderson .Paak", + "https://i.scdn.co/image/ab67616d0000b273e9df9b5a7df491536c51c922", + "https://p.scdn.co/mp3-preview/0bb7472026a00790950fc231fe61963ef7cc867b?cid=774b29d4f13844c495f206cafdad9c86") + ), + new Spot("3", new Music("7suNqxRED5CrwyZSzYC0nT", + "Extendo", + "Kali Uchis", + "https://i.scdn.co/image/ab67616d0000b273b856464c40a062d1723a21f2", + "https://p.scdn.co/mp3-preview/5398121f6295965e3c7cad8a6dca5667ba7f4713?cid=774b29d4f13844c495f206cafdad9c86") + ), + new Spot("4", new Music("07JqNLmPUJSlcouGQoJlzq", + "Addiction", + "Harry Styles", + "https://i.scdn.co/image/ab67616d0000b2739297f238f237431d56c67460", + "https://p.scdn.co/mp3-preview/33d12e9e5a3dd3394b1649d515912260b01579dd?cid=774b29d4f13844c495f206cafdad9c86") + ), + new Spot("5", new Music("5Ylp75kdffyJSwISRPqEiL", + "La Vidéo", + "Harry Styles", + "https://i.scdn.co/image/ab67616d0000b2738900d48677696015bf325b8b", + "https://p.scdn.co/mp3-preview/4fff3f8d76a422f42cea39f001836a3d54937fc4?cid=774b29d4f13844c495f206cafdad9c86") + ) +]; 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..4b76015 100644 --- a/src/FLAD/navigation/FavoriteNavigation.tsx +++ b/src/FLAD/navigation/FavoriteNavigation.tsx @@ -2,20 +2,28 @@ 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'; +import InfoScreen from '../screens/testPage'; +import { createSharedElementStackNavigator } from 'react-navigation-shared-element'; +import CurrentMusic from '../components/CurrentMusic'; +const Stack = createSharedElementStackNavigator(); export default function MusicNavigation() { - const Stack = createStackNavigator(); return ( - + + {return [route.params.music.id]}} /> ) diff --git a/src/FLAD/navigation/Navigation.tsx b/src/FLAD/navigation/Navigation.tsx index 90987fa..eba9bb6 100644 --- a/src/FLAD/navigation/Navigation.tsx +++ b/src/FLAD/navigation/Navigation.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { View, StyleSheet, Platform } from 'react-native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { NavigationContainer } from '@react-navigation/native'; @@ -11,6 +11,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(); @@ -23,6 +26,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 @@ -45,8 +57,8 @@ export default function Navigation() { , diff --git a/src/FLAD/navigation/SpotNavigation.tsx b/src/FLAD/navigation/SpotNavigation.tsx index 158e177..595c106 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"; @@ -22,10 +22,10 @@ export default function SpotNavigation() { name="Spots" component={Spot} /> - + /> */} {/* { + return { + type: favoritesTypes.GET_FAVORITE_MUSICS, + playload: favoritesMusic, + }; +} +export const addFavoritesMusic = (favoritesMusic: Music) => { + return { + type: favoritesTypes.ADD_FAVORITE_MUSICS , + playload: favoritesMusic, + }; +} diff --git a/src/FLAD/redux/reducers/appReducer.tsx b/src/FLAD/redux/reducers/appReducer.tsx index c08cc64..2d6bc04 100644 --- a/src/FLAD/redux/reducers/appReducer.tsx +++ b/src/FLAD/redux/reducers/appReducer.tsx @@ -4,18 +4,30 @@ import { discoveriesTypes } from "../types/discoverieTypes"; import { favoritesTypes } from "../types/favoritesTypes"; import { spotifyTypes } from "../types/spotifyTypes"; import { spotTypes } from "../types/spotTypes"; - +let 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: + return {...state, favoriteMusic: [action.playload, ...state.favoriteMusic]}; + case favoritesTypes.REMOVE_FAVORITE_MUSICS: return {...state, favoriteMusic: state.favoriteMusic}; case spotTypes.FETCH_SPOT: return {...state, spot: action.payload}; 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..051d19d 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,46 @@ export const getCurrentUserMusic = (resuestHandler : SpotifyService)=> { } } } +export const searchMusic = async (resuestHandler : SpotifyService,search: string) => { + // + return async (dispatch) => { + // const fetchAll = async () => { + // const data = await fetch(`https://kanjialive-api.p.rapidapi.com/api/public/search/${search}`, options) + // .then(response => response.json()); + + // const fetchPromises = data.map(it => + // fetch(`https://kanjialive-api.p.rapidapi.com/api/public/kanji/${it.kanji.character}`, options) + // .then(detail => detail.json()) + // ); + + // const kanjis = await Promise.all(fetchPromises) + // .then(details => details.map(detail_data => KanjiMapper.ApiJsonToKanji(detail_data))); + + // return kanjis; + // }; + + return resuestHandler.searchMusic(search).then(musics => dispatch((musics))).catch(err => console.log("something goes wrong while searching : " + err)); + + + }; +} +// 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 bd6f8f8..d515231 100644 --- a/src/FLAD/screens/Favorite.tsx +++ b/src/FLAD/screens/Favorite.tsx @@ -1,29 +1,28 @@ -import React, { useState} from 'react'; -import { Image,StyleSheet, Text, View, FlatList, ScrollView, TouchableOpacity, SafeAreaView } 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'; +import { SharedElement } from 'react-navigation-shared-element'; 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(); @@ -40,9 +39,24 @@ export default function favoritePage() { return ( - - Favoris - Retrouvez ici vos musiques favorites + + Favoris + Retrouvez ici vos musiques favorites + + + + ( + {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..dc77d51 --- /dev/null +++ b/src/FLAD/screens/MusicDetail.tsx @@ -0,0 +1,283 @@ +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"; +import SpotifyService from "../services/spotify/spotify.service"; +import { SharedElement } from "react-navigation-shared-element"; + +const halfPi = Math.PI/2; + +//@ts-ignore +const MusicDetail = ({ 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 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); + setIsPlaying(true); + + } else { + setIsPlaying(true); + //@ts-ignore + await sound.playAsync(); + } + }; + + const handleStopSound = async () => { + if (sound !== null) { + setIsPlaying(false); + + //@ts-ignore + await sound.stopAsync(); + } + else{ + } + }; + useEffect(() => { + return sound ? () => { + console.log('Unloading Sound'); + //@ts-ignore + sound.unloadAsync(); + } + : undefined; + }, [sound]); + // useEffect(() => { + // if(isPlaying){ + + // } + // }) + + const sensor = useAnimatedSensor(SensorType.ROTATION); + const styleAniamatedImage = useAnimatedStyle(() => { + const {yaw, pitch, roll} = sensor.sensor.value; + const verticalAxis =interpolate( + pitch, + [-halfPi*2,halfPi*2], + [-45, 45] + ) + const horizontalAxis =interpolate( + roll, + [-halfPi*2,halfPi*2], + [-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); + const playMusic = async (id: string) => { + try { + const service = new SpotifyService("BQDWJTPvSloZPYDqLc1YWri2LEcognvqoM5bdoCWMuHR9In2FhaKq5tW3-VC5JET9dD9K-W4Rmm0IiyhtX-fSL3Tb8RTHMJUc5GKFq2jxWlH7QXxsiYZV8Fhw2qU1eCpSof1qkPsBd1R36GOgcBaXq2N6kLTP5UcfP-gzjz65x_fVRSxoP6znK2dkvL6saQ6WwzoEFopqpqo") ; + console.log("=====================================================)))))))))))))))"+id+"================================") + await service.playMusic(id); + }catch(error){} + } + + return ( + + {/* */} + + + +