diff --git a/server.js b/server.js index 694e8d0..00ddff1 100644 --- a/server.js +++ b/server.js @@ -471,6 +471,98 @@ app.get('/api/messages/:contactId', authenticate, async (req, res) => { } }); +app.get('/api/messages/:contactId', authenticate, async (req, res) => { + const userId = req.user.id; + const contactId = parseInt(req.params.contactId, 10); + try { + // Ensure table exists + await virtualWorldPool.query(` + CREATE TABLE IF NOT EXISTS messages ( + id SERIAL PRIMARY KEY, + sender_id INT NOT NULL, + receiver_id INT NOT NULL, + message TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + is_read BOOLEAN NOT NULL DEFAULT FALSE + )`); + } catch (e) { + console.warn('[GET /api/messages/:contactId] ensure table failed:', e.message); + } + + try { + const sql = `SELECT * FROM messages + WHERE (sender_id = $1 AND receiver_id = $2) + OR (sender_id = $2 AND receiver_id = $1) + ORDER BY created_at ASC`; + const messagesRes = await virtualWorldPool.query(sql, [userId, contactId]); + res.json(messagesRes.rows); + } catch (err) { + console.error('[GET /api/messages/:contactId] error:', err); + res.status(500).json({ error: 'Ошибка получения сообщений' }); + } +}); + +app.get('/api/messages-read/:contactId', authenticate, async (req, res) => { + const userId = req.user.id; + const contactId = parseInt(req.params.contactId, 10); + + try { + // Проверяем есть ли НЕпрочитанные сообщения от этого контакта + const sql = `SELECT EXISTS ( + SELECT 1 FROM messages + WHERE sender_id = $1 + AND receiver_id = $2 + AND is_read = false + AND sender_id != receiver_id + ) as has_unread`; + + const result = await virtualWorldPool.query(sql, [contactId, userId]); + + // Если есть непрочитанные - возвращаем "true", иначе "false" + const hasUnread = result.rows[0].has_unread; + res.json(hasUnread ? "true" : "false"); + + } catch (err) { + console.error('[GET /api/messages-read/:contactId] error:', err); + res.status(500).json({ error: 'Ошибка проверки состояния' }); + } +}); + + + + +app.post('/api/messages-read-true-false', authenticate, async (req, res) => { + try { + const userId = req.user.id; + const { contactId } = req.body; + + if (!contactId) { + return res.status(400).json({ error: 'contactId required' }); + } + + // Проверяем что contactId не равен ID текущего пользователя + if (parseInt(contactId) === userId) { + return res.json({ success: true, skipped: 'Нельзя отмечать свои собственные сообщения' }); + } + + // Отмечаем сообщения как прочитанные ТОЛЬКО если отправитель ≠ получатель + await virtualWorldPool.query( + `UPDATE messages + SET is_read = true + WHERE sender_id = $1 AND receiver_id = $2 + AND sender_id != receiver_id`, // Добавляем проверку + [contactId, userId] + ); + + res.json({ success: true }); + + } catch (error) { + console.error('Error updating read status:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + + app.post('/api/messages/send', authenticate, async (req, res) => { const senderId = req.user.id; const { receiverId, message } = req.body || {}; diff --git a/src/Game.js b/src/Game.js index f12e769..c14b02d 100644 --- a/src/Game.js +++ b/src/Game.js @@ -1364,6 +1364,7 @@ function Game({ avatarUrl, gender }) { const [newMessage, setNewMessage] = useState(""); const [messageInterval, setMessageInterval] = useState(null); const [messages, setMessages] = useState([]); + //const [readmes, setReadmes] = useState('false'); const [userProfile, setUserProfile] = useState(null); // Функция загрузки сообщений @@ -1371,7 +1372,29 @@ function Game({ avatarUrl, gender }) { if (!contactId) return; const token = localStorage.getItem('token'); + async function markMessagesAsRead(contactId, token) { + try { + const res = await fetch('/api/messages-read-true-false', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + contactId: contactId + }) + }); + + if (!res.ok) { + console.error('Ошибка отметки сообщений как прочитанных'); + } + } catch (error) { + console.error('Error marking as read:', error); + } + } + try { + // 1. Загружаем сообщения const res = await fetch(`/api/messages/${contactId}`, { headers: { Authorization: `Bearer ${token}` } }); @@ -1379,21 +1402,51 @@ function Game({ avatarUrl, gender }) { if (res.ok) { const data = await res.json(); setMessages(data); - console.log('Сообщение загружено'); + console.log('Сообщения загружены'); + + // 2. Отмечаем сообщения как прочитанные + await markMessagesAsRead(contactId, token); + // Прокручиваем чат вниз setTimeout(() => { const chatContainer = document.getElementById('chatContainer'); if (chatContainer) { chatContainer.scrollTop = chatContainer.scrollHeight; } - }, 100); + }, 1000); } else { console.error('Ошибка загрузки сообщений'); } } catch (err) { - console.error('Ошибка сети:', err); + console.error('Ошибка:', err); } } + /* async function readmessages(contactId) { + if (!contactId) return; + + const token = localStorage.getItem('token'); + try { + const res = await fetch(`/api/messages-read/${contactId}`, { + headers: { Authorization: `Bearer ${token}` } + }); + + if (res.ok) { + const data = await res.text(); + if (data == "true") { + readmes('true'); // Есть непрочитанные + } else { + readmes('false'); // Нет непрочитанных + } + console.log('Статус прочитанности проверен:', data); + } else { + console.error('Ошибка проверки сообщений'); + readmes('false'); + } + } catch (err) { + console.error('Ошибка:', err); + readmes('false'); + } + }*/ // Функция отправки сообщения async function sendMessage() { @@ -1431,10 +1484,11 @@ function Game({ avatarUrl, gender }) { if (activeChat) { // Первоначальная загрузка сообщений loadMessages(activeChat.id); - + //readmessages(activeChat.id) // Запускаем интервал для проверки новых сообщений const interval = setInterval(() => { loadMessages(activeChat.id); + //readmessages(activeChat.id); }, 1000); // Проверка каждую секунду setMessageInterval(interval); @@ -5588,39 +5642,70 @@ function Game({ avatarUrl, gender }) { ))} - {/* Область чата */} -
Нет сообщений
- ) : ( - messages.map(msg => ( -Нет сообщений
+ ) : ( + messages.map(msg => ( +