Page MenuHomePhorge

D129.1726791330.diff
No OneTemporary

D129.1726791330.diff

diff --git a/src/contents/ui/RoomPage.qml b/src/contents/ui/RoomPage.qml
--- a/src/contents/ui/RoomPage.qml
+++ b/src/contents/ui/RoomPage.qml
@@ -23,6 +23,7 @@
room: roomPage.room
}
property var roomTimeline: room.timeline()
+ property var pinnedEvents: room.pinnedEventsTimeline()
property var lastReceiptableEventId: getLastReceiptableEventId(roomTimeline, roomTimeline.count)
property var paginationRequests: ({})
property var refreshRoomStateRequest: null
@@ -67,6 +68,15 @@
visible: isInvite
onTriggered: leaveRoomHandler.call()
},
+ Kirigami.Action {
+ id: pinnedEventsAction
+ objectName: 'pinnedEventsAction'
+ icon.name: 'pin'
+ visible: roomPage.pinnedEvents.count
+ enabled: roomPage.pinnedEvents.count
+ text: l10n.get('room-pinned-events-action', { count: roomPage.pinnedEvents.count })
+ onTriggered: activateRoomPinnedEventsPage(room)
+ },
Kirigami.Action {
id: roomSettingsAction
icon.name: 'settings-configure'
diff --git a/src/contents/ui/RoomPinnedEventsPage.qml b/src/contents/ui/RoomPinnedEventsPage.qml
new file mode 100644
--- /dev/null
+++ b/src/contents/ui/RoomPinnedEventsPage.qml
@@ -0,0 +1,27 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+
+import '.' as Kazv
+
+Kazv.ClosableScrollablePage {
+ id: roomPinnedEventsPage
+
+ property var room
+ property var roomNameProvider: Kazv.RoomNameProvider {
+ room: roomPinnedEventsPage.room
+ }
+ property var pinnedTimeline: room.pinnedEventsTimeline()
+
+ title: l10n.get('room-pinned-events-page-title', { room: roomNameProvider.name })
+
+ RoomTimelineView {
+ timeline: roomPinnedEventsPage.pinnedTimeline
+ }
+}
diff --git a/src/contents/ui/RoomTimelineView.qml b/src/contents/ui/RoomTimelineView.qml
--- a/src/contents/ui/RoomTimelineView.qml
+++ b/src/contents/ui/RoomTimelineView.qml
@@ -12,6 +12,7 @@
ListView {
id: roomTimelineView
+ objectName: 'roomTimelineView'
property var timeline
property var eventIds: timeline.eventIds
diff --git a/src/contents/ui/main.qml b/src/contents/ui/main.qml
--- a/src/contents/ui/main.qml
+++ b/src/contents/ui/main.qml
@@ -175,6 +175,12 @@
});
}
+ function activateRoomPinnedEventsPage(room) {
+ pageStack.push(Qt.resolvedUrl('RoomPinnedEventsPage.qml'), {
+ room
+ });
+ }
+
function activateRoomInvitePage(room) {
pageStack.push(Qt.resolvedUrl("room-settings/RoomInvitePage.qml"), {
room
diff --git a/src/l10n/cmn-Hans/100-ui.ftl b/src/l10n/cmn-Hans/100-ui.ftl
--- a/src/l10n/cmn-Hans/100-ui.ftl
+++ b/src/l10n/cmn-Hans/100-ui.ftl
@@ -133,6 +133,9 @@
room-invite-popup-text = 你被邀请到这个房间了。
room-invite-popup-text-with-inviter = 你被 { $inviterName } 邀请到这个房间了。
+room-pinned-events-action = { $count } 条置顶消息...
+room-pinned-events-page-title = { $room } 的置顶消息
+
## 状态事件
## 通用参数:
## gender = 发送者的性别(male/female/neutral)
diff --git a/src/l10n/en/100-ui.ftl b/src/l10n/en/100-ui.ftl
--- a/src/l10n/en/100-ui.ftl
+++ b/src/l10n/en/100-ui.ftl
@@ -137,6 +137,12 @@
room-invite-popup-text = You are invited to join this room.
room-invite-popup-text-with-inviter = You are invited to join this room by { $inviterName }.
+room-pinned-events-action = { $count } pinned { $count ->
+ [1] message
+ *[other] messages
+}...
+room-pinned-events-page-title = Pinned messages of { $room }
+
## State events
## Common parameters:
## gender = gender of the sender (male/female/neutral)
diff --git a/src/matrix-room-timeline.hpp b/src/matrix-room-timeline.hpp
--- a/src/matrix-room-timeline.hpp
+++ b/src/matrix-room-timeline.hpp
@@ -32,6 +32,7 @@
public:
explicit MatrixRoomTimeline(Kazv::Room room, QObject *parent = 0);
+ explicit MatrixRoomTimeline(lager::reader<immer::flex_vector<std::string>> eventIds, lager::reader<immer::map<std::string, Kazv::Event>> messagesMap, lager::reader<immer::flex_vector<Kazv::LocalEchoDesc>> localEchoes, lager::reader<immer::map<std::string, std::string>> timelineGaps, Kazv::Room room, QObject *parent = 0);
~MatrixRoomTimeline() override;
LAGER_QT_READER(QSet<QString>, gaps);
diff --git a/src/matrix-room-timeline.cpp b/src/matrix-room-timeline.cpp
--- a/src/matrix-room-timeline.cpp
+++ b/src/matrix-room-timeline.cpp
@@ -23,13 +23,13 @@
using namespace Kazv;
-MatrixRoomTimeline::MatrixRoomTimeline(Kazv::Room room, QObject *parent)
+MatrixRoomTimeline::MatrixRoomTimeline(lager::reader<immer::flex_vector<std::string>> eventIds, lager::reader<immer::map<std::string, Kazv::Event>> messagesMap, lager::reader<immer::flex_vector<LocalEchoDesc>> localEchoes, lager::reader<immer::map<std::string, std::string>> timelineGaps, Kazv::Room room, QObject *parent)
: KazvAbstractListModel(parent)
, m_room(room)
- , m_timelineEventIds(m_room.timelineEventIds())
- , m_messagesMap(m_room.messagesMap())
- , m_localEchoes(m_room.localEchoes())
- , m_timelineGaps(m_room.timelineGaps())
+ , m_timelineEventIds(eventIds)
+ , m_messagesMap(messagesMap)
+ , m_localEchoes(localEchoes)
+ , m_timelineGaps(timelineGaps)
, LAGER_QT(gaps)(m_timelineGaps.map([](auto g) {
QSet<QString> res{};
for (const auto &[k, _v] : g) {
@@ -44,6 +44,18 @@
).map([](const auto &tlSize, const auto &localSize) { return tlSize + localSize; }), InitLater);
}
+MatrixRoomTimeline::MatrixRoomTimeline(Kazv::Room room, QObject *parent)
+ : MatrixRoomTimeline(
+ room.timelineEventIds(),
+ room.messagesMap(),
+ room.localEchoes(),
+ room.timelineGaps(),
+ room,
+ parent
+ )
+{
+}
+
MatrixRoomTimeline::~MatrixRoomTimeline() = default;
MatrixEvent *MatrixRoomTimeline::at(int index) const
diff --git a/src/matrix-room.hpp b/src/matrix-room.hpp
--- a/src/matrix-room.hpp
+++ b/src/matrix-room.hpp
@@ -68,6 +68,8 @@
Q_INVOKABLE MatrixRoomTimeline *timeline() const;
+ Q_INVOKABLE MatrixRoomTimeline *pinnedEventsTimeline() const;
+
Q_INVOKABLE MatrixEvent *messageById(QString eventId) const;
Q_INVOKABLE void sendMessage(const QJsonObject &eventJson, const QString &relType, const QString &relatedTo) const;
diff --git a/src/matrix-room.cpp b/src/matrix-room.cpp
--- a/src/matrix-room.cpp
+++ b/src/matrix-room.cpp
@@ -105,6 +105,17 @@
return new MatrixRoomTimeline(m_room);
}
+MatrixRoomTimeline *MatrixRoom::pinnedEventsTimeline() const
+{
+ return new MatrixRoomTimeline(
+ m_room.pinnedEvents(),
+ m_room.messagesMap(),
+ lager::make_constant(immer::flex_vector<LocalEchoDesc>()),
+ lager::make_constant(immer::map<std::string, std::string>()),
+ m_room
+ );
+}
+
static void maybeAddRelations(nlohmann::json &msg, const QString &relType, const QString &relatedTo)
{
if (relatedTo.isEmpty()) {
diff --git a/src/resources.qrc b/src/resources.qrc
--- a/src/resources.qrc
+++ b/src/resources.qrc
@@ -11,6 +11,7 @@
<file alias="RoomListView.qml">contents/ui/RoomListView.qml</file>
<file alias="RoomListViewItemDelegate.qml">contents/ui/RoomListViewItemDelegate.qml</file>
<file alias="RoomPage.qml">contents/ui/RoomPage.qml</file>
+ <file alias="RoomPinnedEventsPage.qml">contents/ui/RoomPinnedEventsPage.qml</file>
<file alias="RoomTimelineView.qml">contents/ui/RoomTimelineView.qml</file>
<file alias="SendMessageBox.qml">contents/ui/SendMessageBox.qml</file>
<file alias="EventView.qml">contents/ui/EventView.qml</file>
diff --git a/src/tests/quick-tests/tst_RoomPage.qml b/src/tests/quick-tests/tst_RoomPage.qml
--- a/src/tests/quick-tests/tst_RoomPage.qml
+++ b/src/tests/quick-tests/tst_RoomPage.qml
@@ -51,12 +51,23 @@
property var roomJoin: Helpers.factory.room({
membership: MK.MatrixRoom.Join,
paginateBackFrom: mockHelper.promise(),
+ pinnedEventsTimeline: () => ({
+ count: 0,
+ }),
})
property var roomLeave: Helpers.factory.room({
membership: MK.MatrixRoom.Leave,
})
+ property var roomWithPinned: Helpers.factory.room({
+ membership: MK.MatrixRoom.Join,
+ paginateBackFrom: mockHelper.promise(),
+ pinnedEventsTimeline: () => ({
+ count: 1,
+ }),
+ })
+
property var l10n: Helpers.fluentMock
property var matrixSdk: TestHelpers.MatrixSdkMock {
property var userId: '@foo:example.org'
@@ -78,6 +89,11 @@
id: pageLeave
room: roomLeave
}
+
+ Kazv.RoomPage {
+ id: pageWithPinned
+ room: roomWithPinned
+ }
}
TestCase {
@@ -128,5 +144,12 @@
tryVerify(() => roomJoin.paginateBackFrom.calledTimes() === 3);
verify(roomJoin.paginateBackFrom.lastArgs()[0] === '$1');
}
+
+ function test_pinnedAction() {
+ verify(!findChild(pageJoin, 'pinnedEventsAction').visible);
+ verify(!findChild(pageJoin, 'pinnedEventsAction').enabled);
+ verify(findChild(pageWithPinned, 'pinnedEventsAction').visible);
+ verify(findChild(pageWithPinned, 'pinnedEventsAction').enabled);
+ }
}
}
diff --git a/src/tests/quick-tests/tst_RoomPinnedEventsPage.qml b/src/tests/quick-tests/tst_RoomPinnedEventsPage.qml
new file mode 100644
--- /dev/null
+++ b/src/tests/quick-tests/tst_RoomPinnedEventsPage.qml
@@ -0,0 +1,70 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import QtQuick
+import QtQuick.Layouts
+import QtTest
+import '../../contents/ui' as Kazv
+import 'test-helpers.js' as Helpers
+import 'test-helpers' as TestHelpers
+
+Item {
+ id: item
+ width: 800
+ height: 600
+
+ property var mockHelper: TestHelpers.MockHelper {}
+
+ property var room: ({
+ name: 'some room',
+ pinnedEventsTimeline() {
+ return item.timeline;
+ },
+ })
+ property var makeTextEvent: (i) => ({
+ eventId: '$' + i,
+ sender: '@foo:tusooa.xyz',
+ type: 'm.room.message',
+ stateKey: '',
+ content: {
+ msgtype: 'm.text',
+ body: 'some body',
+ },
+ formattedTime: '4:06 P.M.',
+ })
+
+ property var timeline: ListModel {
+ ListElement {}
+ ListElement {}
+
+ function at(index) {
+ return makeTextEvent(index);
+ }
+ }
+
+ Kazv.RoomPinnedEventsPage {
+ anchors.fill: parent
+ id: pinnedEventsPage
+ room: item.room
+ }
+
+ TestCase {
+ id: roomPinnedEventsPageTest
+ name: 'RoomPinnedEventsPageTest'
+ when: windowShown
+
+ function initTestCase() {
+ pinnedEventsPage.contentItem.clip = false;
+ }
+
+ function test_pinned() {
+ const roomTimelineView = findChild(pinnedEventsPage, 'roomTimelineView');
+ verify(roomTimelineView);
+ tryVerify(() => roomTimelineView.itemAtIndex(0));
+ tryVerify(() => roomTimelineView.itemAtIndex(1));
+ }
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 19, 5:15 PM (8 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15943
Default Alt Text
D129.1726791330.diff (10 KB)

Event Timeline