After Width: | Height: | Size: 142 KiB |
After Width: | Height: | Size: 51 KiB |
@ -0,0 +1,68 @@
|
||||
import express, { Application } from 'express';
|
||||
// import compression from 'compression';
|
||||
import cors from 'cors';
|
||||
// import db from './database';
|
||||
// import morgan from 'morgan';
|
||||
import Controller from './controller/Icontroller';
|
||||
// import ErrorMiddleware from './middleware/error.middleware';
|
||||
import bodyParser from 'body-parser';
|
||||
|
||||
// to secure
|
||||
// import helmet from 'helmet';
|
||||
|
||||
import http from 'http';
|
||||
|
||||
class App {
|
||||
public express: Application;
|
||||
public port: number;
|
||||
public dataBase: null;
|
||||
|
||||
public server : any;
|
||||
|
||||
constructor(controllers: Controller[], port: number) {
|
||||
this.express = express();
|
||||
this.port = port;
|
||||
this.dataBase = null;
|
||||
|
||||
// this.initialiseDatabase();
|
||||
this.initialiseMiddleware();
|
||||
this.initialiseControllers(controllers);
|
||||
|
||||
// this.initialiseErrorHandling();
|
||||
}
|
||||
|
||||
private initialiseMiddleware(): void {
|
||||
// this.express.use(helmet());
|
||||
this.express.use(cors());
|
||||
// this.express.use(morgan('dev'));
|
||||
this.express.use(express.json());
|
||||
this.express.use(express.urlencoded({ extended: false }));
|
||||
// this.express.use(compression());
|
||||
// mine
|
||||
this.express.use(bodyParser.json());
|
||||
this.express.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
private initialiseControllers(controllers: Controller[]): void {
|
||||
controllers.forEach((controller: Controller) => {
|
||||
this.express.use('/api', controller.router);
|
||||
});
|
||||
}
|
||||
|
||||
// private initialiseErrorHandling(): void {
|
||||
// this.express.use(ErrorMiddleware);
|
||||
// }
|
||||
|
||||
public listen(): void {
|
||||
const server = this.express.listen(this.port, () => {
|
||||
console.log(`⚡️[server] : App listening on the port ${this.port}`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default App;
|
@ -0,0 +1,15 @@
|
||||
import { Router } from 'express';
|
||||
|
||||
interface Controller {
|
||||
path: string;
|
||||
router: Router;
|
||||
// constructor() {
|
||||
// this.initialiseRoutes();
|
||||
// }
|
||||
|
||||
// initialiseRoutes(): void ;
|
||||
|
||||
}
|
||||
// il y a un truc inject
|
||||
|
||||
export default Controller;
|
@ -0,0 +1,27 @@
|
||||
import { Router } from "express";
|
||||
import Controller from "./Icontroller";
|
||||
|
||||
type PingResponse = {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export default class PingController implements Controller {
|
||||
public path = '/ping';
|
||||
public router = Router();
|
||||
|
||||
constructor() {
|
||||
this.initialiseRoutes();
|
||||
}
|
||||
|
||||
private initialiseRoutes(): void {
|
||||
this.router.get("/ping", async (_req, res) => {
|
||||
const response = await this.getMessage();
|
||||
return res.send(response);
|
||||
});
|
||||
}
|
||||
async getMessage(): Promise<PingResponse> {
|
||||
return {
|
||||
message: "pong",
|
||||
};
|
||||
}
|
||||
}
|
@ -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,287 @@
|
||||
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';
|
||||
import qs from 'qs';
|
||||
|
||||
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.query.refresh_token;
|
||||
if (!req.query.refresh_token) {
|
||||
return res.json({
|
||||
"error": "Parameter refresh_token missing"
|
||||
});
|
||||
}
|
||||
var authOptions = {
|
||||
method: 'POST',
|
||||
url: 'https://accounts.spotify.com/api/token',
|
||||
data: qs.stringify({
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: params
|
||||
}),
|
||||
headers: {
|
||||
'Authorization': 'Basic ' + ( Buffer.from(this.CLIENT_ID + ':' + this.CLIENT_SECRET).toString('base64')),
|
||||
'Content-Type' : 'application/x-www-form-urlencoded'
|
||||
},
|
||||
json: true
|
||||
};
|
||||
|
||||
// request.post(authOptions, function(error, response, body) {
|
||||
// if (!error && response.statusCode === 200) {
|
||||
// var access_token = body.access_token;
|
||||
// res.send({
|
||||
// 'access_token': access_token
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
axios(authOptions)
|
||||
.then(session => {
|
||||
if(session.status === 200){
|
||||
|
||||
res.send({
|
||||
"access_token": session.data.access_token,
|
||||
"expires_in": session.data.expires_in
|
||||
});
|
||||
}});
|
||||
console.log("goood");
|
||||
} catch (error) {
|
||||
console.log("errur");
|
||||
next(new HttpException(400, 'Cannot create post'));
|
||||
}
|
||||
|
||||
}
|
||||
// };
|
||||
|
||||
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;
|
||||
var state = req.query.state || null;
|
||||
// var storedState = req.cookies ? req.cookies[stateKey] : null;
|
||||
var authOptions = {
|
||||
method: 'POST',
|
||||
url: 'https://accounts.spotify.com/api/token',
|
||||
data: qs.stringify({
|
||||
code: code,
|
||||
redirect_uri: this.CALLBACK_URL,
|
||||
grant_type: 'authorization_code'
|
||||
}),
|
||||
headers: {
|
||||
'Authorization': 'Basic ' + ( Buffer.from(this.CLIENT_ID + ':' + this.CLIENT_SECRET).toString('base64')),
|
||||
'Content-Type' : 'application/x-www-form-urlencoded'
|
||||
},
|
||||
json: true
|
||||
};
|
||||
try {
|
||||
console.log('presssquuueee');
|
||||
var resp = await axios(authOptions);
|
||||
if (resp.status === 200) {
|
||||
console.log(resp);
|
||||
console.log('oon esttt laaa');
|
||||
var access_token = resp.data.access_token;
|
||||
console.log(access_token);
|
||||
// should redirect res.redirect('/')
|
||||
res.json("ok");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('heuuuuuuuuuuuuuuuuuuuuubizzzaaarrreeee');
|
||||
console.log(error);
|
||||
next(new HttpException(400, 'On peut pas te connecter mec'));
|
||||
}
|
||||
|
||||
|
||||
// axios({
|
||||
// method: 'post',
|
||||
// url: 'https://accounts.spotify.com/api/token',
|
||||
// data: {
|
||||
// firstName: 'Fred',
|
||||
// lastName: 'Flintstone'
|
||||
// },
|
||||
// headers: {
|
||||
// 'Authorization': 'Basic ' + ( Buffer.from(this.CLIENT_ID + ':' + this.CLIENT_SECRET).toString('base64')),
|
||||
// 'Content-Type' : 'application/x-www-form-urlencoded'
|
||||
// },
|
||||
// });
|
||||
// request.post(authOptions, function(error, response, body) {
|
||||
// if (!error && response.statusCode === 200) {
|
||||
// var access_token = body.access_token;
|
||||
// console.log(access_token);
|
||||
// res.redirect(200, '/')
|
||||
// }
|
||||
// console.log(error);
|
||||
// });
|
||||
|
||||
};
|
||||
|
||||
|
||||
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,169 @@
|
||||
import { Router, Request, Response, NextFunction, RequestHandler } from 'express';
|
||||
import Controller from '../Icontroller';
|
||||
import HttpException from '../../middleware/exeption/httpExeption';
|
||||
import LocationService from '../../service/LocationService';
|
||||
|
||||
|
||||
class TaskController implements Controller {
|
||||
public path = '/task';
|
||||
public router = Router();
|
||||
private userService = new UserService();
|
||||
private locationService = new LocationService();
|
||||
|
||||
constructor() {
|
||||
this.initialiseRoutes();
|
||||
}
|
||||
|
||||
private initialiseRoutes(): void {
|
||||
//create
|
||||
this.router.post(`${this.path}`,this.createUser);
|
||||
|
||||
// // get One
|
||||
this.router.get (`${this.path}/:userId`, this.getUserById);
|
||||
// // get All
|
||||
this.router.get (`${this.path}`, this.getAllUsers);
|
||||
|
||||
//update One
|
||||
this.router.put (`${this.path}/:userId`, this.updateUser);
|
||||
|
||||
//Delete One
|
||||
this.router.delete (`${this.path}/:userId`, this.deleteUser);
|
||||
|
||||
}
|
||||
|
||||
private createUser = async (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<Response | void> => {
|
||||
try {
|
||||
|
||||
console.log(req.body);
|
||||
const reqBody:CreateTaskReqBody = Object.assign({}, req.body);
|
||||
checkIfIsValidCreateTaskReqBody(reqBody);
|
||||
await this.userService.createUserById(reqBody.fin
|
||||
);
|
||||
|
||||
res.status(200).send({ status: "Success", msg: "Success add" });
|
||||
|
||||
|
||||
} catch (error) {
|
||||
next(new HttpException(400, 'Cannot create post'));
|
||||
}
|
||||
};
|
||||
private readonly getUserById: 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.userService.getUserById(id, userId);
|
||||
res.status(201).send(data);
|
||||
|
||||
}
|
||||
catch(error){
|
||||
next(new HttpException(400, 'Cannot create post'));
|
||||
}
|
||||
|
||||
}
|
||||
private readonly getAllUsers: RequestHandler = async (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<Response | void> => {
|
||||
try {
|
||||
const userId = req.params.userId;
|
||||
const tasks = await this.userService.getUsers(userId);
|
||||
const responseList = tasks.map(task => new TaskResumedRes(task));
|
||||
res.status(201).send(responseList);
|
||||
|
||||
}
|
||||
catch(error){
|
||||
next(new HttpException(400, 'Cannot get user task'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private deleteUser = async (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<Response | void> => {
|
||||
try {
|
||||
const id = req.params.taskId;
|
||||
const userId = req.params.userId;
|
||||
await this.userService.DeleteUser(id, userId);
|
||||
return res.status(200).send({ status: "Success", msg: "Data Removed" });
|
||||
} catch (error) {
|
||||
next(new HttpException(400, 'Cannot create post'));
|
||||
}
|
||||
};
|
||||
|
||||
private updateUser = 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.userService.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'));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
private getUserNext: RequestHandler = async (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<Response | void> => {
|
||||
try {
|
||||
const longitude = Number(req.body.longitude);
|
||||
const latitude = Number(req.body.latitude);
|
||||
//verify::val_int(){
|
||||
if (isNaN(longitude) || isNaN(latitude)) {
|
||||
console.log('Impossible de convertir la chaîne en nombre');
|
||||
}
|
||||
//}
|
||||
const userId = req.body.userId;
|
||||
const data = await this.locationService.getNearUser(userId,latitude,longitude);
|
||||
console.log(data);
|
||||
res.status(201).send(data);
|
||||
|
||||
}
|
||||
catch(error){
|
||||
next(new HttpException(400, 'Cannot create post'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TaskController;
|
@ -0,0 +1,3 @@
|
||||
const uri = "mongodb+srv://fladDevDb:ZslYlNRWIOUU7i6o@fladcluster.b29tytu.mongodb.net/?retryWrites=true&w=majority"
|
||||
|
||||
export default db = new MongoClient(uri);
|
@ -0,0 +1,6 @@
|
||||
const notificationSchema = new mongoose.Schema({
|
||||
type: {type: String, required: true},
|
||||
content: {type: String, required: true}
|
||||
});
|
||||
|
||||
export default {Annonce: mongoose.model("nofitication", notificationSchema)}
|
@ -0,0 +1,21 @@
|
||||
|
||||
const userSchema: Schema = new mongoose.Schema<IUser>({
|
||||
pseudo: {type: String, index: { unique: true }},
|
||||
email: {type: String},
|
||||
idDafl: {type: String, index: { unique: true }},
|
||||
idSpotify: {type: String},
|
||||
password: {type: String},
|
||||
prenom: {type: String, default: ""},
|
||||
description: {type: String, default: ""},
|
||||
nom: {type: String, default: ""},
|
||||
ville: {type: String, default: ""},
|
||||
profilPic: {type: String},
|
||||
noteList: [],
|
||||
notifications: [],
|
||||
friends: {type: [String] },
|
||||
favoris: [],
|
||||
conversations: {type: [String] }
|
||||
});
|
||||
// fladDevDb
|
||||
// ZslYlNRWIOUU7i6o
|
||||
export const User: Model<IUser> = model('User', userSchema);
|
@ -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;
|
@ -0,0 +1,8 @@
|
||||
// export const loggerOptions: expressWinston.LoggerOptions = {
|
||||
// transports: [new winston.transports.Console()],
|
||||
// format: winston.format.combine(
|
||||
// winston.format.json(),
|
||||
// winston.format.prettyPrint(),
|
||||
// winston.format.colorize({ all: true })
|
||||
// ),
|
||||
// };
|
@ -0,0 +1,5 @@
|
||||
export default interface IUser{
|
||||
name: string;
|
||||
email: string;
|
||||
avatar?: string;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
export interface Position {
|
||||
/**
|
||||
* Creation timestamp for coords
|
||||
*/
|
||||
timestamp: number;
|
||||
/**
|
||||
* The GPS coordinates along with the accuracy of the data
|
||||
*/
|
||||
coords: {
|
||||
/**
|
||||
* Latitude in decimal degrees
|
||||
*/
|
||||
latitude: number;
|
||||
/**
|
||||
* longitude in decimal degrees
|
||||
*/
|
||||
longitude: number;
|
||||
};
|
||||
}
|
||||
export class PlacePosition implements Position {
|
||||
timestamp: number;
|
||||
coords: {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
};
|
||||
constructor(timestamp: number,latitude : number ,longitude: number){
|
||||
this.timestamp = timestamp;
|
||||
this.coords = {latitude, longitude};
|
||||
}
|
||||
}
|
||||
export class UserLocation {
|
||||
uuid: string;
|
||||
latitude : number;
|
||||
longitude: number;
|
||||
constructor(uuid: string, latitude: number, longitude: number){
|
||||
this.uuid = uuid;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
}
|
||||
}
|
||||
|
||||
export class Place{
|
||||
position: Position;
|
||||
address: Address;
|
||||
constructor(address: Address,position: Position){
|
||||
this.position = position;
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export type Address = {
|
||||
street : string;
|
||||
city : string;
|
||||
state : string;
|
||||
zip : string;
|
||||
}
|
@ -0,0 +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 SpotifyController()],
|
||||
Number(8080)
|
||||
// Number(process.env.PORT)
|
||||
|
||||
);
|
||||
|
||||
app.listen();
|
||||
|
||||
|
||||
|
@ -0,0 +1,136 @@
|
||||
// import db from '../database';
|
||||
import { Place, PlacePosition, Position, UserLocation } from '../model/locationModel';
|
||||
import axios from 'axios';
|
||||
|
||||
class LocationService {
|
||||
private API_KEY : string = "AIzaSyBFCEAtmhZ8jvw84UTQvX3Aqpr66GVqB_A";
|
||||
public async getNearUser(uuid : string, latitude : number, longitude : number)
|
||||
{
|
||||
const UserCollectionref = db.collection('UserPosition');
|
||||
db.collection('UserPosition').doc(uuid).set({uuid : uuid, latitude : latitude, longitude : longitude});
|
||||
// const newPosition = {
|
||||
// name: 'Los Angeles',
|
||||
// state: 'CA',
|
||||
// country: 'USA'
|
||||
// };
|
||||
const snapshot = await UserCollectionref.where("uuid", "!=", uuid).get();
|
||||
if (snapshot.empty) {
|
||||
console.log('No matching documents.');
|
||||
return;
|
||||
}
|
||||
|
||||
let dbUsersList:UserLocation[] = [];
|
||||
snapshot.forEach(doc => {
|
||||
dbUsersList.push(new UserLocation(doc.data().uuid,doc.data().latitude,doc.data().longitude));
|
||||
console.log(doc.id, '=>', doc.data());
|
||||
});
|
||||
|
||||
let listUser: string[] = []; //Set the listUser to an empty list
|
||||
dbUsersList.forEach(user => {
|
||||
console.log(user);
|
||||
const dist = this.distanceBetween(latitude , longitude , user.latitude, user.longitude); //With the function meters, determinate the distance between the current user and the user who is in the actual row
|
||||
console.log(user.uuid,dist);
|
||||
if (dist <= 5) { //If the user in the actual row is less than 100 meters away of the current user
|
||||
|
||||
listUser.push(user.uuid); //Add the username and the ID of the song that user who is in the actual row is listening
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return listUser; //Return an array
|
||||
// $listUser[] = ['user' => $userID, 'music' => $idMusic]; //Add the username and the ID of the song that user who is in the actual row is listening
|
||||
|
||||
}
|
||||
|
||||
public getCenter (points: Position[]) {
|
||||
if (Array.isArray(points) === false || points.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const numberOfPoints = points.length;
|
||||
|
||||
const sum = points.reduce(
|
||||
(acc, point) => {
|
||||
const pointLat = this.toRad(point.coords.latitude);
|
||||
const pointLon = this.toRad(point.coords.longitude);
|
||||
return {
|
||||
X: acc.X + Math.cos(pointLat) * Math.cos(pointLon),
|
||||
Y: acc.Y + Math.cos(pointLat) * Math.sin(pointLon),
|
||||
Z: acc.Z + Math.sin(pointLat),
|
||||
};
|
||||
},
|
||||
{ X: 0, Y: 0, Z: 0 }
|
||||
);
|
||||
|
||||
const X = sum.X / numberOfPoints;
|
||||
const Y = sum.Y / numberOfPoints;
|
||||
const Z = sum.Z / numberOfPoints;
|
||||
|
||||
return {
|
||||
longitude: this.toDeg(Math.atan2(Y, X)),
|
||||
latitude: this.toDeg(Math.atan2(Z, Math.sqrt(X * X + Y * Y))),
|
||||
};
|
||||
};
|
||||
|
||||
public toRad = (value: number) => (value * Math.PI) / 180;
|
||||
public toDeg = (value: number) => (value * 180) / Math.PI;
|
||||
|
||||
// sa c'est un utils du coup mettre dans une calss utils
|
||||
// resulta en km
|
||||
private distanceBetween (lat1 : number, lon1 : number, lat2: number, lon2 : number) : number {
|
||||
if ((lat1 == lat2) && (lon1 == lon2)) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
var radlat1 = Math.PI * lat1/180;
|
||||
var radlat2 = Math.PI * lat2/180;
|
||||
var theta = lon1-lon2;
|
||||
var radtheta = Math.PI * theta/180;
|
||||
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
|
||||
|
||||
if (dist > 1) {
|
||||
dist = 1;
|
||||
}
|
||||
|
||||
dist = Math.acos(dist);
|
||||
dist = dist * 180/Math.PI;
|
||||
dist = dist * 60 * 1.1515;
|
||||
dist = dist * 1.609344;
|
||||
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
private distanceBetweenPosition(first : Position, second : Position) : number {
|
||||
return this.distanceBetween (first.coords.latitude, first.coords.longitude, second.coords.latitude, second.coords.longitude)
|
||||
}
|
||||
|
||||
// give a array of position sorted by distance and return the first
|
||||
private findNearest(main : Position, list : Position[]){
|
||||
this.orderByDistance(main, list)[0]
|
||||
}
|
||||
|
||||
//distanceFn: DistanceFn = getDistance est param sa serrait cool de lui passer un fonction
|
||||
private orderByDistance (mainPos: Position,coords: Position[]){
|
||||
return coords
|
||||
.slice()
|
||||
.sort((a, b) => this.distanceBetweenPosition(mainPos, a) - this.distanceBetweenPosition(mainPos, b));
|
||||
};
|
||||
|
||||
// getCenter(coords)
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default LocationService;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,113 @@
|
||||
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'));
|
||||
// }
|
||||
// };
|
||||
|
||||
}
|
||||
|
||||
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(){
|
||||
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 142 KiB |
@ -0,0 +1,5 @@
|
||||
export const spotifyCredentials = {
|
||||
clientId: 'a5cb39302b6e4c64957de1df50742d71',
|
||||
clientSecret: 'e23db1cd77ee4b589ee99525e282b2e8',
|
||||
redirectUri: 'Your Redirect URI'
|
||||
}
|
After Width: | Height: | Size: 757 B |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 715 B |
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;
|
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
@ -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;
|
@ -1,17 +1,12 @@
|
||||
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
|
||||
},
|
||||
{
|
||||
name : "red",
|
||||
sourceUrl : "https://images.unsplash.com/photo-1614613535308-eb5fbd3d2c17?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80",
|
||||
index : 2
|
||||
},
|
||||
{
|
||||
name : "green",
|
||||
sourceUrl : "https://images.unsplash.com/photo-1584679109597-c656b19974c9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=580&q=80",
|
||||
index : 1
|
||||
name : "her",
|
||||
sourceUrl : "https://images.unsplash.com/photo-1484589065579-248aad0d8b13?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1359&q=80",
|
||||
index : 3
|
||||
}
|
||||
|
||||
]
|
@ -0,0 +1,137 @@
|
||||
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
|
||||
export 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'
|
||||
}
|
||||
|
||||
})
|
||||
|
@ -1,73 +1,215 @@
|
||||
import { View, Text, Image, Animated ,PanResponder, Dimensions } from 'react-native'
|
||||
import React, { useRef, useState, useTransition } from 'react'
|
||||
import { View, Text, Image, Animated ,PanResponder, Dimensions, StyleSheet, ImageBackground, Button, Pressable } 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 Card from '../components/Card';
|
||||
|
||||
import { cards as cardArray } from '../FakeData/data'
|
||||
import FladButton from '../components/button/button';
|
||||
import axios from 'axios';
|
||||
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
import { MY_SECURE_AUTH_STATE_KEY } from './login';
|
||||
|
||||
import * as Location from 'expo-location';
|
||||
|
||||
const {width : wWidht} = Dimensions.get("window");
|
||||
const width = wWidht *0.75;
|
||||
const height = wWidht * (465/264);
|
||||
const borderRadius = 24;
|
||||
|
||||
interface SpotProps {
|
||||
title: string;
|
||||
image: any;
|
||||
onSwipe: (direction: "left" | "right") => void;
|
||||
}
|
||||
|
||||
}
|
||||
type LocationData = {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
interface NearbyUser {
|
||||
id: number;
|
||||
name: string;
|
||||
latitude: number;
|
||||
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 sendUserLoc(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;}
|
||||
|
||||
// })
|
||||
// .catch(function (error) {
|
||||
// console.log(error);
|
||||
// });
|
||||
// };
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const Spot: React.FC<SpotProps> = ({ title, image, onSwipe }) => {
|
||||
const [cards, setCards] = useState(cardArray);
|
||||
const aIndex = useTransition();
|
||||
const onSwipe = (index: number, direction: 'left' | 'right') => {
|
||||
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
|
||||
console.log('Swiped right');
|
||||
|
||||
// Swiped right
|
||||
console.log("===================")
|
||||
} else if (direction === 'left') {
|
||||
console.log('Swiped 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 [currentCard, setCurrentCard] = useState(0);
|
||||
const hapti = (() => {
|
||||
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy)
|
||||
getValueFor(MY_SECURE_AUTH_STATE_KEY)
|
||||
.then(key => { (key != null) ? getUserData(key) :console.log("error key is nullll") } ) ;
|
||||
// Haptics.NotificationFeedbackType.Success
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
const [locationData, setLocationData] = useState<LocationData>();
|
||||
const [prevLocationData, setPrevLocationData] = useState<LocationData>();
|
||||
const [nearbyUsers, setNearbyUsers] = useState<NearbyUser[]>([]);
|
||||
const [currentMusic, setCurrentMusic] = useState<string>("");
|
||||
|
||||
async function getLocation() {
|
||||
var { status } = await Location.requestForegroundPermissionsAsync();
|
||||
if (status !== 'granted') {
|
||||
console.log('Permission to access location was denied');
|
||||
return;
|
||||
}
|
||||
|
||||
let currentLocation = await Location.getCurrentPositionAsync({});
|
||||
setLocationData({
|
||||
latitude: currentLocation.coords.latitude,
|
||||
longitude: currentLocation.coords.longitude,
|
||||
timestamp: currentLocation.timestamp
|
||||
});
|
||||
};
|
||||
async function sendLocationToServer() {
|
||||
getLocation();
|
||||
if (!locationData) return;
|
||||
if (prevLocationData && locationData.latitude === prevLocationData.latitude && locationData.longitude === prevLocationData.longitude) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await axios.post(
|
||||
'http://localhost/api/users/david/nextToMe',
|
||||
locationData
|
||||
);
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error('Failed to send location to server');
|
||||
}
|
||||
|
||||
setPrevLocationData(locationData);
|
||||
setNearbyUsers(response.data);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
setInterval(sendLocationToServer, 30000)
|
||||
return (
|
||||
|
||||
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', position : 'absolute', backgroundColor : '' }}>
|
||||
|
||||
<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}>
|
||||
|
||||
|
||||
<View key={card.name} style = {{ position:'absolute'
|
||||
}} >
|
||||
|
||||
<Pressable onLongPress={hapti}>
|
||||
|
||||
<Card
|
||||
title={card.name}
|
||||
image={card.sourceUrl}
|
||||
onSwipe={(direction) => onSwipe(index, direction)}
|
||||
/>
|
||||
</Pressable>
|
||||
{/* <Button
|
||||
title="Success"
|
||||
onPress={
|
||||
() =>
|
||||
Haptics.notificationAsync(
|
||||
Haptics.NotificationFeedbackType.Success
|
||||
)
|
||||
}
|
||||
></Button> */}
|
||||
<FladButton name="discovery"/>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
|
||||
|
||||
|
||||
// <View style={styles.container}>
|
||||
// <Text>Open up App.tsx to start working on your app!</Text>
|
||||
// {/* <View>
|
||||
// <Animated.View>
|
||||
{/* <LinearGradient
|
||||
// Background Linear Gradient
|
||||
colors={['rgba(0,0,0,0.8)', 'transparent']}
|
||||
|
||||
// </Animated.View>
|
||||
// {cardArray.map( ({index}) => currentCard < index && step + step && (
|
||||
// <Card card={card} ></Card>
|
||||
/> */}
|
||||
|
||||
// ) )}
|
||||
</View>
|
||||
|
||||
// </View> */}
|
||||
// <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
||||
// <Card title="Swipe me left or right" />
|
||||
// </View>
|
||||
// <StatusBar style="auto" />
|
||||
// </View>
|
||||
);
|
||||
};
|
||||
};
|
||||
const styles = StyleSheet.create({
|
||||
spot : {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}
|
||||
})
|
||||
|
||||
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,23 +1,25 @@
|
||||
import axios from "axios";
|
||||
|
||||
export class SpotifyService {
|
||||
|
||||
private identification : ApiSpotifyIdentification;
|
||||
public request : SpotifyRequest;
|
||||
export default class SpotifyService {
|
||||
private readonly API_URL = "http://localhost:8080/api/spotify/exchange";
|
||||
|
||||
constructor() {
|
||||
constructor() {
|
||||
|
||||
}
|
||||
}
|
||||
// get id(){
|
||||
// return this.identification;
|
||||
// }
|
||||
|
||||
get identification{
|
||||
|
||||
}
|
||||
|
||||
async uploadName() {
|
||||
|
||||
}
|
||||
async apiAuth(url : string) {
|
||||
await this.identification.setCode(url);
|
||||
this.request = ApiSpotifyRequests(await this.identification.createToken());
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
// import { Linking } from 'react-native';
|
||||
|
||||
|
||||
|
||||
// export class SpotifyRequest {
|
||||
|
||||
|
||||
|
||||
// constructor() {
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// }
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|