aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChatMessage.cpp5
-rw-r--r--src/ChatWindow.cpp121
-rw-r--r--src/Window.cpp107
3 files changed, 108 insertions, 125 deletions
diff --git a/src/ChatMessage.cpp b/src/ChatMessage.cpp
index 93b52e9..d48a6a9 100644
--- a/src/ChatMessage.cpp
+++ b/src/ChatMessage.cpp
@@ -4,11 +4,10 @@
namespace dchat
{
- ChatMessage::ChatMessage(const Glib::ustring &_username, const Glib::ustring &_text, uint32_t _timestampSeconds, const User *_user) :
+ ChatMessage::ChatMessage(const Glib::ustring &_username, const Glib::ustring &_text, uint32_t _timestampSeconds) :
username(_username),
text(_text),
- timestampSeconds(_timestampSeconds),
- user(_user)
+ timestampSeconds(_timestampSeconds)
{
avatar.set_halign(Gtk::ALIGN_START);
avatar.set_valign(Gtk::ALIGN_START);
diff --git a/src/ChatWindow.cpp b/src/ChatWindow.cpp
index 041d2c3..98c4269 100644
--- a/src/ChatWindow.cpp
+++ b/src/ChatWindow.cpp
@@ -3,6 +3,7 @@
#include <gtkmm/alignment.h>
#include <gtkmm/viewport.h>
#include <gtkmm/scrollbar.h>
+#include <gtkmm/eventbox.h>
#include <cassert>
namespace dchat
@@ -11,8 +12,7 @@ namespace dchat
const int MERGE_MESSAGE_TIMESTAMP_DIFF_SEC = 60;
ChatWindow::ChatWindow() :
- channelCount(0),
- lastMessage(nullptr)
+ roomCount(0)
{
setupTopBar();
@@ -107,9 +107,20 @@ namespace dchat
chatInput.set_hexpand(true);
chatInput.set_name("chat-input");
chatInput.set_wrap_mode(Gtk::WrapMode::WRAP_WORD_CHAR);
+ chatScrollWindow->add(chatInput);
double fontSize = 18.5;//PANGO_PIXELS(chatInput.get_style_context()->get_font().get_size());
chatPrevNumLines = 1;
+ chatInput.signal_key_press_event().connect([this](GdkEventKey *event)
+ {
+ if((event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) && !(event->state & Gdk::SHIFT_MASK))
+ {
+ currentRoom->publishMessage(chatInput.get_buffer()->get_text());
+ chatInput.get_buffer()->set_text("");
+ return true;
+ }
+ return false;
+ }, false);
chatInput.get_buffer()->signal_changed().connect([this, chatScrollWindow, fontSize]
{
int numLines = chatInput.get_buffer()->get_line_count();
@@ -144,100 +155,90 @@ namespace dchat
chatScrollWindow->set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_ALWAYS);
}
});
- chatScrollWindow->add(chatInput);
}
- void ChatWindow::addChannel(const odhtdb::Hash &nodeHash)
+ void ChatWindow::addRoom(std::shared_ptr<Room> room)
{
- assert(channelDataById.find(nodeHash) == channelDataById.end());
- fprintf(stderr, "Added channel %s\n", nodeHash.toString().c_str());
+ fprintf(stderr, "Added channel %s\n", room->id->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);
channelButton->show();
- leftPanelChannels.attach(*channelButton, 0, 1 + channelCount, 1, 1);
- ++channelCount;
- channelDataById[nodeHash] = { channelButton, 0 };
+ leftPanelChannels.attach(*channelButton, 0, 1 + roomCount, 1, 1);
+ ++roomCount;
+ roomDataById[*room->id] = { channelButton };
+ currentRoom = room;
}
- void ChatWindow::addLocalMessage(const odhtdb::Hash &channelId, const odhtdb::Signature::PublicKey &userPublicKey, uint32_t timestampSeconds, Glib::ustring msg)
+ void ChatWindow::addMessage(const RoomAddMessageRequest &request)
{
- auto it = channelDataById.find(channelId);
- assert(it != channelDataById.end());
- 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;
- }
+ auto roomMessages = request.room->messages;
+ RoomMessage *lastMessage = nullptr;
+ if(!roomMessages.empty())
+ lastMessage = &roomMessages.back();
- if(lastMessage && lastMessage->user->publicKey == userPublicKey)
+ if(lastMessage && lastMessage->creator->publicKey == request.message.creator->publicKey)
{
- int64_t msgTimeDiff = (int64_t)timestampSeconds - (int64_t)lastMessage->timestampSeconds;
+ int64_t msgTimeDiff = (int64_t)request.message.timestampSeconds - (int64_t)lastMessage->timestampSeconds;
if(msgTimeDiff <= MERGE_MESSAGE_TIMESTAMP_DIFF_SEC)
{
- lastMessage->text.set_text(lastMessage->text.get_text() + "\n" + msg);
+ auto message = messageById[lastMessage->id];
+ message->text.set_text(message->text.get_text() + "\n" + request.message.text);
+ // Since messages that are sent withing a timeframe are combined, several message ids can refer to the same message
+ messageById[request.message.id] = message;
+ if(*request.room->id == *currentRoom->id)
+ {
+ auto adj = messageArea.get_vadjustment();
+ adj->set_value(adj->get_upper());
+ messageAreaLayout.queue_draw();
+ while(gtk_events_pending())
+ gtk_main_iteration_do(FALSE);
+ }
return;
}
}
- ChatMessage *message = Gtk::manage(new ChatMessage(user->name, msg, timestampSeconds, user));
- lastMessage = message;
+ ChatMessage *message = Gtk::manage(new ChatMessage(request.message.creator->nickname, request.message.text, request.message.timestampSeconds));
message->set_valign(Gtk::Align::ALIGN_START);
message->set_hexpand(true);
message->show_all();
- messageAreaLayout.attach(*message, 0, it->second.messageCount, 1, 1);
- ++it->second.messageCount;
- }
+ messageById[request.message.id] = message;
+ messageAreaLayout.attach(*message, 0, roomMessages.size(), 1, 1);
- void ChatWindow::addUser(const odhtdb::Signature::PublicKey &userPublicKey)
- {
- User *existingUser = getUserByPublicKey(userPublicKey);
- if(existingUser)
+ // TODO: When we get a message in the current room we scroll to the bottom, but this should only be done if we are not manually scrolling to view old messages
+ if(*request.room->id == *currentRoom->id)
{
- fprintf(stderr, "ChatWindow::addUser: user %s was not added because the user has already been added\n", userPublicKey.toString().c_str());
- return;
+ auto adj = messageArea.get_vadjustment();
+ adj->set_value(adj->get_upper());
+ messageAreaLayout.queue_draw();
+ while(gtk_events_pending())
+ gtk_main_iteration_do(FALSE);
}
+ }
+ void ChatWindow::addUser(std::shared_ptr<Room> room, std::shared_ptr<User> user)
+ {
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());
+ user->userdata = username;
+ leftPanelUsers.attach(*username, 0, room->userByPublicKey.size(), 1, 1);
+ fprintf(stderr, "Added user %s\n", user->publicKey.toString().c_str());
}
- void ChatWindow::setUserNickname(const odhtdb::Signature::PublicKey &userPublicKey, const Glib::ustring &name)
+ void ChatWindow::setUserNickname(const UserChangeNicknameRequest &request)
{
- 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());
+ Gtk::Label *userNicknameLabel = (Gtk::Label*)request.user->userdata;
+ userNicknameLabel->set_text(request.newNickname);
+ fprintf(stderr, "Set nickname for user %s to %s\n", request.user->publicKey.toString().c_str(), request.newNickname.c_str());
}
- User* ChatWindow::getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey) const
+ void ChatWindow::scrollToBottom()
{
- for(User *user : users)
- {
- if(user->publicKey == publicKey)
- {
- return user;
- }
- }
- return nullptr;
+ auto adj = messageArea.get_vadjustment();
+ adj->set_value(adj->get_upper());
}
} \ No newline at end of file
diff --git a/src/Window.cpp b/src/Window.cpp
index 6a0ab64..b9e1490 100644
--- a/src/Window.cpp
+++ b/src/Window.cpp
@@ -1,15 +1,16 @@
#include "../include/Window.hpp"
-#include "../include/ChannelDataType.hpp"
+#include <dchat/RoomDataType.hpp>
#include "../include/WindowNotification.hpp"
#include <dchat/Cache.hpp>
#include <sibs/SafeDeserializer.hpp>
#include <math.h>
#include <chrono>
+#include <gtkmm.h>
namespace dchat
{
- const int nodesPerColumn = 5;
- const int nodesPerRow = 5;
+ const int nodesPerColumn = 10;
+ const int nodesPerRow = 10;
Window::Window()
{
@@ -28,12 +29,12 @@ namespace dchat
overlay.show();
windowNotification->show_all();
stack.show();
- chatWindow.show_all();
- loginWindow.show();
+ //chatWindow.show_all();
+ //loginWindow.show();
loginWindow.setLoginHandler([this, windowNotification](const Glib::ustring &username, const Glib::ustring &password)
{
- if(!database)
+ if(!rooms || !rooms->database)
{
windowNotification->show("You are not connected to the bootstrap node yet! please wait...");
return;
@@ -42,15 +43,18 @@ namespace dchat
try
{
fprintf(stderr, "Trying to login with username %s\n", username.raw().c_str());
- auto storedNodes = database->getStoredNodeUserInfoDecrypted(username.raw(), password.raw());
+ rooms->loginUser(username.raw(), password.raw());
windowNotification->show(Glib::ustring("Successfully logged in as ") + username);
drawBackgroundConnection.disconnect();
+ chatWindow.show_all();
stack.set_visible_child(chatWindow);
- for(auto &nodeInfo : storedNodes)
+ Glib::signal_timeout().connect([this]
{
- database->loadNode(nodeInfo.first);
- }
+ printf("scroll to bottom!\n");
+ chatWindow.scrollToBottom();
+ return false;
+ }, 100);
}
catch(std::exception &e)
{
@@ -62,7 +66,7 @@ namespace dchat
loginWindow.setRegisterHandler([this, windowNotification](const Glib::ustring &username, const Glib::ustring &password)
{
- if(!database)
+ if(!rooms || !rooms->database)
{
windowNotification->show("You are not connected to the bootstrap node yet! please wait...");
return;
@@ -71,9 +75,10 @@ namespace dchat
try
{
fprintf(stderr, "Trying to register username %s\n", username.raw().c_str());
- database->storeUserWithoutNodes(username.raw(), password.raw());
+ rooms->registerUser(username.raw(), password.raw());
windowNotification->show(Glib::ustring("Successfully registered user ") + username);
drawBackgroundConnection.disconnect();
+ chatWindow.show_all();
stack.set_visible_child(chatWindow);
}
catch(std::exception &e)
@@ -91,65 +96,43 @@ namespace dchat
windowNotification->show("Passwords do not match");
});
- odhtdb::DatabaseCallbackFuncs callbackFuncs;
- callbackFuncs.createNodeCallbackFunc = [this](const odhtdb::DatabaseCreateNodeRequest &request)
+ RoomCallbackFuncs roomCallbackFuncs;
+ roomCallbackFuncs.connectCallbackFunc = [this, windowNotification](std::shared_ptr<Rooms> rooms, const char *errMsg)
{
- std::lock_guard<std::mutex> lock(databaseCallbackMutex);
- chatWindow.addChannel(*request.nodeHash);
- chatWindow.addUser(*request.creatorPublicKey);
- };
-
- callbackFuncs.addNodeCallbackFunc = [this](const odhtdb::DatabaseAddNodeRequest &request)
- {
- std::lock_guard<std::mutex> lock(databaseCallbackMutex);
- if(request.decryptedData.size == 0)
- return;
-
- ChannelDataType channelDataType = (ChannelDataType)static_cast<const char*>(request.decryptedData.data)[0];
- try
+ this->rooms = rooms;
+ if(rooms)
{
- switch(channelDataType)
- {
- 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;
- }
+ loginWindow.show();
+ stack.set_visible_child(loginWindow);
+ windowNotification->show("Connected to 83.252.53.188:27130");
+ loginWindow.loginUsernameInput.grab_focus();
}
- catch(std::exception &e)
+ else
{
- fprintf(stderr, "Failed to process add node request, reason: %s\n", e.what());
+ std::string errMsgToShow = "Failed to connect to boostrap node, reason: ";
+ errMsgToShow += errMsg;
+ windowNotification->show(errMsgToShow);
}
};
-
- callbackFuncs.addUserCallbackFunc = [this](const odhtdb::DatabaseAddUserRequest &request)
+ roomCallbackFuncs.createRoomCallbackFunc = [this](std::shared_ptr<Room> room)
+ {
+ chatWindow.addRoom(room);
+ };
+ roomCallbackFuncs.addUserCallbackFunc = [this](std::shared_ptr<Room> room, std::shared_ptr<User> user)
+ {
+ chatWindow.addUser(room, user);
+ };
+ roomCallbackFuncs.addMessageCallbackFunc = [this](const RoomAddMessageRequest &request)
+ {
+ chatWindow.addMessage(request);
+ };
+ roomCallbackFuncs.userChangeNicknameCallbackFunc = [this](const UserChangeNicknameRequest &request)
{
- std::lock_guard<std::mutex> lock(databaseCallbackMutex);
- chatWindow.addUser(*request.userToAddPublicKey);
+ chatWindow.setUserNickname(request);
};
- fprintf(stderr, "Connecting...\n");
- database = odhtdb::Database::connect("83.252.53.188", 27130, Cache::getDchatDir(), callbackFuncs).get();
- stack.set_visible_child(loginWindow);
- windowNotification->show("Connected to 83.252.53.188:27130");
+ windowNotification->show("Connecting to 83.252.53.188:27130");
+ Rooms::connect("83.252.53.188", 27130, roomCallbackFuncs);
backgroundRng.seed(std::random_device()());
std::uniform_int_distribution<std::mt19937::result_type> sizeDeviationRand(0, 5);