Spaces:
Sleeping
Sleeping
Commit ·
2ef5cc9
1
Parent(s): 897b4ca
khien cho agent hieu ngu canh room
Browse files- src/components/ChatArea.jsx +56 -3
src/components/ChatArea.jsx
CHANGED
|
@@ -61,6 +61,7 @@ function ChatArea({
|
|
| 61 |
const typingTimeoutRef = useRef(null);
|
| 62 |
const [roomTypingUser, setRoomTypingUser] = useState(null); // { name, timeoutId }
|
| 63 |
const roomTypingTimeoutRef = useRef(null); // Track typing timeout to clear properly
|
|
|
|
| 64 |
const isCreatingConversationRef = useRef(false);
|
| 65 |
const pendingMessageQueueRef = useRef([]); // Queue messages while creating conversation
|
| 66 |
const sendingTimeoutsRef = useRef({}); // { [tempId]: timeoutId } - auto-clear pending after 10s
|
|
@@ -259,17 +260,54 @@ function ChatArea({
|
|
| 259 |
useEffect(() => {
|
| 260 |
if (!isSpaceRoom || !room) return;
|
| 261 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 262 |
const handleUserTyping = (data) => {
|
| 263 |
if (data.roomId === room && data.userId !== currentUser?.id) {
|
| 264 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 265 |
// Clear previous timeout before setting new one
|
| 266 |
if (roomTypingTimeoutRef.current) {
|
| 267 |
clearTimeout(roomTypingTimeoutRef.current);
|
| 268 |
}
|
| 269 |
// Auto-clear after 3s
|
|
|
|
| 270 |
roomTypingTimeoutRef.current = setTimeout(() => {
|
| 271 |
setRoomTypingUser((current) =>
|
| 272 |
-
current ===
|
| 273 |
);
|
| 274 |
}, 3000);
|
| 275 |
}
|
|
@@ -277,20 +315,35 @@ function ChatArea({
|
|
| 277 |
|
| 278 |
const handleUserStopTyping = (data) => {
|
| 279 |
if (data.roomId === room) {
|
| 280 |
-
|
| 281 |
}
|
| 282 |
};
|
| 283 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
socketService.on("userTyping", handleUserTyping);
|
| 285 |
socketService.on("userStopTyping", handleUserStopTyping);
|
| 286 |
|
| 287 |
return () => {
|
|
|
|
|
|
|
| 288 |
socketService.off("userTyping", handleUserTyping);
|
| 289 |
socketService.off("userStopTyping", handleUserStopTyping);
|
| 290 |
if (roomTypingTimeoutRef.current) {
|
| 291 |
clearTimeout(roomTypingTimeoutRef.current);
|
| 292 |
roomTypingTimeoutRef.current = null;
|
| 293 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
};
|
| 295 |
}, [isSpaceRoom, room, currentUser?.id]);
|
| 296 |
|
|
|
|
| 61 |
const typingTimeoutRef = useRef(null);
|
| 62 |
const [roomTypingUser, setRoomTypingUser] = useState(null); // { name, timeoutId }
|
| 63 |
const roomTypingTimeoutRef = useRef(null); // Track typing timeout to clear properly
|
| 64 |
+
const roomBotTypingClearRef = useRef(null);
|
| 65 |
const isCreatingConversationRef = useRef(false);
|
| 66 |
const pendingMessageQueueRef = useRef([]); // Queue messages while creating conversation
|
| 67 |
const sendingTimeoutsRef = useRef({}); // { [tempId]: timeoutId } - auto-clear pending after 10s
|
|
|
|
| 260 |
useEffect(() => {
|
| 261 |
if (!isSpaceRoom || !room) return;
|
| 262 |
|
| 263 |
+
const clearRoomTyping = (delay = 0) => {
|
| 264 |
+
if (roomTypingTimeoutRef.current) {
|
| 265 |
+
clearTimeout(roomTypingTimeoutRef.current);
|
| 266 |
+
roomTypingTimeoutRef.current = null;
|
| 267 |
+
}
|
| 268 |
+
if (roomBotTypingClearRef.current) {
|
| 269 |
+
clearTimeout(roomBotTypingClearRef.current);
|
| 270 |
+
roomBotTypingClearRef.current = null;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
if (delay > 0) {
|
| 274 |
+
roomBotTypingClearRef.current = setTimeout(() => {
|
| 275 |
+
setRoomTypingUser(null);
|
| 276 |
+
roomBotTypingClearRef.current = null;
|
| 277 |
+
}, delay);
|
| 278 |
+
} else {
|
| 279 |
+
setRoomTypingUser(null);
|
| 280 |
+
}
|
| 281 |
+
};
|
| 282 |
+
|
| 283 |
+
const isStudyBotPayload = (data) => {
|
| 284 |
+
const sender = data?.sender || data?.author || {};
|
| 285 |
+
const senderName = typeof sender === "object"
|
| 286 |
+
? sender.display_name || sender.username || ""
|
| 287 |
+
: typeof sender === "string"
|
| 288 |
+
? sender
|
| 289 |
+
: "";
|
| 290 |
+
const senderUsername = typeof sender === "object" ? sender.username || "" : "";
|
| 291 |
+
return data?.isBot || senderName === "StudyBot" || senderUsername === "studybot";
|
| 292 |
+
};
|
| 293 |
+
|
| 294 |
const handleUserTyping = (data) => {
|
| 295 |
if (data.roomId === room && data.userId !== currentUser?.id) {
|
| 296 |
+
if (data.isTyping === false) {
|
| 297 |
+
clearRoomTyping(data.isBot ? 120 : 0);
|
| 298 |
+
return;
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
setRoomTypingUser(data.isBot ? "StudyBot" : data.senderName || "Someone");
|
| 302 |
// Clear previous timeout before setting new one
|
| 303 |
if (roomTypingTimeoutRef.current) {
|
| 304 |
clearTimeout(roomTypingTimeoutRef.current);
|
| 305 |
}
|
| 306 |
// Auto-clear after 3s
|
| 307 |
+
const typingName = data.isBot ? "StudyBot" : data.senderName || "Someone";
|
| 308 |
roomTypingTimeoutRef.current = setTimeout(() => {
|
| 309 |
setRoomTypingUser((current) =>
|
| 310 |
+
current === typingName ? null : current
|
| 311 |
);
|
| 312 |
}, 3000);
|
| 313 |
}
|
|
|
|
| 315 |
|
| 316 |
const handleUserStopTyping = (data) => {
|
| 317 |
if (data.roomId === room) {
|
| 318 |
+
clearRoomTyping();
|
| 319 |
}
|
| 320 |
};
|
| 321 |
|
| 322 |
+
const handleRoomMessage = (data) => {
|
| 323 |
+
const messageRoomId = data.room_id || data.roomId;
|
| 324 |
+
if (messageRoomId === room && isStudyBotPayload(data)) {
|
| 325 |
+
clearRoomTyping(50);
|
| 326 |
+
}
|
| 327 |
+
};
|
| 328 |
+
|
| 329 |
+
socketService.on("typing", handleUserTyping);
|
| 330 |
+
socketService.onNewMessage(handleRoomMessage);
|
| 331 |
socketService.on("userTyping", handleUserTyping);
|
| 332 |
socketService.on("userStopTyping", handleUserStopTyping);
|
| 333 |
|
| 334 |
return () => {
|
| 335 |
+
socketService.off("typing", handleUserTyping);
|
| 336 |
+
socketService.off("newMessage", handleRoomMessage);
|
| 337 |
socketService.off("userTyping", handleUserTyping);
|
| 338 |
socketService.off("userStopTyping", handleUserStopTyping);
|
| 339 |
if (roomTypingTimeoutRef.current) {
|
| 340 |
clearTimeout(roomTypingTimeoutRef.current);
|
| 341 |
roomTypingTimeoutRef.current = null;
|
| 342 |
}
|
| 343 |
+
if (roomBotTypingClearRef.current) {
|
| 344 |
+
clearTimeout(roomBotTypingClearRef.current);
|
| 345 |
+
roomBotTypingClearRef.current = null;
|
| 346 |
+
}
|
| 347 |
};
|
| 348 |
}, [isSpaceRoom, room, currentUser?.id]);
|
| 349 |
|