redux_part_4 #12

Merged
emre.kartal merged 4 commits from redux_part_4 into master 2 years ago

@ -2,6 +2,9 @@ import { StyleSheet } from 'react-native';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import store from './redux/store'; import store from './redux/store';
import AuthNavigation from './navigation/AuthNavigation'; import AuthNavigation from './navigation/AuthNavigation';
import * as SplashScreen from 'expo-splash-screen';
SplashScreen.preventAutoHideAsync();
export default function App() { export default function App() {

@ -0,0 +1,12 @@
export default class Artist {
private id : string;
private name : string;
private url : string; // Image.source
constructor(id : string, name : string, url : string){
this.id = id;
this.name = name;
this.url = url;
}
}

@ -11,4 +11,14 @@ export default class MusicFactory {
); );
return music; return music;
} }
static mapFromSpotifyTrackSmpified(jsonMusic :any ): Music {
const music = new Music(
jsonMusic.id,
jsonMusic.name,
"",
jsonMusic.album.images[0].url,
jsonMusic.preview_url
);
return music;
}
} }

@ -39,7 +39,7 @@
[ [
"expo-location", "expo-location",
{ {
"locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location." "locationAlwaysAndWhenInUsePermission": "Allow Flad to use your location."
} }
] ]
] ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 B

@ -3,6 +3,8 @@ const Icons = {
discovery: require('./icon_discovery.png'), discovery: require('./icon_discovery.png'),
like: require('./icon_like.png'), like: require('./icon_like.png'),
dislike: require('./icon_dislike.png'), dislike: require('./icon_dislike.png'),
bookmark : require('./icon_bookmark.svg'),
share : require('./Vector.png'),
// riveLike : require('./light_like.riv'), // riveLike : require('./light_like.riv'),
} }

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.6666 3.33219L9.71998 4.27886L8.65998 3.21886V10.6655H7.33998V3.21886L6.27998 4.27886L5.33332 3.33219L7.99998 0.665527L10.6666 3.33219ZM13.3333 6.66553V13.9989C13.3333 14.7322 12.7333 15.3322 12 15.3322H3.99998C3.25998 15.3322 2.66665 14.7322 2.66665 13.9989V6.66553C2.66665 5.92553 3.25998 5.33219 3.99998 5.33219H5.99998V6.66553H3.99998V13.9989H12V6.66553H9.99998V5.33219H12C12.7333 5.33219 13.3333 5.92553 13.3333 6.66553Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 557 B

@ -0,0 +1,50 @@
import { useCallback, useState } from 'react';
import { View, StyleSheet ,Text,Image, Pressable, Linking, Alert} from 'react-native'
interface ArtistChipProps {
backgroundColor : string;
artist : Artist;
}
const ArtistChip = ({artist} : ArtistChipProps) => {
const handlePress = useCallback(async () => {
// Checking if the link is supported for links with custom URL scheme.
const supported = await Linking.canOpenURL(artist.url);
if (supported) {
// Opening the link with some app, if the URL scheme is "http" the web link should be opened
// by some browser in the mobile
await Linking.openURL(artist.url);
} else {
Alert.alert(`Don't know how to open this URL: ${artist.url}`);
}
}, [artist.url]);
return (
<View>
<Pressable onPress={handlePress}>
<View>
<Image
source={{
uri: artist.image,
}}
></Image>
</View>
<View>
<Text>ii</Text>
</View>
</Pressable>
</View>
);
};
const styles = StyleSheet.create({
input : {
justifyContent : 'center',
alignItems : 'center',
placeholder : "placeholde"
},
})
export default HalfCirlce;

@ -78,6 +78,5 @@ export const ArtistLayout = () => {
container: { container: {
flexDirection: "row", flexDirection: "row",
flexWrap: "wrap", flexWrap: "wrap",
}, },
}); });

@ -12,15 +12,16 @@ import { Feather as Icon } from "@expo/vector-icons";
import Music from "../Model/Music"; import Music from "../Model/Music";
import { State, TapGestureHandler } from "react-native-gesture-handler"; import { State, TapGestureHandler } from "react-native-gesture-handler";
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { RenderCellProps } from "./littleCard";
interface HorizontalFlatListProps { interface HorizontalFlatListProps {
// React.ReactNode; // React.ReactNode;
renderCell: (image: string, titre : string) => React.ReactElement children:(props: RenderCellProps) => React.ReactElement
title : string; title : string;
data : any[]; data : any[];
} }
export const HorizontalFlatList = ({ title, data, renderCell}: HorizontalFlatListProps) => { export const HorizontalFlatList = ({ title, data, children : RenderCell }: HorizontalFlatListProps) => {
return ( return (
@ -31,22 +32,19 @@ export const HorizontalFlatList = ({ title, data, renderCell}: HorizontalFlatLis
data={data} data={data}
horizontal={true} horizontal={true}
keyExtractor={item => item.id} keyExtractor={item => item.id}
renderItem={({item}) =>{ renderItem={({ item }) => RenderCell(item)}/></View>
return renderCell(item.image, image.titre);
}}
/></View>
); );
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
similarSection: { similarSection: {
paddingTop: 30 paddingTop: 16
}, },
similarTitle: { similarTitle: {
color: "#2998FD", color: "#FFF",
paddingLeft: 35, paddingLeft: 8,
fontSize: 17, fontSize: 24,
fontWeight: "600", fontWeight: "600",
paddingBottom: 20 paddingBottom: 16
} }
}); });

@ -1,19 +1,23 @@
import {TouchableOpacity, ScrollView, View, Text, StyleSheet, Image, SafeAreaView, FlatList, Animated} from 'react-native'; import {TouchableOpacity, ScrollView, View, Text, StyleSheet, Image, SafeAreaView, FlatList, Animated} from 'react-native';
export interface RenderCellProps {
export default function littleCard ({image,titre}){ image: string;
title: string;
}
export const LittleCard = (props : RenderCellProps)=>{
console.log('==============='+ props.image + props.title+ '==ok============');
return ( return (
<View style={styles.similarContainer}> <View style={styles.similarContainer}>
<Image source={{uri: image}} style={styles.similarPoster}></Image> <Image source={{uri: props.image}} style={styles.similarPoster}></Image>
<Text numberOfLines={2} style={styles.similarTitleFilm}>{titre} <Text numberOfLines={2} style={styles.similarTitleFilm}>{props.title}
</Text> </Text>
</View> </View>
) )
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
similarContainer: { similarContainer: {
width: 90,
marginHorizontal: 7 marginHorizontal: 7
}, },
similarTitleFilm: { similarTitleFilm: {
@ -22,8 +26,8 @@ const styles = StyleSheet.create({
fontWeight: "300" fontWeight: "300"
}, },
similarPoster: { similarPoster: {
height: 130, height: 160,
width: 90, width: 160,
borderRadius: 8 borderRadius: 16
} }
}) })

@ -82,5 +82,24 @@ export const spotArray2: Spot[] = [
"Harry Styles", "Harry Styles",
"https://i.scdn.co/image/ab67616d0000b2738900d48677696015bf325b8b", "https://i.scdn.co/image/ab67616d0000b2738900d48677696015bf325b8b",
"https://p.scdn.co/mp3-preview/4fff3f8d76a422f42cea39f001836a3d54937fc4?cid=774b29d4f13844c495f206cafdad9c86") "https://p.scdn.co/mp3-preview/4fff3f8d76a422f42cea39f001836a3d54937fc4?cid=774b29d4f13844c495f206cafdad9c86")
),
new Spot("6", new Music("30d0q6kt1BIfwAQUCAfxVQ",
"Calme toi",
"Kerchack",
"https://i.scdn.co/image/ab67616d0000b273b4f73fb5c5ea299c7ebfbf60",
"https://p.scdn.co/mp3-preview/5de1103b9528c1e47e03d32b0aa5dbfe797191a2?cid=774b29d4f13844c495f206cafdad9c86")
),
new Spot("7", new Music("7IXQrRgmHxWYWitSlyFY7z",
"Peur (feat. Ziak)",
"Ziak",
"https://i.scdn.co/image/ab67616d0000b273b533a3a5625bc6ce1be56a2e",
"https://p.scdn.co/mp3-preview/2c613f31b11375980aba80a5b535bf87ddb6211b?cid=774b29d4f13844c495f206cafdad9c86")
),
new Spot("8", new Music("7wBoSW48q4ZFe8qSdozqqi",
"Blue",
"Kerchack",
"https://i.scdn.co/image/ab67616d0000b273cc4e66af40292c9d92146909",
"https://p.scdn.co/mp3-preview/401b51374dd3f2a15466a0b415a9ac7d2114a54b?cid=774b29d4f13844c495f206cafdad9c86")
) )
]; ];

@ -4,56 +4,128 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
import StartNavigation from './StartNavigation'; import StartNavigation from './StartNavigation';
import { Provider, useDispatch, useSelector } from 'react-redux'; import { Provider, useDispatch, useSelector } from 'react-redux';
import store from '../redux/store'; import store from '../redux/store';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect, useState } from 'react';
import * as SplashScreen from 'expo-splash-screen'; import * as SplashScreen from 'expo-splash-screen';
import { View } from 'react-native'; import { View } from 'react-native';
import { getRefreshToken } from '../redux/thunk/authThunk'; import { getRefreshToken } from '../redux/thunk/authThunk';
import * as Location from 'expo-location';
SplashScreen.preventAutoHideAsync(); // const LOCATION_TASK_NAME = 'flad-background-location-task';
export default function AuthNavigation() { export default function AuthNavigation() {
//@ts-ignore //@ts-ignore
const appIsReady : boolean = useSelector(state => state.userReducer.loading); const tokenProcesed : boolean = useSelector(state => state.userReducer.loading);
//@ts-ignore //@ts-ignore
const isLogin : boolean = useSelector(state => state.userReducer.isLogedIn); const isLogin : boolean = useSelector(state => state.userReducer.isLogedIn);
// const userToken : string = useSelector(state => state.userReducer.userFladToken); // const userToken : string = useSelector(state => state.userReducer.userFladToken);
const [appIsReady, setAppIsReady] = useState(false);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [location, setLocation] = useState({});
const [errorMsg, setErrorMsg] = useState('');
// // seems background task but not optimized
// TaskManager.defineTask(LOCATION_TASK_NAME, async ({ data, error }) => {
// if (error) {
// console.log(error);
// return;
// }
// if (data) {
// const { locations } = data;
// // send location updates to server
// console.log(locations);
// }
// });
// const startLocationUpdates = async () => {
// try {
// await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
// accuracy: Location.Accuracy.Balanced,
// timeInterval: 5000, // send location updates every 5 seconds
// foregroundService: {
// notificationTitle: 'Location tracking',
// notificationBody: 'Location tracking is active.',
// },
// });
// } catch (error) {
// console.log(error);
// }
// };
// useEffect(() => {
// startLocationUpdates();
// return () => {
// Location.stopLocationUpdatesAsync(LOCATION_TASK_NAME);
// };
// }, []);
useEffect(() => { useEffect(() => {
async function prepare() { async function prepare() {
console.log(appIsReady, "1 AuthNav")
//@ts-ignore //@ts-ignore
await dispatch(getRefreshToken()) await dispatch(getRefreshToken())
await SplashScreen.hideAsync(); if (tokenProcesed && appIsReady ) {
await SplashScreen.hideAsync();
} // await SplashScreen.hideAsync();
} }
prepare(); prepare();
}, [dispatch]); }, [appIsReady,tokenProcesed]);
const onStackRootView = useCallback(async () => { // const onStackRootView = useCallback(async () => {
if (appIsReady) {
await SplashScreen.hideAsync();
}
}, [appIsReady]);
if (appIsReady == false) { // }, [appIsReady]);
console.log(appIsReady, "T9 AuthNav") // useEffect(() => {
// const sendLocationUpdate = async () => {
// try {
// let { status } = await Location.requestForegroundPermissionsAsync();
// console.log('Sending location update ================================###############');
// if (status === 'granted') {
// console.log(appIsReady)
// if (true) {// should app is ready
// // see deeper the documentation
// // const [status, requestPermission] = Location.useBackgroundPermissions();
// const locationresp = await Location.getCurrentPositionAsync({});
// setLocation(locationresp);
// // send location to server
// console.log(locationresp);
// if(locationresp !=location ){
// }
// console.log(location);
// }
// }
// else{
// console.log(`Sending location update with error ${status} ================================###############`);
// setErrorMsg('Permission to access location was denied');
// return;
// }
// } catch (error) {
// console.log(error);
// }
// };
// const interval = setInterval(sendLocationUpdate, 5000); // send location updates every 5 seconds
// return () => {
// clearInterval(interval);
// };
// }, []);
if (tokenProcesed == false) {
return null; return null;
} }
console.log(appIsReady, "k9 AuthNav")
// console.log(userToken, "k9 AuthNav") // console.log(userToken, "k9 AuthNav")
return ( return (
<> <>
{isLogin ? ( {isLogin ? (
/* {userToken != null ? ( */ /* {userToken != null ? ( */
<SafeAreaProvider> // should set the reference to the function in Navigation to realy perform an on ready
// test purpose
<SafeAreaProvider onLayout={()=>setAppIsReady(true)}>
<Navigation/> <Navigation/>
</SafeAreaProvider> </SafeAreaProvider>
) : ) :
<SafeAreaProvider > <SafeAreaProvider onLayout={()=>setAppIsReady(true)}>
<StartNavigation/> <StartNavigation />
</SafeAreaProvider> </SafeAreaProvider>
} }
</> </>

@ -1,5 +1,6 @@
import Music from "../../Model/Music"; import Music from "../../Model/Music";
import { Spot } from "../../Model/Spot"; import { Spot } from "../../Model/Spot";
import { spotifyTypes } from "../types/spotifyTypes";
import {spotTypes} from "../types/spotTypes"; import {spotTypes} from "../types/spotTypes";
export const setSpotList = (spotList: Spot[]) => { export const setSpotList = (spotList: Spot[]) => {
@ -11,7 +12,7 @@ export const setSpotList = (spotList: Spot[]) => {
export const setUserCurrentMusic = (currentMusic: Music) => { export const setUserCurrentMusic = (currentMusic: Music) => {
return { return {
type: spotTypes.FETCH_SPOT, type: spotifyTypes.GET_USER_CURRENT_MUSIC,
playload: currentMusic, playload: currentMusic,
}; };
} }

@ -1,3 +1,4 @@
import { User } from "../../Model/User";
import { userTypes } from "../types/userTypes"; import { userTypes } from "../types/userTypes";
@ -31,12 +32,12 @@ export const restoreToken = (token : string) => {
playload : token playload : token
}; };
} }
// export const UserLogin = (username: string, password: string) => { export const userSignUp = (user : User) => {
// return { return {
// type: userTypes.LOGIN, type: userTypes.LOGIN,
// playload : username, password playload : user
// }; };
// } }
export const UserLogout = () => { export const UserLogout = () => {
return { return {

@ -5,24 +5,18 @@ import { favoritesTypes } from "../types/favoritesTypes";
import { spotifyTypes } from "../types/spotifyTypes"; import { spotifyTypes } from "../types/spotifyTypes";
import { spotTypes } from "../types/spotTypes"; import { spotTypes } from "../types/spotTypes";
let 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"),
// 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("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("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"), 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 = { const initialState = {
spot: [] as Spot[], spot: [] as Spot[],
favoriteMusic: tmpMusic, favoriteMusic: tmpMusic,
userCurrentMusic : null userCurrentMusic : null
} }
const appReducer = (state = initialState, action : any) => { const appReducer = (state = initialState, action : any) => {
switch (action.type) { switch (action.type) {
case favoritesTypes.GET_FAVORITE_MUSICS: case favoritesTypes.GET_FAVORITE_MUSICS:
return {...state, favoriteMusic: action.playload}; return {...state, favoriteMusic: action.playload};
case favoritesTypes.ADD_FAVORITE_MUSICS: case favoritesTypes.ADD_FAVORITE_MUSICS:
@ -37,7 +31,7 @@ const initialState = {
return {...state, userCurrentMusic: action.payload}; return {...state, userCurrentMusic: action.payload};
default: default:
return state; return state;
}
} }
}
export default appReducer export default appReducer

@ -5,7 +5,7 @@ String getApiRedirectUrl() => _api.identification.redirectUri;
String getIdSpotify() => _currentUser.idSpotify; String getIdSpotify() => _currentUser.idSpotify;
String getIdDafl() => _currentUser.idDafl; String getIdFlad() => _currentUser.idFlad;
case getCompleteMusic case getCompleteMusic

@ -3,7 +3,7 @@ import { userTypes } from "../types/userTypes";
const initialState = { const initialState = {
loading: false, loading: false,
user: User, // for user object user: User, // for user object
userFladToken: null, // for storing the JWT userFladToken: "", // for storing the JWT
userSpotifyToken : null, userSpotifyToken : null,
error: null, error: null,
isLogedIn: false, isLogedIn: false,
@ -14,11 +14,13 @@ const initialState = {
// just for the navigation and speciafly use // just for the navigation and speciafly use
// and // and
case userTypes.RESTORE_TOKEN: case userTypes.RESTORE_TOKEN:
const resp = (action.playload == "" ? false : true)
console.log(resp, "si il ya le tokennen ou passssssssssss")
return { return {
...state, ...state,
userFladToken : action.playload, userFladToken : action.playload,
loading: true, loading: true,
// isLogedIn: true, isLogedIn: resp,
}; };
case userTypes.LOGIN: case userTypes.LOGIN:
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3"); console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
@ -39,12 +41,15 @@ const initialState = {
user :action.playload, user :action.playload,
isLogedIn: true isLogedIn: true
}; };
// case USER_SIGNUP:
// return {...state, nounours: action.payload};
case userTypes.USER_LOGOUT: case userTypes.USER_LOGOUT:
return {...state, return {...state,
user :null, user :null,
isLogedIn: false } isLogedIn: false }
case userTypes.SAVE_SPOTIFY:
return {
...state,
userSpotifyToken : action.playload,
};
default: default:
return state; return state;
} }

@ -4,7 +4,7 @@ import axios from "axios";
import { json } from "express"; import { json } from "express";
import { useEffect } from "react"; import { useEffect } from "react";
import { API_URL } from "../../fladConfig"; import { API_URL } from "../../fladConfig";
import { Credentials, CredentialsRegister, restoreToken, setLoginState } from "../actions/userActions"; import { Credentials, CredentialsRegister, restoreToken, setLoginState, userSignUp } from "../actions/userActions";
import * as SecureStore from 'expo-secure-store'; import * as SecureStore from 'expo-secure-store';
import { User } from "../../Model/User"; import { User } from "../../Model/User";
import { UserFactory } from "../../Model/factory/UserFactory"; import { UserFactory } from "../../Model/factory/UserFactory";
@ -38,7 +38,7 @@ export const registerUser = ( resgisterCredential : CredentialsRegister) => {
"https://flad-api-production.up.railway.app/api/users", "https://flad-api-production.up.railway.app/api/users",
{headers} {headers}
) )
dispatch(setLoginState( UserFactory.JsonToModel(user.data) )); // our action is called here dispatch(userSignUp( UserFactory.JsonToModel(user.data) )); // our action is called here
// console.log(user.data); // console.log(user.data);
// dispatch(setLoginState(user.data) ); // our action is called here // dispatch(setLoginState(user.data) ); // our action is called here
} else { } else {
@ -108,15 +108,13 @@ export const getRefreshToken = () => {
//@ts-ignore //@ts-ignore
return async dispatch => { return async dispatch => {
try { try {
let userToken : string | null = await SecureStore.getItemAsync(key); let userToken : string | null = await SecureStore.getItemAsync('key');
console.log("==========key ==================");
console.log(userToken);
console.log("==========key ==================");
if (userToken) { if (userToken) {
console.log("==========key2 =================="); console.log("==========key2 ==================");
console.log(userToken); console.log(userToken);
console.log("==========key =================="); console.log("==========key ==================");
console.log("==========on devrais être laaaa ==================");
dispatch(restoreToken(userToken) ); dispatch(restoreToken(userToken) );

@ -2,6 +2,7 @@
export const userTypes = { export const userTypes = {
LOGIN: 'LOGIN', LOGIN: 'LOGIN',
SIGNUP: 'SIGNUP', SIGNUP: 'SIGNUP',
SAVE_SPOTIFY :'SAVE_SPOTIFY',
UPDATE_USER: 'UPDATE_USER', UPDATE_USER: 'UPDATE_USER',
UPDATE_PROFILE_PICTURE: 'UPDATE_PROFILE_PICTURE', UPDATE_PROFILE_PICTURE: 'UPDATE_PROFILE_PICTURE',
USER_LOGOUT : 'USER_LOGOUT', USER_LOGOUT : 'USER_LOGOUT',

@ -1,5 +1,5 @@
import { NavigationProp, RouteProp } from "@react-navigation/native"; import { NavigationProp, RouteProp, useNavigation } from "@react-navigation/native";
import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity } from "react-native"; import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity, ScrollView, Pressable } from "react-native";
import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, useDerivedValue, useSharedValue, Value, withSpring, withTiming } from "react-native-reanimated"; import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, useDerivedValue, useSharedValue, Value, withSpring, withTiming } from "react-native-reanimated";
import { BlurView } from 'expo-blur'; import { BlurView } from 'expo-blur';
import qs from "qs"; import qs from "qs";
@ -14,215 +14,143 @@ import Music from "../Model/Music";
import SpotifyService from "../services/spotify/spotify.service"; import SpotifyService from "../services/spotify/spotify.service";
import { SharedElement } from "react-navigation-shared-element"; import { SharedElement } from "react-navigation-shared-element";
import { SafeAreaView } from "react-native-safe-area-context"; import { SafeAreaView } from "react-native-safe-area-context";
import { LinearGradient } from "expo-linear-gradient";
import Icons from "../assets/icons/icons/icon";
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import { Feather as Icon } from "@expo/vector-icons";
import { HorizontalFlatList } from "../components/HorizontalFlatList";
import { LittleCard } from "../components/littleCard";
import normalize from "../components/Normalize";
import { Circle } from "react-native-svg";
import { AntDesign } from '@expo/vector-icons';
import * as SecureStore from 'expo-secure-store';
const halfPi = Math.PI/2; const halfPi = Math.PI/2;
//@ts-ignore //@ts-ignore
const MusicDetail = ({ route }) => { const MusicDetail = ({ route }) => {
const music : Music = route.params.music; const music : Music = route.params.music;
const [currentspot, setCurrentspot] = useState(music); const [currentspot, setCurrentSpot] = useState(music);
const [sound, setSound] = useState(null); const [simularMusic, setSimularMusic] = useState<Music[]>([]);
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
const loader = useSharedValue(0); const [sound, setSound] = useState(null);
useEffect(() => {
loader.value = isPlaying ? 1 : 0
}, [isPlaying,loader ]);
const transition = useDerivedValue(()=>{ const navigator = useNavigation();
return withTiming(loader.value, {duration : 1000})
}
)
const [testtoken, setTesttoken] = useState('')
// const styleAniamatedButton = useAnimatedStyle(() => { const sheet = async () => {
// const verticalAxis =interpolate( SecureStore.getItemAsync('MySecureAuthStateKey').then(result => { setTesttoken(result)});
// transition.value,
// [0,1],
// [circumference, 0]
// )
// return { }
// top : withSpring( verticalAxis),
// left : withSpring(horizontalAxis),
// };
// })
useEffect(() => {
sheet();
getSimilarTrack();
}, [testtoken]);
const playTrackPreview = async () => { // const getSimilarTrack = async () => {
console.log("==============================================================================================================="); // const service = new SpotifyService(testtoken);
// const simularMusic = await service.getSimilarTrack(currentspot.id, 5, 'FR');
// console.log("suggesstd", simularMusic)
// setSimularMusic(simularMusic);
console.log('get in Sound'); // }
const getSimilarTrack = async () => {
try {
const service = new SpotifyService(testtoken);
const simularMusic = await service.getSimilarTrack(currentspot.id, 5, 'FR');
console.log("suggesstd", simularMusic);
setSimularMusic(simularMusic);
} catch (error) {
console.error('Error ================ in getSimilarTrack', error);
// Handle the error here.
}
}
const { sound } = await Audio.Sound.createAsync({uri :music.trackPreviewUrl}); const handlePlaySound = async () => {
//@ts-ignore if (sound === null) {
setSound(sound); const { sound: newSound } = await Audio.Sound.createAsync(
console.log('Playing Sound'); { uri: music.trackPreviewUrl },
await sound.playAsync(); { shouldPlay: true }
setIsPlaying(true); );
setSound(newSound);
setIsPlaying(true);
// const soundObject = new Audio.Sound();
// try { } else {
// await soundObject.loadAsync({ uri: trackPreviewUrl }); setIsPlaying(true);
// await soundObject.playAsync(); //@ts-ignore
// setIsPlaying(true); await sound.playAsync();
// } catch (error) { }
// console.log('Error loading sound:', error);
// }
}; };
const handlePlaySound = async () => { const handleStopSound = async () => {
if (sound === null) { if (sound !== null) {
const { sound: newSound } = await Audio.Sound.createAsync( setIsPlaying(false);
{ 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 //@ts-ignore
sound.unloadAsync(); await sound.stopAsync();
} }
: undefined; else{
}, [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){}
} }
};
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),
};
})
return ( return (
<SafeAreaView style={styles.mainSafeArea}> <View style={styles.body}>
<View style={styles.backgroundSection}>
<Image
blurRadius={133}
style={styles.back_drop}
source={{
uri: currentspot.image,
}}
></Image>
{/* <LinearGradient
// Background Linear Gradient
colors={['rgba(0,0,0,0.8)', 'transparent']}
/> */}
<LinearGradient style={styles.gradientFade}
// Button Linear Gradient
colors={['rgba(56,56,56,0)', 'rgba(14,14,14,1)']}>
</LinearGradient>
</View>
<View style={styles.background1}>
<ScrollView style={styles.list} showsVerticalScrollIndicator={false} scrollEventThrottle={4}>
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}> <View style={styles.section1}>
<View style={{ flex: 1,justifyContent : 'flex-start', alignItems : 'center' }}>
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */} {/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
<View> <View>
@ -233,53 +161,66 @@ const MusicDetail = ({ route }) => {
style={[ style={[
{ {
width: 370, // width: 370,
height: 370, // width: 400,
width: 392,
height: 392,
borderRadius : 24, borderRadius : 24,
resizeMode: 'stretch', resizeMode: 'stretch',
},styleAniamatedImage },styleAniamatedImage
]} ]}
/> />
<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,
}}
onPressOut={handleStopSound}
onLongPress={handlePlaySound}
delayLongPress={1000}>
<Text style={ {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',}}>
{isPlaying ? 'Playing...' : 'Play'}
</Text>
</TouchableOpacity>
</Animated.View>
{/* </TapGestureHandler> */}
{/* Button */}
{/* </SharedElement> */}
</View> </View>
</SafeAreaView> <View style={{marginTop : 45,flex: 1, flexDirection : 'row', }}>
<View>
</View>
<TouchableOpacity activeOpacity={0.5} style={{
backgroundColor: '#F80404',
borderRadius: 100,
padding: normalize(23)
}}>
<View style={{flex: 1, justifyContent : 'center', alignContent : 'center'}}>
<FontAwesome name="play" size={32} color="#FFFF" ></FontAwesome>
</View>
</TouchableOpacity>
</View>
</View>
</View>
<View style ={{flex: 1, flexDirection : 'row', justifyContent :'space-evenly', width : '100%' }}>
<TouchableOpacity activeOpacity={0.6} style={{ flexDirection : 'row', justifyContent : 'space-evenly',alignItems: 'center', width: 180,
height: 64, borderRadius: 8, opacity: 0.86 ,backgroundColor: '#0B0606', }}>
<FontAwesome name="bookmark" size={24} color="#FFFF" ></FontAwesome>
<Text style={{ fontSize: normalize(16), fontWeight:"700", color : '#FFFFFF' }}>Dans ma collection</Text>
</TouchableOpacity>
<TouchableOpacity activeOpacity={0.6} style={{ flexDirection : 'row', justifyContent : 'space-evenly',alignItems: 'center', width: 180,
height: 64, borderRadius: 8, opacity: 0.86 ,backgroundColor: '#0B0606', }}>
<Icon name="share" size={24} color="#FFFF"></Icon>
{/* <FontAwesome name="bookmark" size={24} color="#FF0000" ></FontAwesome> */}
<Text style={{ fontSize: normalize(16), fontWeight:"700", color : '#FFFFFF' }}>Partagedr cette music</Text>
</TouchableOpacity>
{/* <Pressable style={{flexDirection : 'row', justifyContent : 'space-between', alignItems: 'center', height: "10%" , borderRadius: 8, opacity: 84 ,backgroundColor: 'rgba(29, 16, 16, 0.84)' }}>
<FontAwesome name="bookmark" size={16} color="#FF0000" ></FontAwesome>
<Text style={{ fontSize: 16, fontWeight:"700",lineHeight:12, color : '#FFFFFF' }}>Dans ma collection 2</Text>
</Pressable> */}
</View>
{simularMusic.length !== 0 && (
<HorizontalFlatList title={'Similar'} data={simularMusic}>
{(props) => (
<Pressable onLongPress={() => { navigator.navigate("MusicDetail", {"music": props}) }} >
<LittleCard image={props.image} title ={props.title}/>
</Pressable>
)}
</HorizontalFlatList>
)}
</ScrollView>
</View>
</View>
); );
}; };
@ -290,5 +231,31 @@ const styles = StyleSheet.create ({
mainSafeArea: { mainSafeArea: {
flex: 1, flex: 1,
backgroundColor: "#141414", backgroundColor: "#141414",
},
body: {
backgroundColor: "#0E0E0E"
},
backgroundSection: {
height: "100%",
width: "100%",
position: "absolute"
},
back_drop: {
height: "160%",
width: '430%',
position: "absolute",
},
gradientFade: {
height: "100%",
},
background1: {
height: '100%',
width: '100%',
},
list: {
height: "100%"
},
section1: {
paddingHorizontal: 25
} }
}) })

@ -10,6 +10,7 @@ import { registerUser } from '../redux/thunk/authThunk';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { CredentialsRegister } from '../redux/actions/userActions'; import { CredentialsRegister } from '../redux/actions/userActions';
import { Buffer } from 'buffer'; import { Buffer } from 'buffer';
import SpotifyService from '../services/spotify/spotify.service';
// @ts-ignore // @ts-ignore
const DismissKeyboard = ({ children }) => ( const DismissKeyboard = ({ children }) => (
@ -109,6 +110,42 @@ const scopes = scopesArr.join(' ');
console.error(err) console.error(err)
} }
} }
const getAuthorizationCode2 = async () => {
try {
const result = await AuthSession.startAsync({
authUrl:'https://flad-api-production.up.railway.app/api/spotify/exchange'
})
console.log("=================grant code ==============<");
console.log(result);
console.log("=================grant code ==============<");
return result.params.code;
} catch (err) {
console.error(err)
}
}
const getTokens2 = async () => {
try {
const authorizationCode = await getAuthorizationCode2() //we wrote this function above
console.log(authorizationCode, "shhhhhhhhhhhhhheeeeeeeeeeeeeeeetttttttttttt");
const response = await fetch('https://flad-api-production.up.railway.app/api/spotify/callback');
const responseJson = await response.json();
console.log(responseJson, "okkkkkkkkkkkkkkk") ;
// destructure the response and rename the properties to be in camelCase to satisfy my linter ;)
const {
access_token: accessToken,
refresh_token: refreshToken,
expires_in: expiresIn,
} = responseJson;
await setSpotifyToken(accessToken);
console.log(spotifyToken);
} catch (err) {
console.error(err);
}
}
const getTokens = async () => { const getTokens = async () => {
try { try {
const authorizationCode = await getAuthorizationCode() //we wrote this function above const authorizationCode = await getAuthorizationCode() //we wrote this function above
@ -130,12 +167,55 @@ const scopes = scopesArr.join(' ');
expires_in: expiresIn, expires_in: expiresIn,
} = responseJson; } = responseJson;
await setSpotifyToken(accessToken); await setSpotifyToken(accessToken);
save(MY_SECURE_AUTH_STATE_KEY, accessToken);
testService(accessToken);
console.log(spotifyToken); console.log(spotifyToken);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
} }
const testService = async (token : string) =>{
try {
const serviceTest = new SpotifyService(token);
console.log("==============Test Service 1 ============");
const respSearch = await serviceTest.searchMusic("Parapluie Tiakola");
console.log("===================repoonce=========================");
console.log(respSearch);
console.log("============================================");
console.log("==============Test Service 2 ============");
const respFull = await serviceTest.getMusicById(respSearch[0].id);
console.log("===================repoonce=========================");
console.log(respFull);
console.log("============================================");
console.log("==============Test Service 3 ============");
const respSimilar = await serviceTest.getSimilarTrack(respSearch[0].id);
console.log("===================repoonce=========================");
console.log(respSimilar);
console.log("============================================");
console.log("==============Test Service 4 ============");
const respCurrent= await serviceTest.getUserCurrentMusic();
console.log("===================repoonce=========================");
console.log(respCurrent);
console.log("============================================");
console.log("==============Test Service 5 ============");
const respRecently= await serviceTest.getUserRecentlyPlayedMusic();
console.log("===================repoonce=========================");
console.log(respRecently);
console.log("============================================");
} catch (error) {
console.log("==============Test Service Error============");
console.error(error);
console.log("============================================");
}
}
return ( return (
<DismissKeyboard> <DismissKeyboard>
<View style={styles.container}> <View style={styles.container}>

@ -20,7 +20,7 @@ import { FetchRequest } from "expo-auth-session/build/Fetch";
import SpotifyService from "../services/spotify/spotify.service"; import SpotifyService from "../services/spotify/spotify.service";
import Music from '../Model/Music'; import Music from '../Model/Music';
import { HorizontalFlatList } from '../components/HorizontalFlatList'; import { HorizontalFlatList } from '../components/HorizontalFlatList';
import littleCard from '../components/littleCard'; import { LittleCard } from '../components/littleCard';
const halfPi = Math.PI/2; const halfPi = Math.PI/2;
// InfoScreen.sharedElement = (navigation : ReturnType<typeof useNavigation>)=>{ // InfoScreen.sharedElement = (navigation : ReturnType<typeof useNavigation>)=>{
// const music = navigation.getParam('music'); // const music = navigation.getParam('music');
@ -377,6 +377,16 @@ const styleAniamatedImage = useAnimatedStyle(() => {
await service.playMusic(id); await service.playMusic(id);
}catch(error){} }catch(error){}
} }
const tmpMusic2: 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"),
] ;
return ( return (
<View style={styles.body}> <View style={styles.body}>
<View style={styles.backgroundSection}> <View style={styles.backgroundSection}>
@ -463,15 +473,19 @@ const styleAniamatedImage = useAnimatedStyle(() => {
</View> </View>
{similarMusics.length !== 0 && ( {similarMusics.length !== 0 && (
<HorizontalFlatList renderCell={littleCard} title={'Simillar Music'} data={similarMusics}> // <HorizontalFlatList renderCell={littleCard} title={'Simillar Music'} data={similarMusics}>
</HorizontalFlatList> // </HorizontalFlatList>
<HorizontalFlatList title={'Simillar Music'} data={tmpMusic2}>
{(props) => (
<LittleCard image={props.image} title ={props.title}/>
)}
</HorizontalFlatList>
)} )}
</ScrollView> </ScrollView>
</View> </View>
</View> </View>

@ -2,6 +2,18 @@ import axios from "axios";
import MusicFactory from "../../Model/factory/MusicFactory"; import MusicFactory from "../../Model/factory/MusicFactory";
import Music from "../../Model/Music"; import Music from "../../Model/Music";
import { FetchOptions, RequestHandler } from "./spotifyRequestHandler/utils"; import { FetchOptions, RequestHandler } from "./spotifyRequestHandler/utils";
export class MusicMinimal {
public id : string;
public title: string;
public image: string;
constructor(id : string,title: string, bio: string, image: string, trackPreviewUrl: string) {
this.title = title;
this.image = image;
this.id = id;
}
}
export default class SpotifyService implements IspotifyService { export default class SpotifyService implements IspotifyService {
private readonly API_URL = "https://flad-api-production.up.railway.app/api/"; private readonly API_URL = "https://flad-api-production.up.railway.app/api/";
@ -138,7 +150,7 @@ export default class SpotifyService implements IspotifyService {
return ; return ;
} }
public async createPlayList(userId : string,name : string,description : string): Promise<void>{ public async createPlayList(userId : string,name? : string,description? : string): Promise<void>{
var requestData :string = '/users/' + encodeURIComponent(userId) + '/playlists'; var requestData :string = '/users/' + encodeURIComponent(userId) + '/playlists';
const fetchOptions: FetchOptions = { const fetchOptions: FetchOptions = {
@ -146,7 +158,7 @@ export default class SpotifyService implements IspotifyService {
body: { body: {
"public": false, "public": false,
"name": name || "New Flad Playlist", "name": name || "New Flad Playlist",
"description": description, "description": description || "New Flad Playlist",
} }
}; };
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token); const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
@ -154,6 +166,75 @@ export default class SpotifyService implements IspotifyService {
return ; return ;
} }
// public async getSimilarTrack(musicId : string,limit : number =1,market? : string): Promise<Music[]>{
// var requestData :string = '/recommendations' +
// '?limit=' +limit+
// '&market=FR' +
// "&seed_tracks=" + musicId;
// const fetchOptions: FetchOptions = {
// method: 'GET',
// body: {
// seed_tracks: musicId,
// market: "FR",
// limit: 1,
// }
// };
// console.log('222222222221baaaaaaaaaaaaahhhhhhhhhhhh LAaa chp gros ' + musicId);
// const respSimilarMusic = await this.spotifyRequestHandler.spotifyFetch(requestData,undefined,this.token);
// console.log(respSimilarMusic.status+'baaaaaaaaaaaaahhhhhhhhhhhh LAaa chp gros');
// console.log(respSimilarMusic.data+'baaaaaaaaaaaaahhhhhhhhhhhh LAaa chp gros2');
// /// if respSimilarMusic == null || respSimilarMusic.data.count == 0 =>
// const similars : Music[]= respSimilarMusic.data.tracks.map(async (trackData: any) => {
// // const { id, name, artists, album } = trackData;
// console.log(trackData.id);
// if(trackData.id){
// const data = await this.getMusicById(trackData.id);
// return data;
// }
// // 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);
// });
// console.log(similars+'################################################');
// return similars;
// }
public async getSimilarTrack(musicId: string, limit: number = 1, market?: string): Promise<Music[]> {
const requestData: string = '/recommendations/' +
'?limit=' + limit +
'&market=FR' +
'&seed_tracks=' + musicId;
console.log(musicId, "=============ouioui=================")
var respSimilarMusic;
try {
console.log( "=======================1=========",requestData,this.token )
respSimilarMusic= await this.spotifyRequestHandler.spotifyFetch(requestData, {}, this.token);
} catch (error) {
console.log(error, "===================================spot Service");
}
if (!respSimilarMusic || !respSimilarMusic.data.tracks) {
return [];
}
const similars: Music[] = await Promise.all(
respSimilarMusic.data.tracks.map(async (trackData: any) => {
if (trackData.id !=undefined) {
const data = await this.getMusicById(trackData.id);
return data;
}
})
)
return similars.filter((music: Music | undefined) => !!music) as Music[];
// return similars;
}
async getSpotifyCredentials() { async getSpotifyCredentials() {

@ -1,4 +1,4 @@
import axios, { AxiosError } from "axios"; import axios, { AxiosError, AxiosResponse } from "axios";
export type Methods = 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH'; export type Methods = 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
@ -19,7 +19,7 @@ export class RequestHandler{
return this._version; return this._version;
} }
public async spotifyFetch(url: string, options: FetchOptions = {}, token: string) { public async spotifyFetch(url: string, options: FetchOptions = {}, token: string) : Promise<AxiosResponse<any,any>> {
console.log(options+ "sds============="); console.log(options+ "sds=============");
const resp = await axios({ const resp = await axios({
url: `https://api.spotify.com/${this.version}${url}`, url: `https://api.spotify.com/${this.version}${url}`,
@ -32,7 +32,8 @@ export class RequestHandler{
}, },
data: options.body data: options.body
}); });
console.log(resp); console.log(")))))))))))))))))))",resp.request, "((((((((((((((((((((");
// console.log(resp, "frfrfrfr");
return resp; return resp;
// if ( // if (
// // @ts-ignore // // @ts-ignore

@ -10,14 +10,8 @@ export class UserService {
return docData(userDocRef); return docData(userDocRef);
} }
async uploadName(name: string, email : string) { async uploadName(name: string, email : string) {
const user = this.auth.currentUser;
try { try {
const userDocRef = doc(this.firestore, `User/${user.uid}`);
await setDoc(userDocRef, {
name,
email
});
return true;
} catch (e) { } catch (e) {
return null; return null;
} }

Loading…
Cancel
Save