diff --git a/ui/StatusQ/sandbox/pages/StatusItemSelectorPage.qml b/ui/StatusQ/sandbox/pages/StatusItemSelectorPage.qml index e90888d5d9..0c619ca255 100644 --- a/ui/StatusQ/sandbox/pages/StatusItemSelectorPage.qml +++ b/ui/StatusQ/sandbox/pages/StatusItemSelectorPage.qml @@ -13,8 +13,6 @@ ColumnLayout { iconSize: 24 title: "Item Selector Title" defaultItemText: "Example: Empty items" - andOperatorText: "and" - orOperatorText: "or" itemsModel: ListModel { id: model @@ -39,7 +37,7 @@ ColumnLayout { model.append({ text: input.text, imageSource: "qrc:/images/SNT.png", - operator: model.count > 0 ? Utils.Operators.Or : Utils.Operators.None + operator: model.count > 0 ? OperatorsUtils.Operators.Or : OperatorsUtils.Operators.None }) dropdown.close() diff --git a/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml b/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml index bbcb52e2b2..f33396e4bd 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml @@ -100,38 +100,12 @@ Rectangle { an image or an icon. */ property bool useIcons: false - /*! - \qmlproperty string StatusItemSelector::andOperatorText - This property holds the string text representation for an `AND` logical operator. - */ - property string andOperatorText: qsTr("and") - /*! - \qmlproperty string StatusItemSelector::orOperatorText - This property holds the string text representation for an `OR` logical operator. - */ - property string orOperatorText: qsTr("or") /*! \qmlsignal StatusItemSelector::itemClicked This signal is emitted when the item is clicked. */ signal itemClicked(var item, int index, var mouse) - - QtObject { - id: d - - function operatorTextFormat(operator) { - switch(operator) { - case Utils.Operators.And: - return root.andOperatorText - case Utils.Operators.Or: - return root.orOperatorText - case Utils.Operators.None: - return "" - } - } - } - color: Theme.palette.baseColor4 implicitHeight: columnLayout.implicitHeight + columnLayout.anchors.topMargin + columnLayout.anchors.bottomMargin implicitWidth: 560 @@ -190,9 +164,9 @@ Rectangle { spacing: flow.spacing StatusBaseText { - visible: model.operator !== Utils.Operators.None + visible: model.operator !== OperatorsUtils.Operators.None Layout.alignment: Qt.AlignVCenter - text: d.operatorTextFormat(model.operator) + text: OperatorsUtils.setOperatorTextFormat(model.operator) color: Theme.palette.primaryColor1 font.pixelSize: 17 MouseArea { @@ -200,10 +174,10 @@ Rectangle { cursorShape: Qt.PointingHandCursor onClicked: { // Switch operator - if(model.operator === Utils.Operators.And) - model.operator = Utils.Operators.Or + if(model.operator === OperatorsUtils.Operators.And) + model.operator = OperatorsUtils.Operators.Or else - model.operator = Utils.Operators.And + model.operator = OperatorsUtils.Operators.And } } } diff --git a/ui/StatusQ/src/StatusQ/Core/Utils/OperatorsUtils.qml b/ui/StatusQ/src/StatusQ/Core/Utils/OperatorsUtils.qml new file mode 100644 index 0000000000..c1cface041 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Core/Utils/OperatorsUtils.qml @@ -0,0 +1,36 @@ +pragma Singleton + +import QtQuick 2.13 + +QtObject { + id: root + + /*! + \qmlproperty string OperatorsUtils::andOperatorText + This property holds the string text representation for an `AND` logical operator. + */ + readonly property string andOperatorText: qsTr("and") + /*! + \qmlproperty string OperatorsUtils::orOperatorText + This property holds the string text representation for an `OR` logical operator. + */ + readonly property string orOperatorText: qsTr("or") + + // Logical operators + enum Operators { + None, + And, + Or + } + + function setOperatorTextFormat(operator) { + switch(operator) { + case OperatorsUtils.Operators.And: + return root.andOperatorText + case OperatorsUtils.Operators.Or: + return root.orOperatorText + case OperatorsUtils.Operators.None: + return "" + } + } +} diff --git a/ui/StatusQ/src/StatusQ/Core/Utils/Utils.qml b/ui/StatusQ/src/StatusQ/Core/Utils/Utils.qml index 9668d1c606..3c333eed67 100644 --- a/ui/StatusQ/src/StatusQ/Core/Utils/Utils.qml +++ b/ui/StatusQ/src/StatusQ/Core/Utils/Utils.qml @@ -5,13 +5,7 @@ import StatusQ.Core.Theme 0.1 import "./xss.js" as XSS QtObject { - - // Logical operators - enum Operators { - None, - And, - Or - } + id: root function getAbsolutePosition(node) { var returnPos = {}; diff --git a/ui/StatusQ/src/StatusQ/Core/Utils/qmldir b/ui/StatusQ/src/StatusQ/Core/Utils/qmldir index 0cf941a8b3..9070479206 100644 --- a/ui/StatusQ/src/StatusQ/Core/Utils/qmldir +++ b/ui/StatusQ/src/StatusQ/Core/Utils/qmldir @@ -5,3 +5,4 @@ XSS 1.0 xss.js singleton Utils 0.1 Utils.qml singleton Emoji 0.1 Emoji.qml JSONListModel 0.1 JSONListModel.qml +singleton OperatorsUtils 0.1 OperatorsUtils.qml diff --git a/ui/StatusQ/src/statusq.qrc b/ui/StatusQ/src/statusq.qrc index 17abbc650f..cb6b678706 100644 --- a/ui/StatusQ/src/statusq.qrc +++ b/ui/StatusQ/src/statusq.qrc @@ -193,5 +193,6 @@ StatusQ/Core/StatusRollArea.qml StatusQ/Popups/Dialog/StatusDialogBackground.qml StatusQ/Popups/StatusMenuInstantiator.qml + StatusQ/Core/Utils/OperatorsUtils.qml diff --git a/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml b/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml index 53d06a9d2f..4df2cd0a64 100644 --- a/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml +++ b/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml @@ -5,7 +5,7 @@ import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 -import StatusQ.Core.Utils 0.1 as SQ +import StatusQ.Core.Utils 0.1 StatusDropdown { @@ -35,7 +35,7 @@ StatusDropdown { function reset() { d.currentHoldingType = HoldingTypes.Type.Token - d.operator = SQ.Utils.Operators.None + d.operator = OperatorsUtils.Operators.None d.tokenAmountText = "" d.collectibleAmountText = "" @@ -106,7 +106,7 @@ StatusDropdown { property int currentHoldingType: HoldingTypes.Type.Token - property int operator: SQ.Utils.Operators.None + property int operator: OperatorsUtils.Operators.None property bool ensDomainNameValid: false signal addClicked @@ -304,7 +304,7 @@ StatusDropdown { const modelItem = store.getTokenByKey(tokenKey) if (modelItem) { - tokensPanel.tokenName = modelItem.name + tokensPanel.tokenName = modelItem.shortName tokensPanel.tokenImage = modelItem.iconSource } else { tokensPanel.tokenName = d.defaultTokenNameText diff --git a/ui/app/AppLayouts/Chat/controls/community/OperatorsSelector.qml b/ui/app/AppLayouts/Chat/controls/community/OperatorsSelector.qml index a65f26d3dd..1e97825a24 100644 --- a/ui/app/AppLayouts/Chat/controls/community/OperatorsSelector.qml +++ b/ui/app/AppLayouts/Chat/controls/community/OperatorsSelector.qml @@ -3,7 +3,7 @@ import QtQuick 2.14 import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 -import StatusQ.Core.Utils 0.1 as SQ +import StatusQ.Core.Utils 0.1 import utils 1.0 @@ -19,12 +19,12 @@ ColumnLayout { { icon: "add", text: qsTr("And..."), - operator: SQ.Utils.Operators.And + operator: OperatorsUtils.Operators.And }, { icon: "condition-Or", text: qsTr("Or..."), - operator: SQ.Utils.Operators.Or + operator: OperatorsUtils.Operators.Or } ] diff --git a/ui/app/AppLayouts/Chat/controls/community/PermissionItem.qml b/ui/app/AppLayouts/Chat/controls/community/PermissionItem.qml new file mode 100644 index 0000000000..bf3c15791d --- /dev/null +++ b/ui/app/AppLayouts/Chat/controls/community/PermissionItem.qml @@ -0,0 +1,245 @@ +import QtQuick 2.3 +import QtQuick.Controls 2.13 +import QtQuick.Layouts 1.14 + +import StatusQ.Core.Theme 0.1 +import StatusQ.Core 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Components 0.1 +import StatusQ.Core.Utils 0.1 + +Control{ + id: root + + property var holdingsListModel + property string permissionName + property var permissionImageSource + property var channelsListModel + property bool isPrivate: false + + signal editClicked + signal duplicateClicked + signal removeClicked + + QtObject { + id: d + readonly property int flowRowHeight: 32 + readonly property int commonMargin: 16 + readonly property int designRadius: 16 + readonly property int itemTextPixelSize: 17 + readonly property int tagTextPixelSize: 15 + readonly property int buttonTextPixelSize: 12 + readonly property int buttonDiameter: 36 + readonly property int buttonTextSpacing: 6 + } + background: Rectangle { + color: "transparent" + border.color: Theme.palette.baseColor2 + border.width: 1 + radius: d.designRadius + } + + contentItem: ColumnLayout { + spacing: 0 + + Rectangle { + id: header + color: Theme.palette.baseColor2 + Layout.fillWidth: true + Layout.preferredHeight: 34 + radius: d.designRadius + + RowLayout { + anchors.fill: parent + spacing: 8 + + StatusIcon { + Layout.leftMargin: 19 + icon: "checkmark" + Layout.preferredWidth: 11 + Layout.preferredHeight: 8 + color: Theme.palette.directColor1 + } + + StatusBaseText { + Layout.fillWidth: true + text: qsTr("Active") + font.pixelSize: d.tagTextPixelSize + } + + StatusIcon { + Layout.rightMargin: 10 + visible: root.isPrivate + icon: "hide" + color: Theme.palette.baseColor1 + } + } + } + + Flow { + id: content + Layout.fillWidth: true + Layout.fillHeight: true + Layout.topMargin: 8 + Layout.rightMargin: d.commonMargin + Layout.leftMargin: d.commonMargin + Layout.bottomMargin: 20 + spacing: 6 + + StatusBaseText { + font.pixelSize: d.itemTextPixelSize + height: d.flowRowHeight + text: qsTr("Anyone who holds") + verticalAlignment: Text.AlignVCenter + } + + Repeater { + model: root.holdingsListModel + + RowLayout { + spacing: content.spacing + + StatusBaseText { + Layout.preferredHeight: d.flowRowHeight + visible: model.operator !== OperatorsUtils.Operators.None + Layout.alignment: Qt.AlignVCenter + text: OperatorsUtils.setOperatorTextFormat(model.operator) + font.pixelSize: d.itemTextPixelSize + verticalAlignment: Text.AlignVCenter + + } + StatusListItemTag { + Layout.preferredHeight: d.flowRowHeight + title: model.text + asset.name: model.imageSource + asset.isImage: true + asset.bgColor: "transparent" + asset.height: 28 + asset.width: asset.height + color: Theme.palette.primaryColor3 + closeButtonVisible: false + titleText.color: Theme.palette.primaryColor1 + titleText.font.pixelSize: d.tagTextPixelSize + } + } + } + + StatusBaseText { + height: d.flowRowHeight + font.pixelSize: d.itemTextPixelSize + text: qsTr("is allowed to") + verticalAlignment: Text.AlignVCenter + } + + StatusListItemTag { + height: d.flowRowHeight + title: root.permissionName + asset.name: root.permissionImageSource + asset.isImage: false + asset.bgColor: "transparent" + color: Theme.palette.primaryColor3 + closeButtonVisible: false + titleText.color: Theme.palette.primaryColor1 + titleText.font.pixelSize: d.tagTextPixelSize + } + + StatusBaseText { + height: d.flowRowHeight + font.pixelSize: d.itemTextPixelSize + text: qsTr("in") + verticalAlignment: Text.AlignVCenter + } + + Repeater { + model: root.channelsListModel + + RowLayout { + spacing: content.spacing + + StatusBaseText { + Layout.preferredHeight: d.flowRowHeight + visible: model.index !== 0 + Layout.alignment: Qt.AlignVCenter + text: qsTr("and") + font.pixelSize: d.itemTextPixelSize + verticalAlignment: Text.AlignVCenter + + } + StatusListItemTag { + Layout.preferredHeight: d.flowRowHeight + title: model.text + asset.name: model.imageSource + asset.isImage: true + asset.bgColor: "transparent" + color: Theme.palette.primaryColor3 + closeButtonVisible: false + titleText.color: Theme.palette.primaryColor1 + titleText.font.pixelSize: d.tagTextPixelSize + } + } + } + } + + RowLayout { + id: footer + spacing: 85 + Layout.fillWidth: true + Layout.bottomMargin: d.commonMargin + Layout.alignment: Qt.AlignHCenter + + ColumnLayout { + spacing: d.buttonTextSpacing + StatusRoundButton { + Layout.alignment: Qt.AlignHCenter + icon.name: "edit_pencil" + Layout.preferredHeight: d.buttonDiameter + Layout.preferredWidth: Layout.preferredHeight + type: StatusRoundButton.Type.Primary + onClicked: root.editClicked() + } + StatusBaseText { + Layout.alignment: Qt.AlignHCenter + text: qsTr("Edit") + color: Theme.palette.primaryColor1 + font.pixelSize: d.buttonTextPixelSize + } + } + + ColumnLayout { + spacing: d.buttonTextSpacing + StatusRoundButton { + Layout.alignment: Qt.AlignHCenter + icon.name: "copy" + Layout.preferredHeight: d.buttonDiameter + Layout.preferredWidth: Layout.preferredHeight + type: StatusRoundButton.Type.Primary + onClicked: root.duplicateClicked() + } + StatusBaseText { + Layout.alignment: Qt.AlignHCenter + text: qsTr("Duplicate") + color: Theme.palette.primaryColor1 + font.pixelSize: d.buttonTextPixelSize + } + } + + ColumnLayout { + spacing: d.buttonTextSpacing + StatusRoundButton { + Layout.alignment: Qt.AlignHCenter + icon.name: "delete" + Layout.preferredHeight: d.buttonDiameter + Layout.preferredWidth: Layout.preferredHeight + type: StatusRoundButton.Type.Quaternary + onClicked: root.removeClicked() + } + StatusBaseText { + Layout.alignment: Qt.AlignHCenter + text: qsTr("Remove") + color: Theme.palette.dangerColor1 + font.pixelSize: d.buttonTextPixelSize + } + } + } + } +} diff --git a/ui/app/AppLayouts/Chat/controls/community/qmldir b/ui/app/AppLayouts/Chat/controls/community/qmldir new file mode 100644 index 0000000000..b72c6605e9 --- /dev/null +++ b/ui/app/AppLayouts/Chat/controls/community/qmldir @@ -0,0 +1,2 @@ +HoldingTypes 1.0 HoldingTypes.qml +PermissionItem 1.0 PermissionItem.qml \ No newline at end of file diff --git a/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml b/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml index 1b97493642..4b8ae9e823 100644 --- a/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml +++ b/ui/app/AppLayouts/Chat/layouts/SettingsPageLayout.qml @@ -19,6 +19,9 @@ Item { // optional property bool dirty: false property bool editable: false + property bool headerButtonVisible: false + property string headerButtonText: "" + property int headerWidth: 0 readonly property Item contentItem: contentLoader.item readonly property size settingsDirtyToastMessageImplicitSize: @@ -27,6 +30,7 @@ Item { signal saveChangesClicked signal resetChangesClicked + signal headerButtonClicked function reloadContent() { contentLoader.active = false @@ -46,17 +50,28 @@ Item { anchors.fill: parent spacing: 16 - Item { - width: parent.width + RowLayout { + Layout.maximumWidth: root.headerWidth === 0 ? parent.width : (root.headerWidth + itemHeader.Layout.leftMargin) Layout.preferredHeight: 56 - Layout.leftMargin: 36 + StatusBaseText { - anchors.verticalCenter: parent.verticalCenter + id: itemHeader + Layout.leftMargin: 64 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter text: root.title color: Theme.palette.directColor1 font.pixelSize: 26 font.bold: true } + + StatusButton { + visible: root.headerButtonVisible + text: root.headerButtonText + Layout.preferredHeight: 44 + Layout.alignment: Qt.AlignHCenter + onClicked: root.headerButtonClicked() + } } Loader { @@ -64,7 +79,7 @@ Item { Layout.fillWidth: true Layout.fillHeight: true Layout.topMargin: 16 - Layout.leftMargin: 24 + Layout.leftMargin: 64 Layout.rightMargin: 24 sourceComponent: root.content diff --git a/ui/app/AppLayouts/Chat/layouts/qmldir b/ui/app/AppLayouts/Chat/layouts/qmldir new file mode 100644 index 0000000000..e1b018562a --- /dev/null +++ b/ui/app/AppLayouts/Chat/layouts/qmldir @@ -0,0 +1 @@ +SettingsPageLayout 1.0 SettingsPageLayout.qml diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml index 9af79bd01b..1fcbd6eeca 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml @@ -1,11 +1,15 @@ import QtQuick 2.14 -import "../../layouts" -import "../../views/communities" +import AppLayouts.Chat.layouts 1.0 +import AppLayouts.Chat.views.communities 1.0 +import AppLayouts.Chat.stores 1.0 SettingsPageLayout { id: root + property var store: CommunitiesStore {} + property int viewWidth: 560 // by design + property string previousPageName function updateState() { if (root.state === d.newPermissionViewState) { @@ -18,34 +22,69 @@ SettingsPageLayout { readonly property string welcomeViewState: "WELCOME" readonly property string newPermissionViewState: "NEWPERMISSION" + readonly property string permissionsViewState: "PERMISSIONS" } - state: d.welcomeViewState // Initial state + state: root.store.permissionsModel.count > 0 ? d.permissionsViewState : d.welcomeViewState states: [ State { name: d.welcomeViewState PropertyChanges {target: root; title: qsTr("Permissions")} PropertyChanges {target: root; previousPageName: ""} PropertyChanges {target: root; content: welcomeView} + PropertyChanges {target: root; headerButtonVisible: true} + PropertyChanges {target: root; headerButtonText: qsTr("Add new permission")} + PropertyChanges {target: root; headerWidth: root.viewWidth} }, State { name: d.newPermissionViewState PropertyChanges {target: root; title: qsTr("New permission")} PropertyChanges {target: root; previousPageName: qsTr("Permissions")} PropertyChanges {target: root; content: newPermissionView} + PropertyChanges {target: root; headerButtonVisible: false} + PropertyChanges {target: root; headerWidth: 0} + }, + State { + name: d.permissionsViewState + PropertyChanges {target: root; title: qsTr("Permissions")} + PropertyChanges {target: root; previousPageName: ""} + PropertyChanges {target: root; content: permissionsView} + PropertyChanges {target: root; headerButtonVisible: true} + PropertyChanges {target: root; headerButtonText: qsTr("Add new permission")} + PropertyChanges {target: root; headerWidth: root.viewWidth} } ] + onHeaderButtonClicked: { + if(root.state === d.welcomeViewState) + root.state = d.newPermissionViewState + + else if (root.state === d.permissionsViewState) + root.state = d.newPermissionViewState + } + // Community Permissions possible view contents: Component { id: welcomeView CommunityWelcomePermissionsView { - onAddPermission: root.state = d.newPermissionViewState + viewWidth: root.viewWidth } } Component { id: newPermissionView - CommunityNewPermissionView {} + CommunityNewPermissionView { + viewWidth: root.viewWidth + store: root.store + onPermissionCreated: root.state = d.permissionsViewState + } + } + + Component { + id: permissionsView + CommunityPermissionsView { + viewWidth: root.viewWidth + store: root.store + } } } diff --git a/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml b/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml index 13b3ae9bdb..188c5bc586 100644 --- a/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml +++ b/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml @@ -1,6 +1,13 @@ import QtQuick 2.0 +import AppLayouts.Chat.controls.community 1.0 +import StatusQ.Core.Utils 0.1 as SQ +import utils 1.0 + QtObject { + id: root + + property var permissionsModel: ListModel {} // Backend permissions list object model asignement. Please check the current expected data in qml defined in `createPermissions` method // TODO: Replace to real data, now dummy model property var tokensModel: ListModel { @@ -71,6 +78,12 @@ QtObject { } } + // TODO: Replace to real data, now dummy model + property var channelsModel: ListModel { + ListElement { key: "wellcome"; iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png"; name: "#welcome"} + ListElement { key: "general"; iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png"; name: "#general"} + } + readonly property QtObject _d: QtObject { id: d @@ -105,7 +118,73 @@ QtObject { return null } - function createPermissions(permissions) { - console.log("TODO: Create permissions - backend call") + function createPermissions(holdings, permissions, isPrivate) { + console.log("TODO: Create permissions - backend call - Now dummy data shown") + // TO BE REMOVED: It shold just be a call to the backend sharing `holdings`, `permissions`, `channels` and `isPrivate` properties. + var permission = { + isPrivate: true, + holdingsListModel: [], + permissionsObjectModel: { + key: "", + text: "", + imageSource: "" + }, + channelsListModel: [] + }; + + // Setting HOLDINGS: + for (var i = 0; i < holdings.count; i++ ) { + var entry = holdings.get(i); + // roles: type, key, name, amount, imageSource, operator + permission.holdingsListModel.push({ + operator: entry.operator, + type: entry.type, + key: entry.key, + name: entry.name, + amount: entry.amount, + imageSource: entry.imageSource + }); + } + + // Setting PERMISSIONS: + permission.permissionsObjectModel.key = permissions.key + permission.permissionsObjectModel.text = permissions.text + permission.permissionsObjectModel.imageSource = permissions.imageSource + + // Setting PRIVATE permission property: + permission.isPrivate = isPrivate + + // TODO: Set channels list. Now mocked data. + permission.channelsListModel = root.channelsModel + + // Add into permission model: + root.permissionsModel.append(permission) + } + + function setHoldingsTextFormat(type, name, amount) { + switch (type) { + case HoldingTypes.Type.Token: + case HoldingTypes.Type.Collectible: + return `${LocaleUtils.numberToLocaleString(amount)} ${name}` + case HoldingTypes.Type.Ens: + if (name) + return qsTr("ENS username on '%1' domain").arg(name) + else + return qsTr("Any ENS username") + default: + return "" + } + } + + function editPermission(index) { + console.log("TODO: Edit permissions - backend call") + } + + function duplicatePermission(index) { + console.log("TODO: Duplicate permissions - backend call") + } + + function removePermission(index) { + console.log("TODO: Remove permissions - backend call") } } diff --git a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml index d61c10f1ac..a96023aede 100644 --- a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml +++ b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml @@ -158,11 +158,7 @@ StatusSectionLayout { centerPanel: Loader { id: centerPanelContentLoader anchors.fill: parent - //anchors.margins: 32 - anchors { - leftMargin: 28 - bottomMargin: 16 - } + anchors.bottomMargin: 16 active: root.community sourceComponent: StackLayout { currentIndex: d.currentIndex diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml index 519a4ca005..227c641a0e 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml @@ -5,7 +5,7 @@ import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 -import StatusQ.Core.Utils 0.1 as SQ +import StatusQ.Core.Utils 0.1 import utils 1.0 import shared.panels 1.0 @@ -13,25 +13,18 @@ import shared.panels 1.0 import SortFilterProxyModel 0.2 import "../../../Chat/controls/community" -import "../../stores" Flickable { id: root - property var store: CommunitiesStore {} + property var store + property int viewWidth: 560 // by design - - signal createPermission() - - // TODO: Call this when permissions are stored in backend to start a new permissions flow - function clearPermissions() { - d.permissions.clear() - } + signal permissionCreated() QtObject { id: d property bool isPrivate: false - property ListModel permissions: ListModel{} property int permissionType: PermissionTypes.Type.None } @@ -42,7 +35,7 @@ Flickable { ColumnLayout { id: mainLayout - width: 560 // by design + width: root.viewWidth spacing: 0 CurveSeparatorWithText { Layout.alignment: Qt.AlignLeft @@ -55,8 +48,6 @@ Flickable { icon: Style.svg("contact_verified") title: qsTr("Who holds") defaultItemText: qsTr("Example: 10 SNT") - andOperatorText: qsTr("and") - orOperatorText: qsTr("or") // roles: type, key, name, amount, imageSource, operator ListModel { @@ -64,28 +55,12 @@ Flickable { } property int editedIndex - - function getText(type, name, amount) { - switch (type) { - case HoldingTypes.Type.Token: - case HoldingTypes.Type.Collectible: - return `${LocaleUtils.numberToLocaleString(amount)} ${name}` - case HoldingTypes.Type.Ens: - if (name) - return qsTr("ENS username on '%1' domain").arg(name) - else - return qsTr("Any ENS username") - default: - return "" - } - } - itemsModel: SortFilterProxyModel { sourceModel: holdingsModel proxyRoles: ExpressionRole { name: "text" - expression: tokensSelector.getText(model.type, model.name, model.amount) + expression: root.store.setHoldingsTextFormat(model.type, model.name, model.amount) } } @@ -95,11 +70,10 @@ Flickable { function addItem(type, item, amount, operator) { const key = item.key - const name = item.name + const name = item.shortName ? item.shortName : item.name const imageSource = item.iconSource.toString() holdingsModel.append({ type, key, name, amount, imageSource, operator }) - d.permissions.append([{ key }, { operator }]) } onAddToken: { @@ -120,13 +94,12 @@ Flickable { const icon = Style.svg("ensUsernames") holdingsModel.append({type: HoldingTypes.Type.Ens, key, name, amount: 1, imageSource: icon, operator }) - d.permissions.append([{ key }, { operator }]) dropdown.close() } onUpdateToken: { const modelItem = store.getTokenByKey(key) - const name = modelItem.name + const name = modelItem.shortName ? modelItem.shortName : modelItem.name const imageSource = modelItem.iconSource.toString() holdingsModel.set(tokensSelector.editedIndex, { type: HoldingTypes.Type.Token, key, name, amount, imageSource }) @@ -155,7 +128,7 @@ Flickable { holdingsModel.remove(tokensSelector.editedIndex) if (holdingsModel.count) { - holdingsModel.set(0, { operator: SQ.Utils.Operators.None}) + holdingsModel.set(0, { operator: OperatorsUtils.Operators.None}) } dropdown.close() @@ -229,7 +202,8 @@ Flickable { value: QtObject { id: permissionsListObjectModel - readonly property int operator: SQ.Utils.Operators.None + readonly property int operator: OperatorsUtils.Operators.None + property var key property string text: "" property string imageSource: "" } @@ -244,6 +218,7 @@ Flickable { onDone: { d.permissionType = permissionType + permissionsListObjectModel.key = permissionType permissionsListObjectModel.text = title permissionsListObjectModel.imageSource = asset permissionsDropdown.close() @@ -321,13 +296,13 @@ Flickable { StatusButton { Layout.topMargin: 24 text: qsTr("Create permission") - enabled: d.permissions.count > 0 + enabled: holdingsModel.count > 0 && permissionsListObjectModel.key !== undefined Layout.preferredHeight: 44 Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true onClicked: { - root.store.createPermissions(d.permissions) - root.clearPermissions() + root.store.createPermissions(holdingsModel, permissionsListObjectModel, d.isPrivate) + root.permissionCreated() } } } diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityPermissionsView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityPermissionsView.qml new file mode 100644 index 0000000000..45a181e7b3 --- /dev/null +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityPermissionsView.qml @@ -0,0 +1,65 @@ +import QtQuick 2.14 +import QtQuick.Layouts 1.14 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Controls 0.1 + +import SortFilterProxyModel 0.2 +import utils 1.0 + +import AppLayouts.Chat.controls.community 1.0 + +Flickable { + id: root + + property var store + property int viewWidth: 560 // by design + + contentWidth: mainLayout.width + contentHeight: mainLayout.height + mainLayout.anchors.topMargin + clip: true + flickableDirection: Flickable.AutoFlickIfNeeded + + ColumnLayout { + id: mainLayout + width: root.viewWidth + spacing: 24 + + Repeater { + model: root.store.permissionsModel + delegate: PermissionItem { + Layout.preferredWidth: root.viewWidth + holdingsListModel: SortFilterProxyModel { + sourceModel: model.holdingsListModel + + proxyRoles: ExpressionRole { + name: "text" + expression: root.store.setHoldingsTextFormat(model.type, model.name, model.amount) + } + } + permissionName: model.permissionsObjectModel.text + permissionImageSource: model.permissionsObjectModel.imageSource + channelsListModel: SortFilterProxyModel { + sourceModel: model.channelsListModel + + proxyRoles: [ + ExpressionRole { + name: "text" + expression: model.name + }, + ExpressionRole { + name: "imageSource" + expression: model.iconSource + } + ] + } + isPrivate: model.isPrivate + + onEditClicked: store.editPermission(model.index) + onDuplicateClicked: store.duplicatePermission(model.index) + onRemoveClicked: store.removePermission(model.index) + } + } + } +} diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityWelcomePermissionsView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityWelcomePermissionsView.qml index 473f434ae6..069df8b3fb 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityWelcomePermissionsView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityWelcomePermissionsView.qml @@ -10,7 +10,7 @@ import utils 1.0 Flickable { id: root - signal addPermission() + property int viewWidth: 560 // by design contentWidth: mainLayout.width contentHeight: mainLayout.height + mainLayout.anchors.topMargin @@ -19,7 +19,7 @@ Flickable { ColumnLayout { id: mainLayout - width: 560 // by design + width: root.viewWidth spacing: 24 Rectangle { @@ -127,13 +127,5 @@ Flickable { } } } - - StatusButton { - text: qsTr("Add permission") - height: 44 - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - onClicked: root.addPermission() - } } } diff --git a/ui/app/AppLayouts/Chat/views/communities/qmldir b/ui/app/AppLayouts/Chat/views/communities/qmldir new file mode 100644 index 0000000000..21a05f921d --- /dev/null +++ b/ui/app/AppLayouts/Chat/views/communities/qmldir @@ -0,0 +1,3 @@ +CommunityWelcomePermissionsView 1.0 CommunityWelcomePermissionsView.qml +CommunityNewPermissionView 1.0 CommunityNewPermissionView.qml +CommunityPermissionsView 1.0 CommunityPermissionsView.qml