diff --git a/client/App.tsx b/client/App.tsx index cd2a5f69d..acc9c036a 100644 --- a/client/App.tsx +++ b/client/App.tsx @@ -1,14 +1,26 @@ import React from "react"; -import { StyleSheet, View, Text } from "react-native"; +import { StyleSheet, Text } from "react-native"; +import { AuthStore } from "./src/services/AuthStore"; +import { NavigationContainer } from "@react-navigation/native"; +import AppNavigator from "./src/navigation/AppNavigator"; +import AuthNavigator from "./src/navigation/AuthNavigator"; + + +const App = () => { + const { initialized, isLoggedin } = AuthStore.useState(); + + if (!initialized) return Loading...; -export default function App() { return ( - - This Componenet is DEPRECATED. - DO NOT TOUCH. THE NEW ENTRY POINT IS AT 'app/index.tsx' - + + {isLoggedin ? ( + + ) : ( + + )} + ); -} +}; const styles = StyleSheet.create({ container: { @@ -18,3 +30,5 @@ const styles = StyleSheet.create({ justifyContent: "center", }, }); + +export default App; diff --git a/client/package-lock.json b/client/package-lock.json index eb11d1b71..a1a0f0199 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,6 +12,9 @@ "@react-native-async-storage/async-storage": "1.18.2", "@react-native-firebase/app": "^18.7.3", "@react-native-firebase/auth": "^18.7.3", + "@react-navigation/bottom-tabs": "^6.5.20", + "@react-navigation/native": "^6.1.17", + "@react-navigation/stack": "^6.3.29", "expo": "~49.0.12", "expo-cli": "^6.3.10", "expo-constants": "~14.4.2", @@ -6736,11 +6739,11 @@ } }, "node_modules/@react-navigation/bottom-tabs": { - "version": "6.5.11", - "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.11.tgz", - "integrity": "sha512-CBN/NOdxnMvmjw+AJQI1kltOYaClTZmGec5pQ3ZNTPX86ytbIOylDIITKMfTgHZcIEFQDymx1SHeS++PIL3Szw==", + "version": "6.5.20", + "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.20.tgz", + "integrity": "sha512-ow6Z06iS4VqBO8d7FP+HsGjJLWt2xTWIvuWjpoCvsM/uQXzCRDIjBv9HaKcXbF0yTW7IMir0oDAbU5PFzEDdgA==", "dependencies": { - "@react-navigation/elements": "^1.3.21", + "@react-navigation/elements": "^1.3.30", "color": "^4.2.3", "warn-once": "^0.1.0" }, @@ -6753,16 +6756,16 @@ } }, "node_modules/@react-navigation/core": { - "version": "6.4.10", - "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz", - "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==", + "version": "6.4.16", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.16.tgz", + "integrity": "sha512-UDTJBsHxnzgFETR3ZxhctP+RWr4SkyeZpbhpkQoIGOuwSCkt1SE0qjU48/u6r6w6XlX8OqVudn1Ab0QFXTHxuQ==", "dependencies": { "@react-navigation/routers": "^6.1.9", "escape-string-regexp": "^4.0.0", "nanoid": "^3.1.23", "query-string": "^7.1.3", "react-is": "^16.13.0", - "use-latest-callback": "^0.1.7" + "use-latest-callback": "^0.1.9" }, "peerDependencies": { "react": "*" @@ -6780,9 +6783,9 @@ } }, "node_modules/@react-navigation/elements": { - "version": "1.3.21", - "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz", - "integrity": "sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg==", + "version": "1.3.30", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.30.tgz", + "integrity": "sha512-plhc8UvCZs0UkV+sI+3bisIyn78wz9O/BiWZXpounu72k/R/Sj5PuZYFJ1fi6psvriUveMCGh4LeZckAZu2qiQ==", "peerDependencies": { "@react-navigation/native": "^6.0.0", "react": "*", @@ -6791,11 +6794,11 @@ } }, "node_modules/@react-navigation/native": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz", - "integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.17.tgz", + "integrity": "sha512-mer3OvfwWOHoUSMJyLa4vnBH3zpFmCwuzrBPlw7feXklurr/ZDiLjLxUScOot6jLRMz/67GyilEYMmP99LL0RQ==", "dependencies": { - "@react-navigation/core": "^6.4.10", + "@react-navigation/core": "^6.4.16", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.1.23" @@ -6806,11 +6809,11 @@ } }, "node_modules/@react-navigation/native-stack": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.17.tgz", - "integrity": "sha512-X8p8aS7JptQq7uZZNFEvfEcPf6tlK4PyVwYDdryRbG98B4bh2wFQYMThxvqa+FGEN7USEuHdv2mF0GhFKfX0ew==", + "version": "6.9.26", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.26.tgz", + "integrity": "sha512-++dueQ+FDj2XkZ902DVrK79ub1vp19nSdAZWxKRgd6+Bc0Niiesua6rMCqymYOVaYh+dagwkA9r00bpt/U5WLw==", "dependencies": { - "@react-navigation/elements": "^1.3.21", + "@react-navigation/elements": "^1.3.30", "warn-once": "^0.1.0" }, "peerDependencies": { @@ -6840,6 +6843,24 @@ "nanoid": "^3.1.23" } }, + "node_modules/@react-navigation/stack": { + "version": "6.3.29", + "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.29.tgz", + "integrity": "sha512-tzlGkoRgB6P7vgw7rHuWo3TL7Gzu6xh5LMf+zSdCuEiKp/qASzxYfnTEr9tOLbVs/gf+qeukEDheCSAJKVpBXw==", + "dependencies": { + "@react-navigation/elements": "^1.3.30", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">= 1.0.0", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, "node_modules/@segment/loosely-validate-event": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", @@ -8408,13 +8429,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9567,16 +9593,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-lazy-prop": { @@ -9966,6 +9995,25 @@ "node": ">= 0.8" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", @@ -11247,9 +11295,9 @@ } }, "node_modules/expo-router": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-2.0.14.tgz", - "integrity": "sha512-F5dP4WMe+zQLzlGSbC+NT9/67FGgwmUCJuPGD4BkK0eRt0uga+y53vQ59m5MCOebqE0N9Ukr/Jz8Num16iGqZA==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-2.0.15.tgz", + "integrity": "sha512-6TZKWG6nVne5kGjTPOInAEsSmWy2K4DxXp96OoNUXKoRbJYIZyB++0VQRhXcUCGQSXZRfUa0z2ud8CusF+axNA==", "dependencies": { "@bacons/react-views": "^1.1.3", "@expo/metro-runtime": "2.2.16", @@ -11267,10 +11315,6 @@ "peerDependencies": { "@react-navigation/drawer": "^6.5.8", "expo": "^49.0.0", - "expo-constants": "*", - "expo-linking": "*", - "expo-status-bar": "*", - "metro": "~0.76.7", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": "*", @@ -12015,15 +12059,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12207,20 +12255,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -17639,9 +17687,9 @@ } }, "node_modules/react-native-gesture-handler": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.14.1.tgz", - "integrity": "sha512-YiM1BApV4aKeuwsM6O4C2ufwewYEKk6VMXOt0YqEZFMwABBFWhXLySFZYjBSNRU2USGppJbfHP1q1DfFQpKhdA==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.0.tgz", + "integrity": "sha512-1hFkx7RIfeJSyTQQ0Nkv4icFVZ5+XjQkd47OgZMBFzoB7ecL+nFSz8KLi3OCWOhq+nbHpSPlSG5VF3CQNCJpWA==", "peer": true, "dependencies": { "@egjs/hammerjs": "^2.0.17", @@ -18420,15 +18468,16 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -18488,13 +18537,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -19920,11 +19973,11 @@ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, "node_modules/url/node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", + "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" diff --git a/client/package.json b/client/package.json index 995d4e31d..a41d23021 100644 --- a/client/package.json +++ b/client/package.json @@ -1,7 +1,7 @@ { "name": "osc-proximity-chat-app", "version": "1.0.0", - "main": "expo-router/entry", + "main": "node_modules/expo/AppEntry.js", "scripts": { "start": "expo start", "android": "expo start --android", @@ -13,6 +13,9 @@ "@react-native-async-storage/async-storage": "1.18.2", "@react-native-firebase/app": "^18.7.3", "@react-native-firebase/auth": "^18.7.3", + "@react-navigation/bottom-tabs": "^6.5.20", + "@react-navigation/native": "^6.1.17", + "@react-navigation/stack": "^6.3.29", "expo": "~49.0.12", "expo-cli": "^6.3.10", "expo-constants": "~14.4.2", @@ -35,10 +38,10 @@ "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", - "react-native-svg": "13.9.0" + "socket.io-client": "^4.7.4" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/client/src/app/(auth)/signup.tsx b/client/src/app/(auth)/signup.tsx deleted file mode 100644 index 81710b0e1..000000000 --- a/client/src/app/(auth)/signup.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import SignUp from '../../components/Auth/SignUpScreen'; - -const SignUpPage = () => { - return ( - - ); -} - -export default SignUpPage \ No newline at end of file diff --git a/client/src/app/(auth)/welcome.tsx b/client/src/app/(auth)/welcome.tsx deleted file mode 100644 index d213d71d7..000000000 --- a/client/src/app/(auth)/welcome.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react' -import WelcomeScreen from '../../components/Home/WelcomeScreen'; -import { router } from 'expo-router'; -import SafeAreaWrapper from '../../components/Common/SafeAreaWrapper'; - -const WelcomePage = () => { - return ( - - - - ) -} - -export default WelcomePage; \ No newline at end of file diff --git a/client/src/app/(home)/chatchannel.tsx b/client/src/app/(home)/chatchannel.tsx deleted file mode 100644 index ad8d1c1db..000000000 --- a/client/src/app/(home)/chatchannel.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react' -import { Stack } from 'expo-router'; -import ChatScreen from '../../components/Chat/ChatScreen' -import SafeAreaWrapper from '../../components/Common/SafeAreaWrapper'; - -const ChatroomPage = () => { - return ( - - - - ); -} - -export default ChatroomPage \ No newline at end of file diff --git a/client/src/app/(auth)/_layout.tsx b/client/src/app_DEPRECATED/(auth)/_layout.tsx similarity index 100% rename from client/src/app/(auth)/_layout.tsx rename to client/src/app_DEPRECATED/(auth)/_layout.tsx diff --git a/client/src/app/(auth)/login.tsx b/client/src/app_DEPRECATED/(auth)/login.tsx similarity index 65% rename from client/src/app/(auth)/login.tsx rename to client/src/app_DEPRECATED/(auth)/login.tsx index 1897b4b18..37ff42002 100644 --- a/client/src/app/(auth)/login.tsx +++ b/client/src/app_DEPRECATED/(auth)/login.tsx @@ -1,5 +1,5 @@ import React from "react"; -import LogIn from "../../components/Auth/LoginScreen"; +import LogIn from "../../screens/auth/LoginScreen"; const LoginPage = () => { return ; diff --git a/client/src/app/(auth)/resetpass.tsx b/client/src/app_DEPRECATED/(auth)/resetpass.tsx similarity index 100% rename from client/src/app/(auth)/resetpass.tsx rename to client/src/app_DEPRECATED/(auth)/resetpass.tsx diff --git a/client/src/app_DEPRECATED/(auth)/signup.tsx b/client/src/app_DEPRECATED/(auth)/signup.tsx new file mode 100644 index 000000000..b872ed28a --- /dev/null +++ b/client/src/app_DEPRECATED/(auth)/signup.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import SignUp from "../../screens/auth/SignUpScreen"; + +const SignUpPage = () => { + return ; +}; + +export default SignUpPage; diff --git a/client/src/app_DEPRECATED/(auth)/welcome.tsx b/client/src/app_DEPRECATED/(auth)/welcome.tsx new file mode 100644 index 000000000..f58ea6738 --- /dev/null +++ b/client/src/app_DEPRECATED/(auth)/welcome.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import WelcomeScreen from "../../screens/auth/WelcomeScreen"; +import { router } from "expo-router"; +import SafeAreaWrapper from "../../components/common/SafeAreaWrapper"; + +const WelcomePage = () => { + return ( + + + + ); +}; + +export default WelcomePage; diff --git a/client/src/app/(home)/_layout.tsx b/client/src/app_DEPRECATED/(home)/_layout.tsx similarity index 100% rename from client/src/app/(home)/_layout.tsx rename to client/src/app_DEPRECATED/(home)/_layout.tsx diff --git a/client/src/app_DEPRECATED/(home)/chatchannel.tsx b/client/src/app_DEPRECATED/(home)/chatchannel.tsx new file mode 100644 index 000000000..b7a0be65f --- /dev/null +++ b/client/src/app_DEPRECATED/(home)/chatchannel.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import { Stack } from "expo-router"; +import ChatScreen from "../../screens/chat/ChatScreen"; +import SafeAreaWrapper from "../../components/common/SafeAreaWrapper"; + +const ChatroomPage = () => { + return ( + + + + ); +}; + +export default ChatroomPage; diff --git a/client/src/app/_layout.tsx b/client/src/app_DEPRECATED/_layout.tsx similarity index 100% rename from client/src/app/_layout.tsx rename to client/src/app_DEPRECATED/_layout.tsx diff --git a/client/src/app/index.tsx b/client/src/app_DEPRECATED/index.tsx similarity index 94% rename from client/src/app/index.tsx rename to client/src/app_DEPRECATED/index.tsx index 6629ea9c5..a8774f768 100644 --- a/client/src/app/index.tsx +++ b/client/src/app_DEPRECATED/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState, useContext } from "react"; import { View, Text } from "react-native"; -import { AuthStore } from "../services/store"; +import { AuthStore } from "../services/AuthStore"; import { useRootNavigationState, useRouter, useSegments } from "expo-router"; const App = () => { diff --git a/client/src/components/Common/ChatScreenFooter.tsx b/client/src/components/Common/ChatScreenFooter.tsx deleted file mode 100644 index af9998ed5..000000000 --- a/client/src/components/Common/ChatScreenFooter.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react' -import { TextInput, View, StyleSheet, Dimensions, Platform, TouchableOpacity } from 'react-native' -import { ChatSendButton } from './CustomButtons' -import { Smile, Image } from "react-native-feather"; - -interface ChatInputProps { - value?: string, - onChangeText?: (text: string) => void - invalid?: boolean, - onSend?: () => void, -} - -export const ChatScreenFooter: React.FC = ({ value, onChangeText, onSend }) => { - - - - return ( - - - - - - - - - - - - - - - ) -}; - -const styles = StyleSheet.create({ - - container: { - flexDirection: 'row', - flex: 1, - alignItems: 'center', - borderColor: "#8E8E8E", - borderWidth: 1, - borderRadius: Dimensions.get('window').width * 0.058, - marginHorizontal: Dimensions.get('window').width * 0.005, - marginBottom: Platform.OS === 'ios' ? 0 : 5, - minHeight: Dimensions.get('window').width * 0.113, - maxHeight: Dimensions.get('window').width * 0.3, - }, - messageInput: { - fontSize: 16, - flex: 1, - marginBottom: Platform.OS === 'ios' ? 5 : 4, - marginTop: Platform.OS === 'ios' ? 2 : 4, - marginHorizontal: Dimensions.get('window').width * 0.018, - - - }, - icons: { - marginHorizontal: Dimensions.get('window').width * 0.008, - }, - iconContainer: { - marginLeft: Dimensions.get('window').width * 0.02, - marginBottom: Dimensions.get('window').width * 0.025, - marginTop: Dimensions.get('window').width * 0.025, - flexDirection: 'row', - alignItems: "flex-end", - justifyContent: "flex-end", - alignSelf: "stretch", - - - }, - sendButtonContainer: { - alignItems: "flex-end", - justifyContent: "flex-end", - flexDirection: "row", - alignSelf: "stretch", - marginRight: Dimensions.get('window').width * 0.01, - marginBottom: Dimensions.get('window').width * 0.01, - marginTop: Dimensions.get('window').width * 0.01, - } - -}); \ No newline at end of file diff --git a/client/src/components/Common/MessageChannel.tsx b/client/src/components/Common/MessageChannel.tsx deleted file mode 100644 index 25c28db30..000000000 --- a/client/src/components/Common/MessageChannel.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react' -import Message from './ChatMessage' -import { FlatList, StyleSheet, View } from 'react-native' -import { MessageChannelProps } from '../../types/Props'; - - -const MessageChannel: React.FC = ({ messages }) => { - const reverseMessages = [...messages].reverse() - - return ( - item.msgId} - renderItem={({ item }) => ( - - )} - inverted={true} // This will render items from the bottom - onLayout={() => { }} // This will make sure the list is scrolled to the bottom on first render - /> - ) -} - -export default MessageChannel diff --git a/client/src/components/_deprecated/Message.tsx b/client/src/components/_deprecated/Message.tsx deleted file mode 100644 index 784e543b5..000000000 --- a/client/src/components/_deprecated/Message.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React from "react"; -import { StyleSheet, View, Text, Image, Dimensions } from "react-native"; -import { MessageType } from "../../utils/types"; - -const windowHeight = Dimensions.get("window").height; -const windowWidth = Dimensions.get("window").width; - -interface MessageProps { - messageContent: string; - timestamp: Date; - author: string; - msgId: string; -} - -export const Message = (messageContent:string, timestamp:Date, author:string, msgID:string) => { - return ( - - - - - - - - {author} - - - {timestamp.toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", - })} - - - - - {messageContent} - - - - - ); -}; - -const styles = StyleSheet.create({ - container: { - maxWidth: windowWidth, - paddingVertical: 5, - paddingTop: 7, - paddingBottom: 7, - }, - row: { - flexDirection: "row", - justifyContent: "space-between", - paddingRight: 4, - paddingLeft: 4, - }, - image: { - width: 45, - height: 45, - borderRadius: 150, - backgroundColor: "black", - justifyContent: "center", - }, - author: { - fontWeight: "bold", - fontSize: 15, - }, - timestamp: { - fontWeight: "500", - }, - - messageContent: { - flexWrap: "wrap", - }, - - message_container: {}, - - image_row: { - width: "15%", - alignItems: "center", - minWidth: 55, - }, - - content_column: { - width: "85%", - paddingLeft: 6, - }, - - header_row: { - flexDirection: "row", - justifyContent: "space-between", - paddingRight: 10, - marginBottom: 5, - }, -}); diff --git a/client/src/components/_deprecated/MessageBox.tsx b/client/src/components/_deprecated/MessageBox.tsx deleted file mode 100644 index 7d60a9d51..000000000 --- a/client/src/components/_deprecated/MessageBox.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import React, { useEffect, useState, useRef } from "react"; -import { - Button, - StyleSheet, - TextInput, - TouchableOpacity, - View, - KeyboardAvoidingView, - Platform, - Image, -} from "react-native"; -import * as Crypto from "expo-crypto"; -import { - MessageType, - MessageDataType, - AppContextType, -} from "../../utils/types"; -import { AppContext } from "../../constants/Contexts"; -const sendIcon = require("../../assets/paper-plane.png"); - -interface MessageBoxProps { - onSendMessage: (message: MessageType) => void; -} - -const postMessage = async (messageData: MessageDataType) => { -const URL = `http://${process.env.EXPO_PUBLIC_BACKEND_ADDRESS}:${process.env.EXPO_PUBLIC_BACKEND_PORT}/messages`; - const response = await fetch(URL, { - method: "POST", - mode: "no-cors", - headers: { - "Content-Type": "application/json", - }, - referrerPolicy: "same-origin", - body: JSON.stringify(messageData), - }); - return response.json(); -}; - -export const MessageBox: React.FC = ({ onSendMessage }) => { - const [messageContent, setMessageContent] = useState(""); - const isMounted = useRef(false); - // TODO: Make sure date(0).getTime() returns a Unix Epoch in seconds - const [messageData, setMessageData] = useState({ - userId: "", - msgId: "", - msgContent: "", - specificLat: "", - specificLon: "", - timeSent: new Date(0).getTime() - }); - const [newMessage, setNewMessage] = useState(); - const keyboardVerticalOffest = Platform.OS === "ios" ? 50 : 0; - const keyboardBehavior = Platform.OS === "ios" ? "padding" : undefined; - const inputBoxStyles = - Platform.OS === "ios" - ? styles.ios_specific_text - : styles.android_specific_text; - - useEffect(() => { - if (isMounted.current) { - postMessage(messageData) - .then((data) => { - if (data) { - if (newMessage) { - onSendMessage(newMessage); - } else { - console.log("How the fuck did this throw an error"); - } - } - }) - .catch((err) => { - console.error(err); - }); - } else { - isMounted.current = true; - } - }, [messageData]); - - return ( - - {(context: AppContextType) => { - const onPress = () => { - if (messageContent === "") { - console.log("Empty string entered..."); - } else { - const date = new Date(); - const messageData: MessageDataType = { - userId: context.user?.userId, - msgId: Crypto.randomUUID(), - msgContent: messageContent, - specificLat: `${context.location?.location?.coords.latitude}`, - specificLon: `${context.location?.location?.coords.longitude}`, - timeSent: date.getTime(), - }; - - const newMessage: MessageType = { - author: String(context.user?.displayName), - timestamp: date, - messageContent: messageData.msgContent, - msgId: messageData.msgId, - }; - setNewMessage(newMessage); - setMessageData(messageData); - setMessageContent(""); - } - }; - - return ( - - - - - - - - - ); - }} - - ); -}; - -const styles = StyleSheet.create({ - container: { - flexDirection: "row", - display: "flex", - overflow: "hidden", // Ensures inner elements don't overflow rounded corners - maxWidth: "90%", - minWidth: "90%", - justifyContent: "space-between", - minHeight: 45, - alignItems: "flex-end", - paddingLeft: 5, - marginBottom: 15, - paddingTop: 15, - }, - button: { - backgroundColor: "#3333ff", - flexDirection: "column", - borderRadius: 25, - height: 45, - width: 45, - justifyContent: "center", - alignItems: "center", - }, - - sendIcon: { - height: 20, - width: 20, - resizeMode: "contain", - marginRight: 3, - }, - android_specific_text: { - backgroundColor: "#F3F2F2", - padding: 8, - paddingLeft: 18, - paddingRight: 18, - width: "84%", - borderRadius: 25, - maxHeight: 200, - minHeight: 45, - }, - - ios_specific_text: { - backgroundColor: "#F3F2F2", - paddingTop: 15, - paddingBottom: 15, - paddingLeft: 18, - paddingRight: 18, - width: "84%", - borderRadius: 25, - maxHeight: 200, - minHeight: 45, - }, -}); diff --git a/client/src/components/_deprecated/MessageList.tsx b/client/src/components/_deprecated/MessageList.tsx deleted file mode 100644 index 470c31ebf..000000000 --- a/client/src/components/_deprecated/MessageList.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from "react"; -import { StyleSheet, FlatList, Dimensions } from "react-native"; -import { MessageType } from "../../utils/types"; -import { Message } from "./Message"; - -const { width } = Dimensions.get("window"); - -interface MessageListProps { - messages: {author: string, messageContent: string, msgId: string}[] -} - -export const MessageList: React.FC = ({ messages }) => { - - const date = new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); - - return ( - item.msgId.toString()} - renderItem={({ item }) => ( - - )} - inverted={true} // This will render items from the bottom - /> - ); -}; - -const styles = StyleSheet.create({ - container: { - height: "100%", - width: "100%", - }, -}); diff --git a/client/src/components/_deprecated/MessageWrapper.tsx b/client/src/components/_deprecated/MessageWrapper.tsx deleted file mode 100644 index 8451308a5..000000000 --- a/client/src/components/_deprecated/MessageWrapper.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from "react"; -import { View, StyleSheet } from "react-native"; -import { MessageList } from "./MessageList"; -import { MessageBox } from "./MessageBox"; -import { useState } from "react"; -import { MessageType } from "../../utils/types"; -import { useSocket } from "../../contexts/SocketContext"; - -export const MessageWrapper = () => { - const socket = useSocket(); - - const messages = [ - { author: "Alex", messageContent: "Hello, my name is Alex!!!", msgID: "1" }, - { author: "Ben", messageContent: "Hello, my name is Ben!!!", msgID: "2" }, - { - author: "Chris", - messageContent: - "This is chris's message, it is a little bit longer because he a very outspoken person and has a lottt to say!", - msgID: "3", - }, - { author: "Alex", messageContent: "Hello, my name is Alex!!!", msgID: "4" }, - { author: "Ben", messageContent: "Hello, my name is Ben!!!", msgID: "5" }, - { - author: "Chris", - messageContent: - "This is chris's message, it is a little bit longer because he a very outspoken person and has a lottt to say!", - msgID: "6", - }, - { author: "Alex", messageContent: "Hello, my name is Alex!!!", msgID: "7" }, - { author: "Ben", messageContent: "Hello, my name is Ben!!!", msgID: "8" }, - ]; - - return ( - - - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: "#fff", - alignItems: "center", - flexDirection: "column", - width: "100%", - }, -}); diff --git a/client/src/components/_deprecated/ProximityChat.tsx b/client/src/components/_deprecated/ProximityChat.tsx deleted file mode 100644 index c29f22917..000000000 --- a/client/src/components/_deprecated/ProximityChat.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { - StyleSheet, - View, - SafeAreaView, - Platform, - StatusBar, -} from "react-native"; -import { - requestForegroundPermissionsAsync, - getCurrentPositionAsync, - reverseGeocodeAsync, - LocationGeocodedAddress, - LocationObject, -} from "expo-location"; -import { AppContext } from "../../constants/Contexts"; -import { SocketProvider } from "../../contexts/SocketContext"; -import { generateName, generateUniqueId } from "../../utils/scripts"; -import { MessageWrapper } from "./MessageWrapper"; - -export default () => { - const [location, setLocation] = useState(); - const [address, setAddress] = useState(); - const [errorMsg, setErrorMsg] = useState(); - - useEffect(() => { - (async () => { - let { status } = await requestForegroundPermissionsAsync(); - if (status !== "granted") { - setErrorMsg("Permission to access location was denied"); - return; - } - - let location = await getCurrentPositionAsync({}); - let address = await reverseGeocodeAsync({ - latitude: location.coords.latitude, - longitude: location.coords.longitude, - }); - setLocation(location); - setAddress(address); - })(); - }); - - let coordsText = ""; - if (errorMsg) { - coordsText = errorMsg; - } else if (location) { - coordsText = `${location.coords.latitude}, ${location.coords.longitude}`; - } - - let addressText = ""; - if (errorMsg) { - addressText = errorMsg; - } else if (address) { - addressText = `${address[0].streetNumber} ${address[0].street}`; - } - - return ( - - - - - - - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: "#fff", - alignItems: "center", - flexDirection: "column", - width: "100%", - }, - container_wrapper: { - width: "100%", - height: "100%", - alignItems: "flex-end", - paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0, - }, -}); diff --git a/client/src/components/Common/AuthButtons.tsx b/client/src/components/auth/AuthButtons.tsx similarity index 96% rename from client/src/components/Common/AuthButtons.tsx rename to client/src/components/auth/AuthButtons.tsx index 7b9c13088..cd733dd8f 100644 --- a/client/src/components/Common/AuthButtons.tsx +++ b/client/src/components/auth/AuthButtons.tsx @@ -12,7 +12,7 @@ import { } from "react-native"; import { router, useRouter } from "expo-router"; import { useFonts } from "expo-font"; -import { appSignOut } from "../../services/store"; +import { appSignOut } from "../../services/AuthStore"; interface SignOutButtonProps {} @@ -23,6 +23,7 @@ export const SignOutButton: React.FC = () => { const [fontsLoaded, fontError] = useFonts({ "Gilroy-ExtraBold": require("../../../assets/fonts/Gilroy-ExtraBold.otf"), "Gilroy-Light": require("../../../assets/fonts/Gilroy-Light.otf"), + "Quicksand-Medium": require("../../../assets/fonts/Quicksand-Medium.ttf"), // fixed loading this file! }); const handleSignOut = async () => { diff --git a/client/src/components/Auth/AuthenticationResponse.tsx b/client/src/components/auth/AuthenticationResponse.tsx similarity index 100% rename from client/src/components/Auth/AuthenticationResponse.tsx rename to client/src/components/auth/AuthenticationResponse.tsx diff --git a/client/src/components/Common/LogInButton.tsx b/client/src/components/auth/LogInButton.tsx similarity index 100% rename from client/src/components/Common/LogInButton.tsx rename to client/src/components/auth/LogInButton.tsx diff --git a/client/src/components/Common/SignUpButton.tsx b/client/src/components/auth/SignUpButton.tsx similarity index 82% rename from client/src/components/Common/SignUpButton.tsx rename to client/src/components/auth/SignUpButton.tsx index 499fe6ba8..4ae154fc1 100644 --- a/client/src/components/Common/SignUpButton.tsx +++ b/client/src/components/auth/SignUpButton.tsx @@ -2,13 +2,12 @@ import { router } from "expo-router"; import React from "react"; import { useFonts } from "expo-font"; import { StyleSheet, Text, TouchableOpacity, Dimensions } from "react-native"; -import { SignUpButtonProps } from "../../utils/types"; +import { SignUpButtonProps } from "../../types/Props"; const SignUpButton: React.FC = ({ onPress }) => { - const [fontsLoaded, fontError] = useFonts({ - 'Gilroy-ExtraBold': require('../../../assets/fonts/Gilroy-ExtraBold.otf'), - 'Gilroy-Light': require('../../../assets/fonts/Gilroy-Light.otf'), + "Gilroy-ExtraBold": require("../../../assets/fonts/Gilroy-ExtraBold.otf"), + "Gilroy-Light": require("../../../assets/fonts/Gilroy-Light.otf"), }); if (!fontsLoaded && !fontError) { @@ -37,7 +36,6 @@ const styles = StyleSheet.create({ color: "white", fontFamily: "Gilroy-ExtraBold", fontSize: Dimensions.get("window").height * 0.03, - }, }); diff --git a/client/src/components/Common/ChatMessage.tsx b/client/src/components/chat/ChatMessage.tsx similarity index 100% rename from client/src/components/Common/ChatMessage.tsx rename to client/src/components/chat/ChatMessage.tsx diff --git a/client/src/components/chat/ChatScreenFooter.tsx b/client/src/components/chat/ChatScreenFooter.tsx new file mode 100644 index 000000000..4b9aebdd0 --- /dev/null +++ b/client/src/components/chat/ChatScreenFooter.tsx @@ -0,0 +1,91 @@ +import React from "react"; +import { + TextInput, + View, + StyleSheet, + Dimensions, + Platform, + TouchableOpacity, +} from "react-native"; +import { ChatSendButton } from "../common/CustomButtons"; +import { Smile, Image } from "react-native-feather"; + +interface ChatInputProps { + value?: string; + onChangeText?: (text: string) => void; + invalid?: boolean; + onSend?: () => void; +} + +export const ChatScreenFooter: React.FC = ({ + value, + onChangeText, + onSend, +}) => { + return ( + + + + + + + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: "row", + flex: 1, + alignItems: "center", + borderColor: "#8E8E8E", + borderWidth: 1, + borderRadius: Dimensions.get("window").width * 0.058, + marginHorizontal: Dimensions.get("window").width * 0.005, + marginBottom: Platform.OS === "ios" ? 0 : 5, + minHeight: Dimensions.get("window").width * 0.113, + maxHeight: Dimensions.get("window").width * 0.3, + }, + messageInput: { + fontSize: 16, + flex: 1, + marginBottom: Platform.OS === "ios" ? 5 : 4, + marginTop: Platform.OS === "ios" ? 2 : 4, + marginHorizontal: Dimensions.get("window").width * 0.018, + }, + icons: { + marginHorizontal: Dimensions.get("window").width * 0.008, + }, + iconContainer: { + marginLeft: Dimensions.get("window").width * 0.02, + marginBottom: Dimensions.get("window").width * 0.025, + marginTop: Dimensions.get("window").width * 0.025, + flexDirection: "row", + alignItems: "flex-end", + justifyContent: "flex-end", + alignSelf: "stretch", + }, + sendButtonContainer: { + alignItems: "flex-end", + justifyContent: "flex-end", + flexDirection: "row", + alignSelf: "stretch", + marginRight: Dimensions.get("window").width * 0.01, + marginBottom: Dimensions.get("window").width * 0.01, + marginTop: Dimensions.get("window").width * 0.01, + }, +}); diff --git a/client/src/components/chat/MessageChannel.tsx b/client/src/components/chat/MessageChannel.tsx new file mode 100644 index 000000000..b6d8b2b64 --- /dev/null +++ b/client/src/components/chat/MessageChannel.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import Message from "./ChatMessage"; +import { FlatList, StyleSheet, View } from "react-native"; +import { MessageChannelProps } from "../../types/Props"; + +const MessageChannel: React.FC = ({ messages }) => { + const reverseMessages = [...messages].reverse(); + + return ( + item.msgId} + renderItem={({ item }) => ( + + )} + inverted={true} // This will render items from the bottom + onLayout={() => {}} // This will make sure the list is scrolled to the bottom on first render + /> + ); +}; + +export default MessageChannel; diff --git a/client/src/components/Common/NearbyCount.tsx b/client/src/components/chat/NearbyCount.tsx similarity index 100% rename from client/src/components/Common/NearbyCount.tsx rename to client/src/components/chat/NearbyCount.tsx diff --git a/client/src/components/Common/NearbyHeader.tsx b/client/src/components/chat/NearbyHeader.tsx similarity index 100% rename from client/src/components/Common/NearbyHeader.tsx rename to client/src/components/chat/NearbyHeader.tsx diff --git a/client/src/components/Common/CustomButtons.tsx b/client/src/components/common/CustomButtons.tsx similarity index 100% rename from client/src/components/Common/CustomButtons.tsx rename to client/src/components/common/CustomButtons.tsx diff --git a/client/src/components/Common/CustomInputs.tsx b/client/src/components/common/CustomInputs.tsx similarity index 100% rename from client/src/components/Common/CustomInputs.tsx rename to client/src/components/common/CustomInputs.tsx diff --git a/client/src/components/Common/SafeAreaWrapper.tsx b/client/src/components/common/SafeAreaWrapper.tsx similarity index 100% rename from client/src/components/Common/SafeAreaWrapper.tsx rename to client/src/components/common/SafeAreaWrapper.tsx diff --git a/client/src/components/Settings/SettingsItem.tsx b/client/src/components/settings/SettingsItem.tsx similarity index 100% rename from client/src/components/Settings/SettingsItem.tsx rename to client/src/components/settings/SettingsItem.tsx diff --git a/client/src/contexts/SocketContext.tsx b/client/src/contexts/SocketContext.tsx index 17c2e285c..305aa6173 100644 --- a/client/src/contexts/SocketContext.tsx +++ b/client/src/contexts/SocketContext.tsx @@ -2,7 +2,7 @@ import React, { createContext, useContext, useEffect, useState } from "react"; import { io, Socket } from "socket.io-client"; import { useLocation } from "./LocationContext"; import { EXPO_IP } from "@env"; -import { AuthStore } from "../services/store"; +import { AuthStore } from "../services/AuthStore"; const SocketContext = createContext(null); @@ -15,52 +15,49 @@ export const SocketProvider = ({ children }: { children: React.ReactNode }) => { const [mounted, setMounted] = useState(false); const locationContext = useLocation(); - useEffect(() => { const getToken = async () => { const token = await AuthStore.getRawState().userAuthInfo?.getIdToken(); console.log("Token:", token); return token; - } - + }; + const initializeSocket = async () => { const token = await getToken(); const socketIo = io(`http://${EXPO_IP}:8080`, { auth: { token: token, - } + }, }); - socketIo.connect() + socketIo.connect(); setSocket(socketIo); setMounted(true); - } - + }; if (!mounted) { initializeSocket(); } return () => { + socket?.disconnect(); console.log("[LOG]: Cleaning up intializeSocket useEffect"); }; }, []); // Listen to the socket state and run once the socket is set! useEffect(() => { - if (!socket) return; - + socket.on("connect", () => { console.log("Connected to server"); - } - ); + }); return () => { console.log("[LOG]: Cleaning up sockets and mounted state."); socket.disconnect(); setSocket(null); setMounted(false); - } + }; }, [socket]); useEffect(() => { diff --git a/client/src/navigation/AppNavigator.tsx b/client/src/navigation/AppNavigator.tsx new file mode 100644 index 000000000..731c832a3 --- /dev/null +++ b/client/src/navigation/AppNavigator.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; +import ChatScreen from "../screens/chat/ChatScreen"; +import SettingsScreen from "../screens/settings/SettingsScreen"; +import { SocketProvider } from "../contexts/SocketContext"; +import { LocationProvider } from "../contexts/LocationContext"; +import { UserProvider } from "../contexts/UserContext"; + +const Tab = createBottomTabNavigator(); + +const AppNavigator = () => { + return ( + + + + + + + + + + + ); +}; + +export default AppNavigator; diff --git a/client/src/navigation/AuthNavigator.tsx b/client/src/navigation/AuthNavigator.tsx new file mode 100644 index 000000000..8f3f12b5c --- /dev/null +++ b/client/src/navigation/AuthNavigator.tsx @@ -0,0 +1,23 @@ +import * as React from "react"; +import { createStackNavigator } from "@react-navigation/stack"; +import WelcomeScreen from "../screens/auth/WelcomeScreen"; +import LoginScreen from "../screens/auth/LoginScreen"; +import SignUpScreen from "../screens/auth/SignUpScreen"; + +const Stack = createStackNavigator(); + +const AuthNavigator = () => { + return ( + + + + + + ); +}; + +export default AuthNavigator; diff --git a/client/src/components/Auth/LoginScreen.tsx b/client/src/screens/auth/LoginScreen.tsx similarity index 91% rename from client/src/components/Auth/LoginScreen.tsx rename to client/src/screens/auth/LoginScreen.tsx index d61dc4cf5..cfb62bfaa 100644 --- a/client/src/components/Auth/LoginScreen.tsx +++ b/client/src/screens/auth/LoginScreen.tsx @@ -11,24 +11,30 @@ import { Keyboard, TouchableOpacity, } from "react-native"; -import { EmailInput, PasswordInput } from "../Common/CustomInputs"; -import { LogInButton, ExternalAuthButton } from "../Common/AuthButtons"; +import { + EmailInput, + PasswordInput, +} from "../../components/common/CustomInputs"; +import { + LogInButton, + ExternalAuthButton, +} from "../../components/auth/AuthButtons"; import { useLocalSearchParams, useRouter } from "expo-router"; -import { appSignIn } from "../../services/store"; +import { appSignIn } from "../../services/AuthStore"; import { AuthenticationErrorMessage, AuthenticationResponse, -} from "./AuthenticationResponse"; +} from "../../components/auth/AuthenticationResponse"; import { ArrowLeftCircle } from "react-native-feather"; -const LoginScreen = () => { - const router = useRouter(); +const LoginScreen = ({ route, navigation }: any) => { const [fontsLoaded, fontError] = useFonts({ "Quicksand-Bold": require("../../../assets/fonts/Quicksand-Bold.ttf"), "Quicksand-Medium": require("../../../assets/fonts/Quicksand-Medium.ttf"), }); - const { inputEmail } = useLocalSearchParams(); + const { newEmail } = route.params; + const [email, setEmail] = React.useState(""); const [password, setPassword] = React.useState(""); const [authResponse, setAuthResponse] = @@ -50,7 +56,7 @@ const LoginScreen = () => { // Listens for the response from the sign in function useEffect(() => { if (authResponse?.user) { - router.replace("(home)/chatchannel"); + console.log("user logged in!"); } else if (authResponse?.error) { console.log(authResponse.error); invalidateLogin(true); @@ -58,7 +64,7 @@ const LoginScreen = () => { }, [authResponse]); useEffect(() => { - setEmail(inputEmail?.toString() || ""); // On load of the page, set the email to the inputEmail if they entered it! + setEmail(newEmail); // On load of the page, set the email to the inputEmail if they entered it! }, []); if (!fontsLoaded && !fontError) { @@ -86,7 +92,7 @@ const LoginScreen = () => { router.back()} + onPress={() => navigation.goBack()} style={styles.back_button} > { Don't have an account? - router.replace({ pathname: "/signup" })} - > + navigation.navigate("Sign Up")}> { - const router = useRouter(); +const SignUpScreen = ({ navigation }: any) => { const [fontsLoaded, fontError] = useFonts({ "Quicksand-Bold": require("../../../assets/fonts/Quicksand-Bold.ttf"), "Quicksand-Medium": require("../../../assets/fonts/Quicksand-Medium.ttf"), @@ -58,7 +59,7 @@ const SignUpScreen = () => { setAuthResponse(await appSignUp(email, password)); if (authResponse?.user) { - router.replace("(home)/chatchannel"); + console.log("User Logged IN!"); } else if (authResponse?.error) { console.log(authResponse.error); } @@ -92,7 +93,7 @@ const SignUpScreen = () => { router.back()} + onPress={() => navigation.goBack()} style={styles.back_button} > { Already have an account? router.replace({ pathname: "/login" })} + onPress={() => navigation.navigate("Log In", { newEmail: "" })} > { ); - - }; const styles = StyleSheet.create({ diff --git a/client/src/components/Home/WelcomeScreen.tsx b/client/src/screens/auth/WelcomeScreen.tsx similarity index 59% rename from client/src/components/Home/WelcomeScreen.tsx rename to client/src/screens/auth/WelcomeScreen.tsx index 2a63a624d..b0e300fdf 100644 --- a/client/src/components/Home/WelcomeScreen.tsx +++ b/client/src/screens/auth/WelcomeScreen.tsx @@ -1,24 +1,36 @@ -import React, { useState, useCallback, useEffect } from 'react' -import { View, Text, Image, StyleSheet, Dimensions, TouchableOpacity, TouchableWithoutFeedback, Keyboard, Platform, KeyboardAvoidingView, SafeAreaView } from 'react-native'; -import { useFonts } from 'expo-font'; -import { Link, router } from 'expo-router'; -import * as SplashScreen from 'expo-splash-screen'; -import { WelcomeEmailInput } from '../Common/CustomInputs'; -import { AuthenticationErrorMessage, AuthenticationResponse, inValidEmailResponse } from '../Auth/AuthenticationResponse'; -import { FirebaseError } from 'firebase/app'; - -const WelcomeScreen = () => { - +import React, { useState } from "react"; +import { + View, + Text, + Image, + StyleSheet, + Dimensions, + TouchableOpacity, + TouchableWithoutFeedback, + Keyboard, + Platform, + KeyboardAvoidingView, +} from "react-native"; +import { useFonts } from "expo-font"; +import { WelcomeEmailInput } from "../../components/common/CustomInputs"; +import { + AuthenticationErrorMessage, + AuthenticationResponse, + inValidEmailResponse, +} from "../../components/auth/AuthenticationResponse"; + +const WelcomeScreen = ({ navigation }: any) => { const keyboardVerticalOffest = Platform.OS === "ios" ? 0 : 0; const keyboardBehavior = Platform.OS === "ios" ? "padding" : undefined; const [fontsLoaded, fontError] = useFonts({ - 'Gilroy-ExtraBold': require('../../../assets/fonts/Gilroy-ExtraBold.otf'), - 'Gilroy-Light': require('../../../assets/fonts/Gilroy-Light.otf'), + "Gilroy-ExtraBold": require("../../../assets/fonts/Gilroy-ExtraBold.otf"), + "Gilroy-Light": require("../../../assets/fonts/Gilroy-Light.otf"), }); - const [email, setEmail] = useState(''); - const [authResponse, setAuthResponse] = React.useState(); + const [email, setEmail] = useState(""); + const [authResponse, setAuthResponse] = + React.useState(); if (!fontsLoaded && !fontError) { return null; @@ -26,15 +38,14 @@ const WelcomeScreen = () => { const handleLogin = () => { const preparedEmail = email.trim(); - if ((preparedEmail.length !== 0) && isValidEmail(preparedEmail)) { - router.push( { pathname: '/login', params: { inputEmail: preparedEmail } } ); - setAuthResponse(undefined) + if (preparedEmail.length !== 0 && isValidEmail(preparedEmail)) { + navigation.navigate("Log In", { newEmail: preparedEmail }); + setAuthResponse(undefined); } else { - console.log('Invalid email'); - setAuthResponse({user: undefined, error: inValidEmailResponse}) + console.log("Invalid email"); + setAuthResponse({ user: undefined, error: inValidEmailResponse }); } - } - + }; const isValidEmail = (email: string) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; @@ -43,53 +54,69 @@ const WelcomeScreen = () => { return ( - - + - - - - - - + Welcome to Proximity Chat! - Login - setEmail(text)} /> - - - + setEmail(text)} + /> + + + - - setAuthResponse(undefined)} /> + setAuthResponse(undefined)} + /> - Don't have an account? Sign up! + Don't have an account?{" "} + { + navigation.navigate("Sign Up"); // Need to restyle + }} + > + Sign up. + - - ) -} + ); +}; const styles = StyleSheet.create({ image: { @@ -120,10 +147,10 @@ const styles = StyleSheet.create({ display: "flex", flexDirection: "column", alignItems: "center", - height: '100%', - width: '100%', + height: "100%", + width: "100%", justifyContent: "flex-end", - + backgroundColor: "white", }, sub_container: { @@ -142,7 +169,6 @@ const styles = StyleSheet.create({ alignItems: "center", justifyContent: "space-evenly", minHeight: Dimensions.get("window").height * 0.35, - }, login_container: { @@ -188,8 +214,7 @@ const styles = StyleSheet.create({ link: { color: "#5dbea3", textDecorationLine: "underline", - } - + }, }); -export default WelcomeScreen +export default WelcomeScreen; diff --git a/client/src/components/Chat/ChatScreen.tsx b/client/src/screens/chat/ChatScreen.tsx similarity index 88% rename from client/src/components/Chat/ChatScreen.tsx rename to client/src/screens/chat/ChatScreen.tsx index 254358858..7542836af 100644 --- a/client/src/components/Chat/ChatScreen.tsx +++ b/client/src/screens/chat/ChatScreen.tsx @@ -11,20 +11,20 @@ import { SafeAreaView, ScrollView, } from "react-native"; -import { ChatInput } from "../Common/CustomInputs"; -import { ChatSendButton } from "../Common/CustomButtons"; -import MessageChannel from "../Common/MessageChannel"; +import { ChatInput } from "../../components/common/CustomInputs"; +import { ChatSendButton } from "../../components/common/CustomButtons"; +import MessageChannel from "../../components/chat/MessageChannel"; import * as Crypto from "expo-crypto"; import { generateName } from "../../utils/scripts"; -import { SignOutButton } from "../Common/AuthButtons" +import { SignOutButton } from "../../components/auth/AuthButtons"; import { Message } 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"; -import { ChatScreenFooter } from "../Common/ChatScreenFooter" +import { AuthStore } from "../../services/AuthStore"; +import { ChatScreenFooter } from "../../components/chat/ChatScreenFooter"; const ChatScreen = () => { const settings = useSettings(); @@ -33,25 +33,25 @@ const ChatScreen = () => { const keyboardBehavior = Platform.OS === "ios" ? "padding" : undefined; const socket = useSocket(); const location = useLocation(); - const user = useUser(); - const userAuth = 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(""); useEffect(() => { if (socket === null) return; // This line might need to be changed - + const handleMessage = (data: any, ack?: any) => { console.log("Message received from server:", data); setMessages((prevMessages) => [...prevMessages, data]); if (ack) console.log("Server acknowledged message:", ack); }; - + socket.on("message", handleMessage); - + return () => { socket.off("message", handleMessage); }; @@ -65,28 +65,27 @@ const ChatScreen = () => { uid: String(userAuth.userAuthInfo?.uid), displayName: "Anonymous", }, - msgId: Crypto.randomUUID(), + msgId: Crypto.randomUUID(), msgContent: messageContent.trim(), timestamp: Date.now(), lastUpdated: Date.now(), location: { lat: Number(location?.latitude), - lon: Number(location?.longitude) + lon: Number(location?.longitude), }, isReply: false, replyTo: "", reactions: {}, - } + }; if (socket !== null) { - socket.emit("message", newMessage) + socket.emit("message", newMessage); } setMessageContent(""); } }; - return (