Added online for contacts. Updated chat
This commit is contained in:
parent
5929303523
commit
b379a2a98c
@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { useSocket } from "../../../hooks/useSocket";
|
||||
import "./styles/ChatTab.css";
|
||||
import PlayerManager from "../../../services/PlayerManager";
|
||||
|
||||
const ChatTab = () => {
|
||||
const { socket } = useSocket();
|
||||
@ -13,8 +14,16 @@ const ChatTab = () => {
|
||||
const [showSidebar, setShowSidebar] = useState(true);
|
||||
const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);
|
||||
const [confirmUnfriend, setConfirmUnfriend] = useState(null);
|
||||
const [onlineList, setOnlineList] = useState(
|
||||
PlayerManager.onlinePlayers || [],
|
||||
);
|
||||
|
||||
const messagesEndRef = useRef(null);
|
||||
const activeChatRef = useRef(activeChat);
|
||||
|
||||
useEffect(() => {
|
||||
activeChatRef.current = activeChat;
|
||||
}, [activeChat]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
@ -30,17 +39,34 @@ const ChatTab = () => {
|
||||
if (!socket) return;
|
||||
|
||||
socket.emit("friend:get_list");
|
||||
|
||||
if (activeChat === "global") {
|
||||
socket.emit("chat:get_global_history");
|
||||
} else {
|
||||
socket.emit("chat:get_private_history", { friendId: activeChat });
|
||||
}
|
||||
}, [socket, activeChat]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket) return;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setOnlineList([...PlayerManager.onlinePlayers]);
|
||||
}, 3000);
|
||||
|
||||
const handleNewMessage = (msg) => {
|
||||
if (
|
||||
(activeChat === "global" && msg.type === "global") ||
|
||||
(activeChat !== "global" &&
|
||||
(msg.senderId === activeChat || msg.receiverId === activeChat))
|
||||
) {
|
||||
setMessages((prev) => [...prev, msg]);
|
||||
const currentActive = activeChatRef.current;
|
||||
const isGlobalMatch = currentActive === "global" && msg.type === "global";
|
||||
const isPrivateMatch =
|
||||
currentActive !== "global" &&
|
||||
msg.type === "private" &&
|
||||
(msg.senderId === currentActive || msg.receiverId === currentActive);
|
||||
|
||||
if (isGlobalMatch || isPrivateMatch) {
|
||||
setMessages((prev) => {
|
||||
if (prev.some((m) => m.id === msg.id)) return prev;
|
||||
return [...prev, msg];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -50,16 +76,19 @@ const ChatTab = () => {
|
||||
|
||||
socket.on("chat:new_message", handleNewMessage);
|
||||
socket.on("chat:global_history", handleHistory);
|
||||
socket.on("chat:private_history", handleHistory);
|
||||
socket.on("player:search_results", handleSearchResults);
|
||||
socket.on("friend:list", handleFriendList);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
socket.off("chat:new_message", handleNewMessage);
|
||||
socket.off("chat:global_history", handleHistory);
|
||||
socket.off("chat:private_history", handleHistory);
|
||||
socket.off("player:search_results", handleSearchResults);
|
||||
socket.off("friend:list", handleFriendList);
|
||||
};
|
||||
}, [socket, activeChat]);
|
||||
}, [socket]);
|
||||
|
||||
useEffect(() => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
@ -110,6 +139,10 @@ const ChatTab = () => {
|
||||
return friend ? friend.username : "UNKNOWN_PILOT";
|
||||
};
|
||||
|
||||
const isFriendOnline = (username) => {
|
||||
return onlineList.includes(username);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`chat-container ${isMobile ? "mobile" : ""}`}>
|
||||
{confirmUnfriend && (
|
||||
@ -148,7 +181,6 @@ const ChatTab = () => {
|
||||
onChange={handleSearch}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{searchResults.length > 0 && (
|
||||
<div className="search-results-dropdown">
|
||||
{searchResults.map((player) => (
|
||||
@ -194,7 +226,7 @@ const ChatTab = () => {
|
||||
onClick={() => selectChat(friend.id)}
|
||||
>
|
||||
<div
|
||||
className={`status-dot ${friend.online ? "online" : "offline"}`}
|
||||
className={`status-dot ${isFriendOnline(friend.username) ? "online" : "offline"}`}
|
||||
></div>
|
||||
<span>{friend.username}</span>
|
||||
</div>
|
||||
|
||||
@ -49,7 +49,31 @@ class ChatManager {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getPrivateHistory(myId, friendId, limit = 50) {
|
||||
try {
|
||||
return await Message.findAll({
|
||||
where: {
|
||||
type: "private",
|
||||
[Op.or]: [
|
||||
{ senderId: myId, receiverId: friendId },
|
||||
{ senderId: friendId, receiverId: myId },
|
||||
],
|
||||
},
|
||||
limit,
|
||||
order: [["createdAt", "ASC"]],
|
||||
include: [
|
||||
{
|
||||
model: Player,
|
||||
as: "sender",
|
||||
attributes: ["username"],
|
||||
},
|
||||
],
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Private History Error:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
async searchPlayers(query, excludeId) {
|
||||
try {
|
||||
return await Player.findAll({
|
||||
|
||||
@ -14,7 +14,6 @@ module.exports = (io, socket) => {
|
||||
socket.emit("chat:global_history", formattedHistory);
|
||||
});
|
||||
socket.on("chat:get_global_history", async () => {
|
||||
console.log(`Player ${socket.player?.id} requested chat history`);
|
||||
const history = await chatManager.getGlobalHistory();
|
||||
|
||||
const formattedHistory = history.map((m) => ({
|
||||
@ -28,10 +27,12 @@ module.exports = (io, socket) => {
|
||||
|
||||
socket.emit("chat:global_history", formattedHistory);
|
||||
});
|
||||
|
||||
socket.on("chat:send_message", async (payload) => {
|
||||
try {
|
||||
const senderId = socket.user?.id;
|
||||
if (!senderId) return;
|
||||
|
||||
const messageData = await chatManager.saveMessage({
|
||||
content: payload.content,
|
||||
type: payload.type || "global",
|
||||
@ -42,20 +43,36 @@ module.exports = (io, socket) => {
|
||||
if (messageData.type === "global") {
|
||||
io.emit("chat:new_message", messageData);
|
||||
} else {
|
||||
console.log(payload.receiverId);
|
||||
socket
|
||||
.to(`user_${payload.receiverId}`)
|
||||
.emit("chat:new_message", messageData);
|
||||
socket.emit("chat:new_message", messageData);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
socket.emit("error", { message: "CHAT_SEND_ERROR" });
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("chat:get_private_history", async ({ friendId }) => {
|
||||
const myId = socket.user?.id;
|
||||
|
||||
if (!myId || !friendId) return;
|
||||
|
||||
const history = await chatManager.getPrivateHistory(myId, friendId);
|
||||
const formattedHistory = history.map((m) => ({
|
||||
id: m.id,
|
||||
content: m.content,
|
||||
senderName: m.sender?.username || "Unknown",
|
||||
senderId: m.senderId,
|
||||
receiverId: m.receiverId,
|
||||
createdAt: m.createdAt,
|
||||
type: m.type,
|
||||
}));
|
||||
socket.emit("chat:private_history", formattedHistory);
|
||||
});
|
||||
socket.on("player:search", async ({ query }) => {
|
||||
const senderId = socket.player?.id;
|
||||
const senderId = socket.user?.id;
|
||||
if (!query || !senderId) return;
|
||||
|
||||
const results = await chatManager.searchPlayers(query, senderId);
|
||||
|
||||
@ -63,7 +63,7 @@ module.exports = async (io, socket) => {
|
||||
});
|
||||
|
||||
socket.broadcast.emit("player:joined", { username: playerRaw.username });
|
||||
|
||||
socket.join(`user_${socket.user.id}`);
|
||||
socket.on("player:get_dashboard", async () => {
|
||||
try {
|
||||
const p = await Player.findByPk(userId);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user