Allow users to hide rooms with specific tags

This commit is contained in:
Nicolas Werner 2021-01-23 00:30:45 +01:00
parent 97340bed13
commit fdb9d7ab40
13 changed files with 159 additions and 46 deletions

View file

@ -155,11 +155,12 @@ RoomInfoListItem > Avatar {
CommunitiesListItem { CommunitiesListItem {
qproperty-highlightedBackgroundColor: #4d84c7; qproperty-highlightedBackgroundColor: #4d84c7;
qproperty-disabledBackgroundColor: palette(mid);
qproperty-hoverBackgroundColor: rgb(67, 70, 77); qproperty-hoverBackgroundColor: rgb(67, 70, 77);
qproperty-backgroundColor: #2d3139; qproperty-backgroundColor: #2d3139;
qproperty-avatarBgColor: #202228; qproperty-avatarBgColor: #202228;
qproperty-avatarFgColor: palette(window); qproperty-avatarFgColor: black;
} }
LoadingIndicator { LoadingIndicator {

View file

@ -122,11 +122,12 @@ RoomInfoListItem > Avatar {
CommunitiesListItem { CommunitiesListItem {
qproperty-highlightedBackgroundColor: #38A3D8; qproperty-highlightedBackgroundColor: #38A3D8;
qproperty-disabledBackgroundColor: palette(mid);
qproperty-hoverBackgroundColor: rgb(70, 77, 93); qproperty-hoverBackgroundColor: rgb(70, 77, 93);
qproperty-backgroundColor: #f2f5f8; qproperty-backgroundColor: #f2f5f8;
qproperty-avatarBgColor: #eee; qproperty-avatarBgColor: #eee;
qproperty-avatarFgColor: black; qproperty-avatarFgColor: palette(buttonText);
} }
#ChatPageLoadSpinner { #ChatPageLoadSpinner {

View file

@ -118,6 +118,7 @@ RoomInfoListItem > Avatar {
CommunitiesListItem { CommunitiesListItem {
qproperty-highlightedBackgroundColor: palette(highlight); qproperty-highlightedBackgroundColor: palette(highlight);
qproperty-disabledBackgroundColor: palette(mid);
qproperty-hoverBackgroundColor: palette(light); qproperty-hoverBackgroundColor: palette(light);
qproperty-backgroundColor: palette(window); qproperty-backgroundColor: palette(window);

View file

@ -267,10 +267,27 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
[this](const QString &groupId) { [this](const QString &groupId) {
current_community_ = groupId; current_community_ = groupId;
if (groupId == "world") if (groupId == "world") {
room_list_->removeFilter(); auto hidden = communitiesList_->hiddenTagsAndCommunities();
else std::set<QString> roomsToHide = communitiesList_->roomList(groupId);
room_list_->applyFilter(communitiesList_->roomList(groupId)); for (const auto &hiddenTag : hidden) {
auto temp = communitiesList_->roomList(hiddenTag);
roomsToHide.insert(temp.begin(), temp.end());
}
room_list_->removeFilter(roomsToHide);
} else {
auto hidden = communitiesList_->hiddenTagsAndCommunities();
hidden.erase(current_community_);
auto roomsToShow = communitiesList_->roomList(groupId);
for (const auto &hiddenTag : hidden) {
for (const auto &r : communitiesList_->roomList(hiddenTag))
roomsToShow.erase(r);
}
room_list_->applyFilter(roomsToShow);
}
}); });
connect(&notificationsManager, connect(&notificationsManager,

View file

@ -135,6 +135,14 @@ CommunitiesList::addCommunity(const std::string &group_id)
&CommunitiesListItem::clicked, &CommunitiesListItem::clicked,
this, this,
&CommunitiesList::highlightSelectedCommunity); &CommunitiesList::highlightSelectedCommunity);
connect(list_item, &CommunitiesListItem::isDisabledChanged, this, [this]() {
for (const auto &community : communities_) {
if (community.second->isPressed()) {
emit highlightSelectedCommunity(community.first);
break;
}
}
});
if (group_id.empty() || group_id.front() != '+') if (group_id.empty() || group_id.front() != '+')
return; return;
@ -157,7 +165,9 @@ CommunitiesList::addCommunity(const std::string &group_id)
connect(this, connect(this,
&CommunitiesList::groupRoomsRetrieved, &CommunitiesList::groupRoomsRetrieved,
this, this,
[this](const QString &id, const std::map<QString, bool> &rooms) { [this](const QString &id, const std::set<QString> &rooms) {
nhlog::ui()->info(
"Fetched rooms for {}: {}", id.toStdString(), rooms.size());
if (communities_.find(id) == communities_.end()) if (communities_.find(id) == communities_.end())
return; return;
@ -179,9 +189,9 @@ CommunitiesList::addCommunity(const std::string &group_id)
return; return;
} }
std::map<QString, bool> room_ids; std::set<QString> room_ids;
for (const auto &room : res.at("chunk")) for (const auto &room : res.at("chunk"))
room_ids.emplace(QString::fromStdString(room.at("room_id")), true); room_ids.emplace(QString::fromStdString(room.at("room_id")));
emit groupRoomsRetrieved(id, room_ids); emit groupRoomsRetrieved(id, room_ids);
}); });
@ -256,7 +266,7 @@ CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUr
}); });
} }
std::map<QString, bool> std::set<QString>
CommunitiesList::roomList(const QString &id) const CommunitiesList::roomList(const QString &id) const
{ {
if (communityExists(id)) if (communityExists(id))
@ -277,6 +287,18 @@ CommunitiesList::currentTags() const
return tags; return tags;
} }
std::set<QString>
CommunitiesList::hiddenTagsAndCommunities() const
{
std::set<QString> hiddenTags;
for (auto &entry : communities_) {
if (entry.second->isDisabled())
hiddenTags.insert(entry.first);
}
return hiddenTags;
}
void void
CommunitiesList::sortEntries() CommunitiesList::sortEntries()
{ {

View file

@ -24,17 +24,18 @@ public:
void addCommunity(const std::string &id); void addCommunity(const std::string &id);
void removeCommunity(const QString &id) { communities_.erase(id); }; void removeCommunity(const QString &id) { communities_.erase(id); };
std::map<QString, bool> roomList(const QString &id) const; std::set<QString> roomList(const QString &id) const;
void syncTags(const std::map<QString, RoomInfo> &info); void syncTags(const std::map<QString, RoomInfo> &info);
void setTagsForRoom(const QString &id, const std::vector<std::string> &tags); void setTagsForRoom(const QString &id, const std::vector<std::string> &tags);
std::vector<std::string> currentTags() const; std::vector<std::string> currentTags() const;
std::set<QString> hiddenTagsAndCommunities() const;
signals: signals:
void communityChanged(const QString &id); void communityChanged(const QString &id);
void avatarRetrieved(const QString &id, const QPixmap &img); void avatarRetrieved(const QString &id, const QPixmap &img);
void groupProfileRetrieved(const QString &group_id, const mtx::responses::GroupProfile &); void groupProfileRetrieved(const QString &group_id, const mtx::responses::GroupProfile &);
void groupRoomsRetrieved(const QString &group_id, const std::map<QString, bool> &res); void groupRoomsRetrieved(const QString &group_id, const std::set<QString> &res);
public slots: public slots:
void updateCommunityAvatar(const QString &id, const QPixmap &img); void updateCommunityAvatar(const QString &id, const QPixmap &img);

View file

@ -1,5 +1,6 @@
#include "CommunitiesListItem.h" #include "CommunitiesListItem.h"
#include <QMenu>
#include <QMouseEvent> #include <QMouseEvent>
#include "Utils.h" #include "Utils.h"
@ -20,18 +21,28 @@ CommunitiesListItem::CommunitiesListItem(QString group_id, QWidget *parent)
rippleOverlay_->setClipPath(path); rippleOverlay_->setClipPath(path);
rippleOverlay_->setClipping(true); rippleOverlay_->setClipping(true);
if (groupId_ == "world") menu_ = new QMenu(this);
avatar_ = QPixmap(":/icons/icons/ui/world.png"); hideRoomsWithTagAction_ =
else if (groupId_ == "tag:m.favourite") new QAction(tr("Hide rooms with this tag or from this community"), this);
avatar_ = QPixmap(":/icons/icons/ui/star.png"); hideRoomsWithTagAction_->setCheckable(true);
else if (groupId_ == "tag:m.lowpriority") menu_->addAction(hideRoomsWithTagAction_);
avatar_ = QPixmap(":/icons/icons/ui/lowprio.png"); connect(menu_, &QMenu::aboutToShow, this, [this]() {
else if (groupId_.startsWith("tag:")) hideRoomsWithTagAction_->setChecked(isDisabled_);
avatar_ = QPixmap(":/icons/icons/ui/tag.png"); });
connect(hideRoomsWithTagAction_, &QAction::triggered, this, [this](bool checked) {
this->setDisabled(checked);
});
updateTooltip(); updateTooltip();
} }
void
CommunitiesListItem::contextMenuEvent(QContextMenuEvent *event)
{
menu_->popup(event->globalPos());
}
void void
CommunitiesListItem::setName(QString name) CommunitiesListItem::setName(QString name)
{ {
@ -48,6 +59,16 @@ CommunitiesListItem::setPressedState(bool state)
} }
} }
void
CommunitiesListItem::setDisabled(bool state)
{
if (isDisabled_ != state) {
isDisabled_ = state;
update();
emit isDisabledChanged();
}
}
void void
CommunitiesListItem::mousePressEvent(QMouseEvent *event) CommunitiesListItem::mousePressEvent(QMouseEvent *event)
{ {
@ -80,12 +101,25 @@ CommunitiesListItem::paintEvent(QPaintEvent *)
if (isPressed_) if (isPressed_)
p.fillRect(rect(), highlightedBackgroundColor_); p.fillRect(rect(), highlightedBackgroundColor_);
else if (isDisabled_)
p.fillRect(rect(), disabledBackgroundColor_);
else if (underMouse()) else if (underMouse())
p.fillRect(rect(), hoverBackgroundColor_); p.fillRect(rect(), hoverBackgroundColor_);
else else
p.fillRect(rect(), backgroundColor_); p.fillRect(rect(), backgroundColor_);
if (avatar_.isNull()) { if (avatar_.isNull()) {
QPixmap source;
if (groupId_ == "world")
source = QPixmap(":/icons/icons/ui/world.png");
else if (groupId_ == "tag:m.favourite")
source = QPixmap(":/icons/icons/ui/star.png");
else if (groupId_ == "tag:m.lowpriority")
source = QPixmap(":/icons/icons/ui/lowprio.png");
else if (groupId_.startsWith("tag:"))
source = QPixmap(":/icons/icons/ui/tag.png");
if (source.isNull()) {
QFont font; QFont font;
font.setPointSizeF(font.pointSizeF() * 1.3); font.setPointSizeF(font.pointSizeF() * 1.3);
p.setFont(font); p.setFont(font);
@ -96,6 +130,18 @@ CommunitiesListItem::paintEvent(QPaintEvent *)
width(), width(),
height(), height(),
IconSize); IconSize);
} else {
QPainter painter(&source);
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
painter.fillRect(source.rect(), avatarFgColor_);
painter.end();
const int imageSz = 32;
p.drawPixmap(
QRect(
(width() - imageSz) / 2, (height() - imageSz) / 2, imageSz, imageSz),
source);
}
} else { } else {
p.save(); p.save();

View file

@ -3,17 +3,22 @@
#include <QSharedPointer> #include <QSharedPointer>
#include <QWidget> #include <QWidget>
#include <set>
#include "Config.h" #include "Config.h"
#include "ui/Theme.h" #include "ui/Theme.h"
class RippleOverlay; class RippleOverlay;
class QMouseEvent; class QMouseEvent;
class QMenu;
class CommunitiesListItem : public QWidget class CommunitiesListItem : public QWidget
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QColor highlightedBackgroundColor READ highlightedBackgroundColor WRITE Q_PROPERTY(QColor highlightedBackgroundColor READ highlightedBackgroundColor WRITE
setHighlightedBackgroundColor) setHighlightedBackgroundColor)
Q_PROPERTY(QColor disabledBackgroundColor READ disabledBackgroundColor WRITE
setDisabledBackgroundColor)
Q_PROPERTY( Q_PROPERTY(
QColor hoverBackgroundColor READ hoverBackgroundColor WRITE setHoverBackgroundColor) QColor hoverBackgroundColor READ hoverBackgroundColor WRITE setHoverBackgroundColor)
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor) Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
@ -26,16 +31,18 @@ public:
void setName(QString name); void setName(QString name);
bool isPressed() const { return isPressed_; } bool isPressed() const { return isPressed_; }
bool isDisabled() const { return isDisabled_; }
void setAvatar(const QImage &img); void setAvatar(const QImage &img);
void setRooms(std::map<QString, bool> room_ids) { room_ids_ = std::move(room_ids); } void setRooms(std::set<QString> room_ids) { room_ids_ = std::move(room_ids); }
void addRoom(const QString &id) { room_ids_[id] = true; } void addRoom(const QString &id) { room_ids_.insert(id); }
void delRoom(const QString &id) { room_ids_.erase(id); } void delRoom(const QString &id) { room_ids_.erase(id); }
std::map<QString, bool> rooms() const { return room_ids_; } std::set<QString> rooms() const { return room_ids_; }
bool is_tag() const { return groupId_.startsWith("tag:"); } bool is_tag() const { return groupId_.startsWith("tag:"); }
QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; } QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; }
QColor disabledBackgroundColor() const { return disabledBackgroundColor_; }
QColor hoverBackgroundColor() const { return hoverBackgroundColor_; } QColor hoverBackgroundColor() const { return hoverBackgroundColor_; }
QColor backgroundColor() const { return backgroundColor_; } QColor backgroundColor() const { return backgroundColor_; }
@ -43,6 +50,7 @@ public:
QColor avatarBgColor() const { return avatarBgColor_; } QColor avatarBgColor() const { return avatarBgColor_; }
void setHighlightedBackgroundColor(QColor &color) { highlightedBackgroundColor_ = color; } void setHighlightedBackgroundColor(QColor &color) { highlightedBackgroundColor_ = color; }
void setDisabledBackgroundColor(QColor &color) { disabledBackgroundColor_ = color; }
void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; } void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; }
void setBackgroundColor(QColor &color) { backgroundColor_ = color; } void setBackgroundColor(QColor &color) { backgroundColor_ = color; }
@ -56,13 +64,16 @@ public:
signals: signals:
void clicked(const QString &group_id); void clicked(const QString &group_id);
void isDisabledChanged();
public slots: public slots:
void setPressedState(bool state); void setPressedState(bool state);
void setDisabled(bool state);
protected: protected:
void mousePressEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
private: private:
const int IconSize = 36; const int IconSize = 36;
@ -70,13 +81,14 @@ private:
QString resolveName() const; QString resolveName() const;
void updateTooltip(); void updateTooltip();
std::map<QString, bool> room_ids_; std::set<QString> room_ids_;
QString name_; QString name_;
QString groupId_; QString groupId_;
QPixmap avatar_; QPixmap avatar_;
QColor highlightedBackgroundColor_; QColor highlightedBackgroundColor_;
QColor disabledBackgroundColor_;
QColor hoverBackgroundColor_; QColor hoverBackgroundColor_;
QColor backgroundColor_; QColor backgroundColor_;
@ -84,6 +96,9 @@ private:
QColor avatarBgColor_; QColor avatarBgColor_;
bool isPressed_ = false; bool isPressed_ = false;
bool isDisabled_ = false;
RippleOverlay *rippleOverlay_; RippleOverlay *rippleOverlay_;
QMenu *menu_;
QAction *hideRoomsWithTagAction_;
}; };

View file

@ -1,6 +1,7 @@
#include "MatrixClient.h" #include "MatrixClient.h"
#include <memory> #include <memory>
#include <set>
#include <QMetaType> #include <QMetaType>
#include <QObject> #include <QObject>
@ -21,6 +22,7 @@ Q_DECLARE_METATYPE(nlohmann::json)
Q_DECLARE_METATYPE(std::string) Q_DECLARE_METATYPE(std::string)
Q_DECLARE_METATYPE(std::vector<std::string>) Q_DECLARE_METATYPE(std::vector<std::string>)
Q_DECLARE_METATYPE(std::vector<QString>) Q_DECLARE_METATYPE(std::vector<QString>)
Q_DECLARE_METATYPE(std::set<QString>)
namespace { namespace {
auto client_ = std::make_shared<mtx::http::Client>(); auto client_ = std::make_shared<mtx::http::Client>();
@ -55,6 +57,7 @@ init()
qRegisterMetaType<std::vector<std::string>>(); qRegisterMetaType<std::vector<std::string>>();
qRegisterMetaType<std::vector<QString>>(); qRegisterMetaType<std::vector<QString>>();
qRegisterMetaType<std::map<QString, bool>>("std::map<QString, bool>"); qRegisterMetaType<std::map<QString, bool>>("std::map<QString, bool>");
qRegisterMetaType<std::set<QString>>();
} }
} // namespace http } // namespace http

View file

@ -17,6 +17,7 @@
#include <QDateTime> #include <QDateTime>
#include <QInputDialog> #include <QInputDialog>
#include <QMenu>
#include <QMouseEvent> #include <QMouseEvent>
#include <QPainter> #include <QPainter>
#include <QSettings> #include <QSettings>
@ -32,7 +33,6 @@
#include "Splitter.h" #include "Splitter.h"
#include "UserSettingsPage.h" #include "UserSettingsPage.h"
#include "Utils.h" #include "Utils.h"
#include "ui/Menu.h"
#include "ui/Ripple.h" #include "ui/Ripple.h"
#include "ui/RippleOverlay.h" #include "ui/RippleOverlay.h"
@ -98,7 +98,7 @@ RoomInfoListItem::init(QWidget *parent)
bubbleDiameter_ = QFontMetrics(unreadCountFont_).averageCharWidth() * 3; bubbleDiameter_ = QFontMetrics(unreadCountFont_).averageCharWidth() * 3;
menu_ = new Menu(this); menu_ = new QMenu(this);
leaveRoom_ = new QAction(tr("Leave room"), this); leaveRoom_ = new QAction(tr("Leave room"), this);
connect(leaveRoom_, &QAction::triggered, this, [this]() { emit leaveRoom(roomId_); }); connect(leaveRoom_, &QAction::triggered, this, [this]() { emit leaveRoom(roomId_); });

View file

@ -28,7 +28,7 @@
#include "UserSettingsPage.h" #include "UserSettingsPage.h"
#include "ui/Avatar.h" #include "ui/Avatar.h"
class Menu; class QMenu;
class RippleOverlay; class RippleOverlay;
class RoomInfoListItem : public QWidget class RoomInfoListItem : public QWidget
@ -178,7 +178,7 @@ private:
DescInfo lastMsgInfo_; DescInfo lastMsgInfo_;
Menu *menu_; QMenu *menu_;
QAction *leaveRoom_; QAction *leaveRoom_;
bool isPressed_ = false; bool isPressed_ = false;

View file

@ -411,20 +411,24 @@ RoomList::closeJoinRoomDialog(bool isJoining, QString roomAlias)
} }
void void
RoomList::removeFilter() RoomList::removeFilter(const std::set<QString> &roomsToHide)
{ {
setUpdatesEnabled(false); setUpdatesEnabled(false);
for (int i = 0; i < contentsLayout_->count(); i++) { for (int i = 0; i < contentsLayout_->count(); i++) {
auto widget = auto widget =
qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget()); qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
if (widget) if (widget) {
if (roomsToHide.find(widget->roomId()) == roomsToHide.end())
widget->show(); widget->show();
else
widget->hide();
}
} }
setUpdatesEnabled(true); setUpdatesEnabled(true);
} }
void void
RoomList::applyFilter(const std::map<QString, bool> &filter) RoomList::applyFilter(const std::set<QString> &filter)
{ {
// Disabling paint updates will resolve issues with screen flickering on big room lists. // Disabling paint updates will resolve issues with screen flickering on big room lists.
setUpdatesEnabled(false); setUpdatesEnabled(false);

View file

@ -23,6 +23,8 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWidget> #include <QWidget>
#include <set>
#include "CacheStructs.h" #include "CacheStructs.h"
#include "UserSettingsPage.h" #include "UserSettingsPage.h"
@ -54,9 +56,9 @@ public:
void addInvitedRoom(const QString &room_id, const RoomInfo &info); void addInvitedRoom(const QString &room_id, const RoomInfo &info);
void removeRoom(const QString &room_id, bool reset); void removeRoom(const QString &room_id, bool reset);
//! Hide rooms that are not present in the given filter. //! Hide rooms that are not present in the given filter.
void applyFilter(const std::map<QString, bool> &rooms); void applyFilter(const std::set<QString> &rooms);
//! Show all the available rooms. //! Show all the available rooms.
void removeFilter(); void removeFilter(const std::set<QString> &roomsToHide);
void updateRoom(const QString &room_id, const RoomInfo &info); void updateRoom(const QString &room_id, const RoomInfo &info);
void cleanupInvites(const std::map<QString, bool> &invites); void cleanupInvites(const std::map<QString, bool> &invites);