diff --git a/.gitignore b/.gitignore index 754a36d..d118476 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ .git/* -CMakeLists.txt.* build/* diff --git a/docroot/style.css b/docroot/style.css index ad13236..52ff54c 100644 --- a/docroot/style.css +++ b/docroot/style.css @@ -114,3 +114,35 @@ height: 31px; .Wt-dialog > div > div > div > h4 { margin: 0; } +.handle { + top: calc(50% - 0.55rem) !important; + margin-left: 2px; + width: 1rem !important; + height: 1rem !important; + background-color: black; + border: 0; + border-radius: 1rem; + + &:focus { + box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(red($primary), green($primary), blue($primary), .25); + } +} +.search-line { + overflow: visible !important; +} +.popup-style { + position: relative; +} +.countries-drop-down { + overflow: auto; + background: RGBA(248, 248, 248, 0.8); + position: absolute; + max-height: 10em; + display: inline-block; + top: 100%; + left: 58px; + z-index: 20; + border: 1px solid #666; + box-shadow: 2px 2px 4px #666; + padding: 2px; +} diff --git a/src/app.cpp b/src/app.cpp index 58debc4..417aa64 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -33,6 +33,9 @@ #include #include #include +#include +#include +#include App::App(const Wt::WEnvironment &env, Broadcast &server): Wt::WApplication(env), @@ -50,8 +53,10 @@ App::App(const Wt::WEnvironment &env, Broadcast &server): createUserListContainer(horizontalContainer); createContentContainer(horizontalContainer); createImprintContainer(verticalContainer); + reSetUser(); if (userName == "") { showLogin(); + Wt::WMessageBox::show("Cookie information", "By technical reasons we set a cookie. This cookie isn't tracking anything or will be saved in a database.", Wt::StandardButton::Ok); } else { startChat(); } @@ -68,6 +73,20 @@ void App::initApp() { useStyleSheet("style.css"); } +void App::reSetUser() { + if (env_.cookies().contains("wtd")) { + auto userData = server_.reSetUser(env_.cookies().find("wtd")->second, sessionId()); + Wt::Json::Object emptyObject = {}; + if (userData != emptyObject) { + userName = (std::string)userData["username"]; + gender = (std::string)userData["gender"]; + country = (std::string)userData["country"]; + isoCountryCode = (std::string)userData["iso-country-code"]; + age = (int)userData["age"]; + } + } +} + Wt::WVBoxLayout *App::createVerticalLayout() { auto verticalBox = root()->addNew(); verticalBox->setHeight(Wt::WLength(100, Wt::LengthUnit::Percentage)); @@ -177,6 +196,7 @@ void App::handleLogin(Wt::WLineEdit* userName, Wt::WComboBox* countryWidget, Wt: setUserData(nick, countryWidget, ageWidget, genderWidget); connectToServer(); startChat(); + setCookie("wtd", sessionId(), 21000); } catch (const std::exception& e) { Wt::WMessageBox::show("Attention", e.what(), Wt::StandardButton::Ok); } @@ -243,7 +263,7 @@ void App::populateGenderComboBox(Wt::WComboBox *genderWidget) { std::string App::getGenderShortByGender(std::string gender) { for (const auto &genderItem: genders_) { if (gender == genderItem.second) { - return genderItem.first; + return genderItem.first.toUTF8(); } } return ""; @@ -258,15 +278,7 @@ void App::updateUserlist(Wt::Json::Array unsortedUserList) { userListContainer_->setOverflow(Wt::Overflow::Auto); auto sortedUserList = sortUserList(unsortedUserList); for (Wt::Json::Object &user: sortedUserList) { - auto userName = (std::string)user["name"]; - auto userItem = layout->addNew(Wt::WString("{1} ({2})").arg(userName).arg((int)user["age"])); - userItem->setStyleClass(Wt::WString("userlist-item userlist-gender-{1}").arg((std::string)user["gender"])); - userItem->setHeight(Wt::WLength(2, Wt::LengthUnit::FontEm)); - userItem->setPadding(Wt::WLength(3, Wt::LengthUnit::Pixel)); - userItem->clicked().connect([=, this]() { - requestConversation(userName); - }); - Wt::WCssDecorationStyle style; + addUserItemToLayout(layout, user); } layout->addWidget(std::make_unique(), 1)->setStyleClass("height-spacer userlist"); triggerUpdate(); @@ -768,7 +780,7 @@ void App::addIdentifier() { void App::addSearchButton() { auto searchButton = menuContainer_->addNew("Search"); - searchButton->clicked().connect(this, &App::executeSearch); + searchButton->clicked().connect(this, &App::showSearchWindow); } void App::addInboxButton() { @@ -776,11 +788,203 @@ void App::addInboxButton() { inbox_->clicked().connect(this, &App::openInbox); } -void App::executeSearch() { +void App::showSearchWindow() { + auto contentLayout = resetSearchFields(); + auto userNameField = setupNameSearchField(contentLayout); + auto ageSearchFields = setupSearchFields(contentLayout); + auto countryFields = setupCountryDropDown(contentLayout); + auto gendersFields = setupGendersDropDown(contentLayout); + auto searchResultContainer = setupSearchButton(contentLayout); + restoreSearchFields(searchResultContainer, userNameField, ageSearchFields.first, ageSearchFields.second, + countryFields.second, gendersFields.second, countryFields.first, gendersFields.first); +} + +Wt::WVBoxLayout *App::resetSearchFields() { currentConversationWith_ = ""; contentContainer_->clear(); - contentContainer_->addNew("search"); inboxOpen_ = false; + auto contentLayout = contentContainer_->setLayout(std::make_unique()); + contentLayout->addNew("

Search

"); + return contentLayout; +} + +std::pair App::setupSearchFields(Wt::WVBoxLayout *contentLayout) { + auto minAgeEdit = addSearchItemLine(contentLayout, "From age"); + minAgeEdit->setRange(18, 150); + minAgeEdit->setValue(18); + minAgeEdit->changed().connect([=, this] { searchFields.minAge = minAgeEdit->value(); }); + auto maxAgeEdit = addSearchItemLine(contentLayout, "To age"); + maxAgeEdit->setRange(18, 150); + maxAgeEdit->setValue(150); + maxAgeEdit->changed().connect([=, this] { searchFields.maxAge = maxAgeEdit->value(); }); + return {minAgeEdit, maxAgeEdit}; +} + +std::pair App::setupCountryDropDown(Wt::WVBoxLayout *contentLayout) { + auto countryDropDown = std::make_unique(); + countryDropDown->setInline(true); + countryDropDown->setStyleClass("countries-drop-down"); + auto countryDropDownContainer = countryDropDown.get(); + auto countryOpenList = addSearchItemLine(contentLayout, "Country", std::move(countryDropDown)); + countryDropDownContainer->hide(); + countryOpenList->clicked().connect([=]() { if (countryDropDownContainer->isHidden()) { countryDropDownContainer->show();} else { countryDropDownContainer->hide(); } }); + countryOpenList->setText("All"); + std::map countries = server_.countries(); + addItem("All", countryDropDownContainer, countryOpenList, &searchFields.countries, true); + addItem(country, countryDropDownContainer, countryOpenList, &searchFields.countries); + for (const auto &itemCountry: countries) { + if (itemCountry.first.toUTF8() != country) { + addItem(itemCountry.first.toUTF8(), countryDropDownContainer, countryOpenList, &searchFields.countries); + } + } + return {countryOpenList, countryDropDownContainer}; +} + +std::pair App::setupGendersDropDown(Wt::WVBoxLayout *contentLayout) { + auto gendersDropDown = std::make_unique(); + gendersDropDown->setInline(true); + gendersDropDown->setStyleClass("countries-drop-down"); + auto gendersDropDownContainer = gendersDropDown.get(); + auto gendersOpenList = addSearchItemLine(contentLayout, "Genders", std::move(gendersDropDown)); + gendersDropDownContainer->hide(); + gendersOpenList->clicked().connect([=]() { if (gendersDropDownContainer->isHidden()) { gendersDropDownContainer->show();} else { gendersDropDownContainer->hide(); } }); + gendersOpenList->setText("All"); + addItem("All", gendersDropDownContainer, gendersOpenList, &searchFields.gender, true); + std::map swappedGenders; + for (const auto& pair : genders_) { + swappedGenders[pair.second] = pair.first; + } + for (const auto &itemGender: swappedGenders) { + addItem(itemGender.first.toUTF8(), gendersDropDownContainer, gendersOpenList, &searchFields.gender); + } + return {gendersOpenList, gendersDropDownContainer}; +} + +void App::addItem(const std::string& country, Wt::WContainerWidget *dropDownContainer, Wt::WPushButton *openListButton, std::unordered_set *saveItems, bool isSelected) { + auto menuItem = dropDownContainer->addNew(country); + menuItem->changed().connect([=, this]() mutable { itemChanged(menuItem, dropDownContainer, openListButton, saveItems); }); + menuItem->setInline(false); + if (isSelected) { + menuItem->setChecked(); + } +} + +void App::addUserItemToLayout(Wt::WVBoxLayout *layout, Wt::Json::Object userObject) { + auto userName = (std::string)userObject["name"]; + auto userItem = layout->addNew(Wt::WString("{1} ({2})").arg(userName).arg((int)userObject["age"])); + userItem->setStyleClass(Wt::WString("userlist-item userlist-gender-{1}").arg((std::string)userObject["gender"])); + userItem->setHeight(Wt::WLength(2, Wt::LengthUnit::FontEm)); + userItem->setPadding(Wt::WLength(3, Wt::LengthUnit::Pixel)); + userItem->clicked().connect([=, this]() { + requestConversation(userName); + }); + +} + +std::unordered_set App::gendersListToShortGendersList(std::unordered_set gendersList) { + std::unordered_set result; + for (const auto &gender: gendersList) { + result.insert(genderShortOfGender(gender)); + } + return result; +} + +std::string App::genderShortOfGender(const std::string incomingGender) { + for (const auto &genderItem: genders_) { + if (incomingGender == genderItem.second) { + return genderItem.first.toUTF8(); + } + } + return incomingGender; +} + +void App::itemChanged(Wt::WCheckBox *item, Wt::WContainerWidget *dropDownContainer, Wt::WPushButton *openButton, std::unordered_set *saveItems) { + saveItems->clear(); + bool unselect = (item->text() == "All" && item->isChecked()); + for (auto &widgetItem: dropDownContainer->children()) { + auto widgetCheckBox = static_cast(widgetItem); + if (unselect && widgetCheckBox->text() != "All" && widgetCheckBox->isChecked()) { + widgetCheckBox->setChecked(false); + } + if (widgetCheckBox->isChecked()) { + saveItems->insert(widgetCheckBox->text().toUTF8()); + } + } + if (saveItems->size() > 1 && saveItems->find("All") != saveItems->end()) { + saveItems->erase(saveItems->find("All")); + static_cast(dropDownContainer->children().at(0))->setChecked(false); + } + if (saveItems->empty()) { + saveItems->insert("All"); + } + std::string result; + for (const auto &selected: *saveItems) { + result += (result.empty() ? "" : ", ") + selected; + } + openButton->setText(result); +} + +void App::restoreSearchFields(Wt::WContainerWidget *searchResultContainer, Wt::WLineEdit *userNameEdit, Wt::WSpinBox *minAgeEdit, + Wt::WSpinBox *maxAgeEdit, Wt::WContainerWidget *countryDropDownContainer, Wt::WContainerWidget *gendersDropDownContainer, + Wt::WPushButton *countryOpenList, Wt::WPushButton *gendersOpenList) { + if (!searchFields.set) { + searchFields = Search(searchResultContainer); + } else { + userNameEdit->setValueText(searchFields.userName); + minAgeEdit->setValue(searchFields.minAge); + maxAgeEdit->setValue(searchFields.maxAge); + for (auto countryWidget: countryDropDownContainer->children()) { + auto countryCheckBox = (Wt::WCheckBox*)countryWidget; + countryCheckBox->setChecked(searchFields.countries.find(countryCheckBox->text().toUTF8()) != searchFields.countries.end()); + } + itemChanged((Wt::WCheckBox*)*countryDropDownContainer->children().begin(), countryDropDownContainer, countryOpenList, &searchFields.countries); + for (auto genderWidget: gendersDropDownContainer->children()) { + auto genderCheckBox = (Wt::WCheckBox*)genderWidget; + genderCheckBox->setChecked(searchFields.gender.find(genderCheckBox->text().toUTF8()) != searchFields.gender.end()); + } + itemChanged((Wt::WCheckBox*)*gendersDropDownContainer->children().begin(), gendersDropDownContainer, gendersOpenList, &searchFields.gender); + startSearch(); + } +} + +Wt::WLineEdit *App::setupNameSearchField(Wt::WVBoxLayout *contentLayout) { + auto userNameEdit = addSearchItemLine(contentLayout, "Username includes"); + userNameEdit->changed().connect([=, this] { searchFields.userName = userNameEdit->text().trim(); }); + return userNameEdit; +} + +Wt::WContainerWidget *App::setupSearchButton(Wt::WVBoxLayout *contentLayout) { + auto searchButton = addSearchItemLine(contentLayout, ""); + searchButton->setText("Search"); + auto searchResultContainer = contentLayout->addWidget(std::make_unique(), 1); + searchResultContainer->addNew("No results"); + searchButton->clicked().connect(this, &App::startSearch); + return searchResultContainer; +} + +void App::startSearch() { + if (searchFields.minAge > searchFields.maxAge) { + searchFields.outputContainer->clear(); + searchFields.outputContainer->addNew("Minimum age must be at least as large as or greater than the maximum age."); + return; + } + server_.userSearch(sessionId(), searchFields.userName.toUTF8(), searchFields.minAge, searchFields.maxAge, + searchFields.countries, gendersListToShortGendersList(searchFields.gender), userName); +} + +void App::showSearch(Wt::Json::Object broadcast) { + searchFields.outputContainer->clear(); + auto searchResult = (Wt::Json::Array)broadcast["data"]; + if (searchResult.size() == 0) { + searchFields.outputContainer->addNew("No results."); + } + auto searchListContainer = searchFields.outputContainer->addNew(); + auto searchList = searchListContainer->setLayout(std::make_unique()); + searchListContainer->setOverflow(Wt::Overflow::Auto); + for (const Wt::Json::Object &searchItem: searchResult) { + addUserItemToLayout(searchList, searchItem); + } + triggerUpdate(); } void App::openInbox() { @@ -810,6 +1014,8 @@ void App::incomingBroadcast() { showSystemMessage(broadcast); } else if (broadcast["type"] == "conversation-start") { showConversation(broadcast); + } else if (broadcast["type"] == "search-result") { + showSearch(broadcast); } } } @@ -912,3 +1118,24 @@ bool App::isNickAllowed(const std::string& nick) { return lowercaseNick.find(lowercasePhrase) == std::string::npos; }); } + +template +Class *App::addSearchItemLine(Wt::WVBoxLayout *layout, std::string label, std::unique_ptr additionalItem) { + auto lineContainer = layout->addNew(); + lineContainer->setStyleClass("search-line"); + lineContainer->setPositionScheme(Wt::PositionScheme::Relative); + auto lineLayout = lineContainer->setLayout(std::make_unique()); + lineContainer->setPadding(Wt::WLength("0")); + lineContainer->setMargin(Wt::WLength("0")); + lineLayout->addNew(label); + lineLayout->setContentsMargins(0, 0, 0, 0); + lineLayout->setSpacing(0); + auto input = std::make_unique(); + auto returnInput = input.get(); + lineLayout->addWidget(std::move(input), 1); + if (additionalItem) { + lineLayout->addWidget(std::move(additionalItem)); + lineContainer->setOverflow(Wt::Overflow::Visible); + } + return returnInput; +} diff --git a/src/app.h b/src/app.h index 7ff0c14..69195c3 100644 --- a/src/app.h +++ b/src/app.h @@ -7,6 +7,7 @@ #include "curl/curl.h" #include #include +#include namespace Magick { class Image; @@ -18,7 +19,7 @@ public: ~App(); private: - std::unordered_map genders_ { + std::map genders_ { {"F", "Female"}, {"M", "Male"}, {"P", "Pair"}, @@ -46,6 +47,22 @@ private: {";p", Smiley("1F61C", "Twinkle tongue")}, {":'(", Smiley("1F622", "Cry")} }; + struct Search { + Wt::WContainerWidget *outputContainer; + Wt::WString userName{""}; + int minAge{18}; + int maxAge{150}; + std::unordered_set gender; + std::unordered_set countries; + Search()=default; + Search(Wt::WContainerWidget *outputContainer_): + outputContainer(outputContainer_) { + set = true; + gender.insert("All"); + countries.insert("All"); + } + bool set = false; + }; Wt::WString smileyPlaceholder_ = "&#x{1};"; const Wt::WEnvironment &env_; Broadcast &server_; @@ -60,7 +77,9 @@ private: bool inboxOpen_{false}; int messageCursorPosition_{-1}; std::unique_ptr messageReceived_; + Search searchFields; void initApp(); + void reSetUser(); Wt::WVBoxLayout *createVerticalLayout(); Wt::WHBoxLayout *createActionLayout(Wt::WVBoxLayout *verticalContainer); void createUserListContainer(Wt::WHBoxLayout *layout); @@ -88,7 +107,10 @@ private: void addIdentifier(); void addSearchButton(); void addInboxButton(); - void executeSearch(); + void showSearchWindow(); + void startSearch(); + void showSearch(Wt::Json::Object broadcast); + template Class *addSearchItemLine(Wt::WVBoxLayout *layout, std::string label, std::unique_ptr additionalItem = nullptr); void openInbox(); bool isNickAllowed(const std::string &nick); bool compareJsonObjects(const Wt::Json::Object &obj1, const Wt::Json::Object &obj2); @@ -146,6 +168,18 @@ private: Wt::WWebWidget *createImageElement(Wt::Json::Object &line, const std::string &writer, Wt::WContainerWidget *outputContainer); Wt::WWebWidget *createTextElement(const std::string &writer, const std::string &text, Wt::WContainerWidget *outputContainer); void createImprintContainer(Wt::WVBoxLayout *containerLayout); + Wt::WContainerWidget *setupSearchButton(Wt::WVBoxLayout *contentLayout); + void restoreSearchFields(Wt::WContainerWidget *searchResultContainer, Wt::WLineEdit *userNameEdit, Wt::WSpinBox *minAgeEdit, Wt::WSpinBox *maxAgeEdit, Wt::WContainerWidget *countryDropDownContainer, Wt::WContainerWidget *gendersDropDownContainer, Wt::WPushButton *countryOpenList, Wt::WPushButton *gendersOpenList); + Wt::WLineEdit *setupNameSearchField(Wt::WVBoxLayout *contentLayout); + std::pair setupGendersDropDown(Wt::WVBoxLayout *contentLayout); + std::pair setupCountryDropDown(Wt::WVBoxLayout *contentLayout); + std::pair setupSearchFields(Wt::WVBoxLayout *contentLayout); + Wt::WVBoxLayout *resetSearchFields(); + void itemChanged(Wt::WCheckBox *item, Wt::WContainerWidget *dropDownContainer, Wt::WPushButton *openButton, std::unordered_set *saveItems); + void addItem(const std::string &country, Wt::WContainerWidget *dropDownContainer, Wt::WPushButton *openListButton, std::unordered_set *saveItems, bool isSelected = false); + void addUserItemToLayout(Wt::WVBoxLayout *layout, Wt::Json::Object userObject); + std::unordered_set gendersListToShortGendersList(std::unordered_set gendersList); + std::string genderShortOfGender(const std::string incomingGender); }; #endif // APP_H diff --git a/src/broadcast.cpp b/src/broadcast.cpp index e6626a8..f44cc7f 100644 --- a/src/broadcast.cpp +++ b/src/broadcast.cpp @@ -23,7 +23,6 @@ Broadcast::~Broadcast() { } void Broadcast::connect(Client *client, const std::function &fct) { - std::unique_lock lock(mutex_); connections_.push_back(std::make_unique(Wt::WApplication::instance()->sessionId(), client, fct)); auto broadcast = createUserList(); for (auto &connection: connections_) { @@ -53,6 +52,23 @@ void Broadcast::disconnect(Client *client) { } +Wt::Json::Object Broadcast::reSetUser(std::string oldSessionId, std::string newSessionId) { + for (auto& connection : connections_) { + if (connection->setSessionId(oldSessionId, newSessionId)) { + Wt::Json::Object userData { + {"gender", Wt::Json::Value(connection->gender())}, + {"country", Wt::Json::Value(connection->country())}, + {"iso-country-code", Wt::Json::Value(getCountryIsoCodeByCountry(connection->country()))}, + {"username", Wt::Json::Value(connection->userName())}, + {"age", Wt::Json::Value(connection->age())}, + }; + reSetSessionIdInMessages(oldSessionId, newSessionId); + return userData; + } + } + return {}; +} + int Broadcast::count() const { std::unique_lock lock(mutex_); return connections_.size(); @@ -349,6 +365,28 @@ void Broadcast::requestConversation(std::string sendToSessionId, std::string wit addMessageToSessionBroadcast(sendToSessionId, broadcast); } +void Broadcast::userSearch(std::string toSession, std::string nameIncludes, int minAge, int maxAge, std::unordered_set countries, std::unordered_set genders, std::string excludeName) { + Wt::Json::Array searchResult; + for (const auto &user: connections_) { + std::cout << user->gender() << std::endl; + if ( + (nameIncludes == "" || user->userName().find(nameIncludes) != std::string::npos) + && (minAge <= user->age()) + && (maxAge >= user->age()) + && (countries.contains("All") || countries.contains(user->country()) || countries.size() == 0) + && (genders.contains("All") || genders.contains(user->gender()) || genders.size() == 0) + && (user->userName() != excludeName) + ) { + searchResult.push_back(user->client()->json()); + } + } + Wt::Json::Object broadcast{ + {"type", "search-result"}, + {"data", searchResult} + }; + addMessageToSessionBroadcast(toSession, broadcast); +} + bool Broadcast::parseCountriesData() { std::istringstream iss(responseData_); std::string line; @@ -366,6 +404,12 @@ bool Broadcast::parseCountriesData() { return true; } +void Broadcast::reSetSessionIdInMessages(std::string oldSessionId, std::string newSessionId) { + for (auto &conversation: conversations_) { + conversation.second.setNewSesionId(oldSessionId, newSessionId); + } +} + Wt::Json::Object Broadcast::createUserList() { Wt::Json::Array userList; for (const auto &connection: connections_) { @@ -505,6 +549,14 @@ std::list Broadcast::Connection::getBroadcasts(bool clear) { return broadcastCopy; } +bool Broadcast::Connection::setSessionId(std::string searchedSessionId, std::string newSessionId) { + if (searchedSessionId == sessionId_) { + sessionId_ = newSessionId; + return true; + } + return false; +} + std::function Broadcast::Connection::fct() { return fct_; } @@ -557,3 +609,15 @@ Wt::Json::Object Broadcast::Message::json() { json["image"] = Wt::Json::Value(image); return json; } + +void Broadcast::Message::setNewSesionId(std::string oldSessionId, std::string newSessionId) { + if (fromSessionId == oldSessionId) { + fromSessionId = newSessionId; + } +} + +void Broadcast::MessageQueue::setNewSesionId(std::string oldSessionId, std::string newSessionId) { + for (auto &message: messages) { + message.setNewSesionId(oldSessionId, newSessionId); + } +} diff --git a/src/broadcast.h b/src/broadcast.h index 66cf2c6..5467140 100644 --- a/src/broadcast.h +++ b/src/broadcast.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -49,16 +50,19 @@ public: Wt::WString message; Wt::Json::Object image; Wt::Json::Object json(); + void setNewSesionId(std::string oldSessionId, std::string newSessionId); }; struct MessageQueue { bool user1Read{false}; bool user2Read{false}; std::vector messages; + void setNewSesionId(std::string oldSessionId, std::string newSessionId); }; Broadcast(Wt::WServer *server); ~Broadcast(); void connect(Client *client, const std::function &fct); void disconnect(Client *client); + Wt::Json::Object reSetUser(std::string oldSessionId, std::string newSessionId); int count() const; std::string userNameForSessionId(std::string sessionId); std::string sessionIdForUserName(std::string userName); @@ -78,6 +82,8 @@ public: void sendUserInformation(std::string sendToSessionId, std::string userName, std::string requestingUserName); void toggleBlockUser(std::string blockingUserName, std::string blockedUser, std::string blockingUserSessionId); void requestConversation(std::string sendToSessionId, std::string withUserName, std::string requestingUserName); + void userSearch(std::string toSession, std::string nameIncludes, int minAge, int maxAge, + std::unordered_set countries, std::unordered_set genders, std::string excludeName); protected: struct Connection { Connection(const std::string &id, Client *client, const std::function &fct); @@ -93,6 +99,7 @@ protected: void addBroadcast(Wt::Json::Object broadcast); std::list getBroadcasts(bool clear = false); std::unordered_map > blockings_; + bool setSessionId(std::string searchedSessionId, std::string newSessionId); private: std::string sessionId_; Client *client_; @@ -118,6 +125,7 @@ private: Wt::Json::Object logoutBroadcast(); static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output); bool parseCountriesData(); + void reSetSessionIdInMessages(std::string oldSessionId, std::string newSessionId); Wt::Json::Object createUserList(); void sendMessageQueueToSession(std::string receiverSessionId, std::string user1, std::string user2, std::vector messages); void addMessageToSessionBroadcast(std::string sessionId, Wt::Json::Object message);