APi create + auth spotify-controller/crypt.ts(tempory using auth implicit flow)

pull/4/head
David D'ALMEIDA 2 years ago
parent fbba95e1cf
commit 0ea0c130af

@ -20,6 +20,9 @@
"typescript": "^4.9.4"
},
"dependencies": {
"@types/crypto-js": "^4.1.1",
"@types/request": "^2.48.8",
"axios": "^1.2.6",
"cors": "^2.8.5",
"express-winston": "^4.2.0",
"morgan": "^1.10.0",

@ -0,0 +1,19 @@
export default class CryptString{
stringCrypt: string;
constructor(length : number){
this.stringCrypt = this.generateRandomString(length);
}
generateRandomString (length : number){
var text = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
}

@ -0,0 +1,6 @@
export type AuthReqBody = {
grant_type: string,
redirect_uri?: string,
code?: string,
refresh_token?: string,
}

@ -0,0 +1,233 @@
import Controller from '../Icontroller';
import { Router, Request, Response, NextFunction, RequestHandler } from 'express';
import { AuthReqBody } from './request/authReqBody';
import HttpException from '../../middleware/exeption/httpExeption';
import axios from 'axios';
import CryptString from './crypt';
import AES from 'crypto-js'
import querystring from 'querystring';
class SpotifyController implements Controller {
public path = '/spotify';
public router = Router();
constructor() {
console.log("useeeee");
this.initialiseRoutes();
}
initialiseRoutes() {
// this.router.post(`${this.path}`,this.createTask);
this.router.get(`${this.path}/exchange`,this.login);
this.router.get(`${this.path}/callback`,this.getAccessToken);
// this.router.post(`${this.path}/refresh`,this.getRefreshToken);
this.router.get(`${this.path}/play/:musicId`, this.getMusic);
}
// need to put in ENvironement file
// private readonly CLIENT_CALLBACK_URL = "http://localhost:8080/callback";
private readonly API_URL = "https://accounts.spotify.com/api/token";
private readonly CLIENT_ID = "1f1e34e4b6ba48b388469dba80202b10";
private readonly CLIENT_SECRET = "779371c6d4994a68b8dd6e84b0873c82";
private readonly CLIENT_CALLBACK_URL = "https://auth.expo.io/@thed47/FLAD//callback";
private readonly CALLBACK_URL = "http://localhost:8080/api/spotify/callback";
private readonly 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';
private readonly ENCRYPTION_SECRET = new CryptString(16);
private login = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
console.log("useeeee");
try {
// const params = req.body;
// if (!params.refresh_token) {
// return res.json({
// "error": "Parameter missing"
// });
// }
// this.spotifyRequest({
// grant_type: "authorization_code",
// redirect_uri: this.CLIENT_CALLBACK_URL,
// // code: params.code
// })
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: this.CLIENT_ID,
scope: this.SCOPES,
redirect_uri: this.CALLBACK_URL,
state: this.ENCRYPTION_SECRET.stringCrypt
}));
// .then(session => {
// let result = {
// "access_token": session.access_token,
// "expires_in": session.expires_in,
// "refresh_token": this.encrypt(session.refresh_token)
// };
// return res.send(result);
// })
// .catch(response => {
// return res.json(response);
// });
} catch (error) {
next(new HttpException(400, 'Cannot create spot'));
}
};
// private getRefreshToken = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// console.log('UUse2');
// try {
// const params = req.body;
// if (!params.refresh_token) {
// return res.json({
// "error": "Parameter missing"
// });
// }
// this.spotifyRequest({
// grant_type: "refresh_token",
// refresh_token: this.decrypt(params.refresh_token)
// })
// .then(session => {
// return res.send({
// "access_token": session.access_token,
// "expires_in": session.expires_in
// });
// })
// .catch(response => {
// return res.json(response);
// });
// console.log("errur");
// } catch (error) {
// next(new HttpException(400, 'Cannot create post'));
// console.log("errur");
// }
// };
public getMusic(){
return null;
}
// private spotifyRequest = (params : AuthReqBody) => {
// return new Promise<any>(() => {
// console.log("============ on est laaaa sa mer");
// var code = req.query.code || null;
// var state = req.query.state || null;
// axios.post(this.API_URL, {
// form: params,
// headers: {
// "Authorization": "Basic " + new Buffer(this.CLIENT_ID + ":" + this.CLIENT_SECRET).toString('base64')
// },
// json: true
// });
// }).then(resp => {
// if (resp.statusCode != 200) {
// return Promise.reject({
// statusCode: resp.statusCode,
// body: resp.body
// });
// }
// return Promise.resolve(resp.body);
// })
// .catch(err => {
// return Promise.reject({
// statusCode: 500,
// body: err.stringify({})
// });
// });
// };
private getAccessToken = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
// console.log("heheh");
// try {
// var code = req.query.code;
// var state = req.query.state;
// console.log("================================================================================================================================");
// console.log(req);
// console.log("================================================================================================================================");
// if (state === null) {
// next(new HttpException(400, 'Cannot create twerk'));
// } else {
// const resp : any = await axios.post('https://accounts.spotify.com/api/token',{
// form: {
// code: code,
// redirect_uri: this.CALLBACK_URL,
// // code_verifier : this.ENCRYPTION_SECRET.stringCrypt,
// grant_type: 'authorization_code'
// },
// headers: {
// 'Authorization': 'Basic ' + (new Buffer(this.CLIENT_ID + ':' + this.CLIENT_SECRET).toString('base64')),
// },json: true}
// );
// if (resp.statusCode != 200) {
// console.log(resp.statusCode, resp.body);
// }
// else{
// console.log("error");
// console.log(resp.statusCode, resp.body);
// }
// }
// // });
// } catch (error) {
// console.log(error);
// next(new HttpException(400, 'Cannot create spot'));
// }
var code = req.query.code || null;
var state = req.query.state || null;
// var storedState = req.cookies ? req.cookies[stateKey] : null;
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: this.CALLBACK_URL,
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer(this.CLIENT_ID + ':' + this.CLIENT_SECRET).toString('base64'))
},
json: true
};
};
private encrypt(text :any){
return CryptoJS.AES.encrypt(text, this.ENCRYPTION_SECRET.stringCrypt).toString();
};
private decrypt(text: any) {
console.log("errer");
var bytes = CryptoJS.AES.decrypt(text, this.ENCRYPTION_SECRET.stringCrypt);
return bytes.toString(CryptoJS.enc.Utf8);
};
}
export default SpotifyController;

@ -0,0 +1,13 @@
class HttpException extends Error {
public status: number;
public message: string;
constructor(status: number, message: string) {
super(message);
this.status = status;
this.message = message;
}
}
// en fontion de l'exeption firebas,etc une bonne exeption
export default HttpException;

@ -1,11 +1,15 @@
import App from "./app";
import SpotifyController from "./controller/spotify-controller/spotifyCtrl";
import PingController from "./controller/TestCtrl";
const app = new App(
[new PingController()],
[new PingController(), new SpotifyController()],
Number(8080)
// Number(process.env.PORT)
);
app.listen();

@ -3,6 +3,7 @@ import { StatusBar } from 'expo-status-bar';
import { useState, useTransition } from 'react';
import { Animated, Dimensions, ImageBackground, StyleSheet, Text, View } from 'react-native';
import Card from './components/Card';
import Login from './pages/login';
import Spot from './pages/spot';
@ -30,8 +31,10 @@ const {width : wWidht} = Dimensions.get("window");
return (
<View style={styles.container}>
<LinearGradient colors={['rgba(2, 2, 2, 0.58) 0%','rgba(0, 0, 0, 0) 90.56%']}style={styles.gradient}>
<Text
style={{
@ -53,9 +56,9 @@ const {width : wWidht} = Dimensions.get("window");
}}>Laylow</Text>
</LinearGradient>
<Login></Login>
{/* <Spot/> */}
<Spot>
</Spot>
</View>
@ -83,9 +86,10 @@ const {width : wWidht} = Dimensions.get("window");
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
backgroundColor: '#000',
alignItems: 'center',
justifyContent: 'center',
},
card: {
borderRadius : 8,

@ -1,6 +1,6 @@
export const cards = [{
name : "blue",
sourceUrl : "https://images.unsplash.com/photo-1484589065579-248aad0d8b13?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1359&q=80",
sourceUrl : "https://cdns-images.dzcdn.net/images/artist/399e7e760d8fedf3cc2891e9c0c41658/200x200-000000-80-0-0.jpg",
index : 3
},
{

@ -0,0 +1,111 @@
// 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) {
// 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'));
// // }
// // };
// }
// export default Manager;

@ -0,0 +1,13 @@
class Music {
private id : string;
private name : string;
private artist : string;
private linkCover : string; // Image.source
constructor(id : string, name : string, artist : string, linkCover : string){
this.id = id;
this.name = name;
this.artist = artist;
this.linkCover = linkCover;
}
}

@ -0,0 +1,8 @@
class Spot {
private userId : string;
public music : Music;;
constructor(userId : string, music : Music){
this.userId = userId;
this.music = music;
}
}

@ -0,0 +1,129 @@
// import { useState } from "react";
// import SpotifyService from "../services/spotify/spotify.service";
// import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';
// class StubManager{
// // injection de dépences
// spotifyService = new SpotifyService();
// // userService = new userService();
// private currentUser = useState(null);
// private discovery = {
// authorizationEndpoint: 'https://accounts.spotify.com/authorize',
// tokenEndpoint: 'https://accounts.spotify.com/api/token',
// };
// constructor() {
// }
// // spotify methods
// apiAuthorization(url : string){
// const [, response, promptAsync] = useAuthRequest(
// {
// clientId: '1f1e34e4b6ba48b388469dba80202b10',
// scopes: ['user-read-email', 'playlist-modify-public'],
// // In order to follow the "Authorization Code Flow" to fetch token after authorizationEndpoint
// // this must be set to false
// usePKCE: false,
// redirectUri: makeRedirectUri({
// scheme: 'flad'
// }),
// },
// this.discovery
// );
// }
// 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'));
// // }
// // };
// }
// export default StubManager;

@ -0,0 +1,9 @@
class User {
//attributes from DAFL
private idDafl : any;;
private idSpotify : any;
//constructors
constructor(){
}
}

@ -11,6 +11,7 @@
"resizeMode": "contain",
"backgroundColor": "#1d2129"
},
"scheme": "flad",
"updates": {
"fallbackToCacheTimeout": 0
},

@ -0,0 +1,5 @@
export const spotifyCredentials = {
clientId: 'a5cb39302b6e4c64957de1df50742d71',
clientSecret: 'e23db1cd77ee4b589ee99525e282b2e8',
redirectUri: 'Your Redirect URI'
}

@ -0,0 +1,3 @@
<svg width="21" height="19" viewBox="0 0 21 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.85029 4.158C1.85877 3.01308 2.68386 2.08791 3.70044 2.08791H17.2996C18.3214 2.08791 19.1498 3.0227 19.1498 4.17582V4.18139L11.7151 8.74107C11.183 9.06737 10.5432 9.07922 10.0019 8.77281L1.85029 4.158ZM1.85022 6.49388V14.8242C1.85022 15.9773 2.67859 16.9121 3.70044 16.9121H17.2996C18.3214 16.9121 19.1498 15.9773 19.1498 14.8242V6.55774L12.5986 10.5756C11.5345 11.2282 10.2548 11.2519 9.17228 10.639L1.85022 6.49388ZM3.70044 0C1.65674 0 0 1.86958 0 4.17582V14.8242C0 17.1304 1.65674 19 3.70044 19H17.2996C19.3433 19 21 17.1304 21 14.8242V4.17582C21 1.86958 19.3433 0 17.2996 0H3.70044Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 757 B

@ -0,0 +1,6 @@
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="path-1-inside-1_70_52" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.12142 8.63961C1.28389 8.84583 1.46152 9.03956 1.65263 9.21911L8.09971 16.2523C8.8973 17.1224 10.271 17.1161 11.0606 16.2388L17.9089 8.62951L17.8988 8.62763C18.674 7.71412 19.1417 6.53135 19.1417 5.23935C19.1417 2.34574 16.7959 0 13.9023 0C12.0669 0 10.4518 0.943814 9.51612 2.3726C8.56693 1.03408 7.00516 0.16054 5.23935 0.16054C2.34574 0.16054 0 2.50628 0 5.39989C0 6.61822 0.415838 7.73942 1.11332 8.6293L1.11217 8.62951L1.12142 8.63961Z"/>
</mask>
<path d="M1.12142 8.63961L2.69245 7.40192L2.6462 7.34322L2.59571 7.28813L1.12142 8.63961ZM1.65263 9.21911L3.12694 7.86766L3.07648 7.81261L3.02206 7.76148L1.65263 9.21911ZM8.09971 16.2523L9.57402 14.9008L9.57402 14.9008L8.09971 16.2523ZM11.0606 16.2388L12.5472 17.5767L12.5472 17.5767L11.0606 16.2388ZM17.9089 8.62951L19.3955 9.96744L21.7842 7.31332L18.2732 6.66296L17.9089 8.62951ZM17.8988 8.62763L16.3739 7.33352L14.1402 9.96545L17.5345 10.5942L17.8988 8.62763ZM9.51612 2.3726L7.88468 3.5295L9.58181 5.92274L11.1892 3.46835L9.51612 2.3726ZM1.11332 8.6293L1.47049 10.5972L4.73275 10.0051L2.68743 7.39553L1.11332 8.6293ZM1.11217 8.62951L0.755003 6.66166L-2.81154 7.30899L-0.362119 9.98099L1.11217 8.62951ZM-0.449608 9.87729C-0.225421 10.1619 0.0196126 10.4291 0.283205 10.6767L3.02206 7.76148C2.90343 7.65003 2.7932 7.52981 2.69245 7.40192L-0.449608 9.87729ZM9.57402 14.9008L3.12694 7.86766L0.178324 10.5706L6.6254 17.6037L9.57402 14.9008ZM9.57402 14.9008L9.57402 14.9008L6.6254 17.6037C8.22058 19.3439 10.968 19.3314 12.5472 17.5767L9.57402 14.9008ZM16.4223 7.29158L9.57402 14.9008L12.5472 17.5767L19.3955 9.96744L16.4223 7.29158ZM17.5345 10.5942L17.5446 10.5961L18.2732 6.66296L18.263 6.66108L17.5345 10.5942ZM19.4236 9.92175C20.4941 8.6604 21.1417 7.02293 21.1417 5.23935H17.1417C17.1417 6.03977 16.8539 6.76784 16.3739 7.33352L19.4236 9.92175ZM21.1417 5.23935C21.1417 1.24117 17.9005 -2 13.9023 -2V2C15.6914 2 17.1417 3.45031 17.1417 5.23935H21.1417ZM13.9023 -2C11.3642 -2 9.13258 -0.692242 7.843 1.27684L11.1892 3.46835C11.7711 2.57987 12.7695 2 13.9023 2V-2ZM11.1476 1.21569C9.83945 -0.628956 7.68082 -1.83946 5.23935 -1.83946V2.16054C6.32949 2.16054 7.29441 2.69712 7.88468 3.5295L11.1476 1.21569ZM5.23935 -1.83946C1.24117 -1.83946 -2 1.40171 -2 5.39989H2C2 3.61085 3.45031 2.16054 5.23935 2.16054V-1.83946ZM-2 5.39989C-2 7.08121 -1.42438 8.63367 -0.460783 9.86307L2.68743 7.39553C2.25605 6.84516 2 6.15522 2 5.39989H-2ZM1.46933 10.5974L1.47049 10.5972L0.756159 6.66145L0.755003 6.66166L1.46933 10.5974ZM2.59571 7.28813L2.58645 7.27804L-0.362119 9.98099L-0.352865 9.99108L2.59571 7.28813Z" fill="white" mask="url(#path-1-inside-1_70_52)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,3 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.88862 0.324035C1.45657 -0.108012 0.756083 -0.108012 0.324036 0.324035C-0.108011 0.756082 -0.108013 1.45657 0.324034 1.88861L5.75471 7.31929L0.324038 12.75C-0.108009 13.182 -0.108009 13.8825 0.324038 14.3145C0.756085 14.7466 1.45657 14.7466 1.88862 14.3145L7.31929 8.88387L12.75 14.3145C13.182 14.7466 13.8825 14.7466 14.3145 14.3145C14.7466 13.8825 14.7466 13.182 14.3145 12.75L8.88387 7.31929L14.3145 1.88863C14.7466 1.45658 14.7466 0.756092 14.3145 0.324045C13.8825 -0.108002 13.182 -0.108004 12.75 0.324043L7.31929 5.75471L1.88862 0.324035Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 715 B

@ -0,0 +1,3 @@
<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.837607 0C1.3002 0 1.67521 0.400086 1.67521 0.893617V17.1064C1.67521 17.5999 1.3002 18 0.837607 18C0.375009 18 0 17.5999 0 17.1064V0.893617C0 0.400086 0.375009 0 0.837607 0ZM4.90598 0C5.36858 0 5.74359 0.400086 5.74359 0.893617V17.1064C5.74359 17.5999 5.36858 18 4.90598 18C4.44339 18 4.06838 17.5999 4.06838 17.1064V0.893617C4.06838 0.400086 4.44339 0 4.90598 0ZM9.93162 2.53621V16.2128H12.3248V12.1941C12.62 12.367 12.9968 12.5 13.4468 12.5H14V16.8511C14 17.4856 13.5178 18 12.9231 18H9.33333C8.72658 18 8.25641 17.4699 8.25641 16.8482V1.3651C8.25641 0.464709 9.19429 -0.101539 9.9188 0.39861L13.5077 2.87616C13.813 3.08688 14 3.44946 14 3.84103V6.5H13.4468C12.9968 6.5 12.62 6.63296 12.3248 6.80589V4.18828L9.93162 2.53621ZM13 9.5C13 10.0523 13.2 10.5 13.4468 10.5H14H16.5V13.5532C16.5 13.8 16.9477 14 17.5 14C18.0523 14 18.5 13.8 18.5 13.5532V10.5H21.5532C21.8 10.5 22 10.0523 22 9.5C22 8.94772 21.8 8.5 21.5532 8.5H18.5V5.44681C18.5 5.20004 18.0523 5 17.5 5C16.9477 5 16.5 5.20004 16.5 5.44681V8.5H14H13.4468C13.2 8.5 13 8.94771 13 9.5Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,7 @@
const Icons = {
discovery: require('./icon_discovery.png'),
// riveLike : require('./light_like.riv'),
}
export default Icons;

Binary file not shown.

@ -75,6 +75,8 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
( translateX.value,
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 2],
[1, 0, 0]);
return {
opacity : opacityl,
};
@ -84,7 +86,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
const opacityl = interpolate
( translateX.value,
[-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 4],
[0.75, 1, 0.75]);
[0.85, 1, 1]);
return {
opacity : opacityl,
@ -93,7 +95,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
const opacDStyle = useAnimatedStyle(() => {
const opacityl = interpolate
( translateY.value,
[-SCREEN_HEIGHT / 4, 0, SCREEN_HEIGHT / 2],
[-SCREEN_HEIGHT / 4, 0, SCREEN_HEIGHT / 4],
[0, 0, 1]);
return {
opacity : opacityl,
@ -133,7 +135,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={[ rStyle, styles.card,opacCStyle ]}>
<Animated.View style={[ rStyle, styles.card,opacCStyle, ]} >
<Animated.View
style={[{
// transform: [{ rotate: "30deg" }],
@ -185,7 +187,8 @@ const styles = StyleSheet.create({
card : {
justifyContent : 'center',
alignItems : 'center',
borderColor : 'red',
borderWidth : 3,
},
image : {
borderRadius : 24,

@ -0,0 +1,49 @@
import { View, Text, Image , Dimensions, StyleSheet, Pressable } from 'react-native'
import React, { useRef, useState } from 'react'
import Animated,{ Extrapolate, interpolate, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
import * as Haptics from 'expo-haptics';
import Icons from '../../assets/icons/icon';
import Rive, { Fit, RiveRef } from 'rive-react-native';
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;
interface ButtonProps {
name : string;
}
const FladButton = ({name} : ButtonProps) => {
const riveRef = React.useRef<RiveRef>(null);
const handlePlay = () => { riveRef.current?.play() };
return (
<Pressable onPress={handlePlay}>
<Image source={Icons.discovery} style={[styles.image]} />
</Pressable>
);
};
const styles = StyleSheet.create({
button : {
justifyContent : 'center',
alignItems : 'center',
},
image : {
borderRadius : 24,
resizeMode: 'cover',
width: 65,
height: 65,
backgroundColor: 'black',
}
})
export default FladButton;

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

@ -10,10 +10,14 @@
"dependencies": {
"@react-navigation/native": "^6.1.2",
"@react-navigation/native-stack": "^6.9.8",
"axios": "^1.2.6",
"expo": "~47.0.12",
"expo-auth-session": "~3.8.0",
"expo-cli": "^6.1.0",
"expo-haptics": "~12.0.1",
"expo-linear-gradient": "~12.0.1",
"expo-random": "~13.0.0",
"expo-secure-store": "~12.0.0",
"expo-status-bar": "~1.4.2",
"react": "18.1.0",
"react-dom": "18.1.0",
@ -22,7 +26,8 @@
"react-native-reanimated": "~2.12.0",
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-web": "~0.18.9"
"react-native-web": "~0.18.9",
"rive-react-native": "^3.0.41"
},
"devDependencies": {
"@babel/core": "^7.12.9",
@ -5018,6 +5023,11 @@
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
"integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ=="
},
"node_modules/@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
},
"node_modules/@types/react": {
"version": "18.0.27",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.27.tgz",
@ -5754,11 +5764,26 @@
}
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.6.tgz",
"integrity": "sha512-rC/7F08XxZwjMV4iuWv+JpD3E0Ksqg9nac4IIg6RwNuF0JTeWoCo/mBNG54+tNhhI11G3/VDRbdDQTs9hGp4pQ==",
"dependencies": {
"follow-redirects": "^1.10.0"
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-core": {
@ -7251,6 +7276,59 @@
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
},
"node_modules/compare-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/compare-urls/-/compare-urls-2.0.0.tgz",
"integrity": "sha512-eCJcWn2OYFEIqbm70ta7LQowJOOZZqq1a2YbbFCFI1uwSvj+TWMwXVn7vPR1ceFNcAIt5RSTDbwdlX82gYLTkA==",
"dependencies": {
"normalize-url": "^2.0.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/compare-urls/node_modules/normalize-url": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
"integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
"dependencies": {
"prepend-http": "^2.0.0",
"query-string": "^5.0.1",
"sort-keys": "^2.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/compare-urls/node_modules/prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
"integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==",
"engines": {
"node": ">=4"
}
},
"node_modules/compare-urls/node_modules/query-string": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
"dependencies": {
"decode-uri-component": "^0.2.0",
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/compare-urls/node_modules/strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/compare-versions": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
@ -9168,6 +9246,38 @@
"url-parse": "^1.5.9"
}
},
"node_modules/expo-auth-session": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/expo-auth-session/-/expo-auth-session-3.8.0.tgz",
"integrity": "sha512-pQ8GryTTZL/JKHvifUGD4GGlZWo7RrcoQlvQ0O5m5edYfoa7fMHCg20MBX4Da4P3eVgJlqWZWCHfBC2fZxcRfA==",
"dependencies": {
"expo-constants": "~14.0.0",
"expo-crypto": "~12.0.0",
"expo-linking": "~3.3.0",
"expo-web-browser": "~12.0.0",
"invariant": "^2.2.4",
"qs": "6.9.1"
},
"peerDependencies": {
"expo-random": "*"
},
"peerDependenciesMeta": {
"expo-random": {
"optional": true
}
}
},
"node_modules/expo-auth-session/node_modules/qs": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz",
"integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==",
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/expo-cli": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/expo-cli/-/expo-cli-6.1.0.tgz",
@ -9931,6 +10041,14 @@
"expo": "*"
}
},
"node_modules/expo-crypto": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-12.0.0.tgz",
"integrity": "sha512-2KC52eLYsXndDZOVFyr+K3Zs9wDgpqZ7F7fwAiUg+yNbE21CJrHKDFvo/Br0FAaDf/w9pUks5/qi1azB5sDzvg==",
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-error-recovery": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/expo-error-recovery/-/expo-error-recovery-4.0.1.tgz",
@ -9986,6 +10104,18 @@
"expo": "*"
}
},
"node_modules/expo-linking": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-3.3.0.tgz",
"integrity": "sha512-wXPzI2kijnql2L2F6i8zP1zINTkYlcRXyh1iV3P6Bt57v6yZiiniZBnb6grJVj19LOmluNs0PYrbX1ZsHBChCg==",
"dependencies": {
"@types/qs": "^6.5.3",
"expo-constants": "~14.0.0",
"invariant": "^2.2.4",
"qs": "^6.9.1",
"url-parse": "^1.5.9"
}
},
"node_modules/expo-modules-autolinking": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.0.2.tgz",
@ -10311,11 +10441,41 @@
"node": ">= 10.0.0"
}
},
"node_modules/expo-random": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/expo-random/-/expo-random-13.0.0.tgz",
"integrity": "sha512-aGb0vtUmFFuW0TF1rdOgsz89zEVD/RXUPUnnZy5+i3jJeQ2PerJ4uo72/EuWqHpCBNto8/qT+aCzFinmQDeTAA==",
"dependencies": {
"base64-js": "^1.3.0"
},
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-secure-store": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-12.0.0.tgz",
"integrity": "sha512-Rz5lYr2NxrnFvIPwuWcseUSbdUjFxNZG0oVulqM9puuK7t5lDG3/SAy+J22ELBhaltuci2VVO6hCdFwRoRiG/Q==",
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-status-bar": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.4.2.tgz",
"integrity": "sha512-ZWjO6D4ARGYfAd3SWDD3STNudHDhyBZDZjhhseqoEmsf7bS9ykny8KKOhlzJW24qIQNPhkgdvHhaw9fQwMJy3Q=="
},
"node_modules/expo-web-browser": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-12.0.0.tgz",
"integrity": "sha512-7/RUuE0sv5kf+mTw5/SOnks0Am1ctoxvT1Xi53Nom2EuXTKBV+b2Kf5xAw3ItoW5W4MHJUX3FdNI6qc9sS9+Pw==",
"dependencies": {
"compare-urls": "^2.0.0"
},
"peerDependencies": {
"expo": "*"
}
},
"node_modules/express": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
@ -12750,6 +12910,14 @@
"node": ">=8"
}
},
"node_modules/is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -17033,6 +17201,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@ -18252,6 +18425,15 @@
"inherits": "^2.0.1"
}
},
"node_modules/rive-react-native": {
"version": "3.0.41",
"resolved": "https://registry.npmjs.org/rive-react-native/-/rive-react-native-3.0.41.tgz",
"integrity": "sha512-N4BQuQwsPK98n8AITrMh/iG/AjCikKm6f1Wt+EMJa6hl987h68mM2z/4vul+CuigkMreiiIH6kUSOAMKMK98KA==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/router-ips": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/router-ips/-/router-ips-1.0.0.tgz",
@ -18978,6 +19160,17 @@
"node": ">=0.8.0"
}
},
"node_modules/sort-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
"integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==",
"dependencies": {
"is-plain-obj": "^1.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/source-list-map": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
@ -22751,6 +22944,14 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/xdl/node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/xdl/node_modules/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
@ -26924,6 +27125,11 @@
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
"integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ=="
},
"@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
},
"@types/react": {
"version": "18.0.27",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.27.tgz",
@ -27546,11 +27752,25 @@
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.6.tgz",
"integrity": "sha512-rC/7F08XxZwjMV4iuWv+JpD3E0Ksqg9nac4IIg6RwNuF0JTeWoCo/mBNG54+tNhhI11G3/VDRbdDQTs9hGp4pQ==",
"requires": {
"follow-redirects": "^1.10.0"
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
},
"dependencies": {
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"babel-core": {
@ -28698,6 +28918,46 @@
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
},
"compare-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/compare-urls/-/compare-urls-2.0.0.tgz",
"integrity": "sha512-eCJcWn2OYFEIqbm70ta7LQowJOOZZqq1a2YbbFCFI1uwSvj+TWMwXVn7vPR1ceFNcAIt5RSTDbwdlX82gYLTkA==",
"requires": {
"normalize-url": "^2.0.1"
},
"dependencies": {
"normalize-url": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
"integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
"requires": {
"prepend-http": "^2.0.0",
"query-string": "^5.0.1",
"sort-keys": "^2.0.0"
}
},
"prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
"integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA=="
},
"query-string": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
"requires": {
"decode-uri-component": "^0.2.0",
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ=="
}
}
},
"compare-versions": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
@ -30196,6 +30456,26 @@
"url-parse": "^1.5.9"
}
},
"expo-auth-session": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/expo-auth-session/-/expo-auth-session-3.8.0.tgz",
"integrity": "sha512-pQ8GryTTZL/JKHvifUGD4GGlZWo7RrcoQlvQ0O5m5edYfoa7fMHCg20MBX4Da4P3eVgJlqWZWCHfBC2fZxcRfA==",
"requires": {
"expo-constants": "~14.0.0",
"expo-crypto": "~12.0.0",
"expo-linking": "~3.3.0",
"expo-web-browser": "~12.0.0",
"invariant": "^2.2.4",
"qs": "6.9.1"
},
"dependencies": {
"qs": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz",
"integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA=="
}
}
},
"expo-cli": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/expo-cli/-/expo-cli-6.1.0.tgz",
@ -30849,6 +31129,12 @@
"uuid": "^3.3.2"
}
},
"expo-crypto": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-12.0.0.tgz",
"integrity": "sha512-2KC52eLYsXndDZOVFyr+K3Zs9wDgpqZ7F7fwAiUg+yNbE21CJrHKDFvo/Br0FAaDf/w9pUks5/qi1azB5sDzvg==",
"requires": {}
},
"expo-error-recovery": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/expo-error-recovery/-/expo-error-recovery-4.0.1.tgz",
@ -30890,6 +31176,18 @@
"integrity": "sha512-TMl/wBTVQOliL4S3DS5Aa3UFfVySr0mdJEHLG6kfBdMCLkr+tfLI2rGyJ+scS7xgMsvhTIaurhf1+Z0sL3aLCg==",
"requires": {}
},
"expo-linking": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-3.3.0.tgz",
"integrity": "sha512-wXPzI2kijnql2L2F6i8zP1zINTkYlcRXyh1iV3P6Bt57v6yZiiniZBnb6grJVj19LOmluNs0PYrbX1ZsHBChCg==",
"requires": {
"@types/qs": "^6.5.3",
"expo-constants": "~14.0.0",
"invariant": "^2.2.4",
"qs": "^6.9.1",
"url-parse": "^1.5.9"
}
},
"expo-modules-autolinking": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.0.2.tgz",
@ -31130,11 +31428,33 @@
}
}
},
"expo-random": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/expo-random/-/expo-random-13.0.0.tgz",
"integrity": "sha512-aGb0vtUmFFuW0TF1rdOgsz89zEVD/RXUPUnnZy5+i3jJeQ2PerJ4uo72/EuWqHpCBNto8/qT+aCzFinmQDeTAA==",
"requires": {
"base64-js": "^1.3.0"
}
},
"expo-secure-store": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-12.0.0.tgz",
"integrity": "sha512-Rz5lYr2NxrnFvIPwuWcseUSbdUjFxNZG0oVulqM9puuK7t5lDG3/SAy+J22ELBhaltuci2VVO6hCdFwRoRiG/Q==",
"requires": {}
},
"expo-status-bar": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.4.2.tgz",
"integrity": "sha512-ZWjO6D4ARGYfAd3SWDD3STNudHDhyBZDZjhhseqoEmsf7bS9ykny8KKOhlzJW24qIQNPhkgdvHhaw9fQwMJy3Q=="
},
"expo-web-browser": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-12.0.0.tgz",
"integrity": "sha512-7/RUuE0sv5kf+mTw5/SOnks0Am1ctoxvT1Xi53Nom2EuXTKBV+b2Kf5xAw3ItoW5W4MHJUX3FdNI6qc9sS9+Pw==",
"requires": {
"compare-urls": "^2.0.0"
}
},
"express": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
@ -32989,6 +33309,11 @@
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
},
"is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg=="
},
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -36417,6 +36742,11 @@
"ipaddr.js": "1.9.1"
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@ -37353,6 +37683,12 @@
"inherits": "^2.0.1"
}
},
"rive-react-native": {
"version": "3.0.41",
"resolved": "https://registry.npmjs.org/rive-react-native/-/rive-react-native-3.0.41.tgz",
"integrity": "sha512-N4BQuQwsPK98n8AITrMh/iG/AjCikKm6f1Wt+EMJa6hl987h68mM2z/4vul+CuigkMreiiIH6kUSOAMKMK98KA==",
"requires": {}
},
"router-ips": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/router-ips/-/router-ips-1.0.0.tgz",
@ -37951,6 +38287,14 @@
}
}
},
"sort-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
"integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==",
"requires": {
"is-plain-obj": "^1.0.0"
}
},
"source-list-map": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
@ -40973,6 +41317,14 @@
"color-convert": "^2.0.1"
}
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",

@ -11,19 +11,24 @@
"dependencies": {
"@react-navigation/native": "^6.1.2",
"@react-navigation/native-stack": "^6.9.8",
"axios": "^1.2.6",
"expo": "~47.0.12",
"expo-auth-session": "~3.8.0",
"expo-cli": "^6.1.0",
"expo-haptics": "~12.0.1",
"expo-linear-gradient": "~12.0.1",
"expo-random": "~13.0.0",
"expo-status-bar": "~1.4.2",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-native": "0.70.5",
"react-native-gesture-handler": "~2.8.0",
"react-native-reanimated": "~2.12.0",
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-web": "~0.18.9",
"expo-linear-gradient": "~12.0.1",
"react-native-reanimated": "~2.12.0",
"react-native-gesture-handler": "~2.8.0",
"expo-haptics": "~12.0.1"
"rive-react-native": "^3.0.41",
"expo-secure-store": "~12.0.0"
},
"devDependencies": {
"@babel/core": "^7.12.9",

@ -0,0 +1,136 @@
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';
import * as AuthSession from 'expo-auth-session';
import Card from '../components/Card';
import axios from 'axios';
import { cards as cardArray } from '../FakeData/data'
import FladButton from '../components/button/button';
import * as WebBrowser from 'expo-web-browser';
import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';
const SCREEN_WIDTH = Dimensions.get('window').width
import * as SecureStore from 'expo-secure-store';
interface LoginProps {
}
interface Params {
[key: string]: string;
}
interface Profile {
display_name: string;
email: string;
id: string;
}
//generate random string
const MY_SECURE_AUTH_STATE_KEY = 'MySecureAuthStateKey';
WebBrowser.maybeCompleteAuthSession();
// Endpoint
const discovery = {
authorizationEndpoint: 'https://accounts.spotify.com/authorize',
tokenEndpoint: 'https://accounts.spotify.com/api/token',
};
async function save(key : string, value : string) {
await SecureStore.setItemAsync(key, value);
}
export default function Login() {
// const [advice, setAdvice] = useState("dd");
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
);
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') {
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]);
return (
<View style={styles.centeredView}>
<Text style={styles.textStyle}>Hello flad test logIn</Text>
<Button disabled={!request} title="Login"
onPress={() => {
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',
},
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'
}
})

@ -6,12 +6,14 @@ import * as Haptics from 'expo-haptics';
import Card from '../components/Card';
import { cards as cardArray } from '../FakeData/data'
import FladButton from '../components/button/button';
interface SpotProps {
}
const Spot: React.FC<SpotProps> = () => {
}
export default function Spot() {
const [cards, setCards] = useState(cardArray);
const [currentCard, setcurrentCard] = useState(cards[cards.length - 1]);
const onSwipe = (index: number, direction: 'left' | 'right') => {
if (direction === 'right') {
// Swiped right
@ -19,8 +21,9 @@ const Spot: React.FC<SpotProps> = () => {
} else if (direction === 'left') {
// Swiped left
}
// update the state of the card or the app
// update the state of the cards state when it remove thisy
setCards(cards.filter((_, i) => i !== index));
setcurrentCard(cards[cards.length -1]);
};
const hapti = (() => {
@ -31,12 +34,28 @@ const Spot: React.FC<SpotProps> = () => {
return (
<View style={styles.spot}>
<ImageBackground blurRadius={20}
style={{
position: 'absolute',
width: "120%",
height: "120%",
justifyContent: "center",
alignItems: "center",
opacity: 0.28
}}
source={{
uri:currentCard.sourceUrl ,
}}
></ImageBackground>
{cards.map((card, index) => (
<View key={card.name} style = {{ position:'absolute'
}} >
<Pressable onLongPress={hapti}>
<Card
@ -45,7 +64,7 @@ const Spot: React.FC<SpotProps> = () => {
onSwipe={(direction) => onSwipe(index, direction)}
/>
</Pressable>
<Button
{/* <Button
title="Success"
onPress={
() =>
@ -53,7 +72,8 @@ const Spot: React.FC<SpotProps> = () => {
Haptics.NotificationFeedbackType.Success
)
}
/>
></Button> */}
<FladButton name="discovery"/>
</View>
))}
@ -68,7 +88,6 @@ const Spot: React.FC<SpotProps> = () => {
);
};
const styles = StyleSheet.create({
spot : {
flex: 1,
@ -77,4 +96,3 @@ const Spot: React.FC<SpotProps> = () => {
}
})
export default Spot;

@ -0,0 +1,33 @@
export class AuthentificationService {
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 {
const user = await signInWithEmailAndPassword(this.auth, email, password);
return user;
} catch (e) {
return null;
}
}
logout() {
return signOut(this.auth);
}
}

@ -1,21 +0,0 @@
// export class ApiSpotifyIdentification {
// private state : string;
// private codeVerifier : string;
// private codeChallenge : string;
// private encodedLogs : string;
// constructor(){
// // this.state = _generateRandomString(16);
// // this.codeVerifier = _generateRandomString(_generateRandomInt(43, 128));
// // this.codeChallenge = _generateCodeChallenge();
// // this.encodedLogs = base64.encode(utf8.encode("$clientId:$_clientSecret"));
// }
// setCode(url : string){
// throw new Error("Not implemented");
// }
// createToken(url : string){
// throw new Error("Not implemented");
// }
// }

@ -1,30 +1,25 @@
// import { ApiSpotifyIdentification } from "./ApiSpotifyIdentification";
// import { SpotifyRequest } from "./spotifyRequestHandler/spotifyRequest";
import axios from "axios";
// export class SpotifyService {
export default class SpotifyService {
private readonly API_URL = "http://localhost:8080/api/spotify/exchange";
// private identification : ApiSpotifyIdentification;
// public request : SpotifyRequest;
constructor() {
// constructor() {
// this.identification= new ApiSpotifyIdentification();
// this.request = new SpotifyRequest();
// }
}
// get id(){
// return this.identification;
// }
// get id(){
// return this.identification;
// }
// async apiAuth(url : string) {
// await this.identification.setCode(url);
// // this.request = ApiSpotifyRequests(await this.identification.createToken());
// }
async getSpotifyCredentials() {
const res = await axios.get(this.API_URL)
// then verify error
const spotifyCredentials = res.data;
return spotifyCredentials
}
// async apiAuth(url : string) {
// await this.identification.setCode(url);
// this.request = ApiSpotifyRequests(await this.identification.createToken());
// }
// async getSpotifyCredentials() {
// const res = await axios.get('/api/spotify-credentials')
// const spotifyCredentials = res.data
// return spotifyCredentials
// }
// }
}

@ -0,0 +1,27 @@
import { AuthentificationService } from "../Auth/authentificationService.service";
export class UserService {
constructor(private auth: AuthentificationService) {}
getUserProfile() {
const user = this.auth.currentUser;
const userDocRef = doc(this.firestore, `User/${user.uid}`);
return docData(userDocRef);
}
async uploadName(name: string, email : string) {
const user = this.auth.currentUser;
try {
const userDocRef = doc(this.firestore, `User/${user.uid}`);
await setDoc(userDocRef, {
name,
email
});
return true;
} catch (e) {
return null;
}
}
}
Loading…
Cancel
Save