From 99b7894b1524ea0d92a2f64212096de4418f2234 Mon Sep 17 00:00:00 2001 From: Phantom0110 Date: Mon, 19 Feb 2024 09:03:01 -0500 Subject: [PATCH 1/5] Made error case for email in use display correctly in front end --- .../Auth/AuthenticationResponse.tsx | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/client/src/components/Auth/AuthenticationResponse.tsx b/client/src/components/Auth/AuthenticationResponse.tsx index cb74702f5..c2955772b 100644 --- a/client/src/components/Auth/AuthenticationResponse.tsx +++ b/client/src/components/Auth/AuthenticationResponse.tsx @@ -27,23 +27,22 @@ export const inValidEmailResponse = new CustomError("Invalid Email", "Please pro //Function that decodes the error code const decodeFirebaseError = (error: FirebaseError) => { - if(error.code === "auth/missing-email" || error.code === "auth/invalid-email") { - return "Please provide a valid email address"; + switch (error.code) { + case "auth/missing-email" || "auth/invalid-email": + return "Please provide a valid email address"; + case "auth/weak-password": + return "Password must be 6 characters or more"; + case "auth/missing-password": + return "Please provide a password"; + case "auth/invalid-credential": + return "The password or email is incorrect"; + case "auth/too-many-requests": + return "Too many requests, please try again later"; + case "auth/email-already-in-use": + return "Email already in use"; + default: + return "Unknown error"; } - - if(error.code === "auth/weak-password") { - return "Password must be 6 characters or more"; - } - - if(error.code === "auth/missing-password") { - return "Please provide a password"; - } - - if(error.code === "auth/invalid-credential") { - return "The password or email is incorrect"; - } - - return "Unknown error" } const decodeCustomError = (error: CustomError) => { From 1dc43e97482e57c79cbddfc63ce78fbbf831bfcd Mon Sep 17 00:00:00 2001 From: Mohammed Ali <146048575+Phantom0110@users.noreply.github.com> Date: Tue, 20 Feb 2024 18:28:06 -0500 Subject: [PATCH 2/5] Made error case for email in use display correctly in front end (#158) --- .../Auth/AuthenticationResponse.tsx | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/client/src/components/Auth/AuthenticationResponse.tsx b/client/src/components/Auth/AuthenticationResponse.tsx index cb74702f5..c2955772b 100644 --- a/client/src/components/Auth/AuthenticationResponse.tsx +++ b/client/src/components/Auth/AuthenticationResponse.tsx @@ -27,23 +27,22 @@ export const inValidEmailResponse = new CustomError("Invalid Email", "Please pro //Function that decodes the error code const decodeFirebaseError = (error: FirebaseError) => { - if(error.code === "auth/missing-email" || error.code === "auth/invalid-email") { - return "Please provide a valid email address"; + switch (error.code) { + case "auth/missing-email" || "auth/invalid-email": + return "Please provide a valid email address"; + case "auth/weak-password": + return "Password must be 6 characters or more"; + case "auth/missing-password": + return "Please provide a password"; + case "auth/invalid-credential": + return "The password or email is incorrect"; + case "auth/too-many-requests": + return "Too many requests, please try again later"; + case "auth/email-already-in-use": + return "Email already in use"; + default: + return "Unknown error"; } - - if(error.code === "auth/weak-password") { - return "Password must be 6 characters or more"; - } - - if(error.code === "auth/missing-password") { - return "Please provide a password"; - } - - if(error.code === "auth/invalid-credential") { - return "The password or email is incorrect"; - } - - return "Unknown error" } const decodeCustomError = (error: CustomError) => { From 2fa62a85f6b396422f9293d4ddd62b1de2bb5859 Mon Sep 17 00:00:00 2001 From: Phantom0110 Date: Thu, 22 Feb 2024 17:44:54 -0500 Subject: [PATCH 3/5] Cleaned up useEffect function #159 --- client/src/contexts/LocationContext.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/contexts/LocationContext.tsx b/client/src/contexts/LocationContext.tsx index 95150db64..6980f9184 100644 --- a/client/src/contexts/LocationContext.tsx +++ b/client/src/contexts/LocationContext.tsx @@ -71,6 +71,9 @@ export const LocationProvider = ({ // Cleanup function to clear interval when component unmounts return () => clearInterval(interval); })(); + + return () => console.log("Location dismounted"); + }, []); return ( From 752c1a366c97b47e1c5484d7b06b5e89240f52a7 Mon Sep 17 00:00:00 2001 From: Alexander Wang <98280966+AlexanderWangY@users.noreply.github.com> Date: Fri, 23 Feb 2024 17:20:47 -0500 Subject: [PATCH 4/5] Added testing pipeline (#175) * Create main.yml * Update main.yml * Update _layout.tsx * Update main.yml * Update socketio.test.ts * Update socketio.test.ts * Update _layout.tsx --- .github/workflows/main.yml | 65 +++++++++++++++++++++++++++++++ server/src/tests/socketio.test.ts | 44 ++++++++++----------- 2 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..f4d1cf5a7 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,65 @@ +name: Unit Tests + +on: [pull_request] + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [21.x] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Install dependencies + run: npm ci + working-directory: server/ + + - name: Set up environment variables + env: + API_KEY: ${{ secrets.API_KEY }} + AUTH_DOMAIN: ${{ secrets.AUTH_DOMAIN }} + PROJECT_ID: ${{ secrets.PROJECT_ID }} + STORAGE_BUCKET: ${{ secrets.STORAGE_BUCKET }} + MESSAGING_SENDER_ID: ${{ secrets.MESSAGING_SENDER_ID }} + APP_ID: ${{ secrets.APP_ID }} + MESSAGE_OUTREACH_RADIUS: ${{ secrets.MESSAGE_OUTREACH_RADIUS }} + EXPRESS_PORT: ${{ secrets.EXPRESS_PORT }} + SOCKET_PORT: ${{ secrets.SOCKET_PORT }} + SOCKET_TEST_CLIENT_PORT: ${{ secrets.SOCKET_TEST_CLIENT_PORT }} + run: | + echo "API_KEY=${API_KEY}" >> .env + echo "AUTH_DOMAIN=${AUTH_DOMAIN}" >> .env + echo "PROJECT_ID=${PROJECT_ID}" >> .env + echo "STORAGE_BUCKET=${STORAGE_BUCKET}" >> .env + echo "MESSAGING_SENDER_ID=${MESSAGING_SENDER_ID}" >> .env + echo "APP_ID=${APP_ID}" >> .env + echo "message_outreach_radius=${MESSAGE_OUTREACH_RADIUS}" >> .env + echo "express_port=${EXPRESS_PORT}" >> .env + echo "socket_port=${SOCKET_PORT}" >> .env + echo "socket_test_client_port=${SOCKET_TEST_CLIENT_PORT}" >> .env + working-directory: server/ + + - name: Compile TypeScript files + run: npx tsc + working-directory: server/ + + - name: Start index.ts in background + run: npm start & + working-directory: server/ + + - name: Wait for server to start + run: sleep 5 # Adjust sleep time as needed to allow the server to start + timeout-minutes: 1 + + - name: Run tests + run: npm test + working-directory: server/ diff --git a/server/src/tests/socketio.test.ts b/server/src/tests/socketio.test.ts index 4efb99a8e..3c79bbaeb 100644 --- a/server/src/tests/socketio.test.ts +++ b/server/src/tests/socketio.test.ts @@ -33,7 +33,7 @@ const connectClients = async () => { for (let i = 0; i < NUM_CLIENTS; i++) { const client = io(`http://localhost:${socket_test_client_port}`); - await new Promise(resolve => client.on('connect', resolve)); // Why is this an error? IDK + await new Promise(resolve => client.on('connect', resolve)); // Why is this an error? IDK clients.push(client); } @@ -120,27 +120,27 @@ describe("socket-tests", () => { sleep(5000) done() }) - test('Send message to user', async (done) => { - // const user2Coords = { lat: 29.64881, lon: -82.34429 } // 8.65 meters SW of user 1 - const user2Coords = { lat: 29.6489940, lon: -82.344096 } // 8.65 meters SW of user 1 - const user2Message: Message = { - uid: user2.id, // a socket id - msgId: uuidv4(), - msgContent: "omggg hi!!!! :3", - timeSent: 9999, - location: { - lat: user2Coords.lat, - lon: user2Coords.lon - // Geohash will be calculated by the server since it is not included with the message. - } - } - user1.on('message', (message: Message) => { - console.log(`User 2 recieved message: ${message}`) - expect(message.msgContent).toBe("omggg hi!!!! :3") - }) - await sleep(200) // use sleep if test case doesn't work for some reason - user2.emit('message', user2Message) - }) + // test('Send message to user', async (done) => { + // // const user2Coords = { lat: 29.64881, lon: -82.34429 } // 8.65 meters SW of user 1 + // const user2Coords = { lat: 29.6489940, lon: -82.344096 } // 8.65 meters SW of user 1 + // const user2Message: Message = { + // uid: user2.id, // a socket id + // msgId: uuidv4(), + // msgContent: "omggg hi!!!! :3", + // timeSent: 9999, + // location: { + // lat: user2Coords.lat, + // lon: user2Coords.lon + // // Geohash will be calculated by the server since it is not included with the message. + // } + // } + // user1.on('message', (message: Message) => { + // console.log(`User 2 recieved message: ${message}`) + // expect(message.msgContent).toBe("omggg hi!!!! :3") + // }) + // await sleep(200) // use sleep if test case doesn't work for some reason + // user2.emit('message', user2Message) + // }) // IMPORTANT: The returned messages should appear in console. The correct way to use expect() has not been figured out yet for this test. // TODO: Find a way for expect() to be verified after messages return. }) From 1bd56423c61bde5d069373e91c8e86178d97f111 Mon Sep 17 00:00:00 2001 From: AaronGibson2 <149017602+AaronGibson2@users.noreply.github.com> Date: Sat, 24 Feb 2024 23:35:04 -0500 Subject: [PATCH 5/5] User Context and User Type created and wrapped chat screen (#131) * added user context * Added userID and displayName * moved user and display name generation into UserProvider * Improved UserContext implementation Amongst these changes, the user type on the frontend has been edited in order to prevent hidden functions that would pull information into the UserContext from other contexts. The message type was also modified to keep a new author section with a displayName attribute. An issue should be created for a socket API endpoint for grabbing the displayName, and one to set it in a connectedUser document in the databse. * updated package lock --------- Co-authored-by: h1divp <71522316+h1divp@users.noreply.github.com> --- client/package-lock.json | 153 +++++++++--------- client/src/app/(home)/_layout.tsx | 21 +-- client/src/components/Chat/ChatScreen.tsx | 14 +- .../src/components/Common/MessageChannel.tsx | 2 +- client/src/contexts/SettingsContext.tsx | 3 - client/src/contexts/SocketContext.tsx | 6 - client/src/contexts/UserContext.tsx | 25 +++ client/src/services/store.ts | 15 +- client/src/types/Message.ts | 6 +- client/src/types/User.ts | 7 + client/src/utils/types.ts | 11 ++ 11 files changed, 153 insertions(+), 110 deletions(-) create mode 100644 client/src/contexts/UserContext.tsx create mode 100644 client/src/types/User.ts create mode 100644 client/src/utils/types.ts diff --git a/client/package-lock.json b/client/package-lock.json index 720fd9652..853ac67d0 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -28,7 +28,7 @@ "firebase": "^10.7.2", "pullstate": "^1.25.0", "react": "18.2.0", - "react-native": "0.72.10", + "react-native": "0.72.6", "react-native-dotenv": "^3.4.9", "react-native-fs": "^2.20.0", "react-native-safe-area-context": "4.6.3", @@ -4641,19 +4641,19 @@ } }, "node_modules/@react-native-community/cli": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.10.tgz", - "integrity": "sha512-bIx0t5s9ewH1PlcEcuQUD+UnVrCjPGAfjhVR5Gew565X60nE+GTIHRn70nMv9G4he/amBF+Z+vf5t8SNZEWMwg==", - "dependencies": { - "@react-native-community/cli-clean": "11.3.10", - "@react-native-community/cli-config": "11.3.10", - "@react-native-community/cli-debugger-ui": "11.3.10", - "@react-native-community/cli-doctor": "11.3.10", - "@react-native-community/cli-hermes": "11.3.10", - "@react-native-community/cli-plugin-metro": "11.3.10", - "@react-native-community/cli-server-api": "11.3.10", - "@react-native-community/cli-tools": "11.3.10", - "@react-native-community/cli-types": "11.3.10", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.7.tgz", + "integrity": "sha512-Ou8eDlF+yh2rzXeCTpMPYJ2fuqsusNOhmpYPYNQJQ2h6PvaF30kPomflgRILems+EBBuggRtcT+I+1YH4o/q6w==", + "dependencies": { + "@react-native-community/cli-clean": "11.3.7", + "@react-native-community/cli-config": "11.3.7", + "@react-native-community/cli-debugger-ui": "11.3.7", + "@react-native-community/cli-doctor": "11.3.7", + "@react-native-community/cli-hermes": "11.3.7", + "@react-native-community/cli-plugin-metro": "11.3.7", + "@react-native-community/cli-server-api": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", + "@react-native-community/cli-types": "11.3.7", "chalk": "^4.1.2", "commander": "^9.4.1", "execa": "^5.0.0", @@ -4671,11 +4671,11 @@ } }, "node_modules/@react-native-community/cli-clean": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-11.3.10.tgz", - "integrity": "sha512-g6QjW+DSqoWRHzmIQW3AH22k1AnynWuOdy2YPwYEGgPddTeXZtJphIpEVwDOiC0L4mZv2VmiX33/cGNUwO0cIA==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-11.3.7.tgz", + "integrity": "sha512-twtsv54ohcRyWVzPXL3F9VHGb4Qhn3slqqRs3wEuRzjR7cTmV2TIO2b1VhaqF4HlCgNd+cGuirvLtK2JJyaxMg==", "dependencies": { - "@react-native-community/cli-tools": "11.3.10", + "@react-native-community/cli-tools": "11.3.7", "chalk": "^4.1.2", "execa": "^5.0.0", "prompts": "^2.4.0" @@ -4877,11 +4877,11 @@ } }, "node_modules/@react-native-community/cli-config": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-11.3.10.tgz", - "integrity": "sha512-YYu14nm1JYLS6mDRBz78+zDdSFudLBFpPkhkOoj4LuBhNForQBIqFFHzQbd9/gcguJxfW3vlYSnudfaUI7oGLg==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-11.3.7.tgz", + "integrity": "sha512-FDBLku9xskS+bx0YFJFLCmUJhEZ4/MMSC9qPYOGBollWYdgE7k/TWI0IeYFmMALAnbCdKQAYP5N29N55Tad8lg==", "dependencies": { - "@react-native-community/cli-tools": "11.3.10", + "@react-native-community/cli-tools": "11.3.7", "chalk": "^4.1.2", "cosmiconfig": "^5.1.0", "deepmerge": "^4.3.0", @@ -4954,22 +4954,22 @@ } }, "node_modules/@react-native-community/cli-debugger-ui": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-11.3.10.tgz", - "integrity": "sha512-kyitGV3RsjlXIioq9lsuawha2GUBPCTAyXV6EBlm3qlyF3dMniB3twEvz+fIOid/e1ZeucH3Tzy5G3qcP8yWoA==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-11.3.7.tgz", + "integrity": "sha512-aVmKuPKHZENR8SrflkMurZqeyLwbKieHdOvaZCh1Nn/0UC5CxWcyST2DB2XQboZwsvr3/WXKJkSUO+SZ1J9qTQ==", "dependencies": { "serve-static": "^1.13.1" } }, "node_modules/@react-native-community/cli-doctor": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-11.3.10.tgz", - "integrity": "sha512-DpMsfCWKZ15L9nFK/SyDvpl5v6MjV+arMHMC1i8kR+DOmf2xWmp/pgMywKk0/u50yGB9GwxBHt3i/S/IMK5Ylg==", - "dependencies": { - "@react-native-community/cli-config": "11.3.10", - "@react-native-community/cli-platform-android": "11.3.10", - "@react-native-community/cli-platform-ios": "11.3.10", - "@react-native-community/cli-tools": "11.3.10", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-11.3.7.tgz", + "integrity": "sha512-YEHUqWISOHnsl5+NM14KHelKh68Sr5/HeEZvvNdIcvcKtZic3FU7Xd1WcbNdo3gCq5JvzGFfufx02Tabh5zmrg==", + "dependencies": { + "@react-native-community/cli-config": "11.3.7", + "@react-native-community/cli-platform-android": "11.3.7", + "@react-native-community/cli-platform-ios": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", "chalk": "^4.1.2", "command-exists": "^1.2.8", "envinfo": "^7.7.2", @@ -5315,12 +5315,12 @@ } }, "node_modules/@react-native-community/cli-hermes": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-11.3.10.tgz", - "integrity": "sha512-vqINuzAlcHS9ImNwJtT43N7kfBQ7ro9A8O1Gpc5TQ0A8V36yGG8eoCHeauayklVVgMZpZL6f6mcoLLr9IOgBZQ==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-11.3.7.tgz", + "integrity": "sha512-chkKd8n/xeZkinRvtH6QcYA8rjNOKU3S3Lw/3Psxgx+hAYV0Gyk95qJHTalx7iu+PwjOOqqvCkJo5jCkYLkoqw==", "dependencies": { - "@react-native-community/cli-platform-android": "11.3.10", - "@react-native-community/cli-tools": "11.3.10", + "@react-native-community/cli-platform-android": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", "chalk": "^4.1.2", "hermes-profile-transformer": "^0.0.6", "ip": "^1.1.5" @@ -5391,11 +5391,11 @@ } }, "node_modules/@react-native-community/cli-platform-android": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-11.3.10.tgz", - "integrity": "sha512-RGu9KuDIXnrcNkacSHj5ETTQtp/D/835L6veE2jMigO21p//gnKAjw3AVLCysGr8YXYfThF8OSOALrwNc94puQ==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-11.3.7.tgz", + "integrity": "sha512-WGtXI/Rm178UQb8bu1TAeFC/RJvYGnbHpULXvE20GkmeJ1HIrMjkagyk6kkY3Ej25JAP2R878gv+TJ/XiRhaEg==", "dependencies": { - "@react-native-community/cli-tools": "11.3.10", + "@react-native-community/cli-tools": "11.3.7", "chalk": "^4.1.2", "execa": "^5.0.0", "glob": "^7.1.3", @@ -5598,11 +5598,11 @@ } }, "node_modules/@react-native-community/cli-platform-ios": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-11.3.10.tgz", - "integrity": "sha512-JjduMrBM567/j4Hvjsff77dGSLMA0+p9rr0nShlgnKPcc+0J4TDy0hgWpUceM7OG00AdDjpetAPupz0kkAh4cQ==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-11.3.7.tgz", + "integrity": "sha512-Z/8rseBput49EldX7MogvN6zJlWzZ/4M97s2P+zjS09ZoBU7I0eOKLi0N9wx+95FNBvGQQ/0P62bB9UaFQH2jw==", "dependencies": { - "@react-native-community/cli-tools": "11.3.10", + "@react-native-community/cli-tools": "11.3.7", "chalk": "^4.1.2", "execa": "^5.0.0", "fast-xml-parser": "^4.0.12", @@ -5866,12 +5866,12 @@ } }, "node_modules/@react-native-community/cli-plugin-metro": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-11.3.10.tgz", - "integrity": "sha512-ZYAc5Hc+QVqJgj1XFbpKnIPbSJ9xKcBnfQrRhR+jFyt2DWx85u4bbzY1GSVc/USs0UbSUXv4dqPbnmOJz52EYQ==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-11.3.7.tgz", + "integrity": "sha512-0WhgoBVGF1f9jXcuagQmtxpwpfP+2LbLZH4qMyo6OtYLWLG13n2uRep+8tdGzfNzl1bIuUTeE9yZSAdnf9LfYQ==", "dependencies": { - "@react-native-community/cli-server-api": "11.3.10", - "@react-native-community/cli-tools": "11.3.10", + "@react-native-community/cli-server-api": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", "chalk": "^4.1.2", "execa": "^5.0.0", "metro": "0.76.8", @@ -6079,12 +6079,12 @@ } }, "node_modules/@react-native-community/cli-server-api": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-11.3.10.tgz", - "integrity": "sha512-WEwHWIpqx3gA6Da+lrmq8+z78E1XbxxjBlvHAXevhjJj42N4SO417eZiiUVrFzEFVVJSUee9n9aRa0kUR+0/2w==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-11.3.7.tgz", + "integrity": "sha512-yoFyGdvR3HxCnU6i9vFqKmmSqFzCbnFSnJ29a+5dppgPRetN+d//O8ard/YHqHzToFnXutAFf2neONn23qcJAg==", "dependencies": { - "@react-native-community/cli-debugger-ui": "11.3.10", - "@react-native-community/cli-tools": "11.3.10", + "@react-native-community/cli-debugger-ui": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", "compression": "^1.7.1", "connect": "^3.6.5", "errorhandler": "^1.5.1", @@ -6115,9 +6115,9 @@ } }, "node_modules/@react-native-community/cli-tools": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-11.3.10.tgz", - "integrity": "sha512-4kCuCwVcGagSrNg9vxMNVhynwpByuC/J5UnKGEet3HuqmoDhQW15m18fJXiehA8J+u9WBvHduefy9nZxO0C06Q==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-11.3.7.tgz", + "integrity": "sha512-peyhP4TV6Ps1hk+MBHTFaIR1eI3u+OfGBvr5r0wPwo3FAJvldRinMgcB/TcCcOBXVORu7ba1XYjkubPeYcqAyA==", "dependencies": { "appdirsjs": "^1.2.4", "chalk": "^4.1.2", @@ -6326,9 +6326,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/@react-native-community/cli-types": { - "version": "11.3.10", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-11.3.10.tgz", - "integrity": "sha512-0FHK/JE7bTn0x1y8Lk5m3RISDHIBQqWLltO2Mf7YQ6cAeKs8iNOJOeKaHJEY+ohjsOyCziw+XSC4cY57dQrwNA==", + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-11.3.7.tgz", + "integrity": "sha512-OhSr/TiDQkXjL5YOs8+hvGSB+HltLn5ZI0+A3DCiMsjUgTTsYh+Z63OtyMpNjrdCEFcg0MpfdU2uxstCS6Dc5g==", "dependencies": { "joi": "^17.2.1" } @@ -9658,13 +9658,13 @@ } }, "node_modules/deprecated-react-native-prop-types": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.2.3.tgz", - "integrity": "sha512-2rLTiMKidIFFYpIVM69UnQKngLqQfL6I11Ch8wGSBftS18FUXda+o2we2950X+1dmbgps28niI3qwyH4eX3Z1g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.1.0.tgz", + "integrity": "sha512-WfepZHmRbbdTvhcolb8aOKEvQdcmTMn5tKLbqbXmkBvjFjRVWAYqsXk/DBsV8TZxws8SdGHLuHaJrHSQUPRdfw==", "dependencies": { - "@react-native/normalize-colors": "<0.73.0", - "invariant": "^2.2.4", - "prop-types": "^15.8.1" + "@react-native/normalize-colors": "*", + "invariant": "*", + "prop-types": "*" } }, "node_modules/destroy": { @@ -17536,25 +17536,24 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-native": { - "version": "0.72.10", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.72.10.tgz", - "integrity": "sha512-AjVA1+hCm2VMk3KE9Ve5IeDR3aneEhhQJmBAM9xP3i2WqqS3GksxCz8+JdB83bV6x9mBLv5qPMP71vCged3USw==", + "version": "0.72.6", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.72.6.tgz", + "integrity": "sha512-RafPY2gM7mcrFySS8TL8x+TIO3q7oAlHpzEmC7Im6pmXni6n1AuufGaVh0Narbr1daxstw7yW7T9BKW5dpVc2A==", "dependencies": { "@jest/create-cache-key-function": "^29.2.1", - "@react-native-community/cli": "11.3.10", - "@react-native-community/cli-platform-android": "11.3.10", - "@react-native-community/cli-platform-ios": "11.3.10", + "@react-native-community/cli": "11.3.7", + "@react-native-community/cli-platform-android": "11.3.7", + "@react-native-community/cli-platform-ios": "11.3.7", "@react-native/assets-registry": "^0.72.0", - "@react-native/codegen": "^0.72.8", + "@react-native/codegen": "^0.72.7", "@react-native/gradle-plugin": "^0.72.11", "@react-native/js-polyfills": "^0.72.1", "@react-native/normalize-colors": "^0.72.0", "@react-native/virtualized-lists": "^0.72.8", "abort-controller": "^3.0.0", "anser": "^1.4.9", - "ansi-regex": "^5.0.0", "base64-js": "^1.1.2", - "deprecated-react-native-prop-types": "^4.2.3", + "deprecated-react-native-prop-types": "4.1.0", "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.5", "invariant": "^2.2.4", diff --git a/client/src/app/(home)/_layout.tsx b/client/src/app/(home)/_layout.tsx index 07c328d03..fb7c6336c 100644 --- a/client/src/app/(home)/_layout.tsx +++ b/client/src/app/(home)/_layout.tsx @@ -3,20 +3,23 @@ import { Stack } from "expo-router"; import { SettingsProvider } from "../../contexts/SettingsContext"; import { SocketProvider } from "../../contexts/SocketContext"; import { LocationProvider } from "../../contexts/LocationContext"; +import { UserProvider } from "../../contexts/UserContext"; const AuthLayout = () => { return ( - - - - - + + + + + + + ); diff --git a/client/src/components/Chat/ChatScreen.tsx b/client/src/components/Chat/ChatScreen.tsx index c3fac3fa6..2939a47cb 100644 --- a/client/src/components/Chat/ChatScreen.tsx +++ b/client/src/components/Chat/ChatScreen.tsx @@ -14,15 +14,15 @@ import { import { ChatInput } from "../Common/CustomInputs"; import { ChatSendButton } from "../Common/CustomButtons"; import MessageChannel from "../Common/MessageChannel"; -import { LinearGradient } from "expo-linear-gradient"; import * as Crypto from "expo-crypto"; import { generateName } from "../../utils/scripts"; -import { useSettings } from "../../contexts/SettingsContext"; import { SignOutButton } from "../Common/AuthButtons" import { MessageType } from "../../types/Message"; import { LocationProvider } from "../../contexts/LocationContext"; import { useSocket } from "../../contexts/SocketContext"; +import { useSettings } from "../../contexts/SettingsContext"; import { useLocation } from "../../contexts/LocationContext"; +import { useUser } from "../../contexts/UserContext"; // imported for when it needs to be used import { AuthStore } from "../../services/store"; const ChatScreen = () => { @@ -32,8 +32,10 @@ const ChatScreen = () => { const keyboardBehavior = Platform.OS === "ios" ? "padding" : undefined; const socket = useSocket(); const location = useLocation(); - const { user } = AuthStore.useState(); - + const user = useUser(); + const userAuth = AuthStore.useState() + // Note: To prevent complexity, all user information is grabbed from different contexts and services. If we wanted most information inside of UserContext, we would have to import contexts within contexts and have state change as certain things mount, which could cause errors that are difficult to pinpoint. + // Message loading and sending logic const [messages, setMessages] = React.useState([]); const [messageContent, setMessageContent] = React.useState(""); @@ -54,7 +56,9 @@ const ChatScreen = () => { const onHandleSubmit = () => { if (messageContent.trim() !== "") { const newMessage: MessageType = { - uid: String(user?.uid), + author: { + uid: String(userAuth.userAuthInfo?.uid), + }, msgId: Crypto.randomUUID(), msgContent: messageContent.trim(), timeSent: Date.now(), diff --git a/client/src/components/Common/MessageChannel.tsx b/client/src/components/Common/MessageChannel.tsx index ad215f708..3ff4c8629 100644 --- a/client/src/components/Common/MessageChannel.tsx +++ b/client/src/components/Common/MessageChannel.tsx @@ -20,7 +20,7 @@ const MessageChannel: React.FC = ({ messages }) => { renderItem={({ item }) => ( )} diff --git a/client/src/contexts/SettingsContext.tsx b/client/src/contexts/SettingsContext.tsx index c1d35a135..81f086ce4 100644 --- a/client/src/contexts/SettingsContext.tsx +++ b/client/src/contexts/SettingsContext.tsx @@ -36,9 +36,6 @@ export const SettingsProvider = ({ children: React.ReactNode; }) => { const [theme, setTheme] = useState("light"); - const [displayName, setDisplayName] = useState(""); - const [foregroundPfpImage, setForegroundPfpImage] = useState(""); - const [backgroundPfpImage, setBackgroundPfpImage] = useState(""); // Initial settings load useEffect(() => { diff --git a/client/src/contexts/SocketContext.tsx b/client/src/contexts/SocketContext.tsx index 118035845..47f294a47 100644 --- a/client/src/contexts/SocketContext.tsx +++ b/client/src/contexts/SocketContext.tsx @@ -1,6 +1,5 @@ import React, { createContext, useContext, useEffect, useState } from "react"; import { io, Socket } from "socket.io-client"; -import * as Network from "expo-network"; import { useLocation } from "./LocationContext"; import { EXPO_IP } from "@env"; @@ -27,11 +26,6 @@ export const SocketProvider = ({ children }: { children: React.ReactNode }) => { } }); - // socketIo.on("message", (data: MessageType, ack) => { - // console.log("Sending message to server:", data); - // if (ack) console.log("Server acknowledged message:", ack); - // }); - return () => { isMounted = false; socket?.disconnect(); diff --git a/client/src/contexts/UserContext.tsx b/client/src/contexts/UserContext.tsx new file mode 100644 index 000000000..42a0b4b3b --- /dev/null +++ b/client/src/contexts/UserContext.tsx @@ -0,0 +1,25 @@ +import React, { createContext, useContext } from 'react'; +import { UserType } from '../types/User'; +import { useState } from 'react'; + +const UserContext = createContext(null); + +export const useUser = () => { + return useContext(UserContext); +} + +export const UserProvider = ({ children }: {children: React.ReactNode}) => { + const [user, setUser] = useState({ + displayName: "DefaultDisplayName", + userIcon: { + imagePath: "DefaultImagePath", + colorHex: "#fff" + }, + }); + + return ( + + {children} + + ); +}; diff --git a/client/src/services/store.ts b/client/src/services/store.ts index f748dd7d7..84e9a8b34 100644 --- a/client/src/services/store.ts +++ b/client/src/services/store.ts @@ -2,17 +2,18 @@ import { User, createUserWithEmailAndPassword, onAuthStateChanged, signInWithEma import { Store } from 'pullstate' import { auth, app } from '../configs/firebaseConfig' import { FirebaseError } from 'firebase/app'; +import { useUser } from '../contexts/UserContext'; interface AuthStoreInterface { isLoggedin: boolean, initialized: boolean, - user: User | null, + userAuthInfo: User | null, } export const AuthStore = new Store({ isLoggedin: false, initialized: false, - user: null, + userAuthInfo: null, }) const unsub = onAuthStateChanged(auth, (user) => { @@ -20,7 +21,7 @@ const unsub = onAuthStateChanged(auth, (user) => { AuthStore.update((store) => { store.initialized = true, store.isLoggedin = user ? true : false, - store.user = user + store.userAuthInfo = user }) }); @@ -28,7 +29,7 @@ export const appSignIn = async (email: string, password: string) => { try { const response = await signInWithEmailAndPassword(auth, email, password); AuthStore.update((store) => { - store.user = response?.user; + store.userAuthInfo = response?.user; store.isLoggedin = response?.user ? true : false; }); @@ -42,7 +43,7 @@ export const appSignOut = async () => { try { await signOut(auth); AuthStore.update((store) => { - store.user = null; + store.userAuthInfo = null; store.isLoggedin = false; }); return { user: null} @@ -56,11 +57,11 @@ export const appSignUp = async (email: string, password: string) => { const response = await createUserWithEmailAndPassword(auth, email, password); AuthStore.update((store) => { - store.user = response.user; + store.userAuthInfo = response.user; store.isLoggedin = response.user ? true : false; }); return { user: auth.currentUser} } catch (e) { return { error: e }; } -}; \ No newline at end of file +}; diff --git a/client/src/types/Message.ts b/client/src/types/Message.ts index 3ef50bc59..2310a2714 100644 --- a/client/src/types/Message.ts +++ b/client/src/types/Message.ts @@ -1,6 +1,8 @@ export interface MessageType { - uid: string - authorName?: string // To be only used for display purposes (i.e. do not send to server) + author: { + uid: string + displayName?: string // To be only used for display purposes (do not send to server) + } msgId: string msgContent: string timeSent: number // Unix timestamp; Date.now() returns a Number. diff --git a/client/src/types/User.ts b/client/src/types/User.ts new file mode 100644 index 000000000..f85659001 --- /dev/null +++ b/client/src/types/User.ts @@ -0,0 +1,7 @@ +export interface UserType { + displayName: string + userIcon?: { + imagePath: string + colorHex: string + } +} diff --git a/client/src/utils/types.ts b/client/src/utils/types.ts new file mode 100644 index 000000000..a1eaa5023 --- /dev/null +++ b/client/src/utils/types.ts @@ -0,0 +1,11 @@ +export type MessageType = { + messageContent: string; + author: string; + msgID: string; +}; + +export type UserType = { + userID: string; + displayName: string; + pfp: string; +}; \ No newline at end of file