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([
|
||||
{
|
||||
featured: true,
|
||||
featured: false,
|
||||
id: "id1",
|
||||
loaded: true,
|
||||
icon: ModelsData.icons.status,
|
||||
banner: ModelsData.banners.status,
|
||||
color: "blue",
|
||||
name: "Status.im",
|
||||
description: "Your portal to Web3. Secure wallet. dApp browser. Private messaging. All-in-one.",
|
||||
name: "Status.app",
|
||||
description: "Your portal to Web3. Secure wallet. Private messaging. Requires secret tokens to join",
|
||||
members: 130,
|
||||
activeMembers: 61,
|
||||
popularity: 4,
|
||||
|
@ -42,8 +42,8 @@ ListModel {
|
|||
"emoji": "💼",
|
||||
},
|
||||
]),
|
||||
permissionsModel: PermissionsModel.shortPermissionsModel,
|
||||
allTokenRequirementsMet: true
|
||||
permissionsModel: PermissionsModel.privatePermissionsMemberNotMetModel,
|
||||
allTokenRequirementsMet: false
|
||||
},
|
||||
{
|
||||
featured: true,
|
||||
|
@ -168,7 +168,7 @@ ListModel {
|
|||
},
|
||||
]),
|
||||
permissionsModel: PermissionsModel.threeShortPermissionsModel,
|
||||
allTokenRequirementsMet: true
|
||||
allTokenRequirementsMet: false
|
||||
},
|
||||
{
|
||||
featured: false,
|
||||
|
@ -218,7 +218,7 @@ ListModel {
|
|||
"emoji": "💼",
|
||||
},
|
||||
]),
|
||||
permissionsModel: PermissionsModel.longPermissionsModel,
|
||||
permissionsModel: PermissionsModel.twoLongPermissionsModel,
|
||||
allTokenRequirementsMet: true
|
||||
},
|
||||
{
|
||||
|
@ -235,7 +235,8 @@ ListModel {
|
|||
popularity: 4,
|
||||
available: true,
|
||||
tags: JSON.stringify([]),
|
||||
permissionsModel: emptyModel
|
||||
permissionsModel: emptyModel,
|
||||
allTokenRequirementsMet: false
|
||||
}
|
||||
])
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ SplitView {
|
|||
Popups {
|
||||
popupParent: root
|
||||
sharedRootStore: SharedStores.RootStore {}
|
||||
rootStore: AppLayoutStores.RootStore
|
||||
rootStore: AppLayoutStores.RootStore {}
|
||||
communityTokensStore: SharedStores.CommunityTokensStore {}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,22 @@ SplitView {
|
|||
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 {
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
|
||||
|
@ -139,7 +155,7 @@ SplitView {
|
|||
}
|
||||
|
||||
Label {
|
||||
text: "Row heigh:"
|
||||
text: "Row height:"
|
||||
}
|
||||
|
||||
Slider {
|
||||
|
|
|
@ -115,7 +115,7 @@ ListModel {
|
|||
members: [{ pubKey: "0xdeadbeef" }],
|
||||
membersCount: 1,
|
||||
loading: false,
|
||||
permissionsModel: null,
|
||||
permissionsModel: PermissionsModel.privatePermissionsMemberNotMetModel,
|
||||
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: [
|
||||
{
|
||||
|
@ -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 ModelChangeGuard guard: ModelChangeGuard {
|
||||
model: root.shortPermissionsModel
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
@ -71,21 +71,19 @@ StatusSectionLayout {
|
|||
sourceModel: root.communitiesStore.curatedCommunitiesModel
|
||||
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
enabled: d.searchMode
|
||||
expression: {
|
||||
searcher.text
|
||||
return name.toLowerCase().includes(searcher.text.toLowerCase())
|
||||
}
|
||||
SQUtils.SearchFilter {
|
||||
roleName: "name"
|
||||
searchPhrase: searcher.text
|
||||
},
|
||||
ExpressionFilter {
|
||||
FastExpressionFilter {
|
||||
expression: {
|
||||
return filteredCommunitiesModel.selectedTagsPredicate(communityTags.selectedTagsNames, model.tags)
|
||||
}
|
||||
expectedRoles: ["tags"]
|
||||
},
|
||||
FastExpressionFilter {
|
||||
expression: !model.amIBanned
|
||||
expectedRoles: ["amIBanned"]
|
||||
ValueFilter {
|
||||
roleName: "amIBanned"
|
||||
value: false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
@ -10,6 +11,8 @@ import StatusQ.Controls 0.1
|
|||
|
||||
import AppLayouts.Communities.views 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
/*!
|
||||
\qmltype PermissionsRow
|
||||
\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}.
|
||||
|
||||
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:
|
||||
\qml
|
||||
|
@ -112,8 +115,22 @@ Control {
|
|||
|
||||
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) {
|
||||
shortModel.clear()
|
||||
dotsVisible = false
|
||||
|
||||
if(!model)
|
||||
return
|
||||
|
@ -170,7 +187,7 @@ Control {
|
|||
|
||||
implicitHeight: 24
|
||||
spacing: 4
|
||||
padding: 1
|
||||
padding: 4
|
||||
|
||||
background: Rectangle {
|
||||
color: root.backgroundColor
|
||||
|
@ -179,19 +196,14 @@ Control {
|
|||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
id: container
|
||||
|
||||
anchors.centerIn: parent
|
||||
anchors.margins: root.padding
|
||||
spacing: root.spacing
|
||||
|
||||
StatusIcon {
|
||||
Layout.preferredHeight: container.height - 6
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
Layout.leftMargin: 4
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
|
||||
icon: root.requirementsMet ? "tiny/unlocked" : "tiny/locked"
|
||||
color: Theme.palette.baseColor1
|
||||
color: root.hovered ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
Repeater {
|
||||
|
@ -216,8 +228,8 @@ Control {
|
|||
}
|
||||
|
||||
StatusRoundedComponent {
|
||||
Layout.preferredHeight: container.height
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
|
||||
visible: d.dotsVisible
|
||||
color: Theme.palette.baseColor3
|
||||
|
@ -232,21 +244,21 @@ Control {
|
|||
width: height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onModelChanged: d.buildShortModel(root.model)
|
||||
Connections {
|
||||
target: root.model
|
||||
function onCountChanged() {
|
||||
d.buildShortModel(root.model)
|
||||
StatusToolTip {
|
||||
text: root.requirementsMet ? qsTr("Eligible to join") : qsTr("Not eligible to join")
|
||||
visible: root.hovered
|
||||
}
|
||||
}
|
||||
Component.onCompleted: d.buildShortModel(root.model)
|
||||
|
||||
ModelChangeTracker {
|
||||
model: d.filteredModel
|
||||
onRevisionChanged: d.buildShortModel(d.filteredModel)
|
||||
}
|
||||
|
||||
ListModel { id: shortModel }
|
||||
|
||||
|
||||
component SinglePermissionRow: RowLayout {
|
||||
component SinglePermissionRow: RowLayout {
|
||||
id: singlePermissionItem
|
||||
|
||||
readonly property int maxVisualTokens: 3
|
||||
|
@ -284,7 +296,7 @@ Control {
|
|||
Connections {
|
||||
target: singlePermissionItem.model
|
||||
function onCountChanged() {
|
||||
buildTokensRowModel(singlePermissionItem.model)
|
||||
singlePermissionItem.buildTokensRowModel(singlePermissionItem.model)
|
||||
}
|
||||
}
|
||||
Component.onCompleted: buildTokensRowModel(singlePermissionItem.model)
|
||||
|
@ -300,8 +312,8 @@ Control {
|
|||
}
|
||||
|
||||
StatusRoundedImage {
|
||||
Layout.preferredHeight: container.height
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
|
||||
z: index
|
||||
image.source: model.imageSource
|
||||
|
@ -313,8 +325,8 @@ Control {
|
|||
|
||||
StatusRoundedComponent {
|
||||
visible: singlePermissionItem.plusElementVisible
|
||||
Layout.preferredHeight: container.height
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
|
||||
z: d.maxTokens
|
||||
color: Theme.palette.baseColor3
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import AppLayouts.Communities.controls 1.0
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
|
@ -11,6 +9,9 @@ import StatusQ.Popups 0.1
|
|||
|
||||
import utils 1.0
|
||||
|
||||
import AppLayouts.Communities.controls 1.0
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
|
@ -48,7 +49,8 @@ Item {
|
|||
delegate: StatusCommunityCard {
|
||||
id: profileDialogCommunityCard
|
||||
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
|
||||
implicitWidth: GridView.view.cellWidth - Style.current.padding
|
||||
implicitHeight: GridView.view.cellHeight - Style.current.padding
|
||||
|
@ -60,7 +62,7 @@ Item {
|
|||
asset.width: 32
|
||||
asset.height: 32
|
||||
name: model.name ?? ""
|
||||
memberCountVisible: false
|
||||
memberCountVisible: model.joined || !model.encrypted
|
||||
banner: model.bannerImageData ?? ""
|
||||
descriptionFontSize: 12
|
||||
descriptionFontColor: Theme.palette.baseColor1
|
||||
|
@ -80,8 +82,7 @@ Item {
|
|||
// Community restrictions
|
||||
bottomRowComponent: (model.joined && !root.readOnly) ?
|
||||
communityMembershipComponent :
|
||||
!!profileDialogCommunityCard.permissionsList && profileDialogCommunityCard.permissionsList.count > 0 ?
|
||||
permissionsRowComponent : null
|
||||
isTokenGatedCommunity ? permissionsRowComponent : null
|
||||
|
||||
Component {
|
||||
id: communityMembershipComponent
|
||||
|
@ -116,13 +117,17 @@ Item {
|
|||
Component {
|
||||
id: permissionsRowComponent
|
||||
PermissionsRow {
|
||||
hoverEnabled: false
|
||||
readonly property int eligibleToJoinAs: PermissionsHelpers.isEligibleToJoinAs(profileDialogCommunityCard.permissionsList)
|
||||
|
||||
assetsModel: root.globalAssetsModel
|
||||
collectiblesModel: root.globalCollectiblesModel
|
||||
model: profileDialogCommunityCard.permissionsList
|
||||
requirementsMet: profileDialogCommunityCard.requirementsMet
|
||||
requirementsMet: eligibleToJoinAs === PermissionTypes.Type.Member
|
||||
|| eligibleToJoinAs === PermissionTypes.Type.Admin
|
||||
|| eligibleToJoinAs === PermissionTypes.Type.Owner
|
||||
backgroundBorderColor: Theme.palette.baseColor2
|
||||
backgroundRadius: 20
|
||||
fontPixelSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,6 +179,8 @@ Item {
|
|||
root.copyToClipboard(contextMenu.url)
|
||||
}
|
||||
}
|
||||
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue