diff --git a/client/package-lock.json b/client/package-lock.json index 853ac67d0..eb11d1b71 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -30,9 +30,11 @@ "react": "18.2.0", "react-native": "0.72.6", "react-native-dotenv": "^3.4.9", + "react-native-feather": "^1.1.2", "react-native-fs": "^2.20.0", "react-native-safe-area-context": "4.6.3", "react-native-screens": "~3.22.0", + "react-native-svg": "13.9.0", "react-native-uuid": "^2.0.1", "react-native-web": "~0.19.6", "socket.io-client": "^4.7.4" @@ -17609,6 +17611,15 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/react-native-feather": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/react-native-feather/-/react-native-feather-1.1.2.tgz", + "integrity": "sha512-qBc0+XegKkX4JV6ykgScasguEV3RdlbYp9IrCMnbozngOgJ7vi76pyRpb+dnZ1AZVkYsbYnpdA9JXeP7EJbMCA==", + "peerDependencies": { + "react-native": ">=0.46", + "react-native-svg": ">=5.3" + } + }, "node_modules/react-native-fs": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz", @@ -17666,6 +17677,85 @@ "react-native": "*" } }, + "node_modules/react-native-svg": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.9.0.tgz", + "integrity": "sha512-Ey18POH0dA0ob/QiwCBVrxIiwflhYuw0P0hBlOHeY4J5cdbs8ngdKHeWC/Kt9+ryP6fNoEQ1PUgPYw2Bs/rp5Q==", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-svg/node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/react-native-svg/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/react-native-svg/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/react-native-svg/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/react-native-svg/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/react-native-uuid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/react-native-uuid/-/react-native-uuid-2.0.1.tgz", diff --git a/server/src/actions/getConnectedUsers.ts b/server/src/actions/getConnectedUsers.ts index c61657006..30724cc52 100644 --- a/server/src/actions/getConnectedUsers.ts +++ b/server/src/actions/getConnectedUsers.ts @@ -1,6 +1,16 @@ import { distanceBetween, geohashForLocation, geohashQueryBounds } from 'geofire-common' import { connectedUsersCollection } from '../utilities/firebaseInit' +export const getConnectedUser = async (socketID: string) => { + try { + const user = await connectedUsersCollection.doc(socketID).get(); + return user.data(); + } catch (error) { + console.error("getConnectedUser failed:", error.message); + return false; + } +} + export const findNearbyUsers = async (centerLat: number, centerLon: number, radius: number) => { // Return an array of nearby userIds (which are also socket ids) given a center latitude and longitude. // Latitude and longitude values use degrees with the same bounds as GeoPoints. Radius values use meters. diff --git a/server/src/actions/updateConnectedUser.ts b/server/src/actions/updateConnectedUser.ts index 59bfe7c54..c05421f12 100644 --- a/server/src/actions/updateConnectedUser.ts +++ b/server/src/actions/updateConnectedUser.ts @@ -26,3 +26,13 @@ export const updateUserLocation = async (socketID: string, lat: number, lon: num return false } } + +export const updateUserDisplayName = async (socketID: string, displayName: string) => { + try { + await connectedUsersCollection.doc(socketID).update({ displayName: displayName }) + return true + } catch (error) { + console.error(error.message) + return false + } +} diff --git a/server/src/index.ts b/server/src/index.ts index bb247896e..202a50f8b 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,18 +1,15 @@ -import express from "express"; -import "dotenv/config"; -import "geofire-common"; -import { Message } from "./types/Message"; -import { createMessage } from "./actions/createMessage"; -import { createUser } from "./actions/createConnectedUser"; -import { - toggleUserConnectionStatus, - updateUserLocation, -} from "./actions/updateConnectedUser"; -import { deleteConnectedUserByUID } from "./actions/deleteConnectedUser"; -import { geohashForLocation } from "geofire-common"; -import { findNearbyUsers } from "./actions/getConnectedUsers"; -import { ConnectedUser } from "./types/User"; -import { getAuth } from "firebase-admin/auth"; +import express from 'express'; +import 'dotenv/config'; +import 'geofire-common'; +import { Message } from './types/Message'; +import { createMessage } from './actions/createMessage'; +import { createUser } from './actions/createConnectedUser'; +import { toggleUserConnectionStatus, updateUserLocation, updateUserDisplayName } from './actions/updateConnectedUser'; +import { deleteConnectedUserByUID } from './actions/deleteConnectedUser'; +import { findNearbyUsers, getConnectedUser } from './actions/getConnectedUsers'; +import {geohashForLocation} from 'geofire-common'; +import { ConnectedUser } from './types/User'; +import { getAuth } from 'firebase-admin/auth'; import Mailgun from "mailgun.js"; const { createServer } = require("http"); @@ -143,9 +140,8 @@ io.on("connection", async (socket: any) => { } catch (error) { console.error("[WS] Error calling updateLocation:", error.message); } - }); -}); - + }) +}) socketServer.listen(socket_port, () => { console.log(`[WS] Listening for new connections on port ${socket_port}.`); }); @@ -168,8 +164,20 @@ app.get("/users", async (req, res) => { const radius = Number(req.query.radius); const userIds = await findNearbyUsers(lat, lon, radius); - console.log(userIds); res.json(userIds); + + } else if (req.query.userId) { + query = "?userId"; + const userId = req.query.userId; + if (typeof userId != "string") throw Error(" [userId] is not a string."); + + const user = await getConnectedUser(userId); + if (user) { + res.json(user); + } else { + // getConnectedUserDisplayName() will return false is an error is thrown, and print it to console. + throw Error("getConnectedUser() failed."); + } } } catch (error) { console.error( @@ -219,6 +227,7 @@ app.put("/users", async (req, res) => { const success = await toggleUserConnectionStatus(userId); if (!success) throw Error(" toggleUserConnectionStatus() failed."); + } else if (req.query.userId && req.query.lat && req.query.lon) { query = "?userId&lat&lon"; const userId = req.query.userId; @@ -230,9 +239,20 @@ app.put("/users", async (req, res) => { const success = await updateUserLocation(userId, lat, lon); if (!success) throw Error(" toggleUserConnectionStatus() failed."); + + } else if (req.query.userId && req.query.displayName) { + query = "?userId&displayName"; + const userId = req.query.userId; + if (typeof userId != "string") throw Error(" [userId] is not a string."); + const displayName = req.query.displayName; + if (typeof displayName != "string") throw Error(" [displayName] is not a string."); + + const success = await updateUserDisplayName(userId, displayName); + if (!success) throw Error("updateDisplayName() failed."); } console.log(`[EXP] Request returned successfully.`); - res.json(`Operation was handled successfully.`); + res.json(`Operation was handled successfully.`); + } catch (error) { console.error( `[EXP] Error returning request :\n`,