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 }