quick dial and creating conversations
This commit is contained in:
@@ -75,8 +75,8 @@ const getOneOnOneConversationIfExists = async (req: Request, res: Response, next
|
|||||||
resultConversation?._id ?? undefined,
|
resultConversation?._id ?? undefined,
|
||||||
undefined,
|
undefined,
|
||||||
resultConversation
|
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) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -85,3 +85,7 @@ export async function createConversation(
|
|||||||
export async function getConversations(): Promise<NirvanaResponse<Conversation[]>> {
|
export async function getConversations(): Promise<NirvanaResponse<Conversation[]>> {
|
||||||
return await NirvanaApi.fetch(`/conversations`, 'GET', true);
|
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 Conversation from '@nirvana/core/models/conversation.model';
|
||||||
import { ConversationMap } from '../util/types';
|
import { ConversationMap } from '../util/types';
|
||||||
|
import CreateConversationRequest from '@nirvana/core/requests/CreateConversationRequest.request';
|
||||||
import { Typography } from '@mui/material';
|
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 { useAsyncFn } from 'react-use';
|
||||||
import { useImmer } from 'use-immer';
|
import { useImmer } from 'use-immer';
|
||||||
|
|
||||||
interface IConversationContext {
|
interface IConversationContext {
|
||||||
conversations: ConversationMap;
|
conversations: ConversationMap;
|
||||||
|
|
||||||
|
selectedConversation?: Conversation;
|
||||||
|
// handleSetConversation?: (conversationId: string) => void;
|
||||||
|
|
||||||
|
handleStartConversation?: (otherUsers: User[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConversationContext = React.createContext<IConversationContext>({
|
const ConversationContext = React.createContext<IConversationContext>({
|
||||||
@@ -22,6 +30,8 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
|
|||||||
// the map that we manage throughout the app
|
// the map that we manage throughout the app
|
||||||
const [conversationMap, setConversationMap] = useImmer<ConversationMap>({});
|
const [conversationMap, setConversationMap] = useImmer<ConversationMap>({});
|
||||||
|
|
||||||
|
const [selectedConversation, setSelectedConversation] = useState<Conversation>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
doFetch();
|
doFetch();
|
||||||
}, [doFetch]);
|
}, [doFetch]);
|
||||||
@@ -42,6 +52,76 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
|
|||||||
}
|
}
|
||||||
}, [fetchState.value, setConversationMap]);
|
}, [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
|
// todo: open up a handler for children
|
||||||
// to refetch or search for a particular conversation and add it to the list of conversations
|
// 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 (
|
return (
|
||||||
<ConversationContext.Provider value={{ conversations: conversationMap }}>
|
<ConversationContext.Provider
|
||||||
|
value={{ conversations: conversationMap, handleStartConversation, selectedConversation }}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</ConversationContext.Provider>
|
</ConversationContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
// make do router given absense of react router in desktop apps
|
// 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 =
|
type TPage =
|
||||||
| 'START_NEW_CONVERSATION'
|
| 'START_NEW_CONVERSATION'
|
||||||
| 'FULL_PAGE_OMNI_SEARCH'
|
| 'FULL_PAGE_OMNI_SEARCH'
|
||||||
| 'CONVERSATION_DETAILS'
|
| 'SELECTED_CONVERSATION'
|
||||||
| 'PROFILE'
|
| 'PROFILE'
|
||||||
| 'WELCOME';
|
| 'WELCOME';
|
||||||
|
|
||||||
@@ -21,6 +23,14 @@ const RouterContext = React.createContext<IRouterContext>({
|
|||||||
export function RouterProvider({ children }: { children: React.ReactNode }) {
|
export function RouterProvider({ children }: { children: React.ReactNode }) {
|
||||||
const [page, setPage] = useState<TPage>('WELCOME');
|
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]);
|
const handleSetPage = useCallback((newPage: TPage) => () => setPage(newPage), [setPage]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import { blueGrey } from '@mui/material/colors';
|
|||||||
import { createConversation } from '../api/NirvanaApi';
|
import { createConversation } from '../api/NirvanaApi';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import useAuth from '../providers/AuthProvider';
|
import useAuth from '../providers/AuthProvider';
|
||||||
|
import useConversations from '../providers/ConversationProvider';
|
||||||
import useRouter from '../providers/RouterProvider';
|
import useRouter from '../providers/RouterProvider';
|
||||||
import useSearch from '../providers/SearchProvider';
|
import useSearch from '../providers/SearchProvider';
|
||||||
|
|
||||||
@@ -81,6 +82,8 @@ export default function NewConversationDialog() {
|
|||||||
|
|
||||||
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const { handleStartConversation } = useConversations();
|
||||||
|
|
||||||
const handleSubmit = useCallback(async () => {
|
const handleSubmit = useCallback(async () => {
|
||||||
if (selectedUsers.length === 0) {
|
if (selectedUsers.length === 0) {
|
||||||
toast.error('Must select a person!');
|
toast.error('Must select a person!');
|
||||||
@@ -94,24 +97,11 @@ export default function NewConversationDialog() {
|
|||||||
|
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
|
|
||||||
try {
|
handleStartConversation(selectedUsers);
|
||||||
// if it's just one other person, then call quick dial master function which would do all of the checking
|
|
||||||
|
|
||||||
// if more than one person, then just create conversation
|
// clear form for next time
|
||||||
|
setSelectedUsers([]);
|
||||||
const createResult = await createConversation(
|
setConversationName('');
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}, [selectedUsers, setConversationName, conversationName, setSelectedUsers, setIsSubmitting]);
|
}, [selectedUsers, setConversationName, conversationName, setSelectedUsers, setIsSubmitting]);
|
||||||
|
|||||||
@@ -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
|
// 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
|
// if action is take, normal ordering should take place with database upserts
|
||||||
temporaryInboxTop?: boolean;
|
temporaryOverrideSort?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user