diff options
-rw-r--r-- | css/style.css | 13 | ||||
-rw-r--r-- | include/LoginWindow.hpp | 21 | ||||
-rw-r--r-- | src/LoginWindow.cpp | 176 | ||||
-rw-r--r-- | src/Window.cpp | 40 |
4 files changed, 222 insertions, 28 deletions
diff --git a/css/style.css b/css/style.css index bb40474..5ea60be 100644 --- a/css/style.css +++ b/css/style.css @@ -25,12 +25,25 @@ button { text-shadow: 0px 0px 0px transparent; } +.confirm-button { + background-color: #3060d8; +} + menu { background-color: #36393e; color: #f7f7f7; border: 1px solid black; } +separator { + background-color: #444444; +} + +.separator-horizontal-margin { + margin-top: 10px; + margin-bottom: 10px; +} + .emoji { background-color: #36393e; color: #f7f7f7; diff --git a/include/LoginWindow.hpp b/include/LoginWindow.hpp index b842eb5..ea9b905 100644 --- a/include/LoginWindow.hpp +++ b/include/LoginWindow.hpp @@ -8,6 +8,8 @@ namespace dchat { using LoginHandler = std::function<void(const Glib::ustring &username, const Glib::ustring &password)>; + using RegisterHandler = std::function<void(const Glib::ustring &username, const Glib::ustring &password)>; + using RegisterPasswordMismatchHandler = std::function<void()>; class LoginWindow : public Gtk::Grid { @@ -15,11 +17,26 @@ namespace dchat LoginWindow(); void setLoginHandler(LoginHandler loginHandler); + void setRegisterHandler(RegisterHandler registerHandler); + void setRegisterPasswordMismatch(RegisterPasswordMismatchHandler passwordMismatchHandler); private: - Gtk::Entry usernameInput; - Gtk::Entry passwordInput; + void setupLogin(); + void setupRegister(); + private: + Gtk::Grid loginLayout; + Gtk::Entry loginUsernameInput; + Gtk::Entry loginPasswordInput; Gtk::Button loginButton; std::function<void()> loginHandler; LoginHandler loginHandlerUser; + + Gtk::Grid registerLayout; + Gtk::Entry registerUsernameInput; + Gtk::Entry registerPasswordInput; + Gtk::Entry registerPasswordRepeatInput; + Gtk::Button registerButton; + std::function<void()> registerHandler; + RegisterHandler registerHandlerUser; + RegisterPasswordMismatchHandler passwordMismatchHandler; }; }
\ No newline at end of file diff --git a/src/LoginWindow.cpp b/src/LoginWindow.cpp index 5dfbed6..33802f1 100644 --- a/src/LoginWindow.cpp +++ b/src/LoginWindow.cpp @@ -3,60 +3,188 @@ #include <gtkmm/entry.h> #include <gtkmm/alignment.h> #include <gtkmm/button.h> +#include <gtkmm/separator.h> +#include <gtkmm/eventbox.h> +#include <gdkmm/cursor.h> #include <cassert> namespace dchat { LoginWindow::LoginWindow() : - loginButton("Login") + loginButton("Login"), + loginHandlerUser(nullptr), + + registerButton("Register"), + registerHandlerUser(nullptr), + passwordMismatchHandler(nullptr) + { + setupLogin(); + setupRegister(); + + set_halign(Gtk::ALIGN_CENTER); + set_valign(Gtk::ALIGN_CENTER); + set_border_width(0); + attach(loginLayout, 0, 0, 1, 1); + attach(registerLayout, 0, 0, 1, 1); + loginLayout.show_all(); + } + + void LoginWindow::setLoginHandler(LoginHandler loginHandler) + { + loginHandlerUser = loginHandler; + } + + void LoginWindow::setRegisterHandler(RegisterHandler registerHandler) + { + registerHandlerUser = registerHandler; + } + + void LoginWindow::setRegisterPasswordMismatch(RegisterPasswordMismatchHandler passwordMismatchHandler) + { + this->passwordMismatchHandler = passwordMismatchHandler; + } + + void LoginWindow::setupLogin() { loginHandler = [this] { if(loginHandlerUser) - loginHandlerUser(usernameInput.get_text(), passwordInput.get_text()); + loginHandlerUser(loginUsernameInput.get_text(), loginPasswordInput.get_text()); }; - Gtk::Label *username = Gtk::manage(new Gtk::Label()); - username->set_text("Username"); + Gtk::Label *username = Gtk::manage(new Gtk::Label("Username")); username->set_halign(Gtk::ALIGN_START); - attach(*username, 0, 0, 1, 1); + loginLayout.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); + loginUsernameInput.set_size_request(200); + loginUsernameInput.signal_activate().connect(loginHandler); + loginLayout.attach_next_to(loginUsernameInput, *username, Gtk::POS_BOTTOM, 3, 1); Gtk::Alignment *usernamePasswordSpacer = Gtk::manage(new Gtk::Alignment()); usernamePasswordSpacer->set_size_request(-1, 35); - attach_next_to(*usernamePasswordSpacer, usernameInput, Gtk::POS_BOTTOM, 1, 1); + loginLayout.attach_next_to(*usernamePasswordSpacer, loginUsernameInput, Gtk::POS_BOTTOM, 1, 1); - Gtk::Label *password = Gtk::manage(new Gtk::Label()); - password->set_text("Password"); + Gtk::Label *password = Gtk::manage(new Gtk::Label("Password")); password->set_halign(Gtk::ALIGN_START); - attach_next_to(*password, *usernamePasswordSpacer, Gtk::POS_BOTTOM, 1, 1); + loginLayout.attach_next_to(*password, *usernamePasswordSpacer, Gtk::POS_BOTTOM, 1, 1); - passwordInput.set_visibility(false); - passwordInput.set_size_request(200); - passwordInput.signal_activate().connect(loginHandler); - attach_next_to(passwordInput, *password, Gtk::POS_BOTTOM, 3, 1); + loginPasswordInput.set_visibility(false); + loginPasswordInput.set_size_request(200); + loginPasswordInput.signal_activate().connect(loginHandler); + loginLayout.attach_next_to(loginPasswordInput, *password, Gtk::POS_BOTTOM, 3, 1); Gtk::Alignment *loginButtonSpacerTop = Gtk::manage(new Gtk::Alignment()); loginButtonSpacerTop->set_size_request(-1, 20); - attach_next_to(*loginButtonSpacerTop, passwordInput, Gtk::POS_BOTTOM, 1, 1); + loginLayout.attach_next_to(*loginButtonSpacerTop, loginPasswordInput, Gtk::POS_BOTTOM, 1, 1); Gtk::Alignment *loginButtonSpacer = Gtk::manage(new Gtk::Alignment()); - attach_next_to(*loginButtonSpacer, *loginButtonSpacerTop, Gtk::POS_BOTTOM, 2, 1); + loginLayout.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); + loginButton.get_style_context()->add_class("confirm-button"); + loginLayout.attach_next_to(loginButton, *loginButtonSpacer, Gtk::POS_RIGHT, 1, 1); - set_halign(Gtk::ALIGN_CENTER); - set_valign(Gtk::ALIGN_CENTER); - get_style_context()->add_class("login-window"); + Gtk::Separator *separator = Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_HORIZONTAL)); + separator->get_style_context()->add_class("separator-horizontal-margin"); + loginLayout.attach_next_to(*separator, *loginButtonSpacer, Gtk::POS_BOTTOM, 3, 1); + + Gtk::Label *registerText = Gtk::manage(new Gtk::Label("Don't have an account? ")); + loginLayout.attach_next_to(*registerText, *separator, Gtk::POS_BOTTOM, 1, 1); + Gtk::Label *registerTextClickable = Gtk::manage(new Gtk::Label()); + registerTextClickable->set_markup("<span color='#3060d8'>Register a new one</span>"); + Gtk::EventBox *eventBox = Gtk::manage(new Gtk::EventBox()); + eventBox->add(*registerTextClickable); + auto pointerCursor = Gdk::Cursor::create(Gdk::Display::get_default(), "pointer"); + //eventBox->get_window()->set_cursor(pointerCursor); + eventBox->signal_button_release_event().connect([this](GdkEventButton *event) + { + loginLayout.hide(); + registerLayout.show_all(); + return true; + }); + loginLayout.attach_next_to(*eventBox, *registerText, Gtk::POS_RIGHT, 1, 1); + + loginLayout.get_style_context()->add_class("login-window"); } - void LoginWindow::setLoginHandler(LoginHandler loginHandler) + void LoginWindow::setupRegister() { - loginHandlerUser = loginHandler; + registerHandler = [this] + { + if(registerPasswordInput.get_text() != registerPasswordRepeatInput.get_text()) + { + if(passwordMismatchHandler) + passwordMismatchHandler(); + return; + } + + if(registerHandlerUser) + registerHandlerUser(registerUsernameInput.get_text(), registerPasswordInput.get_text()); + }; + + Gtk::Label *username = Gtk::manage(new Gtk::Label("Username")); + username->set_halign(Gtk::ALIGN_START); + registerLayout.attach(*username, 0, 0, 1, 1); + + registerUsernameInput.set_size_request(200); + registerUsernameInput.signal_activate().connect(registerHandler); + registerLayout.attach_next_to(registerUsernameInput, *username, Gtk::POS_BOTTOM, 3, 1); + + Gtk::Alignment *usernamePasswordSpacer = Gtk::manage(new Gtk::Alignment()); + usernamePasswordSpacer->set_size_request(-1, 35); + registerLayout.attach_next_to(*usernamePasswordSpacer, registerUsernameInput, Gtk::POS_BOTTOM, 1, 1); + + Gtk::Label *password = Gtk::manage(new Gtk::Label("Password")); + password->set_halign(Gtk::ALIGN_START); + registerLayout.attach_next_to(*password, *usernamePasswordSpacer, Gtk::POS_BOTTOM, 1, 1); + + registerPasswordInput.set_visibility(false); + registerPasswordInput.set_size_request(200); + registerPasswordInput.signal_activate().connect(registerHandler); + registerLayout.attach_next_to(registerPasswordInput, *password, Gtk::POS_BOTTOM, 3, 1); + + Gtk::Label *repeatPassword = Gtk::manage(new Gtk::Label("Repeat password")); + repeatPassword->set_halign(Gtk::ALIGN_START); + registerLayout.attach_next_to(*repeatPassword, registerPasswordInput, Gtk::POS_BOTTOM, 1, 1); + + registerPasswordRepeatInput.set_visibility(false); + registerPasswordRepeatInput.set_size_request(200); + registerPasswordRepeatInput.signal_activate().connect(registerHandler); + registerLayout.attach_next_to(registerPasswordRepeatInput, *repeatPassword, Gtk::POS_BOTTOM, 3, 1); + + Gtk::Alignment *registerButtonSpacerTop = Gtk::manage(new Gtk::Alignment()); + registerButtonSpacerTop->set_size_request(-1, 20); + registerLayout.attach_next_to(*registerButtonSpacerTop, registerPasswordRepeatInput, Gtk::POS_BOTTOM, 1, 1); + + Gtk::Alignment *registerButtonSpacer = Gtk::manage(new Gtk::Alignment()); + registerLayout.attach_next_to(*registerButtonSpacer, *registerButtonSpacerTop, Gtk::POS_BOTTOM, 2, 1); + + registerButton.set_halign(Gtk::ALIGN_END); + registerButton.signal_clicked().connect(registerHandler); + registerButton.get_style_context()->add_class("confirm-button"); + registerLayout.attach_next_to(registerButton, *registerButtonSpacer, Gtk::POS_RIGHT, 1, 1); + + Gtk::Separator *separator = Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_HORIZONTAL)); + separator->get_style_context()->add_class("separator-horizontal-margin"); + registerLayout.attach_next_to(*separator, *registerButtonSpacer, Gtk::POS_BOTTOM, 3, 1); + + Gtk::Label *loginText = Gtk::manage(new Gtk::Label("Already have an account? ")); + registerLayout.attach_next_to(*loginText, *separator, Gtk::POS_BOTTOM, 1, 1); + Gtk::Label *loginTextClickable = Gtk::manage(new Gtk::Label()); + loginTextClickable->set_markup("<span color='#3060d8'>Login to an existing account</span>"); + Gtk::EventBox *eventBox = Gtk::manage(new Gtk::EventBox()); + eventBox->add(*loginTextClickable); + auto pointerCursor = Gdk::Cursor::create(Gdk::Display::get_default(), "pointer"); + //eventBox->get_window()->set_cursor(pointerCursor); + eventBox->signal_button_release_event().connect([this](GdkEventButton *event) + { + registerLayout.hide(); + loginLayout.show_all(); + return true; + }); + registerLayout.attach_next_to(*eventBox, *loginText, Gtk::POS_RIGHT, 1, 1); + + registerLayout.get_style_context()->add_class("login-window"); } }
\ No newline at end of file diff --git a/src/Window.cpp b/src/Window.cpp index 72a3d9d..970242d 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -21,10 +21,15 @@ namespace dchat stack.add(loginWindow, "login"); stack.add(chatWindow, "chat"); - show_all(); + overlay->show(); + windowNotification->show_all(); + stack.show(); + chatWindow.show_all(); + loginWindow.show(); loginWindow.setLoginHandler([this, windowNotification](const Glib::ustring &username, const Glib::ustring &password) { + std::lock_guard<std::mutex> lock(databaseCallbackMutex); if(!database) { windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); @@ -35,7 +40,7 @@ namespace dchat { fprintf(stderr, "Trying to login with username %s\n", username.raw().c_str()); auto storedNodes = database->getStoredNodeUserInfoDecrypted(username.raw(), password.raw()); - fprintf(stderr, "Successfully logged in as %s\n", username.raw().c_str()); + windowNotification->show(Glib::ustring("Successfully logged in as ") + username); stack.set_visible_child(chatWindow); for(auto &nodeInfo : storedNodes) @@ -51,6 +56,37 @@ namespace dchat } }); + loginWindow.setRegisterHandler([this, windowNotification](const Glib::ustring &username, const Glib::ustring &password) + { + std::lock_guard<std::mutex> lock(databaseCallbackMutex); + if(!database) + { + windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); + return; + } + + try + { + fprintf(stderr, "Trying to register username %s\n", username.raw().c_str()); + database->storeUserWithoutNodes(username.raw(), password.raw()); + windowNotification->show(Glib::ustring("Successfully registered user ") + username); + stack.set_visible_child(chatWindow); + } + catch(std::exception &e) + { + Glib::ustring errMsg = "Failed to register username "; + errMsg += username.raw(); + errMsg += ", reason: "; + errMsg += e.what(); + windowNotification->show(errMsg); + } + }); + + loginWindow.setRegisterPasswordMismatch([windowNotification] + { + windowNotification->show("Passwords do not match"); + }); + odhtdb::DatabaseCallbackFuncs callbackFuncs; callbackFuncs.createNodeCallbackFunc = [this](const odhtdb::DatabaseCreateNodeRequest &request) { |