Warning, /network/neochat/src/qml/Permissions.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003
0004 import QtQuick
0005 import QtQuick.Controls as QQC2
0006 import QtQuick.Layouts
0007
0008 import org.kde.kirigami as Kirigami
0009 import org.kde.kirigamiaddons.formcard as FormCard
0010 import org.kde.kirigamiaddons.delegates as Delegates
0011 import org.kde.kirigamiaddons.labs.components as KirigamiComponents
0012 import org.kde.kitemmodels
0013
0014 import org.kde.neochat
0015
0016 FormCard.FormCardPage {
0017 id: root
0018
0019 property NeoChatRoom room
0020
0021 title: i18nc('@title:window', 'Permissions')
0022
0023 property UserListModel userListModel: UserListModel {
0024 id: userListModel
0025 room: root.room
0026 }
0027
0028 property ListModel powerLevelModel: ListModel {
0029 id: powerLevelModel
0030 }
0031
0032 FormCard.FormHeader {
0033 title: i18n("Privileged Users")
0034 }
0035 FormCard.FormCard {
0036 Repeater {
0037 model: KSortFilterProxyModel {
0038 sourceModel: userListModel
0039 sortRoleName: "powerLevel"
0040 sortOrder: Qt.DescendingOrder
0041 filterRowCallback: function(source_row, source_parent) {
0042 let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole)
0043 return powerLevelRole > 0;
0044 }
0045 }
0046 delegate: FormCard.FormTextDelegate {
0047 text: name
0048 textItem.textFormat: Text.PlainText
0049 description: userId
0050 contentItem.children: RowLayout {
0051 spacing: Kirigami.Units.largeSpacing
0052 QQC2.Label {
0053 id: powerLevelLabel
0054 visible: !room.canSendState("m.room.power_levels") || (room.getUserPowerLevel(room.localUser.id) <= model.powerLevel && model.userId != room.localUser.id)
0055 text: powerLevelString
0056 color: Kirigami.Theme.disabledTextColor
0057 }
0058 QQC2.ComboBox {
0059 focusPolicy: Qt.NoFocus // provided by parent
0060 model: powerLevelModel
0061 textRole: "text"
0062 valueRole: "powerLevel"
0063 visible: !powerLevelLabel.visible
0064 Component.onCompleted: {
0065 /**
0066 * This is very silly but the only way to populate the model with
0067 * translated strings. Done here because the model needs to be filled
0068 * before the first delegate sets it's current index.
0069 */
0070 if (powerLevelModel.count == 0) {
0071 powerLevelModel.append({"text": i18n("Member (0)"), "powerLevel": 0});
0072 powerLevelModel.append({"text": i18n("Moderator (50)"), "powerLevel": 50});
0073 powerLevelModel.append({"text": i18n("Admin (100)"), "powerLevel": 100});
0074 }
0075 currentIndex = indexOfValue(powerLevel)
0076 }
0077 onActivated: {
0078 room.setUserPowerLevel(userId, currentValue)
0079 }
0080 }
0081 }
0082 }
0083 }
0084 FormCard.FormDelegateSeparator { below: userListSearchCard }
0085 FormCard.AbstractFormDelegate {
0086 id: userListSearchCard
0087 visible: room.canSendState("m.room.power_levels")
0088
0089 contentItem: Kirigami.SearchField {
0090 id: userListSearchField
0091
0092 autoAccept: false
0093
0094 Layout.fillWidth: true
0095
0096 Keys.onUpPressed: userListView.decrementCurrentIndex()
0097 Keys.onDownPressed: userListView.incrementCurrentIndex()
0098
0099 onAccepted: {
0100 let currentUser = userListView.itemAtIndex(userListView.currentIndex);
0101 currentUser.action.trigger();
0102 }
0103 }
0104 QQC2.Popup {
0105 id: userListSearchPopup
0106
0107 x: userListSearchField.x
0108 y: userListSearchField.y - height
0109 width: userListSearchField.width
0110 height: {
0111 let maxHeight = userListSearchField.mapToGlobal(userListSearchField.x, userListSearchField.y).y - Kirigami.Units.largeSpacing * 3;
0112 let minHeight = Kirigami.Units.gridUnit * 2 + userListSearchPopup.padding * 2;
0113 let filterContentHeight = userListView.contentHeight + userListSearchPopup.padding * 2;
0114
0115 return Math.max(Math.min(filterContentHeight, maxHeight), minHeight);
0116 }
0117 padding: Kirigami.Units.smallSpacing
0118 leftPadding: Kirigami.Units.smallSpacing / 2
0119 rightPadding: Kirigami.Units.smallSpacing / 2
0120 modal: false
0121 onClosed: userListSearchField.text = ""
0122
0123 background: Kirigami.ShadowedRectangle {
0124 property color borderColor: Kirigami.Theme.textColor
0125
0126 Kirigami.Theme.colorSet: Kirigami.Theme.View
0127 Kirigami.Theme.inherit: false
0128
0129 radius: 4
0130 color: Kirigami.Theme.backgroundColor
0131
0132 border {
0133 color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3)
0134 width: 1
0135 }
0136
0137 shadow {
0138 xOffset: 0
0139 yOffset: 4
0140 color: Qt.rgba(0, 0, 0, 0.3)
0141 size: 8
0142 }
0143 }
0144
0145 contentItem: QQC2.ScrollView {
0146 // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890)
0147 QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
0148
0149 ListView {
0150 id: userListView
0151 clip: true
0152
0153 model: UserFilterModel {
0154 id: userListFilterModel
0155 sourceModel: userListModel
0156 filterText: userListSearchField.text
0157
0158 onFilterTextChanged: {
0159 if (filterText.length > 0 && !userListSearchPopup.visible) {
0160 userListSearchPopup.open()
0161 } else if (filterText.length <= 0 && userListSearchPopup.visible) {
0162 userListSearchPopup.close()
0163 }
0164 }
0165 }
0166
0167 delegate: Delegates.RoundedItemDelegate {
0168 id: userListItem
0169
0170 required property string userId
0171 required property string avatar
0172 required property string name
0173 required property int powerLevel
0174 required property string powerLevelString
0175
0176 text: name
0177
0178 contentItem: RowLayout {
0179 KirigamiComponents.Avatar {
0180 Layout.preferredWidth: Kirigami.Units.iconSizes.medium
0181 Layout.preferredHeight: Kirigami.Units.iconSizes.medium
0182 source: userListItem.avatar ? ("image://" + userListItem.avatar) : ""
0183 name: userListItem.name
0184 }
0185
0186 Delegates.SubtitleContentItem {
0187 itemDelegate: userListItem
0188 subtitle: userListItem.userId
0189 labelItem.textFormat: Text.PlainText
0190 subtitleItem.textFormat: Text.PlainText
0191 Layout.fillWidth: true
0192 }
0193
0194 QQC2.Label {
0195 visible: userListItem.powerLevel > 0
0196
0197 text: userListItem.powerLevelString
0198 color: Kirigami.Theme.disabledTextColor
0199 textFormat: Text.PlainText
0200 wrapMode: Text.NoWrap
0201 }
0202 }
0203
0204 action: Kirigami.Action {
0205 id: editPowerLevelAction
0206 onTriggered: {
0207 userListSearchPopup.close()
0208 let dialog = powerLevelDialog.createObject(applicationWindow().overlay, {
0209 room: root.room,
0210 userId: userListItem.userId,
0211 powerLevel: userListItem.powerLevel
0212 });
0213 dialog.open();
0214 }
0215 }
0216
0217 Component {
0218 id: powerLevelDialog
0219 PowerLevelDialog {
0220 id: powerLevelDialog
0221 }
0222 }
0223 }
0224 }
0225 }
0226 }
0227 }
0228 }
0229
0230 FormCard.FormHeader {
0231 visible: room.canSendState("m.room.power_levels")
0232 title: i18n("Default permissions")
0233 }
0234 FormCard.FormCard {
0235 visible: room.canSendState("m.room.power_levels")
0236 FormCard.FormComboBoxDelegate {
0237 text: i18n("Default user power level")
0238 description: i18n("This is power level for all new users when joining the room")
0239 textRole: "text"
0240 valueRole: "powerLevel"
0241 model: powerLevelModel
0242 Component.onCompleted: currentIndex = indexOfValue(room.defaultUserPowerLevel)
0243 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultUserPowerLevel = currentValue
0244 }
0245 FormCard.FormComboBoxDelegate {
0246 text: i18n("Default power level to set the room state")
0247 description: i18n("This is used for all state events that do not have their own entry here")
0248 textRole: "text"
0249 valueRole: "powerLevel"
0250 model: powerLevelModel
0251 Component.onCompleted: currentIndex = indexOfValue(room.statePowerLevel)
0252 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.statePowerLevel = currentValue
0253 }
0254 FormCard.FormComboBoxDelegate {
0255 text: i18n("Default power level to send messages")
0256 description: i18n("This is used for all message events that do not have their own entry here")
0257 textRole: "text"
0258 valueRole: "powerLevel"
0259 model: powerLevelModel
0260 Component.onCompleted: currentIndex = indexOfValue(room.defaultEventPowerLevel)
0261 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultEventPowerLevel = currentValue
0262 }
0263 }
0264
0265 FormCard.FormHeader {
0266 visible: room.canSendState("m.room.power_levels")
0267 title: i18n("Basic permissions")
0268 }
0269 FormCard.FormCard {
0270 visible: room.canSendState("m.room.power_levels")
0271 FormCard.FormComboBoxDelegate {
0272 text: i18n("Invite users")
0273 textRole: "text"
0274 valueRole: "powerLevel"
0275 model: powerLevelModel
0276 Component.onCompleted: currentIndex = indexOfValue(room.invitePowerLevel)
0277 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.invitePowerLevel = currentValue
0278 }
0279 FormCard.FormComboBoxDelegate {
0280 text: i18n("Kick users")
0281 textRole: "text"
0282 valueRole: "powerLevel"
0283 model: powerLevelModel
0284 Component.onCompleted: currentIndex = indexOfValue(room.kickPowerLevel)
0285 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.kickPowerLevel = currentValue
0286 }
0287 FormCard.FormComboBoxDelegate {
0288 text: i18n("Ban users")
0289 textRole: "text"
0290 valueRole: "powerLevel"
0291 model: powerLevelModel
0292 Component.onCompleted: currentIndex = indexOfValue(room.banPowerLevel)
0293 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.banPowerLevel = currentValue
0294 }
0295 FormCard.FormComboBoxDelegate {
0296 text: i18n("Remove message sent by other users")
0297 textRole: "text"
0298 valueRole: "powerLevel"
0299 model: powerLevelModel
0300 Component.onCompleted: currentIndex = indexOfValue(room.redactPowerLevel)
0301 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.redactPowerLevel = currentValue
0302 }
0303 }
0304
0305 FormCard.FormHeader {
0306 visible: room.canSendState("m.room.power_levels")
0307 title: i18n("Event permissions")
0308 }
0309 FormCard.FormCard {
0310 visible: room.canSendState("m.room.power_levels")
0311 FormCard.FormComboBoxDelegate {
0312 text: i18n("Change user permissions")
0313 description: "m.room.power_levels"
0314 textRole: "text"
0315 valueRole: "powerLevel"
0316 model: powerLevelModel
0317 Component.onCompleted: currentIndex = indexOfValue(room.powerLevelPowerLevel)
0318 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.powerLevelPowerLevel = currentValue
0319 }
0320 FormCard.FormComboBoxDelegate {
0321 text: i18n("Change the room name")
0322 description: "m.room.name"
0323 textRole: "text"
0324 valueRole: "powerLevel"
0325 model: powerLevelModel
0326 Component.onCompleted: currentIndex = indexOfValue(room.namePowerLevel)
0327 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.namePowerLevel = currentValue
0328 }
0329 FormCard.FormComboBoxDelegate {
0330 text: i18n("Change the room avatar")
0331 description: "m.room.avatar"
0332 textRole: "text"
0333 valueRole: "powerLevel"
0334 model: powerLevelModel
0335 Component.onCompleted: currentIndex = indexOfValue(room.avatarPowerLevel)
0336 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.avatarPowerLevel = currentValue
0337 }
0338 FormCard.FormComboBoxDelegate {
0339 text: i18n("Change the room canonical alias")
0340 description: "m.room.canonical_alias"
0341 textRole: "text"
0342 valueRole: "powerLevel"
0343 model: powerLevelModel
0344 Component.onCompleted: currentIndex = indexOfValue(room.canonicalAliasPowerLevel)
0345 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.canonicalAliasPowerLevel = currentValue
0346 }
0347 FormCard.FormComboBoxDelegate {
0348 text: i18n("Change the room topic")
0349 description: "m.room.topic"
0350 textRole: "text"
0351 valueRole: "powerLevel"
0352 model: powerLevelModel
0353 Component.onCompleted: currentIndex = indexOfValue(room.topicPowerLevel)
0354 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.topicPowerLevel = currentValue
0355 }
0356 FormCard.FormComboBoxDelegate {
0357 text: i18n("Enable encryption for the room")
0358 description: "m.room.encryption"
0359 textRole: "text"
0360 valueRole: "powerLevel"
0361 model: powerLevelModel
0362 Component.onCompleted: currentIndex = indexOfValue(room.encryptionPowerLevel)
0363 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.encryptionPowerLevel = currentValue
0364 }
0365 FormCard.FormComboBoxDelegate {
0366 text: i18n("Change the room history visibility")
0367 description: "m.room.history_visibility"
0368 textRole: "text"
0369 valueRole: "powerLevel"
0370 model: powerLevelModel
0371 Component.onCompleted: currentIndex = indexOfValue(room.historyVisibilityPowerLevel)
0372 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.historyVisibilityPowerLevel = currentValue
0373 }
0374 FormCard.FormComboBoxDelegate {
0375 text: i18n("Set pinned events")
0376 description: "m.room.pinned_events"
0377 textRole: "text"
0378 valueRole: "powerLevel"
0379 model: powerLevelModel
0380 Component.onCompleted: currentIndex = indexOfValue(room.pinnedEventsPowerLevel)
0381 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.pinnedEventsPowerLevel = currentValue
0382 }
0383 FormCard.FormComboBoxDelegate {
0384 text: i18n("Upgrade the room")
0385 description: "m.room.tombstone"
0386 textRole: "text"
0387 valueRole: "powerLevel"
0388 model: powerLevelModel
0389 Component.onCompleted: currentIndex = indexOfValue(room.tombstonePowerLevel)
0390 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.tombstonePowerLevel = currentValue
0391 }
0392 FormCard.FormComboBoxDelegate {
0393 text: i18n("Set the room server access control list (ACL)")
0394 description: "m.room.server_acl"
0395 textRole: "text"
0396 valueRole: "powerLevel"
0397 model: powerLevelModel
0398 Component.onCompleted: currentIndex = indexOfValue(room.serverAclPowerLevel)
0399 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.serverAclPowerLevel = currentValue
0400 }
0401 FormCard.FormComboBoxDelegate {
0402 visible: room.isSpace
0403 text: i18n("Set the children of this space")
0404 description: "m.space.child"
0405 textRole: "text"
0406 valueRole: "powerLevel"
0407 model: powerLevelModel
0408 Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel)
0409 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceChildPowerLevel = currentValue
0410 }
0411 FormCard.FormComboBoxDelegate {
0412 text: i18n("Set the parent space of this room")
0413 description: "m.space.parent"
0414 textRole: "text"
0415 valueRole: "powerLevel"
0416 model: powerLevelModel
0417 Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel)
0418 onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceParentPowerLevel = currentValue
0419 }
0420 }
0421 }