mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-20 02:28:56 +00:00
fix(community): Token gating info when permission not met and set to private
- hide the permission from the `PermissionsRow` when it's set to private and the conditions are not met - display a tooltip "(Not) eligible to join" over the lock icon - show the same info in both community portal and profile dialog's community showcase tab - speedup searching/filtering in the community portal - fixup and extend the SB pages to demonstrate the new behavior Fixes #14747
This commit is contained in:
parent
fe9308fa1e
commit
235162dc01
@ -8,14 +8,14 @@ ListModel {
|
|||||||
|
|
||||||
Component.onCompleted: append([
|
Component.onCompleted: append([
|
||||||
{
|
{
|
||||||
featured: true,
|
featured: false,
|
||||||
id: "id1",
|
id: "id1",
|
||||||
loaded: true,
|
loaded: true,
|
||||||
icon: ModelsData.icons.status,
|
icon: ModelsData.icons.status,
|
||||||
banner: ModelsData.banners.status,
|
banner: ModelsData.banners.status,
|
||||||
color: "blue",
|
color: "blue",
|
||||||
name: "Status.im",
|
name: "Status.app",
|
||||||
description: "Your portal to Web3. Secure wallet. dApp browser. Private messaging. All-in-one.",
|
description: "Your portal to Web3. Secure wallet. Private messaging. Requires secret tokens to join",
|
||||||
members: 130,
|
members: 130,
|
||||||
activeMembers: 61,
|
activeMembers: 61,
|
||||||
popularity: 4,
|
popularity: 4,
|
||||||
@ -42,8 +42,8 @@ ListModel {
|
|||||||
"emoji": "💼",
|
"emoji": "💼",
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
permissionsModel: PermissionsModel.shortPermissionsModel,
|
permissionsModel: PermissionsModel.privatePermissionsMemberNotMetModel,
|
||||||
allTokenRequirementsMet: true
|
allTokenRequirementsMet: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
featured: true,
|
featured: true,
|
||||||
@ -168,7 +168,7 @@ ListModel {
|
|||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
permissionsModel: PermissionsModel.threeShortPermissionsModel,
|
permissionsModel: PermissionsModel.threeShortPermissionsModel,
|
||||||
allTokenRequirementsMet: true
|
allTokenRequirementsMet: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
featured: false,
|
featured: false,
|
||||||
@ -218,7 +218,7 @@ ListModel {
|
|||||||
"emoji": "💼",
|
"emoji": "💼",
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
permissionsModel: PermissionsModel.longPermissionsModel,
|
permissionsModel: PermissionsModel.twoLongPermissionsModel,
|
||||||
allTokenRequirementsMet: true
|
allTokenRequirementsMet: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -235,7 +235,8 @@ ListModel {
|
|||||||
popularity: 4,
|
popularity: 4,
|
||||||
available: true,
|
available: true,
|
||||||
tags: JSON.stringify([]),
|
tags: JSON.stringify([]),
|
||||||
permissionsModel: emptyModel
|
permissionsModel: emptyModel,
|
||||||
|
allTokenRequirementsMet: false
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ SplitView {
|
|||||||
Popups {
|
Popups {
|
||||||
popupParent: root
|
popupParent: root
|
||||||
sharedRootStore: SharedStores.RootStore {}
|
sharedRootStore: SharedStores.RootStore {}
|
||||||
rootStore: AppLayoutStores.RootStore
|
rootStore: AppLayoutStores.RootStore {}
|
||||||
communityTokensStore: SharedStores.CommunityTokensStore {}
|
communityTokensStore: SharedStores.CommunityTokensStore {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,22 @@ SplitView {
|
|||||||
requirementsMet: permissionsMetCheckEditor.checked
|
requirementsMet: permissionsMetCheckEditor.checked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
|
|
||||||
|
text: "Private + unmet permissions:"
|
||||||
|
}
|
||||||
|
|
||||||
|
PermissionsRow {
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
|
Layout.bottomMargin: spacing
|
||||||
|
|
||||||
|
assetsModel: root.assetsModel
|
||||||
|
collectiblesModel: root.collectiblesModel
|
||||||
|
model: PermissionsModel.privatePermissionsMemberNotMetModel
|
||||||
|
requirementsMet: false
|
||||||
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
|
|
||||||
@ -139,7 +155,7 @@ SplitView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: "Row heigh:"
|
text: "Row height:"
|
||||||
}
|
}
|
||||||
|
|
||||||
Slider {
|
Slider {
|
||||||
|
@ -115,7 +115,7 @@ ListModel {
|
|||||||
members: [{ pubKey: "0xdeadbeef" }],
|
members: [{ pubKey: "0xdeadbeef" }],
|
||||||
membersCount: 1,
|
membersCount: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
permissionsModel: null,
|
permissionsModel: PermissionsModel.privatePermissionsMemberNotMetModel,
|
||||||
allTokenRequirementsMet: false
|
allTokenRequirementsMet: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -85,6 +85,24 @@ QtObject {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
readonly property var privatePermissionsMemberModelNotMetData: [
|
||||||
|
{
|
||||||
|
holdingsListModel: root.createHoldingsModel4(),
|
||||||
|
channelsListModel: root.createChannelsModel1(),
|
||||||
|
permissionType: PermissionTypes.Type.Member,
|
||||||
|
permissionState: PermissionTypes.State.Approved,
|
||||||
|
isPrivate: true,
|
||||||
|
tokenCriteriaMet: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
holdingsListModel: root.createHoldingsModel2(),
|
||||||
|
channelsListModel: root.createChannelsModel2(),
|
||||||
|
permissionType: PermissionTypes.Type.Member,
|
||||||
|
permissionState: PermissionTypes.State.Approved,
|
||||||
|
isPrivate: true,
|
||||||
|
tokenCriteriaMet: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
readonly property var shortPermissionsModelData: [
|
readonly property var shortPermissionsModelData: [
|
||||||
{
|
{
|
||||||
@ -554,6 +572,17 @@ QtObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property ListModel privatePermissionsMemberNotMetModel: ListModel {
|
||||||
|
readonly property ModelChangeGuard guard: ModelChangeGuard {
|
||||||
|
model: root.privatePermissionsMemberNotMetModel
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
append(privatePermissionsMemberModelNotMetData)
|
||||||
|
guard.enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
readonly property var shortPermissionsModel: ListModel {
|
readonly property var shortPermissionsModel: ListModel {
|
||||||
readonly property ModelChangeGuard guard: ModelChangeGuard {
|
readonly property ModelChangeGuard guard: ModelChangeGuard {
|
||||||
model: root.shortPermissionsModel
|
model: root.shortPermissionsModel
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import QtQuick 2.13
|
import QtQuick 2.15
|
||||||
import QtQuick.Layouts 1.13
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
import StatusQ 0.1
|
import StatusQ 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Core.Utils 0.1
|
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Components 0.1
|
import StatusQ.Components 0.1
|
||||||
import StatusQ.Popups 0.1
|
import StatusQ.Popups 0.1
|
||||||
@ -71,21 +71,19 @@ StatusSectionLayout {
|
|||||||
sourceModel: root.communitiesStore.curatedCommunitiesModel
|
sourceModel: root.communitiesStore.curatedCommunitiesModel
|
||||||
|
|
||||||
filters: [
|
filters: [
|
||||||
ExpressionFilter {
|
SQUtils.SearchFilter {
|
||||||
enabled: d.searchMode
|
roleName: "name"
|
||||||
expression: {
|
searchPhrase: searcher.text
|
||||||
searcher.text
|
|
||||||
return name.toLowerCase().includes(searcher.text.toLowerCase())
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ExpressionFilter {
|
FastExpressionFilter {
|
||||||
expression: {
|
expression: {
|
||||||
return filteredCommunitiesModel.selectedTagsPredicate(communityTags.selectedTagsNames, model.tags)
|
return filteredCommunitiesModel.selectedTagsPredicate(communityTags.selectedTagsNames, model.tags)
|
||||||
}
|
}
|
||||||
|
expectedRoles: ["tags"]
|
||||||
},
|
},
|
||||||
FastExpressionFilter {
|
ValueFilter {
|
||||||
expression: !model.amIBanned
|
roleName: "amIBanned"
|
||||||
expectedRoles: ["amIBanned"]
|
value: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Core.Utils 0.1
|
import StatusQ.Core.Utils 0.1
|
||||||
@ -10,6 +11,8 @@ import StatusQ.Controls 0.1
|
|||||||
|
|
||||||
import AppLayouts.Communities.views 1.0
|
import AppLayouts.Communities.views 1.0
|
||||||
|
|
||||||
|
import SortFilterProxyModel 0.2
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmltype PermissionsRow
|
\qmltype PermissionsRow
|
||||||
\inherits Control
|
\inherits Control
|
||||||
@ -17,7 +20,7 @@ import AppLayouts.Communities.views 1.0
|
|||||||
\brief It is a permissions row control that provides information about community tokens permissions. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-controls2-control.html}{Control}.
|
\brief It is a permissions row control that provides information about community tokens permissions. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-controls2-control.html}{Control}.
|
||||||
|
|
||||||
The \c PermissionsRow is the token permissions representation row component.
|
The \c PermissionsRow is the token permissions representation row component.
|
||||||
It has different ui abreviations / permutations depending on the tokens and permissons the permissions model provides.
|
It has different ui abreviations / permutations depending on the tokens and permissions the permissions model provides.
|
||||||
|
|
||||||
Example of how to use it:
|
Example of how to use it:
|
||||||
\qml
|
\qml
|
||||||
@ -112,8 +115,22 @@ Control {
|
|||||||
|
|
||||||
property bool dotsVisible: false
|
property bool dotsVisible: false
|
||||||
|
|
||||||
|
readonly property var filteredModel: SortFilterProxyModel {
|
||||||
|
sourceModel: root.model
|
||||||
|
filters: FastExpressionFilter {
|
||||||
|
expression: {
|
||||||
|
if (model.isPrivate) {
|
||||||
|
return model.tokenCriteriaMet
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
expectedRoles: ["isPrivate", "tokenCriteriaMet"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function buildShortModel(model) {
|
function buildShortModel(model) {
|
||||||
shortModel.clear()
|
shortModel.clear()
|
||||||
|
dotsVisible = false
|
||||||
|
|
||||||
if(!model)
|
if(!model)
|
||||||
return
|
return
|
||||||
@ -170,7 +187,7 @@ Control {
|
|||||||
|
|
||||||
implicitHeight: 24
|
implicitHeight: 24
|
||||||
spacing: 4
|
spacing: 4
|
||||||
padding: 1
|
padding: 4
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: root.backgroundColor
|
color: root.backgroundColor
|
||||||
@ -179,19 +196,14 @@ Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
id: container
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
anchors.margins: root.padding
|
|
||||||
spacing: root.spacing
|
spacing: root.spacing
|
||||||
|
|
||||||
StatusIcon {
|
StatusIcon {
|
||||||
Layout.preferredHeight: container.height - 6
|
Layout.fillHeight: true
|
||||||
Layout.preferredWidth: Layout.preferredHeight
|
Layout.preferredWidth: height
|
||||||
Layout.leftMargin: 4
|
|
||||||
|
|
||||||
icon: root.requirementsMet ? "tiny/unlocked" : "tiny/locked"
|
icon: root.requirementsMet ? "tiny/unlocked" : "tiny/locked"
|
||||||
color: Theme.palette.baseColor1
|
color: root.hovered ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
@ -216,8 +228,8 @@ Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StatusRoundedComponent {
|
StatusRoundedComponent {
|
||||||
Layout.preferredHeight: container.height
|
Layout.fillHeight: true
|
||||||
Layout.preferredWidth: Layout.preferredHeight
|
Layout.preferredWidth: height
|
||||||
|
|
||||||
visible: d.dotsVisible
|
visible: d.dotsVisible
|
||||||
color: Theme.palette.baseColor3
|
color: Theme.palette.baseColor3
|
||||||
@ -232,21 +244,21 @@ Control {
|
|||||||
width: height
|
width: height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onModelChanged: d.buildShortModel(root.model)
|
StatusToolTip {
|
||||||
Connections {
|
text: root.requirementsMet ? qsTr("Eligible to join") : qsTr("Not eligible to join")
|
||||||
target: root.model
|
visible: root.hovered
|
||||||
function onCountChanged() {
|
|
||||||
d.buildShortModel(root.model)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onCompleted: d.buildShortModel(root.model)
|
|
||||||
|
ModelChangeTracker {
|
||||||
|
model: d.filteredModel
|
||||||
|
onRevisionChanged: d.buildShortModel(d.filteredModel)
|
||||||
|
}
|
||||||
|
|
||||||
ListModel { id: shortModel }
|
ListModel { id: shortModel }
|
||||||
|
|
||||||
|
component SinglePermissionRow: RowLayout {
|
||||||
component SinglePermissionRow: RowLayout {
|
|
||||||
id: singlePermissionItem
|
id: singlePermissionItem
|
||||||
|
|
||||||
readonly property int maxVisualTokens: 3
|
readonly property int maxVisualTokens: 3
|
||||||
@ -284,7 +296,7 @@ Control {
|
|||||||
Connections {
|
Connections {
|
||||||
target: singlePermissionItem.model
|
target: singlePermissionItem.model
|
||||||
function onCountChanged() {
|
function onCountChanged() {
|
||||||
buildTokensRowModel(singlePermissionItem.model)
|
singlePermissionItem.buildTokensRowModel(singlePermissionItem.model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onCompleted: buildTokensRowModel(singlePermissionItem.model)
|
Component.onCompleted: buildTokensRowModel(singlePermissionItem.model)
|
||||||
@ -300,8 +312,8 @@ Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StatusRoundedImage {
|
StatusRoundedImage {
|
||||||
Layout.preferredHeight: container.height
|
Layout.fillHeight: true
|
||||||
Layout.preferredWidth: Layout.preferredHeight
|
Layout.preferredWidth: height
|
||||||
|
|
||||||
z: index
|
z: index
|
||||||
image.source: model.imageSource
|
image.source: model.imageSource
|
||||||
@ -313,8 +325,8 @@ Control {
|
|||||||
|
|
||||||
StatusRoundedComponent {
|
StatusRoundedComponent {
|
||||||
visible: singlePermissionItem.plusElementVisible
|
visible: singlePermissionItem.plusElementVisible
|
||||||
Layout.preferredHeight: container.height
|
Layout.fillHeight: true
|
||||||
Layout.preferredWidth: Layout.preferredHeight
|
Layout.preferredWidth: height
|
||||||
|
|
||||||
z: d.maxTokens
|
z: d.maxTokens
|
||||||
color: Theme.palette.baseColor3
|
color: Theme.palette.baseColor3
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
|
|
||||||
import AppLayouts.Communities.controls 1.0
|
|
||||||
|
|
||||||
import StatusQ.Components 0.1
|
import StatusQ.Components 0.1
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
@ -11,6 +9,9 @@ import StatusQ.Popups 0.1
|
|||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
|
import AppLayouts.Communities.controls 1.0
|
||||||
|
import AppLayouts.Communities.helpers 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
@ -48,7 +49,8 @@ Item {
|
|||||||
delegate: StatusCommunityCard {
|
delegate: StatusCommunityCard {
|
||||||
id: profileDialogCommunityCard
|
id: profileDialogCommunityCard
|
||||||
readonly property var permissionsList: model.permissionsModel
|
readonly property var permissionsList: model.permissionsModel
|
||||||
readonly property bool requirementsMet: !!model.allTokenRequirementsMet ? model.allTokenRequirementsMet : false
|
readonly property bool isTokenGatedCommunity: PermissionsHelpers.isTokenGatedCommunity(permissionsList)
|
||||||
|
|
||||||
cardSize: StatusCommunityCard.Size.Small
|
cardSize: StatusCommunityCard.Size.Small
|
||||||
implicitWidth: GridView.view.cellWidth - Style.current.padding
|
implicitWidth: GridView.view.cellWidth - Style.current.padding
|
||||||
implicitHeight: GridView.view.cellHeight - Style.current.padding
|
implicitHeight: GridView.view.cellHeight - Style.current.padding
|
||||||
@ -60,7 +62,7 @@ Item {
|
|||||||
asset.width: 32
|
asset.width: 32
|
||||||
asset.height: 32
|
asset.height: 32
|
||||||
name: model.name ?? ""
|
name: model.name ?? ""
|
||||||
memberCountVisible: false
|
memberCountVisible: model.joined || !model.encrypted
|
||||||
banner: model.bannerImageData ?? ""
|
banner: model.bannerImageData ?? ""
|
||||||
descriptionFontSize: 12
|
descriptionFontSize: 12
|
||||||
descriptionFontColor: Theme.palette.baseColor1
|
descriptionFontColor: Theme.palette.baseColor1
|
||||||
@ -80,8 +82,7 @@ Item {
|
|||||||
// Community restrictions
|
// Community restrictions
|
||||||
bottomRowComponent: (model.joined && !root.readOnly) ?
|
bottomRowComponent: (model.joined && !root.readOnly) ?
|
||||||
communityMembershipComponent :
|
communityMembershipComponent :
|
||||||
!!profileDialogCommunityCard.permissionsList && profileDialogCommunityCard.permissionsList.count > 0 ?
|
isTokenGatedCommunity ? permissionsRowComponent : null
|
||||||
permissionsRowComponent : null
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: communityMembershipComponent
|
id: communityMembershipComponent
|
||||||
@ -116,13 +117,17 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: permissionsRowComponent
|
id: permissionsRowComponent
|
||||||
PermissionsRow {
|
PermissionsRow {
|
||||||
hoverEnabled: false
|
readonly property int eligibleToJoinAs: PermissionsHelpers.isEligibleToJoinAs(profileDialogCommunityCard.permissionsList)
|
||||||
|
|
||||||
assetsModel: root.globalAssetsModel
|
assetsModel: root.globalAssetsModel
|
||||||
collectiblesModel: root.globalCollectiblesModel
|
collectiblesModel: root.globalCollectiblesModel
|
||||||
model: profileDialogCommunityCard.permissionsList
|
model: profileDialogCommunityCard.permissionsList
|
||||||
requirementsMet: profileDialogCommunityCard.requirementsMet
|
requirementsMet: eligibleToJoinAs === PermissionTypes.Type.Member
|
||||||
|
|| eligibleToJoinAs === PermissionTypes.Type.Admin
|
||||||
|
|| eligibleToJoinAs === PermissionTypes.Type.Owner
|
||||||
backgroundBorderColor: Theme.palette.baseColor2
|
backgroundBorderColor: Theme.palette.baseColor2
|
||||||
backgroundRadius: 20
|
backgroundRadius: 20
|
||||||
|
fontPixelSize: 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +179,8 @@ Item {
|
|||||||
root.copyToClipboard(contextMenu.url)
|
root.copyToClipboard(contextMenu.url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClosed: destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user