From 757679a6e005c0571a6493c84175c5de9f4b21c1 Mon Sep 17 00:00:00 2001 From: miruka Date: Mon, 13 Jul 2020 18:44:20 -0400 Subject: [PATCH] Make power level control permission-aware --- TODO.md | 7 +++++ src/backend/matrix_client.py | 2 ++ src/backend/models/items.py | 2 ++ src/gui/Base/PowerLevelControl.qml | 29 ++++++++++++------- .../RoomPane/MemberView/MemberProfile.qml | 10 ++++++- .../Chat/RoomPane/MemberView/MemberView.qml | 5 ++++ 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/TODO.md b/TODO.md index b88433d5..76795c14 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,12 @@ # TODO +- fix reply bar height +- don't trust PowerLevelsEvent, may be old +- joining new DM, not loading past events? +- HLabeledItem disabled opacity +- cancel setPowerLevel future on Cancel button click +- enter to trigger apply button +- destroy setPowerLevel future on Component.onDestruction - warn about setting level of someone to 100 - gray out if no permission to change - improve event text diff --git a/src/backend/matrix_client.py b/src/backend/matrix_client.py index 2a831283..93d25a99 100644 --- a/src/backend/matrix_client.py +++ b/src/backend/matrix_client.py @@ -1684,6 +1684,7 @@ class MatrixClient(nio.AsyncClient): guests_allowed = room.guest_access == "can_join", default_power_level = levels.defaults.users_default, + own_power_level = levels.get_user_level(self.user_id), can_invite = levels.can_user_invite(self.user_id), can_kick = levels.can_user_kick(self.user_id), can_redact_all = levels.can_user_redact(self.user_id), @@ -1694,6 +1695,7 @@ class MatrixClient(nio.AsyncClient): can_set_encryption = can_send_state("m.room.encryption"), can_set_join_rules = can_send_state("m.room.join_rules"), can_set_guest_access = can_send_state("m.room.guest_access"), + can_set_power_levels = can_send_state("m.room.power_levels"), last_event_date = last_event_date, diff --git a/src/backend/models/items.py b/src/backend/models/items.py index fdc4b5ca..1b80b13a 100644 --- a/src/backend/models/items.py +++ b/src/backend/models/items.py @@ -180,6 +180,7 @@ class Room(ModelItem): guests_allowed: bool = True default_power_level: int = 0 + own_power_level: int = 0 can_invite: bool = False can_kick: bool = False can_redact_all: bool = False @@ -190,6 +191,7 @@ class Room(ModelItem): can_set_encryption: bool = False can_set_join_rules: bool = False can_set_guest_access: bool = False + can_set_power_levels: bool = False last_event_date: datetime = ZERO_DATE diff --git a/src/gui/Base/PowerLevelControl.qml b/src/gui/Base/PowerLevelControl.qml index 4b457a2a..eaccbae3 100644 --- a/src/gui/Base/PowerLevelControl.qml +++ b/src/gui/Base/PowerLevelControl.qml @@ -4,14 +4,21 @@ import QtQuick 2.12 import QtQuick.Layouts 1.12 AutoDirectionLayout { - id: control + id: root property int defaultLevel: 0 + property int maximumLevel: 100 readonly property alias changed: field.changed - readonly property int level: Math.min(100, parseInt(field.text || "0", 10)) + + readonly property int level: + Math.min(maximumLevel, parseInt(field.text || "0", 10)) + readonly property alias fieldFocused: field.activeFocus + readonly property bool fieldOverMaximum: + parseInt(field.text || "0", 10) > maximumLevel + signal accepted() function reset() { field.reset() } @@ -26,15 +33,15 @@ AutoDirectionLayout { radius: 0 horizontalAlignment: Qt.AlignHCenter - validator: IntValidator { top: 100 } + validator: IntValidator { top: root.maximumLevel } inputMethodHints: Qt.ImhFormattedNumbersOnly - maximumLength: control.level < 0 ? 16 : 3 - defaultText: String(control.defaultLevel) + maximumLength: root.level < 0 ? 16 : String(root.maximumLevel).length + defaultText: String(root.defaultLevel) + error: root.fieldOverMaximum - onAccepted: control.accepted() + onAccepted: root.accepted() onActiveFocusChanged: - if (! activeFocus && parseInt(text || "0", 10) > 100) - text = 100 + if (! activeFocus && fieldOverMaximum) text = root.maximumLevel Layout.minimumWidth: mainUI.fontMetrics.boundingRect("-999").width + @@ -52,7 +59,7 @@ AutoDirectionLayout { height: parent.height icon.name: "user-power-default" toolTip.text: qsTr("Limited") - checked: control.level < 50 + checked: root.level < 50 uncheckable: false onClicked: field.text = 0 } @@ -61,7 +68,7 @@ AutoDirectionLayout { height: parent.height icon.name: "user-power-50" toolTip.text: qsTr("Moderator") - checked: control.level >= 50 && control.level < 100 + checked: root.level >= 50 && root.level < 100 uncheckable: false onClicked: field.text = 50 } @@ -70,7 +77,7 @@ AutoDirectionLayout { height: parent.height icon.name: "user-power-100" toolTip.text: qsTr("Admin") - checked: control.level >= 100 + checked: root.level >= 100 uncheckable: false onClicked: field.text = 100 } diff --git a/src/gui/Pages/Chat/RoomPane/MemberView/MemberProfile.qml b/src/gui/Pages/Chat/RoomPane/MemberView/MemberProfile.qml index 86437202..4bce1a59 100644 --- a/src/gui/Pages/Chat/RoomPane/MemberView/MemberProfile.qml +++ b/src/gui/Pages/Chat/RoomPane/MemberView/MemberProfile.qml @@ -12,6 +12,8 @@ HListView { property string userId property string roomId + property int ownPowerLevel + property int canSetPowerLevels property QtObject member // RoomMember model item property HStackView stackView @@ -160,6 +162,10 @@ HListView { HLabeledItem { id: powerLevel + enabled: + root.canSetPowerLevels && + root.ownPowerLevel > member.power_level + label.text: qsTr("Power level:") label.horizontalAlignment: Qt.AlignHCenter @@ -168,6 +174,7 @@ HListView { PowerLevelControl { width: parent.width defaultLevel: member.power_level + maximumLevel: root.ownPowerLevel rowSpacing: powerLevel.spacing onAccepted: applyButton.clicked() onFieldFocusedChanged: @@ -191,6 +198,7 @@ HListView { ApplyButton { id: applyButton + enabled: ! powerLevel.item.fieldOverMaximum loading: setPowerFuture !== null onClicked: { setPowerFuture = py.callClientCoro( @@ -230,7 +238,7 @@ HListView { Component.onDestruction: if (setPowerFuture) setPowerFuture.cancel() Keys.onEnterPressed: Keys.onReturnPressed(event) - Keys.onReturnPressed: if (! powerLevelFieldFocused && currentItem) { + Keys.onReturnPressed: if (! root.powerLevelFieldFocused && currentItem) { currentItem.leftClicked() currentItem.clicked() } diff --git a/src/gui/Pages/Chat/RoomPane/MemberView/MemberView.qml b/src/gui/Pages/Chat/RoomPane/MemberView/MemberView.qml index 1f4311b4..1ca1ed46 100644 --- a/src/gui/Pages/Chat/RoomPane/MemberView/MemberView.qml +++ b/src/gui/Pages/Chat/RoomPane/MemberView/MemberView.qml @@ -33,6 +33,11 @@ HColumnLayout { { userId: chat.userId, roomId: chat.roomId, + ownPowerLevel: + Qt.binding(() => chat.roomInfo.own_power_level), + canSetPowerLevels: Qt.binding(() => + chat.roomInfo.can_set_power_levels + ), member: model, stackView: stackView, },