From ab8f84f3717256dc84542726ba6d53ee1233ce90 Mon Sep 17 00:00:00 2001 From: Torsten Schulz Date: Wed, 21 Feb 2024 11:08:27 +0100 Subject: [PATCH] Fixed problems with block; refactored code --- CMakeLists.txt | 2 +- src/app.cpp | 140 +++++++++++++++++++++++++++------------------- src/app.h | 6 +- src/broadcast.cpp | 23 ++++++-- src/broadcast.h | 2 + 5 files changed, 107 insertions(+), 66 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b295252..b7590cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ endif() if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) - target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} GraphicsMagick++) + target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} GraphicsMagick++ GraphicsMagick) endif() include(GNUInstallDirs) diff --git a/src/app.cpp b/src/app.cpp index e16e6ba..4b93be7 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -399,8 +399,8 @@ std::unique_ptr App::createInfoText(Wt::Json::Object userData) { std::unique_ptr App::createBlockButton(Wt::Json::Object userData) { auto blockButton = std::make_unique((bool)userData["blocked"] ? "Unblock user" : "Block user"); - blockButton->clicked().connect([=, this, &userData]() { - server_.toggleBlockUser(userName, (std::string)userData["name"], userName); + blockButton->clicked().connect([=, this]() mutable { + server_.toggleBlockUser(userName, (std::string)userData["name"], sessionId()); }); return blockButton; } @@ -433,56 +433,69 @@ Wt::WLineEdit* App::createInputLine(Wt::WHBoxLayout* inputLayout) { Wt::WImage* App::createSendImageButton(Wt::WHBoxLayout* inputLayout) { auto sendImageButton = inputLayout->addNew(Wt::WLink("/image.png")); sendImageButton->setToolTip("Send an image"); - sendImageButton->clicked().connect([=, this]() { - auto fileDialog = root()->addNew("Send Image to User"); - auto layout = fileDialog->contents()->setLayout(std::make_unique()); - layout->addNew("Please select an immage"); - auto fileWidget = layout->addNew(); - fileWidget->setFilters("image/*"); - auto image = layout->addNew(); - image->setMaximumSize(Wt::WLength(100, Wt::LengthUnit::Pixel), Wt::WLength(100, Wt::LengthUnit::Pixel)); - image->setHeight(Wt::WLength::Auto); - auto localImage = std::make_shared(); - auto buttonsContainer = layout->addNew(); - auto okButton = buttonsContainer->addNew("Send image"); - fileWidget->uploaded().connect([=, this]() mutable { - try { - Magick::Image originalImage; - originalImage.quiet(true); - originalImage.read(fileWidget->spoolFileName()); - *localImage = scaleImage(originalImage, 500); - auto smallImage = scaleImage(originalImage, 100); - Magick::Blob previewBlob; - smallImage.write(&previewBlob); - auto previewBase64 = previewBlob.base64(); - auto previewImage = Wt::Utils::base64Decode(previewBase64); - auto imageResource = std::make_shared( - "image/png", - std::vector(previewImage.begin(), previewImage.end())); - image->setImageLink(Wt::WLink(imageResource)); - image->resize(Wt::WLength(smallImage.columns(), Wt::LengthUnit::Pixel), Wt::WLength(smallImage.rows(), Wt::LengthUnit::Pixel)); - okButton->setEnabled(true); - triggerUpdate(); - } catch (const std::exception& e) { - std::cerr << "Error processing uploaded image: " << e.what() << std::endl; - } - }); - fileWidget->changed().connect([=]() { fileWidget->upload(); }); - fileWidget->fileTooLarge().connect([](){ std::cout << "file too big" << std::endl; }); - okButton->setDisabled(true); - okButton->clicked().connect([=, this]() { - server_.addImage(sessionId(), currentConversationWith_, localImage); - fileDialog->accept(); - }); - auto cancelButton = buttonsContainer->addNew("Cancel"); - cancelButton->clicked().connect([=](){ fileDialog->reject(); }); - fileDialog->setClosable(true); - fileDialog->setModal(true); - fileDialog->show(); - }); + sendImageButton->clicked().connect(this, &App::sendImage); return sendImageButton; } +void App::sendImage() { + auto fileDialog = root()->addNew("Send Image to User"); + auto layout = fileDialog->contents()->setLayout(std::make_unique()); + layout->addNew("Please select an immage"); + auto fileWidget = layout->addNew(); + fileWidget->setFilters("image/*"); + auto image = layout->addNew(); + image->setMaximumSize(Wt::WLength(100, Wt::LengthUnit::Pixel), Wt::WLength(100, Wt::LengthUnit::Pixel)); + image->setHeight(Wt::WLength::Auto); + auto localImage = std::make_shared(); + auto buttonsContainer = layout->addNew(); + auto okButton = buttonsContainer->addNew("Send image"); + fileWidget->uploaded().connect([=, this]() mutable { + imageUploaded(fileWidget, localImage, image, okButton); + }); + fileWidget->changed().connect([=]() { fileWidget->upload(); }); + fileWidget->fileTooLarge().connect([](){ std::cout << "file too big" << std::endl; }); + okButton->setDisabled(true); + okButton->clicked().connect([=, this]() { + server_.addImage(sessionId(), currentConversationWith_, localImage); + fileDialog->accept(); + }); + auto cancelButton = buttonsContainer->addNew("Cancel"); + cancelButton->clicked().connect([=](){ fileDialog->reject(); }); + fileDialog->setClosable(true); + fileDialog->setModal(true); + fileDialog->show(); +} + +void App::imageUploaded(Wt::WFileUpload *fileWidget, std::shared_ptr localImage, Wt::WImage *image, Wt::WPushButton *okButton) { + try { + std::list originalImages; + Magick::readImages(&originalImages, fileWidget->spoolFileName()); + std::list coalescedList; + Magick::coalesceImages(&coalescedList, originalImages.begin(), originalImages.end()); + Magick::Image coalescedImage; + Magick::Blob coalescedBlob; + Magick::writeImages(coalescedList.begin(), coalescedList.end(), &coalescedBlob); + coalescedImage.read(coalescedBlob); + *localImage = coalescedImage; + Magick::Blob previewBlob; + coalescedImage.write(&previewBlob); + Magick::writeImages(coalescedList.begin(), coalescedList.end(), &previewBlob); + auto previewBase64 = previewBlob.base64(); + auto previewImage = Wt::Utils::base64Decode(previewBase64); + std::string imageFormat = coalescedImage.magick(); + auto imageResource = std::make_shared( + "image/" + imageFormat, + std::vector(previewImage.begin(), previewImage.end())); + image->setImageLink(Wt::WLink(imageResource)); + image->resize(Wt::WLength(localImage->columns(), Wt::LengthUnit::Pixel), Wt::WLength(localImage->rows(), Wt::LengthUnit::Pixel)); + std::cout << __LINE__ << std::endl; + okButton->setEnabled(true); + triggerUpdate(); + } catch (const std::exception& e) { + std::cerr << "Error processing uploaded image: " << e.what() << std::endl; + } +} + Magick::Image App::scaleImage(const Magick::Image& originalImage, int maxSize) const { int scale = 100; int maxDimension = std::max(originalImage.size().width(), originalImage.size().height()); @@ -654,8 +667,11 @@ Wt::WWebWidget* App::createImageElement(Wt::Json::Object& line, const std::strin imageLineItem->addNew(outputText)->setStyleClass("output-line"); auto image = imageLineItem->addNew(); auto imageBlob = Wt::Utils::base64Decode((std::string)imageDescription["imageblobbase64"]); + Magick::Image magickImage; + magickImage.read(imageBlob); + std::string imageFormat = magickImage.magick(); auto imageResource = std::make_shared( - "image/png", + "image/" + imageFormat, std::vector(imageBlob.begin(), imageBlob.end())); image->setImageLink(Wt::WLink(imageResource)); image->resize(Wt::WLength((int)imageDescription["width"], Wt::LengthUnit::Pixel), Wt::WLength((int)imageDescription["height"], Wt::LengthUnit::Pixel)); @@ -749,8 +765,9 @@ void App::updateUserinfo(Wt::Json::Object data) { auto infoLayoutItem = containerLayout->itemAt(0); auto infoWidget = (Wt::WContainerWidget*)(infoLayoutItem->widget()); auto infoWidgetLayout = (Wt::WHBoxLayout*)infoWidget->layout(); - auto infoTextWidget = dynamic_cast(infoWidgetLayout->itemAt(0)->widget()); - auto blockButton = dynamic_cast(infoWidgetLayout->itemAt(1)->widget()); + auto infoTextWidget = dynamic_cast(infoWidgetLayout->itemAt(1)->widget()); + auto blockButton = dynamic_cast(infoWidgetLayout->itemAt(2)->widget()); + std::cout << Wt::Json::serialize(userData) << std::endl; try { infoWidget->setStyleClass(Wt::WString("user-conversation-info userlist-gender-{1}").arg((std::string)userData["gender"])); if (infoTextWidget) { @@ -792,15 +809,20 @@ void App::toggleSmileysBar(Wt::WContainerWidget *smileyBar) { smileyBar->setHidden(!smileyBar->isHidden()); } -void App::showSystemMessage(Wt::Json::Object broadcast) { - if ((std::string)broadcast["relatedUser"] != currentConversationWith_) { +void App::systemEvent(Wt::Json::Object broadcast) { + if ((std::string)broadcast["related-user"] != currentConversationWith_) { return; } auto containerLayout = (Wt::WVBoxLayout*)contentContainer_->layout(); - auto outputLayoutItem = containerLayout->itemAt(1); - auto outputContainer = (Wt::WContainerWidget*)outputLayoutItem->widget(); - auto outputLine = outputContainer->addNew((std::string)broadcast["data"]); - outputLine->setStyleClass("system-message"); + auto infoLayoutItem = containerLayout->itemAt(0); + auto infoWidget = (Wt::WContainerWidget*)(infoLayoutItem->widget()); + auto infoWidgetLayout = (Wt::WHBoxLayout*)infoWidget->layout(); + auto blockButton = dynamic_cast(infoWidgetLayout->itemAt(2)->widget()); + if (broadcast["data"] == "blocked") { + blockButton->setText("Unblock"); + } else if (broadcast["data"] == "unblocked") { + blockButton->setText("Block"); + } } @@ -1219,7 +1241,7 @@ void App::incomingBroadcast() { } else if (broadcast["type"] == "userinfo") { updateUserinfo(broadcast); } else if (broadcast["type"] == "system") { - showSystemMessage(broadcast); + systemEvent(broadcast); } else if (broadcast["type"] == "conversation-start") { showConversation(broadcast); } else if (broadcast["type"] == "search-result") { diff --git a/src/app.h b/src/app.h index 35b11b8..d251953 100644 --- a/src/app.h +++ b/src/app.h @@ -11,6 +11,7 @@ namespace Magick { class Image; + class Blob; } class App : public Wt::WApplication, public Client { @@ -140,7 +141,7 @@ private: void updateUserinfo(Wt::Json::Object data); std::unique_ptr createSmileysBar(Wt::WLineEdit *inputLine, std::shared_ptr cursorPosition); void toggleSmileysBar(Wt::WContainerWidget *smileyBar); - void showSystemMessage(Wt::Json::Object broadcast); + void systemEvent(Wt::Json::Object broadcast); void addStartChatButton(Wt::WGridLayout *contentGrid, Wt::WLineEdit *userName, Wt::WComboBox *country, Wt::WSpinBox *age, Wt::WComboBox *gender); Wt::WComboBox *addCountrySelection(Wt::WGridLayout *contentGrid); Wt::WSpinBox *addAgeInput(Wt::WGridLayout *contentGrid); @@ -205,6 +206,9 @@ private: void addLoginTimeView(); void addTimeoutView(); void showPartnerSites(); + void sendImage(); + void imageUploaded(Wt::WFileUpload *fileWidget, std::shared_ptr localImage, Wt::WImage *image, Wt::WPushButton *okButton); + bool isAnimatedGIF(const Magick::Blob &blob); }; #endif // APP_H diff --git a/src/broadcast.cpp b/src/broadcast.cpp index 8fd8477..4ed7eea 100644 --- a/src/broadcast.cpp +++ b/src/broadcast.cpp @@ -324,7 +324,7 @@ void Broadcast::sendUserInformation(std::string sendToSessionId, std::string use if (blockings_.find(userName) == blockings_.end()) { blockings_[userName] = std::set(); } - userData["blocked"] = !(blockings_.find(userName) == blockings_.end() || blockings_[userName].find(requestingUserName) == blockings_[userName].end()); + userData["blocked"] = (blockings_.find(userName) != blockings_.end() && blockings_[userName].find(requestingUserName) != blockings_[userName].end()); Wt::Json::Object broadcast{ {"type", "userinfo"}, {"data", userData} @@ -341,10 +341,9 @@ void Broadcast::toggleBlockUser(std::string blockingUserName, std::string blocke blockings_[blockedUser].erase(blockingUserName); sendUnblockDone(blockingUserSessionId, blockedUser); } else { - blockings_[blockedUser].insert(blockingUserSessionId); + blockings_[blockedUser].insert(blockingUserName); sendBlockDone(blockingUserSessionId, blockedUser); } - sendUserInformation(blockingUserSessionId, blockedUser, blockingUserName); } void Broadcast::requestConversation(std::string sendToSessionId, std::string withUserName, std::string requestingUserName) { @@ -524,20 +523,22 @@ void Broadcast::sendBlockedMessage(std::string sessionId, std::string toUserName } void Broadcast::sendBlockDone(std::string sessionId, std::string toUserName) { + addMessage(sessionId, toUserName, Message("Conversation is blocked.")); Wt::Json::Object broadcast{ {"type", "system"}, {"related-user", Wt::WString(toUserName)}, - {"data", "User is blocked."} + {"data", "blocked"} }; addMessageToSessionBroadcast(sessionId, broadcast); } void Broadcast::sendUnblockDone(std::string sessionId, std::string toUserName) { + addMessage(sessionId, toUserName, Message("Conversation is unblocked.")); Wt::Json::Object broadcast{ {"type", "system"}, {"related-user", Wt::WString(toUserName)}, - {"data", "User is unblocked."} + {"data", "unblocked"} }; addMessageToSessionBroadcast(sessionId, broadcast); } @@ -671,6 +672,18 @@ Broadcast::Message::Message(std::string fromSessionId_, std::shared_ptr image_); + Message(Wt::WString message_); + bool systemMessage{false}; std::string fromSessionId; std::string sendType; Wt::WDateTime sendTime;