From f11044b5eb9cf42cc71930b567b7566f1293a936 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Tue, 19 Dec 2017 22:36:12 +0200 Subject: [PATCH] Handle incoming invites fixes #128 --- include/Cache.h | 7 ++ include/ChatPage.h | 1 + include/RoomInfoListItem.h | 79 +++++++++---- include/RoomList.h | 6 + libs/matrix-structs | 2 +- resources/styles/nheko-dark.qss | 3 + resources/styles/nheko.qss | 3 + resources/styles/system.qss | 3 + src/Cache.cc | 95 +++++++++++++++- src/ChatPage.cc | 28 ++++- src/RoomInfoListItem.cc | 189 +++++++++++++++++++++----------- src/RoomList.cc | 29 +++++ 12 files changed, 352 insertions(+), 93 deletions(-) diff --git a/include/Cache.h b/include/Cache.h index 031c8b16..c141a42a 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -19,6 +19,7 @@ #include #include +#include class RoomState; @@ -33,10 +34,15 @@ public: QString nextBatchToken() const; QMap states(); + using Invites = std::map; + Invites invites(); + void setInvites(const Invites &invites); + void deleteData(); void unmount() { isMounted_ = false; }; void removeRoom(const QString &roomid); + void removeInvite(const QString &roomid); void setup(); bool isFormatValid(); @@ -49,6 +55,7 @@ private: lmdb::env env_; lmdb::dbi stateDb_; lmdb::dbi roomDb_; + lmdb::dbi invitesDb_; bool isMounted_; diff --git a/include/ChatPage.h b/include/ChatPage.h index 94c54f0b..14d44ff3 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h @@ -78,6 +78,7 @@ private slots: void logout(); void addRoom(const QString &room_id); void removeRoom(const QString &room_id); + void removeInvite(const QString &room_id); private: using UserID = QString; diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h index acb1ab84..d4e4f983 100644 --- a/include/RoomInfoListItem.h +++ b/include/RoomInfoListItem.h @@ -21,6 +21,8 @@ #include #include +#include + #include "RoomState.h" class Menu; @@ -52,12 +54,17 @@ class RoomInfoListItem : public QWidget Q_PROPERTY(QColor highlightedSubtitleColor READ highlightedSubtitleColor WRITE setHighlightedSubtitleColor) + Q_PROPERTY(QColor btnColor READ btnColor WRITE setBtnColor) + Q_PROPERTY(QColor btnTextColor READ btnTextColor WRITE setBtnTextColor) + public: RoomInfoListItem(QSharedPointer settings, RoomState state, QString room_id, QWidget *parent = 0); + RoomInfoListItem(QString room_id, mtx::responses::InvitedRoom room, QWidget *parent = 0); + ~RoomInfoListItem(); void updateUnreadMessageCount(int count); @@ -71,35 +78,36 @@ public: void setAvatar(const QImage &avatar_image); void setDescriptionMessage(const DescInfo &info); - inline QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; } - inline QColor hoverBackgroundColor() const { return hoverBackgroundColor_; } - inline QColor backgroundColor() const { return backgroundColor_; } + QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; } + QColor hoverBackgroundColor() const { return hoverBackgroundColor_; } + QColor backgroundColor() const { return backgroundColor_; } - inline QColor highlightedTitleColor() const { return highlightedTitleColor_; } - inline QColor highlightedSubtitleColor() const { return highlightedSubtitleColor_; } + QColor highlightedTitleColor() const { return highlightedTitleColor_; } + QColor highlightedSubtitleColor() const { return highlightedSubtitleColor_; } - inline QColor titleColor() const { return titleColor_; } - inline QColor subtitleColor() const { return subtitleColor_; } + QColor titleColor() const { return titleColor_; } + QColor subtitleColor() const { return subtitleColor_; } + QColor btnColor() const { return btnColor_; } + QColor btnTextColor() const { return btnTextColor_; } - inline void setHighlightedBackgroundColor(QColor &color) - { - highlightedBackgroundColor_ = color; - } - inline void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; } - inline void setBackgroundColor(QColor &color) { backgroundColor_ = color; } + void setHighlightedBackgroundColor(QColor &color) { highlightedBackgroundColor_ = color; } + void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; } + void setBackgroundColor(QColor &color) { backgroundColor_ = color; } - inline void setHighlightedTitleColor(QColor &color) { highlightedTitleColor_ = color; } - inline void setHighlightedSubtitleColor(QColor &color) - { - highlightedSubtitleColor_ = color; - } + void setHighlightedTitleColor(QColor &color) { highlightedTitleColor_ = color; } + void setHighlightedSubtitleColor(QColor &color) { highlightedSubtitleColor_ = color; } - inline void setTitleColor(QColor &color) { titleColor_ = color; } - inline void setSubtitleColor(QColor &color) { subtitleColor_ = color; } + void setTitleColor(QColor &color) { titleColor_ = color; } + void setSubtitleColor(QColor &color) { subtitleColor_ = color; } + + void setBtnColor(QColor &color) { btnColor_ = color; } + void setBtnTextColor(QColor &color) { btnTextColor_ = color; } signals: void clicked(const QString &room_id); void leaveRoom(const QString &room_id); + void acceptInvite(const QString &room_id); + void declineInvite(const QString &room_id); public slots: void setPressedState(bool state); @@ -111,15 +119,33 @@ protected: void contextMenuEvent(QContextMenuEvent *event) override; private: - QString notificationText(); + void init(QWidget *parent); + QString roomName() + { + if (roomType_ == RoomType::Joined) + return state_.getName(); - const int Padding = 7; - const int IconSize = 48; + return roomName_; + } + + QString notificationText(); RippleOverlay *ripple_overlay_; + enum class RoomType + { + Joined, + Invited, + }; + + RoomType roomType_ = RoomType::Joined; + + // State information for the joined rooms. RoomState state_; + // State information for the invited rooms. + mtx::responses::InvitedRoom invitedRoom_; + QString roomId_; QString roomName_; @@ -135,7 +161,6 @@ private: bool isPressed_ = false; - int maxHeight_; int unreadMsgCount_ = 0; QColor highlightedBackgroundColor_; @@ -147,4 +172,10 @@ private: QColor titleColor_; QColor subtitleColor_; + + QColor btnColor_; + QColor btnTextColor_; + + QRectF acceptBtnRegion_; + QRectF declineBtnRegion_; }; diff --git a/include/RoomList.h b/include/RoomList.h index f75f7ba4..8487df10 100644 --- a/include/RoomList.h +++ b/include/RoomList.h @@ -24,6 +24,8 @@ #include #include +#include + #include "dialogs/LeaveRoom.h" class LeaveRoomDialog; @@ -47,17 +49,21 @@ public: const QMap &states); void sync(const QMap &states, QMap> &settings); + void syncInvites(const std::map &rooms); void clear(); void addRoom(const QMap> &settings, const RoomState &state, const QString &room_id); + void addInvitedRoom(const QString &room_id, const mtx::responses::InvitedRoom &room); void removeRoom(const QString &room_id, bool reset); signals: void roomChanged(const QString &room_id); void totalUnreadMessageCountUpdated(int count); + void acceptInvite(const QString &room_id); + void declineInvite(const QString &room_id); public slots: void updateRoomAvatar(const QString &roomid, const QPixmap &img); diff --git a/libs/matrix-structs b/libs/matrix-structs index ff5a9c88..582c6956 160000 --- a/libs/matrix-structs +++ b/libs/matrix-structs @@ -1 +1 @@ -Subproject commit ff5a9c887af1a8cffd13876abcf4c079a8525bd3 +Subproject commit 582c6956c464e80f738c57ded239c3fb613f1c24 diff --git a/resources/styles/nheko-dark.qss b/resources/styles/nheko-dark.qss index 0fd519ea..a730a6e0 100644 --- a/resources/styles/nheko-dark.qss +++ b/resources/styles/nheko-dark.qss @@ -49,6 +49,9 @@ RoomInfoListItem { qproperty-highlightedTitleColor: #e4e5e8; qproperty-highlightedSubtitleColor: #e4e5e8; + + qproperty-btnColor: #414A59; + qproperty-btnTextColor: white; } LoadingIndicator { diff --git a/resources/styles/nheko.qss b/resources/styles/nheko.qss index c55b64fb..3e740e2a 100644 --- a/resources/styles/nheko.qss +++ b/resources/styles/nheko.qss @@ -47,6 +47,9 @@ RoomInfoListItem { qproperty-highlightedTitleColor: white; qproperty-highlightedSubtitleColor: white; + + qproperty-btnColor: #ccc; + qproperty-btnTextColor: #333; } #ChatPageLoadSpinner { diff --git a/resources/styles/system.qss b/resources/styles/system.qss index e6dab15e..afb2ad26 100644 --- a/resources/styles/system.qss +++ b/resources/styles/system.qss @@ -55,6 +55,9 @@ RoomInfoListItem { qproperty-highlightedTitleColor: palette(light); qproperty-highlightedSubtitleColor: palette(light); + + qproperty-btnColor: palette(light); + qproperty-btnTextColor: palette(text); } LoadingIndicator { diff --git a/src/Cache.cc b/src/Cache.cc index 7d044e8f..4e2f32a9 100644 --- a/src/Cache.cc +++ b/src/Cache.cc @@ -33,6 +33,7 @@ Cache::Cache(const QString &userId) : env_{nullptr} , stateDb_{0} , roomDb_{0} + , invitesDb_{0} , isMounted_{false} , userId_{userId} {} @@ -86,9 +87,10 @@ Cache::setup() env_.open(statePath.toStdString().c_str()); } - auto txn = lmdb::txn::begin(env_); - stateDb_ = lmdb::dbi::open(txn, "state", MDB_CREATE); - roomDb_ = lmdb::dbi::open(txn, "rooms", MDB_CREATE); + auto txn = lmdb::txn::begin(env_); + stateDb_ = lmdb::dbi::open(txn, "state", MDB_CREATE); + roomDb_ = lmdb::dbi::open(txn, "rooms", MDB_CREATE); + invitesDb_ = lmdb::dbi::open(txn, "invites", MDB_CREATE); txn.commit(); @@ -174,6 +176,20 @@ Cache::removeRoom(const QString &roomid) txn.commit(); } +void +Cache::removeInvite(const QString &room_id) +{ + if (!isMounted_) + return; + + auto txn = lmdb::txn::begin(env_, nullptr, 0); + + lmdb::dbi_del( + txn, invitesDb_, lmdb::val(room_id.toUtf8(), room_id.toUtf8().size()), nullptr); + + txn.commit(); +} + QMap Cache::states() { @@ -310,3 +326,76 @@ Cache::setCurrentFormat() txn.commit(); } + +std::map +Cache::invites() +{ + std::map invites; + + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + auto cursor = lmdb::cursor::open(txn, invitesDb_); + + std::string room_id; + std::string payload; + + mtx::responses::InvitedRoom state; + + while (cursor.get(room_id, payload, MDB_NEXT)) { + state = nlohmann::json::parse(payload); + invites.emplace(room_id, state); + } + + if (invites.size() > 0) + qDebug() << "Retrieved" << invites.size() << "invites"; + + cursor.close(); + + txn.commit(); + + return invites; +} + +void +Cache::setInvites(const std::map &invites) +{ + if (!isMounted_) + return; + + using Aliases = mtx::events::StrippedEvent; + using Avatar = mtx::events::StrippedEvent; + using Member = mtx::events::StrippedEvent; + using Name = mtx::events::StrippedEvent; + using Topic = mtx::events::StrippedEvent; + + try { + auto txn = lmdb::txn::begin(env_); + + for (auto it = invites.cbegin(); it != invites.cend(); ++it) { + nlohmann::json j; + + for (const auto &e : it->second.invite_state) { + if (mpark::holds_alternative(e)) { + j["invite_state"]["events"].push_back(mpark::get(e)); + } else if (mpark::holds_alternative(e)) { + j["invite_state"]["events"].push_back(mpark::get(e)); + } else if (mpark::holds_alternative(e)) { + j["invite_state"]["events"].push_back( + mpark::get(e)); + } else if (mpark::holds_alternative(e)) { + j["invite_state"]["events"].push_back( + mpark::get(e)); + } else if (mpark::holds_alternative(e)) { + j["invite_state"]["events"].push_back( + mpark::get(e)); + } + } + + lmdb::dbi_put(txn, invitesDb_, lmdb::val(it->first), lmdb::val(j.dump())); + } + + txn.commit(); + } catch (const lmdb::error &e) { + qCritical() << "setInvitedRooms: " << e.what(); + unmount(); + } +} diff --git a/src/ChatPage.cc b/src/ChatPage.cc index 5788c697..a5b36d81 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -134,6 +134,9 @@ ChatPage::ChatPage(QSharedPointer client, QWidget *parent) connect( room_list_, &RoomList::roomChanged, view_manager_, &TimelineViewManager::setHistoryView); + connect(room_list_, &RoomList::acceptInvite, client_.data(), &MatrixClient::joinRoom); + connect(room_list_, &RoomList::declineInvite, client_.data(), &MatrixClient::leaveRoom); + connect(view_manager_, &TimelineViewManager::clearRoomMessageCount, room_list_, @@ -266,8 +269,9 @@ ChatPage::ChatPage(QSharedPointer client, QWidget *parent) this, &ChatPage::updateOwnProfileInfo); connect(client_.data(), &MatrixClient::ownAvatarRetrieved, this, &ChatPage::setOwnAvatar); - connect(client_.data(), &MatrixClient::joinedRoom, this, [=]() { + connect(client_.data(), &MatrixClient::joinedRoom, this, [=](const QString &room_id) { emit showNotification("You joined the room."); + removeInvite(room_id); }); connect(client_.data(), &MatrixClient::invitedUser, this, [=](QString, QString user) { emit showNotification(QString("Invited user %1").arg(user)); @@ -400,8 +404,11 @@ ChatPage::syncCompleted(const mtx::responses::Sync &response) auto stateDiff = generateMembershipDifference(response.rooms.join, state_manager_); QtConcurrent::run(cache_.data(), &Cache::setState, nextBatchToken, stateDiff); + QtConcurrent::run(cache_.data(), &Cache::setInvites, response.rooms.invite); room_list_->sync(state_manager_, settingsManager_); + room_list_->syncInvites(response.rooms.invite); + view_manager_->sync(response.rooms); client_->setNextBatchToken(nextBatchToken); @@ -445,12 +452,14 @@ ChatPage::initialSyncCompleted(const mtx::responses::Sync &response) &Cache::setState, QString::fromStdString(response.next_batch), state_manager_); + QtConcurrent::run(cache_.data(), &Cache::setInvites, response.rooms.invite); // Populate timelines with messages. view_manager_->initialize(response.rooms); // Initialize room list. room_list_->setInitialRooms(settingsManager_, state_manager_); + room_list_->syncInvites(response.rooms.invite); client_->setNextBatchToken(QString::fromStdString(response.next_batch)); client_->sync(); @@ -552,6 +561,7 @@ ChatPage::loadStateFromCache() // Initialize room list from the restored state and settings. room_list_->setInitialRooms(settingsManager_, state_manager_); + room_list_->syncInvites(cache_->invites()); // Check periodically if the timelines have been loaded. consensusTimer_->start(CONSENSUS_TIMEOUT); @@ -629,6 +639,7 @@ ChatPage::removeRoom(const QString &room_id) settingsManager_.remove(room_id); try { cache_->removeRoom(room_id); + cache_->removeInvite(room_id); } catch (const lmdb::error &e) { qCritical() << "The cache couldn't be updated: " << e.what(); // TODO: Notify the user. @@ -638,6 +649,21 @@ ChatPage::removeRoom(const QString &room_id) room_list_->removeRoom(room_id, room_id == current_room_); } +void +ChatPage::removeInvite(const QString &room_id) +{ + try { + cache_->removeInvite(room_id); + } catch (const lmdb::error &e) { + qCritical() << "The cache couldn't be updated: " << e.what(); + // TODO: Notify the user. + cache_->unmount(); + cache_->deleteData(); + } + + room_list_->removeRoom(room_id, room_id == current_room_); +} + void ChatPage::updateTypingUsers(const QString &roomid, const std::vector &user_ids) { diff --git a/src/RoomInfoListItem.cc b/src/RoomInfoListItem.cc index 875bb506..fa567243 100644 --- a/src/RoomInfoListItem.cc +++ b/src/RoomInfoListItem.cc @@ -15,9 +15,12 @@ * along with this program. If not, see . */ +#include #include #include +#include + #include "Config.h" #include "Menu.h" #include "Ripple.h" @@ -26,6 +29,44 @@ #include "RoomSettings.h" #include "Theme.h" +constexpr int Padding = 7; +constexpr int IconSize = 48; +constexpr int MaxHeight = IconSize + 2 * Padding; + +constexpr int InviteBtnX = IconSize + 2 * Padding; +constexpr int InviteBtnY = IconSize / 2 + Padding; + +void +RoomInfoListItem::init(QWidget *parent) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setMouseTracking(true); + setAttribute(Qt::WA_Hover); + + setFixedHeight(MaxHeight); + + QPainterPath path; + path.addRect(0, 0, parent->width(), height()); + + ripple_overlay_ = new RippleOverlay(this); + ripple_overlay_->setClipPath(path); + ripple_overlay_->setClipping(true); +} + +RoomInfoListItem::RoomInfoListItem(QString room_id, + mtx::responses::InvitedRoom room, + QWidget *parent) + : QWidget(parent) + , roomType_{RoomType::Invited} + , invitedRoom_{std::move(room)} + , roomId_{std::move(room_id)} +{ + init(parent); + + roomAvatar_ = QString::fromStdString(invitedRoom_.avatar()); + roomName_ = QString::fromStdString(invitedRoom_.name()); +} + RoomInfoListItem::RoomInfoListItem(QSharedPointer settings, RoomState state, QString room_id, @@ -35,21 +76,9 @@ RoomInfoListItem::RoomInfoListItem(QSharedPointer settings, , roomId_(room_id) , roomSettings_{settings} , isPressed_(false) - , maxHeight_(IconSize + 2 * Padding) , unreadMsgCount_(0) { - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setMouseTracking(true); - setAttribute(Qt::WA_Hover); - - setFixedHeight(maxHeight_); - - QPainterPath path; - path.addRect(0, 0, parent->width(), height()); - - ripple_overlay_ = new RippleOverlay(this); - ripple_overlay_->setClipPath(path); - ripple_overlay_->setClipping(true); + init(parent); menu_ = new Menu(this); @@ -99,82 +128,100 @@ RoomInfoListItem::paintEvent(QPaintEvent *event) font.setPixelSize(conf::fontSize); QFontMetrics metrics(font); + QPen titlePen(titleColor_); + QPen subtitlePen(subtitleColor_); + if (isPressed_) { p.fillRect(rect(), highlightedBackgroundColor_); + titlePen.setColor(highlightedTitleColor_); + subtitlePen.setColor(highlightedSubtitleColor_); } else if (underMouse()) { p.fillRect(rect(), hoverBackgroundColor_); } else { p.fillRect(rect(), backgroundColor_); } - // p.setPen(QColor("#333")); - QRect avatarRegion(Padding, Padding, IconSize, IconSize); // Description line with the default font. - int bottom_y = maxHeight_ - Padding - Padding / 3 - metrics.ascent() / 2; + int bottom_y = MaxHeight - Padding - Padding / 3 - metrics.ascent() / 2; if (width() > ui::sidebar::SmallSize) { - if (isPressed_) { - QPen pen(highlightedTitleColor_); - p.setPen(pen); - } else { - QPen pen(titleColor_); - p.setPen(pen); - } font.setPixelSize(conf::roomlist::fonts::heading); p.setFont(font); + p.setPen(titlePen); // Name line. QFontMetrics fontNameMetrics(font); int top_y = 2 * Padding + fontNameMetrics.ascent() / 2; auto name = metrics.elidedText( - state_.getName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8); + roomName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8); p.drawText(QPoint(2 * Padding + IconSize, top_y), name); - if (isPressed_) { - QPen pen(highlightedSubtitleColor_); - p.setPen(pen); - } else { - QPen pen(subtitleColor_); - p.setPen(pen); - } + if (roomType_ == RoomType::Joined) { + font.setPixelSize(conf::fontSize); + p.setFont(font); + p.setPen(subtitlePen); - font.setPixelSize(conf::fontSize); - p.setFont(font); + auto msgStampWidth = QFontMetrics(font).width(lastMsgInfo_.timestamp) + 5; - auto msgStampWidth = QFontMetrics(font).width(lastMsgInfo_.timestamp) + 5; + // The limit is the space between the end of the avatar and the start of the + // timestamp. + int usernameLimit = + std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - 20); + auto userName = + metrics.elidedText(lastMsgInfo_.username, Qt::ElideRight, usernameLimit); - // The limit is the space between the end of the avatar and the start of the - // timestamp. - int usernameLimit = - std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - 20); - auto userName = - metrics.elidedText(lastMsgInfo_.username, Qt::ElideRight, usernameLimit); - - font.setBold(true); - p.setFont(font); - p.drawText(QPoint(2 * Padding + IconSize, bottom_y), userName); - - int nameWidth = QFontMetrics(font).width(userName); - - font.setBold(false); - p.setFont(font); - - // The limit is the space between the end of the username and the start of - // the timestamp. - int descriptionLimit = - std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - nameWidth - 5); - auto description = - metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit); - p.drawText(QPoint(2 * Padding + IconSize + nameWidth, bottom_y), description); - - // We either show the bubble or the last message timestamp. - if (unreadMsgCount_ == 0) { font.setBold(true); - p.drawText(QPoint(width() - Padding - msgStampWidth, bottom_y), - lastMsgInfo_.timestamp); + p.setFont(font); + p.drawText(QPoint(2 * Padding + IconSize, bottom_y), userName); + + int nameWidth = QFontMetrics(font).width(userName); + + font.setBold(false); + p.setFont(font); + + // The limit is the space between the end of the username and the start of + // the timestamp. + int descriptionLimit = std::max( + 0, width() - 3 * Padding - msgStampWidth - IconSize - nameWidth - 5); + auto description = + metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit); + p.drawText(QPoint(2 * Padding + IconSize + nameWidth, bottom_y), + description); + + // We either show the bubble or the last message timestamp. + if (unreadMsgCount_ == 0) { + font.setBold(true); + p.drawText(QPoint(width() - Padding - msgStampWidth, bottom_y), + lastMsgInfo_.timestamp); + } + } else { + int btnWidth = (width() - IconSize - 6 * Padding) / 2; + + acceptBtnRegion_ = QRectF(InviteBtnX, InviteBtnY, btnWidth, 20); + declineBtnRegion_ = + QRectF(InviteBtnX + btnWidth + 2 * Padding, InviteBtnY, btnWidth, 20); + + QPainterPath acceptPath; + acceptPath.addRoundedRect(acceptBtnRegion_, 10, 10); + + p.setPen(Qt::NoPen); + p.fillPath(acceptPath, btnColor_); + p.drawPath(acceptPath); + + QPainterPath declinePath; + declinePath.addRoundedRect(declineBtnRegion_, 10, 10); + + p.setPen(Qt::NoPen); + p.fillPath(declinePath, btnColor_); + p.drawPath(declinePath); + + p.setPen(QPen(btnTextColor_)); + p.setFont(font); + p.drawText(acceptBtnRegion_, Qt::AlignCenter, tr("Accept")); + p.drawText(declineBtnRegion_, Qt::AlignCenter, tr("Decline")); } } @@ -196,8 +243,7 @@ RoomInfoListItem::paintEvent(QPaintEvent *event) p.setFont(font); p.setPen(QColor("#333")); p.setBrush(Qt::NoBrush); - p.drawText( - avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(state_.getName()[0])); + p.drawText(avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(roomName()[0])); } else { p.save(); @@ -289,6 +335,9 @@ RoomInfoListItem::contextMenuEvent(QContextMenuEvent *event) { Q_UNUSED(event); + if (roomType_ == RoomType::Invited) + return; + toggleNotifications_->setText(notificationText()); menu_->popup(event->globalPos()); } @@ -301,6 +350,18 @@ RoomInfoListItem::mousePressEvent(QMouseEvent *event) return; } + if (roomType_ == RoomType::Invited) { + const auto point = event->pos(); + + if (acceptBtnRegion_.contains(point)) + emit acceptInvite(roomId_); + + if (declineBtnRegion_.contains(point)) + emit declineInvite(roomId_); + + return; + } + emit clicked(roomId_); setPressedState(true); diff --git a/src/RoomList.cc b/src/RoomList.cc index a892e406..1e639838 100644 --- a/src/RoomList.cc +++ b/src/RoomList.cc @@ -287,3 +287,32 @@ RoomList::paintEvent(QPaintEvent *) QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } + +void +RoomList::syncInvites(const std::map &rooms) +{ + for (auto it = rooms.cbegin(); it != rooms.cend(); ++it) { + const auto room_id = QString::fromStdString(it->first); + + if (!rooms_.contains(room_id)) + addInvitedRoom(room_id, it->second); + } +} + +void +RoomList::addInvitedRoom(const QString &room_id, const mtx::responses::InvitedRoom &room) +{ + auto room_item = new RoomInfoListItem(room_id, room, scrollArea_); + connect(room_item, &RoomInfoListItem::acceptInvite, this, &RoomList::acceptInvite); + connect(room_item, &RoomInfoListItem::declineInvite, this, &RoomList::declineInvite); + + rooms_.insert(room_id, QSharedPointer(room_item)); + + auto avatarUrl = QString::fromStdString(room.avatar()); + + if (!avatarUrl.isEmpty()) + client_->fetchRoomAvatar(room_id, avatarUrl); + + int pos = contentsLayout_->count() - 1; + contentsLayout_->insertWidget(pos, room_item); +}