diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp index ff3c92a3..0a1c93e6 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettings.cpp @@ -363,97 +363,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) auto filter = new ClickableFilter(this); avatar_->installEventFilter(filter); avatar_->setCursor(Qt::PointingHandCursor); - connect(filter, &ClickableFilter::clicked, this, [this]() { - const auto fileName = QFileDialog::getOpenFileName( - this, tr("Select an avatar"), "", tr("All Files (*)")); - - if (fileName.isEmpty()) - return; - - QMimeDatabase db; - QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent); - - const auto format = mime.name().split("/")[0]; - - QFile file{fileName, this}; - if (format != "image") { - displayErrorMessage(tr("The selected media is not an image")); - return; - } - - if (!file.open(QIODevice::ReadOnly)) { - displayErrorMessage( - tr("Error while reading media: %1").arg(file.errorString())); - return; - } - - if (spinner_) { - startLoadingSpinner(); - resetErrorLabel(); - } - - // Events emitted from the http callbacks (different threads) will - // be queued back into the UI thread through this proxy object. - auto proxy = std::make_shared(); - connect(proxy.get(), - &ThreadProxy::error, - this, - &RoomSettings::displayErrorMessage); - connect( - proxy.get(), &ThreadProxy::avatarChanged, this, &RoomSettings::setAvatar); - - const auto bin = file.peek(file.size()); - const auto payload = std::string(bin.data(), bin.size()); - const auto dimensions = QImageReader(&file).size(); - - // First we need to create a new mxc URI - // (i.e upload media to the Matrix content repository) for the new avatar. - http::client()->upload( - payload, - mime.name().toStdString(), - QFileInfo(fileName).fileName().toStdString(), - [proxy = std::move(proxy), - dimensions, - payload, - mimetype = mime.name().toStdString(), - size = payload.size(), - room_id = room_id_.toStdString(), - content = std::move(bin)](const mtx::responses::ContentURI &res, - mtx::http::RequestErr err) { - if (err) { - emit proxy->error(tr("Failed to upload image: %s") - .arg(QString::fromStdString( - err->matrix_error.error))); - return; - } - - using namespace mtx::events; - state::Avatar avatar_event; - avatar_event.image_info.w = dimensions.width(); - avatar_event.image_info.h = dimensions.height(); - avatar_event.image_info.mimetype = mimetype; - avatar_event.image_info.size = size; - avatar_event.url = res.content_uri; - - http::client() - ->send_state_event( - room_id, - avatar_event, - [content = std::move(content), - proxy = std::move(proxy)](const mtx::responses::EventId &, - mtx::http::RequestErr err) { - if (err) { - emit proxy->error( - tr("Failed to upload image: %s") - .arg(QString::fromStdString( - err->matrix_error.error))); - return; - } - - emit proxy->avatarChanged(QImage::fromData(content)); - }); - }); - }); + connect(filter, &ClickableFilter::clicked, this, &RoomSettings::updateAvatar); } auto roomNameLabel = new QLabel(QString::fromStdString(info_.name), this); @@ -737,3 +647,89 @@ RoomSettings::resetErrorLabel() errorLabel_->clear(); } } + +void +RoomSettings::updateAvatar() +{ + const auto fileName = + QFileDialog::getOpenFileName(this, tr("Select an avatar"), "", tr("All Files (*)")); + + if (fileName.isEmpty()) + return; + + QMimeDatabase db; + QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent); + + const auto format = mime.name().split("/")[0]; + + QFile file{fileName, this}; + if (format != "image") { + displayErrorMessage(tr("The selected media is not an image")); + return; + } + + if (!file.open(QIODevice::ReadOnly)) { + displayErrorMessage(tr("Error while reading media: %1").arg(file.errorString())); + return; + } + + if (spinner_) { + startLoadingSpinner(); + resetErrorLabel(); + } + + // Events emitted from the http callbacks (different threads) will + // be queued back into the UI thread through this proxy object. + auto proxy = std::make_shared(); + connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayErrorMessage); + connect(proxy.get(), &ThreadProxy::avatarChanged, this, &RoomSettings::setAvatar); + + const auto bin = file.peek(file.size()); + const auto payload = std::string(bin.data(), bin.size()); + const auto dimensions = QImageReader(&file).size(); + + // First we need to create a new mxc URI + // (i.e upload media to the Matrix content repository) for the new avatar. + http::client()->upload( + payload, + mime.name().toStdString(), + QFileInfo(fileName).fileName().toStdString(), + [proxy = std::move(proxy), + dimensions, + payload, + mimetype = mime.name().toStdString(), + size = payload.size(), + room_id = room_id_.toStdString(), + content = std::move(bin)](const mtx::responses::ContentURI &res, + mtx::http::RequestErr err) { + if (err) { + emit proxy->error( + tr("Failed to upload image: %s") + .arg(QString::fromStdString(err->matrix_error.error))); + return; + } + + using namespace mtx::events; + state::Avatar avatar_event; + avatar_event.image_info.w = dimensions.width(); + avatar_event.image_info.h = dimensions.height(); + avatar_event.image_info.mimetype = mimetype; + avatar_event.image_info.size = size; + avatar_event.url = res.content_uri; + + http::client()->send_state_event( + room_id, + avatar_event, + [content = std::move(content), proxy = std::move(proxy)]( + const mtx::responses::EventId &, mtx::http::RequestErr err) { + if (err) { + emit proxy->error( + tr("Failed to upload image: %s") + .arg(QString::fromStdString(err->matrix_error.error))); + return; + } + + emit proxy->avatarChanged(QImage::fromData(content)); + }); + }); +} diff --git a/src/dialogs/RoomSettings.h b/src/dialogs/RoomSettings.h index ebc9f04a..ac9097dd 100644 --- a/src/dialogs/RoomSettings.h +++ b/src/dialogs/RoomSettings.h @@ -102,6 +102,10 @@ protected: void paintEvent(QPaintEvent *event) override; void showEvent(QShowEvent *event) override; +private slots: + //! The file dialog opens so the user can select and upload a new room avatar. + void updateAvatar(); + private: //! Whether the user has enough power level to send m.room.join_rules events. bool canChangeJoinRules(const std::string &room_id, const std::string &user_id) const;