diff --git a/ui/app/AppLayouts/Chat/controls/community/EnsPanel.qml b/ui/app/AppLayouts/Chat/controls/community/EnsPanel.qml
index 6e61d0157d..039bb0f0b0 100644
--- a/ui/app/AppLayouts/Chat/controls/community/EnsPanel.qml
+++ b/ui/app/AppLayouts/Chat/controls/community/EnsPanel.qml
@@ -53,6 +53,7 @@ ColumnLayout {
// intercepting event by the StatusRadioButton
MouseArea {
anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
onClicked: root.ensType = EnsPanel.EnsType.Any
}
}
@@ -76,6 +77,7 @@ ColumnLayout {
MouseArea {
anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
onClicked: root.ensType = EnsPanel.EnsType.CustomSubdomain
}
}
diff --git a/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml b/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml
index 680e026a07..53d06a9d2f 100644
--- a/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml
+++ b/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml
@@ -53,6 +53,9 @@ StatusDropdown {
width: d.defaultWidth
padding: d.padding
+ // force keeping within the bounds of the enclosing window
+ margins: 0
+
onClosed: root.reset()
enum FlowType {
diff --git a/ui/app/AppLayouts/Chat/controls/community/PermissionListItem.qml b/ui/app/AppLayouts/Chat/controls/community/PermissionListItem.qml
new file mode 100644
index 0000000000..523bc3e29a
--- /dev/null
+++ b/ui/app/AppLayouts/Chat/controls/community/PermissionListItem.qml
@@ -0,0 +1,50 @@
+import StatusQ.Core 0.1
+import StatusQ.Components 0.1
+import StatusQ.Controls 0.1
+
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+
+StatusListItem {
+ id: root
+
+ property ButtonGroup buttonGroup
+ property alias checked: radioButton.checked
+ readonly property alias radioButton: radioButton
+
+ implicitHeight: 44
+ leftPadding: 8
+ rightPadding: 9
+ statusListItemTitle.font.pixelSize: 13
+
+ statusListItemTitleArea.anchors.leftMargin: 8
+
+ asset.bgWidth: 32
+ asset.bgHeight: 32
+
+ components: [
+ StatusRadioButton {
+ id: radioButton
+
+ // reference to root for better integration with ButtonGroup
+ // by accessing main component via ButtonGroup::checkedButton.item
+ readonly property alias item: root
+
+ size: StatusRadioButton.Size.Small
+ ButtonGroup.group: root.buttonGroup
+
+ rightPadding: 0
+ }
+ ]
+
+ // using MouseArea instead of build-in 'clicked' signal to avoid
+ // intercepting event by the StatusRadioButton
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!radioButton.checked)
+ radioButton.toggle()
+ }
+ cursorShape: Qt.PointingHandCursor
+ }
+}
diff --git a/ui/app/AppLayouts/Chat/controls/community/PermissionTypes.qml b/ui/app/AppLayouts/Chat/controls/community/PermissionTypes.qml
new file mode 100644
index 0000000000..eb9b929392
--- /dev/null
+++ b/ui/app/AppLayouts/Chat/controls/community/PermissionTypes.qml
@@ -0,0 +1,7 @@
+import QtQml 2.14
+
+QtObject {
+ enum Type {
+ None, Admin, Member, Moderator, ViewAndPost, Read
+ }
+}
diff --git a/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml b/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml
new file mode 100644
index 0000000000..79ff813f10
--- /dev/null
+++ b/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml
@@ -0,0 +1,202 @@
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.14
+
+import StatusQ.Core 0.1
+import StatusQ.Core.Theme 0.1
+import StatusQ.Controls 0.1
+
+import shared.panels 1.0
+
+
+StatusDropdown {
+ id: root
+
+ property int mode: PermissionsDropdown.Mode.Add
+ property int initialPermissionType: PermissionTypes.Type.None
+
+ enum Mode {
+ Add, Update
+ }
+
+ signal done(int permissionType, string title, string asset)
+
+ width: d.width
+ padding: d.padding
+
+ // force keeping within the bounds of the enclosing window
+ margins: 0
+
+ onAboutToShow: {
+ group.checkState = Qt.Unchecked
+ d.initialPermissionTypeChanged()
+ }
+
+ QtObject {
+ id: d
+
+ // internals
+ readonly property int initialPermissionType: root.initialPermissionType
+
+ // values from design
+ readonly property int padding: 8
+ readonly property int width: 289
+ readonly property int sectionHeight: 34
+ readonly property int sectionFontSize: 12
+ readonly property int extraMarginForText: 8
+
+ readonly property int separatorTopMargin: 4
+ readonly property int separatorBottomMargin: 12
+
+ readonly property int descriptionFontSize: 13
+ readonly property int descriptionLineHeight: 18
+
+ readonly property int buttonTopMargin: 32
+ }
+
+ ButtonGroup {
+ id: group
+ }
+
+ contentItem: ColumnLayout {
+ spacing: 0
+
+ Item {
+ Layout.fillWidth: true
+ Layout.preferredHeight: d.sectionHeight
+
+ StatusBaseText {
+ anchors.margins: d.extraMarginForText
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ text: qsTr("Community")
+ color: Theme.palette.baseColor1
+ font.pixelSize: d.sectionFontSize
+ elide: Text.ElideRight
+ }
+ }
+
+ PermissionListItem {
+ readonly property int permissionType: PermissionTypes.Type.Admin
+ readonly property string description: {
+ const generalInfo = qsTr("Members who meet the requirements will be allowed to create and edit permissions, token sales, airdrops and subscriptions")
+ const warning = qsTr("Be careful with assigning this permission.")
+ const warningExplanation = qsTr("Only the community owner can modify admin permissions")
+
+ const warningStyled = `${warning}`
+ return `${generalInfo}
${warningStyled} ${warningExplanation}`
+ }
+
+ title: qsTr("Become admin")
+ asset.name: "admin"
+ checked: d.initialPermissionType === permissionType
+ buttonGroup: group
+
+ Layout.fillWidth: true
+ }
+
+ PermissionListItem {
+ readonly property int permissionType: PermissionTypes.Type.Member
+ readonly property string description:
+ qsTr("Anyone who meets the requirements will be allowed to join your community")
+
+ title: qsTr("Become member")
+ asset.name: "in-contacts"
+ checked: d.initialPermissionType === permissionType
+ buttonGroup: group
+
+ Layout.fillWidth: true
+ }
+
+ Item {
+ Layout.fillWidth: true
+ Layout.preferredHeight: d.sectionHeight
+
+ StatusBaseText {
+ anchors.margins: d.extraMarginForText
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ text: qsTr("Channels")
+ color: Theme.palette.baseColor1
+ font.pixelSize: d.sectionFontSize
+ elide: Text.ElideRight
+ }
+ }
+
+ PermissionListItem {
+ readonly property int permissionType: PermissionTypes.Type.Moderator
+ readonly property string description:
+ qsTr("Members who meet the requirements will be allowed to read, write, ban members and pin messages in the selected channels")
+
+ title: qsTr("Moderate")
+ asset.name: "arbitrator"
+ checked: d.initialPermissionType === permissionType
+ buttonGroup: group
+
+ Layout.fillWidth: true
+ }
+
+ PermissionListItem {
+ readonly property int permissionType: PermissionTypes.Type.ViewAndPost
+ readonly property string description:
+ qsTr("Members who meet the requirements will be allowed to read and write in the selected channels")
+
+ title: qsTr("View and post")
+ asset.name: "edit"
+ checked: d.initialPermissionType === permissionType
+ buttonGroup: group
+
+ Layout.fillWidth: true
+ }
+
+ PermissionListItem {
+ readonly property int permissionType: PermissionTypes.Type.Read
+ readonly property string description:
+ qsTr("Members who meet the requirements will be allowed to read the selected channels")
+
+ title: qsTr("Read")
+ asset.name: "show"
+ checked: d.initialPermissionType === permissionType
+ buttonGroup: group
+
+ Layout.fillWidth: true
+ }
+
+ Separator {
+ visible: !!group.checkedButton
+
+ Layout.fillWidth: true
+ Layout.topMargin: d.separatorTopMargin
+ Layout.bottomMargin: d.separatorBottomMargin
+ }
+
+ StatusBaseText {
+ Layout.fillWidth: true
+ Layout.leftMargin: d.extraMarginForText
+
+ visible: !!group.checkedButton
+ text: group.checkedButton ? group.checkedButton.item.description : ""
+
+ textFormat: Text.StyledText
+ wrapMode: Text.Wrap
+ color: Theme.palette.baseColor1
+ font.pixelSize: d.descriptionFontSize
+ lineHeight: d.descriptionLineHeight
+ lineHeightMode: Text.FixedHeight
+ }
+
+ StatusButton {
+ Layout.fillWidth: true
+ Layout.topMargin: d.buttonTopMargin
+
+ text: root.mode === PermissionsDropdown.Mode.Add ? qsTr("Add") : qsTr("Update")
+ enabled: !!group.checkedButton
+
+ onClicked: root.done(group.checkedButton.item.permissionType,
+ group.checkedButton.item.title,
+ group.checkedButton.item.asset.name)
+ }
+ }
+}
diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml
index 9635253bdd..519a4ca005 100644
--- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml
+++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml
@@ -32,6 +32,7 @@ Flickable {
id: d
property bool isPrivate: false
property ListModel permissions: ListModel{}
+ property int permissionType: PermissionTypes.Type.None
}
contentWidth: mainLayout.width
@@ -116,7 +117,7 @@ Flickable {
onAddEns: {
const key = any ? "EnsAny" : "EnsCustom"
const name = any ? "" : customDomain
- const icon = "qrc:imports/assets/icons/profile/ensUsernames.svg"
+ const icon = Style.svg("ensUsernames")
holdingsModel.append({type: HoldingTypes.Type.Ens, key, name, amount: 1, imageSource: icon, operator })
d.permissions.append([{ key }, { operator }])
@@ -144,7 +145,7 @@ Flickable {
onUpdateEns: {
const key = any ? "EnsAny" : "EnsCustom"
const name = any ? "" : customDomain
- const icon = "qrc:imports/assets/icons/profile/ensUsernames.svg"
+ const icon = Style.svg("ensUsernames")
holdingsModel.set(tokensSelector.editedIndex, { type: HoldingTypes.Type.Ens, key, name: name, amount: 1, imageSource: icon })
dropdown.close()
@@ -166,7 +167,7 @@ Flickable {
dropdown.x = tokensSelector.addButton.width + 4
dropdown.y = 0
- if (tokensSelector.itemsModel.count === 0)
+ if (holdingsModel.count === 0)
dropdown.openFlow(HoldingsDropdown.FlowType.Add)
else
dropdown.openFlow(HoldingsDropdown.FlowType.AddWithOperators)
@@ -214,11 +215,59 @@ Flickable {
color: Style.current.separator
}
StatusItemSelector {
+ id: permissionsSelector
+
Layout.fillWidth: true
icon: Style.svg("profile/security")
iconSize: 24
+ useIcons: true
title: qsTr("Is allowed to")
defaultItemText: qsTr("Example: View and post")
+
+ Binding on itemsModel {
+ when: d.permissionType !== PermissionTypes.Type.None
+ value: QtObject {
+ id: permissionsListObjectModel
+
+ readonly property int operator: SQ.Utils.Operators.None
+ property string text: ""
+ property string imageSource: ""
+ }
+ }
+
+ addButton.visible: d.permissionType === PermissionTypes.Type.None
+
+ PermissionsDropdown {
+ id: permissionsDropdown
+
+ initialPermissionType: d.permissionType
+
+ onDone: {
+ d.permissionType = permissionType
+ permissionsListObjectModel.text = title
+ permissionsListObjectModel.imageSource = asset
+ permissionsDropdown.close()
+ }
+ }
+
+ addButton.onClicked: {
+ permissionsDropdown.mode = PermissionsDropdown.Mode.Add
+ permissionsDropdown.parent = permissionsSelector.addButton
+ permissionsDropdown.x = permissionsSelector.addButton.width + 4
+ permissionsDropdown.y = 0
+ permissionsDropdown.open()
+ }
+
+ onItemClicked: {
+ if (mouse.button !== Qt.LeftButton)
+ return
+
+ permissionsDropdown.mode = PermissionsDropdown.Mode.Update
+ permissionsDropdown.parent = item
+ permissionsDropdown.x = mouse.x + 4
+ permissionsDropdown.y = 1
+ permissionsDropdown.open()
+ }
}
Rectangle {
Layout.leftMargin: 16