summary refs log tree commit diff
path: root/src/CommunitiesList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/CommunitiesList.cpp')
-rw-r--r--src/CommunitiesList.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/src/CommunitiesList.cpp b/src/CommunitiesList.cpp
new file mode 100644

index 00000000..c271be89 --- /dev/null +++ b/src/CommunitiesList.cpp
@@ -0,0 +1,195 @@ +#include "CommunitiesList.h" +#include "Cache.h" +#include "Logging.h" +#include "MatrixClient.h" + +#include <QLabel> + +CommunitiesList::CommunitiesList(QWidget *parent) + : QWidget(parent) +{ + QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(1); + setSizePolicy(sizePolicy); + + setStyleSheet("border-style: none;"); + + topLayout_ = new QVBoxLayout(this); + topLayout_->setSpacing(0); + topLayout_->setMargin(0); + + setFixedWidth(ui::sidebar::CommunitiesSidebarSize); + + scrollArea_ = new QScrollArea(this); + scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + scrollArea_->setWidgetResizable(true); + scrollArea_->setAlignment(Qt::AlignLeading | Qt::AlignTop | Qt::AlignVCenter); + + scrollAreaContents_ = new QWidget(); + + contentsLayout_ = new QVBoxLayout(scrollAreaContents_); + contentsLayout_->setSpacing(0); + contentsLayout_->setMargin(0); + + addGlobalItem(); + contentsLayout_->addStretch(1); + + scrollArea_->setWidget(scrollAreaContents_); + topLayout_->addWidget(scrollArea_); + + connect( + this, &CommunitiesList::avatarRetrieved, this, &CommunitiesList::updateCommunityAvatar); +} + +void +CommunitiesList::setCommunities(const mtx::responses::JoinedGroups &response) +{ + communities_.clear(); + + addGlobalItem(); + + for (const auto &group : response.groups) + addCommunity(group); + + communities_["world"]->setPressedState(true); + emit communityChanged("world"); +} + +void +CommunitiesList::addCommunity(const std::string &group_id) +{ + const auto id = QString::fromStdString(group_id); + + CommunitiesListItem *list_item = new CommunitiesListItem(id, scrollArea_); + communities_.emplace(id, QSharedPointer<CommunitiesListItem>(list_item)); + contentsLayout_->insertWidget(contentsLayout_->count() - 1, list_item); + + connect(this, + &CommunitiesList::groupProfileRetrieved, + this, + [this](const QString &id, const mtx::responses::GroupProfile &profile) { + if (communities_.find(id) == communities_.end()) + return; + + communities_.at(id)->setName(QString::fromStdString(profile.name)); + + if (!profile.avatar_url.empty()) + fetchCommunityAvatar(id, + QString::fromStdString(profile.avatar_url)); + }); + connect(this, + &CommunitiesList::groupRoomsRetrieved, + this, + [this](const QString &id, const std::vector<QString> &rooms) { + if (communities_.find(id) == communities_.end()) + return; + + communities_.at(id)->setRooms(rooms); + }); + connect(list_item, + &CommunitiesListItem::clicked, + this, + &CommunitiesList::highlightSelectedCommunity); + + http::client()->group_profile( + group_id, [id, this](const mtx::responses::GroupProfile &res, mtx::http::RequestErr err) { + if (err) { + return; + } + + emit groupProfileRetrieved(id, res); + }); + + http::client()->group_rooms( + group_id, [id, this](const nlohmann::json &res, mtx::http::RequestErr err) { + if (err) { + return; + } + + std::vector<QString> room_ids; + for (const auto &room : res.at("chunk")) + room_ids.push_back(QString::fromStdString(room.at("room_id"))); + + emit groupRoomsRetrieved(id, room_ids); + }); +} + +void +CommunitiesList::updateCommunityAvatar(const QString &community_id, const QPixmap &img) +{ + if (!communityExists(community_id)) { + qWarning() << "Avatar update on nonexistent community" << community_id; + return; + } + + communities_.at(community_id)->setAvatar(img.toImage()); +} + +void +CommunitiesList::highlightSelectedCommunity(const QString &community_id) +{ + if (!communityExists(community_id)) { + qDebug() << "CommunitiesList: clicked unknown community"; + return; + } + + emit communityChanged(community_id); + + for (const auto &community : communities_) { + if (community.first != community_id) { + community.second->setPressedState(false); + } else { + community.second->setPressedState(true); + scrollArea_->ensureWidgetVisible(community.second.data()); + } + } +} + +void +CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUrl) +{ + auto savedImgData = cache::client()->image(avatarUrl); + if (!savedImgData.isNull()) { + QPixmap pix; + pix.loadFromData(savedImgData); + emit avatarRetrieved(id, pix); + return; + } + + if (avatarUrl.isEmpty()) + return; + + mtx::http::ThumbOpts opts; + opts.mxc_url = avatarUrl.toStdString(); + http::client()->get_thumbnail( + opts, [this, opts, id](const std::string &res, mtx::http::RequestErr err) { + if (err) { + nhlog::net()->warn("failed to download avatar: {} - ({} {})", + opts.mxc_url, + mtx::errors::to_string(err->matrix_error.errcode), + err->matrix_error.error); + return; + } + + cache::client()->saveImage(opts.mxc_url, res); + + auto data = QByteArray(res.data(), res.size()); + + QPixmap pix; + pix.loadFromData(data); + + emit avatarRetrieved(id, pix); + }); +} + +std::vector<QString> +CommunitiesList::roomList(const QString &id) const +{ + if (communityExists(id)) + return communities_.at(id)->rooms(); + + return {}; +}