From 7fb2f1a28f248061dbc991f40c171c0bb1b03126 Mon Sep 17 00:00:00 2001 From: ritwik-69 <72665321+ritwik-69@users.noreply.github.com> Date: Mon, 24 Jun 2024 19:42:06 +0530 Subject: [PATCH] Game:Add support for replying to messages in Message box This commit lets you reply to others in chat during game. fixes #153 --- backend/src/types.ts | 16 ++- frontend/src/library/chatbox/Chatbox.tsx | 27 +++++- frontend/src/library/chatbox/Message.tsx | 33 +++++++ frontend/src/library/chatbox/MessageInput.tsx | 97 +++++++++++++------ 4 files changed, 140 insertions(+), 33 deletions(-) diff --git a/backend/src/types.ts b/backend/src/types.ts index 79bc17a..e0f1d2a 100644 --- a/backend/src/types.ts +++ b/backend/src/types.ts @@ -130,6 +130,7 @@ export enum ChatEventTypes { REACT_TO_MESSAGE = 'REACT_TO_MESSAGE', DELETE_MESSAGE = 'DELETE_MESSAGE', EDIT_MESSAGE = 'EDIT_MESSAGE', + REPLY_MESSAGE = 'REPLY_MESSAGE', } export type ChatEvent = @@ -156,6 +157,14 @@ export type ChatEvent = ref: string; newContent: string; }; + } + | { + type: ChatEventTypes.REPLY_MESSAGE; + data: { + ref: string; + name: string; + data: string; + }; }; export type AppEventType = GameEventTypes | ChatEventTypes; @@ -167,12 +176,17 @@ export type AppEvent = GameEvent | ChatEvent; export type ChatMessage = { content: string; id: string; - ref?: string | null; + ref?: replyMessage | null; atMentions?: string[]; reactions?: [string, string][]; playerName: string; }; +export type replyMessage = { + ref?: string; + data?: string; +}; + export type ClientId = string; //todo: Add more events diff --git a/frontend/src/library/chatbox/Chatbox.tsx b/frontend/src/library/chatbox/Chatbox.tsx index 0c06638..d99208a 100644 --- a/frontend/src/library/chatbox/Chatbox.tsx +++ b/frontend/src/library/chatbox/Chatbox.tsx @@ -1,7 +1,11 @@ import React, { useEffect, useState } from 'react'; import MessageList from './MessageList'; import MessageInput from './MessageInput'; -import { ChatEventTypes, ChatMessage } from '../../../../backend/src/types'; +import { + ChatEventTypes, + ChatMessage, + replyMessage, +} from '../../../../backend/src/types'; import { FaComments } from 'react-icons/fa'; import * as channel from '../../channel'; import { useToast } from '../toast/toast-context'; @@ -12,6 +16,7 @@ import { useToast } from '../toast/toast-context'; const Chatbox: React.FC = () => { const [messages, setMessages] = useState<{ [k: string]: ChatMessage }>({}); const [isVisible, setIsVisible] = useState(false); + const [replyMessage, setReplyMessage] = useState(null); const toast = useToast(); useEffect(() => { @@ -58,6 +63,24 @@ const Chatbox: React.FC = () => { }; }); break; + case ChatEventTypes.REPLY_MESSAGE: + if (event.data) { + const message = messages[event.data.ref]; + if (message) { + setReplyMessage({ + ref: message.playerName, + data: message.content, + }); + } else { + console.log( + 'Message not found for reply:', + event.data.ref + ); + } + } else { + setReplyMessage(null); + } + break; } }); }, [messages, isVisible, toast]); @@ -81,7 +104,7 @@ const Chatbox: React.FC = () => {
- +
diff --git a/frontend/src/library/chatbox/Message.tsx b/frontend/src/library/chatbox/Message.tsx index 705eb1d..ba6828c 100644 --- a/frontend/src/library/chatbox/Message.tsx +++ b/frontend/src/library/chatbox/Message.tsx @@ -21,12 +21,39 @@ const Message: React.FC = ({ message }) => { }); setShowEmojiPicker(false); }; + const handleReply = () => { + triggerEvent({ + type: ChatEventTypes.REPLY_MESSAGE, + data: { + ref: message.id, + name: message.playerName, + data: message.content, + }, + }); + }; return (
{message.playerName}
+ + {message.ref && message.ref.data && ( +
+

+ {message.ref.ref} +

+ +

+ {message.ref && + message.ref.data && + message.ref.data.length > 35 + ? message.ref.data.slice(0, 35) + '...' + : message.ref.data} +

+
+ )} +
{message.content}
@@ -46,6 +73,12 @@ const Message: React.FC = ({ message }) => {
)} +
); diff --git a/frontend/src/library/chatbox/MessageInput.tsx b/frontend/src/library/chatbox/MessageInput.tsx index 73dfcdb..5489185 100644 --- a/frontend/src/library/chatbox/MessageInput.tsx +++ b/frontend/src/library/chatbox/MessageInput.tsx @@ -1,16 +1,21 @@ import React, { useState } from 'react'; import EmojiPicker, { EmojiClickData } from 'emoji-picker-react'; import Button from '../button'; -import { ChatEventTypes } from '../../../../backend/src/types'; +import { ChatEventTypes, replyMessage } from '../../../../backend/src/types'; import { triggerEvent } from '../../channel'; import { useAuth } from '../../contexts/AuthContext'; -const MessageInput: React.FC = () => { +interface MessageInputProps { + replyMessage?: replyMessage | null; // Optional prop +} + +const MessageInput: React.FC = ({ replyMessage = null }) => { const [content, setContent] = useState(''); const [showEmojiPicker, setShowEmojiPicker] = useState(false); const auth = useAuth(); const handleSend = async () => { + handleClose(); if (content.trim() !== '') { triggerEvent({ type: ChatEventTypes.SEND_MESSAGE, @@ -18,6 +23,7 @@ const MessageInput: React.FC = () => { id: Date.now().toString(), content: content.trim(), playerName: auth.getUser()?.name || 'Unknown user', + ref: replyMessage, }, }); setContent(''); @@ -34,38 +40,69 @@ const MessageInput: React.FC = () => { handleSend(); } }; + const handleClose = () => { + triggerEvent({ + type: ChatEventTypes.REPLY_MESSAGE, + data: null, + }); + }; return ( -
- - {showEmojiPicker && ( -
- +
+ {replyMessage && ( +
+
+

+ Replying to: {replyMessage.ref} +

+ +

+ {replyMessage && + replyMessage.data && + replyMessage.data.length > 35 + ? replyMessage.data.slice(0, 35) + '...' + : replyMessage.data} +

+ +
)} - setContent(e.target.value)} - onKeyDown={handleKeyDown} - className="flex-0.5 px-1 py-1 border-2 border-gray-500 rounded-xl font-kavoon text-sm" - placeholder="Type a message..." - /> - +
+ + {showEmojiPicker && ( +
+ +
+ )} + setContent(e.target.value)} + onKeyDown={handleKeyDown} + className="flex-1 px-1 py-1 border-2 border-gray-500 rounded-xl font-kavoon text-sm" + placeholder="Type a message..." + /> + +
); };