Skip to content
Snippets Groups Projects
Commit 57de5d9a authored by 석찬 윤's avatar 석찬 윤
Browse files

Merge branch 'develop' into 'main'

fix: 모바일 뷰 오류 해결

See merge request !58
parents e5fa519e a99513d7
No related branches found
No related tags found
1 merge request!58fix: 모바일 뷰 오류 해결
Pipeline #11060 passed
......@@ -56,7 +56,9 @@ export default function Card({
return (
<div className={cn(variantClass)} onClick={onDetail}>
<h3 className="mb-2 text-xl font-bold">{title}</h3>
<h3 className="mb-2 text-xl font-bold" onClick={onDetail}>
{title}
</h3>
<Label size="sm" theme="black">
장소: {location}
</Label>
......
import { useParams, useLocation } from 'react-router-dom';
import { useEffect, useState, useRef, useCallback, useMemo } from 'react';
import './ChattingDetail.css';
import styled, { keyframes } from 'styled-components';
import { FaSearch, FaArrowUp, FaArrowDown } from 'react-icons/fa';
import { useParams, useLocation } from "react-router-dom";
import { useEffect, useState, useRef, useCallback, useMemo } from "react";
import "./ChattingDetail.css";
import styled, { keyframes } from "styled-components";
import { FaSearch, FaArrowUp, FaArrowDown } from "react-icons/fa";
import Button from "../components/Button";
import ChattingNoticeDetailModal from '../components/ChattingNoticeDetailModal';
import ChattingNoticeListModal from '../components/ChattingNoticeListModal';
import ChattingNoticeDetailModal from "../components/ChattingNoticeDetailModal";
import ChattingNoticeListModal from "../components/ChattingNoticeListModal";
// 웹소켓 서버 연결 URL
const WS_URL = process.env.REACT_APP_WS_URL;
......@@ -69,26 +69,28 @@ const ChatRoomMessages = styled.div`
const MessageContainer = styled.div`
display: flex;
justify-content: ${(props) => (props.isMine ? 'flex-end' : 'flex-start')};
justify-content: ${(props) => (props.isMine ? "flex-end" : "flex-start")};
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
border: ${(props) => (props.highlighted ? '2px solid blue' : 'none')};
border: ${(props) => (props.highlighted ? "2px solid blue" : "none")};
transition: background-color 0.3s ease, border 0.3s ease;
animation: ${(props) => (props.highlighted ? shakeAnimation : 'none')} 0.5s ease;
animation: ${(props) => (props.highlighted ? shakeAnimation : "none")} 0.5s
ease;
`;
const MessageBubble = styled.div`
max-width: 60%;
padding: 10px;
border-radius: 10px;
background-color: ${(props) => (props.isMine ? '#dcf8c6' : '#f9f9f9')};
text-align: ${(props) => (props.isMine ? 'right' : 'left')};
border: ${(props) => (props.highlighted ? '2px solid blue' : 'none')};
background-color: ${(props) => (props.isMine ? "#dcf8c6" : "#f9f9f9")};
text-align: ${(props) => (props.isMine ? "right" : "left")};
border: ${(props) => (props.highlighted ? "2px solid blue" : "none")};
word-wrap: break-word;
transition: background-color 0.3s ease, border 0.3s ease;
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1);
animation: ${(props) => (props.highlighted ? shakeAnimation : 'none')} 0.5s ease;
animation: ${(props) => (props.highlighted ? shakeAnimation : "none")} 0.5s
ease;
`;
const CenteredMessage = styled.div`
......@@ -107,7 +109,7 @@ const CenteredMessage = styled.div`
const MessageTimestamp = styled.div`
font-size: 0.8em;
color: #888;
text-align: ${(props) => (props.isMine ? 'right' : 'left')};
text-align: ${(props) => (props.isMine ? "right" : "left")};
`;
const ChatRoomInput = styled.div`
......@@ -146,9 +148,11 @@ const FixedSearchBar = styled(SearchBar)`
`;
const NoticeContainer = styled.div`
background-color: ${({ isCollapsed }) => (isCollapsed ? "transparent" : "#f8f9fa")};
background-color: ${({ isCollapsed }) =>
isCollapsed ? "transparent" : "#f8f9fa"};
padding: ${({ isCollapsed }) => (isCollapsed ? "0" : "10px")};
border-bottom: ${({ isCollapsed }) => (isCollapsed ? "none" : "1px solid #ddd")};
border-bottom: ${({ isCollapsed }) =>
isCollapsed ? "none" : "1px solid #ddd"};
position: relative; /* 확성기 위치 조정을 위해 사용 */
`;
......@@ -198,8 +202,8 @@ function ChattingDetail() {
// const [notice, setNotice] = useState(null); // 공지 메시지
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [searchTerm, setSearchTerm] = useState('');
const [input, setInput] = useState("");
const [searchTerm, setSearchTerm] = useState("");
const [searchResults, setSearchResults] = useState([]);
const [currentSearchIndex, setCurrentSearchIndex] = useState(0);
const [isSearching, setIsSearching] = useState(false);
......@@ -272,12 +276,16 @@ function ChattingDetail() {
};
const handleDismissNotice = () => {
const dismissedNotices = JSON.parse(localStorage.getItem('dismissedNotices')) || [];
const dismissedNotices =
JSON.parse(localStorage.getItem("dismissedNotices")) || [];
// 현재 공지사항이 로컬 스토리지에 추가되도록 처리
if (notice && !dismissedNotices.includes(notice.message)) {
dismissedNotices.push(notice.message);
localStorage.setItem('dismissedNotices', JSON.stringify(dismissedNotices));
localStorage.setItem(
"dismissedNotices",
JSON.stringify(dismissedNotices)
);
}
setIsNoticeVisible(false); // 공지를 숨김
......@@ -285,21 +293,24 @@ function ChattingDetail() {
const fetchUnreadCounts = async () => {
try {
const response = await fetch(`${process.env.REACT_APP_BASE_URL}/api/chat/unread-count/${chatRoomId}`, {
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/chat/unread-count/${chatRoomId}`,
{
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
});
}
);
if (response.ok) {
const data = await response.json();
setChatUnread(data);
} else {
console.error('Failed to fetch unread counts');
console.error("Failed to fetch unread counts");
}
} catch (error) {
console.error('Error fetching unread counts:', error);
console.error("Error fetching unread counts:", error);
}
};
......@@ -317,10 +328,12 @@ function ChattingDetail() {
}
try {
const response = await fetch(`${process.env.REACT_APP_BASE_URL}/api/chat/update-status-and-logid`, {
method: 'POST',
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/chat/update-status-and-logid`,
{
method: "POST",
headers: {
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
body: JSON.stringify({
chatRoomId,
......@@ -328,15 +341,18 @@ function ChattingDetail() {
isOnline: status,
logId: logId, // 상태에 따라 logId도 함께 보냄
}),
});
}
);
if (!response.ok) {
throw new Error('Failed to update status and logId');
throw new Error("Failed to update status and logId");
}
console.log(`${nickname} : 상태업데이트 to ${status}, logId updated to ${logId} for `);
console.log(
`${nickname} : 상태업데이트 to ${status}, logId updated to ${logId} for `
);
} catch (err) {
console.error('Error updating status and logId:', err);
console.error("Error updating status and logId:", err);
}
};
......@@ -344,9 +360,8 @@ function ChattingDetail() {
e.preventDefault();
if (window.confirm("이 메시지를 공지로 설정하시겠습니까?")) {
try {
const noticeMessage = {
type: 'notice', // 메시지 유형: 공지사항 설정
type: "notice", // 메시지 유형: 공지사항 설정
chatRoomId: chatRoomId, // 현재 채팅방 ID
nickname: loggedInUser, // 공지 설정한 사용자 닉네임
text: messageData.message, // 공지 내용
......@@ -354,15 +369,14 @@ function ChattingDetail() {
// WebSocket을 통해 서버로 메시지 전송
ws.current.send(JSON.stringify(noticeMessage));
console.log('공지사항 설정 메시지 전송:', noticeMessage);
console.log("공지사항 설정 메시지 전송:", noticeMessage);
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/chat/${chatRoomId}/notices`,
{
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
body: JSON.stringify({
sender: messageData.sender,
......@@ -375,10 +389,10 @@ function ChattingDetail() {
const newNotice = await response.json();
setNotice(newNotice); // 공지를 로컬 상태로 업데이트
} else {
console.error('Failed to set notice');
console.error("Failed to set notice");
}
} catch (error) {
console.error('Error setting notice:', error);
console.error("Error setting notice:", error);
}
}
};
......@@ -402,11 +416,14 @@ function ChattingDetail() {
const fetchLatestNotice = async () => {
try {
const response = await fetch(`${process.env.REACT_APP_BASE_URL}/api/chat/${chatRoomId}/notices/latest`);
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/chat/${chatRoomId}/notices/latest`
);
if (response.ok) {
const latestNotice = await response.json();
const dismissedNotices = JSON.parse(localStorage.getItem('dismissedNotices')) || [];
const dismissedNotices =
JSON.parse(localStorage.getItem("dismissedNotices")) || [];
const isDismissed = dismissedNotices.includes(latestNotice.message);
// 새로운 공지라면 표시하고, 숨겨진 공지가 아니라면 표시
......@@ -417,18 +434,18 @@ function ChattingDetail() {
setNotice(null);
setIsNoticeVisible(false);
} else {
console.error('Failed to fetch latest notice');
console.error("Failed to fetch latest notice");
}
} catch (error) {
console.error('Error fetching latest notice:', error);
console.error("Error fetching latest notice:", error);
}
};
const scrollToHighlightedMessage = () => {
if (highlightedMessageRef.current) {
highlightedMessageRef.current.scrollIntoView({
behavior: 'smooth',
block: 'center'
behavior: "smooth",
block: "center",
});
}
};
......@@ -448,19 +465,21 @@ function ChattingDetail() {
reconnectAttempts = 0; // 재연결 성공 시 시도 횟수 초기화
const joinMessage = JSON.stringify({
type: 'join',
type: "join",
chatRoomId,
nickname,
});
ws.current.send(joinMessage);
console.log(`(클라이언트) WebSocket 연결 완료 - 채팅방: ${chatRoomId}, 닉네임: ${nickname}`);
console.log(
`(클라이언트) WebSocket 연결 완료 - 채팅방: ${chatRoomId}, 닉네임: ${nickname}`
);
};
ws.current.onmessage = (event) => {
const messageData = JSON.parse(event.data);
console.log("받은 메시지", messageData);
if (messageData.type === 'status') {
if (messageData.type === "status") {
const { nickname, isOnline } = messageData;
if (!isOnline) {
console.log(`${nickname}님이 오프라인 상태로 전환되었습니다.`);
......@@ -469,27 +488,30 @@ function ChattingDetail() {
return;
}
if (messageData.type === 'notice') {
if (messageData.type === "notice") {
// 공지사항 변경 이벤트 처리
console.log('새 공지사항 알림 수신:', messageData);
console.log("새 공지사항 알림 수신:", messageData);
setNotice({
sender: messageData.sender,
message: messageData.message,
});
setIsNoticeVisible(true); // 공지를 표시하도록 설정
fetchLatestNotice(); // 최신 공지사항 업데이트
} else if (messageData.type === 'previousMessages') {
} else if (messageData.type === "previousMessages") {
// setMessages((prevMessages) => [...prevMessages, ...messageData.messages]);
setMessages((prevMessages) => {
const messageIds = new Set(prevMessages.map((msg) => msg._id)); // 기존 메시지의 ID 저장
const newMessages = messageData.messages.filter((msg) => !messageIds.has(msg._id)); // 중복 제거
const newMessages = messageData.messages.filter(
(msg) => !messageIds.has(msg._id)
); // 중복 제거
return [...prevMessages, ...newMessages];
});
} else {
// setMessages((prevMessages) => [...prevMessages, messageData]);
setMessages((prevMessages) => {
const messageIds = new Set(prevMessages.map((msg) => msg._id)); // 기존 메시지의 ID 저장
if (!messageIds.has(messageData._id)) { // 새 메시지가 중복되지 않으면 추가
if (!messageIds.has(messageData._id)) {
// 새 메시지가 중복되지 않으면 추가
return [...prevMessages, messageData];
}
return prevMessages;
......@@ -500,8 +522,12 @@ function ChattingDetail() {
const lastMessage = messageData; // 새로 받은 메시지
lastReadLogIdRef.current = lastMessage._id;
console.log('Received message logId:', lastReadLogIdRef.current);
if (!chatUnreadSortArray.length || chatUnreadSortArray[chatUnreadSortArray.length - 1][1] <= messageData._id) {
console.log("Received message logId:", lastReadLogIdRef.current);
if (
!chatUnreadSortArray.length ||
chatUnreadSortArray[chatUnreadSortArray.length - 1][1] <=
messageData._id
) {
fetchUnreadCounts(chatRoomId);
}
}
......@@ -509,46 +535,57 @@ function ChattingDetail() {
};
ws.current.onclose = async (event) => {
console.warn('(클라이언트)WebSocket 연결이 종료되었습니다.', event);
console.warn("(클라이언트)WebSocket 연결이 종료되었습니다.", event);
// 탭이 활성화된 상태에서만 재연결 시도
if (isTabActiveRef.current && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
if (
isTabActiveRef.current &&
reconnectAttempts < MAX_RECONNECT_ATTEMPTS
) {
setTimeout(() => {
console.log(`WebSocket 재연결 시도 (${reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS})`);
console.log(
`WebSocket 재연결 시도 (${
reconnectAttempts + 1
}/${MAX_RECONNECT_ATTEMPTS})`
);
reconnectAttempts++;
joinRoom(); // 재연결 시도
}, 2000); // 2초 후 재연결
} else if (!isTabActiveRef.current) {
console.log('브라우저 탭이 비활성화 상태입니다. WebSocket 재연결을 시도하지 않습니다.');
console.log(
"브라우저 탭이 비활성화 상태입니다. WebSocket 재연결을 시도하지 않습니다."
);
} else {
console.error('WebSocket 재연결 실패: 최대 시도 횟수를 초과했습니다.');
console.error("WebSocket 재연결 실패: 최대 시도 횟수를 초과했습니다.");
}
};
ws.current.onerror = (error) => {
console.error('WebSocket 오류:', error);
console.error("WebSocket 오류:", error);
};
};
const updateLastReadAt = async () => {
try {
const response = await fetch(`${process.env.REACT_APP_BASE_URL}/api/chat/update-read-status`, {
method: 'POST',
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/chat/update-read-status`,
{
method: "POST",
headers: {
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
body: JSON.stringify({ chatRoomId, nickname }),
});
}
);
if (!response.ok) {
throw new Error('Failed to update lastReadAt');
throw new Error("Failed to update lastReadAt");
}
console.log('lastReadAt updated for', nickname);
console.log("lastReadAt updated for", nickname);
} catch (err) {
console.error('Error updating lastReadAt:', err);
console.error("Error updating lastReadAt:", err);
}
};
// // 채팅방에서 퇴장
......@@ -568,8 +605,10 @@ function ChattingDetail() {
// };
const handleSearch = (e) => {
if (e.key === 'Enter') {
const results = messages.filter((message) => message.message.includes(searchTerm));
if (e.key === "Enter") {
const results = messages.filter((message) =>
message.message.includes(searchTerm)
);
setSearchResults(results);
setCurrentSearchIndex(results.length > 0 ? results.length - 1 : -1);
setIsSearching(true);
......@@ -580,13 +619,16 @@ function ChattingDetail() {
};
const handleArrowDown = () => {
if (searchResults.length > 0 && currentSearchIndex < searchResults.length - 1) {
if (
searchResults.length > 0 &&
currentSearchIndex < searchResults.length - 1
) {
setCurrentSearchIndex((prevIndex) => prevIndex + 1);
setTimeout(() => {
scrollToHighlightedMessage();
}, 0);
} else {
alert('더 이상 검색결과가 없습니다.');
alert("더 이상 검색결과가 없습니다.");
}
};
......@@ -597,14 +639,14 @@ function ChattingDetail() {
scrollToHighlightedMessage();
}, 0);
} else {
alert('더 이상 검색결과가 없습니다.');
alert("더 이상 검색결과가 없습니다.");
}
};
const sendMessage = () => {
if (input.trim()) {
const message = JSON.stringify({
type: 'message',
type: "message",
chatRoomId,
sender: loggedInUser,
nickname,
......@@ -613,15 +655,15 @@ function ChattingDetail() {
try {
ws.current.send(message);
console.log('전송한 메시지:', message);
console.log("전송한 메시지:", message);
updateLastReadAt();
} catch (error) {
console.error('메시지 전송 오류:', error);
console.error("메시지 전송 오류:", error);
}
setInput('');
setInput("");
} else {
alert('메시지를 입력하세요.');
alert("메시지를 입력하세요.");
}
};
......@@ -637,7 +679,7 @@ function ChattingDetail() {
const sendHeartbeat = () => {
if (ws.current && ws.current.readyState === WebSocket.OPEN) {
const heartbeatMessage = JSON.stringify({
type: 'heartbeat',
type: "heartbeat",
chatRoomId,
nickname,
});
......@@ -662,10 +704,10 @@ function ChattingDetail() {
updateLastReadAt();
// 탭 상태가 변경되면 Heartbeat 중단/재개
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") {
stopHeartbeat();
} else if (document.visibilityState === 'visible') {
} else if (document.visibilityState === "visible") {
startHeartbeat();
}
});
......@@ -679,20 +721,22 @@ function ChattingDetail() {
useEffect(() => {
// eslint-disable-next-line react-hooks/exhaustive-deps
const handleVisibilityChange = () => {
if (document.visibilityState === 'hidden') { // 브라우저 탭이 비활성화되었을 때
if (document.visibilityState === "hidden") {
// 브라우저 탭이 비활성화되었을 때
// isTabActive = false; // 탭 비활성화 상태로 설정
isTabActiveRef.current = false; // 탭 비활성화 상태로 설정
updateUserStatusAndLogId(false);
if (ws.current) {
ws.current.close(); // WebSocket 연결 종료
console.log('브라우저 탭 비활성화: WebSocket 연결 종료');
console.log("브라우저 탭 비활성화: WebSocket 연결 종료");
}
} else if (document.visibilityState === 'visible') { // 브라우저 탭이 다시 활성화되었을 때
} else if (document.visibilityState === "visible") {
// 브라우저 탭이 다시 활성화되었을 때
// isTabActive = true; // 탭 활성화 상태로 설정
isTabActiveRef.current = false; // 탭 비활성화 상태로 설정
updateUserStatusAndLogId(true);
if (!ws.current || ws.current.readyState === WebSocket.CLOSED) {
console.log('브라우저 탭 활성화: WebSocket 연결 재시작');
console.log("브라우저 탭 활성화: WebSocket 연결 재시작");
joinRoom(); // WebSocket 재연결 시도
}
}
......@@ -713,8 +757,8 @@ function ChattingDetail() {
}, [currentSearchIndex, searchResults.length]);
useEffect(() => {
console.log('chatRoomId:', chatRoomId);
console.log('nickname:', nickname);
console.log("chatRoomId:", chatRoomId);
console.log("nickname:", nickname);
setLoggedInUser(nickname);
}, [chatRoomId, nickname]);
......@@ -727,15 +771,17 @@ function ChattingDetail() {
// 공지사항 목록 가져오기
const fetchNotices = async () => {
try {
const response = await fetch(`${process.env.REACT_APP_BASE_URL}/api/chat/${chatRoomId}/notices`);
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/chat/${chatRoomId}/notices`
);
if (response.ok) {
const data = await response.json();
setNotices(data); // 공지사항 목록 업데이트
} else {
console.error('Failed to fetch notices');
console.error("Failed to fetch notices");
}
} catch (error) {
console.error('Error fetching notices:', error);
console.error("Error fetching notices:", error);
}
};
fetchNotices();
......@@ -743,7 +789,7 @@ function ChattingDetail() {
useEffect(() => {
// 공지가 변경되면 렌더링
console.log('공지사항 업데이트:', notice);
console.log("공지사항 업데이트:", notice);
}, [notice]);
useEffect(() => {
......@@ -754,12 +800,12 @@ function ChattingDetail() {
}
};
window.addEventListener('beforeunload', handleBeforeUnload); // 브라우저 종료/새로고침 이벤트 리스너 추가
window.addEventListener("beforeunload", handleBeforeUnload); // 브라우저 종료/새로고침 이벤트 리스너 추가
return () => {
console.log("페이지 이동시 상태 업데이트");
updateUserStatusAndLogId(false); // 페이지 이동 시 상태 업데이트
window.removeEventListener('beforeunload', handleBeforeUnload); // 컴포넌트 언마운트 시 이벤트 리스너 제거
window.removeEventListener("beforeunload", handleBeforeUnload); // 컴포넌트 언마운트 시 이벤트 리스너 제거
if (ws.current) {
ws.current.close(); // WebSocket 연결 종료
}
......@@ -770,21 +816,26 @@ function ChattingDetail() {
useEffect(() => {
const lastMessage = messages[messages.length - 1];
localStorage.setItem(
`loadedPreviousMessages-${chatRoomId}`,
"true"
);
localStorage.setItem(`loadedPreviousMessages-${chatRoomId}`, "true");
const hasLoadedPreviousMessages = localStorage.getItem(
`loadedPreviousMessages-${chatRoomId}`
);
if (!hasLoadedPreviousMessages && lastMessage && lastMessage.type === "previousMessages") {
if (
!hasLoadedPreviousMessages &&
lastMessage &&
lastMessage.type === "previousMessages"
) {
return; // 이전 메시지일 경우 자동 스크롤 방지
}
// 새 메시지 수신 시 자동으로 아래로 스크롤
if (lastMessage && lastMessage.type === "message" && messagesEndRef.current) {
if (
lastMessage &&
lastMessage.type === "message" &&
messagesEndRef.current
) {
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
}
}, [messages, chatRoomId]);
......@@ -792,12 +843,15 @@ function ChattingDetail() {
const highlightSearchTerm = (message) => {
if (!searchTerm) return message;
const regex = new RegExp(`(${searchTerm})`, 'gi');
const regex = new RegExp(`(${searchTerm})`, "gi");
const parts = message.split(regex);
return parts.map((part, index) =>
part.toLowerCase() === searchTerm.toLowerCase() ? (
<span key={index} style={{ backgroundColor: 'yellow', fontWeight: 'bold' }}>
<span
key={index}
style={{ backgroundColor: "yellow", fontWeight: "bold" }}
>
{part}
</span>
) : (
......@@ -809,7 +863,7 @@ function ChattingDetail() {
return (
<ChatRoomContainer>
<ChatRoomHeader>
<h1 className="heading-1 text-gray-800">{chatRoomName}</h1>
<h1 className="text-gray-800 heading-1">{chatRoomName}</h1>
{/* 검색 버튼 */}
<Button
size="lg"
......@@ -937,13 +991,12 @@ function ChattingDetail() {
const sameSenderAsNext =
nextMessage && nextMessage.sender === messageData.sender;
const messageTime = new Date(messageData.timestamp).toLocaleTimeString(
[],
{
const messageTime = new Date(
messageData.timestamp
).toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
}
);
});
const prevMessageTime =
prevMessage &&
......@@ -959,7 +1012,9 @@ function ChattingDetail() {
if (messageData.type === "join" || messageData.type === "leave") {
return (
<CenteredMessage key={index}>{messageData.message}</CenteredMessage>
<CenteredMessage key={index}>
{messageData.message}
</CenteredMessage>
);
}
......@@ -983,7 +1038,9 @@ function ChattingDetail() {
<MessageContainer
isMine={isMine}
highlighted={searchResults[currentSearchIndex] === messageData}
highlighted={
searchResults[currentSearchIndex] === messageData
}
ref={
searchResults[currentSearchIndex] === messageData
? highlightedMessageRef
......@@ -1019,7 +1076,9 @@ function ChattingDetail() {
<MessageBubble
isMine={isMine}
highlighted={searchResults[currentSearchIndex] === messageData}
highlighted={
searchResults[currentSearchIndex] === messageData
}
onContextMenu={(e) => handleRightClick(e, messageData)}
style={{
textAlign: "left",
......@@ -1087,7 +1146,7 @@ function ChattingDetail() {
theme="pink"
state={input.trim() ? "default" : "disable"}
onClick={sendMessage}
className="ml-3 flex items-center justify-center whitespace-nowrap w-16" // w-32로 버튼 너비 설정
className="flex items-center justify-center flex-1 w-16 ml-3 tablet:flex-initial whitespace-nowrap" // w-32로 버튼 너비 설정
>
전송
</Button>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment