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({ 0072 "text": i18n("Member (0)"), 0073 "powerLevel": 0 0074 }); 0075 powerLevelModel.append({ 0076 "text": i18n("Moderator (50)"), 0077 "powerLevel": 50 0078 }); 0079 powerLevelModel.append({ 0080 "text": i18n("Admin (100)"), 0081 "powerLevel": 100 0082 }); 0083 } 0084 currentIndex = indexOfValue(powerLevel); 0085 } 0086 onActivated: { 0087 room.setUserPowerLevel(userId, currentValue); 0088 } 0089 } 0090 } 0091 } 0092 } 0093 FormCard.FormDelegateSeparator { 0094 below: userListSearchCard 0095 } 0096 FormCard.AbstractFormDelegate { 0097 id: userListSearchCard 0098 visible: room.canSendState("m.room.power_levels") 0099 0100 contentItem: Kirigami.SearchField { 0101 id: userListSearchField 0102 0103 autoAccept: false 0104 0105 Layout.fillWidth: true 0106 0107 Keys.onUpPressed: userListView.decrementCurrentIndex() 0108 Keys.onDownPressed: userListView.incrementCurrentIndex() 0109 0110 onAccepted: { 0111 let currentUser = userListView.itemAtIndex(userListView.currentIndex); 0112 currentUser.action.trigger(); 0113 } 0114 } 0115 QQC2.Popup { 0116 id: userListSearchPopup 0117 0118 x: userListSearchField.x 0119 y: userListSearchField.y - height 0120 width: userListSearchField.width 0121 height: { 0122 let maxHeight = userListSearchField.mapToGlobal(userListSearchField.x, userListSearchField.y).y - Kirigami.Units.largeSpacing * 3; 0123 let minHeight = Kirigami.Units.gridUnit * 2 + userListSearchPopup.padding * 2; 0124 let filterContentHeight = userListView.contentHeight + userListSearchPopup.padding * 2; 0125 return Math.max(Math.min(filterContentHeight, maxHeight), minHeight); 0126 } 0127 padding: Kirigami.Units.smallSpacing 0128 leftPadding: Kirigami.Units.smallSpacing / 2 0129 rightPadding: Kirigami.Units.smallSpacing / 2 0130 modal: false 0131 onClosed: userListSearchField.text = "" 0132 0133 background: Kirigami.ShadowedRectangle { 0134 property color borderColor: Kirigami.Theme.textColor 0135 0136 Kirigami.Theme.colorSet: Kirigami.Theme.View 0137 Kirigami.Theme.inherit: false 0138 0139 radius: 4 0140 color: Kirigami.Theme.backgroundColor 0141 0142 border { 0143 color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) 0144 width: 1 0145 } 0146 0147 shadow { 0148 xOffset: 0 0149 yOffset: 4 0150 color: Qt.rgba(0, 0, 0, 0.3) 0151 size: 8 0152 } 0153 } 0154 0155 contentItem: QQC2.ScrollView { 0156 // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) 0157 QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff 0158 0159 ListView { 0160 id: userListView 0161 clip: true 0162 0163 model: UserFilterModel { 0164 id: userListFilterModel 0165 sourceModel: userListModel 0166 filterText: userListSearchField.text 0167 0168 onFilterTextChanged: { 0169 if (filterText.length > 0 && !userListSearchPopup.visible) { 0170 userListSearchPopup.open(); 0171 } else if (filterText.length <= 0 && userListSearchPopup.visible) { 0172 userListSearchPopup.close(); 0173 } 0174 } 0175 } 0176 0177 delegate: Delegates.RoundedItemDelegate { 0178 id: userListItem 0179 0180 required property string userId 0181 required property string avatar 0182 required property string name 0183 required property int powerLevel 0184 required property string powerLevelString 0185 0186 text: name 0187 0188 contentItem: RowLayout { 0189 KirigamiComponents.Avatar { 0190 Layout.preferredWidth: Kirigami.Units.iconSizes.medium 0191 Layout.preferredHeight: Kirigami.Units.iconSizes.medium 0192 source: userListItem.avatar ? ("image://" + userListItem.avatar) : "" 0193 name: userListItem.name 0194 } 0195 0196 Delegates.SubtitleContentItem { 0197 itemDelegate: userListItem 0198 subtitle: userListItem.userId 0199 labelItem.textFormat: Text.PlainText 0200 subtitleItem.textFormat: Text.PlainText 0201 Layout.fillWidth: true 0202 } 0203 0204 QQC2.Label { 0205 visible: userListItem.powerLevel > 0 0206 0207 text: userListItem.powerLevelString 0208 color: Kirigami.Theme.disabledTextColor 0209 textFormat: Text.PlainText 0210 wrapMode: Text.NoWrap 0211 } 0212 } 0213 0214 action: Kirigami.Action { 0215 id: editPowerLevelAction 0216 onTriggered: { 0217 userListSearchPopup.close(); 0218 let dialog = powerLevelDialog.createObject(applicationWindow().overlay, { 0219 room: root.room, 0220 userId: userListItem.userId, 0221 powerLevel: userListItem.powerLevel 0222 }); 0223 dialog.open(); 0224 } 0225 } 0226 0227 Component { 0228 id: powerLevelDialog 0229 PowerLevelDialog { 0230 id: powerLevelDialog 0231 } 0232 } 0233 } 0234 } 0235 } 0236 } 0237 } 0238 } 0239 0240 FormCard.FormHeader { 0241 visible: room.canSendState("m.room.power_levels") 0242 title: i18n("Default permissions") 0243 } 0244 FormCard.FormCard { 0245 visible: room.canSendState("m.room.power_levels") 0246 FormCard.FormComboBoxDelegate { 0247 text: i18n("Default user power level") 0248 description: i18n("This is power level for all new users when joining the room") 0249 textRole: "text" 0250 valueRole: "powerLevel" 0251 model: powerLevelModel 0252 Component.onCompleted: currentIndex = indexOfValue(room.defaultUserPowerLevel) 0253 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0254 room.defaultUserPowerLevel = currentValue; 0255 } 0256 } 0257 FormCard.FormComboBoxDelegate { 0258 text: i18n("Default power level to set the room state") 0259 description: i18n("This is used for all state events that do not have their own entry here") 0260 textRole: "text" 0261 valueRole: "powerLevel" 0262 model: powerLevelModel 0263 Component.onCompleted: currentIndex = indexOfValue(room.statePowerLevel) 0264 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0265 room.statePowerLevel = currentValue; 0266 } 0267 } 0268 FormCard.FormComboBoxDelegate { 0269 text: i18n("Default power level to send messages") 0270 description: i18n("This is used for all message events that do not have their own entry here") 0271 textRole: "text" 0272 valueRole: "powerLevel" 0273 model: powerLevelModel 0274 Component.onCompleted: currentIndex = indexOfValue(room.defaultEventPowerLevel) 0275 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0276 room.defaultEventPowerLevel = currentValue; 0277 } 0278 } 0279 } 0280 0281 FormCard.FormHeader { 0282 visible: room.canSendState("m.room.power_levels") 0283 title: i18n("Basic permissions") 0284 } 0285 FormCard.FormCard { 0286 visible: room.canSendState("m.room.power_levels") 0287 FormCard.FormComboBoxDelegate { 0288 text: i18n("Invite users") 0289 textRole: "text" 0290 valueRole: "powerLevel" 0291 model: powerLevelModel 0292 Component.onCompleted: currentIndex = indexOfValue(room.invitePowerLevel) 0293 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0294 room.invitePowerLevel = currentValue; 0295 } 0296 } 0297 FormCard.FormComboBoxDelegate { 0298 text: i18n("Kick users") 0299 textRole: "text" 0300 valueRole: "powerLevel" 0301 model: powerLevelModel 0302 Component.onCompleted: currentIndex = indexOfValue(room.kickPowerLevel) 0303 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0304 room.kickPowerLevel = currentValue; 0305 } 0306 } 0307 FormCard.FormComboBoxDelegate { 0308 text: i18n("Ban users") 0309 textRole: "text" 0310 valueRole: "powerLevel" 0311 model: powerLevelModel 0312 Component.onCompleted: currentIndex = indexOfValue(room.banPowerLevel) 0313 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0314 room.banPowerLevel = currentValue; 0315 } 0316 } 0317 FormCard.FormComboBoxDelegate { 0318 text: i18n("Remove message sent by other users") 0319 textRole: "text" 0320 valueRole: "powerLevel" 0321 model: powerLevelModel 0322 Component.onCompleted: currentIndex = indexOfValue(room.redactPowerLevel) 0323 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0324 room.redactPowerLevel = currentValue; 0325 } 0326 } 0327 } 0328 0329 FormCard.FormHeader { 0330 visible: room.canSendState("m.room.power_levels") 0331 title: i18n("Event permissions") 0332 } 0333 FormCard.FormCard { 0334 visible: room.canSendState("m.room.power_levels") 0335 FormCard.FormComboBoxDelegate { 0336 text: i18n("Change user permissions") 0337 description: "m.room.power_levels" 0338 textRole: "text" 0339 valueRole: "powerLevel" 0340 model: powerLevelModel 0341 Component.onCompleted: currentIndex = indexOfValue(room.powerLevelPowerLevel) 0342 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0343 room.powerLevelPowerLevel = currentValue; 0344 } 0345 } 0346 FormCard.FormComboBoxDelegate { 0347 text: i18n("Change the room name") 0348 description: "m.room.name" 0349 textRole: "text" 0350 valueRole: "powerLevel" 0351 model: powerLevelModel 0352 Component.onCompleted: currentIndex = indexOfValue(room.namePowerLevel) 0353 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0354 room.namePowerLevel = currentValue; 0355 } 0356 } 0357 FormCard.FormComboBoxDelegate { 0358 text: i18n("Change the room avatar") 0359 description: "m.room.avatar" 0360 textRole: "text" 0361 valueRole: "powerLevel" 0362 model: powerLevelModel 0363 Component.onCompleted: currentIndex = indexOfValue(room.avatarPowerLevel) 0364 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0365 room.avatarPowerLevel = currentValue; 0366 } 0367 } 0368 FormCard.FormComboBoxDelegate { 0369 text: i18n("Change the room canonical alias") 0370 description: "m.room.canonical_alias" 0371 textRole: "text" 0372 valueRole: "powerLevel" 0373 model: powerLevelModel 0374 Component.onCompleted: currentIndex = indexOfValue(room.canonicalAliasPowerLevel) 0375 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0376 room.canonicalAliasPowerLevel = currentValue; 0377 } 0378 } 0379 FormCard.FormComboBoxDelegate { 0380 text: i18n("Change the room topic") 0381 description: "m.room.topic" 0382 textRole: "text" 0383 valueRole: "powerLevel" 0384 model: powerLevelModel 0385 Component.onCompleted: currentIndex = indexOfValue(room.topicPowerLevel) 0386 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0387 room.topicPowerLevel = currentValue; 0388 } 0389 } 0390 FormCard.FormComboBoxDelegate { 0391 text: i18n("Enable encryption for the room") 0392 description: "m.room.encryption" 0393 textRole: "text" 0394 valueRole: "powerLevel" 0395 model: powerLevelModel 0396 Component.onCompleted: currentIndex = indexOfValue(room.encryptionPowerLevel) 0397 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0398 room.encryptionPowerLevel = currentValue; 0399 } 0400 } 0401 FormCard.FormComboBoxDelegate { 0402 text: i18n("Change the room history visibility") 0403 description: "m.room.history_visibility" 0404 textRole: "text" 0405 valueRole: "powerLevel" 0406 model: powerLevelModel 0407 Component.onCompleted: currentIndex = indexOfValue(room.historyVisibilityPowerLevel) 0408 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0409 room.historyVisibilityPowerLevel = currentValue; 0410 } 0411 } 0412 FormCard.FormComboBoxDelegate { 0413 text: i18n("Set pinned events") 0414 description: "m.room.pinned_events" 0415 textRole: "text" 0416 valueRole: "powerLevel" 0417 model: powerLevelModel 0418 Component.onCompleted: currentIndex = indexOfValue(room.pinnedEventsPowerLevel) 0419 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0420 room.pinnedEventsPowerLevel = currentValue; 0421 } 0422 } 0423 FormCard.FormComboBoxDelegate { 0424 text: i18n("Upgrade the room") 0425 description: "m.room.tombstone" 0426 textRole: "text" 0427 valueRole: "powerLevel" 0428 model: powerLevelModel 0429 Component.onCompleted: currentIndex = indexOfValue(room.tombstonePowerLevel) 0430 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0431 room.tombstonePowerLevel = currentValue; 0432 } 0433 } 0434 FormCard.FormComboBoxDelegate { 0435 text: i18n("Set the room server access control list (ACL)") 0436 description: "m.room.server_acl" 0437 textRole: "text" 0438 valueRole: "powerLevel" 0439 model: powerLevelModel 0440 Component.onCompleted: currentIndex = indexOfValue(room.serverAclPowerLevel) 0441 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0442 room.serverAclPowerLevel = currentValue; 0443 } 0444 } 0445 FormCard.FormComboBoxDelegate { 0446 visible: room.isSpace 0447 text: i18n("Set the children of this space") 0448 description: "m.space.child" 0449 textRole: "text" 0450 valueRole: "powerLevel" 0451 model: powerLevelModel 0452 Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel) 0453 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0454 room.spaceChildPowerLevel = currentValue; 0455 } 0456 } 0457 FormCard.FormComboBoxDelegate { 0458 text: i18n("Set the parent space of this room") 0459 description: "m.space.parent" 0460 textRole: "text" 0461 valueRole: "powerLevel" 0462 model: powerLevelModel 0463 Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel) 0464 onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { 0465 room.spaceParentPowerLevel = currentValue; 0466 } 0467 } 0468 } 0469 }