Add kick to room member context menu

This commit is contained in:
miruka 2020-04-19 11:12:35 -04:00
parent bdb9a650d9
commit 2a0a3765fc
9 changed files with 71 additions and 8 deletions

View File

@ -1182,6 +1182,7 @@ class MatrixClient(nio.AsyncClient):
guests_allowed = room.guest_access == "can_join", guests_allowed = room.guest_access == "can_join",
can_invite = levels.can_user_invite(self.user), can_invite = levels.can_user_invite(self.user),
can_kick = levels.can_user_kick(self.user),
can_redact_all = levels.can_user_redact(self.user), can_redact_all = levels.can_user_redact(self.user),
can_send_messages = can_send_msg(), can_send_messages = can_send_msg(),
can_set_name = can_send_state("m.room.name"), can_set_name = can_send_state("m.room.name"),

View File

@ -70,6 +70,7 @@ class Room(ModelItem):
guests_allowed: bool = True guests_allowed: bool = True
can_invite: bool = False can_invite: bool = False
can_kick: bool = False
can_redact_all: bool = False can_redact_all: bool = False
can_send_messages: bool = False can_send_messages: bool = False
can_set_name: bool = False can_set_name: bool = False

View File

@ -272,7 +272,7 @@ class NioCallbacks:
self.client.skipped_events[room.room_id] += 1 self.client.skipped_events[room.room_id] += 1
return None return None
reason = f". Reason: {now['reason']}" if now.get("reason") else "" reason = f", reason: {now['reason']}" if now.get("reason") else ""
if membership == "join": if membership == "join":
return ( return (
@ -303,7 +303,7 @@ class NioCallbacks:
f"%1 unbanned %2 from the room{reason}" f"%1 unbanned %2 from the room{reason}"
if prev and prev_membership == "ban" else if prev and prev_membership == "ban" else
f"%1 kicked out %2 from the room{reason}", f"%1 kicked %2 out from the room{reason}",
) )
if membership == "ban": if membership == "ban":

View File

@ -10,7 +10,7 @@ Banner {
avatar.userId: chat.userId avatar.userId: chat.userId
avatar.displayName: chat.userInfo.display_name avatar.displayName: chat.userInfo.display_name
avatar.mxc: chat.userInfo.avatar_url avatar.mxc: chat.userInfo.avatar_url
labelText: qsTr("You are not part of this room anymore") labelText: qsTr("You are no longer part of this room")
buttonModel: [ buttonModel: [
{ {

View File

@ -52,6 +52,23 @@ HTileDelegate {
text: qsTr("Copy user ID") text: qsTr("Copy user ID")
onTriggered: Clipboard.text = model.id onTriggered: Clipboard.text = model.id
} }
HMenuItemPopupSpawner {
icon.name: "room-kick"
icon.color: theme.colors.negativeBackground
text: model.invited ? qsTr("Disinvite") : qsTr("Kick")
enabled: chat.roomInfo.can_kick
popup: "Popups/KickPopup.qml"
popupParent: chat
properties: ({
userId: chat.userId,
roomId: chat.roomId,
targetUserId: model.id,
targetDisplayName: model.display_name,
targetIsInvited: model.invited,
})
}
} }

View File

@ -0,0 +1,40 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
import QtQuick 2.12
import QtQuick.Layouts 1.12
import "../Base"
BoxPopup {
summary.textFormat: Text.StyledText
summary.text:
targetIsInvited ?
qsTr("Withdraw %1's invitation?").arg(coloredTarget) :
qsTr("Kick %1 out of the room?").arg(coloredTarget)
okText: qsTr("Kick")
onOpened: reasonField.field.forceActiveFocus()
onOk: py.callClientCoro(
userId,
"room_kick",
[roomId, targetUserId, reasonField.field.text || null],
)
property string userId
property string roomId
property string targetUserId
property string targetDisplayName
property bool targetIsInvited: false
readonly property string coloredTarget:
utils.coloredNameHtml(targetDisplayName, targetUserId)
HLabeledTextField {
id: reasonField
label.text: qsTr("Optional reason:")
Layout.fillWidth: true
}
}

View File

@ -160,9 +160,7 @@ QtObject {
} }
function coloredNameHtml( function coloredNameHtml(name, userId, displayText=null, dim=false) {
name, userId, displayText=null, disambiguate=false, dim=false,
) {
// substring: remove leading @ // substring: remove leading @
return `<font color="${nameColor(name || userId.substring(1), dim)}">`+ return `<font color="${nameColor(name || userId.substring(1), dim)}">`+
escapeHtml(displayText || name || userId) + escapeHtml(displayText || name || userId) +
@ -210,7 +208,7 @@ QtObject {
if (ev.content.includes("%2")) if (ev.content.includes("%2"))
content = content.arg(coloredNameHtml( content = content.arg(coloredNameHtml(
ev.redacter_name, ev.redacter_id, "", false, true, ev.redacter_name, ev.redacter_id, "", true,
)) ))
return qsTr( return qsTr(

View File

@ -1 +1,3 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"><path d="M5.662 23l-5.369-5.365c-.195-.195-.293-.45-.293-.707 0-.256.098-.512.293-.707l14.929-14.928c.195-.194.451-.293.707-.293.255 0 .512.099.707.293l7.071 7.073c.196.195.293.451.293.708 0 .256-.097.511-.293.707l-11.216 11.219h5.514v2h-12.343zm3.657-2l-5.486-5.486-1.419 1.414 4.076 4.072h2.829zm6.605-17.581l-10.677 10.68 5.658 5.659 10.676-10.682-5.657-5.657z"/></svg> <svg clip-rule="evenodd" fill-rule="evenodd" height="24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="m5.662 23-5.369-5.365c-.195-.195-.293-.45-.293-.707 0-.256.098-.512.293-.707l14.929-14.928c.195-.194.451-.293.707-.293.255 0 .512.099.707.293l7.071 7.073c.196.195.293.451.293.708 0 .256-.097.511-.293.707l-11.216 11.219h5.514v2zm3.657-2-5.486-5.486-1.419 1.414 4.076 4.072zm6.605-17.581-10.677 10.68 5.658 5.659 10.676-10.682z"/>
</svg>

Before

Width:  |  Height:  |  Size: 475 B

After

Width:  |  Height:  |  Size: 453 B

View File

@ -0,0 +1,4 @@
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="m0 2v20h14v-2h-12v-16h12v-2z"/>
<path d="m16 10.766911v-4.8320919l8 6.0651809-8 6.065181v-4.832092h-8v-2.466178z"/>
</svg>

After

Width:  |  Height:  |  Size: 224 B