summary refs log tree commit diff
path: root/src/dialogs/RoomSettings.cpp
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-08-29 16:00:07 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-08-29 16:00:07 +0300
commit56ee290b035c4832accc33632730afe8e3899d78 (patch)
tree531843196495ae7d2a6dc6e1b6f0c3f3aed6a22a /src/dialogs/RoomSettings.cpp
parentCall adjustSize before showing the timeline widget (diff)
downloadnheko-56ee290b035c4832accc33632730afe8e3899d78.tar.xz
Add the ability to change the room avatar
fixes #418
Diffstat (limited to 'src/dialogs/RoomSettings.cpp')
-rw-r--r--src/dialogs/RoomSettings.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp

index 2cba2990..ff3c92a3 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettings.cpp
@@ -1,7 +1,10 @@ #include <QApplication> #include <QComboBox> +#include <QFileDialog> +#include <QImageReader> #include <QLabel> #include <QMessageBox> +#include <QMimeDatabase> #include <QPainter> #include <QPixmap> #include <QShowEvent> @@ -356,6 +359,103 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) else avatar_->setImage(avatarImg_); + if (canChangeAvatar(room_id_.toStdString(), utils::localUser().toStdString())) { + 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<ThreadProxy>(); + 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<state::Avatar, EventType::RoomAvatar>( + 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)); + }); + }); + }); + } + auto roomNameLabel = new QLabel(QString::fromStdString(info_.name), this); roomNameLabel->setFont(doubleFont); @@ -537,6 +637,19 @@ RoomSettings::canChangeNameAndTopic(const std::string &room_id, const std::strin return false; } +bool +RoomSettings::canChangeAvatar(const std::string &room_id, const std::string &user_id) const +{ + try { + return cache::client()->hasEnoughPowerLevel( + {EventType::RoomAvatar}, room_id, user_id); + } catch (const lmdb::error &e) { + nhlog::db()->warn("lmdb error: {}", e.what()); + } + + return false; +} + void RoomSettings::updateAccessRules(const std::string &room_id, const mtx::events::state::JoinRules &join_rule, @@ -597,6 +710,26 @@ RoomSettings::startLoadingSpinner() } void +RoomSettings::displayErrorMessage(const QString &msg) +{ + stopLoadingSpinner(); + + errorLabel_->show(); + errorLabel_->setText(msg); +} + +void +RoomSettings::setAvatar(const QImage &img) +{ + stopLoadingSpinner(); + + avatarImg_ = img; + + if (avatar_) + avatar_->setImage(img); +} + +void RoomSettings::resetErrorLabel() { if (errorLabel_) {