Skip to content

Commit

Permalink
fix: 채팅방 사용성 개선
Browse files Browse the repository at this point in the history
  • Loading branch information
DaeHee99 committed Dec 17, 2024
2 parents 4833150 + aa66d34 commit 37647f3
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function TalkBubble({
{type === "TEXT" ? (
<div
className={clsx(
"text-boldgray text-sm p-4 rounded-lg max-w-[200px] md:max-w-[400px]",
"text-boldgray text-sm p-4 rounded-lg max-w-[200px] md:max-w-[400px] whitespace-pre-wrap",
isMyMessage ? "bg-skyblue" : "bg-lightgray",
!isMyMessage && isPrevSameDate && isPrevSameUser && "ml-12"
)}
Expand Down
50 changes: 33 additions & 17 deletions src/pages/TalkPage/TalkRoom/TalkRoomBody/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,36 +35,52 @@ function TalkRoomBody({
const user = useSelector((state: RootState) => state.user);
const [showScrollButton, setShowScrollButton] = useState(false);

const scrollDownHandler = useCallback(() => {
const talkRoomSpace = talkRoomRef.current;
if (talkRoomSpace) {
const { scrollHeight, clientHeight } = talkRoomSpace;
talkRoomSpace.scrollTo({
top: scrollHeight - clientHeight,
behavior: "smooth",
});
}
}, [talkRoomRef]);
const scrollDownHandler = useCallback(
(smooth: boolean = false) => {
const talkRoomSpace = talkRoomRef.current;
if (talkRoomSpace) {
const { scrollHeight, clientHeight } = talkRoomSpace;
talkRoomSpace.scrollTo({
top: scrollHeight - clientHeight,
behavior: smooth ? "smooth" : "auto",
});
}
},
[talkRoomRef]
);

useEffect(() => {
const handleResize = () => {
scrollDownHandler();
};

window.addEventListener("resize", handleResize);
scrollDownHandler();
return () => {
window.removeEventListener("resize", handleResize);
};
}, [scrollDownHandler]);

useEffect(() => {
const handleScroll = () => {
if (!talkRoomRef.current) return;
const { scrollHeight, clientHeight, scrollTop } = talkRoomRef.current;
const isScrolledToBottom = scrollHeight - clientHeight <= scrollTop + 200;

setShowScrollButton(!isScrolledToBottom);
};

talkRoomRef.current?.addEventListener("scroll", handleScroll);
const currentRef = talkRoomRef.current;
currentRef?.addEventListener("scroll", handleScroll);
return () => {
talkRoomRef.current?.removeEventListener("scroll", handleScroll);
currentRef?.removeEventListener("scroll", handleScroll);
};
}, []);

useEffect(() => {
if (showScrollButton) return;
scrollDownHandler();
}, [messages]);
if (!showScrollButton) {
scrollDownHandler(true);
}
}, [messages, showScrollButton, scrollDownHandler]);

return (
<div
Expand Down Expand Up @@ -107,7 +123,7 @@ function TalkRoomBody({
width: `${talkRoomRef.current?.clientWidth}px`,
}}
>
<button onClick={scrollDownHandler}>
<button onClick={() => scrollDownHandler(true)}>
<img
src={chatArrowIcon}
alt="chat-down"
Expand Down
67 changes: 57 additions & 10 deletions src/pages/TalkPage/TalkRoom/TalkRoomForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
SetStateAction,
useCallback,
useMemo,
useRef,
useState,
useEffect,
} from "react";

interface Props {
Expand All @@ -23,6 +25,8 @@ function TalkRoomForm({
isBlocked,
}: Props) {
const [message, setMessage] = useState("");
const textareaRef = useRef<HTMLTextAreaElement>(null);
const formRef = useRef<HTMLFormElement>(null);

const chatPlaceholder = useMemo(() => {
if (isBlock) return "차단한 상대와 대화가 불가능합니다.";
Expand All @@ -31,17 +35,48 @@ function TalkRoomForm({
}, [isBlock, isBlocked]);

const submitHandler = useCallback(
(e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (message === "") return;
(e?: FormEvent<HTMLFormElement>) => {
if (e) e.preventDefault();
if (message.trim() === "") return;

sendMessageHandler(message);
setMessage("");

requestAnimationFrame(() => {
textareaRef.current?.focus();
});
},
[message, sendMessageHandler]
);

const onKeyDownHandler = useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
submitHandler();
}
},
[message]
[submitHandler]
);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
formRef.current &&
!formRef.current.contains(event.target as Node) &&
textareaRef.current
) {
textareaRef.current.blur();
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);

return (
<form onSubmit={submitHandler}>
<form onSubmit={submitHandler} ref={formRef}>
<div className="flex items-center px-3">
<button
type="button"
Expand All @@ -63,21 +98,33 @@ function TalkRoomForm({
></path>
</svg>
</button>
<input
type="text"
className="block mx-2 p-2.5 w-full text-sm text-black bg-white rounded-lg border border-mediumgray focus:outline-none focus:border-primary"
<textarea
ref={textareaRef}
className={clsx(
"block mx-2 p-2.5 w-full text-sm text-black bg-white rounded-lg border border-mediumgray focus:outline-none focus:border-primary",
"resize-none overflow-y-scroll noScrollBar"
)}
placeholder={chatPlaceholder}
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={onKeyDownHandler}
disabled={isBlock || isBlocked}
style={{
lineHeight: "20px",
minHeight: "40px",
maxHeight: "40px",
}}
rows={1}
/>
<button
type="submit"
className={clsx(
"w-20 h-10 p-2 text-sm rounded-lg",
!message ? "bg-lightgray text-darkgray" : "bg-primary text-white"
!message.trim()
? "bg-lightgray text-darkgray"
: "bg-primary text-white"
)}
disabled={!message}
disabled={!message.trim()}
>
전송
</button>
Expand Down
47 changes: 44 additions & 3 deletions src/pages/TalkPage/TalkRoom/TalkRoomWrapper/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,56 @@
import { memo, ReactNode } from "react";
import { useState, useEffect, memo, ReactNode, useMemo } from "react";

interface Props {
children: ReactNode;
}

function TalkRoomWrapper({ children }: Props) {
const [viewportHeight, setViewportHeight] = useState<number>(
window.innerHeight
);
const [heightMargin, setHeightMargin] = useState<number>(0);

const styleHeight = useMemo(
() => `${viewportHeight - heightMargin}px`,
[viewportHeight, heightMargin]
);

useEffect(() => {
const handleResize = () => {
const newHeight = window.visualViewport
? window.visualViewport.height
: window.innerHeight;
setViewportHeight(newHeight);
setHeightMargin(window.innerWidth < 768 ? 24 : 90);
};

if (window.visualViewport) {
window.visualViewport.addEventListener("resize", handleResize);
handleResize();
return () => {
window.visualViewport?.removeEventListener("resize", handleResize);
};
} else {
window.addEventListener("resize", handleResize);
handleResize();
return () => {
window.removeEventListener("resize", handleResize);
};
}
}, []);

useEffect(() => {
document.documentElement.style.height = styleHeight;
return () => {
document.documentElement.style.height = "";
};
}, [styleHeight]);

return (
<div
className="flex flex-col justify-between gap-3 h-full pb-3 px-1 bg-white rounded-lg border border-mediumgray m-3 z-50 relative"
className="flex flex-col justify-between gap-3 pb-3 px-1 bg-white rounded-lg border border-mediumgray m-3 z-50 relative"
style={{
height: `calc(100% - 24px)`,
height: styleHeight,
}}
>
{children}
Expand Down
5 changes: 2 additions & 3 deletions src/pages/TalkPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,9 @@ function TalkPage() {
useEffect(() => {
getChatListFunc();

document.body.classList.add("overflow-hidden");
document.body.style.overflow = "hidden";
return () => {
document.body.classList.remove("overflow-hidden");
if (client.current) client.current.deactivate();
document.body.style.overflow = "auto";
};
}, []);

Expand Down

0 comments on commit 37647f3

Please sign in to comment.