aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChatMessage.cpp6
-rw-r--r--src/ChatWindow.cpp89
-rw-r--r--src/Window.cpp39
3 files changed, 116 insertions, 18 deletions
diff --git a/src/ChatMessage.cpp b/src/ChatMessage.cpp
index 048bfca..db5fad2 100644
--- a/src/ChatMessage.cpp
+++ b/src/ChatMessage.cpp
@@ -2,9 +2,11 @@
namespace dchat
{
- ChatMessage::ChatMessage(const Glib::ustring &_username, const Glib::ustring &_text) :
+ ChatMessage::ChatMessage(const Glib::ustring &_username, const Glib::ustring &_text, uint32_t _timestampSeconds, const User *_user) :
username(_username),
- text(_text)
+ text(_text),
+ timestampSeconds(_timestampSeconds),
+ user(_user)
{
username.set_selectable(true);
username.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_START);
diff --git a/src/ChatWindow.cpp b/src/ChatWindow.cpp
index bebc644..b0bb696 100644
--- a/src/ChatWindow.cpp
+++ b/src/ChatWindow.cpp
@@ -5,8 +5,12 @@
namespace dchat
{
+ // Merge all messages that are written by the same user without interrupt within a timeframe
+ const int MERGE_MESSAGE_TIMESTAMP_DIFF_SEC = 60;
+
ChatWindow::ChatWindow() :
- channelCount(0)
+ channelCount(0),
+ lastMessage(nullptr)
{
setupTopBar();
@@ -66,15 +70,14 @@ namespace dchat
leftPanelChannels.attach(*channelsTitle, 0, 0, 1, 1);
////
- Gtk::Grid *leftPanelUsers = Gtk::manage(new Gtk::Grid());
- leftPanelUsers->set_vexpand(true);
- leftPanel->add2(*leftPanelUsers);
+ leftPanelUsers.set_vexpand(true);
+ leftPanel->add2(leftPanelUsers);
Gtk::Label *usersTitle = Gtk::manage(new Gtk::Label());
usersTitle->set_name("users-title");
usersTitle->set_text("Users");
usersTitle->set_halign(Gtk::ALIGN_START);
- leftPanelUsers->attach(*usersTitle, 0, 0, 1, 1);
+ leftPanelUsers.attach(*usersTitle, 0, 0, 1, 1);
}
void ChatWindow::setupMessageArea(Gtk::Grid *rightPanel)
@@ -102,8 +105,9 @@ namespace dchat
void ChatWindow::addChannel(const odhtdb::Hash &nodeHash)
{
assert(channelDataById.find(nodeHash) == channelDataById.end());
- printf("Added channel\n");
- Gtk::Button *channelButton = Gtk::manage(new Gtk::Button("Channel name"));
+ fprintf(stderr, "Added channel %s\n", nodeHash.toString().c_str());
+ Gtk::ToggleButton *channelButton = Gtk::manage(new Gtk::ToggleButton("Channel name"));
+ channelButton->set_active(true);
channelButton->get_style_context()->add_class("channel-button");
channelButton->set_hexpand(true);
channelButton->get_child()->set_halign(Gtk::ALIGN_START);
@@ -113,15 +117,82 @@ namespace dchat
channelDataById[nodeHash] = { channelButton, 0 };
}
- void ChatWindow::addLocalMessage(const odhtdb::Hash &channelId, Glib::ustring msg)
+ void ChatWindow::addLocalMessage(const odhtdb::Hash &channelId, const odhtdb::Signature::PublicKey &userPublicKey, uint32_t timestampSeconds, Glib::ustring msg)
{
auto it = channelDataById.find(channelId);
assert(it != channelDataById.end());
- ChatMessage *message = Gtk::manage(new ChatMessage("Arezu", msg));
+ User *user = getUserByPublicKey(userPublicKey);
+ if(!user)
+ {
+ fprintf(stderr, "Unable to add message to channel because the user %s doesn't exist in it\n", userPublicKey.toString().c_str());
+ return;
+ }
+
+ if(lastMessage && lastMessage->user->publicKey == userPublicKey)
+ {
+ int64_t msgTimeDiff = (int64_t)timestampSeconds - (int64_t)lastMessage->timestampSeconds;
+ if(msgTimeDiff <= MERGE_MESSAGE_TIMESTAMP_DIFF_SEC)
+ {
+ lastMessage->text.set_text(lastMessage->text.get_text() + "\n" + msg);
+ return;
+ }
+ }
+
+ ChatMessage *message = Gtk::manage(new ChatMessage(user->name, msg, timestampSeconds, user));
+ lastMessage = message;
message->set_valign(Gtk::Align::ALIGN_START);
message->set_hexpand(true);
message->show_all();
chatAreaLayout.attach(*message, 0, it->second.messageCount, 1, 1);
++it->second.messageCount;
}
+
+ void ChatWindow::addUser(const odhtdb::Signature::PublicKey &userPublicKey)
+ {
+ User *existingUser = getUserByPublicKey(userPublicKey);
+ if(existingUser)
+ {
+ fprintf(stderr, "ChatWindow::addUser: user %s was not added because the user has already been added\n", userPublicKey.toString().c_str());
+ return;
+ }
+
+ Gtk::Label *username = Gtk::manage(new Gtk::Label("NoName"));
+ username->set_halign(Gtk::ALIGN_START);
+ username->show();
+ username->get_style_context()->add_class("username-list-username");
+ leftPanelUsers.attach(*username, 0, 1 + users.size(), 1, 1);
+ users.push_back(new User { userPublicKey, "NoName" });
+ fprintf(stderr, "Added user %s\n", userPublicKey.toString().c_str());
+ }
+
+ void ChatWindow::setUserNickname(const odhtdb::Signature::PublicKey &userPublicKey, const Glib::ustring &name)
+ {
+ for(size_t i = 0; i < users.size(); ++i)
+ {
+ User *user = users[i];
+ if(user->publicKey == userPublicKey)
+ {
+ user->name = name;
+ Gtk::Widget *usernameLabel = leftPanelUsers.get_child_at(0, 1 + i);
+ assert(usernameLabel);
+ //assert(usernameLabel->get_type() == Gtk::Label::get_type());
+ static_cast<Gtk::Label*>(usernameLabel)->set_text(name);
+ fprintf(stderr, "Set nickname for user %s to %s\n", userPublicKey.toString().c_str(), name.c_str());
+ return;
+ }
+ }
+ fprintf(stderr, "ChatWindow::setUserNickname: user %s doesn't exist\n", userPublicKey.toString().c_str());
+ }
+
+ User* ChatWindow::getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey) const
+ {
+ for(User *user : users)
+ {
+ if(user->publicKey == publicKey)
+ {
+ return user;
+ }
+ }
+ return nullptr;
+ }
} \ No newline at end of file
diff --git a/src/Window.cpp b/src/Window.cpp
index 38c187e..72a3d9d 100644
--- a/src/Window.cpp
+++ b/src/Window.cpp
@@ -2,6 +2,7 @@
#include "../include/Cache.hpp"
#include "../include/ChannelDataType.hpp"
#include "../include/WindowNotification.hpp"
+#include <sibs/SafeDeserializer.hpp>
namespace dchat
{
@@ -11,6 +12,7 @@ namespace dchat
Gtk::Overlay *overlay = Gtk::manage(new Gtk::Overlay());
WindowNotification *windowNotification = Gtk::manage(new WindowNotification());
overlay->add_overlay(*windowNotification);
+ overlay->set_overlay_pass_through(*windowNotification);
overlay->add(stack);
add(*overlay);
@@ -54,6 +56,7 @@ namespace dchat
{
std::lock_guard<std::mutex> lock(databaseCallbackMutex);
chatWindow.addChannel(*request.nodeHash);
+ chatWindow.addUser(*request.creatorPublicKey);
};
callbackFuncs.addNodeCallbackFunc = [this](const odhtdb::DatabaseAddNodeRequest &request)
@@ -63,22 +66,44 @@ namespace dchat
return;
ChannelDataType channelDataType = (ChannelDataType)static_cast<const char*>(request.decryptedData.data)[0];
- switch(channelDataType)
+ try
{
- case ChannelDataType::ADD_MESSAGE:
+ switch(channelDataType)
{
- Glib::ustring msg((const char*)request.decryptedData.data + 1, request.decryptedData.size - 1);
- chatWindow.addLocalMessage(*request.nodeHash, std::move(msg));
- break;
+ case ChannelDataType::ADD_MESSAGE:
+ {
+ Glib::ustring msg((const char*)request.decryptedData.data + 1, request.decryptedData.size - 1);
+ uint32_t timestampSeconds = ntp::NtpTimestamp::fromCombined(request.timestamp).seconds;
+ chatWindow.addLocalMessage(*request.nodeHash, *request.creatorPublicKey, timestampSeconds, std::move(msg));
+ break;
+ }
+ case ChannelDataType::NICKNAME_CHANGE:
+ {
+ sibs::SafeDeserializer deserializer((const u8*)request.decryptedData.data + 1, request.decryptedData.size - 1);
+ u8 nameLength = deserializer.extract<u8>();
+ if(nameLength > 0)
+ {
+ std::string nickname;
+ nickname.resize(nameLength);
+ deserializer.extract((u8*)&nickname[0], nameLength);
+ chatWindow.setUserNickname(*request.creatorPublicKey, nickname);
+ }
+ break;
+ }
+ default:
+ break;
}
- default:
- break;
+ }
+ catch(std::exception &e)
+ {
+ fprintf(stderr, "Failed to process add node request, reason: %s\n", e.what());
}
};
callbackFuncs.addUserCallbackFunc = [this](const odhtdb::DatabaseAddUserRequest &request)
{
std::lock_guard<std::mutex> lock(databaseCallbackMutex);
+ chatWindow.addUser(*request.userToAddPublicKey);
};
fprintf(stderr, "Connecting...\n");