diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 029444a3..91ecd58a 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -100,7 +100,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
user_info_widget_ = new UserInfoWidget(sideBar_);
user_mentions_popup_ = new popups::UserMentions();
- room_list_ = new RoomList(sideBar_);
+ room_list_ = new RoomList(userSettings, sideBar_);
connect(room_list_, &RoomList::joinRoom, this, &ChatPage::joinRoom);
sideBarLayout_->addWidget(user_info_widget_);
diff --git a/src/RoomInfoListItem.cpp b/src/RoomInfoListItem.cpp
index 61fb5e47..cc5f5776 100644
--- a/src/RoomInfoListItem.cpp
+++ b/src/RoomInfoListItem.cpp
@@ -26,6 +26,7 @@
#include "Config.h"
#include "RoomInfoListItem.h"
#include "Splitter.h"
+#include "UserSettingsPage.h"
#include "Utils.h"
#include "ui/Menu.h"
#include "ui/Ripple.h"
@@ -99,7 +100,10 @@ RoomInfoListItem::init(QWidget *parent)
menu_->addAction(leaveRoom_);
}
-RoomInfoListItem::RoomInfoListItem(QString room_id, const RoomInfo &info, QWidget *parent)
+RoomInfoListItem::RoomInfoListItem(QString room_id,
+ const RoomInfo &info,
+ QSharedPointer<UserSettings> userSettings,
+ QWidget *parent)
: QWidget(parent)
, roomType_{info.is_invite ? RoomType::Invited : RoomType::Joined}
, roomId_(std::move(room_id))
@@ -107,6 +111,7 @@ RoomInfoListItem::RoomInfoListItem(QString room_id, const RoomInfo &info, QWidge
, isPressed_(false)
, unreadMsgCount_(0)
, unreadHighlightedMsgCount_(0)
+ , settings(userSettings)
{
init(parent);
}
@@ -324,6 +329,34 @@ RoomInfoListItem::updateUnreadMessageCount(int count, int highlightedCount)
update();
}
+enum NotificationImportance : short
+{
+ ImportanceDisabled = -1,
+ AllEventsRead = 0,
+ NewMessage = 1,
+ NewMentions = 2,
+ Invite = 3
+};
+
+short int
+RoomInfoListItem::calculateImportance() const
+{
+ // Returns the degree of importance of the unread messages in the room.
+ // If sorting by importance is disabled in settings, this only ever
+ // returns ImportanceDisabled or Invite
+ if (isInvite()) {
+ return Invite;
+ } else if (!settings->isSortByImportanceEnabled()) {
+ return ImportanceDisabled;
+ } else if (unreadHighlightedMsgCount_) {
+ return NewMentions;
+ } else if (unreadMsgCount_) {
+ return NewMessage;
+ } else {
+ return AllEventsRead;
+ }
+}
+
void
RoomInfoListItem::setPressedState(bool state)
{
diff --git a/src/RoomInfoListItem.h b/src/RoomInfoListItem.h
index c1ee533d..e609f4d8 100644
--- a/src/RoomInfoListItem.h
+++ b/src/RoomInfoListItem.h
@@ -25,6 +25,7 @@
#include <mtx/responses.hpp>
#include "CacheStructs.h"
+#include "UserSettingsPage.h"
#include "ui/Avatar.h"
class Menu;
@@ -63,11 +64,16 @@ class RoomInfoListItem : public QWidget
Q_PROPERTY(QColor btnTextColor READ btnTextColor WRITE setBtnTextColor)
public:
- RoomInfoListItem(QString room_id, const RoomInfo &info, QWidget *parent = nullptr);
+ RoomInfoListItem(QString room_id,
+ const RoomInfo &info,
+ QSharedPointer<UserSettings> userSettings,
+ QWidget *parent = nullptr);
void updateUnreadMessageCount(int count, int highlightedCount);
void clearUnreadMessageCount() { updateUnreadMessageCount(0, 0); };
+ short int calculateImportance() const;
+
QString roomId() { return roomId_; }
bool isPressed() const { return isPressed_; }
int unreadMessageCount() const { return unreadMsgCount_; }
@@ -128,7 +134,7 @@ public:
roomType_ = RoomType::Joined;
}
- bool isInvite() { return roomType_ == RoomType::Invited; }
+ bool isInvite() const { return roomType_ == RoomType::Invited; }
void setReadState(bool hasUnreadMessages)
{
if (hasUnreadMessages_ != hasUnreadMessages) {
@@ -214,4 +220,6 @@ private:
QColor bubbleBgColor_;
QColor bubbleFgColor_;
+
+ QSharedPointer<UserSettings> settings;
};
diff --git a/src/RoomList.cpp b/src/RoomList.cpp
index 6feb4f76..1c7c340d 100644
--- a/src/RoomList.cpp
+++ b/src/RoomList.cpp
@@ -16,6 +16,7 @@
*/
#include <limits>
+#include <set>
#include <QObject>
#include <QPainter>
@@ -26,11 +27,13 @@
#include "MainWindow.h"
#include "RoomInfoListItem.h"
#include "RoomList.h"
+#include "UserSettingsPage.h"
#include "Utils.h"
#include "ui/OverlayModal.h"
-RoomList::RoomList(QWidget *parent)
+RoomList::RoomList(QSharedPointer<UserSettings> userSettings, QWidget *parent)
: QWidget(parent)
+ , settings(userSettings)
{
topLayout_ = new QVBoxLayout(this);
topLayout_->setSpacing(0);
@@ -62,12 +65,16 @@ RoomList::RoomList(QWidget *parent)
topLayout_->addWidget(scrollArea_);
connect(this, &RoomList::updateRoomAvatarCb, this, &RoomList::updateRoomAvatar);
+ connect(userSettings.data(),
+ &UserSettings::roomSortingChanged,
+ this,
+ &RoomList::sortRoomsByLastMessage);
}
void
RoomList::addRoom(const QString &room_id, const RoomInfo &info)
{
- auto room_item = new RoomInfoListItem(room_id, info, scrollArea_);
+ auto room_item = new RoomInfoListItem(room_id, info, settings, scrollArea_);
room_item->setRoomName(QString::fromStdString(std::move(info.name)));
connect(room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
@@ -122,6 +129,8 @@ RoomList::updateUnreadMessageCount(const QString &roomid, int count, int highlig
rooms_[roomid]->updateUnreadMessageCount(count, highlightedCount);
calculateUnreadMessageCount();
+
+ sortRoomsByLastMessage();
}
void
@@ -328,30 +337,51 @@ RoomList::updateRoomDescription(const QString &roomid, const DescInfo &info)
emit sortRoomsByLastMessage();
}
+struct room_sort
+{
+ bool operator()(const RoomInfoListItem *a, const RoomInfoListItem *b) const
+ {
+ // Sort by "importance" (i.e. invites before mentions before
+ // notifs before new events before old events), then secondly
+ // by recency.
+
+ // Checking importance first
+ const auto a_importance = a->calculateImportance();
+ const auto b_importance = b->calculateImportance();
+ if (a_importance != b_importance) {
+ return a_importance > b_importance;
+ }
+
+ // Now sort by recency
+ // Zero if empty, otherwise the time that the event occured
+ const uint64_t a_recency = a->lastMessageInfo().userid.isEmpty()
+ ? 0
+ : a->lastMessageInfo().datetime.toMSecsSinceEpoch();
+ const uint64_t b_recency = b->lastMessageInfo().userid.isEmpty()
+ ? 0
+ : b->lastMessageInfo().datetime.toMSecsSinceEpoch();
+ return a_recency > b_recency;
+ }
+};
+
void
RoomList::sortRoomsByLastMessage()
{
isSortPending_ = false;
- std::multimap<uint64_t, RoomInfoListItem *, std::greater<uint64_t>> times;
+ std::multiset<RoomInfoListItem *, room_sort> times;
for (int ii = 0; ii < contentsLayout_->count(); ++ii) {
auto room = qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(ii)->widget());
if (!room)
continue;
-
- // Not a room message.
- if (room->isInvite())
- times.emplace(std::numeric_limits<uint64_t>::max(), room);
- else if (room->lastMessageInfo().userid.isEmpty())
- times.emplace(0, room);
else
- times.emplace(room->lastMessageInfo().datetime.toMSecsSinceEpoch(), room);
+ times.insert(room);
}
for (auto it = times.cbegin(); it != times.cend(); ++it) {
- const auto roomWidget = it->second;
+ const auto roomWidget = *it;
const auto currentIndex = contentsLayout_->indexOf(roomWidget);
const auto newIndex = std::distance(times.cbegin(), it);
@@ -468,7 +498,7 @@ RoomList::updateRoom(const QString &room_id, const RoomInfo &info)
void
RoomList::addInvitedRoom(const QString &room_id, const RoomInfo &info)
{
- auto room_item = new RoomInfoListItem(room_id, info, scrollArea_);
+ auto room_item = new RoomInfoListItem(room_id, info, settings, scrollArea_);
connect(room_item, &RoomInfoListItem::acceptInvite, this, &RoomList::acceptInvite);
connect(room_item, &RoomInfoListItem::declineInvite, this, &RoomList::declineInvite);
diff --git a/src/RoomList.h b/src/RoomList.h
index fef552c6..a0151f92 100644
--- a/src/RoomList.h
+++ b/src/RoomList.h
@@ -23,6 +23,9 @@
#include <QVBoxLayout>
#include <QWidget>
+#include "CacheStructs.h"
+#include "UserSettingsPage.h"
+
class LeaveRoomDialog;
class OverlayModal;
class RoomInfoListItem;
@@ -35,7 +38,7 @@ class RoomList : public QWidget
Q_OBJECT
public:
- explicit RoomList(QWidget *parent = nullptr);
+ explicit RoomList(QSharedPointer<UserSettings> userSettings, QWidget *parent = nullptr);
void initialize(const QMap<QString, RoomInfo> &info);
void sync(const std::map<QString, RoomInfo> &info);
@@ -100,4 +103,5 @@ private:
QString selectedRoom_;
bool isSortPending_ = false;
+ QSharedPointer<UserSettings> settings;
};
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index 930b1b7b..6cd9a95c 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -58,6 +58,7 @@ UserSettings::load()
isButtonsInTimelineEnabled_ = settings.value("user/timeline/buttons", true).toBool();
isMarkdownEnabled_ = settings.value("user/markdown_enabled", true).toBool();
isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool();
+ sortByImportance_ = settings.value("user/sort_by_unread", true).toBool();
isReadReceiptsEnabled_ = settings.value("user/read_receipts", true).toBool();
theme_ = settings.value("user/theme", defaultTheme_).toString();
font_ = settings.value("user/font_family", "default").toString();
@@ -135,6 +136,7 @@ UserSettings::save()
settings.setValue("font_size", baseFontSize_);
settings.setValue("typing_notifications", isTypingNotificationsEnabled_);
+ settings.setValue("minor_events", sortByImportance_);
settings.setValue("read_receipts", isReadReceiptsEnabled_);
settings.setValue("group_view", isGroupViewEnabled_);
settings.setValue("markdown_enabled", isMarkdownEnabled_);
@@ -197,6 +199,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
groupViewToggle_ = new Toggle{this};
timelineButtonsToggle_ = new Toggle{this};
typingNotifications_ = new Toggle{this};
+ sortByImportance_ = new Toggle{this};
readReceipts_ = new Toggle{this};
markdownEnabled_ = new Toggle{this};
desktopNotifications_ = new Toggle{this};
@@ -300,6 +303,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
boxWrap(tr("Group's sidebar"), groupViewToggle_);
boxWrap(tr("Show buttons in timeline"), timelineButtonsToggle_);
boxWrap(tr("Typing notifications"), typingNotifications_);
+ boxWrap(tr("Sort rooms by unreads"), sortByImportance_);
formLayout_->addRow(new HorizontalLine{this});
boxWrap(tr("Read receipts"), readReceipts_);
boxWrap(tr("Send messages as Markdown"), markdownEnabled_);
@@ -401,6 +405,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
settings_->setTypingNotifications(!isDisabled);
});
+ connect(sortByImportance_, &Toggle::toggled, this, [this](bool isDisabled) {
+ settings_->setSortByImportance(!isDisabled);
+ });
+
connect(timelineButtonsToggle_, &Toggle::toggled, this, [this](bool isDisabled) {
settings_->setButtonsInTimeline(!isDisabled);
});
@@ -439,6 +447,7 @@ UserSettingsPage::showEvent(QShowEvent *)
groupViewToggle_->setState(!settings_->isGroupViewEnabled());
avatarCircles_->setState(!settings_->isAvatarCirclesEnabled());
typingNotifications_->setState(!settings_->isTypingNotificationsEnabled());
+ sortByImportance_->setState(!settings_->isSortByImportanceEnabled());
timelineButtonsToggle_->setState(!settings_->isButtonsInTimelineEnabled());
readReceipts_->setState(!settings_->isReadReceiptsEnabled());
markdownEnabled_->setState(!settings_->isMarkdownEnabled());
diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h
index ca5a213c..1c20214e 100644
--- a/src/UserSettingsPage.h
+++ b/src/UserSettingsPage.h
@@ -87,6 +87,12 @@ public:
save();
}
+ void setSortByImportance(bool state)
+ {
+ sortByImportance_ = state;
+ emit roomSortingChanged();
+ }
+
void setButtonsInTimeline(bool state)
{
isButtonsInTimelineEnabled_ = state;
@@ -112,6 +118,7 @@ public:
bool isAvatarCirclesEnabled() const { return avatarCircles_; }
bool isMarkdownEnabled() const { return isMarkdownEnabled_; }
bool isTypingNotificationsEnabled() const { return isTypingNotificationsEnabled_; }
+ bool isSortByImportanceEnabled() const { return sortByImportance_; }
bool isButtonsInTimelineEnabled() const { return isButtonsInTimelineEnabled_; }
bool isReadReceiptsEnabled() const { return isReadReceiptsEnabled_; }
bool hasDesktopNotifications() const { return hasDesktopNotifications_; }
@@ -121,6 +128,7 @@ public:
signals:
void groupViewStateChanged(bool state);
+ void roomSortingChanged();
private:
// Default to system theme if QT_QPA_PLATFORMTHEME var is set.
@@ -134,6 +142,7 @@ private:
bool isGroupViewEnabled_;
bool isMarkdownEnabled_;
bool isTypingNotificationsEnabled_;
+ bool sortByImportance_;
bool isButtonsInTimelineEnabled_;
bool isReadReceiptsEnabled_;
bool hasDesktopNotifications_;
@@ -185,6 +194,7 @@ private:
Toggle *groupViewToggle_;
Toggle *timelineButtonsToggle_;
Toggle *typingNotifications_;
+ Toggle *sortByImportance_;
Toggle *readReceipts_;
Toggle *markdownEnabled_;
Toggle *desktopNotifications_;
|