fix: can't join an encrypted community
- fix the corner case and allow the user to join a community without an explicitely stated "Member" permission - enable/disable the Share/Join/Save buttons when the permission to join check is ongoing, or when the permission check failed - display tooltips over the disabled buttons explaining why it's disabled - always display the eligibility button floating on top of the (scrollable) contents Fixes #14473 Fixes #14299
This commit is contained in:
parent
78acdca225
commit
0c8231a6b6
|
@ -55,6 +55,7 @@ SplitView {
|
|||
|
||||
isInvitationPending: ctrlIsInvitationPending.checked
|
||||
requirementsCheckPending: ctrlRequirementsCheckPending.checked
|
||||
joinPermissionsCheckSuccessful: ctrlJoinPermissionsCheckSuccessful.checked
|
||||
|
||||
walletAccountsModel: WalletAccountsModel {}
|
||||
walletAssetsModel: root.walletAssetStore.groupedAccountAssetsModel
|
||||
|
@ -80,7 +81,7 @@ SplitView {
|
|||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
SplitView.fillWidth: true
|
||||
|
@ -218,6 +219,14 @@ Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
|
|||
text: "Requirements check pending"
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
Layout.leftMargin: 12
|
||||
id: ctrlJoinPermissionsCheckSuccessful
|
||||
visible: !ctrlIsInvitationPending.checked
|
||||
text: "Join permission successful"
|
||||
checked: true
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ ToolTip {
|
|||
|
||||
implicitWidth: Math.min(maxWidth, implicitContentWidth + 16)
|
||||
padding: 8
|
||||
margins: 8
|
||||
delay: 200
|
||||
background: Item {
|
||||
id: statusToolTipBackground
|
||||
|
|
|
@ -21,10 +21,11 @@ Dialog {
|
|||
\qmlproperty color backgroundColor
|
||||
This property decides the modal background color
|
||||
*/
|
||||
property string backgroundColor: Theme.palette.statusModal.backgroundColor
|
||||
property color backgroundColor: Theme.palette.statusModal.backgroundColor
|
||||
/*!
|
||||
\qmlproperty closeHandler
|
||||
This property decides the action to be performed when the close button is clicked. It allows to define
|
||||
a custom function to be called when the popup is closed by the user.
|
||||
*/
|
||||
property var closeHandler: root.close
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
int roleByName(QAbstractItemModel* model, const QString &roleName)
|
||||
constexpr int roleByName(QAbstractItemModel* model, const QString &roleName)
|
||||
{
|
||||
if (!model)
|
||||
return -1;
|
||||
|
@ -161,18 +161,23 @@ int /*PermissionTypes::Type*/ PermissionUtilsInternal::isEligibleToJoinAs(QAbstr
|
|||
}
|
||||
|
||||
QSet<PermissionTypes::Type> tmpRes;
|
||||
bool hasAnyJoinPermission{false};
|
||||
bool hasMemberPermission{false};
|
||||
constexpr auto isJoinTypePermission = [](PermissionTypes::Type type) {
|
||||
return type == PermissionTypes::Type::TokenMaster ||
|
||||
type == PermissionTypes::Type::Admin ||
|
||||
type == PermissionTypes::Type::Member;
|
||||
};
|
||||
|
||||
constexpr auto isMemberPermission = [](PermissionTypes::Type type) {
|
||||
return type == PermissionTypes::Type::Member;
|
||||
};
|
||||
|
||||
const auto permissionsCount = permissionsModel->rowCount();
|
||||
for (int i = 0; i < permissionsCount; i++) {
|
||||
const auto permissionType = static_cast<PermissionTypes::Type>(permissionsModel->data(permissionsModel->index(i, 0), permissionTypeRole).toInt());
|
||||
if (isJoinTypePermission(permissionType)) {
|
||||
hasAnyJoinPermission = true;
|
||||
if (isMemberPermission(permissionType))
|
||||
hasMemberPermission = true;
|
||||
const auto tokenCriteriaMet = permissionsModel->data(permissionsModel->index(i, 0), tokenCriteriaMetRole).toBool();
|
||||
if (tokenCriteriaMet) {
|
||||
tmpRes.insert(permissionType);
|
||||
|
@ -180,16 +185,13 @@ int /*PermissionTypes::Type*/ PermissionUtilsInternal::isEligibleToJoinAs(QAbstr
|
|||
}
|
||||
}
|
||||
|
||||
if (!hasAnyJoinPermission)
|
||||
return PermissionTypes::Type::Member;
|
||||
|
||||
if (tmpRes.contains(PermissionTypes::Type::TokenMaster))
|
||||
return PermissionTypes::Type::TokenMaster;
|
||||
|
||||
if (tmpRes.contains(PermissionTypes::Type::Admin))
|
||||
return PermissionTypes::Type::Admin;
|
||||
|
||||
if (tmpRes.contains(PermissionTypes::Type::Member))
|
||||
if (tmpRes.contains(PermissionTypes::Type::Member) || !hasMemberPermission)
|
||||
return PermissionTypes::Type::Member;
|
||||
|
||||
return PermissionTypes::Type::None;
|
||||
|
|
|
@ -621,6 +621,7 @@ QtObject {
|
|||
readonly property string image: model.image
|
||||
readonly property bool joined: model.joined
|
||||
readonly property bool amIBanned: model.amIBanned
|
||||
readonly property string introMessage: model.introMessage
|
||||
// add others when needed..
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ Control {
|
|||
required property int /*PermissionTypes.Type*/ eligibleToJoinAs
|
||||
|
||||
property bool requirementsCheckPending: false
|
||||
property bool joinPermissionsCheckSuccessful
|
||||
|
||||
required property string communityId
|
||||
required property string communityName
|
||||
|
@ -101,11 +102,27 @@ Control {
|
|||
onClicked: root.close()
|
||||
}
|
||||
|
||||
readonly property var saveButton: StatusButton {
|
||||
enabled: d.dirty
|
||||
type: d.lostCommunityPermission || d.lostChannelPermissions ? StatusBaseButton.Type.Danger : StatusBaseButton.Type.Normal
|
||||
visible: root.isEditMode
|
||||
readonly property string tooltipText: {
|
||||
if (root.requirementsCheckPending)
|
||||
return qsTr("Requirements check pending")
|
||||
|
||||
if (!root.joinPermissionsCheckSuccessful)
|
||||
return qsTr("Checking permissions to join failed")
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
readonly property var saveButton: StatusButton {
|
||||
visible: root.isEditMode
|
||||
interactive: d.dirty && !root.requirementsCheckPending && root.joinPermissionsCheckSuccessful
|
||||
loading: root.requirementsCheckPending
|
||||
type: d.lostCommunityPermission || d.lostChannelPermissions ? StatusBaseButton.Type.Danger : StatusBaseButton.Type.Normal
|
||||
tooltip.text: {
|
||||
if (interactive)
|
||||
return ""
|
||||
|
||||
return d.tooltipText
|
||||
}
|
||||
text: {
|
||||
if (d.lostCommunityPermission) {
|
||||
return qsTr("Save changes & leave %1").arg(root.communityName)
|
||||
|
@ -147,7 +164,14 @@ Control {
|
|||
|
||||
readonly property var shareAddressesButton: StatusButton {
|
||||
visible: !root.isEditMode
|
||||
enabled: root.eligibleToJoinAs !== PermissionTypes.Type.None
|
||||
interactive: root.eligibleToJoinAs !== PermissionTypes.Type.None && root.joinPermissionsCheckSuccessful
|
||||
loading: root.requirementsCheckPending
|
||||
tooltip.text: {
|
||||
if (interactive)
|
||||
return ""
|
||||
|
||||
return d.tooltipText
|
||||
}
|
||||
text: {
|
||||
if (d.selectedSharedAddressesCount === root.totalNumOfAddressesForSharing) {
|
||||
return qsTr("Share all addresses to join")
|
||||
|
@ -306,6 +330,7 @@ Control {
|
|||
assetsModel: root.assetsModel
|
||||
collectiblesModel: root.collectiblesModel
|
||||
requirementsCheckPending: root.requirementsCheckPending
|
||||
joinPermissionsCheckSuccessful: root.joinPermissionsCheckSuccessful
|
||||
communityName: root.communityName
|
||||
communityIcon: root.communityIcon
|
||||
eligibleToJoinAs: root.eligibleToJoinAs
|
||||
|
|
|
@ -32,6 +32,7 @@ Rectangle {
|
|||
property var collectiblesModel
|
||||
|
||||
property bool requirementsCheckPending
|
||||
property bool joinPermissionsCheckSuccessful
|
||||
|
||||
readonly property bool lostPermissionToJoin: d.lostPermissionToJoin
|
||||
readonly property bool lostChannelPermissions: d.lostChannelPermissions
|
||||
|
@ -256,6 +257,7 @@ Rectangle {
|
|||
|
||||
CommunityEligibilityTag {
|
||||
id: eligibilityHintBubble
|
||||
visible: !root.requirementsCheckPending && root.joinPermissionsCheckSuccessful
|
||||
eligibleToJoinAs: root.eligibleToJoinAs
|
||||
isEditMode: root.isEditMode
|
||||
isDirty: root.isDirty
|
||||
|
|
|
@ -18,6 +18,8 @@ QtObject {
|
|||
property var communitiesModuleInst: communitiesModule
|
||||
property bool newVersionAvailable: false
|
||||
readonly property bool requirementsCheckPending: communitiesModuleInst.requirementsCheckPending
|
||||
readonly property bool joinPermissionsCheckSuccessful: communitiesModuleInst.joinPermissionsCheckSuccessful
|
||||
readonly property bool channelsPermissionsCheckSuccessful: communitiesModuleInst.channelsPermissionsCheckSuccessful
|
||||
property string latestVersion
|
||||
property string downloadURL
|
||||
|
||||
|
|
|
@ -705,6 +705,7 @@ QtObject {
|
|||
id: dialogRoot
|
||||
|
||||
requirementsCheckPending: root.rootStore.requirementsCheckPending
|
||||
joinPermissionsCheckSuccessful: root.rootStore.joinPermissionsCheckSuccessful
|
||||
|
||||
walletAccountsModel: root.rootStore.walletAccountsModel
|
||||
walletCollectiblesModel: WalletStore.RootStore.collectiblesStore.allCollectiblesModel
|
||||
|
@ -952,7 +953,9 @@ QtObject {
|
|||
|
||||
communityName: chatStore.sectionDetails.name
|
||||
communityIcon: chatStore.sectionDetails.image
|
||||
|
||||
requirementsCheckPending: root.rootStore.requirementsCheckPending
|
||||
joinPermissionsCheckSuccessful: root.rootStore.joinPermissionsCheckSuccessful
|
||||
|
||||
introMessage: chatStore.sectionDetails.introMessage
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ StatusStackModal {
|
|||
required property string communityIcon
|
||||
required property bool requirementsCheckPending
|
||||
|
||||
property bool joinPermissionsCheckSuccessful
|
||||
|
||||
property string introMessage
|
||||
|
||||
property bool isInvitationPending: false
|
||||
|
@ -84,12 +86,31 @@ StatusStackModal {
|
|||
rightButtons: [d.shareButton, finishButton]
|
||||
|
||||
finishButton: StatusButton {
|
||||
enabled: {
|
||||
if (root.isInvitationPending || d.accessType !== Constants.communityChatOnRequestAccess)
|
||||
interactive: {
|
||||
if (root.isInvitationPending)
|
||||
return true
|
||||
|
||||
if (root.requirementsCheckPending || !root.joinPermissionsCheckSuccessful)
|
||||
return false
|
||||
|
||||
if (d.accessType !== Constants.communityChatOnRequestAccess)
|
||||
return true
|
||||
|
||||
return d.eligibleToJoinAs !== PermissionTypes.Type.None
|
||||
}
|
||||
loading: root.requirementsCheckPending && !root.isInvitationPending
|
||||
tooltip.text: {
|
||||
if (interactive)
|
||||
return ""
|
||||
|
||||
if (root.requirementsCheckPending)
|
||||
return qsTr("Requirements check pending")
|
||||
|
||||
if (!root.joinPermissionsCheckSuccessful)
|
||||
return qsTr("Checking permissions to join failed")
|
||||
|
||||
return ""
|
||||
}
|
||||
text: {
|
||||
if (root.isInvitationPending) {
|
||||
return qsTr("Cancel Membership Request")
|
||||
|
@ -269,7 +290,7 @@ StatusStackModal {
|
|||
d.selectedSharedAddressesMap = tmpMap
|
||||
}
|
||||
|
||||
// Returns an object containing all selected addresses and selected airdrop address.s
|
||||
// Returns an object containing all selected addresses and selected airdrop address
|
||||
function getSelectedAddresses() {
|
||||
const result = {addresses: [], airdropAddress: ""}
|
||||
for (const [key, value] of d.selectedSharedAddressesMap) {
|
||||
|
@ -341,6 +362,7 @@ StatusStackModal {
|
|||
communityName: root.communityName
|
||||
communityIcon: root.communityIcon
|
||||
requirementsCheckPending: root.requirementsCheckPending
|
||||
joinPermissionsCheckSuccessful: root.joinPermissionsCheckSuccessful
|
||||
|
||||
walletAccountsModel: d.initialAddressesModel
|
||||
|
||||
|
@ -416,36 +438,47 @@ StatusStackModal {
|
|||
}
|
||||
|
||||
stackItems: [
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
contentWidth: availableWidth
|
||||
Item {
|
||||
implicitHeight: scrollView.contentHeight + scrollView.bottomPadding + eligibilityTag.anchors.bottomMargin
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 24
|
||||
width: scrollView.availableWidth
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
anchors.fill: parent
|
||||
contentWidth: availableWidth
|
||||
bottomPadding: 80
|
||||
|
||||
StatusRoundedImage {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 64
|
||||
Layout.preferredHeight: Layout.preferredWidth
|
||||
visible: ((image.status == Image.Loading) ||
|
||||
(image.status == Image.Ready)) &&
|
||||
!image.isError
|
||||
image.source: root.communityIcon
|
||||
ColumnLayout {
|
||||
spacing: Style.current.bigPadding
|
||||
width: parent.width
|
||||
|
||||
StatusRoundedImage {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 64
|
||||
Layout.preferredHeight: Layout.preferredWidth
|
||||
visible: ((image.status == Image.Loading) ||
|
||||
(image.status == Image.Ready)) &&
|
||||
!image.isError
|
||||
image.source: root.communityIcon
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
text: root.introMessage || qsTr("Community <b>%1</b> has no intro message...").arg(root.communityName)
|
||||
color: Theme.palette.directColor1
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
text: root.introMessage || qsTr("Community <b>%1</b> has no intro message...").arg(root.communityName)
|
||||
color: Theme.palette.directColor1
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
CommunityEligibilityTag {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
eligibleToJoinAs: d.eligibleToJoinAs
|
||||
visible: !root.isInvitationPending && d.accessType === Constants.communityChatOnRequestAccess
|
||||
}
|
||||
CommunityEligibilityTag {
|
||||
id: eligibilityTag
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: Style.current.bigPadding
|
||||
eligibleToJoinAs: d.eligibleToJoinAs
|
||||
isEditMode: root.isEditMode
|
||||
visible: !root.isInvitationPending && !root.requirementsCheckPending && root.joinPermissionsCheckSuccessful &&
|
||||
d.accessType === Constants.communityChatOnRequestAccess
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue