diff --git a/public/css/index.css b/public/css/index.css
index a974847..4722460 100644
--- a/public/css/index.css
+++ b/public/css/index.css
@@ -97,13 +97,14 @@ canvas {
}
.chat-container {
- overflow: scroll;
border: black solid
}
.messages-container {
width: 100%;
height: 75%;
+ overflow: scroll;
+ overflow-wrap: anywhere;
border: gray solid;
}
@@ -125,4 +126,11 @@ canvas {
font-size: 15pt;
margin: 0;
padding: 0
+}
+
+.chat-message {
+ margin-top: 8px;
+ margin-bottom: 8px;
+ margin-left: 8px;
+ margin-right: 16px;
}
\ No newline at end of file
diff --git a/public/js/chat.js b/public/js/chat.js
index f8d15d0..493d043 100644
--- a/public/js/chat.js
+++ b/public/js/chat.js
@@ -4,21 +4,50 @@ function getCookie(name) {
if (parts.length === 2) return parts.pop().split(';').shift();
}
-$(document).ready(() => {
- //prod
- // const socket = new WebSocket('wss://auth.foxarmy.org');
- //dev
- const socket = new WebSocket('ws://localhost:3000');
+$(document).ready(async () => {
+ const wsConnectionString = (await fetch(`/api/websocketConnection`)).text()
+ const socket = new WebSocket(wsConnectionString);
+ let lastMessageNumber = 0;
+ let page = 20;
+ const fetchMoreMessages = async () => {
+ if (lastMessageNumber < 0 ) return [];
+ let messages = await (await fetch(`/api/getChatMessages/${lastMessageNumber}/${page}`)).json();
+ lastMessageNumber = messages.length < page? -1 : lastMessageNumber + messages.length
+ return messages
+ }
const appendMessageToChat = (author, content) => {
- const messageDiv = document.createElement('div')//`
<${message.author}> ${message.content}
`
+ const messageDiv = document.createElement('div')
messageDiv.className = "chat-message"
messageDiv.textContent = `<${author}> ${content}`
document.getElementsByClassName("messages-container")[0].appendChild(messageDiv)
}
- socket.onmessage = message => {
+ const prependMessageToChat = (author, content) => {
+ const messageDiv = document.createElement('div')
+ messageDiv.className = "chat-message"
+ messageDiv.textContent = `<${author}> ${content}`
+ const messageContainer = document.getElementsByClassName("messages-container")[0]
+ messageContainer.firstChild.insertAdjacentElement('afterend', messageDiv)
+ }
+ const onFetchMessageButtonClick = async () => {
+ let messages = await fetchMoreMessages(lastMessageNumber, page);
+ if (messages.length == 0) return;
+
+ messages.forEach(message => {
+ prependMessageToChat(message.author, message.content);
+ });
+ }
+
+ $("#fetch-messages-button").click(onFetchMessageButtonClick);
+
+ await onFetchMessageButtonClick();
+
+
+
+
+ socket.onmessage = message => {
try {
message = JSON.parse(message.data)
} catch(e) {
@@ -40,6 +69,8 @@ $(document).ready(() => {
socket.send(JSON.stringify(message));
appendMessageToChat(message.author, message.content)
$("#chat-input").val("")
+ let messageContainer = $(".messages-container")
+ messageContainer.animate({ scrollTop: messageContainer.prop("scrollHeight")}, 1000);
}
$("#send-message-button").click(sendData);
diff --git a/sample.env b/sample.env
index c241b43..eed77c1 100644
--- a/sample.env
+++ b/sample.env
@@ -6,4 +6,5 @@ DBPORT=5432
DBPASS=GENERATE_A_STRONG_PASSWORD_HERE
PORT=3000
REQUIRE_TOKEN=false
-DELETE_TOKEN_ON_USE=true
\ No newline at end of file
+DELETE_TOKEN_ON_USE=true
+WS_CONNECTION_STRING=wss://auth.foxarmy.org
diff --git a/src/controllers/api.js b/src/controllers/api.js
new file mode 100644
index 0000000..60f0619
--- /dev/null
+++ b/src/controllers/api.js
@@ -0,0 +1,20 @@
+import ApiService from "../services/api.js";
+import dotenv from 'dotenv';
+
+dotenv.config({path: ".env"});
+
+class ApiController {
+ async getChatMessages(req, res) {
+ const {limit, offset} = req.params;
+
+ const messages = await ApiService.getChatMessages(limit, offset);
+
+ return res.status(200).send(messages);
+ }
+
+ async getWebsocketConnection(req, res) {
+ return res.status(200).send(process.env.WS_CONNECTION_STRING)
+ }
+}
+
+export default new ApiController();
\ No newline at end of file
diff --git a/src/messages.js b/src/messages.js
index f82ba1a..4c959aa 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -91,6 +91,8 @@ const startChat = async () => {
origin: "website"
})
}]
+ }).catch(e => {
+ console.log(e)
});
// we are not sending this message to all websockets right now, because plugin will emit
// a chat event once it'll catch this message from kafka, triggering a new message
diff --git a/src/middlewares/auth.js b/src/middlewares/auth.js
index bf15825..891e838 100644
--- a/src/middlewares/auth.js
+++ b/src/middlewares/auth.js
@@ -26,7 +26,6 @@ const validateInviteToken = async (req, res, next) => {
let tokenValid = false;
inviteTokens.forEach((token) => {
- console.log(`${token} == ${inviteToken}`)
if (token == inviteToken) tokenValid = true;
});
diff --git a/src/routers/api.js b/src/routers/api.js
index 6744c44..7d96573 100644
--- a/src/routers/api.js
+++ b/src/routers/api.js
@@ -6,6 +6,7 @@ import auth from '../middlewares/auth.js';
import utils from '../utils.js';
import UserController from '../controllers/user.js';
+import ApiController from '../controllers/api.js';
const ApiRouter = new Router();
@@ -16,5 +17,7 @@ ApiRouter.post('/changepassword', auth.authenticate, existance.userExist, UserCo
ApiRouter.post('/uploadSkin', existance.userExist, auth.authenticate, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadSkin);
ApiRouter.post('/uploadCape', existance.userExist, auth.authenticate, auth.canHaveCloak, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadCape);
ApiRouter.get('/getUsername', existance.userExist, auth.authenticate, UserController.getUsername);
+ApiRouter.get('/getChatMessages/:offset/:limit', auth.authenticate, ApiController.getChatMessages);
+ApiRouter.get('/webSocketConnection', auth.authenticate, ApiController.getWebsocketConnection)
export default ApiRouter;
\ No newline at end of file
diff --git a/src/services/api.js b/src/services/api.js
new file mode 100644
index 0000000..9aef7bb
--- /dev/null
+++ b/src/services/api.js
@@ -0,0 +1,15 @@
+import db from '../db.js';
+
+class ApiService {
+ async getChatMessages(limit, offset) {
+ try {
+ const messages = (await db.query("SELECT * FROM chat_messages ORDER BY ID DESC LIMIT $1 OFFSET $2", [limit, offset])).rows
+
+ return messages
+ } catch(e) {
+ console.log(e)
+ }
+ }
+}
+
+export default new ApiService();
\ No newline at end of file
diff --git a/views/chat.pug b/views/chat.pug
index 02d52bd..97e798c 100644
--- a/views/chat.pug
+++ b/views/chat.pug
@@ -15,7 +15,7 @@ html
h1 Чат
div(class="chat-container")
div(class="messages-container")
-
+ button(id="fetch-messages-button") Загрузить ещё
div(class="input-container")
input(type="text" id="chat-input")
button(id="send-message-button") Отправить
\ No newline at end of file