diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 62ac341a..5bc20dbe 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -37,14 +37,27 @@ Page { id: communityContextMenu property string tagId + property bool hidden + property bool muted - function show(id_, tags_) { + function show(id_, hidden_, muted_) { tagId = id_; + hidden = hidden_; + muted = muted_; open(); } + Platform.MenuItem { + text: qsTr("Do not show notification counts for this space or tag.") + checkable: true + checked: communityContextMenu.muted + onTriggered: Communities.toggleTagMute(communityContextMenu.tagId) + } + Platform.MenuItem { text: qsTr("Hide rooms with this tag or from this space by default.") + checkable: true + checked: communityContextMenu.hidden onTriggered: Communities.toggleTagId(communityContextMenu.tagId) } @@ -68,6 +81,7 @@ Page { required property string id required property int unreadMessages required property bool hasLoudNotification + required property bool muted height: avatarSize + 2 * Nheko.paddingMedium width: ListView.view.width @@ -76,7 +90,7 @@ Page { ToolTip.text: communityItem.tooltip ToolTip.delay: Nheko.tooltipDelay onClicked: Communities.setCurrentTagId(communityItem.id) - onPressAndHold: communityContextMenu.show(communityItem.id) + onPressAndHold: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted) states: [ State { name: "highlight" @@ -113,7 +127,7 @@ Page { TapHandler { acceptedButtons: Qt.RightButton - onSingleTapped: communityContextMenu.show(communityItem.id) + onSingleTapped: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted) gesturePolicy: TapHandler.ReleaseWithinBounds acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad } @@ -174,6 +188,8 @@ Page { mayBeVisible: { if (!communitySidebar.collapsed) return false + else if (communityItem.muted) + return false else if (Settings.spaceNotifications === Settings.SpaceNotificationsOff) return false else if (Settings.spaceNotifications === Settings.SidebarHiddenRooms) @@ -215,10 +231,17 @@ Page { mayBeVisible: { if (communitySidebar.collapsed) return false + else if (communityItem.muted) + return false else if (Settings.spaceNotification === Settings.SpaceNotificationsOff) return false - else if ((Settings.spaceNotifications === Settings.SidebarHiddenRooms) && communityItem.hidden) - return true + else if (Settings.spaceNotifications === Settings.SidebarHiddenRooms) + { + if (communityItem.hidden) + return true + else + return false + } else return true } diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index c4cc339b..2c6dc782 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -140,7 +140,8 @@ UserSettings::load(std::optional profile) userId_ = settings.value(prefix + "auth/user_id", "").toString(); deviceId_ = settings.value(prefix + "auth/device_id", "").toString(); hiddenTags_ = settings.value(prefix + "user/hidden_tags", QStringList{}).toStringList(); - hiddenPins_ = settings.value(prefix + "user/hidden_pins", QStringList{}).toStringList(); + mutedTags_ = settings.value(prefix + "user/muted_tags", QStringList{"global"}).toStringList(); + hiddenPins_ = settings.value(prefix + "user/hidden_pins", QStringList{}).toStringList(); hiddenWidgets_ = settings.value(prefix + "user/hidden_widgets", QStringList{}).toStringList(); recentReactions_ = settings.value(prefix + "user/recent_reactions", QStringList{}).toStringList(); @@ -228,14 +229,21 @@ UserSettings::setGroupView(bool state) } void -UserSettings::setHiddenTags(QStringList hiddenTags) +UserSettings::setHiddenTags(const QStringList &hiddenTags) { hiddenTags_ = hiddenTags; save(); } void -UserSettings::setHiddenPins(QStringList hiddenTags) +UserSettings::setMutedTags(const QStringList &mutedTags) +{ + mutedTags_ = mutedTags; + save(); +} + +void +UserSettings::setHiddenPins(const QStringList &hiddenTags) { hiddenPins_ = hiddenTags; save(); @@ -243,7 +251,7 @@ UserSettings::setHiddenPins(QStringList hiddenTags) } void -UserSettings::setHiddenWidgets(QStringList hiddenTags) +UserSettings::setHiddenWidgets(const QStringList &hiddenTags) { hiddenWidgets_ = hiddenTags; save(); @@ -851,6 +859,7 @@ UserSettings::save() onlyShareKeysWithVerifiedUsers_); settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_); settings.setValue(prefix + "user/hidden_tags", hiddenTags_); + settings.setValue(prefix + "user/muted_tags", mutedTags_); settings.setValue(prefix + "user/hidden_pins", hiddenPins_); settings.setValue(prefix + "user/hidden_widgets", hiddenWidgets_); settings.setValue(prefix + "user/recent_reactions", recentReactions_); @@ -1451,7 +1460,7 @@ UserSettingsModel::data(const QModelIndex &index, int role) const case SpaceNotifications: return QStringList{QStringLiteral("Sidebar and room list"), QStringLiteral("Sidebar"), - QStringLiteral("Sidebar (hidden rooms only)"), + QStringLiteral("Sidebar (hidden spaces and tags only)"), QStringLiteral("Off")}; } } else if (role == Good) { diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index daf41383..db12b1e6 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -196,9 +196,10 @@ public: void setDeviceId(QString deviceId); void setHomeserver(QString homeserver); void setDisableCertificateValidation(bool disabled); - void setHiddenTags(QStringList hiddenTags); - void setHiddenPins(QStringList hiddenTags); - void setHiddenWidgets(QStringList hiddenTags); + void setHiddenTags(const QStringList &hiddenTags); + void setMutedTags(const QStringList &mutedTags); + void setHiddenPins(const QStringList &hiddenTags); + void setHiddenWidgets(const QStringList &hiddenTags); void setRecentReactions(QStringList recent); void setUseIdenticon(bool state); void setOpenImageExternal(bool state); @@ -263,6 +264,7 @@ public: QString homeserver() const { return homeserver_; } bool disableCertificateValidation() const { return disableCertificateValidation_; } QStringList hiddenTags() const { return hiddenTags_; } + QStringList mutedTags() const { return mutedTags_; } QStringList hiddenPins() const { return hiddenPins_; } QStringList hiddenWidgets() const { return hiddenWidgets_; } QStringList recentReactions() const { return recentReactions_; } @@ -385,6 +387,7 @@ private: QString deviceId_; QString homeserver_; QStringList hiddenTags_; + QStringList mutedTags_; QStringList hiddenPins_; QStringList hiddenWidgets_; QStringList recentReactions_; diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index 8e1cf140..91f7d555 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -16,6 +16,8 @@ CommunitiesModel::CommunitiesModel(QObject *parent) : QAbstractListModel(parent) + , hiddenTagIds_{UserSettings::instance()->hiddenTags()} + , mutedTagIds_{UserSettings::instance()->mutedTags()} { connect(ChatPage::instance(), &ChatPage::unreadMessages, this, [this](int) { // Simply updating every space is easier than tracking which ones need updated. @@ -40,6 +42,7 @@ CommunitiesModel::roleNames() const {Id, "id"}, {UnreadMessages, "unreadMessages"}, {HasLoudNotification, "hasLoudNotification"}, + {Muted, "muted"}, }; } @@ -62,6 +65,13 @@ CommunitiesModel::setData(const QModelIndex &index, const QVariant &value, int r QVariant CommunitiesModel::data(const QModelIndex &index, int role) const { + if (role == CommunitiesModel::Roles::Muted) { + if (index.row() == 0) + return mutedTagIds_.contains(QStringLiteral("global")); + else + return mutedTagIds_.contains(data(index, CommunitiesModel::Roles::Id).toString()); + } + if (index.row() == 0) { switch (role) { case CommunitiesModel::Roles::AvatarUrl: @@ -333,7 +343,6 @@ CommunitiesModel::initializeSidebar() for (const auto &t : ts) tags_.push_back(QString::fromStdString(t)); - hiddenTagIds_ = UserSettings::instance()->hiddenTags(); spaceOrder_.restoreCollapsed(); endResetModel(); @@ -485,13 +494,11 @@ CommunitiesModel::setCurrentTagId(const QString &tagId) void CommunitiesModel::toggleTagId(QString tagId) { - if (hiddenTagIds_.contains(tagId)) { + if (hiddenTagIds_.contains(tagId)) hiddenTagIds_.removeOne(tagId); - UserSettings::instance()->setHiddenTags(hiddenTagIds_); - } else { + else hiddenTagIds_.push_back(tagId); - UserSettings::instance()->setHiddenTags(hiddenTagIds_); - } + UserSettings::instance()->setHiddenTags(hiddenTagIds_); if (tagId.startsWith(QLatin1String("tag:"))) { auto idx = tags_.indexOf(tagId.mid(4)); @@ -509,6 +516,34 @@ CommunitiesModel::toggleTagId(QString tagId) emit hiddenTagsChanged(); } +void +CommunitiesModel::toggleTagMute(QString tagId) +{ + if (tagId.isEmpty()) + tagId = QStringLiteral("global"); + + if (mutedTagIds_.contains(tagId)) + mutedTagIds_.removeOne(tagId); + else + mutedTagIds_.push_back(tagId); + UserSettings::instance()->setMutedTags(mutedTagIds_); + + if (tagId.startsWith(QLatin1String("tag:"))) { + auto idx = tags_.indexOf(tagId.mid(4)); + if (idx != -1) + emit dataChanged(index(idx + 1 + spaceOrder_.size()), + index(idx + 1 + spaceOrder_.size())); + } else if (tagId.startsWith(QLatin1String("space:"))) { + auto idx = spaceOrder_.indexOf(tagId.mid(6)); + if (idx != -1) + emit dataChanged(index(idx + 1), index(idx + 1)); + } else if (tagId == QLatin1String("dm")) { + emit dataChanged(index(1), index(1)); + } else if (tagId == QLatin1String("global")) { + emit dataChanged(index(0), index(0)); + } +} + FilteredCommunitiesModel::FilteredCommunitiesModel(CommunitiesModel *model, QObject *parent) : QSortFilterProxyModel(parent) { diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h index bcb487e7..5a659751 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -50,6 +50,7 @@ public: Id, UnreadMessages, HasLoudNotification, + Muted, IsDirect, }; @@ -141,6 +142,7 @@ public slots: return tagsWD; } void toggleTagId(QString tagId); + void toggleTagMute(QString tagId); FilteredCommunitiesModel *filtered() { return new FilteredCommunitiesModel(this, this); } signals: @@ -153,6 +155,7 @@ private: QStringList tags_; QString currentTagId_; QStringList hiddenTagIds_; + QStringList mutedTagIds_; FlatTree spaceOrder_; std::map spaces_; std::vector directMessages_;