aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--css/style.css4
-rw-r--r--include/Cache.hpp16
-rw-r--r--include/ChannelDataType.hpp16
-rw-r--r--include/ChatWindow.hpp15
-rw-r--r--include/LoginWindow.hpp6
-rw-r--r--include/Window.hpp24
-rw-r--r--include/env.hpp59
-rw-r--r--include/types.hpp22
-rw-r--r--src/Cache.cpp63
-rw-r--r--src/ChatWindow.cpp52
-rw-r--r--src/LoginWindow.cpp16
-rw-r--r--src/Window.cpp63
-rw-r--r--src/main.cpp33
13 files changed, 329 insertions, 60 deletions
diff --git a/css/style.css b/css/style.css
index d07b4c4..bcafa69 100644
--- a/css/style.css
+++ b/css/style.css
@@ -54,6 +54,10 @@ button {
font-size: 16px;
}
+.channel-button {
+ background-color: transparent;
+}
+
#users-title {
color: #f7f7f7;
font-weight: bold;
diff --git a/include/Cache.hpp b/include/Cache.hpp
new file mode 100644
index 0000000..97ef495
--- /dev/null
+++ b/include/Cache.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <boost/filesystem/path.hpp>
+
+namespace dchat
+{
+ class Cache
+ {
+ public:
+ Cache();
+ ~Cache();
+
+ // Creates directory if it doesn't exist (recursively). Throws boost exception on failure
+ static boost::filesystem::path getDchatDir();
+ };
+}
diff --git a/include/ChannelDataType.hpp b/include/ChannelDataType.hpp
new file mode 100644
index 0000000..398e716
--- /dev/null
+++ b/include/ChannelDataType.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "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/ChatWindow.hpp b/include/ChatWindow.hpp
index 2d45b76..b13046e 100644
--- a/include/ChatWindow.hpp
+++ b/include/ChatWindow.hpp
@@ -1,12 +1,14 @@
#pragma once
#include <gtkmm/label.h>
+#include <gtkmm/button.h>
#include <gtkmm/grid.h>
#include <gtkmm/entry.h>
#include <gtkmm/paned.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/stack.h>
#include <gtkmm/textview.h>
+#include <odhtdb/Hash.hpp>
namespace dchat
{
@@ -14,6 +16,8 @@ namespace dchat
{
public:
ChatWindow();
+ void addChannel(const odhtdb::Hash &nodeHash);
+ void addLocalMessage(const odhtdb::Hash &channelId, Glib::ustring msg);
private:
void setupTopBar();
void setupLeftPanel(Gtk::Paned *sidePanels);
@@ -22,8 +26,19 @@ namespace dchat
private:
Gtk::Grid topbar;
Gtk::Entry topbarSearchBar;
+ Gtk::Grid leftPanelChannels;
Gtk::Label currentChannelTitle;
Gtk::ScrolledWindow chatArea;
+ Gtk::Grid chatAreaLayout;
Gtk::TextView chatInput;
+
+ struct ChannelData
+ {
+ Gtk::Button *button;
+ int messageCount;
+ };
+
+ odhtdb::MapHash<ChannelData> channelDataById;
+ int channelCount;
};
} \ No newline at end of file
diff --git a/include/LoginWindow.hpp b/include/LoginWindow.hpp
index b60dddb..b842eb5 100644
--- a/include/LoginWindow.hpp
+++ b/include/LoginWindow.hpp
@@ -7,15 +7,19 @@
namespace dchat
{
+ using LoginHandler = std::function<void(const Glib::ustring &username, const Glib::ustring &password)>;
+
class LoginWindow : public Gtk::Grid
{
public:
LoginWindow();
- void setLoginHandler(std::function<void()> loginHandler);
+ void setLoginHandler(LoginHandler loginHandler);
private:
Gtk::Entry usernameInput;
Gtk::Entry passwordInput;
Gtk::Button loginButton;
+ std::function<void()> loginHandler;
+ LoginHandler loginHandlerUser;
};
} \ No newline at end of file
diff --git a/include/Window.hpp b/include/Window.hpp
index 2810bbd..96197c6 100644
--- a/include/Window.hpp
+++ b/include/Window.hpp
@@ -4,17 +4,21 @@
#include "LoginWindow.hpp"
#include <gtkmm/window.h>
#include <gtkmm/stack.h>
+#include <odhtdb/Database.hpp>
+#include <mutex>
namespace dchat
{
- class Window : public Gtk::Window
- {
- public:
- Window();
- virtual ~Window();
- protected:
- Gtk::Stack stack;
- LoginWindow loginWindow;
- ChatWindow chatWindow;
- };
+ class Window : public Gtk::Window
+ {
+ public:
+ Window();
+ virtual ~Window();
+ protected:
+ std::unique_ptr<odhtdb::Database> database;
+ std::mutex databaseCallbackMutex;
+ Gtk::Stack stack;
+ LoginWindow loginWindow;
+ ChatWindow chatWindow;
+ };
} \ No newline at end of file
diff --git a/include/env.hpp b/include/env.hpp
new file mode 100644
index 0000000..abaedd8
--- /dev/null
+++ b/include/env.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#define OS_FAMILY_WINDOWS 0
+#define OS_FAMILY_POSIX 1
+
+#define OS_TYPE_WINDOWS 0
+#define OS_TYPE_LINUX 1
+
+#if defined(_WIN32) || defined(_WIN64)
+ #if defined(_WIN64)
+ #define SYS_ENV_64BIT
+ #else
+ #define SYS_ENV_32BIT
+ #endif
+ #define OS_FAMILY OS_FAMILY_WINDOWS
+ #define OS_TYPE OS_TYPE_WINDOWS
+
+ #ifndef UNICODE
+ #define UNICODE
+ #endif
+
+ #ifndef _UNICODE
+ #define _UNICODE
+ #endif
+
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+
+ #include <Windows.h>
+#endif
+
+#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(_POSIX_VERSION)
+ #define OS_FAMILY OS_FAMILY_POSIX
+#endif
+
+#ifdef __linux__
+ #define OS_TYPE OS_TYPE_LINUX
+#endif
+
+#if defined(__GNUC__)
+ #if defined(__x86_64__) || defined(__pc64__)
+ #define SYS_ENV_64BIT
+ #else
+ #define SYS_ENV_32BIT
+ #endif
+#endif
+
+#if !defined(SYS_ENV_32BIT) && !defined(SYS_ENV_64BIT)
+ #error "System is not detected as either 32-bit or 64-bit"
+#endif
+
+#if !defined(OS_FAMILY)
+ #error "System not supported. Only Windows and Posix systems supported right now"
+#endif
+
+#if !defined(OS_TYPE)
+ #error "System not supported. Only Windows and linux systems supported right now"
+#endif
diff --git a/include/types.hpp b/include/types.hpp
new file mode 100644
index 0000000..762dab1
--- /dev/null
+++ b/include/types.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <cstdint>
+
+namespace dchat
+{
+ typedef int8_t i8;
+ typedef int16_t i16;
+ typedef int32_t i32;
+ typedef int64_t i64;
+
+ typedef uint8_t u8;
+ typedef uint16_t u16;
+ typedef uint32_t u32;
+ typedef uint64_t u64;
+
+ typedef float f32;
+ typedef double f64;
+
+ typedef intptr_t ssize;
+ typedef uintptr_t usize;
+}
diff --git a/src/Cache.cpp b/src/Cache.cpp
new file mode 100644
index 0000000..d4c19fb
--- /dev/null
+++ b/src/Cache.cpp
@@ -0,0 +1,63 @@
+#include "../include/Cache.hpp"
+#include "../include/env.hpp"
+#include <boost/filesystem/convenience.hpp>
+
+#if OS_FAMILY == OS_FAMILY_POSIX
+#include <pwd.h>
+#else
+#include <string>
+#endif
+
+using namespace std;
+
+namespace dchat
+{
+ static boost::filesystem::path getHomeDir()
+ {
+ #if OS_FAMILY == OS_FAMILY_POSIX
+ const char *homeDir = getenv("HOME");
+ if(!homeDir)
+ {
+ passwd *pw = getpwuid(getuid());
+ homeDir = pw->pw_dir;
+ }
+ return boost::filesystem::path(homeDir);
+ #elif OS_FAMILY == OS_FAMILY_WINDOWS
+ BOOL ret;
+ HANDLE hToken;
+ std::wstring homeDir;
+ DWORD homeDirLen = MAX_PATH;
+ homeDir.resize(homeDirLen);
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
+ return Result<FileString>::Err("Failed to open process token");
+
+ if (!GetUserProfileDirectory(hToken, &homeDir[0], &homeDirLen))
+ {
+ CloseHandle(hToken);
+ return Result<FileString>::Err("Failed to get home directory");
+ }
+
+ CloseHandle(hToken);
+ homeDir.resize(wcslen(homeDir.c_str()));
+ return boost::filesystem::path(homeDir);
+ #endif
+ }
+
+ Cache::Cache()
+ {
+
+ }
+
+ Cache::~Cache()
+ {
+
+ }
+
+ boost::filesystem::path Cache::getDchatDir()
+ {
+ boost::filesystem::path dchatHomeDir = getHomeDir() / ".local" / "share" / "dchat";
+ boost::filesystem::create_directories(dchatHomeDir);
+ return dchatHomeDir;
+ }
+}
diff --git a/src/ChatWindow.cpp b/src/ChatWindow.cpp
index a428d0b..70dd734 100644
--- a/src/ChatWindow.cpp
+++ b/src/ChatWindow.cpp
@@ -1,10 +1,12 @@
#include "../include/ChatWindow.hpp"
#include "../include/ChatMessage.hpp"
#include <gtkmm/alignment.h>
+#include <cassert>
namespace dchat
{
- ChatWindow::ChatWindow()
+ ChatWindow::ChatWindow() :
+ channelCount(0)
{
setupTopBar();
@@ -54,14 +56,14 @@ namespace dchat
leftPanel->set_vexpand(true);
sidePanels->add1(*leftPanel);
- Gtk::Grid *leftPanelChannels = Gtk::manage(new Gtk::Grid());
- leftPanelChannels->set_vexpand(true);
- leftPanel->add1(*leftPanelChannels);
+ leftPanelChannels.set_vexpand(true);
+ leftPanel->add1(leftPanelChannels);
Gtk::Label *channelsTitle = Gtk::manage(new Gtk::Label());
channelsTitle->set_name("channels-title");
channelsTitle->set_text("Channels");
- leftPanelChannels->attach(*channelsTitle, 0, 0, 1, 1);
+ channelsTitle->set_halign(Gtk::ALIGN_START);
+ leftPanelChannels.attach(*channelsTitle, 0, 0, 1, 1);
////
Gtk::Grid *leftPanelUsers = Gtk::manage(new Gtk::Grid());
@@ -71,6 +73,7 @@ namespace dchat
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);
}
@@ -79,17 +82,8 @@ namespace dchat
chatArea.set_vexpand(true);
rightPanel->attach(chatArea, 0, 0, 1, 2);
- Gtk::Grid *chatAreaLayout = Gtk::manage(new Gtk::Grid());
- chatAreaLayout->set_name("chat-area-layout");
- chatArea.add(*chatAreaLayout);
-
- for(int i = 0; i < 100; ++i)
- {
- ChatMessage *message = Gtk::manage(new ChatMessage("Arezu", "hellooooo" + std::to_string(i)));
- message->set_valign(Gtk::Align::ALIGN_START);
- message->set_hexpand(true);
- chatAreaLayout->attach(*message, 0, i, 1, 1);
- }
+ chatAreaLayout.set_name("chat-area-layout");
+ chatArea.add(chatAreaLayout);
}
void ChatWindow::setupChatInput(Gtk::Grid *rightPanel)
@@ -103,4 +97,30 @@ namespace dchat
chatInput.set_wrap_mode(Gtk::WrapMode::WRAP_WORD_CHAR);
chatScrollWindow->add(chatInput);
}
+
+ 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"));
+ 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 };
+ }
+
+ void ChatWindow::addLocalMessage(const odhtdb::Hash &channelId, Glib::ustring msg)
+ {
+ auto it = channelDataById.find(channelId);
+ assert(it != channelDataById.end());
+ ChatMessage *message = Gtk::manage(new ChatMessage("Arezu", msg));
+ 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;
+ }
} \ No newline at end of file
diff --git a/src/LoginWindow.cpp b/src/LoginWindow.cpp
index 4232982..5dfbed6 100644
--- a/src/LoginWindow.cpp
+++ b/src/LoginWindow.cpp
@@ -10,12 +10,19 @@ namespace dchat
LoginWindow::LoginWindow() :
loginButton("Login")
{
+ loginHandler = [this]
+ {
+ if(loginHandlerUser)
+ loginHandlerUser(usernameInput.get_text(), passwordInput.get_text());
+ };
+
Gtk::Label *username = Gtk::manage(new Gtk::Label());
username->set_text("Username");
username->set_halign(Gtk::ALIGN_START);
attach(*username, 0, 0, 1, 1);
usernameInput.set_size_request(200);
+ usernameInput.signal_activate().connect(loginHandler);
attach_next_to(usernameInput, *username, Gtk::POS_BOTTOM, 3, 1);
Gtk::Alignment *usernamePasswordSpacer = Gtk::manage(new Gtk::Alignment());
@@ -29,6 +36,7 @@ namespace dchat
passwordInput.set_visibility(false);
passwordInput.set_size_request(200);
+ passwordInput.signal_activate().connect(loginHandler);
attach_next_to(passwordInput, *password, Gtk::POS_BOTTOM, 3, 1);
Gtk::Alignment *loginButtonSpacerTop = Gtk::manage(new Gtk::Alignment());
@@ -39,6 +47,7 @@ namespace dchat
attach_next_to(*loginButtonSpacer, *loginButtonSpacerTop, Gtk::POS_BOTTOM, 2, 1);
loginButton.set_halign(Gtk::ALIGN_END);
+ loginButton.signal_clicked().connect(loginHandler);
attach_next_to(loginButton, *loginButtonSpacer, Gtk::POS_RIGHT, 1, 1);
set_halign(Gtk::ALIGN_CENTER);
@@ -46,11 +55,8 @@ namespace dchat
get_style_context()->add_class("login-window");
}
- void LoginWindow::setLoginHandler(std::function<void()> loginHandler)
+ void LoginWindow::setLoginHandler(LoginHandler loginHandler)
{
- assert(loginHandler);
- usernameInput.signal_activate().connect(loginHandler);
- passwordInput.signal_activate().connect(loginHandler);
- loginButton.signal_clicked().connect(loginHandler);
+ loginHandlerUser = loginHandler;
}
} \ No newline at end of file
diff --git a/src/Window.cpp b/src/Window.cpp
index c912130..5f27000 100644
--- a/src/Window.cpp
+++ b/src/Window.cpp
@@ -1,4 +1,6 @@
#include "../include/Window.hpp"
+#include "../include/Cache.hpp"
+#include "../include/ChannelDataType.hpp"
namespace dchat
{
@@ -12,10 +14,67 @@ namespace dchat
show_all_children();
- loginWindow.setLoginHandler([]
+ loginWindow.setLoginHandler([this](const Glib::ustring &username, const Glib::ustring &password)
{
- printf("login!\n");
+ if(!database)
+ {
+ fprintf(stderr, "You are not connected to the bootstrap node yet! please wait...\n");
+ return;
+ }
+
+ try
+ {
+ printf("Trying to login with username %s\n", username.raw().c_str());
+ auto storedNodes = database->getStoredNodeUserInfoDecrypted(username.raw(), password.raw());
+ printf("Successfully logged in as %s\n", username.raw().c_str());
+ stack.set_visible_child(chatWindow);
+
+ for(auto &nodeInfo : storedNodes)
+ {
+ database->loadNode(nodeInfo.first);
+ }
+ }
+ catch(std::exception &e)
+ {
+ fprintf(stderr, "Failed to login, reason: %s\n", e.what());
+ }
});
+
+ odhtdb::DatabaseCallbackFuncs callbackFuncs;
+ callbackFuncs.createNodeCallbackFunc = [this](const odhtdb::DatabaseCreateNodeRequest &request)
+ {
+ std::lock_guard<std::mutex> lock(databaseCallbackMutex);
+ chatWindow.addChannel(*request.nodeHash);
+ };
+
+ 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];
+ switch(channelDataType)
+ {
+ case ChannelDataType::ADD_MESSAGE:
+ {
+ Glib::ustring msg((const char*)request.decryptedData.data + 1, request.decryptedData.size - 1);
+ chatWindow.addLocalMessage(*request.nodeHash, std::move(msg));
+ break;
+ }
+ default:
+ break;
+ }
+ };
+
+ callbackFuncs.addUserCallbackFunc = [this](const odhtdb::DatabaseAddUserRequest &request)
+ {
+ std::lock_guard<std::mutex> lock(databaseCallbackMutex);
+ };
+
+ printf("Connecting...\n");
+ database = odhtdb::Database::connect("83.252.53.188", 27130, Cache::getDchatDir(), callbackFuncs).get();
+ stack.set_visible_child(loginWindow);
}
Window::~Window()
diff --git a/src/main.cpp b/src/main.cpp
index d83fd27..6c7dec6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,7 +1,6 @@
#include "../include/Window.hpp"
#include <gtkmm/application.h>
#include <gtkmm/cssprovider.h>
-#include <odhtdb/Database.hpp>
int main (int argc, char *argv[])
{
@@ -10,16 +9,16 @@ int main (int argc, char *argv[])
auto css = Gtk::CssProvider::create();
try
{
- if(!css->load_from_path("css/style.css"))
- {
- fprintf(stderr, "Failed to load css/style.css");
- return 1;
- }
+ if(!css->load_from_path("css/style.css"))
+ {
+ fprintf(stderr, "Failed to load css/style.css");
+ return 1;
+ }
}
catch(Gtk::CssProviderError &e)
{
- fprintf(stderr, "Failed to load css/style.css, error: %s\n", e.what().c_str());
- return 1;
+ fprintf(stderr, "Failed to load css/style.css, error: %s\n", e.what().c_str());
+ return 1;
}
dchat::Window window;
@@ -27,23 +26,5 @@ int main (int argc, char *argv[])
auto screen = Gdk::Screen::get_default();
ctx->add_provider_for_screen(screen, css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
- odhtdb::DatabaseCallbackFuncs callbackFuncs;
- callbackFuncs.createNodeCallbackFunc = [](const odhtdb::DatabaseCreateNodeRequest &request)
- {
-
- };
-
- callbackFuncs.addNodeCallbackFunc = [](const odhtdb::DatabaseAddNodeRequest &request)
- {
-
- };
-
- callbackFuncs.addUserCallbackFunc = [](const odhtdb::DatabaseAddUserRequest &request)
- {
-
- };
-
- //odhtdb::Database database("206.189.13.66", 27130, "/tmp/dchat_gtk", callbackFuncs);
-
return app->run(window);
}