aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------depends/dchat_core0
-rw-r--r--include/ChannelDataType.hpp16
-rw-r--r--include/ChatMessage.hpp3
-rw-r--r--include/ChatWindow.hpp26
-rw-r--r--include/LoginWindow.hpp2
-rw-r--r--include/User.hpp13
-rw-r--r--include/Window.hpp4
-rw-r--r--src/ChatMessage.cpp5
-rw-r--r--src/ChatWindow.cpp121
-rw-r--r--src/Window.cpp107
10 files changed, 123 insertions, 174 deletions
diff --git a/depends/dchat_core b/depends/dchat_core
-Subproject 699811dbcc8194c95ffe7874ac8d2fb97e03941
+Subproject 391e0cb6a667fa384d61a9ef7909482d2e1bbb5
diff --git a/include/ChannelDataType.hpp b/include/ChannelDataType.hpp
deleted file mode 100644
index 21e828d..0000000
--- a/include/ChannelDataType.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#include <dchat/types.hpp>
-
-namespace dchat
-{
- enum class ChannelDataType : u8
- {
- ADD_MESSAGE,
- EDIT_MESSAGE,
- DELETE_MESSAGE,
- NICKNAME_CHANGE,
- CHANGE_AVATAR,
- CHANGE_CHANNEL_NAME,
- };
-} \ No newline at end of file
diff --git a/include/ChatMessage.hpp b/include/ChatMessage.hpp
index c13db9d..c1ef459 100644
--- a/include/ChatMessage.hpp
+++ b/include/ChatMessage.hpp
@@ -10,13 +10,12 @@ namespace dchat
class ChatMessage : public Gtk::Grid
{
public:
- ChatMessage(const Glib::ustring &username, const Glib::ustring &text, uint32_t timestampSeconds, const User *user);
+ ChatMessage(const Glib::ustring &username, const Glib::ustring &text, uint32_t timestampSeconds);
Gtk::Grid avatar;
Gtk::Label username;
Gtk::Label text;
uint32_t timestampSeconds;
- const User *user;
private:
bool updateContent(const Cairo::RefPtr<Cairo::Context> &cairo);
};
diff --git a/include/ChatWindow.hpp b/include/ChatWindow.hpp
index 0b58506..988b225 100644
--- a/include/ChatWindow.hpp
+++ b/include/ChatWindow.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "User.hpp"
+#include <dchat/Room.hpp>
#include <gtkmm/label.h>
#include <gtkmm/togglebutton.h>
#include <gtkmm/grid.h>
@@ -20,13 +20,11 @@ namespace dchat
{
public:
ChatWindow();
- void addChannel(const odhtdb::Hash &nodeHash);
- void addLocalMessage(const odhtdb::Hash &channelId, const odhtdb::Signature::PublicKey &userPublicKey, uint32_t timestampSeconds, Glib::ustring msg);
- void addUser(const odhtdb::Signature::PublicKey &userPublicKey);
- void setUserNickname(const odhtdb::Signature::PublicKey &userPublicKey, const Glib::ustring &name);
-
- // Returns nullptr if user with @publicKey is not found
- User* getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey) const;
+ void addRoom(std::shared_ptr<Room> room);
+ void addMessage(const RoomAddMessageRequest &request);
+ void addUser(std::shared_ptr<Room> room, std::shared_ptr<User> user);
+ void setUserNickname(const UserChangeNicknameRequest &request);
+ void scrollToBottom();
private:
void setupTopBar();
void setupLeftPanel(Gtk::Paned *sidePanels);
@@ -42,17 +40,15 @@ namespace dchat
Gtk::Grid messageAreaLayout;
Gtk::TextView chatInput;
- struct ChannelData
+ struct RoomData
{
Gtk::ToggleButton *button;
- int messageCount;
};
- odhtdb::MapHash<ChannelData> channelDataById;
- int channelCount;
- std::vector<User*> users;
-
- ChatMessage *lastMessage;
+ odhtdb::MapHash<RoomData> roomDataById;
+ odhtdb::MapHash<ChatMessage*> messageById;
int chatPrevNumLines;
+ int roomCount;
+ std::shared_ptr<Room> currentRoom;
};
} \ No newline at end of file
diff --git a/include/LoginWindow.hpp b/include/LoginWindow.hpp
index ea9b905..d5585a5 100644
--- a/include/LoginWindow.hpp
+++ b/include/LoginWindow.hpp
@@ -22,7 +22,7 @@ namespace dchat
private:
void setupLogin();
void setupRegister();
- private:
+ public:
Gtk::Grid loginLayout;
Gtk::Entry loginUsernameInput;
Gtk::Entry loginPasswordInput;
diff --git a/include/User.hpp b/include/User.hpp
deleted file mode 100644
index 471a5cc..0000000
--- a/include/User.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include <glibmm/ustring.h>
-#include <odhtdb/Signature.hpp>
-
-namespace dchat
-{
- struct User
- {
- const odhtdb::Signature::PublicKey publicKey;
- Glib::ustring name;
- };
-} \ No newline at end of file
diff --git a/include/Window.hpp b/include/Window.hpp
index 4c67a68..a29ec62 100644
--- a/include/Window.hpp
+++ b/include/Window.hpp
@@ -5,7 +5,7 @@
#include <gtkmm/window.h>
#include <gtkmm/stack.h>
#include <gtkmm/overlay.h>
-#include <odhtdb/Database.hpp>
+#include <dchat/Room.hpp>
#include <mutex>
#include <random>
#include <vector>
@@ -26,7 +26,7 @@ namespace dchat
void draw(const Cairo::RefPtr<Cairo::Context> &cairo) { Gtk::Overlay::draw(cairo); }
};
- std::unique_ptr<odhtdb::Database> database;
+ std::shared_ptr<Rooms> rooms;
std::mutex databaseCallbackMutex;
OverlayDrawable overlay;
Gtk::Stack stack;
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);