diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index 94e30c147..c6b1bfb9a 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -1075,6 +1075,12 @@ void NeoChatRoom::setHistoryVisibility(const QString &historyVisibilityRule) // Not emitting historyVisibilityChanged() here, since that would override the change in the UI with the *current* value, which is not the *new* value. } +int NeoChatRoom::getUserPowerLevel(const QString &userId) const +{ + auto powerLevelEvent = getCurrentState(); + return powerLevelEvent->powerLevelForUser(userId); +} + void NeoChatRoom::setUserPowerLevel(const QString &userID, const int &powerLevel) { if (joinedCount() <= 1) { diff --git a/src/neochatroom.h b/src/neochatroom.h index 9caf80021..3320d96fd 100644 --- a/src/neochatroom.h +++ b/src/neochatroom.h @@ -153,6 +153,14 @@ public: [[nodiscard]] QString historyVisibility() const; void setHistoryVisibility(const QString &historyVisibilityRule); + /** + * @brief Get the power level for the given user ID in the room. + * + * Returns the default value for a user in the room if they have no escalated + * privileges or if they are not a member so membership should be known before using. + */ + Q_INVOKABLE [[nodiscard]] int getUserPowerLevel(const QString &userId) const; + Q_INVOKABLE void setUserPowerLevel(const QString &userID, const int &powerLevel); [[nodiscard]] int powerLevel(const QString &eventName, const bool &isStateEvent = false) const; diff --git a/src/qml/Dialog/PowerLevelDialog.qml b/src/qml/Dialog/PowerLevelDialog.qml new file mode 100644 index 000000000..5377137e6 --- /dev/null +++ b/src/qml/Dialog/PowerLevelDialog.qml @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2023 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQuick.Layouts 1.15 + +import org.kde.kirigami 2.15 as Kirigami + +import org.kde.neochat 1.0 + +Kirigami.OverlaySheet { + id: root + title: i18n("Edit user power level") + + property var room + property var userId + property int powerLevel + + onSheetOpenChanged: { + if (sheetOpen) { + powerLevelComboBox.currentIndex = powerLevelComboBox.indexOfValue(root.powerLevel) + } + } + Kirigami.FormLayout { + QQC2.ComboBox { + id: powerLevelComboBox + model: ListModel { + id: powerLevelModel + } + textRole: "text" + valueRole: "powerLevel" + popup.z: root.z + 1 // Otherwise the popup will be behind the overlay sheet. + + // Done this way so we can have translated strings. + Component.onCompleted: { + powerLevelModel.append({"text": i18n("Member (0)"), "powerLevel": 0}); + powerLevelModel.append({"text": i18n("Moderator (50)"), "powerLevel": 50}); + powerLevelModel.append({"text": i18n("Admin (100)"), "powerLevel": 100}); + } + } + QQC2.Button { + text: i18n("Confirm") + onClicked: { + room.setUserPowerLevel(root.userId, powerLevelComboBox.currentValue) + root.close() + root.destroy() + } + } + } +} diff --git a/src/qml/Dialog/UserDetailDialog.qml b/src/qml/Dialog/UserDetailDialog.qml index a3c6a05b8..f8d9de8ce 100644 --- a/src/qml/Dialog/UserDetailDialog.qml +++ b/src/qml/Dialog/UserDetailDialog.qml @@ -139,6 +139,29 @@ Kirigami.OverlaySheet { } } } + Kirigami.BasicListItem { + visible: room.canSendState("m.room.power_levels") + action: Kirigami.Action { + text: i18n("Set user power level") + icon.name: "visibility" + onTriggered: { + let dialog = powerLevelDialog.createObject(applicationWindow().overlay, { + room: root.room, + userId: root.user.id, + powerLevel: root.room.getUserPowerLevel(root.user.id) + }); + dialog.open() + root.close() + } + } + + Component { + id: powerLevelDialog + PowerLevelDialog { + id: powerLevelDialog + } + } + } Kirigami.BasicListItem { visible: user === room.localUser || room.canSendState("redact") diff --git a/src/qml/RoomSettings/Permissions.qml b/src/qml/RoomSettings/Permissions.qml index 4e0d60cb8..2b302a5a8 100644 --- a/src/qml/RoomSettings/Permissions.qml +++ b/src/qml/RoomSettings/Permissions.qml @@ -28,9 +28,6 @@ Kirigami.ScrollablePage { ListModel { id: powerLevelModel - ListElement {text: "Member (0)"; powerLevel: 0} - ListElement {text: "Moderator (50)"; powerLevel: 50} - ListElement {text: "Admin (100)"; powerLevel: 100} } ColumnLayout { @@ -67,7 +64,19 @@ Kirigami.ScrollablePage { textRole: "text" valueRole: "powerLevel" visible: room.canSendState("m.room.power_levels") - Component.onCompleted: currentIndex = indexOfValue(powerLevel) + Component.onCompleted: { + /** + * This is very silly but the only way to populate the model with + * translated strings. Done here because the model needs to be filled + * before the first delegate sets it's current index. + */ + if (powerLevelModel.count == 0) { + powerLevelModel.append({"text": i18n("Member (0)"), "powerLevel": 0}); + powerLevelModel.append({"text": i18n("Moderator (50)"), "powerLevel": 50}); + powerLevelModel.append({"text": i18n("Admin (100)"), "powerLevel": 100}); + } + currentIndex = indexOfValue(powerLevel) + } onActivated: { room.setUserPowerLevel(userId, currentValue) } @@ -162,9 +171,12 @@ Kirigami.ScrollablePage { id: editPowerLevelAction onTriggered: { userListSearchPopup.close() - powerLevelSheet.userId = userId - powerLevelSheet.powerLevel = powerLevel - powerLevelSheet.open() + let dialog = powerLevelDialog.createObject(applicationWindow().overlay, { + room: root.room, + userId: model.userId, + powerLevel: model.powerLevel + }); + dialog.open(); } } @@ -184,6 +196,13 @@ Kirigami.ScrollablePage { textFormat: Text.PlainText wrapMode: Text.NoWrap } + + Component { + id: powerLevelDialog + PowerLevelDialog { + id: powerLevelDialog + } + } } } } @@ -393,34 +412,4 @@ Kirigami.ScrollablePage { } } } - Kirigami.OverlaySheet { - id: powerLevelSheet - title: i18n("Edit user power level") - - property var userId - property int powerLevel - - onSheetOpenChanged: { - if (sheetOpen) { - powerLevelComboBox.currentIndex = powerLevelComboBox.indexOfValue(powerLevelSheet.powerLevel) - } - } - Kirigami.FormLayout { - QQC2.ComboBox { - id: powerLevelComboBox - focusPolicy: Qt.NoFocus // provided by parent - model: powerLevelModel - textRole: "text" - valueRole: "powerLevel" - visible: room.canSendState("m.room.power_levels") - } - QQC2.Button { - text: i18n("Confirm") - onClicked: { - room.setUserPowerLevel(powerLevelSheet.userId, powerLevelComboBox.currentValue) - powerLevelSheet.close() - } - } - } - } } diff --git a/src/res.qrc b/src/res.qrc index 96adb1d48..76f92b994 100644 --- a/src/res.qrc +++ b/src/res.qrc @@ -64,6 +64,7 @@ qml/Dialog/OpenFileDialog.qml qml/Dialog/KeyVerification/KeyVerificationDialog.qml qml/Dialog/ConfirmLogoutDialog.qml + qml/Dialog/PowerLevelDialog.qml qml/Dialog/KeyVerification/Message.qml qml/Dialog/KeyVerification/EmojiItem.qml qml/Dialog/KeyVerification/EmojiRow.qml