Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/changelogs/57.add b/changelogs/57.add
new file mode 100644
index 0000000..cedea31
--- /dev/null
+++ b/changelogs/57.add
@@ -0,0 +1 @@
+Sort rooms by descending order of latest event timestamp
diff --git a/src/matrix-room-list.cpp b/src/matrix-room-list.cpp
index 14aa0d3..f489e5e 100644
--- a/src/matrix-room-list.cpp
+++ b/src/matrix-room-list.cpp
@@ -1,116 +1,140 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <immer/config.hpp> // https://github.com/arximboldi/immer/issues/168
+#include <zug/into_vector.hpp>
#include <lager/commit.hpp>
#include <lager/constant.hpp>
#include <lager/lenses/optional.hpp>
#include "matrix-room-list.hpp"
#include "matrix-room.hpp"
#include "helper.hpp"
using namespace Kazv;
+static Timestamp latestEventTimestamp(const RoomModel &room)
+{
+ auto latestEventId = room.timeline[room.timeline.size() - 1];
+ auto latestEvent = room.messages[latestEventId];
+ return latestEvent.originServerTs();
+}
+
MatrixRoomList::MatrixRoomList(Kazv::Client client, QString tagId, QObject *parent)
: QAbstractListModel(parent)
, m_client(client)
, m_tagId(tagId)
, m_tagIdCursor(lager::make_sensor([this] { return m_tagId.toStdString(); }))
, m_internalCount(0)
- , m_roomIds(lager::with(m_tagIdCursor, m_client.roomIds(), m_client.roomIdsByTagId())
+ , m_roomIds(lager::with(m_tagIdCursor, m_client.rooms(), m_client.roomIdsByTagId())
.map([](const auto &tagIdStdStr, const auto &allRooms, const auto &roomsByTagMap) {
+ auto toId = zug::map([](const auto &pair) {
+ return pair.first;
+ });
+
+ auto sortByTimestampDesc = [allRooms](std::vector<std::string> container) {
+ std::sort(
+ container.begin(),
+ container.end(),
+ [allRooms](const std::string &idA, const std::string &idB) {
+ return latestEventTimestamp(allRooms[idA])
+ > latestEventTimestamp(allRooms[idB]);
+ }
+ );
+ return immer::flex_vector<std::string>(container.begin(), container.end());
+ };
+
if (tagIdStdStr.empty()) {
- return allRooms;
+ return sortByTimestampDesc(zug::into_vector(
+ toId,
+ allRooms
+ ));
} else {
- return intoImmer(
- immer::flex_vector<std::string>{},
- zug::map([](const auto &pair) {
- return pair.first;
- }),
+ return sortByTimestampDesc(zug::into_vector(
+ toId,
roomsByTagMap[tagIdStdStr]
- );
+ ));
}
}))
, LAGER_QT(count)(m_roomIds.xform(containerSize))
, LAGER_QT(roomIds)(m_roomIds.xform(zug::map(
[](auto container) {
return zug::into(QStringList{}, strToQt, std::move(container));
})))
{
m_internalCount = count();
connect(this, &MatrixRoomList::countChanged, this, &MatrixRoomList::updateInternalCount);
}
MatrixRoomList::~MatrixRoomList() = default;
void MatrixRoomList::setTagId(QString tagId)
{
m_tagId = tagId;
lager::commit(m_tagIdCursor);
}
MatrixRoom *MatrixRoomList::at(int index) const
{
qDebug() << "Room at index " << index << " requested";
return new MatrixRoom(
m_client.roomByCursor(
lager::with(m_roomIds, lager::make_constant(index))
.xform(zug::map([](auto ids, auto i) {
try {
return ids.at(i);
} catch (const std::out_of_range &) {
return std::string{};
}
}))),
m_client.userId());
}
QString MatrixRoomList::roomIdAt(int index) const
{
using namespace Kazv::CursorOp;
return +m_roomIds[index][lager::lenses::or_default].xform(strToQt);
}
MatrixRoom *MatrixRoomList::room(QString roomId) const
{
return new MatrixRoom(m_client.room(roomId.toStdString()), m_client.userId());
}
QVariant MatrixRoomList::data(const QModelIndex &/* index */, int /* role */) const
{
return QVariant();
}
int MatrixRoomList::rowCount(const QModelIndex &parent = QModelIndex()) const
{
if (parent.isValid()) {
return 0;
} else {
return count();
}
}
void MatrixRoomList::updateInternalCount()
{
auto curCount = count();
auto oldCount = m_internalCount;
auto diff = std::abs(curCount - oldCount);
if (curCount > oldCount) {
beginInsertRows(QModelIndex(), 0, diff - 1);
m_internalCount = curCount;
endInsertRows();
} else if (curCount < oldCount) {
beginRemoveRows(QModelIndex(), 0, diff - 1);
m_internalCount = curCount;
endRemoveRows();
}
}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 4647978..4aa637b 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -1,26 +1,26 @@
set(kazvtestlib_SRCS
test-model.cpp
)
add_library(kazvtestlib STATIC ${kazvtestlib_SRCS})
-target_link_libraries(kazvtestlib PUBLIC kazvprivlib)
+target_link_libraries(kazvtestlib PUBLIC kazvprivlib libkazv::kazvtestfixtures)
ecm_add_tests(
qt-job-handler-test.cpp
qt-promise-handler-test.cpp
device-mgmt-test.cpp
matrix-sdk-test.cpp
matrix-promise-test.cpp
matrix-room-timeline-test.cpp
matrix-room-member-list-model-test.cpp
matrix-room-list-test.cpp
LINK_LIBRARIES Qt5::Test kazvtestlib
)
ecm_add_test(
quick-test.cpp
TEST_NAME quicktest
LINK_LIBRARIES Qt5::QuickTest kazvtestlib
)
set_tests_properties(quicktest PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
diff --git a/src/tests/matrix-room-list-test.cpp b/src/tests/matrix-room-list-test.cpp
index 3b985d5..ed17c3f 100644
--- a/src/tests/matrix-room-list-test.cpp
+++ b/src/tests/matrix-room-list-test.cpp
@@ -1,60 +1,139 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <immer/config.hpp> // https://github.com/arximboldi/immer/issues/168
#include <memory>
#include <QtTest>
#include <matrix-room-timeline.hpp>
#include <matrix-sdk.hpp>
#include <matrix-room-list.hpp>
#include <matrix-room.hpp>
#include <matrix-event.hpp>
#include "test-model.hpp"
#include "test-utils.hpp"
+#include "factory.hpp"
using namespace Kazv;
+using namespace Kazv::Factory;
class MatrixRoomListTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testRoomList();
+ void testSorted();
+ void testSortedWithTag();
};
+static auto tagEvent = Event{R"({
+ "content": {
+ "tags": {"m.favourite": {}}
+ },
+ "type": "m.tag"
+})"_json};
+
void MatrixRoomListTest::testRoomList()
{
auto model = makeTestModel();
RoomModel room;
room.roomId = "!test:tusooa.xyz";
- room.accountData = room.accountData.set("m.tag", Event{R"({
- "content": {
- "tags": {"m.favourite": {}}
- },
- "type": "m.tag"
- })"_json});
+ room.accountData = room.accountData.set("m.tag", tagEvent);
model.client.roomList.rooms = model.client.roomList.rooms.set(room.roomId, room);
std::unique_ptr<MatrixSdk> sdk{makeTestSdk(model)};
auto roomList = toUniquePtr(sdk->roomList());
QCOMPARE(roomList->count(), 2);
roomList->setTagId("m.favourite");
QCOMPARE(roomList->count(), 1);
roomList->setTagId("u.xxx");
QCOMPARE(roomList->count(), 0);
}
+void MatrixRoomListTest::testSorted()
+{
+ auto model = makeTestModel();
+ model.client = makeClient();
+ auto room1 = makeRoom(
+ withRoomTimeline({
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 1000)),
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 2000))
+ })
+ );
+ auto room2 = makeRoom(
+ withRoomTimeline({
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 700)),
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 1500))
+ })
+ );
+ auto room3 = makeRoom(
+ withRoomTimeline({
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 1500)),
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 2500))
+ })
+ );
+
+ withRoom(room1)(model.client);
+ withRoom(room2)(model.client);
+ withRoom(room3)(model.client);
+
+ std::unique_ptr<MatrixSdk> sdk{makeTestSdk(model)};
+ auto roomList = toUniquePtr(sdk->roomList());
+
+ QCOMPARE(roomList->roomIdAt(0), QString::fromStdString(room3.roomId));
+ QCOMPARE(roomList->roomIdAt(1), QString::fromStdString(room1.roomId));
+ QCOMPARE(roomList->roomIdAt(2), QString::fromStdString(room2.roomId));
+}
+
+void MatrixRoomListTest::testSortedWithTag()
+{
+ auto model = makeTestModel();
+ model.client = makeClient();
+ auto room1 = makeRoom(
+ withRoomTimeline({
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 1000)),
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 2000))
+ })
+ | withRoomAccountData({tagEvent})
+ );
+ auto room2 = makeRoom(
+ withRoomTimeline({
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 700)),
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 1500))
+ })
+ | withRoomAccountData({tagEvent})
+ );
+ auto room3 = makeRoom(
+ withRoomTimeline({
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 1500)),
+ makeEvent(withEventKV("/origin_server_ts"_json_pointer, 2500))
+ })
+ | withRoomAccountData({tagEvent})
+ );
+
+ withRoom(room1)(model.client);
+ withRoom(room2)(model.client);
+ withRoom(room3)(model.client);
+
+ std::unique_ptr<MatrixSdk> sdk{makeTestSdk(model)};
+ auto roomList = toUniquePtr(sdk->roomList());
+
+ QCOMPARE(roomList->roomIdAt(0), QString::fromStdString(room3.roomId));
+ QCOMPARE(roomList->roomIdAt(1), QString::fromStdString(room1.roomId));
+ QCOMPARE(roomList->roomIdAt(2), QString::fromStdString(room2.roomId));
+}
+
QTEST_MAIN(MatrixRoomListTest)
#include "matrix-room-list-test.moc"

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 31, 4:14 AM (19 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1801020
Default Alt Text
(10 KB)

Event Timeline