diff --git a/src/app/qml/UserDetailDialog.qml b/src/app/qml/UserDetailDialog.qml index e021e348f..8c2b9e852 100644 --- a/src/app/qml/UserDetailDialog.qml +++ b/src/app/qml/UserDetailDialog.qml @@ -293,5 +293,25 @@ Kirigami.Dialog { icon.name: "username-copy" onClicked: Clipboard.saveText("https://matrix.to/#/" + root.user.id) } + + FormCard.FormButtonDelegate { + text: i18nc("@action:button 'Report' as in 'Report this user to the administrators'", "Report…") + icon.name: "dialog-warning-symbolic" + visible: root.connection.supportsMatrixSpecVersion("v1.13") + onClicked: { + let dialog = ((QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), { + title: i18nc("@title:dialog", "Report User"), + placeholder: i18nc("@info:placeholder", "Reason for reporting this user"), + icon: "dialog-warning-symbolic", + actionText: i18nc("@action:button 'Report' as in 'Report this user to the administrators'", "Report") + }, { + title: i18nc("@title", "Report User"), + width: Kirigami.Units.gridUnit * 25 + }) as ReasonDialog; + dialog.accepted.connect(reason => { + root.connection.reportUser(root.user.id, reason); + }); + } + } } } diff --git a/src/libneochat/CMakeLists.txt b/src/libneochat/CMakeLists.txt index 32d4d1feb..be18088b7 100644 --- a/src/libneochat/CMakeLists.txt +++ b/src/libneochat/CMakeLists.txt @@ -33,6 +33,8 @@ target_sources(LibNeoChat PRIVATE events/imagepackevent.cpp events/pollevent.cpp jobs/neochatgetcommonroomsjob.cpp + jobs/neochatreportroomjob.cpp + jobs/neochatreportuserjob.cpp models/actionsmodel.cpp models/completionmodel.cpp models/completionproxymodel.cpp diff --git a/src/libneochat/jobs/neochatreportroomjob.cpp b/src/libneochat/jobs/neochatreportroomjob.cpp new file mode 100644 index 000000000..a4b917f76 --- /dev/null +++ b/src/libneochat/jobs/neochatreportroomjob.cpp @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "neochatreportroomjob.h" + +using namespace Quotient; + +NeochatReportRoomJob::NeochatReportRoomJob(const QString &userId, const QString &reason) + : BaseJob(HttpVerb::Post, u"ReportRoomJob"_s, makePath(" /_matrix/client/v3/", userId, "/report")) +{ + QJsonObject _dataJson; + addParam(_dataJson, "reason"_L1, reason); + setRequestData({_dataJson}); +} diff --git a/src/libneochat/jobs/neochatreportroomjob.h b/src/libneochat/jobs/neochatreportroomjob.h new file mode 100644 index 000000000..1311a4aac --- /dev/null +++ b/src/libneochat/jobs/neochatreportroomjob.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +// TODO: Remove once libQuotient updates to Matrix API v1.14 +class NeochatReportRoomJob : public Quotient::BaseJob +{ +public: + explicit NeochatReportRoomJob(const QString &roomId, const QString &reason); +}; diff --git a/src/libneochat/jobs/neochatreportuserjob.cpp b/src/libneochat/jobs/neochatreportuserjob.cpp new file mode 100644 index 000000000..eb6f9c3a5 --- /dev/null +++ b/src/libneochat/jobs/neochatreportuserjob.cpp @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "neochatreportuserjob.h" + +using namespace Quotient; + +NeochatReportUserJob::NeochatReportUserJob(const QString &userId, const QString &reason) + : BaseJob(HttpVerb::Post, u"ReportUserJob"_s, makePath("/_matrix/client/v3/users/", userId, "/report")) +{ + QJsonObject _dataJson; + addParam(_dataJson, "reason"_L1, reason); + setRequestData({_dataJson}); +} diff --git a/src/libneochat/jobs/neochatreportuserjob.h b/src/libneochat/jobs/neochatreportuserjob.h new file mode 100644 index 000000000..dc1ac759d --- /dev/null +++ b/src/libneochat/jobs/neochatreportuserjob.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +// TODO: Remove once libQuotient updates to Matrix API v1.14 +class NeochatReportUserJob : public Quotient::BaseJob +{ +public: + explicit NeochatReportUserJob(const QString &userId, const QString &reason); +}; diff --git a/src/libneochat/neochatconnection.cpp b/src/libneochat/neochatconnection.cpp index c65ee654a..666b45f90 100644 --- a/src/libneochat/neochatconnection.cpp +++ b/src/libneochat/neochatconnection.cpp @@ -6,6 +6,7 @@ #include #include +#include "jobs/neochatreportuserjob.h" #include "neochatroom.h" #include "spacehierarchycache.h" diff --git a/src/libneochat/neochatroom.cpp b/src/libneochat/neochatroom.cpp index ee11c78e3..c69668605 100644 --- a/src/libneochat/neochatroom.cpp +++ b/src/libneochat/neochatroom.cpp @@ -50,12 +50,12 @@ #include "roomlastmessageprovider.h" #include "spacehierarchycache.h" #include "urlhelper.h" +#include "jobs/neochatreportroomjob.h" #ifndef Q_OS_ANDROID #include #include #endif - #include #include @@ -1838,4 +1838,9 @@ QString NeoChatRoom::pinnedMessage() const return m_pinnedMessage; } +void NeoChatRoom::report(const QString &reason) +{ + connection()->callApi(id(), reason); +} + #include "moc_neochatroom.cpp" diff --git a/src/libneochat/neochatroom.h b/src/libneochat/neochatroom.h index 56ec51a0b..0c9c29c08 100644 --- a/src/libneochat/neochatroom.h +++ b/src/libneochat/neochatroom.h @@ -622,6 +622,11 @@ public: */ QString pinnedMessage() const; + /** + * @brief Send a report about this room. + */ + Q_INVOKABLE void report(const QString &reason); + private: bool m_visible = false; diff --git a/src/rooms/RoomContextMenu.qml b/src/rooms/RoomContextMenu.qml index 9304af9e9..a715d3b68 100644 --- a/src/rooms/RoomContextMenu.qml +++ b/src/rooms/RoomContextMenu.qml @@ -150,6 +150,26 @@ KirigamiComponents.ConvergentContextMenu { separator: true } + Kirigami.Action { + text: i18nc("@action:button 'Report' as in 'Report this room to the administrators'", "Report…") + icon.name: "dialog-warning-symbolic" + visible: root.connection.supportsMatrixSpecVersion("v1.13") + onTriggered: { + let dialog = (root.Kirigami.PageStack.pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), { + title: i18nc("@title:dialog", "Report Room"), + placeholder: i18nc("@info:placeholder", "Reason for reporting this room"), + icon: "dialog-warning-symbolic", + actionText: i18nc("@action:button 'Report' as in 'Report this room to the administrators'", "Report") + }, { + title: i18nc("@title", "Report Room"), + width: Kirigami.Units.gridUnit * 25 + }) as ReasonDialog; + dialog.accepted.connect(reason => { + currentRoom.report(reason); + }); + } + } + QQC2.Action { text: i18nc("@action:inmenu", "Leave Room…") icon.name: "go-previous"