starting detail page
continuous-integration/drone/push Build is passing Details

pull/11/head
David D'ALMEIDA 2 years ago
parent ce7dc3f8bc
commit 1147620e2f

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

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

@ -18,6 +18,9 @@ const locationSchema = new Schema(
type: Number,
required: true,
},
currentMusicId : {
type: String,
}
},

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

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

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

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

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

@ -14,7 +14,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;
@ -50,7 +50,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);
}

@ -1,5 +1,7 @@
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';
@ -7,18 +9,25 @@ type CustomCardMusic = { //Props
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 (
<View style={styles.container}>
<View style={styles.imageContainer}>
<Image source={source} style={styles.image}/>
</View>
<View style={styles.textContainer}>
<Text style={styles.title}>{CBP.title}</Text>
<Text style={styles.description}>{CBP.description}</Text>
{/* currentMusic.id === CBP.id && styles.currentMusic */}
<Text style={[styles.title]}>{CBP.title}</Text>
<Text style={[styles.description]}>{CBP.description}</Text>
</View>
</View>
);
@ -59,5 +68,8 @@ const styles = StyleSheet.create({
description: {
color: 'white',
fontSize: normalize(18)
},
currentMusic: {
color: 'red'
}
});

@ -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 (
// <View style={{
// width: 200,
// height: 200,
// backgroundColor: 'white',
// alignItems: 'center',
// justifyContent: 'center',
// borderRadius: 25,
// // iOS
// shadowOpacity: 0.2,
// shadowOffset: { width: 0, height: 0 },
// shadowRadius: 20,
// // Android
// elevation: 2,
// }}>
// <Animated.View style={[{
// width: 200,
// height: 200,
// backgroundColor: 'white',
// alignItems: 'center',
// justifyContent: 'center',
// borderRadius: 25,
// // iOS
// shadowOpacity: 0.2,
// shadowOffset: { width: 0, height: 0 },
// shadowRadius: 20,
// // Android
// elevation: 2,
// }, { overflow: 'hidden' }]}>
// <Animated.View style={rStyle} />
// </Animated.View>
// </View>
// );
// }
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 (
<View style={{
width: 200,
height: 200,
backgroundColor: 'white',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 25,
// iOS
shadowOpacity: 0.2,
shadowOffset: { width: 0, height: 0 },
shadowRadius: 20,
// Android
elevation: 2,
}}>
<Animated.View style={[{
width: 200,
height: 200,
backgroundColor: 'white',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 25,
// iOS
shadowOpacity: 0.2,
shadowOffset: { width: 0, height: 0 },
shadowRadius: 20,
// Android
elevation: 2,
}, { overflow: 'hidden' }]}>
<Animated.View style={rStyle} />
</Animated.View>
</View>
);
}

@ -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 (
<View style={styles.similarSection}>
<Text style={styles.similarTitle} >{title}</Text>
<FlatList
showsHorizontalScrollIndicator={false}
data={data}
horizontal={true}
keyExtractor={item => item.id}
renderItem={({item}) =>{
return renderCell(item.image, image.titre);
}}
/></View>
);
};
const styles = StyleSheet.create({
similarSection: {
paddingTop: 30
},
similarTitle: {
color: "#2998FD",
paddingLeft: 35,
fontSize: 17,
fontWeight: "600",
paddingBottom: 20
}
});

@ -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 (
<TouchableOpacity onPress={onS}>
<Animated.View
style={styles.container}
entering={ZoomIn}
exiting={ZoomOut}
layout={Layout.delay(200)}
>
<View style={styles.card}>
{ selected && (
<View style={styles.cheked}>
<Icon name="check-circle" color="black" size={24} />
</View>
)}
</View>
</Animated.View>
</TouchableOpacity>
);
};
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",
}
});

@ -0,0 +1,29 @@
import {TouchableOpacity, ScrollView, View, Text, StyleSheet, Image, SafeAreaView, FlatList, Animated} from 'react-native';
export default function littleCard ({image,titre}){
return (
<View style={styles.similarContainer}>
<Image source={{uri: image}} style={styles.similarPoster}></Image>
<Text numberOfLines={2} style={styles.similarTitleFilm}>{titre}
</Text>
</View>
)
}
const styles = StyleSheet.create({
similarContainer: {
width: 90,
marginHorizontal: 7
},
similarTitleFilm: {
color: "#DADADA",
paddingTop: 5,
fontWeight: "300"
},
similarPoster: {
height: 130,
width: 90,
borderRadius: 8
}
})

@ -1,4 +1,7 @@
export const cards = [{
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
@ -35,3 +38,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")
)
];

@ -3,25 +3,27 @@ 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 (
<Stack.Navigator initialRouteName="Favorite">
<Stack.Navigator initialRouteName="Favorite" screenOptions={{gestureEnabled: true, headerShown: false, cardOverlayEnabled: true, cardStyle: {backgroundColor: "transparent"}}} >
<Stack.Screen
name="Favorite"
component={Favorite}
options={{ headerShown: false }}
/>
<Stack.Screen
name="MusicDetail"
component={MusicDetail}
options={{ headerShown: false }}
component={InfoScreen}
sharedElements ={(route)=> {return [route.params.music.id]}}
/>
<Stack.Screen
name="Genre"
component={ArtistLayout}
options={{ headerShown: false }}
component={CurrentMusic}
/>
</Stack.Navigator>
)

@ -22,10 +22,10 @@ export default function SpotNavigation() {
name="Spots"
component={Spot}
/>
<Stack.Screen
{/* <Stack.Screen
name="DetailsSpot"
component={SpotDetailsPage}
/>
/> */}
{/* <Stack.Screen
name="DetailsSpot"
component={SpotDetailsPage}

@ -9,3 +9,9 @@ export const getFavoritesMusic = (favoritesMusic: Music[]) => {
playload: favoritesMusic,
};
}
export const addFavoritesMusic = (favoritesMusic: Music) => {
return {
type: favoritesTypes.ADD_FAVORITE_MUSICS ,
playload: favoritesMusic,
};
}

@ -4,7 +4,7 @@ import { discoveriesTypes } from "../types/discoverieTypes";
import { favoritesTypes } from "../types/favoritesTypes";
import { spotifyTypes } from "../types/spotifyTypes";
import { spotTypes } from "../types/spotTypes";
const tmpMusic: Music[] = [
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"),
@ -26,8 +26,8 @@ const initialState = {
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};

@ -93,7 +93,29 @@ 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 => {

@ -6,6 +6,7 @@ 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();
@ -47,7 +48,10 @@ export default function favoritePage() {
data={favoritesMusic}
renderItem={({ item }) => (
<TouchableHighlight onPress={() => {navigueToDetail(item)}}>
<CardMusic image={item.image} title={item.title} description={item.bio}/>
<SharedElement id={item.id}>
<CardMusic image={item.image} title={item.title} description={item.bio} id={item.id}/>
</SharedElement>
</TouchableHighlight>
)}
keyExtractor={(item: Music) => item.title }

@ -1,4 +1,3 @@
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";
@ -13,18 +12,12 @@ 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";
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);
@ -56,7 +49,6 @@ const MusicDetail = ({ route }) => {
// })
const trackPreviewUrl = 'https://p.scdn.co/mp3-preview/08ef3b9d6dbd6bab233f5e9ca564091902767f71?cid=774b29d4f13844c495f206cafdad9c86';
const playTrackPreview = async () => {
console.log("===============================================================================================================");
@ -87,8 +79,10 @@ const MusicDetail = ({ route }) => {
{ shouldPlay: true }
);
setSound(newSound);
setIsPlaying(true);
} else {
setIsPlaying(true);
//@ts-ignore
await sound.playAsync();
}
@ -96,11 +90,12 @@ const MusicDetail = ({ route }) => {
const handleStopSound = async () => {
if (sound !== null) {
setIsPlaying(false);
//@ts-ignore
await sound.stopAsync();
}
else{
setIsPlaying(true);
}
};
useEffect(() => {
@ -117,18 +112,17 @@ const MusicDetail = ({ route }) => {
// }
// })
console.log(music);
const sensor = useAnimatedSensor(SensorType.ROTATION);
const styleAniamatedImage = useAnimatedStyle(() => {
const {yaw, pitch, roll} = sensor.sensor.value;
const verticalAxis =interpolate(
pitch,
[-halfPi,halfPi],
[-halfPi*2,halfPi*2],
[-45, 45]
)
const horizontalAxis =interpolate(
roll,
[-halfPi,halfPi],
[-halfPi*2,halfPi*2],
[-45, 45]
)
return {
@ -218,14 +212,14 @@ const MusicDetail = ({ route }) => {
const animationState = new Value(State.UNDETERMINED);
const playMusic = async (id: string) => {
try {
const service = new SpotifyService("BQC4k_OPQXENwmm2S8qLm9whlJT9IjeKsuG6kJNyVCSd88b0L-zOY84VqwvQxFsc9G3GvtPyUMezwxi8BBBloitzbhWX5tmTKTaLsJosGTnb7xivwNhRv0-LnNYbZWB24ZGAg0xPmDLn0yYmYlo7M_SMK5cCZdYQcZNXAuMYaI18GVXKoICBaKfCn4GcqBiRRgXyCVQnNGU4") ;
const service = new SpotifyService("BQDWJTPvSloZPYDqLc1YWri2LEcognvqoM5bdoCWMuHR9In2FhaKq5tW3-VC5JET9dD9K-W4Rmm0IiyhtX-fSL3Tb8RTHMJUc5GKFq2jxWlH7QXxsiYZV8Fhw2qU1eCpSof1qkPsBd1R36GOgcBaXq2N6kLTP5UcfP-gzjz65x_fVRSxoP6znK2dkvL6saQ6WwzoEFopqpqo") ;
console.log("=====================================================)))))))))))))))"+id+"================================")
await service.playMusic(id);
}catch(error){}
}
return (
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
<View style={{borderWidth : 1, borderColor : 'red'}}>
@ -250,6 +244,7 @@ const MusicDetail = ({ route }) => {
// promptAsync();
}}
/>
</View>
{/* Button */}
@ -262,7 +257,7 @@ const MusicDetail = ({ route }) => {
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 24,
}} onPressIn={handlePlaySound}
}}
onPressOut={handleStopSound}
onLongPress={handlePlaySound}
delayLongPress={1000}>
@ -279,20 +274,6 @@ const MusicDetail = ({ route }) => {
{/* </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>

@ -6,7 +6,7 @@ import Animated from 'react-native-reanimated';
import Card from '../components/Card';
import { cards as cardArray } from '../data/data'
import { cards as cardArray, spotArray2 } from '../data/data'
import FladButton from '../components/button/button';
import axios from 'axios';
@ -21,6 +21,9 @@ import Lotties from '../assets/lottie/Lottie';
import FladLoading from '../components/FladLoadingScreen';
import { SharedElement } from 'react-navigation-shared-element';
import { useNavigation } from '@react-navigation/native';
import Music from '../Model/Music';
import { addFavoritesMusic } from '../redux/actions/appActions';
import { useDispatch } from 'react-redux';
interface SpotProps {
}
@ -90,17 +93,30 @@ async function getValueFor(key:string) :Promise<string | null> {
}
export default function Spot() {
const [cards, setCards] = useState(cardArray);
const [cards, setCards] = useState(spotArray2);
const [currentCard, setcurrentCard] = useState(cards[cards.length - 1]);
const onSwipe = (index: number, direction: 'left' | 'right') => {
const onSwipe = (index: number, direction: 'left' | 'right' | 'down') => {
if (direction === 'right') {
// Swiped right
console.log("====2==="+currentCard.music.title+"======2=========");
addLike(currentCard.music);
console.log('Swiped right');
} else if (direction === 'left') {
// Swiped left
console.log('Swiped left');
}
else if (direction === 'down') {
// Swiped down
console.log('Swiped down');
}
// update the state of the cards state when it remove thisy
setCards(cards.filter((_, i) => i !== index));
setcurrentCard(cards[index-1]);
// update the state of the cards state when it remove this
setTimeout(() => {
setCards(cards.filter((_, i) => i !== index));
setcurrentCard(cards[index - 1]);
}, 3);
// setCards(cards.filter((_, i) => i !== index));
// setcurrentCard(cards[index-1]);
};
const likeButtonref = useRef<LottieView>(null);
@ -110,17 +126,21 @@ export default function Spot() {
const onLike = useCallback( () => {
likeButtonref.current?.reset();
likeButtonref.current?.play(0,55);
likeButtonref.current?.play(55,0);
}, [])
// function addLike(props: Movie) {
// dispatch(addFavoriteMu(props));
// dispatch(removeMovieTrending(props));
// if (displayIndex == trendingMovies.length - 1) {
// setdisplayIndex(0);
// swiper.swipeLeft();
// }
// }
const dispatch = useDispatch();
function addLike(music: Music) {
onLike();
console.log("====3==="+currentCard.music.title+"======3=========");
dispatch(addFavoritesMusic(music))
// dispatch(addFavoriteMusic(props));
// if (displayIndex == trendingMovies.length - 1) {
// setdisplayIndex(0);
// swiper.swipeLeft();
// }
}
@ -199,7 +219,7 @@ export default function Spot() {
opacity: 0.48
}}
source={{
uri:currentCard.sourceUrl ,
uri:currentCard.music.image ,
}}
></ImageBackground>
@ -230,13 +250,13 @@ export default function Spot() {
<View style={{flex : 1.83, justifyContent: 'center', alignItems: 'center' }}>
{cards.map((card, index) => (
<View key={card.name} style = {{ position:'absolute'}} >
<View key={card.userSpotifyId} style = {{ position:'absolute'}} >
<Pressable onLongPress={() => {hapti(card)}} >
{/* <SharedElement id={card.name}> */}
<Card
title={card.name}
image={card.sourceUrl}
title={card.music.title}
image={card.music.image}
onSwipe={(direction) => {onSwipe(index, direction)}}
/>
{/* </SharedElement> */}
@ -255,7 +275,7 @@ export default function Spot() {
<LottieView autoPlay={false} loop={false} ref={likeButtonref} source={Lotties.likeAnimation} style={styles.lottie}/>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={onLike}>
<LottieView autoPlay={false} loop={false} ref={likeButtonref} source={Lotties.likeAnimation} style={styles.lottie}/>
<LottieView autoPlay={false} loop={false} ref={likeButtonref} speed={2} source={Lotties.likeAnimation} style={styles.lottie}/>
</TouchableOpacity>
</Animated.View>

@ -0,0 +1,479 @@
import * as React from 'react';
import {TouchableOpacity, ScrollView, View, Text, StyleSheet, Image, SafeAreaView, FlatList, Animated} from 'react-native';
import {useSafeAreaInsets} from "react-native-safe-area-context";
import {LinearGradient} from 'expo-linear-gradient';
import {useEffect, useState} from "react";
import Ionicons from "@expo/vector-icons/Ionicons";
import { SharedElement } from "react-navigation-shared-element";
import { NavigationProp, RouteProp, useNavigation } from "@react-navigation/native";
import { Dimensions, useWindowDimensions, Button } from "react-native";
import { 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 { State, TapGestureHandler } from "react-native-gesture-handler";
import { RequestHandler } from "../services/spotify/spotifyRequestHandler/utils";
import { FetchRequest } from "expo-auth-session/build/Fetch";
import SpotifyService from "../services/spotify/spotify.service";
import Music from '../Model/Music';
import { HorizontalFlatList } from '../components/HorizontalFlatList';
import littleCard from '../components/littleCard';
const halfPi = Math.PI/2;
// InfoScreen.sharedElement = (navigation : ReturnType<typeof useNavigation>)=>{
// const music = navigation.getParam('music');
// return [music.id];
// }
// @ts-ignore
export default function InfoScreen({route, navigation}) {
const item: Music = route.params.music;
const insets = useSafeAreaInsets();
const [similarMusics, setSimilarMusics] = useState<Music[]>([]);
// parralax
// parralax
const styles = StyleSheet.create({
background1: {
height: '100%',
width: '100%',
paddingTop: insets.top,
},
body: {
backgroundColor: "#0E0E0E"
},
backgroundSection: {
height: "100%",
width: "100%",
position: "absolute"
},
back_drop: {
height: "45%",
width: '100%',
position: "absolute",
},
gradientFade: {
height: "30%",
top: "25%"
},
backButton: {
position: "absolute",
top: 10,
left: 5
},
list: {
height: "100%"
},
section1: {
paddingHorizontal: 35
},
title: {
color: "white",
fontSize: 43,
fontWeight: "bold",
paddingBottom: 10,
paddingTop: "45%"
},
characteristics: {
flexDirection: "row",
width: "100%",
justifyContent: "flex-start"
},
stars: {
flexDirection: "row",
width: "100%",
justifyContent: "flex-start",
alignItems: "center",
paddingBottom: 30
},
starsLabel: {
color: "#FFC42D",
fontWeight: "bold",
paddingLeft: 10,
fontSize: 16
},
player: {
borderRadius: 10,
overflow: "hidden"
},
resume: {
color: "#B3B3B3",
paddingTop: 30,
fontSize: 17
},
creditSection: {
paddingTop: 30
},
creditTitle: {
color: "#2998FD",
paddingBottom: 20,
paddingLeft: 35,
fontSize: 17,
fontWeight: "600"
},
similarSection: {
paddingTop: 30
},
similarTitle: {
color: "#2998FD",
paddingLeft: 35,
fontSize: 17,
fontWeight: "600",
paddingBottom: 20
},
similarContainer: {
width: 90,
marginHorizontal: 7
},
similarPoster: {
height: 130,
width: 90,
borderRadius: 8
},
similarTitleFilm: {
color: "#DADADA",
paddingTop: 5,
fontWeight: "300"
},
reviewSection: {
paddingTop: 30
},
reviewTitle: {
color: "#2998FD",
paddingLeft: 35,
fontSize: 17,
fontWeight: "600",
paddingBottom: 10
},
reviewContainer: {
marginHorizontal: 7,
width: 300,
padding: 20,
backgroundColor: "#09090F",
marginVertical: 10,
borderRadius: 14,
borderWidth: 0.8,
borderColor: "rgba(223,223,223,0.14)"
},
reviewInfo: {
flexDirection: "row",
paddingBottom: 20
},
imageProfile: {
height: 50,
width: 50,
borderRadius: 100
},
infoContainer: {
paddingLeft: 10,
flexDirection: "row",
justifyContent: "space-between",
width: "80%",
alignItems: "center"
},
pseudo: {
color: "white",
paddingTop: 5,
fontWeight: "700",
fontSize: 16
},
date: {
color: "grey",
paddingTop: 5,
fontWeight: "500",
fontSize: 14
},
message: {
color: "#B3B3B3",
paddingTop: 5,
fontWeight: "400"
},
creditContainer: {
width: 90,
marginHorizontal: 7,
alignItems: "center"
},
bubble: {
justifyContent: "center"
},
photo: {
height: 90,
width: 90,
borderRadius: 200,
borderWidth: 3,
borderColor: "rgba(255,255,255,0.8)"
},
popularityDot: {
backgroundColor: "white",
borderRadius: 20,
padding: 2,
paddingHorizontal: 5,
justifyContent: "center",
alignItems: "center",
position: "absolute",
bottom: 0,
right: 0,
flexDirection: "row"
},
popularityLabel: {
color: "black",
fontWeight: "500",
paddingRight: 4
},
creditName: {
color: "#DADADA",
paddingTop: 5,
fontWeight: "300"
}
});
const getSimilarMusics = async () => {
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"),
] ;
setSimilarMusics(tmpMusic);
}
useEffect(() => {
getSimilarMusics();
}, []);
////////////////////////////////////////////////
const {width, height} = useWindowDimensions();
const [currentspot, setCurrentspot] = useState(item);
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 :item.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: item.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]);
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 animationState = new Value(State.UNDETERMINED);
const playMusic = async (id: string) => {
try {
const service = new SpotifyService("BQC4k_OPQXENwmm2S8qLm9whlJT9IjeKsuG6kJNyVCSd88b0L-zOY84VqwvQxFsc9G3GvtPyUMezwxi8BBBloitzbhWX5tmTKTaLsJosGTnb7xivwNhRv0-LnNYbZWB24ZGAg0xPmDLn0yYmYlo7M_SMK5cCZdYQcZNXAuMYaI18GVXKoICBaKfCn4GcqBiRRgXyCVQnNGU4") ;
console.log("=====================================================)))))))))))))))"+id+"================================")
await service.playMusic(id);
}catch(error){}
}
return (
<View style={styles.body}>
<View style={styles.backgroundSection}>
<Image
style={styles.back_drop}
source={{
uri: item.image,
}}
></Image>
<LinearGradient
// Background Linear Gradient
colors={['rgba(0,0,0,0.8)', 'transparent']}
/>
<LinearGradient style={styles.gradientFade}
// Button Linear Gradient
colors={['rgba(14,14,14,0)', 'rgba(14,14,14,0.7)', 'rgba(14,14,14,1)', 'rgba(14,14,14,1)']}>
</LinearGradient>
</View>
<View style={styles.background1}>
<TouchableOpacity onPress={() => navigation.goBack()} style={{zIndex: 100}}>
<Ionicons name="ios-arrow-back" size={30} color="white" style={styles.backButton}/>
</TouchableOpacity>
<ScrollView style={styles.list} showsVerticalScrollIndicator={false} scrollEventThrottle={4}
>
<View style={styles.section1}>
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
<View>
<SharedElement id ={item.id}>
<Animated.Image
source={{
uri:currentspot.image ,
}}
style={[
{
width: 370,
height: 370,
borderRadius : 24,
resizeMode: 'stretch',
},styleAniamatedImage
]}
/>
</SharedElement>
<Button title="Play Track On Device"
onPress={() => {
playMusic(currentspot.id)
// 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>
</View>
</View>
{similarMusics.length !== 0 && (
<HorizontalFlatList renderCell={littleCard} title={'Simillar Music'} data={similarMusics}>
</HorizontalFlatList>
)}
</ScrollView>
</View>
</View>
)
}

@ -48,7 +48,6 @@ export default class SpotifyService implements IspotifyService {
public async playMusic(idMusic : string): Promise<void>{
var requestData :string = '/me/player/play';
const fetchOptions: FetchOptions = {
method: 'PUT',
body: {
@ -57,6 +56,7 @@ export default class SpotifyService implements IspotifyService {
}
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
console.log(respMusic.data);
// need to handle when
// if (respMusic.status != 200) {
// if (respMusic.status == 400 && respMusic.data.message =='need to use Spotify premium'){
@ -71,6 +71,91 @@ export default class SpotifyService implements IspotifyService {
return ;
}
public async searchMusic(text : string): Promise<Music[]>{
var requestData :string = '/search';
const fetchOptions: FetchOptions = {
params: {
q: text,
type: 'track'
}
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
if (respMusic.status != 200) {
}
const tracksData = respMusic?.data?.tracks?.items;
if (!tracksData || !Array.isArray(tracksData)) {
return [];
}
const tracks = tracksData.map((trackData: any) => {
// const { id, name, artists, album } = trackData;
return MusicFactory.mapFromSpotifyTrack(trackData)
// const artistNames = artists.map((artist: any) => artist.name).join(', ');
// const linkCover = album?.images[0]?.url || '';
// return new Music(id, name, artistNames, linkCover);
});
return tracks;
}
// tempo version
public async getMusicMoreDetails(idMusic : string): Promise<string>{
var requestData :string = '/audio-features/' + idMusic;
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined,this.token);
if (respMusic.status != 200) {
}
return respMusic.data.audio_features.tempo;
}
public async getRelatedArtist(idArtist : string): Promise<string>{
var requestData :string = '/artists/' + idArtist + '/related-artists';
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined,this.token);
if (respMusic.status != 200) {
}
return respMusic.data.audio_features.tempo;
}
public async getArtistTopTracks(idArtist : string): Promise<string>{
var requestData :string = '/artists/' + idArtist + '/top-tracks';
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined,this.token);
if (respMusic.status != 200) {
}
return respMusic.data.audio_features.tempo;
}
public async addItemToPlayList(playlistId : string, idMusic : string): Promise<void>{
var requestData :string = '/playlists/' + playlistId + '/tracks';
const fetchOptions: FetchOptions = {
method: 'POST',
body: {
uris: [`spotify:track:${idMusic}`]
}
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
console.log(respMusic.data);
return ;
}
public async createPlayList(userId : string,name : string,description : string): Promise<void>{
var requestData :string = '/users/' + encodeURIComponent(userId) + '/playlists';
const fetchOptions: FetchOptions = {
method: 'POST',
body: {
"public": false,
"name": name || "New Flad Playlist",
"description": description,
}
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
console.log(respMusic.data);
return ;
}
async getSpotifyCredentials() {
const res = await axios.get(this.API_URL)
// then verify error

@ -20,6 +20,7 @@ export class RequestHandler{
}
public async spotifyFetch(url: string, options: FetchOptions = {}, token: string) {
console.log(options+ "sds=============");
const resp = await axios({
url: `https://api.spotify.com/${this.version}${url}`,
method: options.method || 'GET',
@ -31,7 +32,7 @@ export class RequestHandler{
},
data: options.body
});
// console.log(resp);
console.log(resp);
return resp;
// if (
// // @ts-ignore

Loading…
Cancel
Save