diff --git a/src/RoomInfoListItem.cpp b/src/RoomInfoListItem.cpp index 61fb5e47b165406195dd994db18a5ffa013a9f30..7871828521ce16e326b9e9f74a7214f01cc74fbd 100644 --- a/src/RoomInfoListItem.cpp +++ b/src/RoomInfoListItem.cpp @@ -324,6 +324,15 @@ RoomInfoListItem::updateUnreadMessageCount(int count, int highlightedCount) update(); } +unsigned short int +RoomInfoListItem::calculateImportance() const +{ + return (hasUnreadMessages_) + + (unreadMsgCount_ != 0) + + (unreadHighlightedMsgCount_ != 0) + + (isInvite()) * 4; +} + void RoomInfoListItem::setPressedState(bool state) { diff --git a/src/RoomInfoListItem.h b/src/RoomInfoListItem.h index c1ee533d0e337e12a60e32bf2e364f412f834b38..a246e487c4045b184e59b67d64ba33aeaa9f034a 100644 --- a/src/RoomInfoListItem.h +++ b/src/RoomInfoListItem.h @@ -68,6 +68,8 @@ public: void updateUnreadMessageCount(int count, int highlightedCount); void clearUnreadMessageCount() { updateUnreadMessageCount(0, 0); }; + unsigned short int calculateImportance() const; + QString roomId() { return roomId_; } bool isPressed() const { return isPressed_; } int unreadMessageCount() const { return unreadMsgCount_; } @@ -128,7 +130,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) { diff --git a/src/RoomList.cpp b/src/RoomList.cpp index 6feb4f76671f958ce7b7ab8b9bc8ccfb436568ab..977cac9952d99161fc94f177d4656653ea27ee8e 100644 --- a/src/RoomList.cpp +++ b/src/RoomList.cpp @@ -16,6 +16,7 @@ */ #include <limits> +#include <set> #include <QObject> #include <QPainter> @@ -328,30 +329,47 @@ 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);