details starting
continuous-integration/drone/push Build is passing Details

pull/12/head
David D'ALMEIDA 2 years ago
parent 37800e2daf
commit 8753904479

@ -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;
}
static mapFromSpotifyTrackSmpified(jsonMusic :any ): Music {
const music = new Music(
jsonMusic.id,
jsonMusic.name,
"",
jsonMusic.album.images[0].url,
jsonMusic.preview_url
);
return music;
}
}

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

@ -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: {
flexDirection: "row",
flexWrap: "wrap",
},
});

@ -12,15 +12,16 @@ 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";
import { RenderCellProps } from "./littleCard";
interface HorizontalFlatListProps {
// React.ReactNode;
renderCell: (image: string, titre : string) => React.ReactElement
children:(props: RenderCellProps) => React.ReactElement
title : string;
data : any[];
}
export const HorizontalFlatList = ({ title, data, renderCell}: HorizontalFlatListProps) => {
export const HorizontalFlatList = ({ title, data, children : RenderCell }: HorizontalFlatListProps) => {
return (
@ -31,22 +32,19 @@ export const HorizontalFlatList = ({ title, data, renderCell}: HorizontalFlatLis
data={data}
horizontal={true}
keyExtractor={item => item.id}
renderItem={({item}) =>{
return renderCell(item.image, image.titre);
}}
/></View>
renderItem={({ item }) => RenderCell(item)}/></View>
);
};
const styles = StyleSheet.create({
similarSection: {
paddingTop: 30
paddingTop: 16
},
similarTitle: {
color: "#2998FD",
paddingLeft: 35,
fontSize: 17,
color: "#FFF",
paddingLeft: 8,
fontSize: 24,
fontWeight: "600",
paddingBottom: 20
paddingBottom: 16
}
});

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

@ -82,5 +82,24 @@ export const spotArray2: Spot[] = [
"Harry Styles",
"https://i.scdn.co/image/ab67616d0000b2738900d48677696015bf325b8b",
"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")
)
];

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

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

@ -4,7 +4,7 @@ import axios from "axios";
import { json } from "express";
import { useEffect } from "react";
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 { User } from "../../Model/User";
import { UserFactory } from "../../Model/factory/UserFactory";
@ -38,7 +38,7 @@ export const registerUser = ( resgisterCredential : CredentialsRegister) => {
"https://flad-api-production.up.railway.app/api/users",
{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);
// dispatch(setLoginState(user.data) ); // our action is called here
} else {
@ -109,9 +109,6 @@ export const getRefreshToken = () => {
return async dispatch => {
try {
let userToken : string | null = await SecureStore.getItemAsync(key);
console.log("==========key ==================");
console.log(userToken);
console.log("==========key ==================");
if (userToken) {
console.log("==========key2 ==================");

@ -1,5 +1,5 @@
import { NavigationProp, RouteProp } from "@react-navigation/native";
import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity } from "react-native";
import { NavigationProp, RouteProp, useNavigation } from "@react-navigation/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 { BlurView } from 'expo-blur';
import qs from "qs";
@ -14,6 +14,15 @@ import Music from "../Model/Music";
import SpotifyService from "../services/spotify/spotify.service";
import { SharedElement } from "react-navigation-shared-element";
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';
const halfPi = Math.PI/2;
@ -22,7 +31,7 @@ const MusicDetail = ({ route }) => {
const music : Music = route.params.music;
const [currentspot, setCurrentspot] = useState(music);
const [sound, setSound] = useState(null);
const [simularMusic, setSimularMusic] = useState([] as Music []);
const [isPlaying, setIsPlaying] = useState(false);
const loader = useSharedValue(0);
useEffect(() => {
@ -218,11 +227,55 @@ const MusicDetail = ({ route }) => {
await service.playMusic(id);
}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"),
] ;
const getSimilarTrack = async () => {
const service =new SpotifyService("BQC0Ne1eU2bR28A65uO-M9QPLCmGveUG5E7tQ5dD8nmzQvcz2OqUWNMYEM7zx0sEIvOPoV3S9XKSlFbFx5C3si97YAXU-4AzRiqoshfmLTFlGoPMkmGhYip9MDzshhbZM76eEWJ6x43YoXiM-TQBhI0HKh78W6a3A34TXIrn0QzU3rvZM2-ftnTfKD2e2bAN3FgDc38C");
var simularMusic = await service.getSimilarTrack(currentspot.id,5,'FR');
setSimularMusic(simularMusic);
}
useEffect(() => {
getSimilarTrack();
}, []);
const navigator = useNavigation();
return (
<SafeAreaView style={styles.mainSafeArea}>
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
<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={styles.section1}>
<View style={{ flex: 1,justifyContent : 'flex-start', alignItems : 'center' }}>
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
<View>
@ -233,51 +286,63 @@ const MusicDetail = ({ route }) => {
style={[
{
width: 370,
height: 370,
// width: 370,
// width: 400,
width: 392,
height: 392,
borderRadius : 24,
resizeMode: 'stretch',
},styleAniamatedImage
]}
/>
<Button title="Play Track On Device"
onPress={() => {
playMusic(currentspot.id)
// promptAsync();
}}
/>
</View>
{/* Button */}
</View>
<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>
{/* <TapGestureHandler {...gestureHandler}> */}
<Animated.View>
<TouchableOpacity style={{
backgroundColor: '#1DB954',
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 24,
}}
onPressOut={handleStopSound}
onLongPress={handlePlaySound}
delayLongPress={1000}>
<View style ={{flex: 1, flexDirection : 'row', justifyContent :'space-evenly', width : '100%' }}>
<Text style={ {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',}}>
{isPlaying ? 'Playing...' : 'Play'}
</Text>
</TouchableOpacity>
</Animated.View>
{/* </TapGestureHandler> */}
{/* Button */}
{/* </SharedElement> */}
<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' }}>Partager 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>
<HorizontalFlatList title={'Similar'} data={tmpMusic2}>
{(props) => (
<Pressable onLongPress={() => { navigator.navigate("MusicDetail", {"music": props}) }} >
<LittleCard image={props.image} title ={props.title}/>
</Pressable>
)}
</HorizontalFlatList>
</ScrollView>
</View>
</View>
</SafeAreaView>
@ -290,5 +355,31 @@ const styles = StyleSheet.create ({
mainSafeArea: {
flex: 1,
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
}
})

@ -109,6 +109,40 @@ const scopes = scopesArr.join(' ');
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 () => {
try {
const authorizationCode = await getAuthorizationCode() //we wrote this function above

@ -20,7 +20,7 @@ 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';
import { LittleCard } from '../components/littleCard';
const halfPi = Math.PI/2;
// InfoScreen.sharedElement = (navigation : ReturnType<typeof useNavigation>)=>{
// const music = navigation.getParam('music');
@ -377,6 +377,16 @@ const styleAniamatedImage = useAnimatedStyle(() => {
await service.playMusic(id);
}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 (
<View style={styles.body}>
<View style={styles.backgroundSection}>
@ -463,12 +473,16 @@ const styleAniamatedImage = useAnimatedStyle(() => {
</View>
{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>
)}

@ -138,7 +138,7 @@ export default class SpotifyService implements IspotifyService {
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';
const fetchOptions: FetchOptions = {
@ -146,7 +146,7 @@ export default class SpotifyService implements IspotifyService {
body: {
"public": false,
"name": name || "New Flad Playlist",
"description": description,
"description": description || "New Flad Playlist",
}
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
@ -154,7 +154,32 @@ export default class SpotifyService implements IspotifyService {
return ;
}
public async getSimilarTrack(musicId : string,limit? : number ,market? : string): Promise<Music[]>{
var requestData :string = '/recommendations';
const fetchOptions: FetchOptions = {
method: 'GET',
body: {
seed_tracks: musicId,
// market: "FR",
// limit: 5,
}
};
console.log('222222222221baaaaaaaaaaaaahhhhhhhhhhhh LAaa chp gros');
const respSimilarMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
console.log(respSimilarMusic.status+'baaaaaaaaaaaaahhhhhhhhhhhh LAaa chp gros');
/// if respSimilarMusic == null || respSimilarMusic.data.count == 0 =>
const similars = respSimilarMusic.data.tracks.map((trackData: any) => {
// const { id, name, artists, album } = trackData;
console.log(trackData.id);
// 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 [] as Music[];
}
async getSpotifyCredentials() {
const res = await axios.get(this.API_URL)

@ -32,7 +32,7 @@ export class RequestHandler{
},
data: options.body
});
console.log(resp);
console.log(resp, "frfrfrfr");
return resp;
// if (
// // @ts-ignore

Loading…
Cancel
Save