perf(admin): speed up admin tabs significantly (#16363)

Iterates #16043

* fix(admin): improve admin panel loading by putting sections in loaders

* fix(admin): speed up members tab by using nim model and real search

* fix(admin): speed up airdrop panel

* fix(admin): mint panel and airdrop panel interactions and previous btn

* fix(admin): speed up overview page

* fix(admin): speed up permissions page
This commit is contained in:
Jonathan Rainville 2024-09-27 13:28:27 -04:00 committed by GitHub
parent c09de56678
commit 1cad66bb2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 397 additions and 348 deletions

View File

@ -236,6 +236,9 @@ method joinCommunityOrEditSharedAddresses*(self: AccessInterface) {.base.} =
method prepareTokenModelForCommunity*(self: AccessInterface, communityId: string) {.base.} = method prepareTokenModelForCommunity*(self: AccessInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method prepareTokenModelForCommunityChat*(self: AccessInterface, communityId: string, chatId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method getCommunityPublicKeyFromPrivateKey*(self: AccessInterface, communityPrivateKey: string): string {.base.} = method getCommunityPublicKeyFromPrivateKey*(self: AccessInterface, communityPrivateKey: string): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -886,6 +886,25 @@ method prepareTokenModelForCommunity*(self: Module, communityId: string) =
self.view.spectatedCommunityPermissionModel.setItems(tokenPermissionsItems) self.view.spectatedCommunityPermissionModel.setItems(tokenPermissionsItems)
self.checkPermissions(communityId, @[]) self.checkPermissions(communityId, @[])
method prepareTokenModelForCommunityChat*(self: Module, communityId: string, chatId: string) =
let community = self.controller.getCommunityById(communityId)
var tokenPermissionsItems: seq[TokenPermissionItem] = @[]
for id, tokenPermission in community.tokenPermissions:
var containsChat = false
for id in tokenPermission.chatIds:
if id == chatId:
containsChat = true
break
if not containsChat:
continue
let chats = community.getCommunityChats(tokenPermission.chatIds)
let tokenPermissionItem = buildTokenPermissionItem(tokenPermission, chats)
tokenPermissionsItems.add(tokenPermissionItem)
self.view.spectatedCommunityPermissionModel.setItems(tokenPermissionsItems)
self.checkPermissions(communityId, @[])
proc applyPermissionResponse*(self: Module, communityId: string, permissions: Table[string, CheckPermissionsResultDto]) = proc applyPermissionResponse*(self: Module, communityId: string, permissions: Table[string, CheckPermissionsResultDto]) =
let community = self.controller.getCommunityById(communityId) let community = self.controller.getCommunityById(communityId)
for id, criteriaResult in permissions: for id, criteriaResult in permissions:

View File

@ -347,6 +347,9 @@ QtObject:
proc prepareTokenModelForCommunity(self: View, communityId: string) {.slot.} = proc prepareTokenModelForCommunity(self: View, communityId: string) {.slot.} =
self.delegate.prepareTokenModelForCommunity(communityId) self.delegate.prepareTokenModelForCommunity(communityId)
proc prepareTokenModelForCommunityChat(self: View, communityId: string, chatId: string) {.slot.} =
self.delegate.prepareTokenModelForCommunityChat(communityId, chatId)
proc signProfileKeypairAndAllNonKeycardKeypairs*(self: View) {.slot.} = proc signProfileKeypairAndAllNonKeycardKeypairs*(self: View) {.slot.} =
self.delegate.signProfileKeypairAndAllNonKeycardKeypairs() self.delegate.signProfileKeypairAndAllNonKeycardKeypairs()

View File

@ -132,6 +132,10 @@ QtObject {
root.communitiesModuleInst.prepareTokenModelForCommunity(publicKey) root.communitiesModuleInst.prepareTokenModelForCommunity(publicKey)
} }
function prepareTokenModelForCommunityChat(publicKey, chatId) {
root.communitiesModuleInst.prepareTokenModelForCommunityChat(publicKey, chatId)
}
readonly property bool allChannelsAreHiddenBecauseNotPermitted: root.chatCommunitySectionModule.allChannelsAreHiddenBecauseNotPermitted && readonly property bool allChannelsAreHiddenBecauseNotPermitted: root.chatCommunitySectionModule.allChannelsAreHiddenBecauseNotPermitted &&
!root.chatCommunitySectionModule.requiresTokenPermissionToJoin !root.chatCommunitySectionModule.requiresTokenPermissionToJoin

View File

@ -252,7 +252,7 @@ QtObject {
filters: [ filters: [
FastExpressionFilter { FastExpressionFilter {
function filterPredicate(id, permissionType) { function filterPredicate(id, permissionType) {
return !PermissionTypes.isCommunityPermission(permissionType) && root.permissionsModel.belongsToChat(id, root.channelId) return !PermissionTypes.isCommunityPermission(permissionType)
} }
expression: { expression: {
return filterPredicate(model.id, model.permissionType) return filterPredicate(model.id, model.permissionType)

View File

@ -3,6 +3,7 @@ import QtQuick.Controls 2.15
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import AppLayouts.Communities.controls 1.0
import AppLayouts.Communities.layouts 1.0 import AppLayouts.Communities.layouts 1.0
import AppLayouts.Communities.views 1.0 import AppLayouts.Communities.views 1.0
import AppLayouts.Communities.helpers 1.0 import AppLayouts.Communities.helpers 1.0

View File

@ -5,6 +5,7 @@ import QtQuick.Controls 2.14
import StatusQ 0.1 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.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
@ -70,23 +71,31 @@ Item {
sourceModel: root.model sourceModel: root.model
proxyRoles: FastExpressionRole {
function displayNameProxy(localNickname, ensName, displayName, aliasName) {
return ProfileUtils.displayName(localNickname, ensName, displayName, aliasName);
}
name: "preferredDisplayName"
expectedRoles: ["localNickname", "displayName", "ensName", "alias"]
expression: displayNameProxy(model.localNickname, model.ensName, model.displayName, model.alias);
}
sorters : [ sorters : [
StringSorter { StringSorter {
roleName: "preferredDisplayName" roleName: "preferredDisplayName"
caseSensitivity: Qt.CaseInsensitive caseSensitivity: Qt.CaseInsensitive
} }
] ]
filters: AnyOf {
SearchFilter {
roleName: "localNickname"
searchPhrase: memberSearch.text
}
SearchFilter {
roleName: "displayName"
searchPhrase: memberSearch.text
}
SearchFilter {
roleName: "ensName"
searchPhrase: memberSearch.text
}
SearchFilter {
roleName: "alias"
searchPhrase: memberSearch.text
}
}
} }
spacing: 0 spacing: 0
@ -288,8 +297,6 @@ Item {
readonly property string title: model.preferredDisplayName readonly property string title: model.preferredDisplayName
width: membersList.width width: membersList.width
visible: memberSearch.text === "" || title.toLowerCase().includes(memberSearch.text.toLowerCase())
height: visible ? implicitHeight : 0
color: "transparent" color: "transparent"
pubKey: model.isEnsVerified ? "" : Utils.getElidedCompressedPk(model.pubKey) pubKey: model.isEnsVerified ? "" : Utils.getElidedCompressedPk(model.pubKey)

View File

@ -258,6 +258,14 @@ StackLayout {
contentItem: Loader { contentItem: Loader {
id: editSettingsPanelLoader id: editSettingsPanelLoader
active: false
onVisibleChanged: {
if (visible) {
active = true
}
}
function reloadContent() { function reloadContent() {
active = false active = false
active = true active = true

View File

@ -99,52 +99,47 @@ StackView {
onClicked: root.push(newPermissionView, StackView.Immediate) onClicked: root.push(newPermissionView, StackView.Immediate)
} }
contentItem: StatusScrollView { contentItem: PermissionsView {
contentHeight: (permissionsView.height + topPadding) id: permissionsView
topPadding: permissionsView.topPadding permissionsModel: root.permissionsModel
padding: 0 assetsModel: root.assetsModel
PermissionsView { collectiblesModel: root.collectiblesModel
id: permissionsView channelsModel: allChannelsTransformed
permissionsModel: root.permissionsModel
assetsModel: root.assetsModel
collectiblesModel: root.collectiblesModel
channelsModel: allChannelsTransformed
communityDetails: root.communityDetails communityDetails: root.communityDetails
viewWidth: root.viewWidth viewWidth: root.viewWidth
onEditPermissionRequested: { onEditPermissionRequested: {
const item = ModelUtils.get(root.permissionsModel, index) const item = ModelUtils.get(root.permissionsModel, index)
const properties = { const properties = {
permissionKeyToEdit: item.key, permissionKeyToEdit: item.key,
holdingsToEditModel: item.holdingsListModel, holdingsToEditModel: item.holdingsListModel,
channelsToEditModel: item.channelsListModel, channelsToEditModel: item.channelsListModel,
permissionTypeToEdit: item.permissionType, permissionTypeToEdit: item.permissionType,
isPrivateToEditValue: item.isPrivate isPrivateToEditValue: item.isPrivate
}
root.pushEditView(properties);
} }
onDuplicatePermissionRequested: { root.pushEditView(properties);
const item = ModelUtils.get(root.permissionsModel, index) }
const properties = { onDuplicatePermissionRequested: {
holdingsToEditModel: item.holdingsListModel, const item = ModelUtils.get(root.permissionsModel, index)
channelsToEditModel: item.channelsListModel,
permissionTypeToEdit: item.permissionType,
isPrivateToEditValue: item.isPrivate
}
root.pushEditView(properties); const properties = {
holdingsToEditModel: item.holdingsListModel,
channelsToEditModel: item.channelsListModel,
permissionTypeToEdit: item.permissionType,
isPrivateToEditValue: item.isPrivate
} }
onRemovePermissionRequested: { root.pushEditView(properties);
const key = ModelUtils.get(root.permissionsModel, index, "key") }
root.removePermissionRequested(key)
} onRemovePermissionRequested: {
const key = ModelUtils.get(root.permissionsModel, index, "key")
root.removePermissionRequested(key)
} }
} }
} }

View File

@ -545,7 +545,7 @@ Item {
collectiblesModel: root.store.collectiblesModel collectiblesModel: root.store.collectiblesModel
ensCommunityPermissionsEnabled: root.store.ensCommunityPermissionsEnabled ensCommunityPermissionsEnabled: root.store.ensCommunityPermissionsEnabled
permissionsModel: { permissionsModel: {
root.store.prepareTokenModelForCommunity(communityData.id) root.store.prepareTokenModelForCommunityChat(communityData.id, chatId)
return root.store.permissionsModel return root.store.permissionsModel
} }
channelsModel: root.store.chatCommunitySectionModule.model channelsModel: root.store.chatCommunitySectionModule.model

View File

@ -4,6 +4,7 @@ import QtQuick.Dialogs 1.3
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
import StatusQ 0.1
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
@ -74,14 +75,19 @@ StatusSectionLayout {
signal backToCommunityClicked signal backToCommunityClicked
backButtonName: stackLayout.children[d.currentIndex].previousPageName || "" backButtonName: {
if (!stackLayout.children[d.currentIndex].item || !stackLayout.children[d.currentIndex].item.previousPageName) {
return ""
}
return stackLayout.children[d.currentIndex].item.previousPageName
}
//navigate to a specific section and subsection //navigate to a specific section and subsection
function goTo(section: int, subSection: int) { function goTo(section: int, subSection: int) {
d.goTo(section, subSection) d.goTo(section, subSection)
} }
onBackButtonClicked: stackLayout.children[d.currentIndex].navigateBack() onBackButtonClicked: stackLayout.children[d.currentIndex].item.navigateBack()
leftPanel: Item { leftPanel: Item {
anchors.fill: parent anchors.fill: parent
@ -167,387 +173,407 @@ StatusSectionLayout {
currentIndex: d.currentIndex currentIndex: d.currentIndex
OverviewSettingsPanel { onCurrentIndexChanged: {
children[currentIndex].active = true
}
// OVERVIEW
Loader {
active: true
readonly property int sectionKey: Constants.CommunitySettingsSections.Overview readonly property int sectionKey: Constants.CommunitySettingsSections.Overview
readonly property string sectionName: qsTr("Overview") readonly property string sectionName: qsTr("Overview")
readonly property string sectionIcon: "show" readonly property string sectionIcon: "show"
readonly property bool sectionEnabled: true readonly property bool sectionEnabled: true
isOwner: root.isOwner sourceComponent: OverviewSettingsPanel {
isAdmin: root.isAdmin isOwner: root.isOwner
isTokenMaster: root.isTokenMasterOwner isAdmin: root.isAdmin
communityId: root.community.id isTokenMaster: root.isTokenMasterOwner
name: root.community.name communityId: root.community.id
description: root.community.description name: root.community.name
introMessage: root.community.introMessage description: root.community.description
outroMessage: root.community.outroMessage introMessage: root.community.introMessage
logoImageData: root.community.image outroMessage: root.community.outroMessage
bannerImageData: root.community.bannerImageData logoImageData: root.community.image
color: root.community.color bannerImageData: root.community.bannerImageData
tags: root.rootStore.communityTags color: root.community.color
selectedTags: root.filteredSelectedTags tags: root.rootStore.communityTags
archiveSupportEnabled: root.community.historyArchiveSupportEnabled selectedTags: root.filteredSelectedTags
archiveSupporVisible: root.community.isControlNode archiveSupportEnabled: root.community.historyArchiveSupportEnabled
requestToJoinEnabled: root.community.access === Constants.communityChatOnRequestAccess archiveSupporVisible: root.community.isControlNode
pinMessagesEnabled: root.community.pinMessageAllMembersEnabled requestToJoinEnabled: root.community.access === Constants.communityChatOnRequestAccess
editable: true pinMessagesEnabled: root.community.pinMessageAllMembersEnabled
loginType: root.rootStore.loginType editable: true
isControlNode: root.isControlNode loginType: root.rootStore.loginType
communitySettingsDisabled: root.communitySettingsDisabled isControlNode: root.isControlNode
overviewChartData: rootStore.overviewChartData communitySettingsDisabled: root.communitySettingsDisabled
shardingEnabled: !isAdmin && !isTokenMaster && localAppSettings.wakuV2ShardedCommunitiesEnabled overviewChartData: rootStore.overviewChartData
shardIndex: root.community.shardIndex shardingEnabled: !isAdmin && !isTokenMaster && localAppSettings.wakuV2ShardedCommunitiesEnabled
shardingInProgress: root.chatCommunitySectionModule.shardingInProgress shardIndex: root.community.shardIndex
pubsubTopic: root.community.pubsubTopic shardingInProgress: root.chatCommunitySectionModule.shardingInProgress
pubsubTopicKey: root.community.pubsubTopicKey pubsubTopic: root.community.pubsubTopic
pubsubTopicKey: root.community.pubsubTopicKey
sendModalPopup: root.sendModalPopup sendModalPopup: root.sendModalPopup
ownerToken: tokensModelChangesTracker.ownerToken ownerToken: tokensModelChangesTracker.ownerToken
isPendingOwnershipRequest: root.isPendingOwnershipRequest isPendingOwnershipRequest: root.isPendingOwnershipRequest
onFinaliseOwnershipClicked: root.finaliseOwnershipClicked() onFinaliseOwnershipClicked: root.finaliseOwnershipClicked()
onCollectCommunityMetricsMessagesCount: { onCollectCommunityMetricsMessagesCount: {
rootStore.collectCommunityMetricsMessagesCount(intervals) rootStore.collectCommunityMetricsMessagesCount(intervals)
}
onEdited: {
const error = root.chatCommunitySectionModule.editCommunity(
StatusQUtils.Utils.filterXSS(item.name),
StatusQUtils.Utils.filterXSS(item.description),
StatusQUtils.Utils.filterXSS(item.introMessage),
StatusQUtils.Utils.filterXSS(item.outroMessage),
item.options.requestToJoinEnabled ? Constants.communityChatOnRequestAccess
: Constants.communityChatPublicAccess,
item.color.toString().toUpperCase(),
item.selectedTags,
Utils.getImageAndCropInfoJson(item.logoImagePath, item.logoCropRect),
Utils.getImageAndCropInfoJson(item.bannerPath, item.bannerCropRect),
item.options.archiveSupportEnabled,
item.options.pinMessagesEnabled
)
if (error) {
errorDialog.text = error.error
errorDialog.open()
} }
}
onInviteNewPeopleClicked: { onEdited: {
Global.openInviteFriendsToCommunityPopup(root.community, const error = root.chatCommunitySectionModule.editCommunity(
root.chatCommunitySectionModule, StatusQUtils.Utils.filterXSS(item.name),
null) StatusQUtils.Utils.filterXSS(item.description),
} StatusQUtils.Utils.filterXSS(item.introMessage),
StatusQUtils.Utils.filterXSS(item.outroMessage),
item.options.requestToJoinEnabled ? Constants.communityChatOnRequestAccess
: Constants.communityChatPublicAccess,
item.color.toString().toUpperCase(),
item.selectedTags,
Utils.getImageAndCropInfoJson(item.logoImagePath, item.logoCropRect),
Utils.getImageAndCropInfoJson(item.bannerPath, item.bannerCropRect),
item.options.archiveSupportEnabled,
item.options.pinMessagesEnabled
)
if (error) {
errorDialog.text = error.error
errorDialog.open()
}
}
onAirdropTokensClicked: root.goTo(Constants.CommunitySettingsSections.Airdrops) onInviteNewPeopleClicked: {
onExportControlNodeClicked: { Global.openInviteFriendsToCommunityPopup(root.community,
if(!root.isControlNode) root.chatCommunitySectionModule,
return null)
}
Global.openExportControlNodePopup(root.community) onAirdropTokensClicked: root.goTo(Constants.CommunitySettingsSections.Airdrops)
} onExportControlNodeClicked: {
if(!root.isControlNode)
return
onImportControlNodeClicked: { Global.openExportControlNodePopup(root.community)
if(root.isControlNode) }
return
Global.openImportControlNodePopup(root.community) onImportControlNodeClicked: {
} if(root.isControlNode)
return
onMintOwnerTokenClicked: { Global.openImportControlNodePopup(root.community)
root.goTo(Constants.CommunitySettingsSections.MintTokens) }
mintPanel.openNewTokenForm(false/*Collectible owner token*/)
}
onShardIndexEdited: if (root.community.shardIndex !== shardIndex) { onMintOwnerTokenClicked: {
root.chatCommunitySectionModule.setCommunityShard(shardIndex) root.goTo(Constants.CommunitySettingsSections.MintTokens)
mintPanel.openNewTokenForm(false/*Collectible owner token*/)
}
onShardIndexEdited: if (root.community.shardIndex !== shardIndex) {
root.chatCommunitySectionModule.setCommunityShard(shardIndex)
}
} }
} }
MembersSettingsPanel { // MEMBERS
Loader {
active: false
readonly property int sectionKey: Constants.CommunitySettingsSections.Members readonly property int sectionKey: Constants.CommunitySettingsSections.Members
readonly property string sectionName: qsTr("Members") readonly property string sectionName: qsTr("Members")
readonly property string sectionIcon: "group-chat" readonly property string sectionIcon: "group-chat"
readonly property bool sectionEnabled: true readonly property bool sectionEnabled: true
rootStore: root.rootStore sourceComponent: MembersSettingsPanel {
membersModel: root.community.members rootStore: root.rootStore
bannedMembersModel: root.community.bannedMembers membersModel: root.community.members
pendingMemberRequestsModel: root.community.pendingMemberRequests bannedMembersModel: root.community.bannedMembers
declinedMemberRequestsModel: root.community.declinedMemberRequests pendingMemberRequestsModel: root.community.pendingMemberRequests
editable: root.isAdmin || root.isOwner || root.isTokenMasterOwner declinedMemberRequestsModel: root.community.declinedMemberRequests
memberRole: community.memberRole editable: root.isAdmin || root.isOwner || root.isTokenMasterOwner
communityName: root.community.name memberRole: community.memberRole
communityName: root.community.name
onKickUserClicked: root.rootStore.removeUserFromCommunity(id) onKickUserClicked: root.rootStore.removeUserFromCommunity(id)
onBanUserClicked: root.rootStore.banUserFromCommunity(id, deleteAllMessages) onBanUserClicked: root.rootStore.banUserFromCommunity(id, deleteAllMessages)
onUnbanUserClicked: root.rootStore.unbanUserFromCommunity(id) onUnbanUserClicked: root.rootStore.unbanUserFromCommunity(id)
onAcceptRequestToJoin: root.rootStore.acceptRequestToJoinCommunity(id, root.community.id) onAcceptRequestToJoin: root.rootStore.acceptRequestToJoinCommunity(id, root.community.id)
onDeclineRequestToJoin: root.rootStore.declineRequestToJoinCommunity(id, root.community.id) onDeclineRequestToJoin: root.rootStore.declineRequestToJoinCommunity(id, root.community.id)
onViewMemberMessagesClicked: { onViewMemberMessagesClicked: {
root.rootStore.loadCommunityMemberMessages(root.community.id, pubKey) root.rootStore.loadCommunityMemberMessages(root.community.id, pubKey)
Global.openCommunityMemberMessagesPopupRequested(root.rootStore, root.chatCommunitySectionModule, pubKey, displayName) Global.openCommunityMemberMessagesPopupRequested(root.rootStore, root.chatCommunitySectionModule, pubKey, displayName)
}
} }
} }
PermissionsSettingsPanel { // PERMISISONS
Loader {
active: false
readonly property int sectionKey: Constants.CommunitySettingsSections.Permissions readonly property int sectionKey: Constants.CommunitySettingsSections.Permissions
readonly property string sectionName: qsTr("Permissions") readonly property string sectionName: qsTr("Permissions")
readonly property string sectionIcon: "objects" readonly property string sectionIcon: "objects"
readonly property bool sectionEnabled: true readonly property bool sectionEnabled: true
readonly property PermissionsStore permissionsStore: sourceComponent: PermissionsSettingsPanel {
rootStore.permissionsStore readonly property PermissionsStore permissionsStore:
rootStore.permissionsStore
permissionsModel: permissionsStore.permissionsModel permissionsModel: permissionsStore.permissionsModel
// temporary solution to provide icons for assets, similar // temporary solution to provide icons for assets, similar
// method is used in wallet (constructing filename from asset's // method is used in wallet (constructing filename from asset's
// symbol) and is intended to be replaced by more robust // symbol) and is intended to be replaced by more robust
// solution soon. // solution soon.
assetsModel: rootStore.assetsModel assetsModel: rootStore.assetsModel
collectiblesModel: rootStore.collectiblesModel collectiblesModel: rootStore.collectiblesModel
channelsModel: rootStore.chatCommunitySectionModule.model channelsModel: rootStore.chatCommunitySectionModule.model
ensCommunityPermissionsEnabled: rootStore.ensCommunityPermissionsEnabled ensCommunityPermissionsEnabled: rootStore.ensCommunityPermissionsEnabled
communityDetails: d.communityDetails communityDetails: d.communityDetails
onCreatePermissionRequested: onCreatePermissionRequested:
permissionsStore.createPermission(holdings, permissionType, permissionsStore.createPermission(holdings, permissionType,
isPrivate, channels) isPrivate, channels)
onUpdatePermissionRequested: onUpdatePermissionRequested:
permissionsStore.editPermission( permissionsStore.editPermission(
key, holdings, permissionType, channels, isPrivate) key, holdings, permissionType, channels, isPrivate)
onRemovePermissionRequested: onRemovePermissionRequested:
permissionsStore.removePermission(key) permissionsStore.removePermission(key)
onNavigateToMintTokenSettings: { onNavigateToMintTokenSettings: {
root.goTo(Constants.CommunitySettingsSections.MintTokens) root.goTo(Constants.CommunitySettingsSections.MintTokens)
mintPanel.openNewTokenForm(isAssetType) mintPanelLoader.item.openNewTokenForm(isAssetType)
}
} }
} }
MintTokensSettingsPanel { // TOKEN
id: mintPanel Loader {
id: mintPanelLoader
active: false
readonly property int sectionKey: Constants.CommunitySettingsSections.MintTokens readonly property int sectionKey: Constants.CommunitySettingsSections.MintTokens
readonly property string sectionName: qsTr("Tokens") readonly property string sectionName: qsTr("Tokens")
readonly property string sectionIcon: "token" readonly property string sectionIcon: "token"
readonly property bool sectionEnabled: true readonly property bool sectionEnabled: true
enabledChainIds: root.enabledChainIds
readonly property CommunityTokensStore communityTokensStore: sourceComponent: MintTokensSettingsPanel {
rootStore.communityTokensStore enabledChainIds: root.enabledChainIds
// General community props readonly property CommunityTokensStore communityTokensStore:
communityId: root.community.id rootStore.communityTokensStore
communityName: root.community.name
communityLogo: root.community.image
communityColor: root.community.color
sendModalPopup: root.sendModalPopup
// User profile props // General community props
isOwner: root.isOwner communityId: root.community.id
isAdmin: root.isAdmin communityName: root.community.name
isTokenMasterOwner: root.isTokenMasterOwner communityLogo: root.community.image
communityColor: root.community.color
sendModalPopup: root.sendModalPopup
// Owner and TMaster properties // User profile props
isOwnerTokenDeployed: tokensModelChangesTracker.isOwnerTokenDeployed isOwner: root.isOwner
isTMasterTokenDeployed: tokensModelChangesTracker.isTMasterTokenDeployed isAdmin: root.isAdmin
anyPrivilegedTokenFailed: tokensModelChangesTracker.isOwnerTokenFailed || tokensModelChangesTracker.isTMasterTokenFailed isTokenMasterOwner: root.isTokenMasterOwner
ownerOrTMasterTokenItemsExist: tokensModelChangesTracker.ownerOrTMasterTokenItemsExist
// Models // Owner and TMaster properties
tokensModel: root.community.communityTokens isOwnerTokenDeployed: tokensModelChangesTracker.isOwnerTokenDeployed
membersModel: root.community.members isTMasterTokenDeployed: tokensModelChangesTracker.isTMasterTokenDeployed
flatNetworks: communityTokensStore.filteredFlatModel anyPrivilegedTokenFailed: tokensModelChangesTracker.isOwnerTokenFailed || tokensModelChangesTracker.isTMasterTokenFailed
accounts: root.walletAccountsModel ownerOrTMasterTokenItemsExist: tokensModelChangesTracker.ownerOrTMasterTokenItemsExist
referenceAssetsBySymbolModel: root.tokensStore.assetsBySymbolModel
onRegisterDeployFeesSubscriber: d.feesBroker.registerDeployFeesSubscriber(feeSubscriber) // Models
tokensModel: root.community.communityTokens
membersModel: root.community.members
flatNetworks: communityTokensStore.filteredFlatModel
accounts: root.walletAccountsModel
referenceAssetsBySymbolModel: root.tokensStore.assetsBySymbolModel
onRegisterSelfDestructFeesSubscriber: d.feesBroker.registerSelfDestructFeesSubscriber(feeSubscriber) onRegisterDeployFeesSubscriber: d.feesBroker.registerDeployFeesSubscriber(feeSubscriber)
onRegisterBurnTokenFeesSubscriber: d.feesBroker.registerBurnFeesSubscriber(feeSubscriber) onRegisterSelfDestructFeesSubscriber: d.feesBroker.registerSelfDestructFeesSubscriber(feeSubscriber)
onStartTokenHoldersManagement: communityTokensStore.startTokenHoldersManagement(root.community.id, chainId, address) onRegisterBurnTokenFeesSubscriber: d.feesBroker.registerBurnFeesSubscriber(feeSubscriber)
onStopTokenHoldersManagement: communityTokensStore.stopTokenHoldersManagement() onStartTokenHoldersManagement: communityTokensStore.startTokenHoldersManagement(root.community.id, chainId, address)
onEnableNetwork: root.enableNetwork(chainId) onStopTokenHoldersManagement: communityTokensStore.stopTokenHoldersManagement()
onMintCollectible: onEnableNetwork: root.enableNetwork(chainId)
communityTokensStore.deployCollectible(
root.community.id, collectibleItem)
onMintAsset: onMintCollectible:
communityTokensStore.deployAsset(root.community.id, assetItem) communityTokensStore.deployCollectible(
root.community.id, collectibleItem)
onMintOwnerToken: onMintAsset:
communityTokensStore.deployOwnerToken( communityTokensStore.deployAsset(root.community.id, assetItem)
root.community.id, ownerToken, tMasterToken)
onRemotelyDestructCollectibles: onMintOwnerToken:
communityTokensStore.remoteSelfDestructCollectibles( communityTokensStore.deployOwnerToken(
root.community.id, walletsAndAmounts, tokenKey, accountAddress) root.community.id, ownerToken, tMasterToken)
onRemotelyDestructAndBan: onRemotelyDestructCollectibles:
communityTokensStore.remotelyDestructAndBan( communityTokensStore.remoteSelfDestructCollectibles(
root.community.id, contactId, tokenKey, accountAddress) root.community.id, walletsAndAmounts, tokenKey, accountAddress)
onRemotelyDestructAndKick: onRemotelyDestructAndBan:
communityTokensStore.remotelyDestructAndKick( communityTokensStore.remotelyDestructAndBan(
root.community.id, contactId, tokenKey, accountAddress) root.community.id, contactId, tokenKey, accountAddress)
onBurnToken: onRemotelyDestructAndKick:
communityTokensStore.burnToken(root.community.id, tokenKey, amount, accountAddress) communityTokensStore.remotelyDestructAndKick(
root.community.id, contactId, tokenKey, accountAddress)
onDeleteToken: onBurnToken:
communityTokensStore.deleteToken(root.community.id, tokenKey) communityTokensStore.burnToken(root.community.id, tokenKey, amount, accountAddress)
onRefreshToken: onDeleteToken:
communityTokensStore.refreshToken(tokenKey) communityTokensStore.deleteToken(root.community.id, tokenKey)
onAirdropToken: { onRefreshToken:
root.goTo(Constants.CommunitySettingsSections.Airdrops) communityTokensStore.refreshToken(tokenKey)
// Force a token selection to be airdroped with given amount onAirdropToken: {
airdropPanel.selectToken(tokenKey, amount, type) root.goTo(Constants.CommunitySettingsSections.Airdrops)
// Set given addresses as recipients // Force a token selection to be airdroped with given amount
airdropPanel.addAddresses(addresses) airdropPanelLoader.item.selectToken(tokenKey, amount, type)
// Set given addresses as recipients
airdropPanelLoader.item.addAddresses(addresses)
}
onKickUserRequested: root.rootStore.removeUserFromCommunity(contactId)
onBanUserRequested: root.rootStore.banUserFromCommunity(contactId)
} }
onKickUserRequested: root.rootStore.removeUserFromCommunity(contactId)
onBanUserRequested: root.rootStore.banUserFromCommunity(contactId)
} }
AirdropsSettingsPanel { // AIRDROPS
id: airdropPanel Loader {
id: airdropPanelLoader
active: false
readonly property int sectionKey: Constants.CommunitySettingsSections.Airdrops readonly property int sectionKey: Constants.CommunitySettingsSections.Airdrops
readonly property string sectionName: qsTr("Airdrops") readonly property string sectionName: qsTr("Airdrops")
readonly property string sectionIcon: "airdrop" readonly property string sectionIcon: "airdrop"
readonly property bool sectionEnabled: true readonly property bool sectionEnabled: true
communityDetails: d.communityDetails sourceComponent: AirdropsSettingsPanel {
id: airdropsSettingsPanel
// Profile type communityDetails: d.communityDetails
isOwner: root.isOwner
isTokenMasterOwner: root.isTokenMasterOwner
isAdmin: root.isAdmin
// Owner and TMaster properties // Profile type
isOwnerTokenDeployed: tokensModelChangesTracker.isOwnerTokenDeployed isOwner: root.isOwner
isTMasterTokenDeployed: tokensModelChangesTracker.isTMasterTokenDeployed isTokenMasterOwner: root.isTokenMasterOwner
isAdmin: root.isAdmin
readonly property CommunityTokensStore communityTokensStore: // Owner and TMaster properties
rootStore.communityTokensStore isOwnerTokenDeployed: tokensModelChangesTracker.isOwnerTokenDeployed
isTMasterTokenDeployed: tokensModelChangesTracker.isTMasterTokenDeployed
readonly property var communityTokens: root.community.communityTokens readonly property CommunityTokensStore communityTokensStore:
rootStore.communityTokensStore
Loader { readonly property RolesRenamingModel renamedTokensBySymbolModel: RolesRenamingModel {
id: assetsModelLoader sourceModel: root.community.communityTokens || null
active: airdropPanel.communityTokens mapping: [
RoleRename {
from: "symbol"
to: "key"
},
RoleRename {
from: "image"
to: "iconSource"
}
]
}
sourceComponent: SortFilterProxyModel { assetsModel: SortFilterProxyModel {
sourceModel: renamedTokensBySymbolModel
sourceModel: airdropPanel.communityTokens
filters: ValueFilter { filters: ValueFilter {
roleName: "tokenType" roleName: "tokenType"
value: Constants.TokenType.ERC20 value: Constants.TokenType.ERC20
} }
proxyRoles: [ proxyRoles: [
ExpressionRole { ConstantRole {
name: "category" name: "category"
value: TokenCategories.Category.Own
// Singleton cannot be used directly in the expression
readonly property int category: TokenCategories.Category.Own
expression: category
}, },
ExpressionRole { ConstantRole {
name: "iconSource"
expression: model.image
},
ExpressionRole {
name: "key"
expression: model.symbol
},
ExpressionRole {
name: "communityId" name: "communityId"
expression: "" value: ""
} }
] ]
} }
} collectiblesModel: SortFilterProxyModel {
sourceModel: renamedTokensBySymbolModel
Loader {
id: collectiblesModelLoader
active: airdropPanel.communityTokens
sourceComponent: SortFilterProxyModel {
sourceModel: airdropPanel.communityTokens
filters: [ filters: [
ValueFilter { ValueFilter {
roleName: "tokenType" roleName: "tokenType"
value: Constants.TokenType.ERC721 value: Constants.TokenType.ERC721
}, },
ExpressionFilter { AnyOf {
function getPrivileges(privilegesLevel) { ValueFilter {
return privilegesLevel === Constants.TokenPrivilegesLevel.Community || roleName: "privilegesLevel"
(root.isOwner && privilegesLevel === Constants.TokenPrivilegesLevel.TMaster) value: Constants.TokenPrivilegesLevel.Community
}
ValueFilter {
roleName: "privilegesLevel"
value: Constants.TokenPrivilegesLevel.TMaster
enabled: root.isOwner
} }
expression: { return getPrivileges(model.privilegesLevel) }
} }
] ]
proxyRoles: [ proxyRoles: [
ExpressionRole { ConstantRole {
name: "category" name: "category"
value: TokenCategories.Category.Own
// Singleton cannot be used directly in the epression
readonly property int category: TokenCategories.Category.Own
expression: category
}, },
ExpressionRole { ConstantRole {
name: "iconSource"
expression: model.image
},
ExpressionRole {
name: "key"
expression: model.symbol
},
ExpressionRole {
name: "communityId" name: "communityId"
expression: "" value: ""
} }
] ]
} }
Connections {
target: root.rootStore.communityTokensStore
function onAirdropStateChanged(communityId, tokenName, chainName, status, url) {
if (root.community.id !== communityId) {
return
}
if (status == Constants.ContractTransactionStatus.InProgress) {
airdropsSettingsPanel.navigateBack()
}
}
}
membersModel: community.members
enabledChainIds: root.enabledChainIds
onEnableNetwork: root.enableNetwork(chainId)
accountsModel: root.walletAccountsModel
onAirdropClicked: communityTokensStore.airdrop(
root.community.id, airdropTokens, addresses,
feeAccountAddress)
onNavigateToMintTokenSettings: {
root.goTo(Constants.CommunitySettingsSections.MintTokens)
mintPanelLoader.item.openNewTokenForm(isAssetType)
}
onRegisterAirdropFeeSubscriber: d.feesBroker.registerAirdropFeesSubscriber(feeSubscriber)
} }
assetsModel: assetsModelLoader.item
collectiblesModel: collectiblesModelLoader.item
membersModel: community.members
enabledChainIds: root.enabledChainIds
onEnableNetwork: root.enableNetwork(chainId)
accountsModel: root.walletAccountsModel
onAirdropClicked: communityTokensStore.airdrop(
root.community.id, airdropTokens, addresses,
feeAccountAddress)
onNavigateToMintTokenSettings: {
root.goTo(Constants.CommunitySettingsSections.MintTokens)
mintPanel.openNewTokenForm(isAssetType)
}
onRegisterAirdropFeeSubscriber: d.feesBroker.registerAirdropFeesSubscriber(feeSubscriber)
} }
} }
@ -723,7 +749,6 @@ StatusSectionLayout {
case Constants.ContractTransactionStatus.InProgress: case Constants.ContractTransactionStatus.InProgress:
title = qsTr("Airdrop on %1 in progress...").arg(chainName) title = qsTr("Airdrop on %1 in progress...").arg(chainName)
loading = true loading = true
airdropPanel.navigateBack()
break break
case Constants.ContractTransactionStatus.Completed: case Constants.ContractTransactionStatus.Completed:
title = qsTr("Airdrop on %1 in complete").arg(chainName) title = qsTr("Airdrop on %1 in complete").arg(chainName)

View File

@ -43,7 +43,7 @@ ColumnLayout {
signal removePermissionRequested(int index) signal removePermissionRequested(int index)
signal userRestrictionsToggled(bool checked) signal userRestrictionsToggled(bool checked)
readonly property alias count: repeater.count readonly property alias count: listView.count
Connections { Connections {
target: root.communityDetails target: root.communityDetails
@ -58,7 +58,7 @@ ColumnLayout {
} }
} }
function resetCommunityItemModel(){ function resetCommunityItemModel() {
communityItemModel.clear() communityItemModel.clear()
communityItemModel.append({ communityItemModel.append({
text: root.communityDetails.name, text: root.communityDetails.name,
@ -87,14 +87,18 @@ ColumnLayout {
] ]
} }
StatusListView {
Repeater { id: listView
id: repeater reuseItems: true
model: root.permissionsModel model: root.permissionsModel
spacing: 24
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredHeight: contentHeight
Layout.topMargin: root.topPadding
delegate: PermissionItem { delegate: PermissionItem {
Layout.fillWidth: true width: root.viewWidth
holdingsListModel: HoldingsSelectionModel { holdingsListModel: HoldingsSelectionModel {
sourceModel: model.holdingsListModel sourceModel: model.holdingsListModel
@ -155,6 +159,7 @@ ColumnLayout {
root.userRestrictionsToggled(checked); root.userRestrictionsToggled(checked);
} }
} }
ConfirmationDialog { ConfirmationDialog {
id: declineAllDialog id: declineAllDialog

View File

@ -91,13 +91,6 @@ Item {
} }
} }
] ]
proxyRoles: ExpressionRole {
function displayNameProxy(nickname, ensName, displayName, aliasName) {
return ProfileUtils.displayName(nickname, ensName, displayName, aliasName)
}
name: "preferredDisplayName"
expression: displayNameProxy(model.localNickname, model.ensName, model.displayName, model.alias)
}
sorters: [ sorters: [
StringSorter { StringSorter {

View File

@ -21,20 +21,6 @@ QtObject {
//TODO: backend implementation //TODO: backend implementation
} }
// TODO: Replace with proper backend implementation
// This is per chat, not per community
readonly property bool viewAndPostCriteriaMet: {
if (selectedChannelPermissionsModel.count == 0)
return true
for (var i = 0; i < selectedChannelPermissionsModel.count; i++) {
var permissionItem = selectedChannelPermissionsModel.get(i);
if (permissionItem && permissionItem.tokenCriteriaMet)
return true
}
return false
}
readonly property var selectedChannelPermissionsModel: SortFilterProxyModel { readonly property var selectedChannelPermissionsModel: SortFilterProxyModel {
id: selectedChannelPermissionsModel id: selectedChannelPermissionsModel
sourceModel: root.permissionsModel sourceModel: root.permissionsModel