diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index 030c14e99..936c61703 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -1751,4 +1751,23 @@ ThreadModel *NeoChatRoom::modelForThread(const QString &threadRootId) return m_threadModels[threadRootId].get(); } +void NeoChatRoom::pinEvent(const QString &eventId) +{ + auto eventIds = pinnedEventIds(); + eventIds.push_back(eventId); + setPinnedEvents(eventIds); +} + +void NeoChatRoom::unpinEvent(const QString &eventId) +{ + auto eventIds = pinnedEventIds(); + eventIds.removeAll(eventId); + setPinnedEvents(eventIds); +} + +bool NeoChatRoom::isEventPinned(const QString &eventId) const +{ + return pinnedEventIds().contains(eventId); +} + #include "moc_neochatroom.cpp" diff --git a/src/neochatroom.h b/src/neochatroom.h index 803c6eacb..20a1e3769 100644 --- a/src/neochatroom.h +++ b/src/neochatroom.h @@ -601,6 +601,23 @@ public: */ Q_INVOKABLE ThreadModel *modelForThread(const QString &threadRootId); + /** + * @brief Pin a message in the room. + * @param eventId The id of the event to pin. + */ + Q_INVOKABLE void pinEvent(const QString &eventId); + + /** + * @brief Unpin a message in the room. + * @param eventId The id of the event to unpin. + */ + Q_INVOKABLE void unpinEvent(const QString &eventId); + + /** + * @return True if @p eventId is pinned in the room. + */ + Q_INVOKABLE bool isEventPinned(const QString &eventId) const; + private: bool m_visible = false; diff --git a/src/qml/DelegateContextMenu.qml b/src/qml/DelegateContextMenu.qml index 25f0b1c25..233ff03c5 100644 --- a/src/qml/DelegateContextMenu.qml +++ b/src/qml/DelegateContextMenu.qml @@ -132,6 +132,15 @@ KirigamiComponents.ConvergentContextMenu { } } + component PinMessageAction: Kirigami.Action { + readonly property bool pinned: currentRoom.isEventPinned(root.eventId) + + visible: currentRoom.canSendState("m.room.pinned_events") + text: pinned ? i18nc("@action:button 'Unpin' as in 'Unpin this message'", "Unpin") : i18nc("@action:button 'Pin' as in 'Pin the message in the room'", "Pin") + icon.name: pinned ? "window-unpin-symbolic" : "pin-symbolic" + onTriggered: pinned ? currentRoom.unpinEvent(root.eventId) : currentRoom.pinEvent(root.eventId) + } + headerContentItem: RowLayout { spacing: Kirigami.Units.largeSpacing diff --git a/src/qml/FileDelegateContextMenu.qml b/src/qml/FileDelegateContextMenu.qml index 8a8effdcb..d29fc7965 100644 --- a/src/qml/FileDelegateContextMenu.qml +++ b/src/qml/FileDelegateContextMenu.qml @@ -90,6 +90,8 @@ DelegateContextMenu { } } + DelegateContextMenu.PinMessageAction {} + DelegateContextMenu.ReportMessageAction {} DelegateContextMenu.ShowUserAction {} diff --git a/src/qml/MessageDelegateContextMenu.qml b/src/qml/MessageDelegateContextMenu.qml index d0bbc470b..54be17dac 100644 --- a/src/qml/MessageDelegateContextMenu.qml +++ b/src/qml/MessageDelegateContextMenu.qml @@ -86,6 +86,7 @@ DelegateContextMenu { Kirigami.Action { separator: true } + DelegateContextMenu.PinMessageAction {} DelegateContextMenu.ReportMessageAction {} DelegateContextMenu.ShowUserAction {} Kirigami.Action {