feat: Add missing eligible to join tag in CommunityMembershipSetupDialog
- implement the eligibility check in C++, returning the highest possible role the user would be allowed to join under - enable/disable the "Share" button based on the above permissions check - remove all the locally placed components, access teh popup only via Global/Popups - calculate the `accessType` internally based on the permissions present - update the eligibility as the async check for permissions is finished - fix the permissions panel background color - partially revert the share/finish/cancel buttons behavior; it must be one button due to StatusStackModal limitations - fix some other minor UI issues or differences to current Figma designs - adjust SB, add the possibility to play around with different permission models Fixes #14100
This commit is contained in:
parent
255f318627
commit
b191caaec6
|
@ -137,6 +137,8 @@ QtObject:
|
|||
|
||||
return self.items[idx]
|
||||
|
||||
proc tokenCriteriaUpdated(self: TokenPermissionsModel) {.signal.}
|
||||
|
||||
proc updateItem*(self: TokenPermissionsModel, permissionId: string, item: TokenPermissionItem) =
|
||||
let idx = self.findIndexById(permissionId)
|
||||
if(idx == -1):
|
||||
|
@ -159,3 +161,4 @@ QtObject:
|
|||
ModelRole.TokenCriteriaMet.int,
|
||||
ModelRole.State.int
|
||||
])
|
||||
self.tokenCriteriaUpdated()
|
||||
|
|
|
@ -23,49 +23,41 @@ SplitView {
|
|||
assetsWithFilteredBalances: groupedAccountsAssetsModel
|
||||
}
|
||||
|
||||
Item {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
function openDialog() {
|
||||
popupComponent.createObject(popupBg)
|
||||
}
|
||||
|
||||
PopupBackground {
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.centerIn: parent
|
||||
text: "Reopen"
|
||||
|
||||
onClicked: dialog.open()
|
||||
}
|
||||
Component.onCompleted: openDialog()
|
||||
|
||||
Component {
|
||||
id: popupComponent
|
||||
CommunityMembershipSetupDialog {
|
||||
id: dialog
|
||||
|
||||
anchors.centerIn: parent
|
||||
visible: true
|
||||
modal: false
|
||||
visible: true
|
||||
closePolicy: Popup.NoAutoClose
|
||||
|
||||
isEditMode: ctrlIsEditMode.checked
|
||||
communityName: "Status"
|
||||
communityIcon: ModelsData.icons.status
|
||||
introMessage: "%1 sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
communityName: ctrlCommunityName.text
|
||||
communityIcon: {
|
||||
if (ctrlIconStatus.checked)
|
||||
return ModelsData.icons.status
|
||||
if (ctrlIconCryptoPunks.checked)
|
||||
return ModelsData.icons.cryptPunks
|
||||
if (ctrlIconRarible.checked)
|
||||
return ModelsData.icons.rarible
|
||||
if (ctrlIconNone.checked)
|
||||
return ""
|
||||
}
|
||||
|
||||
1. Ut enim ad minim veniam
|
||||
2. Excepteur sint occaecat cupidatat non proident
|
||||
3. Duis aute irure
|
||||
4. Dolore eu fugiat nulla pariatur
|
||||
5. 🚗 consectetur adipiscing elit
|
||||
|
||||
Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.".arg(dialog.communityName)
|
||||
introMessage: ctrlIntro.text.arg(communityName)
|
||||
|
||||
isInvitationPending: ctrlIsInvitationPending.checked
|
||||
requirementsCheckPending: ctrlRequirementsCheckPending.checked
|
||||
|
||||
walletAccountsModel: WalletAccountsModel {}
|
||||
walletAssetsModel: root.walletAssetStore.groupedAccountAssetsModel
|
||||
permissionsModel: dialog.accessType === Constants.communityChatOnRequestAccess ? PermissionsModel.complexPermissionsModel
|
||||
: null
|
||||
permissionsModel: ctrlPermissionsModel.currentValue
|
||||
assetsModel: AssetsModel {}
|
||||
collectiblesModel: CollectiblesModel {}
|
||||
|
||||
|
@ -86,6 +78,23 @@ Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
|
|||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
PopupBackground {
|
||||
id: popupBg
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.centerIn: parent
|
||||
text: "Reopen"
|
||||
|
||||
onClicked: root.openDialog()
|
||||
}
|
||||
}
|
||||
|
||||
LogsAndControlsPanel {
|
||||
|
@ -112,21 +121,29 @@ Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
|
|||
}
|
||||
|
||||
TextField {
|
||||
id: ctrlCommunityName
|
||||
Layout.fillWidth: true
|
||||
text: dialog.communityName
|
||||
onTextChanged: dialog.communityName = text
|
||||
text: "Status"
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: "Intro message"
|
||||
text: "Intro"
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: ctrlIntro
|
||||
Layout.fillWidth: true
|
||||
text: dialog.introMessage
|
||||
onTextChanged: dialog.introMessage = text
|
||||
text: "%1 sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
|
||||
1. Ut enim ad minim veniam
|
||||
2. Excepteur sint occaecat cupidatat non proident
|
||||
3. Duis aute irure
|
||||
4. Dolore eu fugiat nulla pariatur
|
||||
5. 🚗 consectetur adipiscing elit
|
||||
|
||||
Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt."
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
|
@ -136,21 +153,21 @@ Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
|
|||
font.weight: Font.Bold
|
||||
}
|
||||
RadioButton {
|
||||
id: ctrlIconStatus
|
||||
checked: true
|
||||
text: "Status"
|
||||
onCheckedChanged: if(checked) dialog.communityIcon = ModelsData.icons.status
|
||||
}
|
||||
RadioButton {
|
||||
id: ctrlIconCryptoPunks
|
||||
text: "Crypto Punks"
|
||||
onCheckedChanged: if(checked) dialog.communityIcon = ModelsData.icons.cryptPunks
|
||||
}
|
||||
RadioButton {
|
||||
id: ctrlIconRarible
|
||||
text: "Rarible"
|
||||
onCheckedChanged: if(checked) dialog.communityIcon = ModelsData.icons.rarible
|
||||
}
|
||||
RadioButton {
|
||||
id: ctrlIconNone
|
||||
text: "None"
|
||||
onCheckedChanged: if(checked) dialog.communityIcon = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,31 +178,41 @@ Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
|
|||
|
||||
CheckBox {
|
||||
id: ctrlIsEditMode
|
||||
visible: !dialog.isInvitationPending
|
||||
visible: !ctrlIsInvitationPending.checked
|
||||
text: "Is edit mode"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: !dialog.isInvitationPending
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: "Access type:"
|
||||
}
|
||||
visible: !ctrlIsInvitationPending.checked
|
||||
|
||||
RadioButton {
|
||||
checked: true
|
||||
text: qsTr("Public access")
|
||||
onCheckedChanged: dialog.accessType = Constants.communityChatPublicAccess
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("On request")
|
||||
onCheckedChanged: dialog.accessType = Constants.communityChatOnRequestAccess
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 12
|
||||
Label {
|
||||
text: "Permissions:"
|
||||
}
|
||||
ComboBox {
|
||||
Layout.fillWidth: true
|
||||
id: ctrlPermissionsModel
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
model: [
|
||||
{ value: PermissionsModel.complexCombinedPermissionsModel, text: "complexCombined" },
|
||||
{ value: PermissionsModel.complexCombinedPermissionsModelNotMet, text: "complexCombinedNotMet" },
|
||||
{ value: PermissionsModel.complexPermissionsModel, text: "complex" },
|
||||
{ value: PermissionsModel.complexPermissionsModelNotMet, text: "complexNotMet" },
|
||||
{ value: PermissionsModel.channelsOnlyPermissionsModel, text: "channelsOnly" },
|
||||
{ value: PermissionsModel.channelsOnlyPermissionsModelNotMet, text: "channelsOnlyNotMet" },
|
||||
{ value: null, text: "null" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
Layout.leftMargin: 12
|
||||
id: ctrlRequirementsCheckPending
|
||||
visible: !dialog.isInvitationPending && dialog.accessType == Constants.communityChatOnRequestAccess
|
||||
visible: !ctrlIsInvitationPending.checked
|
||||
text: "Requirements check pending"
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,24 @@ ListModel {
|
|||
symbol: "SNT",
|
||||
category: TokenCategories.Category.General,
|
||||
communityId: ""
|
||||
},
|
||||
{
|
||||
key: "stt",
|
||||
iconSource: ModelsData.assets.snt,
|
||||
name: "stt",
|
||||
shortName: "stt",
|
||||
symbol: "STT",
|
||||
category: TokenCategories.Category.Own,
|
||||
communityId: ""
|
||||
},
|
||||
{
|
||||
key: "eth",
|
||||
iconSource: ModelsData.assets.eth,
|
||||
name: "eth",
|
||||
shortName: "eth",
|
||||
symbol: "ETH",
|
||||
category: TokenCategories.Category.General,
|
||||
communityId: ""
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -239,6 +239,22 @@ QtObject {
|
|||
isPrivate: false,
|
||||
tokenCriteriaMet: false
|
||||
},
|
||||
{
|
||||
id: "tmaster1",
|
||||
holdingsListModel: root.createHoldingsModel2(),
|
||||
permissionType: PermissionTypes.Type.TokenMaster,
|
||||
permissionState: PermissionTypes.State.Approved,
|
||||
isPrivate: false,
|
||||
tokenCriteriaMet: true
|
||||
},
|
||||
{
|
||||
id: "tmaster2",
|
||||
holdingsListModel: root.createHoldingsModel3(),
|
||||
permissionType: PermissionTypes.Type.TokenMaster,
|
||||
permissionState: PermissionTypes.State.Approved,
|
||||
isPrivate: false,
|
||||
tokenCriteriaMet: false
|
||||
},
|
||||
{
|
||||
id: "member1",
|
||||
holdingsListModel: root.createHoldingsModel2(),
|
||||
|
@ -276,6 +292,14 @@ QtObject {
|
|||
isPrivate: false,
|
||||
tokenCriteriaMet: false
|
||||
},
|
||||
{
|
||||
id: "tmaster1",
|
||||
holdingsListModel: root.createHoldingsModel2(),
|
||||
permissionType: PermissionTypes.Type.TokenMaster,
|
||||
permissionState: PermissionTypes.State.Approved,
|
||||
isPrivate: false,
|
||||
tokenCriteriaMet: false
|
||||
},
|
||||
{
|
||||
id: "member1",
|
||||
holdingsListModel: root.createHoldingsModel1(),
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
|
||||
class QAbstractItemModel;
|
||||
|
||||
namespace PermissionTypes {
|
||||
enum Type { NoPermissions = -1, None = 0, Admin, Member, Read, ViewAndPost, TokenMaster, Owner };
|
||||
}
|
||||
|
||||
class PermissionUtilsInternal : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -18,4 +22,12 @@ public:
|
|||
//!< traverse the permissions @p model, and look for unique channels recursively under channelsListModel->key; filtering out @p permissionTypes ([PermissionTypes.Type.FOO])
|
||||
//! @return an array of `array<key,channelName>`, sorted by `channelName`
|
||||
Q_INVOKABLE QJsonArray getUniquePermissionChannels(QAbstractItemModel *model, const QList<int> &permissionTypes = {}) const;
|
||||
|
||||
//!< Check whether the user can join the community and under which (highest possible) role
|
||||
//!< @return either:
|
||||
//! - `NoPermissions` if the permissionsModel is empty or malformed
|
||||
//! - `Member` if no such join permission(s) exist in the permissionsModel (e.g. when it has channel only permissions)
|
||||
//! - if satisfied: `TokenMaster`, `Admin`, or `Member`, in this order of relevance
|
||||
//! - `None` if no permission to join is satisfied (user can't join at all)
|
||||
Q_INVOKABLE int /*PermissionTypes::Type*/ isEligibleToJoinAs(QAbstractItemModel *permissionsModel) const;
|
||||
};
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
<file>assets/img/icons/tiny/tiny-checkmark.svg</file>
|
||||
<file>assets/img/icons/tiny/tiny-contact.svg</file>
|
||||
<file>assets/img/icons/tiny/tiny-exclamation.svg</file>
|
||||
<file>assets/img/icons/tiny/token-master.svg</file>
|
||||
<file>assets/img/icons/tiny/tribute-to-talk.svg</file>
|
||||
<file>assets/img/icons/tiny/unlocked.svg</file>
|
||||
<file>assets/img/icons/tiny/warning.svg</file>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 6.51587C13.5 6.85724 13.2457 7.4564 12.2033 8.05443C11.2022 8.62875 9.71934 9.03175 8 9.03175C6.28066 9.03175 4.79778 8.62875 3.79668 8.05443C2.75427 7.4564 2.5 6.85724 2.5 6.51587C2.5 6.1745 2.75427 5.57534 3.79668 4.97731C4.79778 4.40299 6.28066 4 8 4C9.71934 4 11.2022 4.40299 12.2033 4.97731C13.2457 5.57534 13.5 6.1745 13.5 6.51587ZM13.5 9.48413C13.5 9.26091 13.2309 9.18924 13.0391 9.30335C11.7659 10.0607 9.97884 10.5317 8 10.5317C6.02116 10.5317 4.2341 10.0607 2.96094 9.30335C2.7691 9.18924 2.5 9.26091 2.5 9.48413C2.5 9.8255 2.75427 10.4247 3.79668 11.0227C4.79778 11.597 6.28066 12 8 12C9.71934 12 11.2022 11.597 12.2033 11.0227C13.2457 10.4247 13.5 9.8255 13.5 9.48413ZM15 6.51587V9.48413V9.49997C15 9.49999 15 9.5 15 9.5C15 9.5 14.9999 9.50001 14.9999 9.50003C14.985 11.7106 11.8568 13.5 8 13.5C4.14325 13.5 1.01499 11.7106 1.00005 9.50003C1.00005 9.50001 1.00004 9.5 1.00003 9.5C1.00001 9.5 1 9.49999 1 9.49997V9.48413V6.51587V6.50003C1 6.50001 1.00001 6.5 1.00003 6.5C1.00004 6.5 1.00005 6.49999 1.00005 6.49997C1.01499 4.28938 4.14325 2.5 8 2.5C11.8568 2.5 14.985 4.28938 14.9999 6.49997C14.9999 6.49999 15 6.5 15 6.5C15 6.5 15 6.50001 15 6.50003V6.51587Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -17,6 +17,10 @@ int roleByName(QAbstractItemModel* model, const QString &roleName)
|
|||
}
|
||||
}
|
||||
|
||||
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(PermissionTypes::Type key, uint seed = 0) noexcept {
|
||||
return qHash(static_cast<int>(key), seed);
|
||||
}
|
||||
|
||||
PermissionUtilsInternal::PermissionUtilsInternal(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
@ -124,3 +128,55 @@ QJsonArray PermissionUtilsInternal::getUniquePermissionChannels(QAbstractItemMod
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
int /*PermissionTypes::Type*/ PermissionUtilsInternal::isEligibleToJoinAs(QAbstractItemModel *permissionsModel) const
|
||||
{
|
||||
if (!permissionsModel)
|
||||
return PermissionTypes::Type::NoPermissions;
|
||||
|
||||
const auto permissionTypeRole = roleByName(permissionsModel, QStringLiteral("permissionType"));
|
||||
if (permissionTypeRole == -1) {
|
||||
qWarning() << Q_FUNC_INFO << "Requested roleName 'permissionType' not found; no permissions at all";
|
||||
return PermissionTypes::Type::NoPermissions;
|
||||
}
|
||||
|
||||
const auto tokenCriteriaMetRole = roleByName(permissionsModel, QStringLiteral("tokenCriteriaMet"));
|
||||
if (tokenCriteriaMetRole == -1) {
|
||||
qWarning() << Q_FUNC_INFO << "Requested roleName 'tokenCriteriaMet' not found; no permissions at all";
|
||||
return PermissionTypes::Type::NoPermissions;
|
||||
}
|
||||
|
||||
QSet<PermissionTypes::Type> tmpRes;
|
||||
bool hasAnyJoinPermission{false};
|
||||
constexpr auto isJoinTypePermission = [](PermissionTypes::Type type) {
|
||||
return type == PermissionTypes::Type::TokenMaster ||
|
||||
type == PermissionTypes::Type::Admin ||
|
||||
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;
|
||||
const auto tokenCriteriaMet = permissionsModel->data(permissionsModel->index(i, 0), tokenCriteriaMetRole).toBool();
|
||||
if (tokenCriteriaMet) {
|
||||
tmpRes.insert(permissionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
return PermissionTypes::Type::Member;
|
||||
|
||||
return PermissionTypes::Type::None;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,8 @@ StackLayout {
|
|||
Loader {
|
||||
id: mainViewLoader
|
||||
readonly property var sectionItem: root.rootStore.chatCommunitySectionModule
|
||||
readonly property int accessType: sectionItem.requiresTokenPermissionToJoin ? Constants.communityChatOnRequestAccess
|
||||
: Constants.communityChatPublicAccess
|
||||
|
||||
sourceComponent: {
|
||||
if (sectionItem.isCommunity() && !sectionItem.amIMember) {
|
||||
|
@ -97,7 +99,7 @@ StackLayout {
|
|||
color: communityData.color
|
||||
image: communityData.image
|
||||
membersCount: communityData.members.count
|
||||
accessType: communityData.access
|
||||
accessType: mainViewLoader.accessType
|
||||
joinCommunity: true
|
||||
amISectionAdmin: communityData.memberRole === Constants.memberRole.owner ||
|
||||
communityData.memberRole === Constants.memberRole.admin ||
|
||||
|
@ -118,24 +120,13 @@ StackLayout {
|
|||
onNotificationButtonClicked: Global.openActivityCenterPopup()
|
||||
onAdHocChatButtonClicked: rootStore.openCloseCreateChatView()
|
||||
onRequestToJoinClicked: {
|
||||
Global.openPopup(communityMembershipSetupDialogComponent, {
|
||||
communityId: joinCommunityView.communityId,
|
||||
isInvitationPending: joinCommunityView.isInvitationPending,
|
||||
communityName: communityData.name,
|
||||
introMessage: communityData.introMessage,
|
||||
communityIcon: communityData.image,
|
||||
accessType: communityData.access
|
||||
})
|
||||
Global.communityIntroPopupRequested(joinCommunityView.communityId, communityData.name, communityData.introMessage,
|
||||
communityData.image, root.rootStore.isMyCommunityRequestPending(communityId))
|
||||
}
|
||||
onInvitationPendingClicked: {
|
||||
Global.openPopup(communityMembershipSetupDialogComponent, {
|
||||
communityId: joinCommunityView.communityId,
|
||||
isInvitationPending: joinCommunityView.isInvitationPending,
|
||||
communityName: communityData.name,
|
||||
introMessage: communityData.introMessage,
|
||||
communityIcon: communityData.image,
|
||||
accessType: communityData.access
|
||||
})
|
||||
Global.communityIntroPopupRequested(joinCommunityView.communityId, communityData.name, communityData.introMessage,
|
||||
communityData.image, root.rootStore.isMyCommunityRequestPending(communityId))
|
||||
joinCommunityView.isInvitationPending = root.rootStore.isMyCommunityRequestPending(communityId)
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -192,24 +183,13 @@ StackLayout {
|
|||
root.openAppSearch()
|
||||
}
|
||||
onRequestToJoinClicked: {
|
||||
Global.openPopup(communityMembershipSetupDialogComponent, {
|
||||
communityId: chatView.communityId,
|
||||
isInvitationPending: root.rootStore.isMyCommunityRequestPending(chatView.communityId),
|
||||
communityName: root.sectionItemModel.name,
|
||||
introMessage: root.sectionItemModel.introMessage,
|
||||
communityIcon: root.sectionItemModel.image,
|
||||
accessType: root.sectionItemModel.access
|
||||
})
|
||||
Global.communityIntroPopupRequested(communityId, root.sectionItemModel.name, root.sectionItemModel.introMessage,
|
||||
root.sectionItemModel.image, root.rootStore.isMyCommunityRequestPending(chatView.communityId))
|
||||
}
|
||||
onInvitationPendingClicked: {
|
||||
Global.openPopup(communityMembershipSetupDialogComponent, {
|
||||
communityId: chatView.communityId,
|
||||
isInvitationPending: root.rootStore.isMyCommunityRequestPending(chatView.communityId),
|
||||
communityName: root.sectionItemModel.name,
|
||||
introMessage: root.sectionItemModel.introMessage,
|
||||
communityIcon: root.sectionItemModel.image,
|
||||
accessType: root.sectionItemModel.access
|
||||
})
|
||||
Global.communityIntroPopupRequested(communityId, root.sectionItemModel.name, root.sectionItemModel.introMessage,
|
||||
root.sectionItemModel.image, root.rootStore.isMyCommunityRequestPending(chatView.communityId))
|
||||
chatView.isInvitationPending = root.rootStore.isMyCommunityRequestPending(dialogRoot.communityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -276,85 +256,6 @@ StackLayout {
|
|||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: communityMembershipSetupDialogComponent
|
||||
|
||||
CommunityMembershipSetupDialog {
|
||||
id: dialogRoot
|
||||
|
||||
property string communityId
|
||||
|
||||
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
|
||||
canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses
|
||||
|
||||
walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel
|
||||
requirementsCheckPending: root.rootStore.requirementsCheckPending
|
||||
permissionsModel: {
|
||||
root.rootStore.prepareTokenModelForCommunity(dialogRoot.communityId)
|
||||
return root.rootStore.permissionsModel
|
||||
}
|
||||
assetsModel: root.rootStore.assetsModel
|
||||
collectiblesModel: root.rootStore.collectiblesModel
|
||||
|
||||
getCurrencyAmount: function (balance, symbol){
|
||||
return currencyStore.getCurrencyAmount(balance, symbol)
|
||||
}
|
||||
|
||||
onPrepareForSigning: {
|
||||
root.rootStore.prepareKeypairsForSigning(dialogRoot.communityId, dialogRoot.name, sharedAddresses, airdropAddress)
|
||||
|
||||
dialogRoot.keypairSigningModel = root.rootStore.communitiesModuleInst.keypairsSigningModel
|
||||
}
|
||||
|
||||
onSignProfileKeypairAndAllNonKeycardKeypairs: {
|
||||
root.rootStore.signProfileKeypairAndAllNonKeycardKeypairs()
|
||||
}
|
||||
|
||||
onSignSharedAddressesForKeypair: {
|
||||
root.rootStore.signSharedAddressesForKeypair(keyUid)
|
||||
}
|
||||
|
||||
onJoinCommunity: {
|
||||
root.rootStore.joinCommunityOrEditSharedAddresses()
|
||||
}
|
||||
|
||||
onCancelMembershipRequest: {
|
||||
root.rootStore.cancelPendingRequest(dialogRoot.communityId)
|
||||
mainViewLoader.item.isInvitationPending = root.rootStore.isMyCommunityRequestPending(dialogRoot.communityId)
|
||||
}
|
||||
|
||||
onSharedAddressesUpdated: {
|
||||
root.rootStore.updatePermissionsModel(dialogRoot.communityId, sharedAddresses)
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
root.rootStore.cleanJoinEditCommunityData()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.rootStore.communitiesModuleInst
|
||||
|
||||
function onAllSharedAddressesSigned() {
|
||||
if (dialogRoot.profileProvesOwnershipOfSelectedAddresses) {
|
||||
dialogRoot.joinCommunity()
|
||||
dialogRoot.close()
|
||||
return
|
||||
}
|
||||
|
||||
if (dialogRoot.allAddressesToRevealBelongToSingleNonProfileKeypair) {
|
||||
dialogRoot.joinCommunity()
|
||||
dialogRoot.close()
|
||||
return
|
||||
}
|
||||
|
||||
if (!!dialogRoot.replaceItem) {
|
||||
dialogRoot.replaceLoader.item.allSigned()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.rootStore
|
||||
enabled: mainViewLoader.item
|
||||
|
|
|
@ -65,7 +65,7 @@ StatusSectionLayout {
|
|||
property var collectiblesModel
|
||||
|
||||
readonly property var pendingViewOnlyPermissionsModel: SortFilterProxyModel {
|
||||
sourceModel: root.viewOnlyPermissionsModel
|
||||
sourceModel: root.viewOnlyPermissionsModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "permissionState"
|
||||
|
@ -75,7 +75,7 @@ StatusSectionLayout {
|
|||
]
|
||||
}
|
||||
readonly property var pendingViewAndPostPermissionsModel: SortFilterProxyModel {
|
||||
sourceModel: root.viewAndPostPermissionsModel
|
||||
sourceModel: root.viewAndPostPermissionsModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "permissionState"
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
required property int /*PermissionTypes.Type*/ eligibleToJoinAs
|
||||
|
||||
implicitWidth: hintRow.implicitWidth + 2*Style.current.padding
|
||||
implicitHeight: 40
|
||||
color: Theme.palette.baseColor2
|
||||
radius: height/2
|
||||
border.width: 1
|
||||
border.color: Theme.palette.indirectColor4
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property var joinHint: PermissionTypes.getJoinEligibilityHint(root.eligibleToJoinAs)
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: hintRow
|
||||
spacing: 4
|
||||
anchors.centerIn: parent
|
||||
|
||||
StatusBaseText {
|
||||
text: d.joinHint[0]
|
||||
}
|
||||
StatusIcon {
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
Layout.leftMargin: 2
|
||||
visible: !!icon
|
||||
icon: d.joinHint[2]
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
text: d.joinHint[1]
|
||||
visible: !!text
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,6 +32,21 @@ QtObject {
|
|||
return ""
|
||||
}
|
||||
|
||||
function getJoinEligibilityHint(type) {
|
||||
const template = qsTr("You are eligible to join as")
|
||||
switch (type) {
|
||||
case PermissionTypes.Type.TokenMaster:
|
||||
return [template, qsTr("TokenMaster"), "tiny/token-master"]
|
||||
case PermissionTypes.Type.Admin:
|
||||
return [template, qsTr("Admin"), "tiny/public-chat"]
|
||||
case PermissionTypes.Type.Member:
|
||||
return [template, qsTr("Member"), "tiny/group"]
|
||||
case PermissionTypes.Type.None:
|
||||
return [qsTr("Not eligible to join with current address selections"), "", ""]
|
||||
}
|
||||
return ["", "", ""]
|
||||
}
|
||||
|
||||
function getIcon(type) {
|
||||
switch (type) {
|
||||
case PermissionTypes.Type.Admin:
|
||||
|
|
|
@ -7,6 +7,7 @@ BannerPicker 1.0 BannerPicker.qml
|
|||
CategoryListItem 1.0 CategoryListItem.qml
|
||||
ColorPicker 1.0 ColorPicker.qml
|
||||
CommunityListItem 1.0 CommunityListItem.qml
|
||||
CommunityEligibilityTag 1.0 CommunityEligibilityTag.qml
|
||||
DescriptionInput 1.0 DescriptionInput.qml
|
||||
EditCommunitySettingsForm 1.0 EditCommunitySettingsForm.qml
|
||||
EnsPanel 1.0 EnsPanel.qml
|
||||
|
|
|
@ -78,8 +78,8 @@ QtObject {
|
|||
return Internal.PermissionUtils.getUniquePermissionChannels(model, permissionsTypesArray)
|
||||
}
|
||||
|
||||
function getUniqueChannelPermission(model, channelKey) {
|
||||
return Internal.PermissionUtils.getUniquePermissionChannels(model, channelKey)
|
||||
function isEligibleToJoinAs(model) {
|
||||
return Internal.PermissionUtils.isEligibleToJoinAs(model)
|
||||
}
|
||||
|
||||
function setHoldingsTextFormat(type, name, amount, decimals) {
|
||||
|
|
|
@ -47,7 +47,7 @@ Control {
|
|||
readonly property string communityMembershipRequestPendingText: qsTr("Membership Request Pending...")
|
||||
readonly property string channelRequirementsNotMetText: qsTr("Channel requirements not met")
|
||||
readonly property string channelMembershipRequestPendingText: qsTr("Channel Membership Request Pending...")
|
||||
readonly property string memberchipRequestRejectedText: qsTr("Membership Request Rejected")
|
||||
readonly property string membershipRequestRejectedText: qsTr("Membership Request Rejected")
|
||||
readonly property string allChannelsAreHiddenBecauseNotPermittedText: qsTr("Sorry, you don't hodl the necessary tokens to view or post in any of <b>%1</b> channels").arg(root.communityName)
|
||||
|
||||
readonly property bool onlyPrivateNotMetPermissions: (d.visiblePermissionsModel.count === 0) && root.communityHoldingsModel.count > 0
|
||||
|
@ -160,12 +160,11 @@ Control {
|
|||
&& root.requiresRequest
|
||||
&& !d.onlyPrivateNotMetPermissions
|
||||
&& !root.allChannelsAreHiddenBecauseNotPermitted
|
||||
text: root.isInvitationPending ? (root.joinCommunity ? d.communityMembershipRequestPendingText : d.channelMembershipRequestPendingText)
|
||||
: d.communityRequestToJoinText
|
||||
font.pixelSize: 13
|
||||
enabled: root.requirementsMet || (root.joinCommunity && d.visiblePermissionsModel.count === 0)
|
||||
text: root.isInvitationPending ? (root.joinCommunity ? d.communityMembershipRequestPendingText : d.channelMembershipRequestPendingText)
|
||||
: d.communityRequestToJoinText
|
||||
font.pixelSize: 13
|
||||
|
||||
onClicked: root.isInvitationPending ? root.invitationPendingClicked() : root.requestToJoinClicked()
|
||||
onClicked: root.isInvitationPending ? root.invitationPendingClicked() : root.requestToJoinClicked()
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
|
@ -175,8 +174,8 @@ Control {
|
|||
&& (root.isJoinRequestRejected || !root.requirementsMet)
|
||||
&& !d.onlyPrivateNotMetPermissions
|
||||
&& !root.allChannelsAreHiddenBecauseNotPermitted
|
||||
text: root.isJoinRequestRejected ? d.memberchipRequestRejectedText :
|
||||
(root.joinCommunity ? d.communityRequirementsNotMetText : d.channelRequirementsNotMetText)
|
||||
text: root.isJoinRequestRejected ? d.membershipRequestRejectedText
|
||||
: (root.joinCommunity ? d.communityRequirementsNotMetText : d.channelRequirementsNotMetText)
|
||||
color: Theme.palette.dangerColor1
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ StatusListView {
|
|||
statusListItemTitle.font.weight: Font.Medium
|
||||
title: model.name
|
||||
tertiaryTitle: !walletAccountAssetsModel.count && root.hasPermissions ? qsTr("No relevant tokens") : ""
|
||||
property string accountAddress: model.address
|
||||
|
||||
SubmodelProxyModel {
|
||||
id: filteredBalances
|
||||
|
@ -75,7 +74,7 @@ StatusListView {
|
|||
delegateModel: SortFilterProxyModel {
|
||||
sourceModel: submodel
|
||||
filters: FastExpressionFilter {
|
||||
expression: listItem.accountAddress === model.account
|
||||
expression: listItem.address === model.account.toLowerCase()
|
||||
expectedRoles: ["account"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ Control {
|
|||
required property int totalNumOfAddressesForSharing
|
||||
required property bool profileProvesOwnershipOfSelectedAddresses
|
||||
required property bool allAddressesToRevealBelongToSingleNonProfileKeypair
|
||||
required property int /*PermissionTypes.Type*/ eligibleToJoinAs
|
||||
|
||||
property bool requirementsCheckPending: false
|
||||
|
||||
|
@ -135,6 +136,7 @@ Control {
|
|||
|
||||
readonly property var shareAddressesButton: StatusButton {
|
||||
visible: !root.isEditMode
|
||||
enabled: root.eligibleToJoinAs !== PermissionTypes.Type.None
|
||||
text: {
|
||||
if (d.selectedSharedAddressesCount === root.totalNumOfAddressesForSharing) {
|
||||
return qsTr("Share all addresses to join")
|
||||
|
@ -177,7 +179,8 @@ Control {
|
|||
text: d.lostCommunityPermission ? qsTr("Selected addresses have insufficient tokens to maintain %1 membership").arg(root.communityName) :
|
||||
d.lostChannelPermissions ? qsTr("By deselecting these addresses, you will lose channel permissions") :
|
||||
""
|
||||
visible: d.lostCommunityPermission || d.lostChannelPermissions
|
||||
active: d.lostCommunityPermission || d.lostChannelPermissions
|
||||
visible: active
|
||||
closeBtnVisible: false
|
||||
}
|
||||
|
||||
|
@ -202,7 +205,7 @@ Control {
|
|||
root.airdropAddressSelected(address)
|
||||
}
|
||||
|
||||
getCurrencyAmount: function (balance, symbol){
|
||||
getCurrencyAmount: function (balance, symbol) {
|
||||
return root.getCurrencyAmount(balance, symbol)
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +214,7 @@ Control {
|
|||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Style.current.padding * 2
|
||||
color: Theme.palette.baseColor2
|
||||
color: permissionsView.color
|
||||
radius: Style.current.padding
|
||||
border.width: 1
|
||||
border.color: Theme.palette.baseColor3
|
||||
|
@ -237,6 +240,7 @@ Control {
|
|||
requirementsCheckPending: root.requirementsCheckPending
|
||||
communityName: root.communityName
|
||||
communityIcon: root.communityIcon
|
||||
eligibleToJoinAs: root.eligibleToJoinAs
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
|
|
@ -18,6 +18,8 @@ import utils 1.0
|
|||
Rectangle {
|
||||
id: root
|
||||
|
||||
required property int /*PermissionTypes.Type*/ eligibleToJoinAs
|
||||
|
||||
property bool isEditMode
|
||||
|
||||
property string communityName
|
||||
|
@ -33,7 +35,7 @@ Rectangle {
|
|||
readonly property bool lostChannelPermissions: d.lostChannelPermissions
|
||||
|
||||
implicitHeight: permissionsScrollView.contentHeight - permissionsScrollView.anchors.topMargin
|
||||
color: Theme.palette.baseColor2
|
||||
color: Theme.palette.baseColor4
|
||||
|
||||
readonly property bool hasAnyVisiblePermission: root.permissionsModel && root.permissionsModel.count &&
|
||||
(d.tokenMasterPermissionsModel.count > 0 || d.adminPermissionsModel.count > 0 ||
|
||||
|
@ -124,6 +126,8 @@ Rectangle {
|
|||
id: permissionsScrollView
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: -Style.current.padding
|
||||
bottomPadding: eligibilityHintBubble.visible ? eligibilityHintBubble.height + eligibilityHintBubble.anchors.bottomMargin*2
|
||||
: 16
|
||||
contentWidth: availableWidth
|
||||
|
||||
ColumnLayout {
|
||||
|
@ -163,11 +167,6 @@ Rectangle {
|
|||
}
|
||||
|
||||
// permission types
|
||||
PermissionPanel {
|
||||
id: tokenMasterPermissionPanel
|
||||
permissionType: PermissionTypes.Type.TokenMaster
|
||||
permissionsModel: d.tokenMasterPermissionsModel
|
||||
}
|
||||
PermissionPanel {
|
||||
id: joinPermissionPanel
|
||||
permissionType: PermissionTypes.Type.Member
|
||||
|
@ -177,6 +176,11 @@ Rectangle {
|
|||
permissionType: PermissionTypes.Type.Admin
|
||||
permissionsModel: d.adminPermissionsModel
|
||||
}
|
||||
PermissionPanel {
|
||||
id: tokenMasterPermissionPanel
|
||||
permissionType: PermissionTypes.Type.TokenMaster
|
||||
permissionsModel: d.tokenMasterPermissionsModel
|
||||
}
|
||||
|
||||
Repeater { // channel repeater
|
||||
id: channelPermissionsPanel
|
||||
|
@ -194,6 +198,15 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
CommunityEligibilityTag {
|
||||
id: eligibilityHintBubble
|
||||
eligibleToJoinAs: root.eligibleToJoinAs
|
||||
visible: !root.isEditMode
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 24
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
component PanelBg: Rectangle {
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
border.width: 1
|
||||
|
@ -207,6 +220,8 @@ Rectangle {
|
|||
Layout.alignment: Qt.AlignTop
|
||||
asset.name: {
|
||||
switch (permissionType) {
|
||||
case PermissionTypes.Type.TokenMaster:
|
||||
return "arbitrator"
|
||||
case PermissionTypes.Type.Admin:
|
||||
return "admin"
|
||||
case PermissionTypes.Type.Member:
|
||||
|
@ -252,6 +267,7 @@ Rectangle {
|
|||
width: 16
|
||||
height: 16
|
||||
image.source: model.imageSource
|
||||
visible: !isError
|
||||
}
|
||||
StatusBaseText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
@ -352,6 +368,7 @@ Rectangle {
|
|||
}
|
||||
Row {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
spacing: 4
|
||||
StatusIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 16
|
||||
|
@ -525,6 +542,7 @@ Rectangle {
|
|||
}
|
||||
Row {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
spacing: 4
|
||||
StatusIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 16
|
||||
|
|
|
@ -502,21 +502,22 @@ Item {
|
|||
}
|
||||
|
||||
onClicked: {
|
||||
Global.openPopup(communityMembershipSetupDialogComponent);
|
||||
Global.communityIntroPopupRequested(communityData.id, communityData.name, communityData.introMessage,
|
||||
communityData.image, d.invitationPending)
|
||||
}
|
||||
|
||||
Connections {
|
||||
enabled: d.joiningCommunityInProgress
|
||||
target: root.store.communitiesModuleInst
|
||||
function onCommunityAccessRequested(communityId: string) {
|
||||
if (communityId === communityData.id) {
|
||||
d.invitationPending = root.store.isMyCommunityRequestPending(communityData.id)
|
||||
if (communityId === root.communityData.id) {
|
||||
d.invitationPending = root.store.isMyCommunityRequestPending(communityId)
|
||||
d.joiningCommunityInProgress = false
|
||||
}
|
||||
}
|
||||
|
||||
function onCommunityAccessFailed(communityId: string, error: string) {
|
||||
if (communityId === communityData.id) {
|
||||
if (communityId === root.communityData.id) {
|
||||
d.invitationPending = false
|
||||
d.joiningCommunityInProgress = false
|
||||
Global.displayToastMessage(qsTr("Request to join failed"),
|
||||
|
@ -528,90 +529,6 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: communityMembershipSetupDialogComponent
|
||||
|
||||
CommunityMembershipSetupDialog {
|
||||
id: dialogRoot
|
||||
|
||||
isInvitationPending: d.invitationPending
|
||||
requirementsCheckPending: root.store.requirementsCheckPending
|
||||
communityName: communityData.name
|
||||
introMessage: communityData.introMessage
|
||||
communityIcon: communityData.image
|
||||
accessType: communityData.access
|
||||
|
||||
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
|
||||
canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses
|
||||
|
||||
walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel
|
||||
permissionsModel: {
|
||||
root.store.prepareTokenModelForCommunity(communityData.id)
|
||||
return root.store.permissionsModel
|
||||
}
|
||||
assetsModel: root.store.assetsModel
|
||||
collectiblesModel: root.store.collectiblesModel
|
||||
|
||||
getCurrencyAmount: function (balance, symbol){
|
||||
return currencyStore.getCurrencyAmount(balance, symbol)
|
||||
}
|
||||
|
||||
onPrepareForSigning: {
|
||||
root.store.prepareKeypairsForSigning(communityData.id, root.store.userProfileInst.name, sharedAddresses, airdropAddress, false)
|
||||
|
||||
dialogRoot.keypairSigningModel = root.store.communitiesModuleInst.keypairsSigningModel
|
||||
}
|
||||
|
||||
onSignProfileKeypairAndAllNonKeycardKeypairs: {
|
||||
root.store.signProfileKeypairAndAllNonKeycardKeypairs()
|
||||
}
|
||||
|
||||
onSignSharedAddressesForKeypair: {
|
||||
root.store.signSharedAddressesForKeypair(keyUid)
|
||||
}
|
||||
|
||||
onJoinCommunity: {
|
||||
d.joiningCommunityInProgress = true
|
||||
root.store.joinCommunityOrEditSharedAddresses()
|
||||
}
|
||||
|
||||
onCancelMembershipRequest: {
|
||||
root.store.cancelPendingRequest(communityData.id)
|
||||
d.invitationPending = root.store.isMyCommunityRequestPending(communityData.id)
|
||||
}
|
||||
|
||||
onSharedAddressesUpdated: {
|
||||
root.store.updatePermissionsModel(communityData.id, sharedAddresses)
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
root.store.cleanJoinEditCommunityData()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.store.communitiesModuleInst
|
||||
|
||||
function onAllSharedAddressesSigned() {
|
||||
if (dialogRoot.profileProvesOwnershipOfSelectedAddresses) {
|
||||
dialogRoot.joinCommunity()
|
||||
dialogRoot.close()
|
||||
return
|
||||
}
|
||||
|
||||
if (dialogRoot.allAddressesToRevealBelongToSingleNonProfileKeypair) {
|
||||
dialogRoot.joinCommunity()
|
||||
dialogRoot.close()
|
||||
return
|
||||
}
|
||||
|
||||
if (!!dialogRoot.replaceItem) {
|
||||
dialogRoot.replaceLoader.item.allSigned()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ StatusListView {
|
|||
readonly property bool isOwner: model.memberRole === Constants.memberRole.owner
|
||||
readonly property bool isAdmin: model.memberRole === Constants.memberRole.admin
|
||||
readonly property bool isTokenMaster: model.memberRole === Constants.memberRole.tokenMaster
|
||||
readonly property bool isInvitationPending: root.rootStore.isMyCommunityRequestPending(model.id)
|
||||
property bool isInvitationPending: root.rootStore.isMyCommunityRequestPending(model.id)
|
||||
|
||||
components: [
|
||||
StatusFlatButton {
|
||||
|
@ -153,9 +153,10 @@ StatusListView {
|
|||
enabled: !listItem.isOwner
|
||||
onTriggered: {
|
||||
moreMenu.close()
|
||||
if (listItem.isInvitationPending)
|
||||
if (listItem.isInvitationPending) {
|
||||
root.cancelMembershipRequest(model.id)
|
||||
else if (listItem.isSpectator)
|
||||
listItem.isInvitationPending = root.rootStore.isMyCommunityRequestPending(model.id)
|
||||
} else if (listItem.isSpectator)
|
||||
root.closeCommunityClicked(model.id)
|
||||
else
|
||||
root.leaveCommunityClicked(model.name, model.id, model.outroMessage)
|
||||
|
|
|
@ -208,100 +208,10 @@ SettingsContentBase {
|
|||
null)
|
||||
}
|
||||
onShowCommunityMembershipSetupDialog: {
|
||||
Global.openPopup(communityMembershipSetupDialogComponent, {
|
||||
communityId: communityId,
|
||||
isInvitationPending: root.rootStore.isMyCommunityRequestPending(communityId),
|
||||
communityName: name,
|
||||
introMessage: introMessage,
|
||||
communityIcon: imageSrc,
|
||||
accessType: accessType
|
||||
})
|
||||
Global.communityIntroPopupRequested(communityId, name, introMessage, imageSrc, root.rootStore.isMyCommunityRequestPending(communityId))
|
||||
}
|
||||
onCancelMembershipRequest: {
|
||||
root.rootStore.cancelPendingRequest(communityId)
|
||||
}
|
||||
}
|
||||
|
||||
readonly property var communityMembershipSetupDialogComponent: Component {
|
||||
id: communityMembershipSetupDialogComponent
|
||||
|
||||
CommunityMembershipSetupDialog {
|
||||
id: dialogRoot
|
||||
|
||||
property string communityId
|
||||
|
||||
readonly property var chatStore: ChatStore.RootStore {
|
||||
chatCommunitySectionModule: {
|
||||
root.rootStore.mainModuleInst.prepareCommunitySectionModuleForCommunityId(dialogRoot.communityId)
|
||||
return root.rootStore.mainModuleInst.getCommunitySectionModule()
|
||||
}
|
||||
}
|
||||
|
||||
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
|
||||
canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses
|
||||
|
||||
walletAssetsModel: walletAssetsStore.groupedAccountAssetsModel
|
||||
requirementsCheckPending: root.rootStore.requirementsCheckPending
|
||||
permissionsModel: {
|
||||
root.rootStore.prepareTokenModelForCommunity(dialogRoot.communityId)
|
||||
return root.rootStore.permissionsModel
|
||||
}
|
||||
assetsModel: chatStore.assetsModel
|
||||
collectiblesModel: chatStore.collectiblesModel
|
||||
|
||||
getCurrencyAmount: function (balance, symbol){
|
||||
return currencyStore.getCurrencyAmount(balance, symbol)
|
||||
}
|
||||
|
||||
onPrepareForSigning: {
|
||||
chatStore.prepareKeypairsForSigning(dialogRoot.communityId, root.rootStore.userProfileInst.name, sharedAddresses, airdropAddress, false)
|
||||
|
||||
dialogRoot.keypairSigningModel = chatStore.communitiesModuleInst.keypairsSigningModel
|
||||
}
|
||||
|
||||
onSignProfileKeypairAndAllNonKeycardKeypairs: {
|
||||
chatStore.signProfileKeypairAndAllNonKeycardKeypairs()
|
||||
}
|
||||
|
||||
onSignSharedAddressesForKeypair: {
|
||||
chatStore.signSharedAddressesForKeypair(keyUid)
|
||||
}
|
||||
|
||||
onJoinCommunity: {
|
||||
chatStore.joinCommunityOrEditSharedAddresses()
|
||||
}
|
||||
|
||||
onCancelMembershipRequest: root.rootStore.cancelPendingRequest(dialogRoot.communityId)
|
||||
|
||||
onSharedAddressesUpdated: {
|
||||
root.rootStore.updatePermissionsModel(dialogRoot.communityId, sharedAddresses)
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
chatStore.cleanJoinEditCommunityData()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatStore.communitiesModuleInst
|
||||
|
||||
function onAllSharedAddressesSigned() {
|
||||
if (dialogRoot.profileProvesOwnershipOfSelectedAddresses) {
|
||||
dialogRoot.joinCommunity()
|
||||
dialogRoot.close()
|
||||
return
|
||||
}
|
||||
|
||||
if (dialogRoot.allAddressesToRevealBelongToSingleNonProfileKeypair) {
|
||||
dialogRoot.joinCommunity()
|
||||
dialogRoot.close()
|
||||
return
|
||||
}
|
||||
|
||||
if (!!dialogRoot.replaceItem) {
|
||||
dialogRoot.replaceLoader.item.allSigned()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,13 +260,12 @@ QtObject {
|
|||
}
|
||||
|
||||
function openCommunityIntroPopup(communityId, name, introMessage,
|
||||
imageSrc, accessType, isInvitationPending) {
|
||||
imageSrc, isInvitationPending) {
|
||||
openPopup(communityJoinDialogPopup,
|
||||
{communityId: communityId,
|
||||
communityName: name,
|
||||
introMessage: introMessage,
|
||||
communityIcon: imageSrc,
|
||||
accessType: accessType,
|
||||
isInvitationPending: isInvitationPending
|
||||
})
|
||||
}
|
||||
|
@ -278,7 +277,6 @@ QtObject {
|
|||
communityName: name,
|
||||
introMessage: qsTr("Share addresses to rejoin %1").arg(name),
|
||||
communityIcon: imageSrc,
|
||||
accessType: Constants.communityChatOnRequestAccess,
|
||||
isInvitationPending: false
|
||||
})
|
||||
}
|
||||
|
@ -710,7 +708,7 @@ QtObject {
|
|||
assetsModel: root.rootStore.assetsModel
|
||||
collectiblesModel: root.rootStore.collectiblesModel
|
||||
|
||||
getCurrencyAmount: function (balance, symbol){
|
||||
getCurrencyAmount: function (balance, symbol) {
|
||||
return currencyStore.getCurrencyAmount(balance, symbol)
|
||||
}
|
||||
|
||||
|
@ -732,7 +730,10 @@ QtObject {
|
|||
root.rootStore.joinCommunityOrEditSharedAddresses()
|
||||
}
|
||||
|
||||
onCancelMembershipRequest: root.rootStore.cancelPendingRequest(dialogRoot.communityId)
|
||||
onCancelMembershipRequest: {
|
||||
root.rootStore.cancelPendingRequest(dialogRoot.communityId)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.communitiesStore.communitiesModuleInst
|
||||
function onCommunityAccessRequested(communityId: string) {
|
||||
|
@ -944,6 +945,8 @@ QtObject {
|
|||
communityIcon: chatStore.sectionDetails.image
|
||||
requirementsCheckPending: root.rootStore.requirementsCheckPending
|
||||
|
||||
introMessage: chatStore.sectionDetails.introMessage
|
||||
|
||||
canProfileProveOwnershipOfProvidedAddressesFn: WalletStore.RootStore.canProfileProveOwnershipOfProvidedAddresses
|
||||
|
||||
walletAccountsModel: root.rootStore.walletAccountsModel
|
||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick.Layouts 1.15
|
|||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
@ -12,6 +13,8 @@ import StatusQ.Popups 0.1
|
|||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
import AppLayouts.Communities.panels 1.0
|
||||
import AppLayouts.Communities.controls 1.0
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
|
@ -26,7 +29,6 @@ StatusStackModal {
|
|||
required property bool requirementsCheckPending
|
||||
|
||||
property string introMessage
|
||||
property int accessType
|
||||
|
||||
property bool isInvitationPending: false
|
||||
|
||||
|
@ -71,13 +73,63 @@ StatusStackModal {
|
|||
|
||||
width: 640 // by design
|
||||
padding: 0
|
||||
stackTitle: root.accessType === Constants.communityChatOnRequestAccess ?
|
||||
stackTitle: d.accessType === Constants.communityChatOnRequestAccess ?
|
||||
qsTr("Request to join %1").arg(root.communityName)
|
||||
: qsTr("Welcome to %1").arg(root.communityName)
|
||||
|
||||
rightButtons: [d.shareButton, finishButton]
|
||||
|
||||
finishButton: root.isInvitationPending ? d.cancelRequestButton : d.shareAddressesButton
|
||||
finishButton: StatusButton {
|
||||
enabled: {
|
||||
if (root.isInvitationPending || d.accessType !== Constants.communityChatOnRequestAccess)
|
||||
return true
|
||||
|
||||
return d.eligibleToJoinAs !== PermissionTypes.Type.None
|
||||
}
|
||||
text: {
|
||||
if (root.isInvitationPending) {
|
||||
return qsTr("Cancel Membership Request")
|
||||
}
|
||||
if (d.selectedSharedAddressesCount === d.totalNumOfAddressesForSharing) {
|
||||
return qsTr("Share all addresses to join")
|
||||
}
|
||||
return qsTr("Share %n address(s) to join", "", d.selectedSharedAddressesCount)
|
||||
}
|
||||
type: root.isInvitationPending ? StatusBaseButton.Type.Danger
|
||||
: StatusBaseButton.Type.Normal
|
||||
|
||||
icon.name: {
|
||||
if (root.isInvitationPending)
|
||||
return ""
|
||||
|
||||
if (root.profileProvesOwnershipOfSelectedAddresses) {
|
||||
if (userProfile.usingBiometricLogin) {
|
||||
return "touch-id"
|
||||
}
|
||||
|
||||
if (userProfile.isKeycardUser) {
|
||||
return "keycard"
|
||||
}
|
||||
|
||||
return "password"
|
||||
}
|
||||
if (root.allAddressesToRevealBelongToSingleNonProfileKeypair) {
|
||||
return "keycard"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (root.isInvitationPending) {
|
||||
root.cancelMembershipRequest()
|
||||
root.close()
|
||||
return
|
||||
}
|
||||
|
||||
d.proceedToSigningOrSubmitRequest(d.communityIntroUid)
|
||||
}
|
||||
}
|
||||
|
||||
backButton: StatusBackButton {
|
||||
visible: !!root.replaceLoader.item
|
||||
|
@ -117,17 +169,29 @@ StatusStackModal {
|
|||
|
||||
readonly property int selectedSharedAddressesCount: d.selectedSharedAddressesMap.size
|
||||
|
||||
readonly property int accessType: d.eligibleToJoinAs !== - 1 ? Constants.communityChatOnRequestAccess
|
||||
: Constants.communityChatPublicAccess
|
||||
property int eligibleToJoinAs: PermissionsHelpers.isEligibleToJoinAs(root.permissionsModel)
|
||||
readonly property var _con: Connections {
|
||||
target: root.permissionsModel
|
||||
function onTokenCriteriaUpdated() {
|
||||
d.eligibleToJoinAs = PermissionsHelpers.isEligibleToJoinAs(root.permissionsModel)
|
||||
}
|
||||
}
|
||||
|
||||
property var initialAddressesModel: SortFilterProxyModel {
|
||||
sourceModel: root.walletAccountsModel
|
||||
sorters: [
|
||||
ExpressionSorter {
|
||||
function isGenerated(modelData) {
|
||||
return modelData.walletType === Constants.generatedWalletType
|
||||
FastExpressionSorter {
|
||||
function sortPredicate(lhs, rhs) {
|
||||
if (lhs.walletType === rhs.walletType) return 0
|
||||
return lhs.walletType === Constants.generatedWalletType ? -1 : 1
|
||||
}
|
||||
|
||||
expression: {
|
||||
return isGenerated(modelLeft)
|
||||
return sortPredicate(modelLeft, modelRight)
|
||||
}
|
||||
expectedRoles: ["walletType"]
|
||||
},
|
||||
RoleSorter {
|
||||
roleName: "position"
|
||||
|
@ -138,50 +202,6 @@ StatusStackModal {
|
|||
]
|
||||
}
|
||||
|
||||
readonly property StatusFlatButton cancelRequestButton: StatusFlatButton {
|
||||
text: qsTr("Cancel Membership Request")
|
||||
type: StatusBaseButton.Type.Danger
|
||||
onClicked: {
|
||||
if (root.isInvitationPending) {
|
||||
root.cancelMembershipRequest()
|
||||
root.close()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property StatusButton shareAddressesButton: StatusButton {
|
||||
text: {
|
||||
if (d.selectedSharedAddressesCount === d.totalNumOfAddressesForSharing) {
|
||||
return qsTr("Share all addresses to join")
|
||||
}
|
||||
|
||||
return qsTr("Share %n address(s) to join", "", d.selectedSharedAddressesCount)
|
||||
}
|
||||
type: StatusBaseButton.Type.Normal
|
||||
icon.name: {
|
||||
if (root.profileProvesOwnershipOfSelectedAddresses) {
|
||||
if (userProfile.usingBiometricLogin) {
|
||||
return "touch-id"
|
||||
}
|
||||
|
||||
if (userProfile.isKeycardUser) {
|
||||
return "keycard"
|
||||
}
|
||||
|
||||
return "password"
|
||||
}
|
||||
|
||||
if (root.allAddressesToRevealBelongToSingleNonProfileKeypair) {
|
||||
return "keycard"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
onClicked: d.proceedToSigningOrSubmitRequest(d.communityIntroUid)
|
||||
}
|
||||
|
||||
function proceedToSigningOrSubmitRequest(uidOfComponentThisFunctionIsCalledFrom) {
|
||||
const selected = d.getSelectedAddresses()
|
||||
root.prepareForSigning(selected.airdropAddress, selected.addresses)
|
||||
|
@ -340,6 +360,7 @@ StatusStackModal {
|
|||
currentSharedAddressesMap: d.currentSharedAddressesMap
|
||||
|
||||
totalNumOfAddressesForSharing: d.totalNumOfAddressesForSharing
|
||||
eligibleToJoinAs: d.eligibleToJoinAs
|
||||
|
||||
profileProvesOwnershipOfSelectedAddresses: root.profileProvesOwnershipOfSelectedAddresses
|
||||
allAddressesToRevealBelongToSingleNonProfileKeypair: root.allAddressesToRevealBelongToSingleNonProfileKeypair
|
||||
|
@ -377,7 +398,6 @@ StatusStackModal {
|
|||
Component {
|
||||
id: sharedAddressesSigningPanelComponent
|
||||
SharedAddressesSigningPanel {
|
||||
|
||||
componentUid: d.signingPanelUid
|
||||
isEditMode: root.isEditMode
|
||||
totalNumOfAddressesForSharing: d.totalNumOfAddressesForSharing
|
||||
|
@ -430,6 +450,12 @@ StatusStackModal {
|
|||
color: Theme.palette.directColor1
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
CommunityEligibilityTag {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
eligibleToJoinAs: d.eligibleToJoinAs
|
||||
visible: !root.isEditMode && !root.isInvitationPending && d.accessType === Constants.communityChatOnRequestAccess
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -85,7 +85,7 @@ QtObject {
|
|||
signal createCommunityPopupRequested(bool isDiscordImport)
|
||||
signal importCommunityPopupRequested()
|
||||
signal communityIntroPopupRequested(string communityId, string name, string introMessage,
|
||||
string imageSrc, int accessType, bool isInvitationPending)
|
||||
string imageSrc, bool isInvitationPending)
|
||||
signal communityShareAddressesPopupRequested(string communityId, string name, string imageSrc)
|
||||
signal leaveCommunityRequested(string community, string communityId, string outroMessage)
|
||||
signal openEditSharedAddressesFlow(string communityId)
|
||||
|
|
Loading…
Reference in New Issue