Merge Conflict
continuous-integration/drone/push Build is passing Details

pull/15/head
root 2 years ago
commit bd5dce0f2b

@ -97,7 +97,10 @@ Notre environnement de travail se base sur plusieurs outils et langages :👇
---
  ![React Native](https://img.shields.io/badge/React%20Native-000?style=for-the-badge&logo=react&logoColor=white&color=lightblue&textColor=white)
  ![Redux](https://img.shields.io/badge/Redux-593D88?style=for-the-badge&logo=redux&logoColor=white)
  ![Docker](https://img.shields.io/badge/Docker-2496ED.svg?style=for-the-badge&logo=Docker&logoColor=white)
  ![React Native](https://img.shields.io/badge/React_Native-20232A?style=for-the-badge&logo=react&logoColor=61DAFB)
  ![Spotify Api](https://img.shields.io/badge/Spotify-1ED760?&style=for-the-badge&logo=spotify&logoColor=white)
  ![TypeScript](https://img.shields.io/badge/TypeScript-000?style=for-the-badge&logo=typescript&logoColor=white&color=blue)
  ![JavaScript](https://img.shields.io/badge/JavaScript-000?style=for-the-badge&logo=javascript&logoColor=white&color=yellow)
@ -114,10 +117,19 @@ Notre environnement de travail se base sur plusieurs outils et langages :👇
La composition pour le projet se voit réaliser par deux élèves de l'IUT d'Aubière:
<br>
⚙️ Emre KARTAL : emre.kartal@etu.uca.fr
Emre KARTAL : emre.kartal@etu.uca.fr
<br>
⚙️ David D'ALMEIDA : david.d_almeida@etu.uca.fr
David D'ALMEIDA : david.d_almeida@etu.uca.fr
<a href = "https://codefirst.iut.uca.fr/git/emre.kartal">
<img src="https://codefirst.iut.uca.fr/git/avatars/402cf312e853192f42c0135a888725c2?size=870" width="50" >
</a>
<a href = "https://codefirst.iut.uca.fr/git/david.d_almeida">
<img src="https://codefirst.iut.uca.fr/git/avatars/0f8eaaad1e26d3de644ca522eccaea7c?size=870" width="50" >
</a>
<div align = center>
© PM2 (Projet inspiré par nos très chers développeurs de la Dafl Team (S.O les Dafl dev))
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 136 KiB

@ -1,199 +0,0 @@
import React, { useState, useRef } from 'react';
import { Modal, View, StyleSheet, Text, FlatList, Animated, TouchableOpacity, ImageBackground, Image } from 'react-native';
// import Modal from "react-native-modal";
import {useNavigation} from "@react-navigation/native";
import normalize from '../components/Normalize';
import OnboardingItem from './OnboardingItem';
import Paginator from './Paginator';
import NextButton from './NextButton';
import slides from '../data/slides';
export default function Onboarding() {
const [currentIndex, setCurrentIndex] = useState(0);
const scrollX = useRef(new Animated.Value(0)).current;
const slidesRef = useRef(null);
const navigation = useNavigation();
const [isModalVisible, setIsModalVisible] = React.useState(false);
const handleModal = () => setIsModalVisible(() => !isModalVisible);
// @ts-ignore
const viewableItemsChanged = useRef(({ viewableItems }) => {
setCurrentIndex(viewableItems[0].index);
}).current;
const viewConfig = useRef({ viewAreaCoveragePercentThreshold: 50 }).current;
const scrollTo = () => {
if(currentIndex < slides.length - 1) {
// @ts-ignore
slidesRef.current.scrollToIndex({ index: currentIndex + 1 });
} else {
setIsModalVisible(() => !isModalVisible);
}
};
return (
// @ts-ignore
<View style={styles.container}>
<View style={styles.balise}>
<FlatList
data={slides}
renderItem={({item}) => <OnboardingItem item={item} />}
horizontal
showsHorizontalScrollIndicator={false}
pagingEnabled
bounces={false}
keyExtractor={(item) => item.id}
onScroll={Animated.event([{ nativeEvent: { contentOffset: { x: scrollX } } }], {
useNativeDriver: false,
})}
scrollEventThrottle={32}
onViewableItemsChanged={viewableItemsChanged}
viewabilityConfig={viewConfig}
ref={slidesRef}
/>
<Paginator data={slides} scrollX={scrollX}/>
<NextButton scrollTo={scrollTo} percentage={(currentIndex + 1) * (100 / slides.length)} />
</View>
<Modal animationType="slide" visible={isModalVisible} transparent={true} presentationStyle={'pageSheet'}>
<View style={styles.modalContent}>
<ImageBackground source={require("../assets/images/Background_Start_Page.png")} style={styles.backgroundImage}>
<View style={styles.modalView}>
<Text style={styles.versionText}>
v2.0
</Text>
<TouchableOpacity onPress={handleModal} style={styles.closeButtonCircle}>
<View>
<Image source={require("../assets/icons/icons/croix.png")} style={styles.imageButton}/>
</View>
</TouchableOpacity>
<Image source={require("../assets/icons/Logo_White_Flad.png")} style={styles.imageLogo}/>
<TouchableOpacity
style={styles.buttonConnection}
onPress={() => {handleModal();
// @ts-ignore
navigation.navigate('Login');
}}>
<Text style={styles.text}>CONTINUER AVEC SPOTIFY</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonInscription} onPress={() => {handleModal(); navigation.navigate('Register');}}>
<Text style={styles.text}>SINSCRIRE MAINTENANT</Text>
</TouchableOpacity>
<Image source={require("../assets/images/Flady.gif")} style={styles.mascot}/>
<TouchableOpacity style={styles.button2Connection} onPress={() => {handleModal(); navigation.navigate('Login');}}>
<Text style={styles.text}>SE CONNECTER</Text>
</TouchableOpacity>
</View>
</ImageBackground>
</View>
</Modal>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#141414'
},
imageLogo: {
width: normalize(324),
height: normalize(162),
marginBottom: '25%'
},
balise: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginBottom: normalize(110)
},
closeButtonCircle: {
backgroundColor: 'gray',
opacity: 0.4,
width: 40,
height: 40,
borderRadius: 20,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
top: 10,
right: 10
},
modalContent: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
modalView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
backgroundImage: {
flex: 1,
width: '100%',
height: '100%',
},
imageButton: {
width: 20,
height: 20
},
versionText: {
position: 'absolute',
top: 50,
right: 10,
color: 'gray',
fontWeight: 'bold',
fontSize: normalize(17)
},
buttonConnection: {
width: 262,
height: 57,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#24CF5F',
borderRadius: 11,
borderColor: '#68F097',
borderWidth: 1,
marginBottom: 12
},
buttonInscription: {
width: 262,
height: 57,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#951DDE',
borderRadius: 11,
borderColor: '#C656ED',
borderWidth: 1,
marginBottom: 220
},
text: {
fontWeight: 'bold',
color: 'white',
fontSize: normalize(18)
},
button2Connection: {
width: '100%',
height: normalize(92),
backgroundColor: '#232123',
borderTopColor: '#3C3C3C',
borderTopWidth: 1,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
bottom: normalize(0)
},
mascot: {
width: normalize(130),
height: normalize(130),
position: 'absolute',
bottom: normalize(90),
right: normalize(0)
}
})

@ -1,12 +1,12 @@
export default class Artist {
private id : string;
private name : string;
private url : string; // Image.source
constructor(id : string, name : string, url : string){
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;
}
}

@ -1,112 +1,112 @@
import { useState } from "react";
import SpotifyService from "../services/spotify/spotify.service";
class Manager{
// injection de dépences
spotifyService = new SpotifyService();
userService = new userService();
private currentUser = useState(null);
constructor() {
}
// spotify methods
apiAuthorization(url : string) {
this.spotifyService.apiAuthorization(url);
}
getCompleteMusic = async (id : string) :Promise<Music> =>{
// Map info = await spotifyService.getTrackInfo(id);
// return Music(id, info['name'], info['artist'], info['cover']);
}
removeFromPlaylist(id : string) {
this.spotifyService.removeFromPlaylist(id);
}
addToPlaylist(id : string) {
this.spotifyService.addToPlaylist(id);
}
playTrack(id : string) {
this.spotifyService.playTrack(id);
}
////////////////////////////////////////////
// private readonly getTaskById: RequestHandler = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const id = req.params.taskId;
// const userId = req.params.userId;
// const data = await this.Taskservice.getTaskById(id, userId);
// res.status(201).send(data);
// }
// catch(error){
// next(new HttpException(400, 'Cannot create post'));
// }
// }
// private delete = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const id = req.params.taskId;
// const userId = req.params.userId;
// await this.Taskservice.DeleteTask(id, userId);
// return res.status(200).send({ status: "Success", msg: "Data Removed" });
// } catch (error) {
// next(new HttpException(400, 'Cannot create post'));
// }
// };
// private updateTask = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const taskId = req.params.taskId;
// const userId = req.params.userId;
// const reqBody:CreateTaskReqBody = Object.assign({}, req.body);
// const updatedTask = await this.Taskservice.UpdateTask(
// // req.auth!.uid,
// taskId,
// userId,
// // firebase.auth().currentUser.getIdToken()
// reqBody.nom,
// reqBody.description,
// reqBody.logo,
// reqBody.duration,
// reqBody.done,
// // reqBody.tags,
// reqBody.repepat,
// reqBody.deb,
// reqBody.fin
// );
// // res.send('Success add');
// // res.status(201).json({ task });
// res.status(204).send(`Update a new contact: ${updatedTask}`);
// } catch (error) {
// console.log(error);
// next(new HttpException(403, 'Cannot create post'));
// }
// };
class Manager {
// injection de dépences
spotifyService = new SpotifyService();
userService = new userService();
private currentUser = useState(null);
constructor() {
}
// spotify methods
apiAuthorization(url: string) {
this.spotifyService.apiAuthorization(url);
}
getCompleteMusic = async (id: string): Promise<Music> => {
// Map info = await spotifyService.getTrackInfo(id);
// return Music(id, info['name'], info['artist'], info['cover']);
}
removeFromPlaylist(id: string) {
this.spotifyService.removeFromPlaylist(id);
}
addToPlaylist(id: string) {
this.spotifyService.addToPlaylist(id);
}
playTrack(id: string) {
this.spotifyService.playTrack(id);
}
////////////////////////////////////////////
// private readonly getTaskById: RequestHandler = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const id = req.params.taskId;
// const userId = req.params.userId;
// const data = await this.Taskservice.getTaskById(id, userId);
// res.status(201).send(data);
// }
// catch(error){
// next(new HttpException(400, 'Cannot create post'));
// }
// }
// private delete = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const id = req.params.taskId;
// const userId = req.params.userId;
// await this.Taskservice.DeleteTask(id, userId);
// return res.status(200).send({ status: "Success", msg: "Data Removed" });
// } catch (error) {
// next(new HttpException(400, 'Cannot create post'));
// }
// };
// private updateTask = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const taskId = req.params.taskId;
// const userId = req.params.userId;
// const reqBody:CreateTaskReqBody = Object.assign({}, req.body);
// const updatedTask = await this.Taskservice.UpdateTask(
// // req.auth!.uid,
// taskId,
// userId,
// // firebase.auth().currentUser.getIdToken()
// reqBody.nom,
// reqBody.description,
// reqBody.logo,
// reqBody.duration,
// reqBody.done,
// // reqBody.tags,
// reqBody.repepat,
// reqBody.deb,
// reqBody.fin
// );
// // res.send('Success add');
// // res.status(201).json({ task });
// res.status(204).send(`Update a new contact: ${updatedTask}`);
// } catch (error) {
// console.log(error);
// next(new HttpException(403, 'Cannot create post'));
// }
// };
}

@ -1,22 +1,22 @@
import Music from "./Music";
export class Spot {
private _userId : string;
private _music : Music;
constructor(userId : string, music : Music){
this._userId = userId;
this._music = music;
}
get userSpotifyId(): string {
return this._userId;
}
set userSpotifyId(value: string) {
this._userId = value;
}
get music(): Music {
return this._music;
}
set music(value: Music) {
this._music = value;
}
private _userId: string;
private _music: Music;
constructor(userId: string, music: Music) {
this._userId = userId;
this._music = music;
}
get userSpotifyId(): string {
return this._userId;
}
set userSpotifyId(value: string) {
this._userId = value;
}
get music(): Music {
return this._music;
}
set music(value: Music) {
this._music = value;
}
}

@ -1,34 +1,34 @@
class TokenSpotify {
class TokenSpotify {
String _accessToken;
final String _refreshToken;
late DateTime _tokenEnd;
// TokenSpotify(this._accessToken, this._refreshToken, int expiresIn) {
// _setTokenEnd(expiresIn);
// }
// TokenSpotify(this._accessToken, this._refreshToken, int expiresIn) {
// _setTokenEnd(expiresIn);
// }
// _setTokenEnd(int expiresIn) {
// _tokenEnd = DateTime.now().add(Duration(seconds: expiresIn));
// }
// _setTokenEnd(int expiresIn) {
// _tokenEnd = DateTime.now().add(Duration(seconds: expiresIn));
// }
// Future<String> getAccessToken() async {
// if (DateTime.now().isAfter(_tokenEnd)) {
// await _actualiseToken();
// }
// return _accessToken;
// }
// Future<String> getAccessToken() async {
// if (DateTime.now().isAfter(_tokenEnd)) {
// await _actualiseToken();
// }
// return _accessToken;
// }
// _actualiseToken() async {
// var urlToken = Uri.https('accounts.spotify.com', 'api/token', {
// 'grant_type': 'refresh_token',
// 'refresh_token': _refreshToken,
// 'client_id': ApiSpotifyIdentification.clientId
// });
// setResponse(await http.post(urlToken, headers: <String, String>{
// 'Content-Type': 'application/x-www-form-urlencoded'
// }));
// var decodedResponse = jsonDecode(utf8.decode(response.bodyBytes)) as Map;
// _accessToken = decodedResponse['access_token'];
// _setTokenEnd(decodedResponse['expires_in']);
// }
// _actualiseToken() async {
// var urlToken = Uri.https('accounts.spotify.com', 'api/token', {
// 'grant_type': 'refresh_token',
// 'refresh_token': _refreshToken,
// 'client_id': ApiSpotifyIdentification.clientId
// });
// setResponse(await http.post(urlToken, headers: <String, String>{
// 'Content-Type': 'application/x-www-form-urlencoded'
// }));
// var decodedResponse = jsonDecode(utf8.decode(response.bodyBytes)) as Map;
// _accessToken = decodedResponse['access_token'];
// _setTokenEnd(decodedResponse['expires_in']);
// }
}

@ -1,42 +1,42 @@
export class User {
//attributes from DAFL
private _idFlad : string;
private _idSpotify : string;
private _email : string;
private _createdAt : Date;
private _name : string;
public image : string = require('../assets/images/jul.png');
//constructors
constructor(idFlad : string, idSpotify : string, email : string, createdAt : Date, name : string, image : string){
this._name = name;
this._idFlad = idFlad;
this._idSpotify = idSpotify;
this._createdAt = createdAt;
this._email = email;
this.image = image;
}
//attributes from DAFL
private _idFlad: string;
private _idSpotify: string;
private _email: string;
private _createdAt: Date;
private _name: string;
public image: string = require('../assets/images/jul.png');
//constructors
constructor(idFlad: string, idSpotify: string, email: string, createdAt: Date, name: string, image: string) {
this._name = name;
this._idFlad = idFlad;
this._idSpotify = idSpotify;
this._createdAt = createdAt;
this._email = email;
this.image = image;
}
get idFlad(): string {
return this._idFlad;
}
get idSpotify(): string {
return this._idSpotify;
}
get email(): string {
return this._email;
}
get createAt(): Date {
return this._createdAt;
}
get name(): string {
return this._name;
}
get idFlad(): string {
return this._idFlad;
}
get idSpotify(): string {
return this._idSpotify;
}
get email(): string {
return this._email;
}
get createAt(): Date {
return this._createdAt;
}
get name(): string {
return this._name;
}
static empty() {
return new User('','','',new Date(),'',require('../assets/images/jul.png'));
}
static empty() {
return new User('', '', '', new Date(), '', require('../assets/images/jul.png'));
}
toString() {
return 'User : ' + this.idFlad + ', ' + this.name + ', ' + this.idSpotify;
toString() {
return 'User : ' + this.idFlad + ', ' + this.name + ', ' + this.idSpotify;
}
}
}

@ -0,0 +1,6 @@
export const GraphicalCharterDark = {
"body": "#141414",
"Text": "white",
"Card": "#232123",
"Line": "#403F3F"
}

@ -0,0 +1,6 @@
export const GraphicalCharterLight = {
"body": "#f2f2f6",
"Text": "black",
"Card": "#fff",
"Line": "#e2e2e3"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 KiB

After

Width:  |  Height:  |  Size: 590 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 KiB

Binary file not shown.

@ -0,0 +1,10 @@
import React from 'react';
export default function AdjustSize(Text: String) {
const titleLength = Text.length;
const minFontSize = 23;
const maxFontSize = 48;
const fontRatio = 1.1;
const fontSize = Math.max(minFontSize, maxFontSize - (titleLength * fontRatio));
return fontSize;
}

@ -2,45 +2,45 @@ import { View, useWindowDimensions } from "react-native";
import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, withTiming } from "react-native-reanimated";
interface SpotProps {
spot: { name: string, sourceUrl: string, index : number };
spot: { name: string, sourceUrl: string, index: number };
}
const halfPi = Math.PI/2;
const halfPi = Math.PI / 2;
const AnimatedParalax = ({}) => {
const {width, height} = useWindowDimensions();
const AnimatedParalax = ({ }) => {
const { width, height } = useWindowDimensions();
const sensor = useAnimatedSensor(SensorType.ROTATION);
const styleAniamatedImage = useAnimatedStyle(() => {
const {yaw, pitch, roll} = sensor.sensor.value;
const verticalAxis =interpolate(
const { yaw, pitch, roll } = sensor.sensor.value;
const verticalAxis = interpolate(
pitch,
[-halfPi,halfPi],
[-halfPi, halfPi],
[-25, 25]
)
const horizontalAxis =interpolate(
const horizontalAxis = interpolate(
roll,
[-halfPi*2,halfPi*2],
[-halfPi * 2, halfPi * 2],
[-35, 35]
)
return {
top : verticalAxis,
left : horizontalAxis,
top: verticalAxis,
left: horizontalAxis,
};
})
return (
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
<View style={{ flex: 1, justifyContent: 'flex-start', alignItems: 'center' }}>
<Animated.Image
source={{
uri:spot.sourceUrl ,
}}
style={[
{
source={{
uri: spot.sourceUrl,
}}
style={[
{
width: 370,
height: 370,
borderRadius : 24,
borderRadius: 24,
resizeMode: 'stretch',
},styleAniamatedImage
]}
}, styleAniamatedImage
]}
/>
</View>

@ -1,10 +1,10 @@
import { View, StyleSheet, Dimensions, Image, TouchableOpacity } from "react-native";
import Animated, {
Layout,
ZoomIn,
ZoomOut,
} from "react-native-reanimated";
Layout,
ZoomIn,
ZoomOut,
} from "react-native-reanimated";
const { width } = Dimensions.get("window");
const SIZE = width / 3;
import { Feather as Icon } from "@expo/vector-icons";
@ -14,68 +14,68 @@ import { useRef, useState } from "react";
interface ArtistProps {
artist: Music;
onPress: () => void;
}
artist: Music;
onPress: () => void;
}
export const Artist = ({ artist, onPress }: ArtistProps) => {
const source = typeof artist.image === 'string' ? { uri: artist.image } : artist.image;
//@ts-ignore
const onSingleTapEvent = (event) => {
if (event.nativeEvent.state === State.ACTIVE) {
alert('Hey single tap!');
}
};
const doubleTapRef = useRef(null);
const [selected,setSeleted] = useState(false);
const onS = () => {
setSeleted(!selected);
onPress();
};
return (
<TouchableOpacity onPress={onS}>
const source = typeof artist.image === 'string' ? { uri: artist.image } : artist.image;
//@ts-ignore
const onSingleTapEvent = (event) => {
if (event.nativeEvent.state === State.ACTIVE) {
alert('Hey single tap!');
}
};
const doubleTapRef = useRef(null);
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}>
<Image source={source} style={styles.image} />
{ selected && (
{selected && (
<View style={styles.cheked}>
<Icon name="check-circle" color="black" size={24} />
<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",
</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",
}
});
}
});

@ -1,49 +1,49 @@
import { useCallback, useState } from 'react';
import { View, StyleSheet ,Text,Image, Pressable, Linking, Alert} from 'react-native'
import { View, StyleSheet, Text, Image, Pressable, Linking, Alert } from 'react-native'
interface ArtistChipProps {
backgroundColor : string;
artist : Artist;
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 (
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>
<Pressable onPress={handlePress}>
<View>
<Image
source={{
uri: artist.image,
}}
></Image>
</View>
<Image
source={{
uri: artist.image,
}}
></Image>
</View>
<View>
<Text>ii</Text>
</View>
</Pressable>
<View>
<Text>ii</Text>
</View>
);
};
</Pressable>
</View>
);
};
const styles = StyleSheet.create({
input : {
justifyContent : 'center',
alignItems : 'center',
placeholder : "placeholde"
input: {
justifyContent: 'center',
alignItems: 'center',
placeholder: "placeholde"
},
})

@ -1,7 +1,7 @@
import { View, Image , Dimensions, StyleSheet } from 'react-native'
import { View, Image, Dimensions, StyleSheet } from 'react-native'
import React from 'react'
import Animated,{ Extrapolate, interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
import Animated, { Extrapolate, interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
import normalize from '../components/Normalize';
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
const SCREEN_WIDTH = Dimensions.get('window').width
@ -11,251 +11,257 @@ const SCREEN_HEIGHT = Dimensions.get('window').height
// const height = wWidht * (465/264);
// const borderRadius = 24;
interface CardProps {
title: string;
image: any;
onSwipe: (direction: "left" | "right" | "down") => void;
}
type ContextType = {
translateX: number;
translateY: number;
};
const Card = ({ title, image, onSwipe } : CardProps) => {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const scale = useSharedValue(1);
const onGestureEvent = useAnimatedGestureHandler<
title: string;
image: any;
onSwipe: (direction: "left" | "right" | "down") => void;
}
type ContextType = {
translateX: number;
translateY: number;
};
const Card = ({ title, image, onSwipe }: CardProps) => {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const scale = useSharedValue(1);
const onGestureEvent = useAnimatedGestureHandler<
PanGestureHandlerGestureEvent,
ContextType
>({
onStart : (event, context) => {
context.translateX = translateX.value;
context.translateY = translateY.value;
},
onActive : (event, context) => {
translateX.value = event.translationX + context.translateX;
translateY.value = event.translationY + context.translateY;
},
onEnd : (event, context) => {
console.log(translateX.value - translateY.value);
// console.log(translateY.value);
// translateX.value = withSpring(0);
// translateY.value = withSpring(snapPoint(translateY.value,velocityY, snapPoints ))
if (translateX.value > 160) {
console.log("translateX2");
runOnJS(onSwipe)("right");
} else if (translateX.value < -160) {
runOnJS(onSwipe)("left");
// onSwipe("left");
}else if (translateY.value > 250) {
runOnJS(onSwipe)("down");
// onSwipe("left");
}
else {
translateX.value = withSpring(0);
translateY.value = withSpring(0);
}
},
});
//better to have 2 listerner => 2 useAnimatedStyle ou faire une ftc qui retourne l'verse de une useAnimatedStyle
const opacLStyle = useAnimatedStyle(() => {
const opacityl = interpolate
( translateX.value,
onStart: (event, context) => {
context.translateX = translateX.value;
context.translateY = translateY.value;
},
onActive: (event, context) => {
translateX.value = event.translationX + context.translateX;
translateY.value = event.translationY + context.translateY;
},
onEnd: (event, context) => {
console.log(translateX.value - translateY.value);
// console.log(translateY.value);
// translateX.value = withSpring(0);
// translateY.value = withSpring(snapPoint(translateY.value,velocityY, snapPoints ))
if (translateX.value > 160) {
console.log("translateX2");
runOnJS(onSwipe)("right");
} else if (translateX.value < -160) {
runOnJS(onSwipe)("left");
// onSwipe("left");
} else if (translateY.value > 250) {
runOnJS(onSwipe)("down");
// onSwipe("left");
}
else {
translateX.value = withSpring(0);
translateY.value = withSpring(0);
}
},
});
//better to have 2 listerner => 2 useAnimatedStyle ou faire une ftc qui retourne l'verse de une useAnimatedStyle
const opacLStyle = useAnimatedStyle(() => {
const opacityl = interpolate
(translateX.value,
[-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 4],
[ 0,0, 1]);
return {
opacity : opacityl,
};
});
const opacRStyle = useAnimatedStyle(() => {
const opacityl = interpolate
( translateX.value,
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 2],
[1, 0, 0]);
return {
opacity : opacityl,
};
});
const opacCStyle = useAnimatedStyle(() => {
const opacityl = interpolate
( translateX.value,
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 4],
[0.35, 0, 0.35]);
return {
opacity : opacityl,
};
});
const opacCStyle2 = useAnimatedStyle(() => {
const opacityl = interpolate
( translateY.value,
[0,SCREEN_HEIGHT/4],
[0,0.35]);
return {
opacity : opacityl,
};
});
const opacDStyle = useAnimatedStyle(() => {
const opacityl = interpolate
( translateY.value,
[ 100, 300],
[ 0, 1]);
return {
opacity : opacityl,
};
});
const horizontalThreshold = SCREEN_WIDTH * 0.65;
const rotateStyle = useAnimatedStyle(() => {
const rot = interpolate
( translateX.value,
[-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
[30, 0, 30],
Extrapolate.CLAMP);
return {
transform: [{ rotate: `${rot}deg` },{
translateX: withSpring(translateX.value),
} ],
};
});
const styleCardsNew = useAnimatedStyle(() => {
const factor = 1;
const rot = interpolate
( translateX.value,
[0, factor * horizontalThreshold],
[0, 15],
);
return {
transform: [
{ scale: scale.value },
{ translateX: translateX.value },
{ translateY: translateY.value },
{ rotateZ: `${rot}deg` },
]
};
});
// Calculate the distance of the card from its starting position
const rStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateX: translateX.value,
},
{
translateY: translateY.value,
},
],
};
});
console.log('==========================================',SCREEN_WIDTH/4 , "===============================");
return (
<View>
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={[ styleCardsNew, styles.container]}>
<Animated.View style={[ styles.image,{backgroundColor: 'black',elevation: 100,
position: "absolute",borderWidth : 8, borderColor : '#FFF',
zIndex: 1000,}, opacCStyle]}>
</Animated.View>
<Animated.View style={[ styles.image,{backgroundColor: 'black',elevation: 100,
position: "absolute",borderWidth : 8, borderColor : '#FFF',
zIndex: 1000,}, opacCStyle2]}>
</Animated.View>
<Image source={{uri : image}} style={[styles.image]} />
<>
<Animated.View
style={[{
// transform: [{ rotate: "30deg" }],
elevation: 100,
position: "absolute",
zIndex: 1000,
},opacRStyle]}
>
<Image style={[{alignSelf : "center"}]}
source={require('../assets/icons/icons/icon_dislike.png')}
/>
[0, 0, 1]);
return {
opacity: opacityl,
};
});
const opacRStyle = useAnimatedStyle(() => {
const opacityl = interpolate
(translateX.value,
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 2],
[1, 0, 0]);
return {
opacity: opacityl,
};
});
const opacCStyle = useAnimatedStyle(() => {
const opacityl = interpolate
(translateX.value,
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 4],
[0.35, 0, 0.35]);
return {
opacity: opacityl,
};
});
const opacCStyle2 = useAnimatedStyle(() => {
const opacityl = interpolate
(translateY.value,
[0, SCREEN_HEIGHT / 4],
[0, 0.35]);
return {
opacity: opacityl,
};
});
const opacDStyle = useAnimatedStyle(() => {
const opacityl = interpolate
(translateY.value,
[100, 300],
[0, 1]);
return {
opacity: opacityl,
};
});
const horizontalThreshold = SCREEN_WIDTH * 0.65;
const rotateStyle = useAnimatedStyle(() => {
const rot = interpolate
(translateX.value,
[-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
[30, 0, 30],
Extrapolate.CLAMP);
return {
transform: [{ rotate: `${rot}deg` }, {
translateX: withSpring(translateX.value),
}],
};
});
const styleCardsNew = useAnimatedStyle(() => {
const factor = 1;
const rot = interpolate
(translateX.value,
[0, factor * horizontalThreshold],
[0, 15],
);
return {
transform: [
{ scale: scale.value },
{ translateX: translateX.value },
{ translateY: translateY.value },
{ rotateZ: `${rot}deg` },
]
};
});
// Calculate the distance of the card from its starting position
const rStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateX: translateX.value,
},
{
translateY: translateY.value,
},
],
};
});
console.log('==========================================', SCREEN_WIDTH / 4, "===============================");
return (
<View>
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={[styleCardsNew, styles.container]}>
<Animated.View style={[styles.image, {
backgroundColor: 'black', elevation: 100,
position: "absolute", borderWidth: 8, borderColor: '#FFF',
zIndex: 1000,
}, opacCStyle]}>
</Animated.View>
<Animated.View style={[styles.image, {
backgroundColor: 'black', elevation: 100,
position: "absolute", borderWidth: 8, borderColor: '#FFF',
zIndex: 1000,
}, opacCStyle2]}>
</Animated.View>
<Image source={{ uri: image }} style={[styles.image]} />
<>
<Animated.View
style={[{
// transform: [{ rotate: "30deg" }],
elevation: 100,
position: "absolute",
zIndex: 1000,
}, opacRStyle]}
>
<Image style={[{ alignSelf: "center" }]}
source={require('../assets/icons/icons/icon_dislike.png')}
/>
</Animated.View>
<Animated.View
style={[{
width: '100%',
height: '100%',
position: "absolute",
justifyContent : "center",
alignContent : "center",
zIndex: 1000,
elevation: 100,
},opacLStyle]}
>
<Image style={[{alignSelf : "center"}]}
source={require('../assets/icons/icons/icon_like.png')}
/>
style={[{
width: '100%',
height: '100%',
position: "absolute",
justifyContent: "center",
alignContent: "center",
zIndex: 1000,
elevation: 100,
}, opacLStyle]}
>
<Image style={[{ alignSelf: "center" }]}
source={require('../assets/icons/icons/icon_like.png')}
/>
</Animated.View>
<Animated.View
style={[{
width: '100%',
height: '100%',
position: "absolute",
justifyContent : "center",
alignContent : "center",
elevation: 100,
zIndex: 1000,
},opacDStyle]}
>
<Image style={[{alignSelf : "center",width: 126.27,
height: 118.64, }]}
source={require('../assets/icons/icons/icon_discovery.png')}
/>
style={[{
width: '100%',
height: '100%',
position: "absolute",
justifyContent: "center",
alignContent: "center",
elevation: 100,
zIndex: 1000,
}, opacDStyle]}
>
<Image style={[{
alignSelf: "center", width: 126.27,
height: 118.64,
}]}
source={require('../assets/icons/icons/icon_discovery.png')}
/>
</Animated.View>
</>
</Animated.View>
</PanGestureHandler>
</View>
);
};
</>
</Animated.View>
</PanGestureHandler>
</View>
);
};
const styles = StyleSheet.create({
card : {
justifyContent : 'center',
alignItems : 'center',
card: {
justifyContent: 'center',
alignItems: 'center',
},
image : {
borderRadius : 24,
image: {
borderRadius: 24,
resizeMode: 'stretch',
height: 362,
width: 362,
},
container: {
flex: 1,
width: '100%',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}
height: normalize(420),
width: normalize(420),
},
container: {
flex: 1,
width: '100%',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}
})
export default Card;

@ -1,75 +1,78 @@
import React from 'react';
import { StyleSheet, Text, View , Image } from 'react-native';
import { StyleSheet, Text, View, Image } from 'react-native';
import { SharedElement } from 'react-navigation-shared-element';
import { useSelector } from 'react-redux';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
import normalize from '../components/Normalize';
type CustomCardMusic = { //Props
image: string;
title: string;
description: string;
id : string;
image: string;
title: string;
description: string;
id: string;
}
export default function CardMusic(CBP: CustomCardMusic) {
const currentMusic = useSelector(state => state.appReducer.currentMusic);
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? GraphicalCharterLight : GraphicalCharterDark;
const currentMusic = useSelector(state => state.appReducer.currentMusic);
const source = typeof CBP.image === 'string' ? { uri: CBP.image } : CBP.image;
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 15
},
imageContainer: {
width: normalize(92),
height: normalize(92),
alignItems: 'center',
justifyContent: 'center',
marginRight: 20,
marginLeft: 20
},
image: {
width: '100%',
height: '100%',
borderRadius: 10
},
textContainer: {
flex: 1,
alignItems: 'flex-start',
justifyContent: 'center',
},
title: {
fontWeight: 'bold',
color: style.Text,
fontSize: normalize(23),
marginBottom: 10
},
description: {
color: style.Text,
fontSize: normalize(18)
},
currentMusic: {
color: 'red'
}
});
return (
<View style={styles.container}>
<View style={styles.imageContainer}>
<Image source={source} style={styles.image}/>
</View>
<View style={styles.textContainer}>
{/* currentMusic.id === CBP.id && styles.currentMusic */}
<Text style={[styles.title]}>{CBP.title}</Text>
<Text style={[styles.description]}>{CBP.description}</Text>
</View>
<View style={styles.imageContainer}>
<Image source={source} style={styles.image} />
</View>
<View style={styles.textContainer}>
{/* currentMusic.id === CBP.id && styles.currentMusic */}
<Text style={[styles.title]}>{CBP.title}</Text>
<Text style={[styles.description]}>{CBP.description}</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 15
},
imageContainer: {
width: normalize(92),
height: normalize(92),
alignItems: 'center',
justifyContent: 'center',
marginRight: 20,
marginLeft: 20
},
image: {
width: '100%',
height: '100%',
borderRadius: 10
},
textContainer: {
flex: 1,
alignItems: 'flex-start',
justifyContent: 'center',
},
title: {
fontWeight: 'bold',
color: 'white',
fontSize: normalize(23),
marginBottom: 10
},
description: {
color: 'white',
fontSize: normalize(18)
},
currentMusic: {
color: 'red'
}
});

@ -1,75 +1,75 @@
import { useState } from 'react';
import { View, Text, Image ,PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, TextInput } from 'react-native'
import { View, Text, Image, PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, TextInput } from 'react-native'
import Animated, { interpolate, lessThan, multiply, useAnimatedStyle } from 'react-native-reanimated';
import HalfCirlce from './HalfCircle';
interface CircularProps {
background : string,
foreground : string,
progress : Animated.Value<number>,
radius : number;
background: string,
foreground: string,
progress: Animated.Value<number>,
radius: number;
}
const PI= Math.PI;
const FladInput = ({background, foreground, progress} : CircularProps) => {
const [focused, setFocused] = useState<boolean>(false);
const theta = multiply(progress,2*PI);
const rotateTop = theta;
const opacity = lessThan(theta, PI);
const PI = Math.PI;
const FladInput = ({ background, foreground, progress }: CircularProps) => {
const [focused, setFocused] = useState<boolean>(false);
const theta = multiply(progress, 2 * PI);
const rotateTop = theta;
const opacity = lessThan(theta, PI);
const rotateAnimation = useAnimatedStyle(() => {
const rotate = interpolate
( theta,
[PI, 2*PI],
[0,PI]);
const rotateAnimation = useAnimatedStyle(() => {
const rotate = interpolate
(theta,
[PI, 2 * PI],
[0, PI]);
return {
...StyleSheet.absoluteFillObject,
transform: [
{ rotate: rotate },
{ translateX: RADUIS / 2 },
{ translateY: RADUIS / 2 }
],
};
});
const rotateAnimation2 = useAnimatedStyle(() => {
const rotate = interpolate
(theta,
[PI, 2 * PI],
[0, PI]);
return {
...StyleSheet.absoluteFillObject,
transform: [
{ rotate: theta },
{ translateX: RADUIS / 2 },
{ translateY: RADUIS / 2 }
],
};
});
return (
<>
<View style={{ zIndex: 1 }}>
<HalfCirlce backgroundColor={background} />
<Animated.View style={{ ...StyleSheet.absoluteFillObject, transform: [{ rotate: '180%' }], opacity }}>
<HalfCirlce backgroundColor={background} />
</Animated.View>
</View>
<View style={{ transform: [{ rotate: '180%' }] }}>
<HalfCirlce backgroundColor={background} />
<Animated.View style={{}}>
<HalfCirlce backgroundColor={background} />
</Animated.View> </View>
</>
);
};
return {
...StyleSheet.absoluteFillObject,
transform: [
{rotate: rotate},
{translateX: RADUIS/2},
{translateY: RADUIS/2}
],
};
});
const rotateAnimation2 = useAnimatedStyle(() => {
const rotate = interpolate
( theta,
[PI, 2*PI],
[0,PI]);
return {
...StyleSheet.absoluteFillObject,
transform: [
{rotate: theta},
{translateX: RADUIS/2},
{translateY: RADUIS/2}
],
};
});
return (
<>
<View style={{zIndex : 1}}>
<HalfCirlce backgroundColor={background}/>
<Animated.View style={{...StyleSheet.absoluteFillObject, transform : [{rotate : '180%'}], opacity}}>
<HalfCirlce backgroundColor={background}/>
</Animated.View>
</View>
<View style={{ transform : [{rotate : '180%'}]}}>
<HalfCirlce backgroundColor={background}/>
<Animated.View style={{}}>
<HalfCirlce backgroundColor={background}/>
</Animated.View> </View>
</>
);
};
const styles = StyleSheet.create({
input : {
justifyContent : 'center',
alignItems : 'center',
placeholder : "placeholde"
input: {
justifyContent: 'center',
alignItems: 'center',
placeholder: "placeholde"
},
})

@ -91,7 +91,7 @@
import React, { useEffect, useRef } from 'react';
import { StyleSheet, Text, View , Image } from 'react-native';
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';
@ -110,6 +110,20 @@ export default function CurrentMusic() {
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',
@ -122,24 +136,10 @@ export default function CurrentMusic() {
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' }]}>
}, { overflow: 'hidden' }]}>
<Animated.View style={rStyle} />
</Animated.View>
</View>
</View>
);
}

@ -1,113 +1,113 @@
import { View, Text, Image , Dimensions, StyleSheet } from 'react-native'
import { View, Text, Image, Dimensions, StyleSheet } from 'react-native'
import React, { useEffect, useRef, useState } from 'react'
import Animated,{ Extrapolate, interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withRepeat, withSpring, withTiming } from 'react-native-reanimated';
import Animated, { Extrapolate, interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withRepeat, withSpring, withTiming } from 'react-native-reanimated';
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
import * as Haptics from 'expo-haptics';
const {width : wWidht} = Dimensions.get("window");
const { width: wWidht } = Dimensions.get("window");
const SCREEN_HEIGHT = Dimensions.get('window').height
const SCREEN_WIDTH = Dimensions.get('window').width
// const width = wWidht *0.75;
// const height = wWidht * (465/264);
// const borderRadius = 24;
const size= 100
const size = 100
const FladLoading = () => {
const progresse = useSharedValue(1);
useEffect(() => {
// withTiming, withSpring
progresse.value =withRepeat( withTiming(0.01,{duration : 750}), -1,true);
}, [progresse]);
const breatheStyle = useAnimatedStyle(() => {
const borderRange = interpolate
( progresse.value,
[0, 1],
[(0*size) / 2,(1*size)/2],
);
return {
justifyContent : 'center',
alignItems : 'center',
width : size,
height : size,
shadowColor : "#DA1D1D",
shadowOffset : {width : 0, height : 0},
shadowOpacity : 1,
shadowRadius :borderRange,
};
});
const breatheStyle2 = useAnimatedStyle(() => {
const borderRange = interpolate
( progresse.value,
[0, 1],
[(0*size) / 2,(1*size)/2],
);
return {
borderRadius : borderRange,
};
});
const breatheStyleSquare = useAnimatedStyle(() => {
const borderRange = interpolate
( progresse.value,
[0, 1],
[(size+20),(size)],
);
return {
width : borderRange,
height : borderRange,
borderRadius : borderRange/2,
borderWidth : size/10,
borderColor : "#F80404",
shadowColor : "#F40C1C",
shadowOffset : {width : 0, height : 0},
shadowOpacity : 1,
shadowRadius :10,
};
});
return (
<View style={{ justifyContent : 'center', alignItems :'center'}}>
<Animated.View style={[{backgroundColor : '#B40404', justifyContent : 'center', alignItems : 'center'}, breatheStyleSquare]}>
<Animated.Image source={require('../assets/icons/icon.png')} style={[{height: size, width : size, borderColor : '#fff',borderRadius : size/2}]}/>
</Animated.View>
{/* <Animated.View style={[ {backgroundColor : 'green'},breatheStyleSquare]}>
const progresse = useSharedValue(1);
useEffect(() => {
// withTiming, withSpring
progresse.value = withRepeat(withTiming(0.01, { duration: 750 }), -1, true);
}, [progresse]);
const breatheStyle = useAnimatedStyle(() => {
const borderRange = interpolate
(progresse.value,
[0, 1],
[(0 * size) / 2, (1 * size) / 2],
);
return {
justifyContent: 'center',
alignItems: 'center',
width: size,
height: size,
shadowColor: "#DA1D1D",
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 1,
shadowRadius: borderRange,
};
});
const breatheStyle2 = useAnimatedStyle(() => {
const borderRange = interpolate
(progresse.value,
[0, 1],
[(0 * size) / 2, (1 * size) / 2],
);
return {
borderRadius: borderRange,
};
});
const breatheStyleSquare = useAnimatedStyle(() => {
const borderRange = interpolate
(progresse.value,
[0, 1],
[(size + 20), (size)],
);
return {
width: borderRange,
height: borderRange,
borderRadius: borderRange / 2,
borderWidth: size / 10,
borderColor: "#F80404",
shadowColor: "#F40C1C",
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 1,
shadowRadius: 10,
};
});
return (
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Animated.View style={[{ backgroundColor: '#B40404', justifyContent: 'center', alignItems: 'center' }, breatheStyleSquare]}>
<Animated.Image source={require('../assets/icons/icon.png')} style={[{ height: size, width: size, borderColor: '#fff', borderRadius: size / 2 }]} />
</Animated.View>
{/* <Animated.View style={[ {backgroundColor : 'green'},breatheStyleSquare]}>
</Animated.View> */}
{/* <Image source={require('../assets/icons/Spotify_-_Animation_1.gif')}/> */}
</View>
);
};
{/* <Image source={require('../assets/icons/Spotify_-_Animation_1.gif')}/> */}
</View>
);
};
const styles = StyleSheet.create({
card : {
justifyContent : 'center',
alignItems : 'center',
card: {
justifyContent: 'center',
alignItems: 'center',
},
image : {
borderRadius : 24,
image: {
borderRadius: 24,
resizeMode: 'stretch',
},
container: {
},
container: {
flex: 1,
width: '100%',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}
}
})
export default FladLoading;

@ -0,0 +1,31 @@
import React from 'react';
import { View, Image, StyleSheet } from 'react-native';
import normalize from './Normalize';
type Flady = {
image: string | object;
};
export default function FladyComponent(monFlady: Flady) {
const source = typeof monFlady.image === 'string' ? { uri: monFlady.image } : monFlady.image;
return (
<View style={styles.container}>
<Image source={source} style={styles.image} />
</View>
)
}
const styles = StyleSheet.create({
container: {
width: normalize(152),
height: normalize(152),
borderRadius: 90,
marginHorizontal: normalize(15),
overflow: 'hidden',
},
image: {
width: normalize(220),
height: normalize(220),
marginLeft: -1
}
})

@ -5,52 +5,52 @@ import { Artist } from "./Artist";
import { StyleSheet } from "react-native";
export const ArtistLayout = () => {
const MUSIC_LIST : Music[] = [
new Music("La pharmacie", "Jul",require("../assets/images/jul.png")),
new Music("Deux frères", "PNL", require("../assets/images/pnl.png")),
new Music("Bambina", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
new Music("Stratos", "Kekra", "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png"),
new Music("Autobahn", "Sch", "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg"),
new Music("Freeze Raël", "Freeze Corleone", "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png"),
new Music("Blanka", "PNL", require("../assets/images/pnl.png")),
new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
]
const [artists, setArtists] = useState<Music[]>(MUSIC_LIST);
const [selectedArtists, setSelectedArtists] = useState<typeof MUSIC_LIST> ([]);
return (
<ScrollView contentContainerStyle={styles.container}>
{artists.map((artist, i) => (
<Artist
artist={artist}
key={artist.title}
onPress={() => {
// artists.splice(i, 1);
// // 2 implementation
const tmppArtist = new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png");
// const existingObjIndex = selectedArtists.findIndex(obj => obj.title === tmppArtist.title);
// if (existingObjIndex === -1) {
// selectedArtists.push(tmppArtist);
// } else {
// selectedArtists.splice(existingObjIndex, 1);
// }
// setSelectedArtists([...selectedArtists]);
// 1 implementation
// setSelectedArtists(selectedArtists.findIndex(obj => obj.title === tmppArtist.title) === -1
// ? [...selectedArtists, tmppArtist]
// : selectedArtists.filter(obj => obj.title !== tmppArtist.title))
// 3 implementations
// use the selectedProps of the Artist Component
// then when we need to finish
// onPress{ () => setSelectedArtists([...selectedArtists,artists.filter(artist => artist.selected)])}
artists.push(tmppArtist);
setArtists([...artists]);
}}
/>
))}
{/* <FlatList
const MUSIC_LIST: Music[] = [
new Music("La pharmacie", "Jul", require("../assets/images/jul.png")),
new Music("Deux frères", "PNL", require("../assets/images/pnl.png")),
new Music("Bambina", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
new Music("Stratos", "Kekra", "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png"),
new Music("Autobahn", "Sch", "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg"),
new Music("Freeze Raël", "Freeze Corleone", "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png"),
new Music("Blanka", "PNL", require("../assets/images/pnl.png")),
new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
]
const [artists, setArtists] = useState<Music[]>(MUSIC_LIST);
const [selectedArtists, setSelectedArtists] = useState<typeof MUSIC_LIST>([]);
return (
<ScrollView contentContainerStyle={styles.container}>
{artists.map((artist, i) => (
<Artist
artist={artist}
key={artist.title}
onPress={() => {
// artists.splice(i, 1);
// // 2 implementation
const tmppArtist = new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png");
// const existingObjIndex = selectedArtists.findIndex(obj => obj.title === tmppArtist.title);
// if (existingObjIndex === -1) {
// selectedArtists.push(tmppArtist);
// } else {
// selectedArtists.splice(existingObjIndex, 1);
// }
// setSelectedArtists([...selectedArtists]);
// 1 implementation
// setSelectedArtists(selectedArtists.findIndex(obj => obj.title === tmppArtist.title) === -1
// ? [...selectedArtists, tmppArtist]
// : selectedArtists.filter(obj => obj.title !== tmppArtist.title))
// 3 implementations
// use the selectedProps of the Artist Component
// then when we need to finish
// onPress{ () => setSelectedArtists([...selectedArtists,artists.filter(artist => artist.selected)])}
artists.push(tmppArtist);
setArtists([...artists]);
}}
/>
))}
{/* <FlatList
data={artists}
// need to reverse colums oreder
numColumns = {3}
@ -67,16 +67,16 @@ export const ArtistLayout = () => {
// ListEmptyComponent = {}
/> */}
</ScrollView>
</ScrollView>
);
};
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "row",
flexWrap: "wrap",
},
});
const styles = StyleSheet.create({
container: {
flexDirection: "row",
flexWrap: "wrap",
},
});

@ -2,31 +2,31 @@ import { useState } from 'react';
import { View, StyleSheet } from 'react-native'
interface HalfCirlceProps {
backgroundColor : string;
backgroundColor: string;
}
const HalfCirlce = ({backgroundColor} : HalfCirlceProps) => {
const [focused, setFocused] = useState<boolean>(false);
return (
<View style={{
width : RADUIS* 2,
height : RADUIS* 2,
overflow : "hidden",
const HalfCirlce = ({ backgroundColor }: HalfCirlceProps) => {
const [focused, setFocused] = useState<boolean>(false);
}}>
<View style={{backgroundColor : backgroundColor, width : RADUIS* 2, height : RADUIS * 2, borderRadius : RADUIS, }}>
return (
<View style={{
width: RADUIS * 2,
height: RADUIS * 2,
overflow: "hidden",
}}>
<View style={{ backgroundColor: backgroundColor, width: RADUIS * 2, height: RADUIS * 2, borderRadius: RADUIS, }}>
</View>
</View>
);
};
</View>
</View>
);
};
const styles = StyleSheet.create({
input : {
justifyContent : 'center',
alignItems : 'center',
placeholder : "placeholde"
input: {
justifyContent: 'center',
alignItems: 'center',
placeholder: "placeholde"
},
})

@ -1,11 +1,11 @@
import { View, StyleSheet, Dimensions,Text, Image, Pressable, TouchableWithoutFeedback, TouchableOpacity, TouchableHighlight, FlatList } from "react-native";
import { View, StyleSheet, Dimensions, Text, Image, Pressable, TouchableWithoutFeedback, TouchableOpacity, TouchableHighlight, FlatList } from "react-native";
import Animated, {
Layout,
Transition,
ZoomIn,
ZoomOut,
} from "react-native-reanimated";
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";
@ -16,35 +16,35 @@ import { RenderCellProps } from "./littleCard";
interface HorizontalFlatListProps {
// React.ReactNode;
children:(props: RenderCellProps) => React.ReactElement
title : string;
data : any[];
}
export const HorizontalFlatList = ({ title, data, children : RenderCell }: HorizontalFlatListProps) => {
// React.ReactNode;
children: (props: RenderCellProps) => React.ReactElement
title: string;
data: any[];
}
export const HorizontalFlatList = ({ title, data, children: 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 }) => RenderCell(item)}/></View>
);
};
const styles = StyleSheet.create({
similarSection: {
paddingTop: 16
},
similarTitle: {
color: "#FFF",
paddingLeft: 8,
fontSize: 24,
fontWeight: "600",
paddingBottom: 16
}
});
return (
<View style={styles.similarSection}>
<Text style={styles.similarTitle} >{title}</Text>
<FlatList
showsHorizontalScrollIndicator={false}
data={data}
horizontal={true}
keyExtractor={item => item.id}
renderItem={({ item }) => RenderCell(item)} /></View>
);
};
const styles = StyleSheet.create({
similarSection: {
paddingTop: 16
},
similarTitle: {
color: "#FFF",
paddingLeft: 8,
fontSize: 24,
fontWeight: "600",
paddingBottom: 16
}
});

@ -1,12 +1,15 @@
import React, { useRef, useEffect } from 'react';
import { View, StyleSheet, TouchableOpacity , Animated } from 'react-native';
import { View, StyleSheet, TouchableOpacity, Animated, useColorScheme } from 'react-native';
import Svg, { G, Circle } from 'react-native-svg';
import { AntDesign } from '@expo/vector-icons';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
import normalize from '../components/Normalize';
// @ts-ignore
export default function NextButton({ percentage, scrollTo }) {
const style = useColorScheme() == 'light' ? GraphicalCharterLight : GraphicalCharterDark;
const size = normalize(148);
const strokeWidth = 2;
const center = size / 2;
@ -40,7 +43,7 @@ export default function NextButton({ percentage, scrollTo }) {
});
}
},
},
// @ts-ignore
[percentage]
@ -56,11 +59,11 @@ export default function NextButton({ percentage, scrollTo }) {
<View style={styles.container}>
<Svg width={size} height={size}>
<G rotation="-90" origin={center}>
<Circle stroke="#E6E7E8" fill="#141414" cx={center} cy={center} r={radius} strokeWidth={strokeWidth}/>
<Circle stroke={style.Text} cx={center} cy={center} r={radius} strokeWidth={strokeWidth} />
<Circle
ref={progressRef}
stroke="#F80404"
fill="#141414"
fill={style.body}
cx={center}
cy={center}
r={radius}

@ -9,7 +9,7 @@ const scale = SCREEN_WIDTH / 480;
// @ts-ignore
export default function normalize(size) {
const newSize = size * scale
const newSize = size * scale
if (Platform.OS === 'ios') {
return Math.round(PixelRatio.roundToNearestPixel(newSize))
} else {

@ -1,15 +1,17 @@
import React, { useState, useRef } from 'react';
import { Modal, View, StyleSheet, Text, FlatList, Animated, TouchableOpacity, ImageBackground, Image } from 'react-native';
import { Modal, View, StyleSheet, useColorScheme, Text, FlatList, Animated, TouchableOpacity, ImageBackground, Image } from 'react-native';
// import Modal from "react-native-modal";
import {useNavigation} from "@react-navigation/native";
import { useNavigation } from "@react-navigation/native";
import normalize from '../components/Normalize';
import OnboardingItem from './OnboardingItem';
import Paginator from './Paginator';
import NextButton from './NextButton';
import slides from '../data/slides';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
export default function Onboarding() {
const style = useColorScheme() == 'light' ? GraphicalCharterLight : GraphicalCharterDark;
const [currentIndex, setCurrentIndex] = useState(0);
const scrollX = useRef(new Animated.Value(0)).current;
const slidesRef = useRef(null);
@ -26,7 +28,7 @@ export default function Onboarding() {
const viewConfig = useRef({ viewAreaCoveragePercentThreshold: 50 }).current;
const scrollTo = () => {
if(currentIndex < slides.length - 1) {
if (currentIndex < slides.length - 1) {
// @ts-ignore
slidesRef.current.scrollToIndex({ index: currentIndex + 1 });
} else {
@ -34,13 +36,119 @@ export default function Onboarding() {
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: style.body
},
imageLogo: {
width: normalize(324),
height: normalize(162),
marginBottom: '25%'
},
balise: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginBottom: normalize(110)
},
closeButtonCircle: {
backgroundColor: 'gray',
opacity: 0.4,
width: 40,
height: 40,
borderRadius: 20,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
top: 10,
right: 10
},
modalContent: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
modalView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
backgroundImage: {
flex: 1,
width: '100%',
height: '100%',
},
imageButton: {
width: 20,
height: 20
},
versionText: {
position: 'absolute',
top: 50,
right: 10,
color: 'gray',
fontWeight: 'bold',
fontSize: normalize(17)
},
buttonConnection: {
width: 262,
height: 57,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#24CF5F',
borderRadius: 11,
borderColor: '#68F097',
borderWidth: 1,
marginBottom: 12
},
buttonInscription: {
width: 262,
height: 57,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#DA1D1D',
borderRadius: 11,
borderColor: '#F40C1C',
borderWidth: 1,
marginBottom: 220
},
text: {
fontWeight: 'bold',
color: 'white',
fontSize: normalize(18)
},
button2Connection: {
width: '100%',
height: normalize(92),
backgroundColor: '#232123',
borderTopColor: '#3C3C3C',
borderTopWidth: 1,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
bottom: normalize(0)
},
mascot: {
width: normalize(130),
height: normalize(130),
position: 'absolute',
bottom: normalize(90),
right: normalize(0)
}
})
return (
// @ts-ignore
<View style={styles.container}>
<View style={styles.balise}>
<FlatList
data={slides}
renderItem={({item}) => <OnboardingItem item={item} />}
<FlatList
data={slides}
renderItem={({ item }) => <OnboardingItem item={item} />}
horizontal
showsHorizontalScrollIndicator={false}
pagingEnabled
@ -50,12 +158,12 @@ export default function Onboarding() {
useNativeDriver: false,
})}
scrollEventThrottle={32}
onViewableItemsChanged={viewableItemsChanged}
onViewableItemsChanged={viewableItemsChanged}
viewabilityConfig={viewConfig}
ref={slidesRef}
/>
<Paginator data={slides} scrollX={scrollX}/>
<NextButton scrollTo={scrollTo} percentage={(currentIndex + 1) * (100 / slides.length)} />
/>
<Paginator data={slides} scrollX={scrollX} />
<NextButton scrollTo={scrollTo} percentage={(currentIndex + 1) * (100 / slides.length)} />
</View>
<Modal animationType="slide" visible={isModalVisible} transparent={true} presentationStyle={'pageSheet'}>
<View style={styles.modalContent}>
@ -66,23 +174,24 @@ export default function Onboarding() {
</Text>
<TouchableOpacity onPress={handleModal} style={styles.closeButtonCircle}>
<View>
<Image source={require("../assets/icons/icons/croix.png")} style={styles.imageButton}/>
<Image source={require("../assets/icons/icons/croix.png")} style={styles.imageButton} />
</View>
</TouchableOpacity>
<Image source={require("../assets/icons/Logo_White_Flad.png")} style={styles.imageLogo}/>
<TouchableOpacity
style={styles.buttonConnection}
onPress={() => {handleModal();
// @ts-ignore
navigation.navigate('Login');
}}>
<Image source={require("../assets/icons/Logo_White_Flad.png")} style={styles.imageLogo} />
<TouchableOpacity
style={styles.buttonConnection}
onPress={() => {
handleModal();
// @ts-ignore
navigation.navigate('Login');
}}>
<Text style={styles.text}>CONTINUER AVEC SPOTIFY</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonInscription} onPress={() => {handleModal(); navigation.navigate('Register');}}>
<TouchableOpacity style={styles.buttonInscription} onPress={() => { handleModal(); navigation.navigate('Register'); }}>
<Text style={styles.text}>SINSCRIRE MAINTENANT</Text>
</TouchableOpacity>
<Image source={require("../assets/images/Flady.gif")} style={styles.mascot}/>
<TouchableOpacity style={styles.button2Connection} onPress={() => {handleModal(); navigation.navigate('Login');}}>
<Image source={require("../assets/images/Flady.gif")} style={styles.mascot} />
<TouchableOpacity style={styles.button2Connection} onPress={() => { handleModal(); navigation.navigate('Login'); }}>
<Text style={styles.text}>SE CONNECTER</Text>
</TouchableOpacity>
</View>
@ -92,108 +201,3 @@ export default function Onboarding() {
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#141414'
},
imageLogo: {
width: normalize(324),
height: normalize(162),
marginBottom: '25%'
},
balise: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginBottom: normalize(110)
},
closeButtonCircle: {
backgroundColor: 'gray',
opacity: 0.4,
width: 40,
height: 40,
borderRadius: 20,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
top: 10,
right: 10
},
modalContent: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
modalView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
backgroundImage: {
flex: 1,
width: '100%',
height: '100%',
},
imageButton: {
width: 20,
height: 20
},
versionText: {
position: 'absolute',
top: 50,
right: 10,
color: 'gray',
fontWeight: 'bold',
fontSize: normalize(17)
},
buttonConnection: {
width: 262,
height: 57,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#24CF5F',
borderRadius: 11,
borderColor: '#68F097',
borderWidth: 1,
marginBottom: 12
},
buttonInscription: {
width: 262,
height: 57,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#DA1D1D',
borderRadius: 11,
borderColor: '#F40C1C',
borderWidth: 1,
marginBottom: 220
},
text: {
fontWeight: 'bold',
color: 'white',
fontSize: normalize(18)
},
button2Connection: {
width: '100%',
height: normalize(92),
backgroundColor: '#232123',
borderTopColor: '#3C3C3C',
borderTopWidth: 1,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
bottom: normalize(0)
},
mascot: {
width: normalize(130),
height: normalize(130),
position: 'absolute',
bottom: normalize(90),
right: normalize(0)
}
})

@ -1,11 +1,43 @@
import React from 'react';
import { View, StyleSheet, Text, Image, useWindowDimensions } from 'react-native';
import { View, StyleSheet, Text, Image, useWindowDimensions, useColorScheme } from 'react-native';
import normalize from '../components/Normalize';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
// @ts-ignore
export default function Onboarding({ item }) {
const style = useColorScheme() == 'light' ? GraphicalCharterLight : GraphicalCharterDark;
const { width, height } = useWindowDimensions();
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: normalize(60),
backgroundColor: style.body
},
image: {
width: '100%',
height: '100%',
justifyContent: 'center'
},
title: {
fontWeight: '800',
fontSize: normalize(32),
marginBottom: 10,
color: style.Text,
textAlign: 'left',
paddingRight: 30,
paddingLeft: 20,
marginTop: normalize(30)
},
description: {
fontWeight: '300',
color: style.Text,
fontSize: normalize(16),
textAlign: 'left',
paddingRight: 30,
paddingLeft: 20
}
})
return (
<View style={[styles.container, { width, height }]}>
<View style={{ overflow: 'hidden', height: height * 0.5 }}>
@ -17,33 +49,3 @@ export default function Onboarding({ item }) {
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: normalize(60),
backgroundColor: '#141414'
},
image: {
width: '100%',
height: '100%',
justifyContent: 'center'
},
title: {
fontWeight: '800',
fontSize: normalize(32),
marginBottom: 10,
color: 'white',
textAlign: 'left',
paddingRight: 30,
paddingLeft: 20,
marginTop: normalize(30)
},
description: {
fontWeight: '300',
color: 'white',
fontSize: normalize(16),
textAlign: 'left',
paddingRight: 30,
paddingLeft: 20
}
})

@ -7,7 +7,7 @@ export default function Paginator({ data, scrollX }) {
const { width } = useWindowDimensions();
return (
<View style={{flexDirection: 'row', height: 64, marginBottom: normalize(50)}}>
<View style={{ flexDirection: 'row', height: 64, marginBottom: normalize(50) }}>
{data.map((_, i) => {
const inputRange = [(i - 1) * width, i * width, (i + 1) * width];
@ -23,14 +23,14 @@ export default function Paginator({ data, scrollX }) {
extrapolate: 'clamp'
})
return <Animated.View
return <Animated.View
style={[
styles.dot,
{
styles.dot,
{
width: dotWidth,
opacity,
}
]}
]}
key={i.toString()}
/>
})}

@ -1,11 +1,11 @@
import { View, StyleSheet, Dimensions, Image, Pressable, TouchableWithoutFeedback, TouchableOpacity, TouchableHighlight } from "react-native";
import Animated, {
Layout,
Transition,
ZoomIn,
ZoomOut,
} from "react-native-reanimated";
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";
@ -15,60 +15,60 @@ 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();
};
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)}
>
return (
<TouchableOpacity onPress={onS}>
<Animated.View
style={styles.container}
entering={ZoomIn}
exiting={ZoomOut}
layout={Layout.delay(200)}
>
<View style={styles.card}>
{ selected && (
{selected && (
<View style={styles.cheked}>
<Icon name="check-circle" color="black" size={24} />
<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",
</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",
}
});
}
});

@ -1,29 +1,29 @@
import { useState } from 'react';
import { View, Text, Image, Animated ,PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, TextInput } from 'react-native'
import { View, Text, Image, Animated, PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, TextInput } from 'react-native'
interface InputProps {
name : string;
placeholder : string;
name: string;
placeholder: string;
}
const FladInput = ({name, placeholder} : InputProps) => {
const [focused, setFocused] = useState<boolean>(false);
return (
<View>
<Text></Text>
<TextInput style={[styles.input]}>
const FladInput = ({ name, placeholder }: InputProps) => {
const [focused, setFocused] = useState<boolean>(false);
return (
<View>
<Text></Text>
<TextInput style={[styles.input]}>
</TextInput>
</View>
);
};
</TextInput>
</View>
);
};
const styles = StyleSheet.create({
input : {
justifyContent : 'center',
alignItems : 'center',
placeholder : "placeholde"
input: {
justifyContent: 'center',
alignItems: 'center',
placeholder: "placeholde"
},
})

@ -1,17 +1,17 @@
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 {
image: string;
title: string;
}
export const LittleCard = (props : RenderCellProps)=>{
console.log('==============='+ props.image + props.title+ '==ok============');
}
export const LittleCard = (props: RenderCellProps) => {
console.log('===============' + props.image + props.title + '==ok============');
return (
<View style={styles.similarContainer}>
<Image source={{uri: props.image}} style={styles.similarPoster}></Image>
<Text numberOfLines={2} style={styles.similarTitleFilm}>{props.title}
</Text>
</View>
<View style={styles.similarContainer}>
<Image source={{ uri: props.image }} style={styles.similarPoster}></Image>
<Text numberOfLines={2} style={styles.similarTitleFilm}>{props.title}
</Text>
</View>
)
}

@ -1,46 +1,46 @@
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
export const cards = [{
name: "blue",
sourceUrl: "https://th.bing.com/th/id/R.dbf87f0d8cbfd078ab6a589a5d921994?rik=1%2f6KliMpOAeh8A&pid=ImgRaw&r=0",
index: 4
},
{
musicName : "Breathin",
name : "Ariana Grande",
sourceUrl : "https://i.ebayimg.com/images/g/rY0AAOSw97djEo2C/s-l500.jpg",
index : 9
musicName: "Breathin",
name: "Ariana Grande",
sourceUrl: "https://i.ebayimg.com/images/g/rY0AAOSw97djEo2C/s-l500.jpg",
index: 9
},
{
musicName : "Zombies",
name : "gambino",
sourceUrl : "https://th.bing.com/th/id/R.0b2d1a59bfda9b1a49ecb561e08535a8?rik=Xyc35OZU%2f6VOVw&pid=ImgRaw&r=0",
index : 3
musicName: "Zombies",
name: "gambino",
sourceUrl: "https://th.bing.com/th/id/R.0b2d1a59bfda9b1a49ecb561e08535a8?rik=Xyc35OZU%2f6VOVw&pid=ImgRaw&r=0",
index: 3
},
{
musicName : "Bambina",
name : "PNL",
sourceUrl : "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png",
index : 10
musicName: "Bambina",
name: "PNL",
sourceUrl: "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png",
index: 10
},
{
musicName : "Freeze Raël",
name : "Freeze Corleone",
sourceUrl : "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png",
index : 23
musicName: "Freeze Raël",
name: "Freeze Corleone",
sourceUrl: "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png",
index: 23
},
{
musicName : "Autobahn",
name : "Sch",
sourceUrl : "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg",
index : 44
musicName: "Autobahn",
name: "Sch",
sourceUrl: "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg",
index: 44
},
{
musicName : "Lakehouse",
name : "Stratos",
sourceUrl : "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png",
index : 89
musicName: "Lakehouse",
name: "Stratos",
sourceUrl: "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png",
index: 89
},
]

@ -1,20 +1,20 @@
export default [
{
id: '1',
title: 'Bienvenue sur Flad',
description: 'L\'application pour découvrir de nouvelles musiques et vous faire de nouveaux amis',
image: require('../assets/images/Board_Image.png')
id: '1',
title: 'Bienvenue sur Flad',
description: 'L\'application pour découvrir de nouvelles musiques et vous faire de nouveaux amis',
image: require('../assets/images/Board_Image.png')
},
{
id: '2',
title: 'Tous les jours de nouvelles musiques qui peuvent vous plaire',
description: 'L\'application apprends de vous et de vos amis pour vous suggérer des albums et des musics',
image: require('../assets/images/Board_Image2.png')
id: '2',
title: 'Tous les jours de nouvelles musiques qui peuvent vous plaire',
description: 'L\'application apprends de vous et de vos amis pour vous suggérer des albums et des musics',
image: require('../assets/images/Board_Image2.png')
},
{
id: '3',
title: 'La musique ça se partage',
description: 'Faites connaissances avec de nouvelles personnes et partagez vos critiques',
image: require('../assets/images/Board_Image3.png')
id: '3',
title: 'La musique ça se partage',
description: 'Faites connaissances avec de nouvelles personnes et partagez vos critiques',
image: require('../assets/images/Board_Image3.png')
}
]

@ -1,11 +1,11 @@
export default class Music {
private _id : string;
private _id: string;
private _title: string;
private _bio: string;
private _image: string;
private _trackPreviewUrl : string;
private _trackPreviewUrl: string;
constructor(id : string,title: string, bio: string, image: string, trackPreviewUrl: string) {
constructor(id: string, title: string, bio: string, image: string, trackPreviewUrl: string) {
this._title = title;
this._bio = bio;
this._image = image;

@ -1,5 +1,5 @@
import Navigation from './Navigation';
import { StyleSheet,SafeAreaView } from 'react-native';
import { StyleSheet, SafeAreaView } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import StartNavigation from './StartNavigation';
import { Provider, useDispatch, useSelector } from 'react-redux';
@ -13,10 +13,12 @@ import * as Location from 'expo-location';
// const LOCATION_TASK_NAME = 'flad-background-location-task';
export default function AuthNavigation() {
//@ts-ignore
const tokenProcesed : boolean = useSelector(state => state.userReducer.loading);
//@ts-ignore
const isLogin : boolean = useSelector(state => state.userReducer.isLogedIn);
const tokenProcesed: boolean = useSelector(state => state.userReducer.loading);
// //@ts-ignore
// const appIsReady: boolean = useSelector(state => state.userReducer.loading);
//@ts-ignore
const isLogin: boolean = useSelector(state => state.userReducer.isLogedIn);
// const userToken : string = useSelector(state => state.userReducer.userFladToken);
const [appIsReady, setAppIsReady] = useState(false);
const dispatch = useDispatch();
@ -25,18 +27,18 @@ export default function AuthNavigation() {
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);
// }
// });
// // 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, {
@ -62,17 +64,17 @@ export default function AuthNavigation() {
useEffect(() => {
async function prepare() {
//@ts-ignore
//@ts-ignore
await dispatch(getRefreshToken())
if (tokenProcesed && appIsReady ) {
if (tokenProcesed && appIsReady) {
await SplashScreen.hideAsync();
} // await SplashScreen.hideAsync();
}
prepare();
}, [appIsReady,tokenProcesed]);
}, [appIsReady, tokenProcesed]);
// const onStackRootView = useCallback(async () => {
// }, [appIsReady]);
// useEffect(() => {
// const sendLocationUpdate = async () => {
@ -89,7 +91,7 @@ export default function AuthNavigation() {
// // send location to server
// console.log(locationresp);
// if(locationresp !=location ){
// }
// console.log(location);
// }
@ -113,21 +115,16 @@ export default function AuthNavigation() {
}
// console.log(userToken, "k9 AuthNav")
return (
<>
{isLogin ? (
/* {userToken != null ? ( */
// should set the reference to the function in Navigation to realy perform an on ready
// test purpose
<SafeAreaProvider onLayout={()=>setAppIsReady(true)}>
<Navigation/>
</SafeAreaProvider>
) :
<SafeAreaProvider onLayout={()=>setAppIsReady(true)}>
<StartNavigation />
</SafeAreaProvider>
}
</>
)
}
return (
<SafeAreaProvider onLayout={() => setAppIsReady(true)}>
{isLogin ? (
/* {userToken != null ? ( */
// should set the reference to the function in Navigation to realy perform an on ready
// test purpose
<Navigation />
) :
<StartNavigation />
}
</SafeAreaProvider>
)
}

@ -9,22 +9,22 @@ import CurrentMusic from '../components/CurrentMusic';
const Stack = createSharedElementStackNavigator();
export default function MusicNavigation() {
return (
<Stack.Navigator initialRouteName="Favorite" screenOptions={{gestureEnabled: true, headerShown: false, cardOverlayEnabled: true, cardStyle: {backgroundColor: "transparent"}}} >
<Stack.Screen
name="Favorite"
component={Favorite}
/>
<Stack.Screen
name="MusicDetail"
component={MusicDetail}
sharedElements ={(route)=> {return [route.params.music.id]}}
/>
<Stack.Screen
name="Genre"
component={CurrentMusic}
/>
</Stack.Navigator>
)
}
return (
<Stack.Navigator initialRouteName="Favorite" screenOptions={{ gestureEnabled: true, headerShown: false, cardOverlayEnabled: true, cardStyle: { backgroundColor: "transparent" } }} >
<Stack.Screen
name="Favorite"
component={Favorite}
/>
<Stack.Screen
name="MusicDetail"
component={MusicDetail}
sharedElements={(route) => { return [route.params.music.id] }}
/>
<Stack.Screen
name="Genre"
component={CurrentMusic}
/>
</Stack.Navigator>
)
}

@ -13,88 +13,100 @@ import Login from '../screens/login';
import FladLoading from '../components/FladLoadingScreen';
import { useDispatch, useSelector } from 'react-redux';
import { getFavoritesMusic } from '../redux/actions/appActions';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
import { getCurrentUserMusic } from '../redux/thunk/spotThunk';
import SpotifyService from '../services/spotify/spotify.service';
// import { fetchFavoritesMusic } from '../redux/thunk/spotThunk';
export default function Navigation() {
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? GraphicalCharterLight : GraphicalCharterDark;
const BottomTabNavigator = createBottomTabNavigator();
const MyTheme = {
dark: false,
colors: {
primary: 'rgb(255, 45, 85)',
card: 'rgb(35, 33, 35)',
border: 'rgb(35, 33, 35)',
card: style.Card,
border: style.Card,
text: 'rgb(138, 138, 138)',
}
};
//@ts-ignore
const favoritesMusicLength : number = useSelector(state => state.appReducer.favoriteMusic.length);
// const dispatch = useDispatch();
const favoritesMusicLength: number = useSelector(state => state.appReducer.favoriteMusic.length);
const dispatch = useDispatch();
// useEffect(() => {
// const loadFavoritesMusics = async () => {
// await dispatch(fetchFavoritesMusic());
// };
// loadFavoritesMusics();
// }, [dispatch]);
return (
// @ts-ignore
<NavigationContainer theme={MyTheme}>
<BottomTabNavigator.Navigator
initialRouteName="Spots"
screenOptions={{
//tabBarShowLabel: false, //to remove the titles under the icons
tabBarStyle: styles.tabBar,
...(Platform.OS === 'android'
? { tabBarLabelStyle: { bottom: normalize(10) } }
: { tabBarLabelStyle: { bottom: normalize(-22) } }
),
const token = "BQBNdaYRkD3GAOFASk8uc-l72zVwQeQ0sFB4GJnkBGudsJHnuAXd4eIWb78gbFLKZeBoHrWpHxMeSmqvHk75Utg9fsOJp7XyJfm-tAlgGhUQ-xiUM8rXTpa9k3M40BMSnujPDrap_O1ChCyGhBWYVHDd2t67qY0NVDvCJ4Qz7LucJJdgu1BN838qXTScQV90zriO8lp6Rjx6SsWov_fMZTyadzxebYIiQ-VDQDs63gUordThas-jFlAHLgJlqPhVOHJ1WaZt-_oLhgY3fk4bhORkyeAFZVRTnjw38A70b0eZU3ziQkOYW6w7kN__tzgP5gis0Y8mEIiUyTnyuQ"
const sheet = async () => {
const service = new SpotifyService(token)
dispatch(getCurrentUserMusic(service))
}
}}>
<BottomTabNavigator.Screen name="Spots" component={SpotNavigation}
options={{
headerShown: false,
tabBarIcon: ({color}) => <View style={styles.IconContainer}><TabBarIcon name="music" color={color}/></View>,
}}/>
<BottomTabNavigator.Screen name="Favorites" component={FavoriteNavigation}
options={{
// use Selector state redux badgeCount ? badgeCount : undefined
useEffect(() => {
sheet()
}, []);
return (
// @ts-ignore
<NavigationContainer theme={MyTheme}>
<BottomTabNavigator.Navigator
initialRouteName="Spots"
screenOptions={{
tabBarStyle: styles.tabBar,
...(Platform.OS === 'android'
? { tabBarLabelStyle: { bottom: normalize(10) } }
: { tabBarLabelStyle: { bottom: normalize(-22) } }
),
tabBarBadge : favoritesMusicLength,
tabBarBadgeStyle : {backgroundColor : 'yellow'},
headerShown: false,
tabBarIcon: ({color}) => <View style={styles.IconContainer}><TabBarIcon name="heart" color={color}/></View>,
}}/>
<BottomTabNavigator.Screen name="Messages" component={Login}
options={{
headerShown: false,
tabBarIcon: ({color}) => <View style={styles.IconContainer}><TabBarIcon name="comment" color={color}/></View>,
}}/>
<BottomTabNavigator.Screen name="Setting" component={SettingNavigation}
options={{
headerShown: false,
tabBarIcon: ({color}) => <View style={styles.IconContainer}><TabBarIcon name="cog" color={color}/></View>,
}}/>
</BottomTabNavigator.Navigator>
</NavigationContainer>
}}>
<BottomTabNavigator.Screen name="Spots" component={SpotNavigation}
options={{
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="music" color={color} /></View>,
}} />
<BottomTabNavigator.Screen name="Favorites" component={FavoriteNavigation}
options={{
tabBarBadge: favoritesMusicLength,
tabBarBadgeStyle: { backgroundColor: 'yellow' },
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="heart" color={color} /></View>,
}} />
<BottomTabNavigator.Screen name="Messages" component={Login}
options={{
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="comment" color={color} /></View>,
}} />
<BottomTabNavigator.Screen name="Setting" component={SettingNavigation}
options={{
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="cog" color={color} /></View>,
}} />
</BottomTabNavigator.Navigator>
</NavigationContainer>
)
}
function TabBarIcon(props: {
name: React.ComponentProps<typeof FontAwesome>['name'];
color: string;
name: React.ComponentProps<typeof FontAwesome>['name'];
color: string;
}) {
return <FontAwesome size={30} {...props} />;
return <FontAwesome size={30} {...props} />;
}
const styles = StyleSheet.create({
tabBar: {
height: 60,
position: 'absolute',
bottom: normalize(50),
borderRadius: 30,
height: 60,
position: 'absolute',
bottom: normalize(50),
borderRadius: 30,
marginHorizontal: 25
},
IconContainer: {
position: 'absolute',
top: 5,
position: 'absolute',
top: 5,
}
})

@ -4,19 +4,19 @@ import SettingProfil from '../screens/SettingProfil';
import { createStackNavigator } from '@react-navigation/stack';
export default function SettingNavigation() {
const Stack = createStackNavigator();
return (
<Stack.Navigator initialRouteName="Setting">
<Stack.Screen
name="Setting"
component={Setting}
options={{ headerShown: false }}
/>
<Stack.Screen
name="SettingProfil"
component={SettingProfil}
options={{ headerShown: false }}
/>
</Stack.Navigator>
)
}
const Stack = createStackNavigator();
return (
<Stack.Navigator initialRouteName="Setting">
<Stack.Screen
name="Setting"
component={Setting}
options={{ headerShown: false }}
/>
<Stack.Screen
name="SettingProfil"
component={SettingProfil}
options={{ headerShown: false }}
/>
</Stack.Navigator>
)
}

@ -1,4 +1,4 @@
import React, {Component} from 'react';
import React, { Component } from 'react';
import FavoritePage from '../screens/favorite';
import { createStackNavigator } from '@react-navigation/stack';
import SpotPage from '../screens/spot'
@ -8,32 +8,32 @@ import MusicDetail from '../screens/MusicDetail';
export default function SpotNavigation() {
// const Stack = createSharedElementStackNavigator();
const Stack = createStackNavigator();
// const Stack = createSharedElementStackNavigator();
const Stack = createStackNavigator();
return (
<Stack.Navigator screenOptions={{
gestureEnabled: false,
headerShown: false,
cardOverlayEnabled: true,
}}
>
<Stack.Screen
name="Spots"
component={SpotPage}
/>
<Stack.Screen
name="DetailsSpot"
component={MusicDetail}
/>
{/* <Stack.Screen
return (
<Stack.Navigator screenOptions={{
gestureEnabled: false,
headerShown: false,
cardOverlayEnabled: true,
}}
>
<Stack.Screen
name="Spots"
component={SpotPage}
/>
<Stack.Screen
name="DetailsSpot"
component={MusicDetail}
/>
{/* <Stack.Screen
name="DetailsSpot"
component={SpotDetailsPage}
sharedElements={(route) => {
return [route.params.spot.name]
}}
/> */}
</Stack.Navigator>
)
}
</Stack.Navigator>
)
}

@ -4,7 +4,7 @@ import Register from '../screens/Register';
import Onboarding from '../components/Onboarding';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';
import {useDispatch, useSelector} from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import * as SplashScreen from 'expo-splash-screen';
import { getRefreshToken } from '../redux/thunk/authThunk';
import { ArtistLayout } from '../components/Genre';
@ -31,27 +31,27 @@ export default function StartNavigation() {
// if (!appIsReady) {
// return null;
// }
const Stack = createStackNavigator();
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Onboarding}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Login"
component={Login}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Register"
component={Register}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
const Stack = createStackNavigator();
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Onboarding}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Login"
component={Login}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Register"
component={Register}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
)
}

@ -44,4 +44,9 @@ export const userSignUp = (user : User) => {
type: userTypes.USER_LOGOUT,
};
}
export const userChangeMode = () => {
return {
type: userTypes.CHANGE_MODE,
};
}

@ -5,32 +5,32 @@ import { favoritesTypes } from "../types/favoritesTypes";
import { spotifyTypes } from "../types/spotifyTypes";
import { spotTypes } from "../types/spotTypes";
let tmpMusic: Music[] = [
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("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("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("5GFHFEASZeJF0gyWuDDjGE", "Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png", "https://p.scdn.co/mp3-preview/9e854f4905c1228482e390169eb76d8520076b8f?cid=774b29d4f13844c495f206cafdad9c86"),
];
const initialState = {
spot: [] as Spot[],
favoriteMusic: tmpMusic,
userCurrentMusic : null
userCurrentMusic: null
}
const appReducer = (state = initialState, action : any) => {
const appReducer = (state = initialState, action: any) => {
switch (action.type) {
case favoritesTypes.GET_FAVORITE_MUSICS:
return {...state, favoriteMusic: action.playload};
case favoritesTypes.ADD_FAVORITE_MUSICS:
return {...state, favoriteMusic: [action.playload, ...state.favoriteMusic]};
case favoritesTypes.REMOVE_FAVORITE_MUSICS:
return {...state, favoriteMusic: state.favoriteMusic};
case spotTypes.FETCH_SPOT:
return {...state, spot: action.payload};
case discoveriesTypes.FETCH_DISCOVERIES:
return;
case spotifyTypes.GET_USER_CURRENT_MUSIC:
return {...state, userCurrentMusic: action.payload};
default:
return state;
case favoritesTypes.GET_FAVORITE_MUSICS:
return { ...state, favoriteMusic: action.playload };
case favoritesTypes.ADD_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 };
case discoveriesTypes.FETCH_DISCOVERIES:
return;
case spotifyTypes.GET_USER_CURRENT_MUSIC:
return { ...state, userCurrentMusic: action.playload };
default:
return state;
}
}

@ -1,18 +0,0 @@
Uri getApiUrlAuthorize() => _api.identification.urlAuthorize;
String getApiRedirectUrl() => _api.identification.redirectUri;
String getIdSpotify() => _currentUser.idSpotify;
String getIdFlad() => _currentUser.idFlad;
case getCompleteMusic
playTrack(String id)
case addToPlaylist:
return {...state, spot: action.payload}
case removeFromPlaylist:

@ -4,56 +4,60 @@ const initialState = {
loading: false,
user: User, // for user object
userFladToken: "", // for storing the JWT
userSpotifyToken : null,
userSpotifyToken: null,
error: null,
isLogedIn: false,
}
const userReducer = (state = initialState, action : any) => {
switch (action.type) {
// just for the navigation and speciafly use
// and
case userTypes.RESTORE_TOKEN:
const resp = (action.playload == "" ? false : true)
console.log(resp, "si il ya le tokennen ou passssssssssss")
return {
...state,
userFladToken : action.playload,
loading: true,
isLogedIn: resp,
};
case userTypes.LOGIN:
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
console.log(action.playload, "LOOGGIIINN");
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
return {
...state,
user :action.playload,
isLogedIn: true
};
case userTypes.SIGNUP:
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
dark: false,
}
console.log(action.playload, "LOOGGIIINN");
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
const userReducer = (state = initialState, action: any) => {
switch (action.type) {
// just for the navigation and speciafly use
// and
case userTypes.RESTORE_TOKEN:
const resp = (action.playload == "" ? false : true)
console.log(resp, "si il ya le tokennen ou passssssssssss")
return {
...state,
userFladToken: action.playload,
loading: true,
isLogedIn: resp,
};
case userTypes.LOGIN:
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
console.log(action.playload, "LOOGGIIINN");
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
return {
...state,
user: action.playload,
isLogedIn: true
};
case userTypes.SIGNUP:
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
console.log(action.playload, "LOOGGIIINN");
console.log("++++++++++++++++++++++++++++++++++++++userRducer+++++++++++++++++++++++++++++3");
return {
...state,
user: action.playload,
isLogedIn: true
};
case userTypes.USER_LOGOUT:
return {
...state,
user: null,
isLogedIn: false
}
case userTypes.SAVE_SPOTIFY:
return {
...state,
user :action.playload,
isLogedIn: true
userSpotifyToken: action.playload,
};
case userTypes.USER_LOGOUT:
return {...state,
user :null,
isLogedIn: false }
case userTypes.SAVE_SPOTIFY:
return {
...state,
userSpotifyToken : action.playload,
};
default:
return state;
}
case userTypes.CHANGE_MODE:
return { ...state, dark: !state.dark }
default:
return state;
}
export default userReducer
}
export default userReducer

@ -1,4 +1,4 @@
import {configureStore} from '@reduxjs/toolkit'
import { configureStore } from '@reduxjs/toolkit'
import appReducer from './reducers/appReducer';
import userReducer from './reducers/userReducer';
@ -9,7 +9,7 @@ const reducer = {
}
const store = configureStore({
reducer : reducer,
reducer: reducer,
},);
export default store;

@ -4,145 +4,168 @@ import axios from "axios";
import { json } from "express";
import { useEffect } from "react";
import { API_URL } from "../../fladConfig";
import { Credentials, CredentialsRegister, restoreToken, setLoginState, userSignUp } from "../actions/userActions";
import { Credentials, CredentialsRegister, restoreToken, setLoginState, UserLogout, userChangeMode, userSignUp } from "../actions/userActions";
import * as SecureStore from 'expo-secure-store';
import { User } from "../../Model/User";
import { UserFactory } from "../../Model/factory/UserFactory";
const key = 'userToken';
export const registerUser = ( resgisterCredential : CredentialsRegister) => {
//@ts-ignore
return async dispatch => {
try {
console.log(resgisterCredential);
//@ts-ignore
return async dispatch => {
try {
console.log(resgisterCredential);
const config = {
headers: {
'Content-Type': 'application/json',
},
}
const resp = await axios.post(
`${API_URL}/api/users/register`,
resgisterCredential,
config
)
if (resp.data.token) {
console.log(resp.data.token);
const token = resp.data.token;
// await SecureStore.setItemAsync(key, token);
const headers = {
'Authorization': 'Bearer ' + token};
const user = await axios.get(
"https://flad-api-production.up.railway.app/api/users",
{headers}
)
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 {
console.log('Login Failed', 'Username or Password is incorrect');
}
// if (resp.data.msg === 'success') { // response success checking logic could differ
// await SecureStore.setItemAsync(key, resp.data.token);
// dispatch(setLoginState(resp.data.user) ); // our action is called here
// } else {
// console.log('Login Failed', 'Username or Password is incorrect');
// }
} catch (error) {
console.log('Error---------', error);
const config = {
headers: {
'Content-Type': 'application/json',
},
}
const resp = await axios.post(
`${API_URL}/api/users/register`,
resgisterCredential,
config
)
if (resp.data.token) {
console.log(resp.data.token);
const token = resp.data.token;
// await SecureStore.setItemAsync(key, token);
const headers = {
'Authorization': 'Bearer ' + token};
const user = await axios.get(
"https://flad-api-production.up.railway.app/api/users",
{headers}
)
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 {
console.log('Login Failed', 'Username or Password is incorrect');
}
// if (resp.data.msg === 'success') { // response success checking logic could differ
// await SecureStore.setItemAsync(key, resp.data.token);
// dispatch(setLoginState(resp.data.user) ); // our action is called here
// } else {
// console.log('Login Failed', 'Username or Password is incorrect');
// }
} catch (error) {
console.log('Error---------', error);
}
}
export const userLogin = ( loginCredential : Credentials) => {
//@ts-ignore
return async dispatch => {
}
export const userLogin = (loginCredential: Credentials) => {
//@ts-ignore
return async dispatch => {
try {
console.log(loginCredential);
const config = {
const config = {
headers: {
'Content-Type': 'application/json',
'Content-Type': 'application/json',
},
}
// const resppp = await axios.get(`${API_URL}/toto`);
// console.log(resppp.data, "sddsd");
const resp = await axios.post(
"https://flad-api-production.up.railway.app/api/users/login",
}
// const resppp = await axios.get(`${API_URL}/toto`);
// console.log(resppp.data, "sddsd");
const resp = await axios.post(
"https://flad-api-production.up.railway.app/api/users/login",
loginCredential,
config
)
console.log("====================================================================================")
console.log(resp.data)
console.log("====================================================================================")
if (resp.data.token) {
console.log(resp.data.token);
const token = resp.data.token;
)
console.log("====================================================================================")
console.log(resp.data)
console.log("====================================================================================")
if (resp.data.token) {
console.log(resp.data.token);
const token = resp.data.token;
await SecureStore.setItemAsync(key, token);
const headers = {
'Authorization': 'Bearer ' + token};
'Authorization': 'Bearer ' + token
};
const user = await axios.get(
"https://flad-api-production.up.railway.app/api/users",
{headers}
)
{ headers }
)
// dispatch(setLoginState(resp.data.user) ); // our action is called here
console.log(user.data);
dispatch(setLoginState(user.data) ); // our action is called here
} else {
console.log(user.data);
dispatch(setLoginState(user.data)); // our action is called here
} else {
console.log('Login Failed', 'Username or Password is incorrect');
}
}
} catch (error) {
console.log('Error---------', error);
console.log('Error---------', error);
}
}
}
}
export const getRefreshToken = () => {
//@ts-ignore
return async dispatch => {
try {
let userToken : string | null = await SecureStore.getItemAsync('key');
if (userToken) {
console.log("==========key2 ==================");
console.log(userToken);
console.log("==========key ==================");
console.log("==========on devrais être laaaa ==================");
dispatch(restoreToken(userToken) );
} else {
console.log("==========OOOOOORRRRRRRRHHHHHHHHHH ==================");
const empty = "";
dispatch(restoreToken(empty) );
console.log("merddee");
}
} catch (e) {
console.log('Error---------', e);
}
//@ts-ignore
return async dispatch => {
try {
let userToken: string | null = await SecureStore.getItemAsync(key);
if (userToken) {
console.log("==========key2 ==================");
console.log(userToken);
console.log("==========key ==================");
console.log("==========on devrais être laaaa ==================");
dispatch(restoreToken(userToken));
} else {
console.log("==========OOOOOORRRRRRRRHHHHHHHHHH ==================");
const empty = "";
dispatch(restoreToken(empty));
console.log("merddee");
}
} catch (e) {
console.log('Error---------', e);
}
}
}
// const logIn = (email, password) => {
// const action = (dispatch) => {
// if (email === user.email && password === user.password) {
// dispatch(setLoggedInState(true));
// return true;
// }
// dispatch(setLoggedInState(false));
// return false;
// };
// return action;
// };
// better
async function save(key : string, value : string) {
await SecureStore.setItemAsync(key, value);
}
export const DeleteToken = () => {
//@ts-ignore
return async dispatch => {
try {
await SecureStore.deleteItemAsync(key);
dispatch(UserLogout());
} catch (e) {
console.log('Error deleting token', e);
}
}
}
export const ChangeMode = () => {
//@ts-ignore
return async dispatch => {
dispatch(userChangeMode());
await SecureStore.deleteItemAsync(key);
}
}
// const logIn = (email, password) => {
// const action = (dispatch) => {
// if (email === user.email && password === user.password) {
// dispatch(setLoggedInState(true));
// return true;
// }
// dispatch(setLoggedInState(false));
// return false;
// };
// return action;
// };
// better
async function save(key: string, value: string) {
await SecureStore.setItemAsync(key, value);
}

@ -91,7 +91,7 @@ export const getCurrentUserMusic = (resuestHandler : SpotifyService)=> {
catch (error) {
console.log('Error---------', error);
}
}
}
}
export const searchMusic = async (resuestHandler : SpotifyService,search: string) => {
//

@ -1,10 +1,10 @@
export const userTypes = {
LOGIN: 'LOGIN',
SIGNUP: 'SIGNUP',
SAVE_SPOTIFY :'SAVE_SPOTIFY',
SAVE_SPOTIFY: 'SAVE_SPOTIFY',
UPDATE_USER: 'UPDATE_USER',
UPDATE_PROFILE_PICTURE: 'UPDATE_PROFILE_PICTURE',
USER_LOGOUT : 'USER_LOGOUT',
RESTORE_TOKEN : "RESTORE_TOKEN"
}
USER_LOGOUT: 'USER_LOGOUT',
RESTORE_TOKEN: "RESTORE_TOKEN",
CHANGE_MODE: "CHANGE_MODE"
}

@ -1,26 +1,38 @@
import React, { useEffect, useState} from 'react';
import { Image,StyleSheet, Text, View, FlatList, ScrollView, TouchableOpacity, TouchableHighlight, SafeAreaView } from 'react-native';
import React, { useEffect, useState } from 'react';
import { Image, StyleSheet, Text, View, FlatList, ScrollView, TouchableOpacity, TouchableHighlight, SafeAreaView } from 'react-native';
import CardMusic from '../components/CardMusic';
import normalize from '../components/Normalize';
import Music from '../Model/Music'
import {useNavigation} from "@react-navigation/native";
import FladyComponent from '../components/FladyComponent';
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';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
export default function favoritePage() {
//Dark Mode
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? GraphicalCharterLight : GraphicalCharterDark;
const navigation = useNavigation();
//@ts-ignore
const favoritesMusic = useSelector(state => state.appReducer.favoriteMusic);
const dispatch = useDispatch();
const navigueToDetail = (music : any) => {
navigation.navigate("MusicDetail", {"music": music})
const images = [
{ id: 1, source: require('../assets/images/FLADYLove.png') },
{ id: 2, source: require('../assets/images/FLADYStar.png') },
{ id: 3, source: require('../assets/images/FLADYHate.png') },
{ id: 4, source: require('../assets/images/FLADYCry.png') },
];
const navigueToDetail = (music: any) => {
navigation.navigate("MusicDetail", { "music": music })
};
// to do
const [filteredDataSource, setFilteredDataSource] = useState<Music[]>([]);
const [search, setSearch] = useState('');
const searchMusic = (text: string) => {
// to do
const [filteredDataSource, setFilteredDataSource] = useState<Music[]>([]);
const [search, setSearch] = useState('');
const searchMusic = (text: string) => {
if (text) {
const newData = favoritesMusic.filter(function (item: Music) {
const search = item.title
@ -36,86 +48,90 @@ export default function favoritePage() {
}
};
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: style.body,
},
titleContainer: {
marginTop: 30,
marginLeft: 20,
},
title: {
fontSize: normalize(28),
fontWeight: 'bold',
color: style.Text,
},
description: {
marginTop: 10,
fontSize: normalize(20),
color: '#787878',
marginBottom: 20
},
button: {
marginTop: '10%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'center',
backgroundColor: 'white',
width: normalize(100),
height: normalize(100),
borderRadius: 21
},
buttonImage: {
width: normalize(46),
height: normalize(46),
},
shadow: {
shadowColor: '#000',
shadowOffset: {
width: 2,
height: 3,
},
shadowOpacity: 0.50,
shadowRadius: 3.84,
}
});
return (
<View style={styles.body}>
<SafeAreaView style={styles.mainSafeArea}>
<SafeAreaView style={styles.mainSafeArea}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Favoris</Text>
<Text style={styles.description}>Retrouvez ici vos musiques favorites</Text>
</View>
<ScrollView>
<View>
<FlatList style={{marginBottom: 80}}
<FlatList style={{ marginBottom: 30 }}
data={favoritesMusic}
renderItem={({ item }) => (
<TouchableHighlight onPress={() => {navigueToDetail(item)}}>
<TouchableHighlight onPress={() => { navigueToDetail(item) }}>
<SharedElement id={item.id}>
<CardMusic image={item.image} title={item.title} description={item.bio} id={item.id}/>
<CardMusic image={item.image} title={item.title} description={item.bio} id={item.id} />
</SharedElement>
</TouchableHighlight>
)}
keyExtractor={(item: Music) => item.title }
keyExtractor={(item: Music) => item.title}
/>
</View>
<TouchableOpacity style={[styles.button, styles.shadow]}
// @ts-ignore
onPress={() => navigation.navigate('Genre')}>
<Image source={require("../assets/icons/icons/next.png")} style={styles.buttonImage}/>
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
</View>
<Text style={[styles.title, { marginLeft: 20 }]}>What's your mood?</Text>
<FlatList
style={{ marginTop: 10 }}
data={images}
keyExtractor={(item) => item.id.toString()}
horizontal
showsHorizontalScrollIndicator={false}
renderItem={({ item }) => (
<FladyComponent image={item.source} />
)}
/>
<TouchableOpacity style={[styles.button, styles.shadow]}
// @ts-ignore
onPress={() => navigation.navigate('Genre')}>
<Image source={require("../assets/icons/icons/next.png")} style={styles.buttonImage} />
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: "#141414",
},
body: {
flex: 1,
justifyContent: 'center',
backgroundColor: "#141414",
},
titleContainer: {
marginTop: 30,
marginLeft: 20,
},
title: {
fontSize: normalize(28),
fontWeight: 'bold',
color: 'white',
},
description: {
marginTop: 10,
fontSize: normalize(20),
color: '#787878',
marginBottom: 20
},
button: {
marginTop: '10%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'center',
backgroundColor: 'white',
width: normalize(100),
height: normalize(100),
borderRadius: 21
},
buttonImage: {
width: normalize(46),
height: normalize(46),
},
shadow: {
shadowColor: '#000',
shadowOffset: {
width: 2,
height: 3,
},
shadowOpacity: 0.50,
shadowRadius: 3.84,
}
});
};

@ -1,9 +1,10 @@
import React, { useState } from 'react';
import { View, Image, StyleSheet, Text, ImageBackground, TextInput, TouchableWithoutFeedback, Keyboard, TouchableOpacity } from 'react-native';
import {useNavigation} from "@react-navigation/native";
import { useNavigation } from "@react-navigation/native";
import normalize from '../components/Normalize';
import { userLogin } from '../redux/thunk/authThunk';
import { useDispatch } from 'react-redux';
import { Audio } from 'expo-av';
import { Credentials } from '../redux/actions/userActions';
// @ts-ignore
@ -14,22 +15,33 @@ const DismissKeyboard = ({ children }) => (
)
export default function loginPage() {
const [sound, setSound] = useState<Audio.Sound>();
const [rememberMe, setRememberMe] = useState(false);
const navigation = useNavigation();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync(
require('../assets/sounds/Click.mp3')
);
setSound(sound);
console.log('Playing Sound');
await sound.playAsync();
}
const dispatch = useDispatch();
const submitForm = () => {
const credentials: Credentials = {
email: username,
password: password
};
};
//@ts-ignore
dispatch(userLogin(credentials))
}
playSound()
}
const toggleRememberMe = () => {
setRememberMe(!rememberMe);
@ -42,19 +54,19 @@ export default function loginPage() {
<Text style={styles.versionText}>
v2.0
</Text>
<Image source={require("../assets/icons/Logo_White_Flad.png")} style={styles.imageLogo}/>
<Image source={require("../assets/icons/Logo_White_Flad.png")} style={styles.imageLogo} />
<Text style={styles.text}>SE CONNECTER</Text>
<View>
<TextInput placeholder="Username"
value={username}
onChangeText={setUsername}style={[styles.input, styles.shadow]}/>
value={username}
onChangeText={setUsername} style={[styles.input, styles.shadow]} />
<Image source={require('../assets/icons/icons/User.png')} style={styles.iconUser} />
</View>
<View>
<TextInput placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry style={[styles.input, styles.shadow]}/>
value={password}
onChangeText={setPassword}
secureTextEntry style={[styles.input, styles.shadow]} />
<Image source={require('../assets/icons/icons/lock.png')} style={styles.iconLock} />
</View>
<View style={styles.rememberMeContainer}>
@ -62,15 +74,15 @@ export default function loginPage() {
<Text style={styles.rememberMeText}>SE SOUVENIR DE MOI</Text>
</View>
<TouchableOpacity style={[styles.button, styles.shadow]} onPress={submitForm}>
<Image source={require("../assets/icons/Check.png")} style={styles.buttonImage}/>
<Image source={require("../assets/icons/Check.png")} style={styles.buttonImage} />
</TouchableOpacity>
<View style={styles.inscriptionText}>
<Text style={{fontSize: normalize(18), color: 'white'}}>Tu n'as pas de compte? </Text>
<TouchableOpacity
<Text style={{ fontSize: normalize(18), color: 'white' }}>Tu n'as pas de compte? </Text>
<TouchableOpacity
// @ts-ignore
onPress={() => navigation.navigate('Register')}
>
<Text style={{fontSize: normalize(18), color: '#406DE1', textDecorationLine: 'underline'}}>S'inscrire</Text>
<Text style={{ fontSize: normalize(18), color: '#406DE1', textDecorationLine: 'underline' }}>S'inscrire</Text>
</TouchableOpacity>
</View>
</ImageBackground>
@ -81,9 +93,9 @@ export default function loginPage() {
const styles = StyleSheet.create ({
const styles = StyleSheet.create({
container: {
flex: 1,
flex: 1,
},
image: {
flex: 1,
@ -110,14 +122,14 @@ const styles = StyleSheet.create ({
width: normalize(46),
height: normalize(46),
},
iconUser : {
iconUser: {
position: 'absolute',
width: 20,
height: 20,
left: normalize(80),
bottom: '50%'
},
iconLock : {
iconLock: {
position: 'absolute',
width: 20,
height: 20,
@ -133,7 +145,7 @@ const styles = StyleSheet.create ({
alignSelf: 'center',
marginBottom: 20,
paddingLeft: 50,
paddingRight: 20
paddingRight: 20
},
text: {
fontWeight: 'bold',
@ -145,8 +157,8 @@ const styles = StyleSheet.create ({
shadow: {
shadowColor: 'black',
shadowOffset: {
width: 2,
height: 3,
width: 2,
height: 3,
},
shadowOpacity: 0.50,
shadowRadius: 3.84,
@ -184,8 +196,8 @@ const styles = StyleSheet.create ({
backgroundColor: 'white'
},
inscriptionText: {
flexDirection: 'row',
alignSelf: 'center',
flexDirection: 'row',
alignSelf: 'center',
bottom: normalize(-98)
}
})

@ -1,5 +1,5 @@
import { NavigationProp, RouteProp, useNavigation } from "@react-navigation/native";
import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity, ScrollView, Pressable } 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 { BlurView } from 'expo-blur';
import qs from "qs";
@ -7,6 +7,7 @@ import axios from "axios";
import { Buffer } from 'buffer';
import { Audio } from 'expo-av';
import { useEffect, useState } from "react";
import normalize from '../components/Normalize';
import { State, TapGestureHandler } from "react-native-gesture-handler";
import { RequestHandler } from "../services/spotify/spotifyRequestHandler/utils";
import { FetchRequest } from "expo-auth-session/build/Fetch";
@ -20,34 +21,33 @@ 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
const MusicDetail = ({ route }) => {
const music : Music = route.params.music;
const MusicDetail = ({ route }) => {
const music: Music = route.params.music;
const [currentspot, setCurrentSpot] = useState(music);
const [simularMusic, setSimularMusic] = useState<Music[]>([]);
const [isPlaying, setIsPlaying] = useState(false);
const [sound, setSound] = useState(null);
const navigator = useNavigation();
const [testtoken, setTesttoken] = useState('')
const sheet = async () => {
SecureStore.getItemAsync('MySecureAuthStateKey').then(result => { setTesttoken(result)});
SecureStore.getItemAsync('MySecureAuthStateKey').then(result => { setTesttoken(result) });
}
useEffect(() => {
sheet();
useEffect(() => {
sheet();
getSimilarTrack();
}, [testtoken]);
@ -56,14 +56,14 @@ const MusicDetail = ({ route }) => {
// const simularMusic = await service.getSimilarTrack(currentspot.id, 5, 'FR');
// console.log("suggesstd", simularMusic)
// setSimularMusic(simularMusic);
// }
const getSimilarTrack = async () => {
const getSimilarTrack = async () => {
try {
const service = new SpotifyService(testtoken);
const service = new SpotifyService(testtoken);
const simularMusic = await service.getSimilarTrack(currentspot.id, 5, 'FR');
console.log("suggesstd", simularMusic);
setSimularMusic(simularMusic);
console.log("suggesstd", simularMusic);
setSimularMusic(simularMusic);
} catch (error) {
console.error('Error ================ in getSimilarTrack', error);
// Handle the error here.
@ -72,61 +72,61 @@ const MusicDetail = ({ route }) => {
const handlePlaySound = async () => {
if (sound === null) {
const { sound: newSound } = await Audio.Sound.createAsync(
{ uri: music.trackPreviewUrl },
{ shouldPlay: true }
);
setSound(newSound);
setIsPlaying(true);
const { sound: newSound } = await Audio.Sound.createAsync(
{ uri: music.trackPreviewUrl },
{ shouldPlay: true }
);
setSound(newSound);
setIsPlaying(true);
} else {
setIsPlaying(true);
//@ts-ignore
await sound.playAsync();
await sound.playAsync();
}
};
const handleStopSound = async () => {
};
const handleStopSound = async () => {
if (sound !== null) {
setIsPlaying(false);
//@ts-ignore
await sound.stopAsync();
await sound.stopAsync();
}
else{
else {
}
};
useEffect(() => {
};
useEffect(() => {
return sound ? () => {
console.log('Unloading Sound');
//@ts-ignore
sound.unloadAsync();
}
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),
};
})
}, [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 (
<View style={styles.body}>
<View style={styles.backgroundSection}>
<View style={styles.backgroundSection}>
<Image
blurRadius={133}
style={styles.back_drop}
@ -141,85 +141,89 @@ const MusicDetail = ({ route }) => {
/> */}
<LinearGradient style={styles.gradientFade}
// Button Linear Gradient
colors={['rgba(56,56,56,0)', 'rgba(14,14,14,1)']}>
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>
<Animated.Image
source={{
uri:currentspot.image ,
}}
style={[
{
// width: 370,
// width: 400,
width: 392,
height: 392,
borderRadius : 24,
resizeMode: 'stretch',
},styleAniamatedImage
]}
/>
</View>
<View style={{marginTop : 45,flex: 1, flexDirection : 'row', }}>
<View>
<ScrollView style={styles.list} showsVerticalScrollIndicator={false} scrollEventThrottle={4}>
</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)' }}>
<View style={styles.section1}>
<View style={{ flex: 1, justifyContent: 'flex-start', alignItems: 'center' }}>
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
<View>
<Animated.Image
source={{
uri: currentspot.image,
}}
style={[
{
// width: 370,
// width: 400,
width: normalize(429),
height: normalize(429),
borderRadius: 24,
resizeMode: 'stretch',
}, styleAniamatedImage
]}
/>
</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>
<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>
{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>
);
@ -227,7 +231,7 @@ const MusicDetail = ({ route }) => {
export default MusicDetail;
const styles = StyleSheet.create ({
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: "#141414",

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { View, Image, StyleSheet, Text, ImageBackground, TextInput, TouchableWithoutFeedback, Keyboard, TouchableOpacity, Platform } from 'react-native';
import {useNavigation} from "@react-navigation/native";
import { useNavigation } from "@react-navigation/native";
import normalize from '../components/Normalize';
import * as SecureStore from 'expo-secure-store';
import * as AuthSession from 'expo-auth-session';
@ -8,15 +8,16 @@ import * as WebBrowser from 'expo-web-browser';
import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';
import { registerUser } from '../redux/thunk/authThunk';
import { useDispatch } from 'react-redux';
import { Audio } from 'expo-av';
import { CredentialsRegister } from '../redux/actions/userActions';
import { Buffer } from 'buffer';
import SpotifyService from '../services/spotify/spotify.service';
// @ts-ignore
const DismissKeyboard = ({ children }) => (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
{children}
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
{children}
</TouchableWithoutFeedback>
)
export const MY_SECURE_AUTH_STATE_KEY = 'MySecureAuthStateKey';
@ -25,347 +26,359 @@ WebBrowser.maybeCompleteAuthSession();
// Endpoint
const discovery = {
authorizationEndpoint: 'https://accounts.spotify.com/authorize',
tokenEndpoint: 'https://accounts.spotify.com/api/token',
authorizationEndpoint: 'https://accounts.spotify.com/authorize',
tokenEndpoint: 'https://accounts.spotify.com/api/token',
};
// save the spotifyToken
async function save(key : string, value : string) {
await SecureStore.setItemAsync(key, value);
async function save(key: string, value: string) {
await SecureStore.setItemAsync(key, value);
}
export default function InscriptionPage() {
const [rememberMe, setRememberMe] = useState(false);
const navigation = useNavigation();
const [spotifyToken, setSpotifyToken] = useState('');
const [spotifyID, setSpotifyIds] = useState('')
const [sound, setSound] = useState<Audio.Sound>();
const [rememberMe, setRememberMe] = useState(false);
const navigation = useNavigation();
const [spotifyToken, setSpotifyToken] = useState('');
const [spotifyID, setSpotifyIds] = useState('')
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync(
require('../assets/sounds/Click.mp3')
);
setSound(sound);
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const toggleRememberMe = () => {
setRememberMe(!rememberMe);
}
//spotify auth
const [request, response, promptAsync] = useAuthRequest(
{
responseType: AuthSession.ResponseType.Token,
clientId: '1f1e34e4b6ba48b388469dba80202b10',
scopes: ['user-read-private','user-read-email','user-read-playback-state','user-read-currently-playing','user-read-recently-played','playlist-modify-public','ugc-image-upload','user-modify-playback-state'],
redirectUri: makeRedirectUri({
scheme: 'flad'
}),
},
discovery
);
useEffect(() => {
if (response && response.type === 'success') {
const auth = response.params.access_token;
const storageValue = JSON.stringify(auth);
if (Platform.OS !== 'web') {
// Securely store the auth on your device
save(MY_SECURE_AUTH_STATE_KEY, storageValue);
}
}
}, [response]);
console.log('Playing Sound');
await sound.playAsync();
}
const dispatch = useDispatch();
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const toggleRememberMe = () => {
setRememberMe(!rememberMe);
}
//spotify auth
const [request, response, promptAsync] = useAuthRequest(
{
responseType: AuthSession.ResponseType.Token,
clientId: '1f1e34e4b6ba48b388469dba80202b10',
scopes: ['user-read-private', 'user-read-email', 'user-read-playback-state', 'user-read-currently-playing', 'user-read-recently-played', 'playlist-modify-public', 'ugc-image-upload', 'user-modify-playback-state'],
redirectUri: makeRedirectUri({
scheme: 'flad'
}),
},
discovery
);
useEffect(() => {
if (response && response.type === 'success') {
const auth = response.params.access_token;
const storageValue = JSON.stringify(auth);
const submitForm = () => {
const credentials: CredentialsRegister = {
email: email,
password: password,
idSpotify : spotifyToken,
name : username,
idFlad : "3030"
};
//@ts-ignore
dispatch(registerUser(credentials))
if (Platform.OS !== 'web') {
// Securely store the auth on your device
save(MY_SECURE_AUTH_STATE_KEY, storageValue);
}
const scopesArr = ['user-read-private','user-read-email','user-read-playback-state','user-read-currently-playing','user-read-recently-played','playlist-modify-public','ugc-image-upload','user-modify-playback-state'];
const scopes = scopesArr.join(' ');
//work so use this for my implementation
const getAuthorizationCode = async () => {
try {
const redirectUrl = "https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d"; //this will be something like https://auth.expo.io/@your-username/your-app-slug
const result = await AuthSession.startAsync({
authUrl:
'https://accounts.spotify.com/authorize' +
'?response_type=code' +
'&client_id=' +
"1f1e34e4b6ba48b388469dba80202b10" +
(scopes ? '&scope=' + encodeURIComponent(scopes) : '') +
'&redirect_uri=' +
encodeURIComponent(redirectUrl),
})
console.log("=================grant code ==============<");
}
}, [response]);
console.log(result);
console.log("=================grant code ==============<");
const dispatch = useDispatch();
return result.params.code;
} catch (err) {
console.error(err)
}
const submitForm = () => {
const credentials: CredentialsRegister = {
email: email,
password: password,
idSpotify: spotifyToken,
name: username,
idFlad: "3030"
};
//@ts-ignore
dispatch(registerUser(credentials))
playSound()
}
const scopesArr = ['user-read-private', 'user-read-email', 'user-read-playback-state', 'user-read-currently-playing', 'user-read-recently-played', 'playlist-modify-public', 'ugc-image-upload', 'user-modify-playback-state'];
const scopes = scopesArr.join(' ');
//work so use this for my implementation
const getAuthorizationCode = async () => {
try {
const redirectUrl = "https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d"; //this will be something like https://auth.expo.io/@your-username/your-app-slug
const result = await AuthSession.startAsync({
authUrl:
'https://accounts.spotify.com/authorize' +
'?response_type=code' +
'&client_id=' +
"1f1e34e4b6ba48b388469dba80202b10" +
(scopes ? '&scope=' + encodeURIComponent(scopes) : '') +
'&redirect_uri=' +
encodeURIComponent(redirectUrl),
})
console.log("=================grant code ==============<");
console.log(result);
console.log("=================grant code ==============<");
return result.params.code;
} catch (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 ==============<");
}
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 ==============<");
console.log(result);
console.log("=================grant code ==============<");
return result.params.code;
} catch (err) {
console.error(err)
}
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);
}
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;
console.log(spotifyToken);
} catch (err) {
console.error(err);
}
await setSpotifyToken(accessToken);
console.log(spotifyToken);
} catch (err) {
console.error(err);
}
const getTokens = async () => {
try {
const authorizationCode = await getAuthorizationCode() //we wrote this function above
console.log(authorizationCode, "shhhhhhhhhhhhhheeeeeeeeeeeeeeeetttttttttttt");
const response = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
Authorization: 'Basic ' + (Buffer.from('1f1e34e4b6ba48b388469dba80202b10' + ':' + '779371c6d4994a68b8dd6e84b0873c82').toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `grant_type=authorization_code&code=${authorizationCode}&redirect_uri=https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d`,
});
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);
save(MY_SECURE_AUTH_STATE_KEY, accessToken);
testService(accessToken);
console.log(spotifyToken);
} catch (err) {
console.error(err);
}
}
const getTokens = async () => {
try {
const authorizationCode = await getAuthorizationCode() //we wrote this function above
console.log(authorizationCode, "shhhhhhhhhhhhhheeeeeeeeeeeeeeeetttttttttttt");
const response = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
Authorization: 'Basic ' + (Buffer.from('1f1e34e4b6ba48b388469dba80202b10' + ':' + '779371c6d4994a68b8dd6e84b0873c82').toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `grant_type=authorization_code&code=${authorizationCode}&redirect_uri=https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d`,
});
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);
save(MY_SECURE_AUTH_STATE_KEY, accessToken);
testService(accessToken);
console.log(spotifyToken);
} catch (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("============================================");
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 (
<DismissKeyboard>
<View style={styles.container}>
<ImageBackground source={require("../assets/images/Background.png")} resizeMode="cover" style={styles.image}>
<Text style={styles.versionText}>
v2.0
</Text>
<Image source={require("../assets/icons/Logo_White_Flad.png")} style={styles.imageLogo}/>
<Text style={styles.text}>S'INSCRIRE</Text>
<View>
<TextInput style={[styles.input, styles.shadow]} placeholder="Username"
value={username}
onChangeText={setUsername}/>
<Image source={require('../assets/icons/icons/User.png')} style={styles.iconUser} />
</View>
<View>
<TextInput style={[styles.input, styles.shadow]} placeholder="Email"
value={email}
onChangeText={setEmail}/>
<Image source={require('../assets/icons/icons/lock.png')} style={styles.iconLock} />
</View>
<View>
<TextInput style={[styles.input, styles.shadow]} placeholder="Password"
value={password} secureTextEntry={true}
onChangeText={setPassword}/>
<Image source={require('../assets/icons/icons/lock.png')} style={styles.iconLock} />
</View>
<TouchableOpacity onPress={async() => {
await getTokens();
}} style={[styles.buttonSpotify, styles.shadow]}>
<Text style={styles.textIntoButton}>Lier compte</Text>
<Image source={require("../assets/icons/icons/Spotify.png")} style={{width: normalize(35), height: normalize(35)}}/>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.shadow]} onPress={() => submitForm()}>
<Image source={require("../assets/icons/icons/next.png")} style={styles.buttonImage}/>
</TouchableOpacity>
<View style={styles.connectionText}>
<Text style={{fontSize: normalize(18), color: 'white'}}>Tu as déjà un compte? </Text>
<TouchableOpacity
// @ts-ignore
onPress={() => navigation.navigate('Login')}
>
<Text style={{fontSize: normalize(18), color: '#406DE1', textDecorationLine: 'underline'}}>Se connecter</Text>
</TouchableOpacity>
</View>
</ImageBackground>
</View>
</DismissKeyboard>
)
return (
<DismissKeyboard>
<View style={styles.container}>
<ImageBackground source={require("../assets/images/Background.png")} resizeMode="cover" style={styles.image}>
<Text style={styles.versionText}>
v2.0
</Text>
<Image source={require("../assets/icons/Logo_White_Flad.png")} style={styles.imageLogo} />
<Text style={styles.text}>S'INSCRIRE</Text>
<View>
<TextInput style={[styles.input, styles.shadow]} placeholder="Username"
value={username}
onChangeText={setUsername} />
<Image source={require('../assets/icons/icons/User.png')} style={styles.iconUser} />
</View>
<View>
<TextInput style={[styles.input, styles.shadow]} placeholder="Email"
value={email}
onChangeText={setEmail} />
<Image source={require('../assets/icons/icons/lock.png')} style={styles.iconLock} />
</View>
<View>
<TextInput style={[styles.input, styles.shadow]} placeholder="Password"
value={password} secureTextEntry={true}
onChangeText={setPassword} />
<Image source={require('../assets/icons/icons/lock.png')} style={styles.iconLock} />
</View>
<TouchableOpacity onPress={async () => {
await getTokens();
}} style={[styles.buttonSpotify, styles.shadow]}>
<Text style={styles.textIntoButton}>Lier compte</Text>
<Image source={require("../assets/icons/icons/Spotify.png")} style={{ width: normalize(35), height: normalize(35) }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.shadow]} onPress={() => submitForm()}>
<Image source={require("../assets/icons/icons/next.png")} style={styles.buttonImage} />
</TouchableOpacity>
<View style={styles.connectionText}>
<Text style={{ fontSize: normalize(18), color: 'white' }}>Tu as déjà un compte? </Text>
<TouchableOpacity
// @ts-ignore
onPress={() => navigation.navigate('Login')}
>
<Text style={{ fontSize: normalize(18), color: '#406DE1', textDecorationLine: 'underline' }}>Se connecter</Text>
</TouchableOpacity>
</View>
</ImageBackground>
</View>
</DismissKeyboard>
)
}
const styles = StyleSheet.create ({
container: {
flex: 1
},
image: {
flex: 1,
justifyContent: 'center',
},
imageLogo: {
width: normalize(324),
height: normalize(162),
alignSelf: 'center',
marginBottom: normalize(58),
marginTop: -20
},
button: {
marginTop: '10%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'center',
backgroundColor: 'white',
width: normalize(100),
height: normalize(100),
borderRadius: 21
},
buttonImage: {
width: normalize(46),
height: normalize(46),
},
versionText: {
position: 'absolute',
top: 40,
right: 20,
color: 'gray',
fontWeight: 'bold',
fontSize: normalize(17)
},
text: {
fontWeight: 'bold',
fontSize: normalize(29),
alignSelf: 'center',
color: 'white',
marginBottom: 15
},
textIntoButton: {
fontWeight: 'bold',
fontSize: normalize(17),
color: 'white',
marginRight: 10
const styles = StyleSheet.create({
container: {
flex: 1
},
image: {
flex: 1,
justifyContent: 'center',
},
imageLogo: {
width: normalize(324),
height: normalize(162),
alignSelf: 'center',
marginBottom: normalize(58),
marginTop: -20
},
button: {
marginTop: '10%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'center',
backgroundColor: 'white',
width: normalize(100),
height: normalize(100),
borderRadius: 21
},
buttonImage: {
width: normalize(46),
height: normalize(46),
},
versionText: {
position: 'absolute',
top: 40,
right: 20,
color: 'gray',
fontWeight: 'bold',
fontSize: normalize(17)
},
text: {
fontWeight: 'bold',
fontSize: normalize(29),
alignSelf: 'center',
color: 'white',
marginBottom: 15
},
textIntoButton: {
fontWeight: 'bold',
fontSize: normalize(17),
color: 'white',
marginRight: 10
},
shadow: {
shadowColor: '#000',
shadowOffset: {
width: 2,
height: 3,
},
shadow: {
shadowColor: '#000',
shadowOffset: {
width: 2,
height: 3,
},
shadowOpacity: 0.50,
shadowRadius: 3.84,
},
input: {
width: normalize(350),
height: normalize(50),
borderRadius: 30,
color: 'black',
backgroundColor: 'white',
alignSelf: 'center',
marginBottom: 20,
paddingLeft: 50,
paddingRight: 20
},
iconUser : {
position: 'absolute',
width: 20,
height: 20,
left: normalize(80),
bottom: '50%'
},
iconLock : {
position: 'absolute',
width: 20,
height: 20,
left: normalize(80),
bottom: '50%'
},
connectionText: {
flexDirection: 'row',
alignSelf: 'center',
bottom: normalize(-98)
},
buttonSpotify: {
width: normalize(350),
height: normalize(50),
backgroundColor: '#24CF5F',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
borderRadius: 30,
flexDirection: 'row'
}
shadowOpacity: 0.50,
shadowRadius: 3.84,
},
input: {
width: normalize(350),
height: normalize(50),
borderRadius: 30,
color: 'black',
backgroundColor: 'white',
alignSelf: 'center',
marginBottom: 20,
paddingLeft: 50,
paddingRight: 20
},
iconUser: {
position: 'absolute',
width: 20,
height: 20,
left: normalize(80),
bottom: '50%'
},
iconLock: {
position: 'absolute',
width: 20,
height: 20,
left: normalize(80),
bottom: '50%'
},
connectionText: {
flexDirection: 'row',
alignSelf: 'center',
bottom: normalize(-98)
},
buttonSpotify: {
width: normalize(350),
height: normalize(50),
backgroundColor: '#24CF5F',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
borderRadius: 30,
flexDirection: 'row'
}
})

@ -1,11 +1,17 @@
import React, { useRef, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { View, StyleSheet, Text, Image, TouchableWithoutFeedback, Keyboard, TouchableOpacity, SafeAreaView } from 'react-native';
import { Svg, Path } from 'react-native-svg';
import {useNavigation} from "@react-navigation/native";
import { useNavigation } from "@react-navigation/native";
import { useDispatch } from 'react-redux';
import normalize from '../components/Normalize';
import { ScrollView, Switch, TextInput } from 'react-native-gesture-handler';
import CardMusic from '../components/CardMusic';
import { ChangeMode, DeleteToken } from '../redux/thunk/authThunk';
import { useSelector } from 'react-redux';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
import SpotifyService from '../services/spotify/spotify.service';
import { getCurrentUserMusic } from '../redux/thunk/spotThunk';
// @ts-ignore
const DismissKeyboard = ({ children }) => (
@ -16,31 +22,222 @@ const DismissKeyboard = ({ children }) => (
export default function Setting() {
const textInputRef = useRef(null);
const dispatch = useDispatch();
const navigation = useNavigation();
const handleSvgPress = () => {
//@ts-ignore
textInputRef.current?.focus();
//@ts-ignore
textInputRef.current?.focus();
};
const currentMusic = useSelector(state => state.appReducer.userCurrentMusic);
//Dark Mode
const[isCheckedDarkMode, setIsCheckedDarkMode] = useState(false);
const toggleDarkMode =
() => setIsCheckedDarkMode(value => !value);
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? GraphicalCharterLight : GraphicalCharterDark;
const ChangeDarkMode = () => {
dispatch(ChangeMode())
}
//Notification
const[isCheckedNotif, setIsCheckedNotif] = useState(false);
const [isCheckedNotif, setIsCheckedNotif] = useState(false);
const toggleNotif =
const toggleNotif =
() => setIsCheckedNotif(value => !value);
//Deconnection
const Deconnection = () => {
//@ts-ignore
dispatch(DeleteToken())
}
//Localisation
const[isCheckedLocalisation, setIsCheckedLocalisation] = useState(false);
const [isCheckedLocalisation, setIsCheckedLocalisation] = useState(false);
const toggleLocalisation =
const toggleLocalisation =
() => setIsCheckedLocalisation(value => !value);
//Style
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: style.body,
},
container: {
marginTop: 30,
marginHorizontal: normalize(25),
paddingBottom: normalize(400),
flex: 1,
backgroundColor: style.body,
},
title: {
fontSize: normalize(30),
fontWeight: 'bold',
color: style.Text,
alignItems: 'center',
},
search: {
paddingVertical: 9,
backgroundColor: style.Card,
borderRadius: 13,
flexDirection: 'row',
marginTop: 9,
marginBottom: 22
},
inputSearch: {
placeholderTextColor: 'red',
color: 'white',
width: normalize(350),
},
profil: {
paddingVertical: 9,
backgroundColor: style.Card,
borderRadius: 13,
flexDirection: 'row',
alignItems: 'center',
marginBottom: normalize(45)
},
imageProfil: {
marginLeft: 15,
marginRight: 7,
width: 50,
height: 50
},
NameProfil: {
fontWeight: 'bold',
color: style.Text,
fontSize: normalize(22)
},
description: {
color: style.Text,
fontSize: normalize(15)
},
profilContainer: {
flex: 1,
marginLeft: 9,
alignItems: 'flex-start',
justifyContent: 'center',
},
buttonSetting: {
width: normalize(17),
height: normalize(17),
marginRight: 22
},
body: {
paddingTop: normalize(10),
backgroundColor: style.Card,
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45),
paddingLeft: normalize(10),
},
view: {
backgroundColor: '#fe9500',
padding: 5,
borderRadius: 10,
marginLeft: 15,
marginBottom: normalize(11)
},
Option: {
flexDirection: 'row',
alignItems: 'center',
},
secondOption: {
marginTop: normalize(11),
flexDirection: 'row',
alignItems: 'center',
},
textOption: {
fontSize: normalize(18),
color: style.Text,
fontWeight: 'bold',
marginBottom: normalize(8)
},
firstOptionView: {
flex: 1,
marginLeft: 15,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: style.Line
},
deconnectedOption: {
paddingVertical: 9,
paddingLeft: 5,
backgroundColor: style.Card,
borderRadius: 13,
flexDirection: 'row',
alignItems: 'center',
},
buttonDeconectedOption: {
backgroundColor: '#DF0404',
padding: 5,
borderRadius: 10,
marginLeft: 15
},
textDeconnectionOption: {
fontSize: normalize(18),
color: '#F80404',
fontWeight: 'bold',
marginLeft: 12
},
notification: {
backgroundColor: '#fe3c30',
padding: 5,
borderRadius: 10,
marginLeft: 15,
marginBottom: normalize(11)
},
secondOptionView: {
flex: 1,
marginLeft: 15,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: style.Line
},
lastOptionView: {
flex: 1,
marginLeft: 15,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center'
},
localisation: {
backgroundColor: '#0835A7',
padding: 5,
borderRadius: 10,
marginLeft: 15,
marginBottom: normalize(11)
},
lastOption: {
marginTop: normalize(11),
flexDirection: 'row',
alignItems: 'center',
},
musicActually: {
paddingTop: normalize(17),
backgroundColor: style.Card,
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45)
},
titleMusic: {
flexDirection: 'row',
marginBottom: 5
},
mascot: {
width: normalize(90),
height: normalize(90),
position: 'absolute',
right: normalize(0),
top: normalize(10)
}
})
return (
<DismissKeyboard>
<SafeAreaView style={styles.mainSafeArea}>
@ -49,91 +246,91 @@ export default function Setting() {
<Text style={styles.title}>Réglages</Text>
<View style={styles.search}>
<TouchableOpacity onPress={handleSvgPress}>
<Svg width="21" height="21" style={{marginHorizontal: normalize(10)}} viewBox="0 0 21 21" fill="none">
<Path d="M13.5625 12.25H12.8713L12.6263 12.0137C13.4838 11.0162 14 9.72125 14 8.3125C14 5.17125 11.4537 2.625 8.3125 2.625C5.17125 2.625 2.625 5.17125 2.625 8.3125C2.625 11.4537 5.17125 14 8.3125 14C9.72125 14 11.0162 13.4838 12.0137 12.6263L12.25 12.8713V13.5625L16.625 17.9287L17.9287 16.625L13.5625 12.25ZM8.3125 12.25C6.13375 12.25 4.375 10.4913 4.375 8.3125C4.375 6.13375 6.13375 4.375 8.3125 4.375C10.4913 4.375 12.25 6.13375 12.25 8.3125C12.25 10.4913 10.4913 12.25 8.3125 12.25Z" fill="#828288"/>
<Svg width="21" height="21" style={{ marginHorizontal: normalize(10) }} viewBox="0 0 21 21" fill="none">
<Path d="M13.5625 12.25H12.8713L12.6263 12.0137C13.4838 11.0162 14 9.72125 14 8.3125C14 5.17125 11.4537 2.625 8.3125 2.625C5.17125 2.625 2.625 5.17125 2.625 8.3125C2.625 11.4537 5.17125 14 8.3125 14C9.72125 14 11.0162 13.4838 12.0137 12.6263L12.25 12.8713V13.5625L16.625 17.9287L17.9287 16.625L13.5625 12.25ZM8.3125 12.25C6.13375 12.25 4.375 10.4913 4.375 8.3125C4.375 6.13375 6.13375 4.375 8.3125 4.375C10.4913 4.375 12.25 6.13375 12.25 8.3125C12.25 10.4913 10.4913 12.25 8.3125 12.25Z" fill="#828288" />
</Svg>
</TouchableOpacity>
<TextInput placeholderTextColor="#828288" ref={textInputRef} placeholder='Recherche' style={styles.inputSearch}></TextInput>
<Svg width="19" height="19" viewBox="0 0 19 19" fill="none">
<Path d="M13.6563 8.3125V10.0938C13.6563 11.1961 13.2184 12.2532 12.4389 13.0327C11.6595 13.8121 10.6023 14.25 9.5 14.25C8.39769 14.25 7.34054 13.8121 6.56109 13.0327C5.78164 12.2532 5.34375 11.1961 5.34375 10.0938V8.3125H4.15625V10.0938C4.15687 11.4078 4.64161 12.6755 5.51785 13.6547C6.39409 14.6339 7.60038 15.2559 8.90625 15.4019V16.625H6.53125V17.8125H12.4688V16.625H10.0938V15.4019C11.3996 15.2559 12.6059 14.6339 13.4822 13.6547C14.3584 12.6755 14.8431 11.4078 14.8438 10.0938V8.3125H13.6563Z" fill="#828288"/>
<Path d="M9.5 13.0625C10.2874 13.0625 11.0425 12.7497 11.5992 12.193C12.156 11.6362 12.4688 10.8811 12.4688 10.0938V4.15625C12.4688 3.36889 12.156 2.61378 11.5992 2.05703C11.0425 1.50028 10.2874 1.1875 9.5 1.1875C8.71264 1.1875 7.95753 1.50028 7.40078 2.05703C6.84403 2.61378 6.53125 3.36889 6.53125 4.15625V10.0938C6.53125 10.8811 6.84403 11.6362 7.40078 12.193C7.95753 12.7497 8.71264 13.0625 9.5 13.0625Z" fill="#828288"/>
<Path d="M13.6563 8.3125V10.0938C13.6563 11.1961 13.2184 12.2532 12.4389 13.0327C11.6595 13.8121 10.6023 14.25 9.5 14.25C8.39769 14.25 7.34054 13.8121 6.56109 13.0327C5.78164 12.2532 5.34375 11.1961 5.34375 10.0938V8.3125H4.15625V10.0938C4.15687 11.4078 4.64161 12.6755 5.51785 13.6547C6.39409 14.6339 7.60038 15.2559 8.90625 15.4019V16.625H6.53125V17.8125H12.4688V16.625H10.0938V15.4019C11.3996 15.2559 12.6059 14.6339 13.4822 13.6547C14.3584 12.6755 14.8431 11.4078 14.8438 10.0938V8.3125H13.6563Z" fill="#828288" />
<Path d="M9.5 13.0625C10.2874 13.0625 11.0425 12.7497 11.5992 12.193C12.156 11.6362 12.4688 10.8811 12.4688 10.0938V4.15625C12.4688 3.36889 12.156 2.61378 11.5992 2.05703C11.0425 1.50028 10.2874 1.1875 9.5 1.1875C8.71264 1.1875 7.95753 1.50028 7.40078 2.05703C6.84403 2.61378 6.53125 3.36889 6.53125 4.15625V10.0938C6.53125 10.8811 6.84403 11.6362 7.40078 12.193C7.95753 12.7497 8.71264 13.0625 9.5 13.0625Z" fill="#828288" />
</Svg>
</View>
<TouchableOpacity onPress={() => navigation.navigate('SettingProfil')}>
<View style={styles.profil}>
<Image source={require('../assets/icons/icons/IconProfil.png')} style={styles.imageProfil}/>
<Image source={require('../assets/icons/icons/IconProfil.png')} style={styles.imageProfil} />
<View style={styles.profilContainer}>
<Text style={styles.NameProfil}>Emre KARTAL</Text>
<Text style={styles.description}>id. Spotify, mail et mot de passe</Text>
</View>
<Image style={styles.buttonSetting} source={require('../assets/icons/icons/buttonProfil.png')}/>
<Image style={styles.buttonSetting} source={require('../assets/icons/icons/buttonProfil.png')} />
</View>
</TouchableOpacity>
<View style={styles.body}>
<View style={styles.Option}>
<View style={styles.view}>
<Svg width="23" height="22" viewBox="0 0 23 18" fill="none">
<Path d="M1 8.63636C1 8.63636 4.81818 1 11.5 1C18.1818 1 22 8.63636 22 8.63636" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<Path d="M1 8.63635C1 8.63635 4.81818 16.2727 11.5 16.2727C18.1818 16.2727 22 8.63635 22 8.63635" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<Path d="M11.4997 11.5C13.0813 11.5 14.3634 10.2179 14.3634 8.63634C14.3634 7.0548 13.0813 5.77271 11.4997 5.77271C9.9182 5.77271 8.63611 7.0548 8.63611 8.63634C8.63611 10.2179 9.9182 11.5 11.4997 11.5Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</Svg>
<Path d="M1 8.63636C1 8.63636 4.81818 1 11.5 1C18.1818 1 22 8.63636 22 8.63636" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<Path d="M1 8.63635C1 8.63635 4.81818 16.2727 11.5 16.2727C18.1818 16.2727 22 8.63635 22 8.63635" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<Path d="M11.4997 11.5C13.0813 11.5 14.3634 10.2179 14.3634 8.63634C14.3634 7.0548 13.0813 5.77271 11.4997 5.77271C9.9182 5.77271 8.63611 7.0548 8.63611 8.63634C8.63611 10.2179 9.9182 11.5 11.4997 11.5Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</Svg>
</View>
<View style={styles.firstOptionView}>
<Text style={styles.textOption}>Dark Mode</Text>
<Switch style={{marginBottom: normalize(10), marginRight: 20}} value={isCheckedDarkMode} onValueChange={toggleDarkMode}/>
<Switch style={{ marginBottom: normalize(10), marginRight: 20 }} value={isDark} onValueChange={ChangeDarkMode} />
</View>
</View>
<View style={styles.secondOption}>
<View style={styles.notification}>
<Svg width="23" height="22" viewBox="0 0 1242 1242">
<Path d="M620.553 1181.81C642.27 1181.31 663.11 1173.14 679.388 1158.76C695.665 1144.37 706.331 1124.69 709.498 1103.2H528.159C531.416 1125.28 542.581 1145.42 559.577 1159.88C576.572 1174.34 598.241 1182.13 620.553 1181.81Z" fill="white"/>
<Path d="M1132.51 969.785L1120.79 959.443C1087.53 929.815 1058.43 895.838 1034.25 858.43C1007.85 806.806 992.03 750.428 987.712 692.605V522.298C987.572 501.611 985.727 480.971 982.196 460.587C923.799 448.585 871.344 416.77 833.712 370.531C796.079 324.292 775.582 266.468 775.69 206.851C775.69 199.611 775.69 192.371 775.69 185.131C739.695 167.417 701.023 155.769 661.233 150.656V107.217C661.233 95.011 656.384 83.3046 647.752 74.6733C639.121 66.0421 627.415 61.1931 615.208 61.1931C603.002 61.1931 591.295 66.0421 582.664 74.6733C574.033 83.3046 569.184 95.011 569.184 107.217V152.38C480.09 164.948 398.552 209.324 339.622 277.315C280.692 345.307 248.349 432.323 248.565 522.298V692.605C244.247 750.428 228.424 806.806 202.024 858.43C178.266 895.745 149.628 929.716 116.87 959.443L105.149 969.785V1067.01H1132.51V969.785Z" fill="white"/>
<Path d="M1034.25 379.226C1129.45 379.226 1206.63 302.051 1206.63 206.851C1206.63 111.65 1129.45 34.4751 1034.25 34.4751C939.053 34.4751 861.878 111.65 861.878 206.851C861.878 302.051 939.053 379.226 1034.25 379.226Z" fill="white"/>
<Path d="M620.553 1181.81C642.27 1181.31 663.11 1173.14 679.388 1158.76C695.665 1144.37 706.331 1124.69 709.498 1103.2H528.159C531.416 1125.28 542.581 1145.42 559.577 1159.88C576.572 1174.34 598.241 1182.13 620.553 1181.81Z" fill="white" />
<Path d="M1132.51 969.785L1120.79 959.443C1087.53 929.815 1058.43 895.838 1034.25 858.43C1007.85 806.806 992.03 750.428 987.712 692.605V522.298C987.572 501.611 985.727 480.971 982.196 460.587C923.799 448.585 871.344 416.77 833.712 370.531C796.079 324.292 775.582 266.468 775.69 206.851C775.69 199.611 775.69 192.371 775.69 185.131C739.695 167.417 701.023 155.769 661.233 150.656V107.217C661.233 95.011 656.384 83.3046 647.752 74.6733C639.121 66.0421 627.415 61.1931 615.208 61.1931C603.002 61.1931 591.295 66.0421 582.664 74.6733C574.033 83.3046 569.184 95.011 569.184 107.217V152.38C480.09 164.948 398.552 209.324 339.622 277.315C280.692 345.307 248.349 432.323 248.565 522.298V692.605C244.247 750.428 228.424 806.806 202.024 858.43C178.266 895.745 149.628 929.716 116.87 959.443L105.149 969.785V1067.01H1132.51V969.785Z" fill="white" />
<Path d="M1034.25 379.226C1129.45 379.226 1206.63 302.051 1206.63 206.851C1206.63 111.65 1129.45 34.4751 1034.25 34.4751C939.053 34.4751 861.878 111.65 861.878 206.851C861.878 302.051 939.053 379.226 1034.25 379.226Z" fill="white" />
</Svg>
</View>
<View style={styles.secondOptionView}>
<Text style={styles.textOption}>Notification</Text>
<Switch style={{marginBottom: normalize(10), marginRight: 20}} value={isCheckedNotif} onValueChange={toggleNotif}/>
<Switch style={{ marginBottom: normalize(10), marginRight: 20 }} value={isCheckedNotif} onValueChange={toggleNotif} />
</View>
</View>
<View style={styles.lastOption}>
<View style={styles.localisation}>
<Svg width="24" height="23" viewBox="0 0 472 420" fill="none">
<Path d="M235.735 0C178.774 0 132.601 46.1729 132.601 103.134C132.601 149.184 200.006 233.115 225.83 263.581C231.061 269.752 240.416 269.752 245.639 263.581C271.463 233.115 338.868 149.184 338.868 103.134C338.868 46.1729 292.696 0 235.735 0ZM235.735 137.512C216.745 137.512 201.357 122.124 201.357 103.134C201.357 84.1441 216.745 68.7559 235.735 68.7559C254.724 68.7559 270.112 84.1441 270.112 103.134C270.112 122.124 254.724 137.512 235.735 137.512ZM16.4687 176.76C11.6081 178.704 7.44144 182.06 4.50605 186.394C1.57065 190.729 0.00116411 195.843 0 201.078L0 405.971C0 415.237 9.35571 421.572 17.9584 418.134L130.964 366.698V175.917C123.728 162.837 117.81 150.101 113.57 137.921L16.4687 176.76ZM235.735 294.398C224.218 294.398 213.323 289.34 205.85 280.516C189.758 261.526 172.643 239.901 157.156 217.719V366.69L314.313 419.075V217.727C298.826 239.901 281.719 261.534 265.619 280.524C258.146 289.34 247.251 294.398 235.735 294.398ZM453.511 131.913L340.505 183.349V419.084L455 373.287C459.862 371.344 464.029 367.989 466.964 363.654C469.9 359.319 471.469 354.204 471.469 348.969V144.076C471.469 134.811 462.113 128.475 453.511 131.913Z" fill="white"/>
<Path d="M235.735 0C178.774 0 132.601 46.1729 132.601 103.134C132.601 149.184 200.006 233.115 225.83 263.581C231.061 269.752 240.416 269.752 245.639 263.581C271.463 233.115 338.868 149.184 338.868 103.134C338.868 46.1729 292.696 0 235.735 0ZM235.735 137.512C216.745 137.512 201.357 122.124 201.357 103.134C201.357 84.1441 216.745 68.7559 235.735 68.7559C254.724 68.7559 270.112 84.1441 270.112 103.134C270.112 122.124 254.724 137.512 235.735 137.512ZM16.4687 176.76C11.6081 178.704 7.44144 182.06 4.50605 186.394C1.57065 190.729 0.00116411 195.843 0 201.078L0 405.971C0 415.237 9.35571 421.572 17.9584 418.134L130.964 366.698V175.917C123.728 162.837 117.81 150.101 113.57 137.921L16.4687 176.76ZM235.735 294.398C224.218 294.398 213.323 289.34 205.85 280.516C189.758 261.526 172.643 239.901 157.156 217.719V366.69L314.313 419.075V217.727C298.826 239.901 281.719 261.534 265.619 280.524C258.146 289.34 247.251 294.398 235.735 294.398ZM453.511 131.913L340.505 183.349V419.084L455 373.287C459.862 371.344 464.029 367.989 466.964 363.654C469.9 359.319 471.469 354.204 471.469 348.969V144.076C471.469 134.811 462.113 128.475 453.511 131.913Z" fill="white" />
</Svg>
</View>
<View style={styles.lastOptionView}>
<Text style={styles.textOption}>Localisation</Text>
<Switch style={{marginBottom: normalize(10), marginRight: 20}} value={isCheckedLocalisation} onValueChange={toggleLocalisation}/>
<Switch style={{ marginBottom: normalize(10), marginRight: 20 }} value={isCheckedLocalisation} onValueChange={toggleLocalisation} />
</View>
</View>
</View>
<View style={styles.titleMusic}>
<Svg width="32" height="23" viewBox="0 0 28 21">
<Path d="M5.84463 0.36924C5.37582 -0.0995746 4.59968 -0.13966 4.10723 0.35111C1.57056 2.8792 0 6.37809 0 10.243C0 14.2583 1.69511 17.8783 4.40753 20.4254C4.90303 20.8906 5.65829 20.8413 6.11707 20.3826C6.65205 19.8476 6.58697 18.9969 6.07118 18.5038C3.89425 16.4228 2.53916 13.4914 2.53916 10.243C2.53916 7.11727 3.79368 4.28541 5.82764 2.22202C6.3189 1.72366 6.36867 0.893273 5.84463 0.36924Z" fill="white"/>
<Path d="M8.82679 3.35124C8.37113 2.89557 7.6097 2.83865 7.11937 3.32383C5.33696 5.08757 4.23193 7.53654 4.23193 10.2428C4.23193 13.1062 5.46885 15.6811 7.43617 17.4616C7.92997 17.9085 8.65988 17.8396 9.10066 17.3988C9.65615 16.8434 9.55157 15.969 9.03099 15.4783C7.63907 14.1659 6.7711 12.306 6.7711 10.2428C6.7711 8.29502 7.5446 6.52876 8.80209 5.23299C9.28672 4.73363 9.3654 3.88984 8.82679 3.35124Z" fill="white"/>
<Path d="M18.2575 3.35124C18.7132 2.89557 19.4746 2.83865 19.965 3.32383C21.7473 5.08757 22.8524 7.53654 22.8524 10.2428C22.8524 13.1062 21.6154 15.6811 19.6481 17.4616C19.1543 17.9085 18.4244 17.8396 17.9836 17.3988C17.4282 16.8434 17.5326 15.969 18.0533 15.4783C19.4453 14.1659 20.3132 12.306 20.3132 10.2428C20.3132 8.29502 19.5398 6.52876 18.2822 5.23299C17.7976 4.73363 17.7188 3.88984 18.2575 3.35124Z" fill="white"/>
<Path d="M21.2398 0.36924C21.7087 -0.0995746 22.4849 -0.13966 22.9773 0.35111C25.5139 2.8792 27.0845 6.37809 27.0845 10.243C27.0845 14.2583 25.3893 17.8783 22.677 20.4254C22.1815 20.8906 21.4262 20.8413 20.9675 20.3826C20.4324 19.8476 20.4975 18.9969 21.0133 18.5038C23.1902 16.4228 24.5453 13.4914 24.5453 10.243C24.5453 7.11727 23.2908 4.28541 21.2567 2.22202C20.7655 1.72366 20.7157 0.893273 21.2398 0.36924Z" fill="white"/>
<Path d="M13.5422 7.70361C12.1399 7.70361 11.0031 8.84043 11.0031 10.2428C11.0031 11.6451 12.1399 12.7819 13.5422 12.7819C14.9445 12.7819 16.0814 11.6451 16.0814 10.2428C16.0814 8.84043 14.9445 7.70361 13.5422 7.70361Z" fill="white"/>
<Path d="M5.84463 0.36924C5.37582 -0.0995746 4.59968 -0.13966 4.10723 0.35111C1.57056 2.8792 0 6.37809 0 10.243C0 14.2583 1.69511 17.8783 4.40753 20.4254C4.90303 20.8906 5.65829 20.8413 6.11707 20.3826C6.65205 19.8476 6.58697 18.9969 6.07118 18.5038C3.89425 16.4228 2.53916 13.4914 2.53916 10.243C2.53916 7.11727 3.79368 4.28541 5.82764 2.22202C6.3189 1.72366 6.36867 0.893273 5.84463 0.36924Z" fill={style.Text} />
<Path d="M8.82679 3.35124C8.37113 2.89557 7.6097 2.83865 7.11937 3.32383C5.33696 5.08757 4.23193 7.53654 4.23193 10.2428C4.23193 13.1062 5.46885 15.6811 7.43617 17.4616C7.92997 17.9085 8.65988 17.8396 9.10066 17.3988C9.65615 16.8434 9.55157 15.969 9.03099 15.4783C7.63907 14.1659 6.7711 12.306 6.7711 10.2428C6.7711 8.29502 7.5446 6.52876 8.80209 5.23299C9.28672 4.73363 9.3654 3.88984 8.82679 3.35124Z" fill={style.Text} />
<Path d="M18.2575 3.35124C18.7132 2.89557 19.4746 2.83865 19.965 3.32383C21.7473 5.08757 22.8524 7.53654 22.8524 10.2428C22.8524 13.1062 21.6154 15.6811 19.6481 17.4616C19.1543 17.9085 18.4244 17.8396 17.9836 17.3988C17.4282 16.8434 17.5326 15.969 18.0533 15.4783C19.4453 14.1659 20.3132 12.306 20.3132 10.2428C20.3132 8.29502 19.5398 6.52876 18.2822 5.23299C17.7976 4.73363 17.7188 3.88984 18.2575 3.35124Z" fill={style.Text} />
<Path d="M21.2398 0.36924C21.7087 -0.0995746 22.4849 -0.13966 22.9773 0.35111C25.5139 2.8792 27.0845 6.37809 27.0845 10.243C27.0845 14.2583 25.3893 17.8783 22.677 20.4254C22.1815 20.8906 21.4262 20.8413 20.9675 20.3826C20.4324 19.8476 20.4975 18.9969 21.0133 18.5038C23.1902 16.4228 24.5453 13.4914 24.5453 10.243C24.5453 7.11727 23.2908 4.28541 21.2567 2.22202C20.7655 1.72366 20.7157 0.893273 21.2398 0.36924Z" fill={style.Text} />
<Path d="M13.5422 7.70361C12.1399 7.70361 11.0031 8.84043 11.0031 10.2428C11.0031 11.6451 12.1399 12.7819 13.5422 12.7819C14.9445 12.7819 16.0814 11.6451 16.0814 10.2428C16.0814 8.84043 14.9445 7.70361 13.5422 7.70361Z" fill={style.Text} />
</Svg>
<Text style={[styles.textOption, {marginLeft: 10}]}>En cours découte...</Text>
<Text style={[styles.textOption, { marginLeft: 10 }]}>En cours découte...</Text>
</View>
<View style={styles.musicActually}>
<CardMusic image="https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png" title='Bambina' description="PNL"/>
<Image source={require("../assets/images/FladyShadow.png")} style={styles.mascot}/>
<CardMusic image={currentMusic.image} title={currentMusic.title} description="PNL" />
<Image source={require("../assets/images/FladyShadow.png")} style={styles.mascot} />
</View>
<View style={styles.deconnectedOption}>
<View style={styles.buttonDeconectedOption}>
<Svg width="23" height="24" viewBox="0 0 23 24">
<Path d="M4.36916 23.102C4.03419 23.102 3.71379 22.9855 3.43707 22.7671L0.5243 20.3349C0.360787 20.2004 0.229004 20.0315 0.138369 19.8401C0.0477338 19.6488 0.000485206 19.4398 0 19.2281L0 3.87773C0 3.44081 0.18933 3.03302 0.5243 2.75631L3.43707 0.324142C3.87399 -0.0253914 4.47111 -0.0982107 4.98085 0.134811C5.23365 0.251805 5.44759 0.438845 5.59731 0.673748C5.74703 0.908652 5.82624 1.18157 5.82555 1.46012V21.6602C5.82624 21.9388 5.74703 22.2117 5.59731 22.4466C5.44759 22.6815 5.23365 22.8685 4.98085 22.9855C4.79152 23.0583 4.57306 23.102 4.36916 23.102ZM17.4767 15.9221V7.18373C17.4767 6.52835 18.2631 6.20795 18.7146 6.67399L22.574 10.5334C23.142 11.1014 23.142 12.0189 22.574 12.5869L18.7146 16.4463C18.6119 16.547 18.4817 16.615 18.3405 16.6418C18.1992 16.6686 18.0532 16.6529 17.9208 16.5969C17.7885 16.5408 17.6756 16.4468 17.5966 16.3267C17.5175 16.2066 17.4758 16.0658 17.4767 15.9221Z" fill="white"/>
<Path d="M5.09735 3.54297H13.1075C13.5153 3.54297 13.8357 3.86337 13.8357 4.27116V7.91213M5.09735 19.5632H13.1075C13.5153 19.5632 13.8357 19.2428 13.8357 18.835V15.1941M21.8458 11.5531H10.1947" stroke="white" stroke-linecap="round"/>
<Path d="M4.36916 23.102C4.03419 23.102 3.71379 22.9855 3.43707 22.7671L0.5243 20.3349C0.360787 20.2004 0.229004 20.0315 0.138369 19.8401C0.0477338 19.6488 0.000485206 19.4398 0 19.2281L0 3.87773C0 3.44081 0.18933 3.03302 0.5243 2.75631L3.43707 0.324142C3.87399 -0.0253914 4.47111 -0.0982107 4.98085 0.134811C5.23365 0.251805 5.44759 0.438845 5.59731 0.673748C5.74703 0.908652 5.82624 1.18157 5.82555 1.46012V21.6602C5.82624 21.9388 5.74703 22.2117 5.59731 22.4466C5.44759 22.6815 5.23365 22.8685 4.98085 22.9855C4.79152 23.0583 4.57306 23.102 4.36916 23.102ZM17.4767 15.9221V7.18373C17.4767 6.52835 18.2631 6.20795 18.7146 6.67399L22.574 10.5334C23.142 11.1014 23.142 12.0189 22.574 12.5869L18.7146 16.4463C18.6119 16.547 18.4817 16.615 18.3405 16.6418C18.1992 16.6686 18.0532 16.6529 17.9208 16.5969C17.7885 16.5408 17.6756 16.4468 17.5966 16.3267C17.5175 16.2066 17.4758 16.0658 17.4767 15.9221Z" fill="white" />
<Path d="M5.09735 3.54297H13.1075C13.5153 3.54297 13.8357 3.86337 13.8357 4.27116V7.91213M5.09735 19.5632H13.1075C13.5153 19.5632 13.8357 19.2428 13.8357 18.835V15.1941M21.8458 11.5531H10.1947" stroke="white" stroke-linecap="round" />
</Svg>
</View>
<TouchableOpacity onPress={() => console.log("Tkt t deconnecter")}>
<TouchableOpacity onPress={() => Deconnection()}>
<Text style={styles.textDeconnectionOption}>Se deconnecter</Text>
</TouchableOpacity>
</View>
@ -143,182 +340,3 @@ export default function Setting() {
</DismissKeyboard>
);
};
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: "#141414",
},
container: {
marginTop: 30,
marginHorizontal: normalize(25),
flex: 1,
backgroundColor: '#141414',
},
title: {
fontSize: normalize(30),
fontWeight: 'bold',
color: 'white',
alignItems: 'center',
},
search: {
paddingVertical: 9,
backgroundColor: "#232123",
borderRadius: 13,
flexDirection: 'row',
marginTop: 9,
marginBottom: 22
},
inputSearch: {
placeholderTextColor:'red',
color: 'white',
width: normalize(350),
},
profil: {
paddingVertical: 9,
backgroundColor: "#232123",
borderRadius: 13,
flexDirection: 'row',
alignItems: 'center',
marginBottom: normalize(45)
},
imageProfil: {
marginLeft: 15,
marginRight: 7,
width: 50,
height: 50
},
NameProfil: {
fontWeight: 'bold',
color: 'white',
fontSize: normalize(22)
},
description: {
color: 'white',
fontSize: normalize(15)
},
profilContainer: {
flex: 1,
marginLeft: 9,
alignItems: 'flex-start',
justifyContent: 'center',
},
buttonSetting: {
width: normalize(17),
height: normalize(17),
marginRight: 22
},
body: {
paddingTop: normalize(10),
backgroundColor: "#232123",
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45),
paddingLeft: normalize(10),
},
view: {
backgroundColor: '#fe9500',
padding: 5,
borderRadius: 10,
marginLeft: 15,
marginBottom: normalize(11)
},
Option: {
flexDirection: 'row',
alignItems: 'center',
},
secondOption: {
marginTop: normalize(11),
flexDirection: 'row',
alignItems: 'center',
},
textOption: {
fontSize: normalize(18),
color: 'white',
fontWeight: 'bold',
marginBottom: normalize(8)
},
firstOptionView: {
flex: 1,
marginLeft: 15,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: '#403F3F'
},
deconnectedOption: {
paddingVertical: 9,
paddingLeft: 5,
backgroundColor: "#232123",
borderRadius: 13,
flexDirection: 'row',
alignItems: 'center',
},
buttonDeconectedOption: {
backgroundColor: '#DF0404',
padding: 5,
borderRadius: 10,
marginLeft: 15
},
textDeconnectionOption: {
fontSize: normalize(18),
color: '#F80404',
fontWeight: 'bold',
marginLeft: 12
},
notification: {
backgroundColor: '#fe3c30',
padding: 5,
borderRadius: 10,
marginLeft: 15,
marginBottom: normalize(11)
},
secondOptionView: {
flex: 1,
marginLeft: 15,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: '#403F3F'
},
lastOptionView: {
flex: 1,
marginLeft: 15,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center'
},
localisation: {
backgroundColor: '#0835A7',
padding: 5,
borderRadius: 10,
marginLeft: 15,
marginBottom: normalize(11)
},
lastOption: {
marginTop: normalize(11),
flexDirection: 'row',
alignItems: 'center',
},
musicActually: {
paddingTop: normalize(17),
backgroundColor: "#232123",
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45)
},
titleMusic: {
flexDirection: 'row',
marginBottom: 5
},
mascot: {
width: normalize(90),
height: normalize(90),
position: 'absolute',
right: normalize(0),
top: normalize(10)
}
})

@ -1,13 +1,16 @@
import React, { useState, useRef } from 'react';
import { View, Text, StyleSheet, TouchableWithoutFeedback, Keyboard, ScrollView, Image } from 'react-native';
import { View, Text, StyleSheet, TouchableWithoutFeedback, Keyboard, ScrollView, Image } from 'react-native';
import { TextInput, TouchableOpacity } from 'react-native-gesture-handler';
import { Svg, Path } from 'react-native-svg';
import Modal from "react-native-modal";
import {useNavigation} from "@react-navigation/native";
import { useNavigation } from "@react-navigation/native";
import { useSelector } from 'react-redux';
import normalize from '../components/Normalize';
import * as ImagePicker from 'expo-image-picker';
import { SafeAreaView } from 'react-native-safe-area-context';
import { GraphicalCharterDark } from '../assets/GraphicalCharterDark';
import { GraphicalCharterLight } from '../assets/GraphicalCharterLight';
// @ts-ignore
const DismissKeyboard = ({ children }) => (
@ -18,6 +21,10 @@ const DismissKeyboard = ({ children }) => (
export default function SettingProfil() {
//Dark Mode
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? GraphicalCharterLight : GraphicalCharterDark;
const [image, setImage] = useState(null);
const navigation = useNavigation();
const [currentIndex, setCurrentIndex] = useState(0);
@ -32,19 +39,231 @@ export default function SettingProfil() {
const pickImage = async () => {
// No permissions request is necessary for launching the image library
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result);
if (!result.canceled) {
setImage(result.assets[0].uri);
setImage(result.assets[0].uri);
}
};
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: style.body,
},
container: {
marginTop: 20,
marginHorizontal: normalize(25),
flex: 1,
backgroundColor: style.body,
},
buttonSetting: {
width: normalize(17),
height: normalize(17),
marginRight: 5
},
modalContent: {
position: 'absolute',
top: '5%',
left: '-5%',
right: '-5%',
height: '100%',
backgroundColor: style.body,
borderRadius: 12
},
modalView: {
flexDirection: 'row',
marginTop: 20,
marginLeft: 30,
marginBottom: normalize(45)
},
exit: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center'
},
textExit: {
fontSize: normalize(20),
color: '#454545',
fontWeight: 'bold'
},
profilHead: {
alignItems: 'center',
},
title: {
fontSize: normalize(30),
fontWeight: 'bold',
color: style.Text,
},
imageWrapper: {
width: 126,
height: 126,
borderRadius: 63,
borderWidth: 3,
borderColor: style.Text,
overflow: 'hidden',
marginVertical: 20,
alignItems: 'center',
justifyContent: 'center',
},
imageProfil: {
width: 120,
height: 120,
},
editButton: {
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: '#7C7C7C',
alignItems: 'center',
justifyContent: 'center'
},
body: {
paddingVertical: 9,
paddingLeft: normalize(10),
backgroundColor: style.Card,
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45)
},
textOption: {
fontSize: normalize(18),
color: style.Text,
fontWeight: 'bold',
marginLeft: 12
},
deleteOption: {
paddingVertical: 9,
paddingLeft: 5,
backgroundColor: style.Card,
borderRadius: 13,
flexDirection: 'row',
alignItems: 'center',
},
textOptionPassword: {
fontSize: normalize(18),
color: '#1c77fb',
marginLeft: 12
},
buttonDeleteOption: {
backgroundColor: '#DF0404',
padding: 5,
borderRadius: 10,
marginLeft: 15
},
textDeleteOption: {
fontSize: normalize(18),
color: '#F80404',
marginLeft: 12
},
optionId: {
flexDirection: 'row',
marginBottom: 20,
},
optionMail: {
flexDirection: 'row',
},
textInputId: {
marginLeft: 50,
width: '57%',
color: 'white',
fontSize: normalize(18),
},
textInputMail: {
marginLeft: 100,
color: 'white',
width: '57%',
fontSize: normalize(18)
},
passwordOption: {
paddingVertical: 9,
paddingLeft: normalize(10),
backgroundColor: style.Card,
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45)
},
passwordIcon: {
backgroundColor: '#8e8d92',
padding: 5,
paddingHorizontal: 8,
borderRadius: 10,
marginLeft: 10
},
optionView: {
flexDirection: 'row',
marginTop: 5
},
cancelText: {
fontSize: normalize(20),
color: '#1c77fb'
},
updateText: {
marginLeft: 60,
fontSize: normalize(20),
color: '#404040'
},
titlePassword: {
fontSize: normalize(22),
color: style.Text,
marginLeft: 50
},
warning: {
color: '#98989f',
fontSize: normalize(15)
},
warningView: {
marginTop: 10,
paddingHorizontal: 40
},
bodyModal: {
paddingVertical: 12,
paddingLeft: 30,
marginHorizontal: normalize(25),
backgroundColor: style.Card,
borderRadius: 13,
alignItems: 'flex-start'
},
optionModalWithUnderline: {
flexDirection: 'row',
borderBottomWidth: 1,
borderColor: style.Line,
paddingBottom: 10,
marginBottom: 10
},
optionModal: {
flexDirection: 'row'
},
textOptionModal: {
fontSize: normalize(18),
color: style.Text,
fontWeight: 'bold',
},
textInputNewModal: {
marginLeft: 40,
color: style.Text,
width: '67.5%',
fontSize: normalize(18)
},
textInputConfirmModal: {
marginLeft: 30,
color: style.Text,
fontSize: normalize(18)
},
textInputOldModal: {
marginLeft: 55,
color: style.Text,
width: '67.5%',
fontSize: normalize(18)
}
})
return (
<DismissKeyboard>
<SafeAreaView style={styles.mainSafeArea}>
@ -52,8 +271,8 @@ export default function SettingProfil() {
<View style={styles.container}>
<TouchableOpacity onPress={() => navigation.navigate('Setting')}>
<View style={styles.exit}>
<Image style={styles.buttonSetting} source={require('../assets/icons/icons/buttonProfil_Inverse.png')}/>
<Text style={styles.textExit}>Exit</Text>
<Image style={styles.buttonSetting} source={require('../assets/icons/icons/buttonProfil_Inverse.png')} />
<Text style={styles.textExit}>Exit</Text>
</View>
</TouchableOpacity>
<View style={styles.profilHead}>
@ -64,27 +283,27 @@ export default function SettingProfil() {
<View style={styles.editButton}>
<TouchableOpacity onPress={pickImage} >
<Image
source={require('../assets/icons/icons/edit.png')} style={{resizeMode: "stretch", height: '85%', aspectRatio: 1}}
/>
</TouchableOpacity>
source={require('../assets/icons/icons/edit.png')} style={{ resizeMode: "stretch", height: '85%', aspectRatio: 1 }}
/>
</TouchableOpacity>
</View>
</View>
<View style={styles.body}>
<View style={styles.optionId}>
<Text style={styles.textOption}>Identifiant</Text>
<TextInput placeholderTextColor='#828288' placeholder='Flady' style={styles.textInputId}/>
<TextInput placeholderTextColor='#828288' placeholder='Flady' style={styles.textInputId} />
</View>
<View style={styles.optionMail}>
<Text style={styles.textOption}>Mail</Text>
<TextInput placeholderTextColor='#828288' placeholder='emre.kartal@etu.uca.fr' style={styles.textInputMail}/>
<TextInput placeholderTextColor='#828288' placeholder='emre.kartal@etu.uca.fr' style={styles.textInputMail} />
</View>
</View>
<View style={styles.passwordOption}>
<TouchableOpacity style={{flexDirection: 'row'}} onPress={handleModal}>
<TouchableOpacity style={{ flexDirection: 'row' }} onPress={handleModal}>
<View style={styles.passwordIcon}>
<Svg width="14" height="20" viewBox="0 0 14 26" >
<Path fill-rule="evenodd" clip-rule="evenodd" d="M3.27129 1.75541C4.23026 1.10258 5.34904 0.723459 6.50733 0.658814C7.66563 0.594169 8.81964 0.846441 9.84531 1.38851C10.7879 1.8833 11.593 2.6042 12.1889 3.48739C12.9939 4.70913 13.3604 6.16796 13.2283 7.62511C13.0962 9.08225 12.4733 10.4514 11.4617 11.5084C11.031 11.9508 10.5387 12.3292 9.99839 12.6274L10.1591 14.3578L9.96312 14.9126L9.00438 15.8973L10.5193 17.3723L10.5326 18.3689L9.05762 19.8838L10.5725 21.3588L10.5858 22.3554L7.63588 25.3852L6.63925 25.3985L4.30933 23.13L4.09638 22.6355L3.96398 12.721C3.36598 12.4165 2.82055 12.0182 2.34835 11.5414C1.68473 10.8774 1.17578 10.0751 0.857766 9.19177C0.539757 8.30846 0.420525 7.36587 0.508571 6.4312C0.596616 5.49652 0.88977 4.59278 1.36714 3.78439C1.8445 2.976 2.49533 2.28386 3.27129 1.75541ZM11.8389 7.50421C11.9428 6.36957 11.6584 5.23325 11.0323 4.28134L11.0412 4.28222C10.5801 3.58952 9.95326 3.02302 9.21756 2.63419C8.48185 2.24536 7.66065 2.04653 6.82857 2.05576C5.99649 2.06499 5.1799 2.28199 4.453 2.68704C3.72611 3.0921 3.11195 3.67236 2.66632 4.37512C2.07477 5.33215 1.8204 6.45957 1.94372 7.57788C2.06704 8.69619 2.56095 9.7411 3.34682 10.5462C3.79752 11.0047 4.33268 11.3684 4.92505 11.6127L5.36528 12.2577L5.5017 22.3236L7.1176 23.8969L9.08424 21.8771L7.56933 20.4021L7.55602 19.4055L9.031 17.8905L7.5161 16.4156L7.50279 15.4189L8.72702 14.1616L8.56231 12.2778L8.97256 11.5736C9.52979 11.3206 10.0346 10.9652 10.4608 10.526C11.249 9.70384 11.7349 8.63846 11.8389 7.50421ZM8.25568 5.66411C8.22318 5.47735 8.15334 5.29906 8.05034 5.13991C7.94734 4.98077 7.8133 4.84403 7.65623 4.73789C7.49916 4.63174 7.3223 4.55837 7.13622 4.52216C6.95014 4.48596 6.75867 4.48765 6.57326 4.52716C6.38785 4.56666 6.21232 4.64315 6.05716 4.75206C5.902 4.86098 5.7704 5.00007 5.67024 5.16101C5.57007 5.32196 5.50341 5.50146 5.47422 5.68877C5.44503 5.87608 5.45393 6.06735 5.50038 6.25114C5.58972 6.60469 5.81261 6.90986 6.12222 7.10253C6.43182 7.29521 6.80405 7.3604 7.16071 7.28441C7.51737 7.20843 7.8307 6.99717 8.03488 6.69503C8.23906 6.39289 8.31821 6.02337 8.25568 5.66411Z" fill="white"/>
<Path fill-rule="evenodd" clip-rule="evenodd" d="M3.27129 1.75541C4.23026 1.10258 5.34904 0.723459 6.50733 0.658814C7.66563 0.594169 8.81964 0.846441 9.84531 1.38851C10.7879 1.8833 11.593 2.6042 12.1889 3.48739C12.9939 4.70913 13.3604 6.16796 13.2283 7.62511C13.0962 9.08225 12.4733 10.4514 11.4617 11.5084C11.031 11.9508 10.5387 12.3292 9.99839 12.6274L10.1591 14.3578L9.96312 14.9126L9.00438 15.8973L10.5193 17.3723L10.5326 18.3689L9.05762 19.8838L10.5725 21.3588L10.5858 22.3554L7.63588 25.3852L6.63925 25.3985L4.30933 23.13L4.09638 22.6355L3.96398 12.721C3.36598 12.4165 2.82055 12.0182 2.34835 11.5414C1.68473 10.8774 1.17578 10.0751 0.857766 9.19177C0.539757 8.30846 0.420525 7.36587 0.508571 6.4312C0.596616 5.49652 0.88977 4.59278 1.36714 3.78439C1.8445 2.976 2.49533 2.28386 3.27129 1.75541ZM11.8389 7.50421C11.9428 6.36957 11.6584 5.23325 11.0323 4.28134L11.0412 4.28222C10.5801 3.58952 9.95326 3.02302 9.21756 2.63419C8.48185 2.24536 7.66065 2.04653 6.82857 2.05576C5.99649 2.06499 5.1799 2.28199 4.453 2.68704C3.72611 3.0921 3.11195 3.67236 2.66632 4.37512C2.07477 5.33215 1.8204 6.45957 1.94372 7.57788C2.06704 8.69619 2.56095 9.7411 3.34682 10.5462C3.79752 11.0047 4.33268 11.3684 4.92505 11.6127L5.36528 12.2577L5.5017 22.3236L7.1176 23.8969L9.08424 21.8771L7.56933 20.4021L7.55602 19.4055L9.031 17.8905L7.5161 16.4156L7.50279 15.4189L8.72702 14.1616L8.56231 12.2778L8.97256 11.5736C9.52979 11.3206 10.0346 10.9652 10.4608 10.526C11.249 9.70384 11.7349 8.63846 11.8389 7.50421ZM8.25568 5.66411C8.22318 5.47735 8.15334 5.29906 8.05034 5.13991C7.94734 4.98077 7.8133 4.84403 7.65623 4.73789C7.49916 4.63174 7.3223 4.55837 7.13622 4.52216C6.95014 4.48596 6.75867 4.48765 6.57326 4.52716C6.38785 4.56666 6.21232 4.64315 6.05716 4.75206C5.902 4.86098 5.7704 5.00007 5.67024 5.16101C5.57007 5.32196 5.50341 5.50146 5.47422 5.68877C5.44503 5.87608 5.45393 6.06735 5.50038 6.25114C5.58972 6.60469 5.81261 6.90986 6.12222 7.10253C6.43182 7.29521 6.80405 7.3604 7.16071 7.28441C7.51737 7.20843 7.8307 6.99717 8.03488 6.69503C8.23906 6.39289 8.31821 6.02337 8.25568 5.66411Z" fill="white" />
</Svg>
</View>
<View style={styles.optionView}>
@ -96,12 +315,12 @@ export default function SettingProfil() {
<View style={styles.deleteOption}>
<View style={styles.buttonDeleteOption}>
<Svg width="20" height="22" viewBox="0 0 25 31">
<Path d="M21.4265 16.0194V21.7371V28.4078L19.8044 29.8373H10.6125L21.4265 16.0194Z" fill="#686868"/>
<Path d="M9.41089 3.4031V1H15.4186V3.4031" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<Path d="M21.4264 8.81006V27.4341C21.4264 28.7613 20.3504 29.8372 19.0233 29.8372H5.80618C4.47901 29.8372 3.40308 28.7613 3.40308 27.4341V8.81006" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<Path d="M1 3.40308H23.8295V5.80618H1V3.40308Z" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<Path d="M15.4185 10.7626V26.8333" stroke="white" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<Path d="M9.41089 10.7626V26.8333" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<Path d="M21.4265 16.0194V21.7371V28.4078L19.8044 29.8373H10.6125L21.4265 16.0194Z" fill="#686868" />
<Path d="M9.41089 3.4031V1H15.4186V3.4031" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" />
<Path d="M21.4264 8.81006V27.4341C21.4264 28.7613 20.3504 29.8372 19.0233 29.8372H5.80618C4.47901 29.8372 3.40308 28.7613 3.40308 27.4341V8.81006" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" />
<Path d="M1 3.40308H23.8295V5.80618H1V3.40308Z" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" />
<Path d="M15.4185 10.7626V26.8333" stroke="white" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" />
<Path d="M9.41089 10.7626V26.8333" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" />
</Svg>
</View>
<TouchableOpacity onPress={() => console.log("Tkt t deconnecter")}>
@ -121,20 +340,20 @@ export default function SettingProfil() {
<View>
<Text style={styles.updateText}>Modifier</Text>
</View>
</TouchableOpacity>
</TouchableOpacity>
</View>
<View style={styles.bodyModal}>
<View style={styles.optionModalWithUnderline}>
<Text style={styles.textOptionModal}>Ancien</Text>
<TextInput placeholderTextColor='#828288' placeholder="saisir l'ancien mot de passe" style={styles.textInputOldModal}/>
<TextInput placeholderTextColor='#828288' placeholder="saisir l'ancien mot de passe" style={styles.textInputOldModal} />
</View>
<View style={styles.optionModalWithUnderline}>
<Text style={styles.textOptionModal}>Nouveau</Text>
<TextInput placeholderTextColor='#828288' placeholder='saisir le mot de passe' style={styles.textInputNewModal}/>
<TextInput placeholderTextColor='#828288' placeholder='saisir le mot de passe' style={styles.textInputNewModal} />
</View>
<View style={styles.optionModal}>
<Text style={styles.textOptionModal}>Confirmer</Text>
<TextInput placeholderTextColor='#828288' placeholder='mot de passe' style={styles.textInputConfirmModal}/>
<TextInput placeholderTextColor='#828288' placeholder='mot de passe' style={styles.textInputConfirmModal} />
</View>
</View>
<View style={styles.warningView}>
@ -147,216 +366,4 @@ export default function SettingProfil() {
</SafeAreaView>
</DismissKeyboard>
);
};
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: "#141414",
},
container: {
marginTop: 20,
marginHorizontal: normalize(25),
flex: 1,
backgroundColor: '#141414',
},
buttonSetting: {
width: normalize(17),
height: normalize(17),
marginRight: 5
},
modalContent: {
position: 'absolute',
top: '5%',
left: '-5%',
right: '-5%',
height: '100%',
backgroundColor: '#141414',
borderRadius: 12
},
modalView: {
flexDirection: 'row',
marginTop: 20,
marginLeft: 30,
marginBottom: normalize(45)
},
exit: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center'
},
textExit: {
fontSize: normalize(20),
color: '#454545',
fontWeight: 'bold'
},
profilHead: {
alignItems: 'center',
},
title: {
fontSize: normalize(30),
fontWeight: 'bold',
color: 'white',
},
imageWrapper: {
width: 126,
height: 126,
borderRadius: 63,
borderWidth: 3,
borderColor: 'white',
overflow: 'hidden',
marginVertical: 20,
alignItems: 'center',
justifyContent: 'center',
},
imageProfil: {
width: 120,
height: 120,
},
editButton: {
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: '#7C7C7C',
alignItems: 'center',
justifyContent: 'center'
},
body: {
paddingVertical: 9,
paddingLeft: normalize(10),
backgroundColor: "#232123",
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45)
},
textOption: {
fontSize: normalize(18),
color: 'white',
fontWeight: 'bold',
marginLeft: 12
},
deleteOption: {
paddingVertical: 9,
paddingLeft: 5,
backgroundColor: "#232123",
borderRadius: 13,
flexDirection: 'row',
alignItems: 'center',
},
textOptionPassword: {
fontSize: normalize(18),
color: '#1c77fb',
marginLeft: 12
},
buttonDeleteOption: {
backgroundColor: '#DF0404',
padding: 5,
borderRadius: 10,
marginLeft: 15
},
textDeleteOption: {
fontSize: normalize(18),
color: '#F80404',
marginLeft: 12
},
optionId: {
flexDirection:'row',
marginBottom: 20,
},
optionMail: {
flexDirection:'row',
},
textInputId: {
marginLeft: 50,
width: '57%',
color: 'white',
fontSize: normalize(18),
},
textInputMail: {
marginLeft: 100,
color: 'white',
width: '57%',
fontSize: normalize(18)
},
passwordOption: {
paddingVertical: 9,
paddingLeft: normalize(10),
backgroundColor: "#232123",
borderRadius: 13,
alignItems: 'flex-start',
marginBottom: normalize(45)
},
passwordIcon: {
backgroundColor: '#8e8d92',
padding: 5,
paddingHorizontal: 8,
borderRadius: 10,
marginLeft: 10
},
optionView: {
flexDirection: 'row',
marginTop: 5
},
cancelText: {
fontSize: normalize(20),
color: '#1c77fb'
},
updateText: {
marginLeft: 60,
fontSize: normalize(20),
color: '#404040'
},
titlePassword: {
fontSize: normalize(22),
color: 'white',
marginLeft: 50
},
warning: {
color: '#98989f',
fontSize: normalize(15)
},
warningView: {
marginTop: 10,
paddingHorizontal: 40
},
bodyModal: {
paddingVertical: 12,
paddingLeft: 30,
marginHorizontal: normalize(25),
backgroundColor: "#232123",
borderRadius: 13,
alignItems: 'flex-start'
},
optionModalWithUnderline: {
flexDirection: 'row',
borderBottomWidth: 1,
borderColor: '#403F3F',
paddingBottom: 10,
marginBottom: 10
},
optionModal: {
flexDirection: 'row'
},
textOptionModal: {
fontSize: normalize(18),
color: 'white',
fontWeight: 'bold',
},
textInputNewModal: {
marginLeft: 40,
color: 'white',
width: '67.5%',
fontSize: normalize(18)
},
textInputConfirmModal: {
marginLeft: 30,
color: 'white',
fontSize: normalize(18)
},
textInputOldModal: {
marginLeft: 55,
color: 'white',
width: '67.5%',
fontSize: normalize(18)
}
})
};

@ -1,6 +1,6 @@
import { SharedElement } from "react-navigation-shared-element";
import { NavigationProp, RouteProp } from "@react-navigation/native";
import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity, SafeAreaView } from "react-native";
import { View, Text, Image, StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity, SafeAreaView } 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";
@ -13,71 +13,71 @@ import { RequestHandler } from "../services/spotify/spotifyRequestHandler/utils"
import { FetchRequest } from "expo-auth-session/build/Fetch";
interface SpotProps {
spot: { name: string, sourceUrl: string, index : number };
spot: { name: string, sourceUrl: string, index: number };
}
const halfPi = Math.PI/2;
const halfPi = Math.PI / 2;
// const {width : wWidht} = Dimensions.get("window");
//@ts-ignore
const SpotDetailsPage = ({ route }) => {
const {width, height} = useWindowDimensions();
console.log(route);
const spot : { name: string, sourceUrl: string, index : number } = route.params.spot;
const [currentspot, setCurrentspot] = useState(spot);
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 { width, height } = useWindowDimensions();
console.log(route);
const spot: { name: string, sourceUrl: string, index: number } = route.params.spot;
const [currentspot, setCurrentspot] = useState(spot);
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 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 () => {
// })
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 :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);
// }
};
console.log('get in Sound');
const { sound } = await Audio.Sound.createAsync({ uri: 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(
@ -85,193 +85,194 @@ const SpotDetailsPage = ({ route }) => {
{ shouldPlay: true }
);
setSound(newSound);
} else {
//@ts-ignore
//@ts-ignore
await sound.playAsync();
}
};
const handleStopSound = async () => {
if (sound !== null) {
//@ts-ignore
//@ts-ignore
await sound.stopAsync();
}
else{
setIsPlaying(true);
else {
setIsPlaying(true);
}
};
useEffect(() => {
useEffect(() => {
return sound ? () => {
console.log('Unloading Sound');
//@ts-ignore
sound.unloadAsync();
}
: undefined;
}, [sound]);
// useEffect(() => {
// if(isPlaying){
// }
// })
console.log(spot);
const sensor = useAnimatedSensor(SensorType.ROTATION);
const styleAniamatedImage = useAnimatedStyle(() => {
const {yaw, pitch, roll} = sensor.sensor.value;
const verticalAxis =interpolate(
pitch,
[-halfPi,halfPi],
[-45, 45]
)
const horizontalAxis =interpolate(
roll,
[-halfPi*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);
return (
<SafeAreaView style={styles.mainSafeArea}>
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
console.log('Unloading Sound');
//@ts-ignore
sound.unloadAsync();
}
: undefined;
}, [sound]);
// useEffect(() => {
// if(isPlaying){
// }
// })
console.log(spot);
const sensor = useAnimatedSensor(SensorType.ROTATION);
const styleAniamatedImage = useAnimatedStyle(() => {
const { yaw, pitch, roll } = sensor.sensor.value;
const verticalAxis = interpolate(
pitch,
[-halfPi, halfPi],
[-45, 45]
)
const horizontalAxis = interpolate(
roll,
[-halfPi * 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);
return (
<SafeAreaView style={styles.mainSafeArea}>
<View style={{ flex: 1, justifyContent: 'flex-start', alignItems: 'center' }}>
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
<View style={{borderWidth : 1, borderColor : 'red'}}>
<Animated.Image
source={{
uri:currentspot.sourceUrl ,
}}
style={[
{
width: 370,
height: 370,
borderRadius : 24,
resizeMode: 'stretch',
},styleAniamatedImage
]}
/>
<Button title="Current Track"
onPress={() => {
getCurrentTrack()
// 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>
{/* </TapGestureHandler> */}
{/* Button */}
<View style={{ borderWidth: 1, borderColor: 'red' }}>
<Animated.Image
source={{
uri: currentspot.sourceUrl,
}}
style={[
{
width: 370,
height: 370,
borderRadius: 24,
resizeMode: 'stretch',
}, styleAniamatedImage
]}
/>
<Button title="Current Track"
onPress={() => {
getCurrentTrack()
// 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>
{/* </TapGestureHandler> */}
{/* Button */}
{/* <View style={detailRadicalStyle.container}>
@ -287,15 +288,15 @@ const SpotDetailsPage = ({ route }) => {
/>
</View> */}
{/* </SharedElement> */}
</View>
</SafeAreaView>
</View>
</SafeAreaView>
);
);
};
export default SpotDetailsPage;
const styles = StyleSheet.create ({
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
backgroundColor: "#141414",

@ -1,4 +1,4 @@
import { View, Text, Image, Animated ,PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, Touchable, TouchableOpacity, Modal, SafeAreaView, TextInput, Platform } from 'react-native'
import { View, Text, Image, Animated, PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, Touchable, TouchableOpacity, Modal, SafeAreaView, TextInput, Platform } from 'react-native'
import React, { useCallback, useEffect, useRef, useState, useTransition } from 'react'
import { LinearGradient } from 'expo-linear-gradient';
import * as Haptics from 'expo-haptics';
@ -19,19 +19,19 @@ import * as SecureStore from 'expo-secure-store';
interface LoginProps {
}
interface Params {
[key: string]: string;
}
interface Profile {
display_name: string;
email: string;
id: string;
}
[key: string]: string;
}
interface Profile {
display_name: string;
email: string;
id: string;
}
//generate random string
export const MY_SECURE_AUTH_STATE_KEY = 'MySecureAuthStateKey';
export const MY_SECURE_AUTH_STATE_KEY = 'MySecureAuthStateKey';
WebBrowser.maybeCompleteAuthSession();
WebBrowser.maybeCompleteAuthSession();
// Endpoint
const discovery = {
@ -39,162 +39,163 @@ const discovery = {
tokenEndpoint: 'https://accounts.spotify.com/api/token',
};
// save the spotifyToken
async function save(key : string, value : string) {
async function save(key: string, value: string) {
await SecureStore.setItemAsync(key, value);
}
export default function Login() {
// const [advice, setAdvice] = useState("dd");
// there we use implicit grant flow
const [request, response, promptAsync] = useAuthRequest(
{
responseType: AuthSession.ResponseType.Token,
clientId: '1f1e34e4b6ba48b388469dba80202b10',
scopes: ['user-read-private','user-read-email','user-read-playback-state','user-read-currently-playing','user-read-recently-played','playlist-modify-public','ugc-image-upload','user-modify-playback-state'],
usePKCE: false,
redirectUri: makeRedirectUri({
scheme: 'https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d',
useProxy : true
})
},
discovery
);
const getAdvice = async () => { axios.get("http://localhost:8080/api/spotify/exchange")
.then(response => {
console.log(response.data.message);
// setAdvice(response.data.message);
}).catch(function (error) {
console.log(error);
});
};
React.useEffect(() => {
if (response && response.type === 'success') {
console.log(response);
console.log("========================code=====================");
console.log(response.params.code)
console.log("=============================================");
console.log("========================acess=====================");
console.log(response.params.access_token)
console.log("=============================================");
const auth = response.params.access_token;
const storageValue = JSON.stringify(auth);
if (Platform.OS !== 'web') {
// Securely store the auth on your device
// save(MY_SECURE_AUTH_STATE_KEY, storageValue);
}
}
}, [response]);
const scopesArr = ['user-read-private','user-read-email','user-read-playback-state','user-read-currently-playing','user-read-recently-played','playlist-modify-public','ugc-image-upload','user-modify-playback-state'];
const scopes = scopesArr.join(' ');
//work so use this for my implementation
const getAuthorizationCode = async () => {
try {
const redirectUrl = "https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d"; //this will be something like https://auth.expo.io/@your-username/your-app-slug
const result = await AuthSession.startAsync({
authUrl:
'https://accounts.spotify.com/authorize' +
'?response_type=code' +
'&client_id=' +
"1f1e34e4b6ba48b388469dba80202b10" +
(scopes ? '&scope=' + encodeURIComponent(scopes) : '') +
'&redirect_uri=' +
encodeURIComponent(redirectUrl),
})
console.log(result);
return result.params.code;
} catch (err) {
console.error(err)
export default function Login() {
// const [advice, setAdvice] = useState("dd");
// there we use implicit grant flow
const [request, response, promptAsync] = useAuthRequest(
{
responseType: AuthSession.ResponseType.Token,
clientId: '1f1e34e4b6ba48b388469dba80202b10',
scopes: ['user-read-private', 'user-read-email', 'user-read-playback-state', 'user-read-currently-playing', 'user-read-recently-played', 'playlist-modify-public', 'ugc-image-upload', 'user-modify-playback-state'],
usePKCE: false,
redirectUri: makeRedirectUri({
scheme: 'https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d',
useProxy: true
})
},
discovery
);
const getAdvice = async () => {
axios.get("http://localhost:8080/api/spotify/exchange")
.then(response => {
console.log(response.data.message);
// setAdvice(response.data.message);
}).catch(function (error) {
console.log(error);
});
};
React.useEffect(() => {
if (response && response.type === 'success') {
console.log(response);
console.log("========================code=====================");
console.log(response.params.code)
console.log("=============================================");
console.log("========================acess=====================");
console.log(response.params.access_token)
console.log("=============================================");
const auth = response.params.access_token;
const storageValue = JSON.stringify(auth);
if (Platform.OS !== 'web') {
// Securely store the auth on your device
// save(MY_SECURE_AUTH_STATE_KEY, storageValue);
}
}
const getTokens = async () => {
try {
const authorizationCode = await getAuthorizationCode() //we wrote this function above
console.log(authorizationCode, "shhhhhhhhhhhhhheeeeeeeeeeeeeeeetttttttttttt");
const response = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
Authorization: 'Basic ' + (Buffer.from('1f1e34e4b6ba48b388469dba80202b10' + ':' + '779371c6d4994a68b8dd6e84b0873c82').toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `grant_type=authorization_code&code=${authorizationCode}&redirect_uri=https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d`,
});
const responseJson = await response.json();
console.log(responseJson.access_token, "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;
} catch (err) {
console.error(err);
}
}, [response]);
const scopesArr = ['user-read-private', 'user-read-email', 'user-read-playback-state', 'user-read-currently-playing', 'user-read-recently-played', 'playlist-modify-public', 'ugc-image-upload', 'user-modify-playback-state'];
const scopes = scopesArr.join(' ');
//work so use this for my implementation
const getAuthorizationCode = async () => {
try {
const redirectUrl = "https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d"; //this will be something like https://auth.expo.io/@your-username/your-app-slug
const result = await AuthSession.startAsync({
authUrl:
'https://accounts.spotify.com/authorize' +
'?response_type=code' +
'&client_id=' +
"1f1e34e4b6ba48b388469dba80202b10" +
(scopes ? '&scope=' + encodeURIComponent(scopes) : '') +
'&redirect_uri=' +
encodeURIComponent(redirectUrl),
})
console.log(result);
return result.params.code;
} catch (err) {
console.error(err)
}
}
const getTokens = async () => {
try {
const authorizationCode = await getAuthorizationCode() //we wrote this function above
console.log(authorizationCode, "shhhhhhhhhhhhhheeeeeeeeeeeeeeeetttttttttttt");
const response = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
Authorization: 'Basic ' + (Buffer.from('1f1e34e4b6ba48b388469dba80202b10' + ':' + '779371c6d4994a68b8dd6e84b0873c82').toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `grant_type=authorization_code&code=${authorizationCode}&redirect_uri=https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d`,
});
const responseJson = await response.json();
console.log(responseJson.access_token, "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;
} catch (err) {
console.error(err);
}
return (
<View style={styles.centeredView}>
<Text style={styles.textStyle}>Hello flad test logIn</Text>
<Button disabled={!request} title="Login"
onPress={() => {
getTokens()
// promptAsync();
}}
/>
</View>
);
}
return (
<View style={styles.centeredView}>
<Text style={styles.textStyle}>Hello flad test logIn</Text>
<Button disabled={!request} title="Login"
onPress={() => {
getTokens()
// promptAsync();
}}
/>
</View>
);
};
const styles = StyleSheet.create({
centeredView: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 22,
},
modalView: {
margin: 20,
backgroundColor: 'white',
borderRadius: 20,
padding: 35,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
},
header :{
alignItems : 'flex-end',
justifyContent: 'center',
centeredView: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 22,
},
modalView: {
margin: 20,
backgroundColor: 'white',
borderRadius: 20,
padding: 35,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
button: {
borderRadius: 20,
padding: 10,
elevation: 2,
},
buttonOpen: {
backgroundColor: '#F194FF',
},
textStyle: {
color: 'white',
fontWeight: 'bold',
textAlign: 'center',
},
close :{
alignSelf : 'flex-end',
backgroundColor : 'red',
justifyContent : 'center'
}
shadowOpacity: 0.25,
shadowRadius: 4,
},
header: {
alignItems: 'flex-end',
justifyContent: 'center',
},
button: {
borderRadius: 20,
padding: 10,
elevation: 2,
},
buttonOpen: {
backgroundColor: '#F194FF',
},
textStyle: {
color: 'white',
fontWeight: 'bold',
textAlign: 'center',
},
close: {
alignSelf: 'flex-end',
backgroundColor: 'red',
justifyContent: 'center'
}
})

@ -1,4 +1,4 @@
import { View, Text, Image ,PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, TouchableOpacity, SafeAreaView } from 'react-native'
import { View, Text, Image, PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable, TouchableOpacity, SafeAreaView } from 'react-native'
import React, { useCallback, useEffect, useRef, useState, useTransition } from 'react'
import { LinearGradient } from 'expo-linear-gradient';
import * as Haptics from 'expo-haptics';
@ -9,11 +9,11 @@ import Card from '../components/Card';
import { cards as cardArray, spotArray2 } from '../data/data'
import FladButton from '../components/button/button';
import axios from 'axios';
import AdjustSize from '../components/AdjustSize';
import * as SecureStore from 'expo-secure-store';
import { MY_SECURE_AUTH_STATE_KEY } from './login';
import * as AuthSession from 'expo-auth-session';
import normalize from '../components/Normalize';
import * as Location from 'expo-location';
import Icons from '../assets/icons/icons/icon';
import LottieView from 'lottie-react-native'
@ -39,27 +39,27 @@ interface NearbyUser {
longitude: number;
}
async function getUserData(accessToken : string) {
axios.get("https://api.spotify.com/v1/me",
{
headers: {
'Authorization': 'Bearer ' + accessToken,
"Content-Type" : "application/json"
}})
.then(response =>
{
if (response && response.statusText === 'success') {
console.log(response.data.message);
const userData = JSON.stringify(response.data);
const userId = response.data.id;
return {userId, userData}
}
})
.catch(function (error) {
console.log(error);
});
};
async function getUserData(accessToken: string) {
axios.get("https://api.spotify.com/v1/me",
{
headers: {
'Authorization': 'Bearer ' + accessToken,
"Content-Type": "application/json"
}
})
.then(response => {
if (response && response.statusText === 'success') {
console.log(response.data.message);
const userData = JSON.stringify(response.data);
const userId = response.data.id;
return { userId, userData }
}
})
.catch(function (error) {
console.log(error);
});
};
// async function sendUserLoc(accessToken : string) {
// axios.get("https://api.spotify.com/v1/me",
// {
@ -80,12 +80,12 @@ async function getUserData(accessToken : string) {
// });
// };
async function getValueFor(key:string) :Promise<string | null> {
async function getValueFor(key: string): Promise<string | null> {
let result = await SecureStore.getItemAsync(key);
if (result) {
alert("🔐 Here's your value 🔐 \n" + result);
} else {
alert('No values stored under that key.');
}
return result;
@ -98,7 +98,7 @@ export default function SpotPage() {
if (direction === 'right') {
// Swiped right
console.log("====2==="+currentCard.music.title+"======2=========");
console.log("====2===" + currentCard.music.title + "======2=========");
addLike(currentCard.music);
console.log('Swiped right');
} else if (direction === 'left') {
@ -122,16 +122,16 @@ export default function SpotPage() {
const dislikeButtonref = useRef<LottieView>(null);
const discoveryButtonref = useRef<LottieView>(null);
const onLike = useCallback( () => {
const onLike = useCallback(() => {
likeButtonref.current?.reset();
likeButtonref.current?.play(0,55);
likeButtonref.current?.play(55,0);
likeButtonref.current?.play(0, 55);
likeButtonref.current?.play(55, 0);
}, [])
const dispatch = useDispatch();
function addLike(music: Music) {
onLike();
console.log("====3==="+currentCard.music.title+"======3=========");
console.log("====3===" + currentCard.music.title + "======3=========");
dispatch(addFavoritesMusic(music))
// dispatch(addFavoriteMusic(props));
@ -139,10 +139,10 @@ export default function SpotPage() {
// setdisplayIndex(0);
// swiper.swipeLeft();
// }
}
}
// const hapti = (() => {
// Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy)
// getValueFor(MY_SECURE_AUTH_STATE_KEY)
@ -150,7 +150,7 @@ export default function SpotPage() {
// // Haptics.NotificationFeedbackType.Success
// });
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// const [locationData, setLocationData] = useState<LocationData>();
// const [prevLocationData, setPrevLocationData] = useState<LocationData>();
// const [nearbyUsers, setNearbyUsers] = useState<NearbyUser[]>([]);
@ -192,140 +192,141 @@ export default function SpotPage() {
// console.error(error);
// }
// };
// setInterval(sendLocationToServer, 30000)
const navigator = useNavigation();
const {width : wWidht} = Dimensions.get("window");
const hapti = (card : Spot) => {
const { width: wWidht } = Dimensions.get("window");
const hapti = (card: Spot) => {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy)
navigator.navigate("DetailsSpot", {"music": card.music})
navigator.navigate("DetailsSpot", { "music": card.music })
// Haptics.NotificationFeedbackType.Success
};
};
return (
<View style={{flex: 1,
<View style={{
flex: 1,
}}>
{ cards.length > 0 ? (
<>
<ImageBackground blurRadius={7}
style={{
position: 'absolute',
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
}}
source={{
uri:currentCard.music.image ,
}}
></ImageBackground>
<SafeAreaView style={styles.mainSafeArea}>
<LinearGradient colors={['rgba(2, 2, 2, 0.58) 0%','rgba(0, 0, 0, 0) 100.56%']}style={styles.gradient}>
{cards.length > 0 ? (
<>
<ImageBackground blurRadius={7}
style={{
position: 'absolute',
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
}}
source={{
uri: currentCard.music.image,
}}
></ImageBackground>
<SafeAreaView style={styles.mainSafeArea}>
<LinearGradient colors={['rgba(2, 2, 2, 0.58) 0%', 'rgba(0, 0, 0, 0) 100.56%']} style={styles.gradient}>
<Text
style={{
fontStyle : 'normal',
left: wWidht/9 ,
top: 75,
color: "#FFFFFF",
fontSize: 30,
fontWeight: "800",
}}>{currentCard.music.title}</Text>
style={{
fontStyle: 'normal',
left: wWidht / 9,
top: normalize(87),
color: "#FFFFFF",
fontSize: normalize(AdjustSize(currentCard.music.title)),
fontWeight: "800",
}}>{currentCard.music.title}</Text>
<Text
style={{
fontStyle : 'normal',
left: wWidht/9 ,
top: 75,
color: "#FFFFFF",
fontSize: 18,
}}>{currentCard.music.bio}</Text>
style={{
fontStyle: 'normal',
left: wWidht / 9,
top: normalize(87),
color: "#FFFFFF",
fontSize: normalize(20),
}}>{currentCard.music.bio}</Text>
</LinearGradient>
</SafeAreaView>
<View style={{flex : 8.35}}>
<View style={{flex : 1.83, justifyContent: 'center', alignItems: 'center' }}>
{cards.map((card, index) => (
<View key={card.userSpotifyId} style = {{ position:'absolute'}} >
<Pressable onLongPress={() => {hapti(card)}} >
{/* <SharedElement id={card.name}> */}
<Card
title={card.music.title}
image={card.music.image}
onSwipe={(direction) => {onSwipe(index, direction)}}
/>
{/* </SharedElement> */}
</Pressable>
</SafeAreaView>
<View style={{ flex: 8.35 }}>
<View style={{ flex: 1.83, justifyContent: 'center', alignItems: 'center' }}>
{cards.map((card, index) => (
<View key={card.userSpotifyId} style={{ position: 'absolute' }} >
<Pressable onLongPress={() => { hapti(card) }} >
{/* <SharedElement id={card.name}> */}
<Card
title={card.music.title}
image={card.music.image}
onSwipe={(direction) => { onSwipe(index, direction) }}
/>
{/* </SharedElement> */}
</Pressable>
</View>
))
}
</View>
<View style={{ flex: 1, flexDirection: 'row', alignItems: "flex-start", justifyContent: 'center' }}>
<Animated.View style={{ flexDirection: 'row', width: '92%', alignItems: "center", justifyContent: 'space-evenly' }}>
<TouchableOpacity style={styles.button} onPress={onLike}>
<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} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={onLike}>
<LottieView autoPlay={false} loop={false} ref={likeButtonref} speed={2} source={Lotties.likeAnimation} style={styles.lottie} />
</TouchableOpacity>
</Animated.View>
</View>
</View>
))
}
</View>
<View style={{flex : 1,flexDirection : 'row', alignItems: "flex-start", justifyContent : 'center'}}>
<Animated.View style={{flexDirection : 'row', width : '92%', alignItems: "center", justifyContent : 'space-evenly'}}>
<TouchableOpacity style={styles.button} onPress={onLike}>
<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}/>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={onLike}>
<LottieView autoPlay={false} loop={false} ref={likeButtonref} speed={2} source={Lotties.likeAnimation} style={styles.lottie}/>
</TouchableOpacity>
</Animated.View>
</View>
</View>
</>
</>
)
: (<View style={{justifyContent : 'center', alignItems : 'center', flex : 1, backgroundColor: "#141414"}}>
<View style={{position: "absolute"}}>
<FladLoading/>
</View>
<Text style={{color: "grey", fontWeight: "400", textAlign: "center", top: 100}}>Vous avez explorer toutes les spot autour de vous.
{"\n"}Continuer dans discoverie pour découvrir de nouvelles music basées dur vos gouts musicaux.</Text>
: (<View style={{ justifyContent: 'center', alignItems: 'center', flex: 1, backgroundColor: "#141414" }}>
<View style={{ position: "absolute" }}>
<FladLoading />
</View>
<Text style={{ color: "grey", fontWeight: "400", textAlign: "center", top: 100 }}>Vous avez explorer toutes les spot autour de vous.
{"\n"}Continuer dans discoverie pour découvrir de nouvelles music basées dur vos gouts musicaux.</Text>
</View>)
}
}
</View>
);
};
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
},
spot : {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
alignContent : 'center',
flexDirection : 'column',
backgroundColor : '#000'
},
lottie : {
width : '100%',
},
button : {
setOpacityTo: 0.8,
alignItems : 'center',
borderRadius : 100,
justifyContent : 'center',
width: 61,
height: 61,
backgroundColor: '#24243A',
opacity : 0.8,
shadowRadius : 2,
},
gradient : {
position : "absolute",
top : 0,
left : 0,
right : 0,
height : 209,
},
})
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
},
spot: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
alignContent: 'center',
flexDirection: 'column',
backgroundColor: '#000'
},
lottie: {
width: '100%',
},
button: {
setOpacityTo: 0.8,
alignItems: 'center',
borderRadius: 100,
justifyContent: 'center',
width: 61,
height: 61,
backgroundColor: '#24243A',
opacity: 0.8,
shadowRadius: 2,
},
gradient: {
position: "absolute",
top: 0,
left: 0,
right: 0,
height: 209,
},
})

@ -1,9 +1,9 @@
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 { 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";
@ -21,13 +21,13 @@ 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;
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}) {
// @ts-ignore
export default function InfoScreen({ route, navigation }) {
const item: Music = route.params.music;
@ -35,9 +35,9 @@ export default function InfoScreen({route, navigation}) {
const [similarMusics, setSimilarMusics] = useState<Music[]>([]);
// parralax
// parralax
// parralax
// parralax
const styles = StyleSheet.create({
@ -234,159 +234,159 @@ export default function InfoScreen({route, navigation}) {
}
});
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("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("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"),
] ;
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 { width, height } = useWindowDimensions();
const [currentspot, setCurrentspot] = useState(item);
const [sound, setSound] = useState(null);
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 [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 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 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 trackPreviewUrl = 'https://p.scdn.co/mp3-preview/08ef3b9d6dbd6bab233f5e9ca564091902767f71?cid=774b29d4f13844c495f206cafdad9c86';
const playTrackPreview = async () => {
console.log("===============================================================================================================");
const handleStopSound = async () => {
if (sound !== null) {
//@ts-ignore
await sound.stopAsync();
}
else{
setIsPlaying(true);
}
};
useEffect(() => {
return sound ? () => {
console.log('Unloading Sound');
console.log('get in Sound');
const { sound } = await Audio.Sound.createAsync({ uri: item.trackPreviewUrl });
//@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),
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);
}
};
})
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){}
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) { }
}
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("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("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"),
] ;
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}>
@ -403,87 +403,88 @@ const styleAniamatedImage = useAnimatedStyle(() => {
/>
<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)']}>
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 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',}}>
<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>
</Text>
</TouchableOpacity>
</Animated.View>
</View>
</View>
</View>
{similarMusics.length !== 0 && (
// <HorizontalFlatList renderCell={littleCard} title={'Simillar Music'} data={similarMusics}>
// </HorizontalFlatList>
<HorizontalFlatList title={'Simillar Music'} data={tmpMusic2}>
// <HorizontalFlatList renderCell={littleCard} title={'Simillar Music'} data={similarMusics}>
// </HorizontalFlatList>
<HorizontalFlatList title={'Simillar Music'} data={tmpMusic2}>
{(props) => (
<LittleCard image={props.image} title ={props.title}/>
<LittleCard image={props.image} title={props.title} />
)}
</HorizontalFlatList>
)}
</ScrollView>

@ -1,16 +1,16 @@
export class AuthentificationService {
constructor(private auth: Auth, private http: HttpClient) { }
name = "toto";
async register({ email, password }) {
constructor(private auth: Auth, private http: HttpClient) { }
name = "toto";
async register({ email, password }) {
try {
const user = await createUserWithEmailAndPassword(this.auth, email, password);
return user;
} catch (e) {
return null;
}
}
}
async login({ email, password }) {
// should for all method use a cloud function to creata user
try {
@ -30,4 +30,4 @@ export class AuthentificationService {

@ -2,73 +2,73 @@ import axios from "axios";
import MusicFactory from "../../Model/factory/MusicFactory";
import Music from "../../Model/Music";
import { FetchOptions, RequestHandler } from "./spotifyRequestHandler/utils";
export class MusicMinimal {
public id : string;
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;
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 {
private readonly API_URL = "https://flad-api-production.up.railway.app/api/";
private spotifyRequestHandler = new RequestHandler();
private readonly token : string;
constructor(token : string) {
this.token = token;
}
// get id(){
private readonly API_URL = "https://flad-api-production.up.railway.app/api/";
private spotifyRequestHandler = new RequestHandler();
private readonly token: string;
constructor(token: string) {
this.token = token;
}
// get id(){
// return this.identification;
// }
// async apiAuth(url : string) {
// await this.identification.setCode(url);
// // this.request = ApiSpotifyRequests(await this.identification.createToken());
// // this.request = ApiSpotifyRequests(await this.identification.createToken());
// }
public async getMusicById(idMusic : string): Promise<Music>{
var requestData :string = '/tracks/' + idMusic;
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined,this.token);
public async getMusicById(idMusic: string): Promise<Music> {
var requestData: string = '/tracks/' + idMusic;
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined, this.token);
if (respMusic.status != 200) {
}
return MusicFactory.mapFromSpotifyTrack(respMusic.data);
}
public async getUserCurrentMusic(): Promise<string | null>{
var requestData :string = '/me/player/currently-playing';
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined,this.token);
public async getUserCurrentMusic(): Promise<string | null> {
var requestData: string = '/me/player/currently-playing';
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined, this.token);
if (respMusic.status != 200) {
return null;
}
console.log(respMusic.data.items.track.id)
return respMusic.data.items.track.id;
}
public async getUserRecentlyPlayedMusic(): Promise<string | null>{
var requestData :string = '/me/player/recently-played';
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined,this.token);
public async getUserRecentlyPlayedMusic(): Promise<string | null> {
var requestData: string = '/me/player/recently-played';
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, undefined, this.token);
if (respMusic.status != 200) {
}
if (respMusic.data.items.length <= 0) {
return null;
}
}
return respMusic.data.items[0].track.id;
}
public async playMusic(idMusic : string): Promise<void>{
var requestData :string = '/me/player/play';
public async playMusic(idMusic: string): Promise<void> {
var requestData: string = '/me/player/play';
const fetchOptions: FetchOptions = {
method: 'PUT',
body: {
uris: [`spotify:track:${idMusic}`],
position_ms: 0
uris: [`spotify:track:${idMusic}`],
position_ms: 0
}
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
console.log(respMusic.data);
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions, this.token);
// need to handle when
// if (respMusic.status != 200) {
// if (respMusic.status == 400 && respMusic.data.message =='need to use Spotify premium'){
@ -80,19 +80,19 @@ export default class SpotifyService implements IspotifyService {
// console.log(respMusic.data);
// }
return ;
return;
}
public async searchMusic(text : string): Promise<Music[]>{
var requestData :string = '/search';
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);
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions, this.token);
if (respMusic.status != 200) {
}
const tracksData = respMusic?.data?.tracks?.items;
@ -105,31 +105,31 @@ export default class SpotifyService implements IspotifyService {
// 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);
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);
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);
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) {
}
@ -137,22 +137,22 @@ export default class SpotifyService implements IspotifyService {
}
public async addItemToPlayList(playlistId : string, idMusic : string): Promise<void>{
var requestData :string = '/playlists/' + playlistId + '/tracks';
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}`]
uris: [`spotify:track:${idMusic}`]
}
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions,this.token);
};
const respMusic = await this.spotifyRequestHandler.spotifyFetch(requestData, fetchOptions, this.token);
console.log(respMusic.data);
return ;
return;
}
public async createPlayList(userId : string,name? : string,description? : string): Promise<void>{
var requestData :string = '/users/' + encodeURIComponent(userId) + '/playlists';
public async createPlayList(userId: string, name?: string, description?: string): Promise<void> {
var requestData: string = '/users/' + encodeURIComponent(userId) + '/playlists';
const fetchOptions: FetchOptions = {
method: 'POST',
body: {
@ -160,10 +160,10 @@ export default class SpotifyService implements IspotifyService {
"name": name || "New Flad Playlist",
"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);
console.log(respMusic.data);
return ;
return;
}
// public async getSimilarTrack(musicId : string,limit : number =1,market? : string): Promise<Music[]>{
@ -171,7 +171,7 @@ export default class SpotifyService implements IspotifyService {
// '?limit=' +limit+
// '&market=FR' +
// "&seed_tracks=" + musicId;
// const fetchOptions: FetchOptions = {
// method: 'GET',
// body: {
@ -180,7 +180,7 @@ export default class SpotifyService implements IspotifyService {
// limit: 1,
// }
// };
// console.log('222222222221baaaaaaaaaaaaahhhhhhhhhhhh LAaa chp gros ' + musicId);
// const respSimilarMusic = await this.spotifyRequestHandler.spotifyFetch(requestData,undefined,this.token);
@ -205,43 +205,43 @@ export default class SpotifyService implements IspotifyService {
// }
public async getSimilarTrack(musicId: string, limit: number = 1, market?: string): Promise<Music[]> {
const requestData: string = '/recommendations/' +
'?limit=' + limit +
'&market=FR' +
'&seed_tracks=' + musicId;
'?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);
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;
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.filter((music: Music | undefined) => !!music) as Music[];
// return similars;
}
}
async getSpotifyCredentials() {
const res = await axios.get(this.API_URL)
// then verify error
// then verify error
const spotifyCredentials = res.data;
return spotifyCredentials
}
}
}

@ -13,14 +13,14 @@ export interface FetchOptions {
body?: Record<string, string | boolean | number | (string | boolean | number)[]>;
}
export class RequestHandler{
export class RequestHandler {
private _version: `v${number}` = 'v1';
get version(): string {
return this._version;
}
public async spotifyFetch(url: string, options: FetchOptions = {}, token: string) : Promise<AxiosResponse<any,any>> {
console.log(options+ "sds=============");
public async spotifyFetch(url: string, options: FetchOptions = {}, token: string): Promise<AxiosResponse<any, any>> {
console.log(options + "sds=============");
const resp = await axios({
url: `https://api.spotify.com/${this.version}${url}`,
method: options.method || 'GET',
@ -32,7 +32,7 @@ export class RequestHandler{
},
data: options.body
});
console.log(")))))))))))))))))))",resp.request, "((((((((((((((((((((");
console.log(")))))))))))))))))))", resp.request, "((((((((((((((((((((");
// console.log(resp, "frfrfrfr");
return resp;
// if (

Loading…
Cancel
Save