Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F114661
D129.1732569335.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D129.1732569335.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 25, 1:15 PM (11 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40328
Default Alt Text
D129.1732569335.diff (10 KB)
Attached To
Mode
D129: Support displaying pinned events
Attached
Detach File
Event Timeline
Log In to Comment