From 685c03e505fb2f8d6e3c583bb6d39eeee010b714 Mon Sep 17 00:00:00 2001 From: talksik Date: Fri, 1 Apr 2022 11:10:37 -0400 Subject: [PATCH] cleaning a bunch of the auth stuff but not done --- packages/api/index.ts | 2 +- packages/api/middleware/auth.ts | 26 +- packages/api/routes/user.ts | 45 +- packages/core/models/user.model.ts | 4 +- packages/core/responses/login.response.ts | 5 + .../src/components/ProtectedRoute/index.tsx | 47 +- packages/desktop/src/controller/index.tsx | 191 +----- packages/desktop/src/controller/nirvanaApi.ts | 53 +- packages/desktop/src/controller/recoil.tsx | 7 +- packages/desktop/src/controller/sockets.tsx | 29 +- packages/desktop/src/electron/constants.ts | 5 +- packages/desktop/src/electron/handleLogin.ts | 32 +- packages/desktop/src/index.ts | 4 +- .../src/pages/Home/conversations/index.tsx | 9 +- .../desktop/src/pages/Home/header/index.tsx | 172 +++--- packages/desktop/src/pages/Home/index.tsx | 11 +- .../desktop/src/pages/Home/search/index.tsx | 26 +- .../pages/Home/selectedConversation/index.tsx | 564 +++++++++--------- 18 files changed, 554 insertions(+), 678 deletions(-) create mode 100644 packages/core/responses/login.response.ts diff --git a/packages/api/index.ts b/packages/api/index.ts index 8f02515..38ea2fb 100644 --- a/packages/api/index.ts +++ b/packages/api/index.ts @@ -25,7 +25,7 @@ app.get("/", (req: Request, res: Response) => { res.send("hello world."); }); -app.use("/api/users", getUserRoutes()); +app.use("/api/user", getUserRoutes()); app.use("/api/search", getSearchRoutes()); app.use("/api/conversations", getConversationRoutes()); app.use("/api/contacts", getContactsRoutes()); diff --git a/packages/api/middleware/auth.ts b/packages/api/middleware/auth.ts index 3477608..5a05e19 100644 --- a/packages/api/middleware/auth.ts +++ b/packages/api/middleware/auth.ts @@ -14,21 +14,23 @@ export const authCheck = async ( ) => { const { authorization } = req.headers; + // verify jwt token + try { - const ticket = await client.verifyIdToken({ - idToken: authorization ?? "", - audience: - "423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com", // Specify the CLIENT_ID of the app that accesses the backend - }); - const userId = ticket.getPayload()?.sub; - const email = ticket.getPayload()?.email; + // const ticket = await client.verifyIdToken({ + // idToken: authorization ?? "", + // audience: + // "423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com", // Specify the CLIENT_ID of the app that accesses the backend + // }); + // const userId = ticket.getPayload()?.sub; + // const email = ticket.getPayload()?.email; - if (!userId) throw new Error("No google user Id found"); + // if (!userId) throw new Error("No google user Id found"); - // used in subsequent handlers - // todo: have to get our database id for the user instead of google's id - res.locals.userId = userId; - res.locals.email = email; + // // used in subsequent handlers + // // todo: have to get our database id for the user instead of google's id + // res.locals.userId = userId; + // res.locals.email = email; next(); } catch (error) { diff --git a/packages/api/routes/user.ts b/packages/api/routes/user.ts index 65f97e0..02a3160 100644 --- a/packages/api/routes/user.ts +++ b/packages/api/routes/user.ts @@ -1,6 +1,7 @@ import { GoogleUserInfo, User } from "@nirvana/core/models"; import express, { Application, Request, Response } from "express"; +import { OAuth2Client } from "google-auth-library"; import { ObjectID } from "bson"; import { ObjectId } from "mongodb"; import { UserService } from "../services/user.service"; @@ -8,31 +9,48 @@ import { UserStatus } from "../../core/models/user.model"; import { authCheck } from "../middleware/auth"; import { collections } from "../services/database.service"; +const client = new OAuth2Client( + "423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com" +); + export default function getUserRoutes() { const router = express.Router(); router.use(express.json()); // get user details based on id token - router.get("/", authCheck, getUserDetails); + // router.get("/", authCheck, getUserDetails); + + router.get("/login", login); + + router.get("/authCheck", authCheck); return router; } -/** - * Use token from middleware and get user properties - * create user if doesn't exist +/** Create user if doesn't exist + * Returns jwt token for client and user details */ -async function getUserDetails(req: Request, res: Response) { - const email: string = res.locals.email; - const userId: string = res.locals.userId; - +async function login(req: Request, res: Response) { // passed in accesstoken no matter what - const { access_token } = req.query; + const { access_token, id_token } = req.query; try { + const ticket = await client.verifyIdToken({ + idToken: (id_token as string) ?? "", + audience: + "423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com", // Specify the CLIENT_ID of the app that accesses the backend + }); + const googleUserId = ticket.getPayload()?.sub as string; + const email = ticket.getPayload()?.email as string; + + if (!googleUserId || !email) { + res.status(401).send("no google account found"); + return; + } + // return user details if it passed auth middleware - const user = await UserService.getUserByGoogleId(userId); + const user = await UserService.getUserByEmail(email); // if no user found, then go ahead and create user if (!user) { @@ -49,7 +67,7 @@ async function getUserDetails(req: Request, res: Response) { // create initial user model object const newUser = new User( - userId, + googleUserId, userInfo.email, userInfo.verifiedEmail, userInfo.name, @@ -67,6 +85,8 @@ async function getUserDetails(req: Request, res: Response) { newUser._id = insertResult?.insertedId; + // create jwt token with new user info + insertResult ? res.status(200).send(newUser) : res.status(500).send("Failed to create account, already exists"); @@ -74,7 +94,8 @@ async function getUserDetails(req: Request, res: Response) { return; } - // otherwise, just return the user details + // create jwt token with existing user info + res.status(200).send(user); } catch (error) { console.log(error); diff --git a/packages/core/models/user.model.ts b/packages/core/models/user.model.ts index c8f4631..6556b40 100644 --- a/packages/core/models/user.model.ts +++ b/packages/core/models/user.model.ts @@ -6,8 +6,8 @@ export class User { public email: string, public verifiedEmail: boolean, public name: string, - public given_name: string, - public family_name: string, + public givenName: string, + public familyName: string, public picture: string, public locale: string, diff --git a/packages/core/responses/login.response.ts b/packages/core/responses/login.response.ts new file mode 100644 index 0000000..7654118 --- /dev/null +++ b/packages/core/responses/login.response.ts @@ -0,0 +1,5 @@ +import { User } from "../models/user.model"; + +export default class LoginResponse { + constructor(public jwtToken: string, public userDetails: User) {} +} diff --git a/packages/desktop/src/components/ProtectedRoute/index.tsx b/packages/desktop/src/components/ProtectedRoute/index.tsx index 2ebaedb..c9997eb 100644 --- a/packages/desktop/src/components/ProtectedRoute/index.tsx +++ b/packages/desktop/src/components/ProtectedRoute/index.tsx @@ -1,8 +1,10 @@ import { $authTokens } from "../../controller/recoil"; import Login from "../../pages/Login"; +import NirvanaApi from "../../controller/nirvanaApi"; +import { STORE_ITEMS } from "../../electron/constants"; import SkeletonLoader from "../loading/skeleton"; import { useEffect } from "react"; -import { useGetUserDetails } from "../../controller/index"; +import { useLogin } from "../../controller/index"; import { useRecoilValue } from "recoil"; export default function ProtectedRoute({ @@ -10,26 +12,37 @@ export default function ProtectedRoute({ }: { children?: React.ReactNode; }) { - const { data, isLoading, isError, refetch } = useGetUserDetails(); - - const authTokens = useRecoilValue($authTokens); + const { mutateAsync } = useLogin(); useEffect(() => { - if (!authTokens) { - refetch(); - } - }, [authTokens]); + // on load of this, if we already have jwt tokens in store, + // then try using them with auth check, and if successful with simple dime call, then let them continue + window.electronAPI.store + .get(STORE_ITEMS.AUTH_SESSION_JWT) + .then((jwtToken: string) => { + if (jwtToken) { + // todo use this to do an auth check...set the necessary things to make react query run the check + // check if the jwt token is good - if (isLoading) - return ( -
- -
- ); + // then pass onto the api and such - if (isError) { - return refetch()} />; - } + NirvanaApi._jwtToken = jwtToken; + } + }); + }, []); + + return ; + + // if (isLoading || isIdle) + // return ( + //
+ // + //
+ // ); + + // if (isError) { + // return ; + // } // if we can successfully get user details, we are good to continue return <>{children}; diff --git a/packages/desktop/src/controller/index.tsx b/packages/desktop/src/controller/index.tsx index 48dc667..ddf4ad4 100644 --- a/packages/desktop/src/controller/index.tsx +++ b/packages/desktop/src/controller/index.tsx @@ -1,175 +1,40 @@ -import { $authTokens, $searchQuery } from "./recoil"; -import axios, { AxiosResponse } from "axios"; -import { queryClient, socket } from "../nirvanaApp"; -import { useEffect, useState } from "react"; +import NirvanaApi, { login } from "./nirvanaApi"; import { useMutation, useQuery } from "react-query"; -import GetContactsResponse from "../../../core/responses/getContacts.response"; -import GetConversationDetailsResponse from "@nirvana/core/responses/getConversationDetails.response"; -import { ObjectId } from "mongodb"; -import { RelationshipState } from "@nirvana/core/models/relationship.model"; -import SearchResponse from "@nirvana/core/responses/search.response"; -import SocketChannels from "@nirvana/core/sockets/channels"; -import UpdateRelationshipStateRequest from "../../../core/requests/updateRelationshipState.request"; -import { User } from "@nirvana/core/models"; -import { nirvanaApi } from "./nirvanaApi"; +import { $authTokens } from "./recoil"; import { useRecoilValue } from "recoil"; -// =========== API -export const localHost = "http://localhost:5000/api"; - -const getUserDetails = async (accessToken: string, idToken: string) => { - const response = await axios.get( - localHost + `/users?access_token=${accessToken}`, - { - headers: { Authorization: idToken }, - } - ); - - return response.data; -}; - -const search = async (idToken: string, searchQuery: string) => { - const response = await axios.get( - localHost + `/search?query=${searchQuery}`, - { - headers: { Authorization: idToken }, - } - ); - - return response.data; -}; - -const getConversationDetails = async ( - idToken: string, - otherUserGoogleId: string -) => { - const response = await axios.get( - localHost + `/conversations/${otherUserGoogleId}`, - { - headers: { Authorization: idToken }, - } - ); - - return response.data; -}; - -const sendContactRequest = async ( - idToken: string, - otherUserGoogleId: string -) => { - const response = await axios.post( - localHost + `/contacts/${otherUserGoogleId}`, - null, - { - headers: { Authorization: idToken }, - } - ); - - return response.data; -}; - -const updateContactRequestState = async ( - idToken: string, - reqObj: UpdateRelationshipStateRequest -) => { - const response = await axios.put(localHost + `/contacts`, reqObj, { - headers: { Authorization: idToken }, - }); - - return response.data; -}; - -const getContactsBasicDetails = async (idToken: string) => { - const response = await axios.get( - localHost + `/contacts`, - { - headers: { Authorization: idToken }, - } - ); - - return response.data; -}; - // ====== QUERIES -export enum Querytypes { - GET_USER_DETAILS = "GET_USER_DETAILS", - GET_SEARCH_RESULTS = "GET_SEARCH_RESULTS", - GET_CONVERSATION_DETAILS = "GET_CONVERSATION_DETAILS", - GET_CONTACTS_RELATIONSHIPS = "GET_CONTACTS_RELATIONSHIPS", + +export function useLogin() { + return useMutation("LOGIN", login, {}); } -export function useGetUserDetails() { - const authTokens = useRecoilValue($authTokens); +// export function useGetUserDetails() { +// const authTokens = useRecoilValue($authTokens); - return useQuery( - Querytypes.GET_USER_DETAILS, - () => getUserDetails(authTokens?.accessToken, authTokens?.idToken), - { - retry: false, - refetchOnWindowFocus: false, - onError: (err) => { - console.log(err); - }, - } - ); -} +// return useQuery( +// Querytypes.GET_USER_DETAILS, +// () => getUserDetails(authTokens?.accessToken, authTokens?.idToken), +// { +// retry: false, +// refetchOnWindowFocus: false, +// onError: (err) => { +// console.log(err); +// }, +// } +// ); +// } -export function useSearch() { - const authTokens = useRecoilValue($authTokens); - const searchQuery = useRecoilValue($searchQuery); +// export function useSearch() { +// const authTokens = useRecoilValue($authTokens); +// const searchQuery = useRecoilValue($searchQuery); - return useQuery( - Querytypes.GET_SEARCH_RESULTS, - () => search(authTokens.idToken, searchQuery), - { enabled: searchQuery ? true : false, refetchOnWindowFocus: false } - ); -} - -export function useConversationDetails(otherUserGoogleId: string) { - const authTokens = useRecoilValue($authTokens); - - return useQuery( - Querytypes.GET_CONVERSATION_DETAILS + "/" + otherUserGoogleId, - () => getConversationDetails(authTokens.idToken, otherUserGoogleId), - { enabled: otherUserGoogleId ? true : false } - ); -} - -export function useGetAllContactBasicDetails() { - const authTokens = useRecoilValue($authTokens); - - return useQuery( - Querytypes.GET_CONTACTS_RELATIONSHIPS, - () => getContactsBasicDetails(authTokens.idToken), - { - refetchOnWindowFocus: false, - } - ); -} +// return useQuery( +// Querytypes.GET_SEARCH_RESULTS, +// () => search(authTokens.idToken, searchQuery), +// { enabled: searchQuery ? true : false, refetchOnWindowFocus: false } +// ); +// } // =========== MUTATIONS - -export function useSendContactRequest() { - const authTokens = useRecoilValue($authTokens); - - return useMutation((otherGoogleUserId: string) => - sendContactRequest(authTokens.idToken, otherGoogleUserId) - ); -} - -export function useUpdateRelationshipState() { - const authTokens = useRecoilValue($authTokens); - - return useMutation( - (updateReqObj: UpdateRelationshipStateRequest) => - updateContactRequestState(authTokens.idToken, updateReqObj), - { - onSettled: (data, error) => { - return queryClient.invalidateQueries( - Querytypes.GET_CONVERSATION_DETAILS + "/" + "" - ); - }, - } - ); -} diff --git a/packages/desktop/src/controller/nirvanaApi.ts b/packages/desktop/src/controller/nirvanaApi.ts index b1bcdf8..5166008 100644 --- a/packages/desktop/src/controller/nirvanaApi.ts +++ b/packages/desktop/src/controller/nirvanaApi.ts @@ -1,20 +1,17 @@ -import axios, { AxiosRequestConfig, AxiosResponse } from "axios"; +import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios"; +import LoginResponse from "../../../core/responses/login.response"; import { User } from "@nirvana/core/models"; // export const localHost = process.env.REACT_APP_API_DOMAIN; export const localHost = "http://localhost:5000/api"; -class NirvanaApi { +export default class NirvanaApi { // auth token from google that our backend will use - private _authToken?: string; + static _jwtToken?: string; - setGoogleIdToken(_googleIdToken: string) { - this._authToken = _googleIdToken; - } - - async fetch(url: string, method: string, privateRoute = false) { + static async fetch(url: string, method: Method, privateRoute = false) { // use the auth token if it's a private route // error if no auth token and it's a private route // throw error and show message on anything that is an error from the backend @@ -22,16 +19,22 @@ class NirvanaApi { try { const fullUrl = localHost + url; - var res; - if (privateRoute && this._authToken) { + let res; + if (privateRoute && this._jwtToken) { res = await fetch(fullUrl, { method: method, - headers: { Authorization: this._authToken }, + headers: { Authorization: this._jwtToken }, }); } else { res = await fetch(fullUrl); } + if (!res.ok) { + if (res.status === 401) throw Error("You are not authorized here"); + + throw Error("Something went wrong"); + } + return await res.json(); } catch (error) { console.log(error); @@ -39,19 +42,19 @@ class NirvanaApi { throw Error(error); } } - - user = { - async getUserDetails(accessToken: string): Promise { - return await axios.get(localHost + `/users?access_token=${accessToken}`, { - headers: { Authorization: this._authToken }, - }); - }, - async createUser(accessToken: string) { - return await axios.post( - localHost + `/users/create?access_token=${accessToken}` - ); - }, - }; } -export const nirvanaApi = new NirvanaApi(); +export async function login(reqLoginTokens: { + accessToken: string; + idToken: string; +}): Promise { + return await NirvanaApi.fetch( + `/user/login?access_token=${reqLoginTokens.accessToken}&id_token=${reqLoginTokens.idToken}`, + "GET", + false + ); +} + +export async function authCheck(jwtToken: string) { + return await NirvanaApi.fetch(`/user/authCheck`, "GET", true); +} diff --git a/packages/desktop/src/controller/recoil.tsx b/packages/desktop/src/controller/recoil.tsx index 3bc0c47..762e5c7 100644 --- a/packages/desktop/src/controller/recoil.tsx +++ b/packages/desktop/src/controller/recoil.tsx @@ -14,12 +14,7 @@ export const $searchQuery = atom({ default: "", }); -export const $authFailureCount = atom({ - key: "AUTH_FAILURE_COUNT", - default: 0, -}); - -// google Id of the selected person/conversation +// conversation id export const $selectedConversation = atom({ key: "SELECTED_CONVERSATION", default: null, diff --git a/packages/desktop/src/controller/sockets.tsx b/packages/desktop/src/controller/sockets.tsx index 76bd09d..2c06231 100644 --- a/packages/desktop/src/controller/sockets.tsx +++ b/packages/desktop/src/controller/sockets.tsx @@ -3,26 +3,27 @@ import { useEffect, useState } from "react"; import SocketChannels from "@nirvana/core/sockets/channels"; import { UserStatus } from "../../../core/models/user.model"; import { socket } from "../nirvanaApp"; -import { useGetAllContactBasicDetails } from "./index"; + +// import { useGetAllContactBasicDetails } from "./index"; export default function useSocketData() { // relationshipId's of the conversations where there is someone speaking const [speakingRooms, setSpeakingRooms] = useState([]); - const { data: allConvosDetsResponse, isFetched } = - useGetAllContactBasicDetails(); + // const { data: allConvosDetsResponse, isFetched } = + // useGetAllContactBasicDetails(); - useEffect(() => { - if (allConvosDetsResponse) { - allConvosDetsResponse.contactsDetails.map((contactDet) => { - // join the right rooms based on the relevant contacts/conversations returned here - socket.emit( - SocketChannels.JOIN_ROOM, - contactDet.relationship._id.toString() - ); - }); - } - }, [isFetched]); + // useEffect(() => { + // if (allConvosDetsResponse) { + // allConvosDetsResponse.contactsDetails.map((contactDet) => { + // // join the right rooms based on the relevant contacts/conversations returned here + // socket.emit( + // SocketChannels.JOIN_ROOM, + // contactDet.relationship._id.toString() + // ); + // }); + // } + // }, [isFetched]); useEffect(() => { socket.on( diff --git a/packages/desktop/src/electron/constants.ts b/packages/desktop/src/electron/constants.ts index 265a8ec..ebaafa7 100644 --- a/packages/desktop/src/electron/constants.ts +++ b/packages/desktop/src/electron/constants.ts @@ -3,12 +3,13 @@ enum Channels { ACTIVATE_LOG_IN = "ACTIVATE_LOG_IN", - AUTH_TOKENS = "AUTH_TOKENS", + GOOGLE_AUTH_TOKENS = "GOOGLE_AUTH_TOKENS", RESIZE_WINDOW = "RESIZE_WINDOW", } export enum STORE_ITEMS { - AUTH_TOKENS = "AUTH_TOKENS", + GOOGLE_AUTH_TOKENS = "GOOGLE_AUTH_TOKENS", + AUTH_SESSION_JWT = "AUTH_SESSION_JWT", } export const Dimensions = { diff --git a/packages/desktop/src/electron/handleLogin.ts b/packages/desktop/src/electron/handleLogin.ts index be8301c..40e4106 100644 --- a/packages/desktop/src/electron/handleLogin.ts +++ b/packages/desktop/src/electron/handleLogin.ts @@ -9,36 +9,14 @@ const myApiOauth = new ElectronGoogleOAuth2( "423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com", "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", [""], - { successRedirectURL: "https://usenirvana.com" } + { successRedirectURL: "http://localhost:3000/auth/success" } ); -// FRESH LOGIN...either tokens of user expired or never had them -export async function handleLogin() { - // read saved refresh token if any - // todo: fix this...should be working - const authTokens = await store.get(STORE_ITEMS.AUTH_TOKENS); - - // todo: remove this when I have way of getting access token from a refresh token - // if (refreshToken) { - // console.log("have a refresh token from user auth previously", refreshToken); - // // myApiOauth.setTokens({ refresh_token: refreshToken }); - - // // send token to client - // browserWindow.webContents.send(Channels.AUTH_TOKENS, refreshToken); - // } else { - // const token = await myApiOauth.openAuthWindowAndGetTokens(); - - // // store the refresh token in cookies for app reopen - // store.set("tokens", token); - - // // todo: send the access token to the renderer - // // send token to client - // browserWindow.webContents.send(Channels.AUTH_TOKENS, token); - // } - +// FRESH GOOGLE LOGIN...either no json web tokens or trying to sign in with another account. +export async function handleGoogleLogin() { const tokens = await myApiOauth.openAuthWindowAndGetTokens(); - store.set(STORE_ITEMS.AUTH_TOKENS, tokens); + store.set(STORE_ITEMS.GOOGLE_AUTH_TOKENS, tokens); - browserWindow.webContents.send(Channels.AUTH_TOKENS, tokens); + browserWindow.webContents.send(Channels.GOOGLE_AUTH_TOKENS, tokens); } diff --git a/packages/desktop/src/index.ts b/packages/desktop/src/index.ts index 07a5175..85908a4 100644 --- a/packages/desktop/src/index.ts +++ b/packages/desktop/src/index.ts @@ -1,7 +1,7 @@ import { BrowserWindow, app, dialog, ipcMain } from "electron"; import Channels, { Dimensions } from "./electron/constants"; -import { handleLogin } from "./electron/handleLogin"; +import { handleGoogleLogin } from "./electron/handleLogin"; import path from "path"; import store from "./electron/store"; @@ -49,7 +49,7 @@ app // activate login ipcMain.on(Channels.ACTIVATE_LOG_IN, async (event, arg) => { console.log("initiating log in"); - await handleLogin(); + await handleGoogleLogin(); }); // access storage/cookies diff --git a/packages/desktop/src/pages/Home/conversations/index.tsx b/packages/desktop/src/pages/Home/conversations/index.tsx index 0279b3f..375de48 100644 --- a/packages/desktop/src/pages/Home/conversations/index.tsx +++ b/packages/desktop/src/pages/Home/conversations/index.tsx @@ -7,13 +7,12 @@ import { FaVolumeUp } from "react-icons/fa"; import SkeletonLoader from "../../../components/loading/skeleton"; import UserAvatarWithStatus from "../../../components/User/userAvatarWithStatus"; import UserStatusText from "../../../components/User/userStatusText"; -import { useGetAllContactBasicDetails } from "../../../controller"; import { useRecoilState } from "recoil"; import useSocketData from "../../../controller/sockets"; export default function Conversations() { - const { data: contactDetailsListResponse, isLoading } = - useGetAllContactBasicDetails(); + // const { data: contactDetailsListResponse, isLoading } = + // useGetAllContactBasicDetails(); const { speakingRooms } = useSocketData(); const [selectedConvo, setSelectedConvo] = useRecoilState( $selectedConversation @@ -45,7 +44,7 @@ export default function Conversations() { - {isLoading ? ( + {/* {isLoading ? ( ) : (
@@ -84,7 +83,7 @@ export default function Conversations() { } )}
- )} + )} */} ); } diff --git a/packages/desktop/src/pages/Home/header/index.tsx b/packages/desktop/src/pages/Home/header/index.tsx index fa50bf2..7b67644 100644 --- a/packages/desktop/src/pages/Home/header/index.tsx +++ b/packages/desktop/src/pages/Home/header/index.tsx @@ -1,100 +1,100 @@ -import { $authTokens, $searchQuery } from "../../../controller/recoil"; -import { Dropdown, Menu } from "antd"; -import Logo, { LogoType } from "../../../components/Logo"; -import { useRecoilState, useSetRecoilState } from "recoil"; +// import { $authTokens, $searchQuery } from "../../../controller/recoil"; +// import { Dropdown, Menu } from "antd"; +// import Logo, { LogoType } from "../../../components/Logo"; +// import { useRecoilState, useSetRecoilState } from "recoil"; -import { GlobalHotKeys } from "react-hotkeys"; -import { STORE_ITEMS } from "../../../electron/constants"; -import SocketChannels from "@nirvana/core/sockets/channels"; -import UserAvatarWithStatus from "../../../components/User/userAvatarWithStatus"; -import { UserStatus } from "@nirvana/core/models"; -import { socket } from "../../../nirvanaApp"; -import { useGetUserDetails } from "../../../controller/index"; -import { useRef } from "react"; +// import { GlobalHotKeys } from "react-hotkeys"; +// import { STORE_ITEMS } from "../../../electron/constants"; +// import SocketChannels from "@nirvana/core/sockets/channels"; +// import UserAvatarWithStatus from "../../../components/User/userAvatarWithStatus"; +// import { UserStatus } from "@nirvana/core/models"; +// import { socket } from "../../../nirvanaApp"; +// // import { useGetUserDetails } from "../../../controller/index"; +// import { useRef } from "react"; -export default function Header() { - const { data: user, isLoading } = useGetUserDetails(); - const [searchQuery, setSearchQuery] = useRecoilState($searchQuery); +// export default function Header() { +// // const { data: user, isLoading } = useGetUserDetails(); +// const [searchQuery, setSearchQuery] = useRecoilState($searchQuery); - const inputRef = useRef(null); +// const inputRef = useRef(null); - const setAuthTokens = useSetRecoilState($authTokens); +// const setAuthTokens = useSetRecoilState($authTokens); - if (isLoading) { - return getting data; - } +// if (isLoading) { +// return getting data; +// } - const logOut = () => { - window.electronAPI.store.set(STORE_ITEMS.AUTH_TOKENS, null); - setAuthTokens(null); - }; +// const logOut = () => { +// window.electronAPI.store.set(STORE_ITEMS.GOOGLE_AUTH_TOKENS, null); +// setAuthTokens(null); +// }; - const updateStatus = (newStatus: UserStatus) => { - // send update in socket - socket.emit( - SocketChannels.SEND_USER_STATUS_UPDATE, - user.googleId, - newStatus - ); - }; +// const updateStatus = (newStatus: UserStatus) => { +// // send update in socket +// socket.emit( +// SocketChannels.SEND_USER_STATUS_UPDATE, +// user.googleId, +// newStatus +// ); +// }; - const ProfileMenu = ( - - - - - - {user.status === UserStatus.ONLINE ? ( - - ) : ( - - )} - - - ); +// const ProfileMenu = ( +// +// +// +// +// +// {user.status === UserStatus.ONLINE ? ( +// +// ) : ( +// +// )} +// +// +// ); - // hot keys for selecting search - const handleSearch = () => { - if (inputRef?.current) { - inputRef?.current?.focus(); - setSearchQuery(""); - } - }; +// // hot keys for selecting search +// const handleSearch = () => { +// if (inputRef?.current) { +// inputRef?.current?.focus(); +// setSearchQuery(""); +// } +// }; - const keyMap = { START_SEARCH: "/" }; - const handlers = { START_SEARCH: handleSearch }; +// const keyMap = { START_SEARCH: "/" }; +// const handlers = { START_SEARCH: handleSearch }; - return ( - <> - +// return ( +// <> +// -
- - setSearchQuery(e.target.value)} - /> +//
+// +// setSearchQuery(e.target.value)} +// /> - +// - - - - - -
- - ); -} +// +// +// +// +// +//
+// +// ); +// } diff --git a/packages/desktop/src/pages/Home/index.tsx b/packages/desktop/src/pages/Home/index.tsx index 8b31f9c..c83b8cc 100644 --- a/packages/desktop/src/pages/Home/index.tsx +++ b/packages/desktop/src/pages/Home/index.tsx @@ -2,29 +2,28 @@ import Logo, { LogoType } from "../../components/Logo"; import { $searchQuery } from "../../controller/recoil"; import Conversations from "./conversations"; -import Header from "./header"; +// import Header from "./header"; import Search from "./search"; -import SelectedConversation from "./selectedConversation"; +// import SelectedConversation from "./selectedConversation"; import { useEffect } from "react"; -import { useGetUserDetails } from "../../controller/"; import { useRecoilValue } from "recoil"; export default function Home() { - const { data: user } = useGetUserDetails(); + // const { data: user } = useGetUserDetails(); const searchQuery = useRecoilValue($searchQuery); return (
{/* header */} -
+ {/*
*/} {/* main content */} {searchQuery ? : }
- + {/* */}
diff --git a/packages/desktop/src/pages/Home/search/index.tsx b/packages/desktop/src/pages/Home/search/index.tsx index dfe5de7..4743e59 100644 --- a/packages/desktop/src/pages/Home/search/index.tsx +++ b/packages/desktop/src/pages/Home/search/index.tsx @@ -2,7 +2,6 @@ import { $searchQuery, $selectedConversation, } from "../../../controller/recoil"; -import { useGetUserDetails, useSearch } from "../../../controller"; import { FaAngleRight } from "react-icons/fa"; import { Tooltip } from "@mui/material"; @@ -22,21 +21,22 @@ export default function Search() { $selectedConversation ); - const { data: userDetails } = useGetUserDetails(); + // const { data: userDetails } = useGetUserDetails(); - const { data, isLoading, isError, refetch } = useSearch(); + // const { data, isLoading, isError, refetch } = useSearch(); useEffect(() => { - refetch(); + // todo debounce after three seconds and show debounce loading while + // refetch(); }, [searchQuery]); - if (!data?.users) { - return ( - - no results. please try someone's email or name. - - ); - } + // if (!data?.users) { + // return ( + // + // no results. please try someone's email or name. + // + // ); + // } const goBack = () => { // implicity takes user back @@ -97,10 +97,10 @@ export default function Search() { Go back - {data?.users?.map((user) => { + {/* {data?.users?.map((user) => { if (user.googleId === userDetails.googleId) return <>; return renderUserRow(user); - })} + })} */} ); } diff --git a/packages/desktop/src/pages/Home/selectedConversation/index.tsx b/packages/desktop/src/pages/Home/selectedConversation/index.tsx index a39f0ce..c2f1afb 100644 --- a/packages/desktop/src/pages/Home/selectedConversation/index.tsx +++ b/packages/desktop/src/pages/Home/selectedConversation/index.tsx @@ -1,331 +1,325 @@ -import { FaMicrophone, FaPlay, FaWindowClose } from "react-icons/fa"; -import { GlobalHotKeys, KeyMap } from "react-hotkeys"; -import { - Querytypes, - useConversationDetails, - useGetUserDetails, - useSendContactRequest, - useUpdateRelationshipState, -} from "../../../controller"; -import { useEffect, useState } from "react"; +// import { FaMicrophone, FaPlay, FaWindowClose } from "react-icons/fa"; +// import { GlobalHotKeys, KeyMap } from "react-hotkeys"; +// import { useEffect, useState } from "react"; -import { $selectedConversation } from "../../../controller/recoil"; -import { Dimensions } from "../../../electron/constants"; -import { RelationshipState } from "@nirvana/core/models/relationship.model"; -import SocketChannels from "@nirvana/core/sockets/channels"; -import UpdateRelationshipStateRequest from "@nirvana/core/requests/updateRelationshipState.request"; -import UserStatusText from "../../../components/User/userStatusText"; -import moment from "moment"; -import { queryClient } from "../../../nirvanaApp"; -import { socket } from "../../../nirvanaApp"; -import toast from "react-hot-toast"; -import { useRecoilState } from "recoil"; +// import { $selectedConversation } from "../../../controller/recoil"; +// import { Dimensions } from "../../../electron/constants"; +// import { Querytypes } from "../../../controller"; +// import { RelationshipState } from "@nirvana/core/models/relationship.model"; +// import SocketChannels from "@nirvana/core/sockets/channels"; +// import UpdateRelationshipStateRequest from "@nirvana/core/requests/updateRelationshipState.request"; +// import UserStatusText from "../../../components/User/userStatusText"; +// import moment from "moment"; +// import { queryClient } from "../../../nirvanaApp"; +// import { socket } from "../../../nirvanaApp"; +// import toast from "react-hot-toast"; +// import { useRecoilState } from "recoil"; -let audioChunks: any = []; +// let audioChunks: any = []; -const constraints = { - audio: true, - // { - // // mandatory: { - // // chromeMediaSource: "desktop", - // // }, - // autoGainControl: true, - // echoCancellation: true, - // } as MediaTrackConstraints, -}; +// const constraints = { +// audio: true, +// // { +// // // mandatory: { +// // // chromeMediaSource: "desktop", +// // // }, +// // autoGainControl: true, +// // echoCancellation: true, +// // } as MediaTrackConstraints, +// }; -export default function SelectedConversation() { - const [selectedConvo, setSelectedConvo] = useRecoilState( - $selectedConversation - ); - const { data: userDetailsData } = useGetUserDetails(); - const { data: convoDetailsResponse, isLoading } = - useConversationDetails(selectedConvo); - const { mutate: sendContactRequest } = useSendContactRequest(); - const { mutate: updateRelationshipState } = useUpdateRelationshipState(); - const [isRecording, setIsRecording] = useState(false); +// export default function SelectedConversation() { +// const [selectedConvo, setSelectedConvo] = useRecoilState( +// $selectedConversation +// ); +// const { data: userDetailsData } = useGetUserDetails(); +// const { data: convoDetailsResponse, isLoading } = +// useConversationDetails(selectedConvo); +// const { mutate: sendContactRequest } = useSendContactRequest(); +// const { mutate: updateRelationshipState } = useUpdateRelationshipState(); +// const [isRecording, setIsRecording] = useState(false); - const [hasMicPermissions, sethasMicPermissions] = useState(false); - const [mediaRecorder, setMediaRecorder] = useState(); +// const [hasMicPermissions, sethasMicPermissions] = useState(false); +// const [mediaRecorder, setMediaRecorder] = useState(); - // audio handling - // setting up recording permissions - useEffect(() => { - try { - // checking for permissions for recording - // won't work in https!!! - navigator.mediaDevices - .getUserMedia(constraints) - .then((stream) => { - const mediaRecorder = new MediaRecorder(stream); - setMediaRecorder(mediaRecorder); +// // audio handling +// // setting up recording permissions +// useEffect(() => { +// try { +// // checking for permissions for recording +// // won't work in https!!! +// navigator.mediaDevices +// .getUserMedia(constraints) +// .then((stream) => { +// const mediaRecorder = new MediaRecorder(stream); +// setMediaRecorder(mediaRecorder); - console.log(mediaRecorder); +// console.log(mediaRecorder); - console.log("Permission Granted"); - sethasMicPermissions(true); - }) - .catch((e: any) => { - console.log("Permission Denied"); +// console.log("Permission Granted"); +// sethasMicPermissions(true); +// }) +// .catch((e: any) => { +// console.log("Permission Denied"); - toast.error( - "Please make sure that you have connected a microphone and given permissions." - ); +// toast.error( +// "Please make sure that you have connected a microphone and given permissions." +// ); - console.log(e); - sethasMicPermissions(false); - }); - } catch (error) { - console.log(error); - toast.error("something went wrong"); - } - }, []); +// console.log(e); +// sethasMicPermissions(false); +// }); +// } catch (error) { +// console.log(error); +// toast.error("something went wrong"); +// } +// }, []); - // todo: hacky way of re-linking event listeners once we have the relationship id - useEffect(() => { - if (mediaRecorder && convoDetailsResponse) { - mediaRecorder.addEventListener( - "dataavailable", - mediaRecorderDataAvailable - ); - mediaRecorder.addEventListener("stop", mediaRecorderStop); - } +// // todo: hacky way of re-linking event listeners once we have the relationship id +// useEffect(() => { +// if (mediaRecorder && convoDetailsResponse) { +// mediaRecorder.addEventListener( +// "dataavailable", +// mediaRecorderDataAvailable +// ); +// mediaRecorder.addEventListener("stop", mediaRecorderStop); +// } - return () => { - if (mediaRecorder) { - mediaRecorder.removeEventListener( - "dataavailable", - mediaRecorderDataAvailable - ); - mediaRecorder.removeEventListener("stop", mediaRecorderStop); - } - }; - }, [mediaRecorder, convoDetailsResponse]); +// return () => { +// if (mediaRecorder) { +// mediaRecorder.removeEventListener( +// "dataavailable", +// mediaRecorderDataAvailable +// ); +// mediaRecorder.removeEventListener("stop", mediaRecorderStop); +// } +// }; +// }, [mediaRecorder, convoDetailsResponse]); - const mediaRecorderDataAvailable = (event: any) => { - audioChunks.push(event.data); - }; +// const mediaRecorderDataAvailable = (event: any) => { +// audioChunks.push(event.data); +// }; - const mediaRecorderStop = () => { - socket.emit( - SocketChannels.SEND_AUDIO_CLIP, - convoDetailsResponse.ourRelationship._id.toString(), - audioChunks - ); +// const mediaRecorderStop = () => { +// socket.emit( +// SocketChannels.SEND_AUDIO_CLIP, +// convoDetailsResponse.ourRelationship._id.toString(), +// audioChunks +// ); - // testing playing before sending off - // const audioBlob = new Blob(audioChunks); - // const audioUrl = URL.createObjectURL(audioBlob); - // const audio = new Audio(audioUrl); - // audio.play(); +// // testing playing before sending off +// // const audioBlob = new Blob(audioChunks); +// // const audioUrl = URL.createObjectURL(audioBlob); +// // const audio = new Audio(audioUrl); +// // audio.play(); - audioChunks = []; - }; +// audioChunks = []; +// }; - useEffect(() => { - // if selected, then change the bounds of this window as well - if (selectedConvo) { - window.electronAPI.window.resizeWindow(Dimensions.selectedConvo); - } else { - // change bounds back - window.electronAPI.window.resizeWindow(Dimensions.default); - } - }, [selectedConvo]); +// useEffect(() => { +// // if selected, then change the bounds of this window as well +// if (selectedConvo) { +// window.electronAPI.window.resizeWindow(Dimensions.selectedConvo); +// } else { +// // change bounds back +// window.electronAPI.window.resizeWindow(Dimensions.default); +// } +// }, [selectedConvo]); - // if no convo selected, don't show this - if (!selectedConvo) { - return <>; - } +// // if no convo selected, don't show this +// if (!selectedConvo) { +// return <>; +// } - // todo: add cancel request option +// // todo: add cancel request option - const sendRequest = () => { - const otherUserGoogleId = convoDetailsResponse.contactUser.googleId; +// const sendRequest = () => { +// const otherUserGoogleId = convoDetailsResponse.contactUser.googleId; - // todo mutation to create a user - sendContactRequest(otherUserGoogleId, { - onSettled: (data, error) => { - return queryClient.invalidateQueries( - Querytypes.GET_CONVERSATION_DETAILS + "/" + otherUserGoogleId - ); - }, - }); - }; +// // todo mutation to create a user +// sendContactRequest(otherUserGoogleId, { +// onSettled: (data, error) => { +// return queryClient.invalidateQueries( +// Querytypes.GET_CONVERSATION_DETAILS + "/" + otherUserGoogleId +// ); +// }, +// }); +// }; - const acceptRequest = () => { - const otherUserGoogleId = convoDetailsResponse.contactUser.googleId; +// const acceptRequest = () => { +// const otherUserGoogleId = convoDetailsResponse.contactUser.googleId; - updateRelationshipState( - new UpdateRelationshipStateRequest( - convoDetailsResponse.ourRelationship._id, - RelationshipState.ACTIVE - ), - { - onSettled: (data, error) => { - return queryClient.invalidateQueries( - Querytypes.GET_CONVERSATION_DETAILS + "/" + otherUserGoogleId - ); - }, - } - ); - }; +// updateRelationshipState( +// new UpdateRelationshipStateRequest( +// convoDetailsResponse.ourRelationship._id, +// RelationshipState.ACTIVE +// ), +// { +// onSettled: (data, error) => { +// return queryClient.invalidateQueries( +// Querytypes.GET_CONVERSATION_DETAILS + "/" + otherUserGoogleId +// ); +// }, +// } +// ); +// }; - if (isLoading) return Please wait; +// if (isLoading) return Please wait; - const renderMainContent = () => { - // if there's no relationship, then don't show messages, show "send request" button - if (!convoDetailsResponse?.ourRelationship) { - return ; - } +// const renderMainContent = () => { +// // if there's no relationship, then don't show messages, show "send request" button +// if (!convoDetailsResponse?.ourRelationship) { +// return ; +// } - // if the relationship is pending and I am the receiver, then I should see an accept or deny button - if ( - convoDetailsResponse.ourRelationship.state === - RelationshipState.PENDING && - userDetailsData.googleId === - convoDetailsResponse.ourRelationship.receiverUserId - ) { - return ( - - please accept this request by clicking here:{" "} - - - ); - } +// // if the relationship is pending and I am the receiver, then I should see an accept or deny button +// if ( +// convoDetailsResponse.ourRelationship.state === +// RelationshipState.PENDING && +// userDetailsData.googleId === +// convoDetailsResponse.ourRelationship.receiverUserId +// ) { +// return ( +// +// please accept this request by clicking here:{" "} +// +// +// ); +// } - // when i sent a request to this person, just tell me that I have to wait - if ( - convoDetailsResponse.ourRelationship.state === - RelationshipState.PENDING && - userDetailsData.googleId === - convoDetailsResponse.ourRelationship.senderUserId - ) { - return Waiting on request to be accepted; - } +// // when i sent a request to this person, just tell me that I have to wait +// if ( +// convoDetailsResponse.ourRelationship.state === +// RelationshipState.PENDING && +// userDetailsData.googleId === +// convoDetailsResponse.ourRelationship.senderUserId +// ) { +// return Waiting on request to be accepted; +// } - if ( - convoDetailsResponse.ourRelationship.state === RelationshipState.ACTIVE - ) { - return this is all of the content; - } +// if ( +// convoDetailsResponse.ourRelationship.state === RelationshipState.ACTIVE +// ) { +// return this is all of the content; +// } - if ( - convoDetailsResponse.ourRelationship.state === RelationshipState.DENIED - ) { - return this request was denied; - } - }; +// if ( +// convoDetailsResponse.ourRelationship.state === RelationshipState.DENIED +// ) { +// return this request was denied; +// } +// }; - const startRecording = async () => { - socketStartedSpeaking(); - setIsRecording(true); +// const startRecording = async () => { +// socketStartedSpeaking(); +// setIsRecording(true); - mediaRecorder.start(); - }; +// mediaRecorder.start(); +// }; - const stopRecording = () => { - socketStopSpeaking(); - setIsRecording(false); +// const stopRecording = () => { +// socketStopSpeaking(); +// setIsRecording(false); - mediaRecorder.stop(); - }; +// mediaRecorder.stop(); +// }; - // emit to room/conversation that someone started speaking - const socketStartedSpeaking = () => { - // send the room name and the update type +// // emit to room/conversation that someone started speaking +// const socketStartedSpeaking = () => { +// // send the room name and the update type - // only send if we are in a relationship - if (convoDetailsResponse.ourRelationship._id.toString()) - socket.emit( - SocketChannels.SEND_STARTED_SPEAKING, - convoDetailsResponse.ourRelationship._id.toString() - ); - }; +// // only send if we are in a relationship +// if (convoDetailsResponse.ourRelationship._id.toString()) +// socket.emit( +// SocketChannels.SEND_STARTED_SPEAKING, +// convoDetailsResponse.ourRelationship._id.toString() +// ); +// }; - const socketStopSpeaking = () => { - // send the room name and the update type +// const socketStopSpeaking = () => { +// // send the room name and the update type - // only send if we are in a relationship - if (convoDetailsResponse.ourRelationship._id.toString()) - socket.emit( - SocketChannels.SEND_STOPPED_SPEAKING, - convoDetailsResponse.ourRelationship._id.toString() - ); - }; +// // only send if we are in a relationship +// if (convoDetailsResponse.ourRelationship._id.toString()) +// socket.emit( +// SocketChannels.SEND_STOPPED_SPEAKING, +// convoDetailsResponse.ourRelationship._id.toString() +// ); +// }; - // hot keys for closing this window - const handleClose = () => { - setSelectedConvo(null); - }; - const keyMap: KeyMap = { - CLOSE_SELECTED_CONVO: "esc", - START_RECORDING: { - name: "START RECORDING", - sequence: "`", - action: "keydown", - }, - STOP_RECORDING: { - name: "STOP RECORDING", - sequence: "`", - action: "keyup", - }, - }; +// // hot keys for closing this window +// const handleClose = () => { +// setSelectedConvo(null); +// }; +// const keyMap: KeyMap = { +// CLOSE_SELECTED_CONVO: "esc", +// START_RECORDING: { +// name: "START RECORDING", +// sequence: "`", +// action: "keydown", +// }, +// STOP_RECORDING: { +// name: "STOP RECORDING", +// sequence: "`", +// action: "keyup", +// }, +// }; - const handlers = { - CLOSE_SELECTED_CONVO: handleClose, - START_RECORDING: startRecording, - STOP_RECORDING: stopRecording, - }; +// const handlers = { +// CLOSE_SELECTED_CONVO: handleClose, +// START_RECORDING: startRecording, +// STOP_RECORDING: stopRecording, +// }; - return ( - <> - +// return ( +// <> +// -
- {/* close marker */} - +//
+// {/* close marker */} +// - {/* top header/profile information */} - - - - - - {convoDetailsResponse.contactUser.name} - - - +// {/* top header/profile information */} +// +// +// +// +// +// {convoDetailsResponse.contactUser.name} +// +// +// - {`joined ${moment( - convoDetailsResponse.contactUser.createdDate - ).fromNow()}`} - - +// {`joined ${moment( +// convoDetailsResponse.contactUser.createdDate +// ).fromNow()}`} +// +// - {renderMainContent()} +// {renderMainContent()} - - - {isRecording ? ( - - ) : ( - - )} - +// +// +// {isRecording ? ( +// +// ) : ( +// +// )} +// - - - - -
- - ); -} +// +// +// +// +//
+// +// ); +// }