quick dial and creating conversations

This commit is contained in:
talksik
2022-06-11 12:25:41 -05:00
parent 4527d110d7
commit 298a989cd9
6 changed files with 111 additions and 25 deletions
+2 -2
View File
@@ -75,8 +75,8 @@ const getOneOnOneConversationIfExists = async (req: Request, res: Response, next
resultConversation?._id ?? undefined,
undefined,
resultConversation
? 'no such conversation exists!'
: 'there is a conversation...quick dial them now!',
? 'there is a conversation...quick dial them now!'
: 'no such conversation exists!',
),
);
} catch (error) {
+4
View File
@@ -85,3 +85,7 @@ export async function createConversation(
export async function getConversations(): Promise<NirvanaResponse<Conversation[]>> {
return await NirvanaApi.fetch(`/conversations`, 'GET', true);
}
export async function checkIfOnOnOneExists(otherUserId: string): Promise<NirvanaResponse<string>> {
return await NirvanaApi.fetch(`/conversations/check/${otherUserId}`, 'GET', true);
}
@@ -1,14 +1,22 @@
import React, { useEffect } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { checkIfOnOnOneExists, createConversation, getConversations } from '../api/NirvanaApi';
import Conversation from '@nirvana/core/models/conversation.model';
import { ConversationMap } from '../util/types';
import CreateConversationRequest from '@nirvana/core/requests/CreateConversationRequest.request';
import { Typography } from '@mui/material';
import { getConversations } from '../api/NirvanaApi';
import User from '@nirvana/core/models/user.model';
import { toast } from 'react-toastify';
import { useAsyncFn } from 'react-use';
import { useImmer } from 'use-immer';
interface IConversationContext {
conversations: ConversationMap;
selectedConversation?: Conversation;
// handleSetConversation?: (conversationId: string) => void;
handleStartConversation?: (otherUsers: User[]) => void;
}
const ConversationContext = React.createContext<IConversationContext>({
@@ -22,6 +30,8 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
// the map that we manage throughout the app
const [conversationMap, setConversationMap] = useImmer<ConversationMap>({});
const [selectedConversation, setSelectedConversation] = useState<Conversation>(undefined);
useEffect(() => {
doFetch();
}, [doFetch]);
@@ -42,6 +52,76 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
}
}, [fetchState.value, setConversationMap]);
/**
* temporaryOverrideSort: tell me if you want to temporarily prioritize this conversation above all others
*/
const selectConversation = useCallback(
(conversationId: string, temporaryOverrideSort = false) => {
/**
* see if there is such a conversation in our map
* if not, then go and fetch it from backend
* set the temporary sort accordingly
*/
const allConversationIds = Object.keys(conversationMap);
if (allConversationIds.includes(conversationId)) {
toast.success('we have that conversation!!!');
setSelectedConversation(conversationMap[conversationId]);
}
},
[conversationMap, setSelectedConversation],
);
const handleStartConversation = useCallback(
async (otherUsers: User[]) => {
try {
/** group conversation
* 1. create it
* 2. select the conversation based on the id
*
* one on one:
* 1. hit backend to see if we already have a conversation with them
* 2. if so, then go and select it with priority sort flag
* 3. if not, then go ahead and create
* 4. use the conversation id to select it
*/
if (!otherUsers || otherUsers.length === 0) {
toast.error('Must provider users');
return;
}
// todo: check to make sure that the other user is not the user himself, although backend should error out
if (otherUsers.length === 1) {
const conversationDmCheck = await checkIfOnOnOneExists(otherUsers[0]._id.toString());
// if we found a conversation
if (conversationDmCheck.data) {
toast.success('already have this user...quick dialing');
selectConversation(conversationDmCheck.data, true);
return;
}
}
const createdConversationResult = await createConversation(
new CreateConversationRequest(otherUsers),
);
selectConversation(createdConversationResult.data.conversationId.toString());
toast.success('started conversation');
} catch (error) {
console.error(error);
toast.error(error.message);
}
},
[conversationMap, selectConversation],
);
// todo: open up a handler for children
// to refetch or search for a particular conversation and add it to the list of conversations
@@ -56,7 +136,9 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
}
return (
<ConversationContext.Provider value={{ conversations: conversationMap }}>
<ConversationContext.Provider
value={{ conversations: conversationMap, handleStartConversation, selectedConversation }}
>
{children}
</ConversationContext.Provider>
);
@@ -1,11 +1,13 @@
// make do router given absense of react router in desktop apps
import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import useConversations from './ConversationProvider';
type TPage =
| 'START_NEW_CONVERSATION'
| 'FULL_PAGE_OMNI_SEARCH'
| 'CONVERSATION_DETAILS'
| 'SELECTED_CONVERSATION'
| 'PROFILE'
| 'WELCOME';
@@ -21,6 +23,14 @@ const RouterContext = React.createContext<IRouterContext>({
export function RouterProvider({ children }: { children: React.ReactNode }) {
const [page, setPage] = useState<TPage>('WELCOME');
const { selectedConversation } = useConversations();
useEffect(() => {
if (selectedConversation) {
setPage('SELECTED_CONVERSATION');
}
}, [setPage, selectedConversation]);
const handleSetPage = useCallback((newPage: TPage) => () => setPage(newPage), [setPage]);
return (
@@ -29,6 +29,7 @@ import { blueGrey } from '@mui/material/colors';
import { createConversation } from '../api/NirvanaApi';
import toast from 'react-hot-toast';
import useAuth from '../providers/AuthProvider';
import useConversations from '../providers/ConversationProvider';
import useRouter from '../providers/RouterProvider';
import useSearch from '../providers/SearchProvider';
@@ -81,6 +82,8 @@ export default function NewConversationDialog() {
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
const { handleStartConversation } = useConversations();
const handleSubmit = useCallback(async () => {
if (selectedUsers.length === 0) {
toast.error('Must select a person!');
@@ -94,24 +97,11 @@ export default function NewConversationDialog() {
setIsSubmitting(true);
try {
// if it's just one other person, then call quick dial master function which would do all of the checking
handleStartConversation(selectedUsers);
// if more than one person, then just create conversation
const createResult = await createConversation(
new CreateConversationRequest(selectedUsers, conversationName),
);
// clear form for next time
setSelectedUsers([]);
setConversationName('');
// todo: select conversation Id that was created
} catch (error) {
console.error(error);
toast.error(error.message);
}
// clear form for next time
setSelectedUsers([]);
setConversationName('');
setIsSubmitting(false);
}, [selectedUsers, setConversationName, conversationName, setSelectedUsers, setIsSubmitting]);
+1 -1
View File
@@ -9,7 +9,7 @@ export type ConversationMap = {
// allows client side to have this pushed up in the list and can uncheck it once user is done with this
// if action is take, normal ordering should take place with database upserts
temporaryInboxTop?: boolean;
temporaryOverrideSort?: boolean;
};
};