mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
Implemented loading of latest messages on joining chat
This commit is contained in:
parent
f10b6df989
commit
07fb313765
@ -14,9 +14,10 @@
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/WindowHandler.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
|
||||
#include "../windows/InfoWindows.h"
|
||||
|
||||
#include "../../lib/MetaString.h"
|
||||
|
||||
LobbyClient::LobbyClient(LobbyWindow * window)
|
||||
: window(window)
|
||||
{
|
||||
@ -25,7 +26,33 @@ LobbyClient::LobbyClient(LobbyWindow * window)
|
||||
|
||||
void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
|
||||
{
|
||||
// FIXME: find better approach
|
||||
const char * payloadBegin = reinterpret_cast<const char*>(message.data());
|
||||
JsonNode json(payloadBegin, message.size());
|
||||
|
||||
if (json["type"].String() == "chatHistory")
|
||||
{
|
||||
for (auto const & entry : json["messages"].Vector())
|
||||
{
|
||||
std::string senderName = entry["senderName"].String();
|
||||
std::string messageText = entry["messageText"].String();
|
||||
int ageSeconds = entry["ageSeconds"].Integer();
|
||||
|
||||
// FIXME: better/unified way to format date
|
||||
auto timeNowChrono = std::chrono::system_clock::now();
|
||||
timeNowChrono -= std::chrono::seconds(ageSeconds);
|
||||
|
||||
std::time_t timeNowC = std::chrono::system_clock::to_time_t(timeNowChrono);
|
||||
std::tm timeNowTm = *std::localtime(&timeNowC);
|
||||
|
||||
MetaString dateFormatted;
|
||||
dateFormatted.appendRawString("%d:%d");
|
||||
dateFormatted.replaceNumber(timeNowTm.tm_hour);
|
||||
dateFormatted.replaceNumber(timeNowTm.tm_min);
|
||||
|
||||
window->onGameChatMessage(senderName, messageText, dateFormatted.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyClient::onConnectionFailed(const std::string & errorMessage)
|
||||
@ -68,6 +95,11 @@ std::shared_ptr<CTextInput> LobbyWidget::getMessageInput()
|
||||
return widget<CTextInput>("messageInput");
|
||||
}
|
||||
|
||||
std::shared_ptr<CTextBox> LobbyWidget::getGameChat()
|
||||
{
|
||||
return widget<CTextBox>("gameChat");
|
||||
}
|
||||
|
||||
LobbyWindow::LobbyWindow():
|
||||
CWindowObject(BORDERED)
|
||||
{
|
||||
@ -99,3 +131,16 @@ void LobbyWindow::doSendChatMessage()
|
||||
|
||||
widget->getMessageInput()->setText("");
|
||||
}
|
||||
|
||||
void LobbyWindow::onGameChatMessage(const std::string & sender, const std::string & message, const std::string & when)
|
||||
{
|
||||
MetaString chatMessageFormatted;
|
||||
chatMessageFormatted.appendRawString("[%s] {%s}: %s\n");
|
||||
chatMessageFormatted.replaceRawString(when);
|
||||
chatMessageFormatted.replaceRawString(sender);
|
||||
chatMessageFormatted.replaceRawString(message);
|
||||
|
||||
chatHistory += chatMessageFormatted.toString();
|
||||
|
||||
widget->getGameChat()->setText(chatHistory);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ public:
|
||||
LobbyWidget(LobbyWindow * window);
|
||||
|
||||
std::shared_ptr<CTextInput> getMessageInput();
|
||||
std::shared_ptr<CTextBox> getGameChat();
|
||||
};
|
||||
|
||||
class LobbyClient : public NetworkClient
|
||||
@ -41,6 +42,8 @@ public:
|
||||
|
||||
class LobbyWindow : public CWindowObject
|
||||
{
|
||||
std::string chatHistory;
|
||||
|
||||
std::shared_ptr<LobbyWidget> widget;
|
||||
std::shared_ptr<LobbyClient> connection;
|
||||
|
||||
@ -51,5 +54,5 @@ public:
|
||||
|
||||
void doSendChatMessage();
|
||||
|
||||
void onGameChatMessage(std::string sender, std::string message, std::string when);
|
||||
void onGameChatMessage(const std::string & sender, const std::string & message, const std::string & when);
|
||||
};
|
||||
|
@ -43,6 +43,7 @@ void NetworkServer::connectionAccepted(std::shared_ptr<NetworkSocket> upcomingCo
|
||||
auto connection = std::make_shared<NetworkConnection>(upcomingConnection, *this);
|
||||
connections.insert(connection);
|
||||
connection->start();
|
||||
onNewConnection(connection);
|
||||
startAsyncAccept();
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,16 @@ void LobbyDatabase::prepareStatements()
|
||||
INSERT INTO chatMessages(senderName, messageText) VALUES( ?, ?);
|
||||
)";
|
||||
|
||||
static const std::string getRecentMessageHistoryText = R"(
|
||||
SELECT senderName, messageText, strftime('%s',CURRENT_TIMESTAMP)- strftime('%s',sendTime) AS secondsElapsed
|
||||
FROM chatMessages
|
||||
WHERE secondsElapsed < 60*60*24
|
||||
ORDER BY sendTime DESC
|
||||
LIMIT 100
|
||||
)";
|
||||
|
||||
insertChatMessageStatement = database->prepare(insertChatMessageText);
|
||||
getRecentMessageHistoryStatement = database->prepare(getRecentMessageHistoryText);
|
||||
}
|
||||
|
||||
void LobbyDatabase::createTableChatMessages()
|
||||
@ -69,9 +78,55 @@ void LobbyDatabase::insertChatMessage(const std::string & sender, const std::str
|
||||
insertChatMessageStatement->reset();
|
||||
}
|
||||
|
||||
void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> &)
|
||||
std::vector<LobbyDatabase::ChatMessage> LobbyDatabase::getRecentMessageHistory()
|
||||
{
|
||||
std::vector<LobbyDatabase::ChatMessage> result;
|
||||
|
||||
while(getRecentMessageHistoryStatement->execute())
|
||||
{
|
||||
LobbyDatabase::ChatMessage message;
|
||||
getRecentMessageHistoryStatement->getColumns(message.sender, message.messageText, message.messageAgeSeconds);
|
||||
result.push_back(message);
|
||||
}
|
||||
getRecentMessageHistoryStatement->reset();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void LobbyServer::sendMessage(const std::shared_ptr<NetworkConnection> & target, const JsonNode & json)
|
||||
{
|
||||
//FIXME: copy-paste from LobbyClient::sendMessage
|
||||
std::string payloadString = json.toJson(true);
|
||||
|
||||
// FIXME: find better approach
|
||||
uint8_t * payloadBegin = reinterpret_cast<uint8_t*>(payloadString.data());
|
||||
uint8_t * payloadEnd = payloadBegin + payloadString.size();
|
||||
|
||||
std::vector<uint8_t> payloadBuffer(payloadBegin, payloadEnd);
|
||||
|
||||
sendPacket(target, payloadBuffer);
|
||||
}
|
||||
|
||||
void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> & connection)
|
||||
{
|
||||
// FIXME: move to authorization message reply
|
||||
auto history = database->getRecentMessageHistory();
|
||||
|
||||
JsonNode json;
|
||||
json["type"].String() = "chatHistory";
|
||||
|
||||
for (auto const & message : boost::adaptors::reverse(history))
|
||||
{
|
||||
JsonNode jsonEntry;
|
||||
|
||||
jsonEntry["messageText"].String() = message.messageText;
|
||||
jsonEntry["senderName"].String() = message.sender;
|
||||
jsonEntry["ageSeconds"].Integer() = message.messageAgeSeconds;
|
||||
|
||||
json["messages"].Vector().push_back(jsonEntry);
|
||||
}
|
||||
|
||||
sendMessage(connection, json);
|
||||
}
|
||||
|
||||
void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
|
||||
|
@ -11,6 +11,10 @@
|
||||
|
||||
#include "../lib/network/NetworkServer.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class SQLiteInstance;
|
||||
class SQLiteStatement;
|
||||
|
||||
@ -18,14 +22,23 @@ class LobbyDatabase
|
||||
{
|
||||
std::unique_ptr<SQLiteInstance> database;
|
||||
std::unique_ptr<SQLiteStatement> insertChatMessageStatement;
|
||||
std::unique_ptr<SQLiteStatement> getRecentMessageHistoryStatement;
|
||||
|
||||
void initializeDatabase();
|
||||
void prepareStatements();
|
||||
void createTableChatMessages();
|
||||
public:
|
||||
struct ChatMessage
|
||||
{
|
||||
std::string sender;
|
||||
std::string messageText;
|
||||
int messageAgeSeconds;
|
||||
};
|
||||
|
||||
LobbyDatabase();
|
||||
|
||||
void insertChatMessage(const std::string & sender, const std::string & messageText);
|
||||
std::vector<ChatMessage> getRecentMessageHistory();
|
||||
};
|
||||
|
||||
class LobbyServer : public NetworkServer
|
||||
@ -34,6 +47,8 @@ class LobbyServer : public NetworkServer
|
||||
|
||||
void onNewConnection(const std::shared_ptr<NetworkConnection> &) override;
|
||||
void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
|
||||
|
||||
void sendMessage(const std::shared_ptr<NetworkConnection> & target, const JsonNode & json);
|
||||
public:
|
||||
LobbyServer();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user