Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85828226
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 31, 4:14 AM (16 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1801020
Default Alt Text
(10 KB)
Attached To
Mode
rK kazv
Attached
Detach File
Event Timeline