diff --git a/client/public/index.html b/client/public/index.html index 7a5e3fc..015cd2f 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -23,7 +23,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - React App + Chat O Cord diff --git a/client/src/components/conversation/chat/index.tsx b/client/src/components/conversation/chat/index.tsx index ef53bcd..bf63aa8 100644 --- a/client/src/components/conversation/chat/index.tsx +++ b/client/src/components/conversation/chat/index.tsx @@ -21,26 +21,31 @@ import { ActiveChatContext } from "../../../utils/context/activeChatContext"; import AuthContext from "../../../utils/context/authContext"; import { Message } from "../../../types/conversation"; import { - addMessages, getMessagesAsync, } from "../../../utils/store/slices/messages.slice"; import { AppDispatch, RootState } from "../../../utils/store"; import { useDispatch, useSelector } from "react-redux"; -import { formatDistance, formatRelative } from "date-fns"; +import { formatDistance } from "date-fns"; import { createMessage, createMessageWithAsset } from "../../../lib/api"; import { updateLastMessage } from "../../../utils/store/slices/conversation.slice"; import classNames from "classnames"; import { useBufferToImageSrc } from "../../../utils/hooks/useBufferToImageSrc"; import { toast } from "sonner"; import { useSocket } from "../../../utils/hooks/useSocket"; -import { setLocalMsgStateHelper, showTimeStampAndAvatar } from "../../../lib/conversationsUtils"; +import { + setLocalMsgStateHelper, + showTimeStampAndAvatar, +} from "../../../lib/conversationsUtils"; export default function ChatSection() { const emojiPanelRef = useRef(null); const fileInputRef = useRef(null); const dispatch = useDispatch(); const [message, setMessage] = useState(""); - const [localMsgState, setLocalMsgState] = useState<{ convId: string; messages: Message[]; }[]>([]); + const [messages, setMessages] = useState([]); + const [localMsgState, setLocalMsgState] = useState< + { convId: string; messages: Message[] }[] + >([]); const [file, setFile] = useState(null); const [imagePreviewSrc, setImagePreviewSrc] = useState(""); const [activeAssetToView, setActiveAssetToView] = useState(""); @@ -67,7 +72,6 @@ export default function ChatSection() { ? activeChat?.creator : activeChat?.recipient; - /** *! ---- NOTE ---- *! MAKE THIS FUNCTION WITH REACT-QUERY @@ -93,7 +97,29 @@ export default function ChatSection() { formData.append("id", activeChat!.id); const { data: messageFromApi } = await createMessageWithAsset(formData); - setLocalMsgState((prev) => setLocalMsgStateHelper(messageFromApi, prev)); + setLocalMsgState((prev) => { + const foundIndex = prev.findIndex( + (state) => state.convId === messageFromApi.conversationId + ); + if (foundIndex !== -1) { + const updatedState = [...prev]; + updatedState[foundIndex] = { + convId: updatedState[foundIndex].convId, + messages: [messageFromApi, ...updatedState[foundIndex].messages], + }; + console.log("added the asset"); + return updatedState; + } else { + console.log("added the asset"); + return [ + ...prev, + { + convId: messageFromApi.conversationId, + messages: [messageFromApi], + }, + ]; + } + }); setFile(null); setImagePreviewSrc(""); @@ -116,7 +142,6 @@ export default function ChatSection() { id: activeChat!.id, }); - //* Update local message state for text messages setLocalMsgState((prev) => setLocalMsgStateHelper(messageFromApi, prev)); @@ -137,7 +162,7 @@ export default function ChatSection() { }); return () => { - window.removeEventListener("keydown", () => { }); + window.removeEventListener("keydown", () => {}); }; }, []); @@ -146,7 +171,9 @@ export default function ChatSection() { dispatch(getMessagesAsync({ id: activeChat.id, limit: 100, page: 1 })) .unwrap() .then((data) => { - setLocalMsgState([{ convId: data.data.id, messages: data.data.messages }]) + setLocalMsgState([ + { convId: data.data.id, messages: data.data.messages }, + ]); }); } }, [activeChat, dispatch]); @@ -154,12 +181,7 @@ export default function ChatSection() { useEffect(() => { socket?.on( "message:received", - (data: { - convId: string; - message: Message; - authorId: string; - attachmentSrc: string; - }) => { + (data: { convId: string; message: Message; authorId: string }) => { if (data.authorId === user?.id) { dispatch( updateLastMessage({ @@ -181,9 +203,19 @@ export default function ChatSection() { convId: string; secureUrl: string; message: Message; - attachmentSrc: string; }) => { - // TODO: IMPLEMENT + if (data.convId === activeChat?.id) { + dispatch( + updateLastMessage({ + id: data.convId, + lastMessageContent: data.message.content, + }) + ); + return; + } + + //* Update localMsgState + setLocalMsgState((prev) => setLocalMsgStateHelper(data.message, prev)); } ); @@ -196,10 +228,10 @@ export default function ChatSection() { }); return () => { - socket?.off("attachment:received", () => { }); - socket?.off("message:received", () => { }); - socket?.off("typing:started", () => { }); - socket?.off("typing:stopped", () => { }); + socket?.off("attachment:received", () => {}); + socket?.off("message:received", () => {}); + socket?.off("typing:started", () => {}); + socket?.off("typing:stopped", () => {}); }; }, [socket]); @@ -226,7 +258,7 @@ export default function ChatSection() { attachment ) : ( - localMsgState.map(state => { + localMsgState.map((state) => { if (state.convId === activeChat!.id) { return state.messages.map((msg, i, msgs) => { return ( {msg.author.profilePic ? ( attachment { setActiveAssetToView(msg.attachmentSrc!); @@ -341,7 +376,11 @@ export default function ChatSection() { )}

diff --git a/client/src/components/conversation/index.components.tsx b/client/src/components/conversation/index.components.tsx index 8109185..b3f8350 100644 --- a/client/src/components/conversation/index.components.tsx +++ b/client/src/components/conversation/index.components.tsx @@ -94,6 +94,7 @@ interface MessageProps extends AllHTMLAttributes, VariantProps { children: React.ReactNode[]; + ref: React.RefObject | null; } export const TextField = ({ variant, size, ...props }: TextFieldProps) => { @@ -108,9 +109,9 @@ export const Button = ({ variant, children, ...props }: ButtonProps) => { ); }; -export const Message = ({ variant, children, ...props }: MessageProps) => { +export const Message = ({ variant, children, ref, ...props }: MessageProps) => { return ( -

+
{children.map((child, index) => ( {child} ))} diff --git a/server/src/message/message.service.ts b/server/src/message/message.service.ts index f764443..741e062 100644 --- a/server/src/message/message.service.ts +++ b/server/src/message/message.service.ts @@ -1,6 +1,6 @@ import { getConversationById } from "../conversations/conversation.service"; import { v2 as cloudinary } from "cloudinary"; -import { bufferToSrc, getDataUri } from "../lib/utils"; +import { getDataUri } from "../lib/utils"; import { CreateMessageDTO } from "./dto/message.dto"; export const getMessages = async (id: string, limit: number) => { @@ -109,7 +109,6 @@ export const createMessageWithAsset = async ( resource_type: "auto", use_asset_folder_as_public_id_prefix: true, }); - const attachmentSrc = bufferToSrc()(file.buffer, file.mimetype); const attachment = await __db?.attachment.create({ data: { @@ -123,9 +122,6 @@ export const createMessageWithAsset = async ( }, }, }, - include: { - message: true, - }, }); await __db?.message.update({ @@ -137,5 +133,5 @@ export const createMessageWithAsset = async ( }, }); - return { message, attachment, secureUrl: secure_url, attachmentSrc }; + return { message, attachment, secureUrl: secure_url }; }; diff --git a/server/src/server.ts b/server/src/server.ts index 87a7903..9ca6771 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -9,7 +9,7 @@ import { sessionMiddleware, wrapper, } from "./lib/session.server"; -import { Conversation, User, Message, Attachment } from "@prisma/client"; +import { User, Message } from "@prisma/client"; import { AuthGuard } from "./middleware/middleware.server"; import { authRouter } from "./auth/auth.router";