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:
parent
c09de56678
commit
1cad66bb2c
|
@ -236,6 +236,9 @@ method joinCommunityOrEditSharedAddresses*(self: AccessInterface) {.base.} =
|
|||
method prepareTokenModelForCommunity*(self: AccessInterface, communityId: string) {.base.} =
|
||||
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.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -886,6 +886,25 @@ method prepareTokenModelForCommunity*(self: Module, communityId: string) =
|
|||
self.view.spectatedCommunityPermissionModel.setItems(tokenPermissionsItems)
|
||||
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]) =
|
||||
let community = self.controller.getCommunityById(communityId)
|
||||
for id, criteriaResult in permissions:
|
||||
|
|
|
@ -347,6 +347,9 @@ QtObject:
|
|||
proc prepareTokenModelForCommunity(self: View, communityId: string) {.slot.} =
|
||||
self.delegate.prepareTokenModelForCommunity(communityId)
|
||||
|
||||
proc prepareTokenModelForCommunityChat(self: View, communityId: string, chatId: string) {.slot.} =
|
||||
self.delegate.prepareTokenModelForCommunityChat(communityId, chatId)
|
||||
|
||||
proc signProfileKeypairAndAllNonKeycardKeypairs*(self: View) {.slot.} =
|
||||
self.delegate.signProfileKeypairAndAllNonKeycardKeypairs()
|
||||
|
||||
|
|
|
@ -132,6 +132,10 @@ QtObject {
|
|||
root.communitiesModuleInst.prepareTokenModelForCommunity(publicKey)
|
||||
}
|
||||
|
||||
function prepareTokenModelForCommunityChat(publicKey, chatId) {
|
||||
root.communitiesModuleInst.prepareTokenModelForCommunityChat(publicKey, chatId)
|
||||
}
|
||||
|
||||
readonly property bool allChannelsAreHiddenBecauseNotPermitted: root.chatCommunitySectionModule.allChannelsAreHiddenBecauseNotPermitted &&
|
||||
!root.chatCommunitySectionModule.requiresTokenPermissionToJoin
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ QtObject {
|
|||
filters: [
|
||||
FastExpressionFilter {
|
||||
function filterPredicate(id, permissionType) {
|
||||
return !PermissionTypes.isCommunityPermission(permissionType) && root.permissionsModel.belongsToChat(id, root.channelId)
|
||||
return !PermissionTypes.isCommunityPermission(permissionType)
|
||||
}
|
||||
expression: {
|
||||
return filterPredicate(model.id, model.permissionType)
|
||||
|
|
|
@ -3,6 +3,7 @@ import QtQuick.Controls 2.15
|
|||
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import AppLayouts.Communities.controls 1.0
|
||||
import AppLayouts.Communities.layouts 1.0
|
||||
import AppLayouts.Communities.views 1.0
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
|
|
|
@ -5,6 +5,7 @@ import QtQuick.Controls 2.14
|
|||
import StatusQ 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
@ -70,23 +71,31 @@ Item {
|
|||
|
||||
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 : [
|
||||
StringSorter {
|
||||
roleName: "preferredDisplayName"
|
||||
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
|
||||
|
||||
|
@ -288,8 +297,6 @@ Item {
|
|||
readonly property string title: model.preferredDisplayName
|
||||
|
||||
width: membersList.width
|
||||
visible: memberSearch.text === "" || title.toLowerCase().includes(memberSearch.text.toLowerCase())
|
||||
height: visible ? implicitHeight : 0
|
||||
color: "transparent"
|
||||
|
||||
pubKey: model.isEnsVerified ? "" : Utils.getElidedCompressedPk(model.pubKey)
|
||||
|
|
|
@ -258,6 +258,14 @@ StackLayout {
|
|||
contentItem: Loader {
|
||||
id: editSettingsPanelLoader
|
||||
|
||||
active: false
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
active = true
|
||||
}
|
||||
}
|
||||
|
||||
function reloadContent() {
|
||||
active = false
|
||||
active = true
|
||||
|
|
|
@ -99,11 +99,7 @@ StackView {
|
|||
onClicked: root.push(newPermissionView, StackView.Immediate)
|
||||
}
|
||||
|
||||
contentItem: StatusScrollView {
|
||||
contentHeight: (permissionsView.height + topPadding)
|
||||
topPadding: permissionsView.topPadding
|
||||
padding: 0
|
||||
PermissionsView {
|
||||
contentItem: PermissionsView {
|
||||
id: permissionsView
|
||||
permissionsModel: root.permissionsModel
|
||||
assetsModel: root.assetsModel
|
||||
|
@ -147,7 +143,6 @@ StackView {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: newPermissionView
|
||||
|
|
|
@ -545,7 +545,7 @@ Item {
|
|||
collectiblesModel: root.store.collectiblesModel
|
||||
ensCommunityPermissionsEnabled: root.store.ensCommunityPermissionsEnabled
|
||||
permissionsModel: {
|
||||
root.store.prepareTokenModelForCommunity(communityData.id)
|
||||
root.store.prepareTokenModelForCommunityChat(communityData.id, chatId)
|
||||
return root.store.permissionsModel
|
||||
}
|
||||
channelsModel: root.store.chatCommunitySectionModule.model
|
||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick.Dialogs 1.3
|
|||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
|
@ -74,14 +75,19 @@ StatusSectionLayout {
|
|||
|
||||
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
|
||||
function goTo(section: int, subSection: int) {
|
||||
d.goTo(section, subSection)
|
||||
}
|
||||
|
||||
onBackButtonClicked: stackLayout.children[d.currentIndex].navigateBack()
|
||||
onBackButtonClicked: stackLayout.children[d.currentIndex].item.navigateBack()
|
||||
|
||||
leftPanel: Item {
|
||||
anchors.fill: parent
|
||||
|
@ -167,12 +173,20 @@ StatusSectionLayout {
|
|||
|
||||
currentIndex: d.currentIndex
|
||||
|
||||
OverviewSettingsPanel {
|
||||
onCurrentIndexChanged: {
|
||||
children[currentIndex].active = true
|
||||
}
|
||||
|
||||
// OVERVIEW
|
||||
Loader {
|
||||
active: true
|
||||
|
||||
readonly property int sectionKey: Constants.CommunitySettingsSections.Overview
|
||||
readonly property string sectionName: qsTr("Overview")
|
||||
readonly property string sectionIcon: "show"
|
||||
readonly property bool sectionEnabled: true
|
||||
|
||||
sourceComponent: OverviewSettingsPanel {
|
||||
isOwner: root.isOwner
|
||||
isAdmin: root.isAdmin
|
||||
isTokenMaster: root.isTokenMasterOwner
|
||||
|
@ -263,13 +277,18 @@ StatusSectionLayout {
|
|||
root.chatCommunitySectionModule.setCommunityShard(shardIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MEMBERS
|
||||
Loader {
|
||||
active: false
|
||||
|
||||
MembersSettingsPanel {
|
||||
readonly property int sectionKey: Constants.CommunitySettingsSections.Members
|
||||
readonly property string sectionName: qsTr("Members")
|
||||
readonly property string sectionIcon: "group-chat"
|
||||
readonly property bool sectionEnabled: true
|
||||
|
||||
sourceComponent: MembersSettingsPanel {
|
||||
rootStore: root.rootStore
|
||||
membersModel: root.community.members
|
||||
bannedMembersModel: root.community.bannedMembers
|
||||
|
@ -289,13 +308,17 @@ StatusSectionLayout {
|
|||
Global.openCommunityMemberMessagesPopupRequested(root.rootStore, root.chatCommunitySectionModule, pubKey, displayName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PermissionsSettingsPanel {
|
||||
// PERMISISONS
|
||||
Loader {
|
||||
active: false
|
||||
readonly property int sectionKey: Constants.CommunitySettingsSections.Permissions
|
||||
readonly property string sectionName: qsTr("Permissions")
|
||||
readonly property string sectionIcon: "objects"
|
||||
readonly property bool sectionEnabled: true
|
||||
|
||||
sourceComponent: PermissionsSettingsPanel {
|
||||
readonly property PermissionsStore permissionsStore:
|
||||
rootStore.permissionsStore
|
||||
|
||||
|
@ -328,17 +351,21 @@ StatusSectionLayout {
|
|||
|
||||
onNavigateToMintTokenSettings: {
|
||||
root.goTo(Constants.CommunitySettingsSections.MintTokens)
|
||||
mintPanel.openNewTokenForm(isAssetType)
|
||||
mintPanelLoader.item.openNewTokenForm(isAssetType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MintTokensSettingsPanel {
|
||||
id: mintPanel
|
||||
|
||||
// TOKEN
|
||||
Loader {
|
||||
id: mintPanelLoader
|
||||
active: false
|
||||
readonly property int sectionKey: Constants.CommunitySettingsSections.MintTokens
|
||||
readonly property string sectionName: qsTr("Tokens")
|
||||
readonly property string sectionIcon: "token"
|
||||
readonly property bool sectionEnabled: true
|
||||
|
||||
sourceComponent: MintTokensSettingsPanel {
|
||||
enabledChainIds: root.enabledChainIds
|
||||
|
||||
readonly property CommunityTokensStore communityTokensStore:
|
||||
|
@ -417,24 +444,30 @@ StatusSectionLayout {
|
|||
root.goTo(Constants.CommunitySettingsSections.Airdrops)
|
||||
|
||||
// Force a token selection to be airdroped with given amount
|
||||
airdropPanel.selectToken(tokenKey, amount, type)
|
||||
airdropPanelLoader.item.selectToken(tokenKey, amount, type)
|
||||
|
||||
// Set given addresses as recipients
|
||||
airdropPanel.addAddresses(addresses)
|
||||
airdropPanelLoader.item.addAddresses(addresses)
|
||||
}
|
||||
|
||||
onKickUserRequested: root.rootStore.removeUserFromCommunity(contactId)
|
||||
onBanUserRequested: root.rootStore.banUserFromCommunity(contactId)
|
||||
}
|
||||
}
|
||||
|
||||
AirdropsSettingsPanel {
|
||||
id: airdropPanel
|
||||
// AIRDROPS
|
||||
Loader {
|
||||
id: airdropPanelLoader
|
||||
active: false
|
||||
|
||||
readonly property int sectionKey: Constants.CommunitySettingsSections.Airdrops
|
||||
readonly property string sectionName: qsTr("Airdrops")
|
||||
readonly property string sectionIcon: "airdrop"
|
||||
readonly property bool sectionEnabled: true
|
||||
|
||||
sourceComponent: AirdropsSettingsPanel {
|
||||
id: airdropsSettingsPanel
|
||||
|
||||
communityDetails: d.communityDetails
|
||||
|
||||
// Profile type
|
||||
|
@ -449,90 +482,82 @@ StatusSectionLayout {
|
|||
readonly property CommunityTokensStore communityTokensStore:
|
||||
rootStore.communityTokensStore
|
||||
|
||||
readonly property var communityTokens: root.community.communityTokens
|
||||
readonly property RolesRenamingModel renamedTokensBySymbolModel: RolesRenamingModel {
|
||||
sourceModel: root.community.communityTokens || null
|
||||
mapping: [
|
||||
RoleRename {
|
||||
from: "symbol"
|
||||
to: "key"
|
||||
},
|
||||
RoleRename {
|
||||
from: "image"
|
||||
to: "iconSource"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: assetsModelLoader
|
||||
active: airdropPanel.communityTokens
|
||||
|
||||
sourceComponent: SortFilterProxyModel {
|
||||
|
||||
sourceModel: airdropPanel.communityTokens
|
||||
assetsModel: SortFilterProxyModel {
|
||||
sourceModel: renamedTokensBySymbolModel
|
||||
filters: ValueFilter {
|
||||
roleName: "tokenType"
|
||||
value: Constants.TokenType.ERC20
|
||||
}
|
||||
proxyRoles: [
|
||||
ExpressionRole {
|
||||
ConstantRole {
|
||||
name: "category"
|
||||
|
||||
// Singleton cannot be used directly in the expression
|
||||
readonly property int category: TokenCategories.Category.Own
|
||||
expression: category
|
||||
value: TokenCategories.Category.Own
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "iconSource"
|
||||
expression: model.image
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "key"
|
||||
expression: model.symbol
|
||||
},
|
||||
ExpressionRole {
|
||||
ConstantRole {
|
||||
name: "communityId"
|
||||
expression: ""
|
||||
value: ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: collectiblesModelLoader
|
||||
active: airdropPanel.communityTokens
|
||||
|
||||
sourceComponent: SortFilterProxyModel {
|
||||
|
||||
sourceModel: airdropPanel.communityTokens
|
||||
collectiblesModel: SortFilterProxyModel {
|
||||
sourceModel: renamedTokensBySymbolModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "tokenType"
|
||||
value: Constants.TokenType.ERC721
|
||||
},
|
||||
ExpressionFilter {
|
||||
function getPrivileges(privilegesLevel) {
|
||||
return privilegesLevel === Constants.TokenPrivilegesLevel.Community ||
|
||||
(root.isOwner && privilegesLevel === Constants.TokenPrivilegesLevel.TMaster)
|
||||
AnyOf {
|
||||
ValueFilter {
|
||||
roleName: "privilegesLevel"
|
||||
value: Constants.TokenPrivilegesLevel.Community
|
||||
}
|
||||
ValueFilter {
|
||||
roleName: "privilegesLevel"
|
||||
value: Constants.TokenPrivilegesLevel.TMaster
|
||||
enabled: root.isOwner
|
||||
}
|
||||
|
||||
expression: { return getPrivileges(model.privilegesLevel) }
|
||||
}
|
||||
]
|
||||
proxyRoles: [
|
||||
ExpressionRole {
|
||||
ConstantRole {
|
||||
name: "category"
|
||||
|
||||
// Singleton cannot be used directly in the epression
|
||||
readonly property int category: TokenCategories.Category.Own
|
||||
expression: category
|
||||
value: TokenCategories.Category.Own
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "iconSource"
|
||||
expression: model.image
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "key"
|
||||
expression: model.symbol
|
||||
},
|
||||
ExpressionRole {
|
||||
ConstantRole {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assetsModel: assetsModelLoader.item
|
||||
collectiblesModel: collectiblesModelLoader.item
|
||||
membersModel: community.members
|
||||
enabledChainIds: root.enabledChainIds
|
||||
onEnableNetwork: root.enableNetwork(chainId)
|
||||
|
@ -544,12 +569,13 @@ StatusSectionLayout {
|
|||
|
||||
onNavigateToMintTokenSettings: {
|
||||
root.goTo(Constants.CommunitySettingsSections.MintTokens)
|
||||
mintPanel.openNewTokenForm(isAssetType)
|
||||
mintPanelLoader.item.openNewTokenForm(isAssetType)
|
||||
}
|
||||
|
||||
onRegisterAirdropFeeSubscriber: d.feesBroker.registerAirdropFeesSubscriber(feeSubscriber)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
@ -723,7 +749,6 @@ StatusSectionLayout {
|
|||
case Constants.ContractTransactionStatus.InProgress:
|
||||
title = qsTr("Airdrop on %1 in progress...").arg(chainName)
|
||||
loading = true
|
||||
airdropPanel.navigateBack()
|
||||
break
|
||||
case Constants.ContractTransactionStatus.Completed:
|
||||
title = qsTr("Airdrop on %1 in complete").arg(chainName)
|
||||
|
|
|
@ -43,7 +43,7 @@ ColumnLayout {
|
|||
signal removePermissionRequested(int index)
|
||||
signal userRestrictionsToggled(bool checked)
|
||||
|
||||
readonly property alias count: repeater.count
|
||||
readonly property alias count: listView.count
|
||||
|
||||
Connections {
|
||||
target: root.communityDetails
|
||||
|
@ -58,7 +58,7 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
function resetCommunityItemModel(){
|
||||
function resetCommunityItemModel() {
|
||||
communityItemModel.clear()
|
||||
communityItemModel.append({
|
||||
text: root.communityDetails.name,
|
||||
|
@ -87,14 +87,18 @@ ColumnLayout {
|
|||
]
|
||||
}
|
||||
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
StatusListView {
|
||||
id: listView
|
||||
reuseItems: true
|
||||
model: root.permissionsModel
|
||||
spacing: 24
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.topMargin: root.topPadding
|
||||
|
||||
delegate: PermissionItem {
|
||||
Layout.fillWidth: true
|
||||
width: root.viewWidth
|
||||
|
||||
holdingsListModel: HoldingsSelectionModel {
|
||||
sourceModel: model.holdingsListModel
|
||||
|
@ -155,6 +159,7 @@ ColumnLayout {
|
|||
root.userRestrictionsToggled(checked);
|
||||
}
|
||||
}
|
||||
|
||||
ConfirmationDialog {
|
||||
id: declineAllDialog
|
||||
|
||||
|
|
|
@ -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: [
|
||||
StringSorter {
|
||||
|
|
|
@ -21,20 +21,6 @@ QtObject {
|
|||
//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 {
|
||||
id: selectedChannelPermissionsModel
|
||||
sourceModel: root.permissionsModel
|
||||
|
|
Loading…
Reference in New Issue