refactor(community_tokens): only fetch holders when going to the page (#16308)

* refactor(community_tokens): only fetch holders when going to the page

Fixes #16307

Instead of fetching community token holders each time members change, we fetch when the page for the token is opened.
It shows a small loading text then the resulting holders.
If the list is already available (fetched previously, we show it directly).
There is still the timer to refresh the list if you stay on the page.

* add loading property to storybook
This commit is contained in:
Jonathan Rainville 2024-09-19 16:32:38 -04:00 committed by GitHub
parent ea8827ec97
commit 3f8dfee3cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 199 additions and 119 deletions

View File

@ -178,9 +178,3 @@ proc declineOwnership*(self: Controller, communityId: string) =
proc asyncGetOwnerTokenOwnerAddress*(self: Controller, chainId: int, contractAddress: string) =
self.communityTokensService.asyncGetOwnerTokenOwnerAddress(chainId, contractAddress)
proc startTokenHoldersManagement*(self: Controller, chainId: int, contractAddress: string) =
self.communityTokensService.startTokenHoldersManagement(chainId, contractAddress)
proc stopTokenHoldersManagement*(self: Controller) =
self.communityTokensService.stopTokenHoldersManagement()

View File

@ -119,9 +119,3 @@ method onOwnerTokenOwnerAddress*(self: AccessInterface, chainId: int, contractAd
method asyncGetOwnerTokenDetails*(self: AccessInterface, communityId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method startTokenHoldersManagement*(self: AccessInterface, chainId: int, contractAddress: string) {.base.} =
raise newException(ValueError, "No implementation available")
method stopTokenHoldersManagement*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -20,6 +20,7 @@ type
burnState*: ContractTransactionStatus
remoteDestructedAddresses*: seq[string]
tokenOwnersModel*: token_owners_model.TokenOwnersModel
tokenHoldersLoading*: bool
proc initTokenItem*(
tokenDto: CommunityTokenDto,
@ -29,7 +30,7 @@ proc initTokenItem*(
burnState: ContractTransactionStatus,
remoteDestructedAddresses: seq[string],
remainingSupply: Uint256,
destructedAmount: Uint256
destructedAmount: Uint256,
): TokenItem =
result.tokenDto = tokenDto
if network != nil:
@ -45,6 +46,7 @@ proc initTokenItem*(
# TODO: provide number of messages here
result = initTokenOwnersItem(owner.contactId, owner.name, owner.imageSource, 0, owner.collectibleOwner, remoteDestructedAddresses)
))
result.tokenHoldersLoading = false
proc `$`*(self: TokenItem): string =
result = fmt"""TokenItem(
@ -55,6 +57,7 @@ proc `$`*(self: TokenItem): string =
destructedAmount: {self.destructedAmount},
burnState: {self.burnState},
tokenOwnersModel: {self.tokenOwnersModel},
tokenHoldersLoading: {self.tokenHoldersLoading},
remoteDestructedAddresses: {self.remoteDestructedAddresses}
]"""

View File

@ -26,6 +26,7 @@ type
ChainName
ChainIcon
TokenOwnersModel
TokenHoldersLoading
AccountName
AccountAddress
RemainingSupply
@ -50,76 +51,105 @@ QtObject:
new(result, delete)
result.setup
proc updateDeployState*(self: TokenModel, chainId: int, contractAddress: string, deployState: DeployState) =
proc getItemIndex(self: TokenModel, chainId: int, contractAddress: string): int =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == contractAddress) and (self.items[i].tokenDto.chainId == chainId)):
self.items[i].tokenDto.deployState = deployState
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.DeployState.int])
return
if self.items[i].tokenDto.address == contractAddress and self.items[i].tokenDto.chainId == chainId:
return i
return -1
proc updateDeployState*(self: TokenModel, chainId: int, contractAddress: string, deployState: DeployState) =
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1 and self.items[itemIdx].tokenDto.deployState == deployState:
return
self.items[itemIdx].tokenDto.deployState = deployState
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.DeployState.int])
proc updateAddress*(self: TokenModel, chainId: int, oldContractAddress: string, newContractAddress: string) =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == oldContractAddress) and (self.items[i].tokenDto.chainId == chainId)):
self.items[i].tokenDto.address = newContractAddress
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.TokenAddress.int])
return
let itemIdx = self.getItemIndex(chainId, oldContractAddress)
if itemIdx == -1 and self.items[itemIdx].tokenDto.address == newContractAddress:
return
self.items[itemIdx].tokenDto.address = newContractAddress
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.TokenAddress.int])
proc updateBurnState*(self: TokenModel, chainId: int, contractAddress: string, burnState: ContractTransactionStatus) =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == contractAddress) and (self.items[i].tokenDto.chainId == chainId)):
self.items[i].burnState = burnState
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.BurnState.int])
return
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1 and self.items[itemIdx].burnState == burnState:
return
self.items[itemIdx].burnState = burnState
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.BurnState.int])
proc updateRemoteDestructedAddresses*(self: TokenModel, chainId: int, contractAddress: string, remoteDestructedAddresses: seq[string]) =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == contractAddress) and (self.items[i].tokenDto.chainId == chainId)):
self.items[i].remoteDestructedAddresses = remoteDestructedAddresses
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.RemotelyDestructState.int])
self.items[i].tokenOwnersModel.updateRemoteDestructState(remoteDestructedAddresses)
self.dataChanged(index, index, @[ModelRole.TokenOwnersModel.int])
return
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1 and self.items[itemIdx].remoteDestructedAddresses == remoteDestructedAddresses:
return
self.items[itemIdx].remoteDestructedAddresses = remoteDestructedAddresses
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.RemotelyDestructState.int])
self.items[itemIdx].tokenOwnersModel.updateRemoteDestructState(remoteDestructedAddresses)
self.dataChanged(index, index, @[ModelRole.TokenOwnersModel.int])
proc updateSupply*(self: TokenModel, chainId: int, contractAddress: string, supply: Uint256, destructedAmount: Uint256) =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == contractAddress) and (self.items[i].tokenDto.chainId == chainId)):
if self.items[i].tokenDto.supply != supply or self.items[i].destructedAmount != destructedAmount:
self.items[i].tokenDto.supply = supply
self.items[i].destructedAmount = destructedAmount
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.Supply.int])
return
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1:
return
if self.items[itemIdx].tokenDto.supply != supply or self.items[itemIdx].destructedAmount != destructedAmount:
self.items[itemIdx].tokenDto.supply = supply
self.items[itemIdx].destructedAmount = destructedAmount
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.Supply.int])
proc updateRemainingSupply*(self: TokenModel, chainId: int, contractAddress: string, remainingSupply: Uint256) =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == contractAddress) and (self.items[i].tokenDto.chainId == chainId)):
if self.items[i].remainingSupply != remainingSupply:
self.items[i].remainingSupply = remainingSupply
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.RemainingSupply.int])
return
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1 and self.items[itemIdx].remainingSupply == remainingSupply:
return
self.items[itemIdx].remainingSupply = remainingSupply
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.RemainingSupply.int])
proc hasTokenHolders*(self: TokenModel, chainId: int, contractAddress: string): bool =
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1:
return false
return self.items[itemIdx].tokenOwnersModel.count > 0
proc setCommunityTokenOwners*(self: TokenModel, chainId: int, contractAddress: string, owners: seq[CommunityCollectibleOwner]) =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == contractAddress) and (self.items[i].tokenDto.chainId == chainId)):
self.items[i].tokenOwnersModel.setItems(owners.map(proc(owner: CommunityCollectibleOwner): TokenOwnersItem =
# TODO: provide number of messages here
result = initTokenOwnersItem(owner.contactId, owner.name, owner.imageSource, 0, owner.collectibleOwner, self.items[i].remoteDestructedAddresses)
))
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.TokenOwnersModel.int])
return
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1:
return
self.items[itemIdx].tokenHoldersLoading = false
self.items[itemIdx].tokenOwnersModel.setItems(owners.map(proc(owner: CommunityCollectibleOwner): TokenOwnersItem =
# TODO: provide number of messages here
result = initTokenOwnersItem(owner.contactId, owner.name, owner.imageSource, 0, owner.collectibleOwner, self.items[itemIdx].remoteDestructedAddresses)
))
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.TokenOwnersModel.int, ModelRole.TokenHoldersLoading.int])
proc setCommunityTokenHoldersLoading*(self: TokenModel, chainId: int, contractAddress: string, value: bool) =
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1 and self.items[itemIdx].tokenHoldersLoading == value:
return
self.items[itemIdx].tokenHoldersLoading = value
let index = self.createIndex(itemIdx, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.TokenHoldersLoading.int])
proc countChanged(self: TokenModel) {.signal.}
@ -129,7 +159,6 @@ QtObject:
self.endResetModel()
self.countChanged()
proc getOwnerToken*(self: TokenModel): TokenItem =
for i in 0 ..< self.items.len:
if(self.items[i].tokenDto.privilegesLevel == PrivilegesLevel.Owner):
@ -144,17 +173,18 @@ QtObject:
self.endInsertRows()
self.countChanged()
proc removeItemByChainIdAndAddress*(self: TokenModel, chainId: int, address: string) =
for i in 0 ..< self.items.len:
if((self.items[i].tokenDto.address == address) and (self.items[i].tokenDto.chainId == chainId)):
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
proc removeItemByChainIdAndAddress*(self: TokenModel, chainId: int, contractAddress: string) =
let itemIdx = self.getItemIndex(chainId, contractAddress)
if itemIdx == -1:
return
self.beginRemoveRows(parentModelIndex, i, i)
self.items.delete(i)
self.endRemoveRows()
self.countChanged()
return
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginRemoveRows(parentModelIndex, itemIdx, itemIdx)
self.items.delete(itemIdx)
self.endRemoveRows()
self.countChanged()
proc getCount*(self: TokenModel): int {.slot.} =
self.items.len
@ -184,6 +214,7 @@ QtObject:
ModelRole.ChainName.int:"chainName",
ModelRole.ChainIcon.int:"chainIcon",
ModelRole.TokenOwnersModel.int:"tokenOwnersModel",
ModelRole.TokenHoldersLoading.int:"tokenHoldersLoading",
ModelRole.AccountName.int:"accountName",
ModelRole.AccountAddress.int:"accountAddress",
ModelRole.RemainingSupply.int:"remainingSupply",
@ -235,6 +266,8 @@ QtObject:
result = newQVariant(item.chainIcon)
of ModelRole.TokenOwnersModel:
result = newQVariant(item.tokenOwnersModel)
of ModelRole.TokenHoldersLoading:
result = newQVariant(item.tokenHoldersLoading)
of ModelRole.AccountName:
result = newQVariant(item.accountName)
of ModelRole.AccountAddress:

View File

@ -385,9 +385,3 @@ method onOwnerTokenOwnerAddress*(self: Module, chainId: int, contractAddress: st
"contractAddress": contractAddress
}
self.view.setOwnerTokenDetails($jsonObj)
method startTokenHoldersManagement*(self: Module, chainId: int, contractAddress: string) =
self.controller.startTokenHoldersManagement(chainId, contractAddress)
method stopTokenHoldersManagement*(self: Module) =
self.controller.stopTokenHoldersManagement()

View File

@ -145,9 +145,3 @@ QtObject:
QtProperty[string] ownerTokenDetails:
read = getOwnerTokenDetails
notify = ownerTokenDetailsChanged
proc startTokenHoldersManagement*(self: View, chainId: int, contractAddress: string) {.slot.} =
self.communityTokensModule.startTokenHoldersManagement(chainId, contractAddress)
proc stopTokenHoldersManagement*(self: View) {.slot.} =
self.communityTokensModule.stopTokenHoldersManagement()

View File

@ -392,6 +392,10 @@ proc init*(self: Controller) =
let args = CommunityTokenOwnersArgs(e)
self.delegate.onCommunityTokenOwnersFetched(args.communityId, args.chainId, args.contractAddress, args.owners)
self.events.on(SIGNAL_COMMUNITY_TOKEN_OWNERS_LOADING_FAILED) do(e: Args):
let args = CommunityTokenOwnersArgs(e)
self.delegate.errorLoadingTokenHolders(args.communityId, args.chainId, args.contractAddress, args.error)
self.events.on(SIGNAL_ACCEPT_REQUEST_TO_JOIN_LOADING) do(e: Args):
var args = CommunityMemberArgs(e)
self.delegate.onAcceptRequestToJoinLoading(args.communityId, args.pubKey)
@ -412,10 +416,6 @@ proc init*(self: Controller) =
let args = CommunityMemberStatusUpdatedArgs(e)
self.delegate.onMembershipStateUpdated(args.communityId, args.memberPubkey, args.state)
self.events.on(SIGNAL_COMMUNITY_MEMBERS_CHANGED) do(e: Args):
let args = CommunityMembersArgs(e)
self.communityTokensService.fetchCommunityTokenOwners(args.communityId)
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_FLOW_TERMINATED) do(e: Args):
let args = SharedKeycarModuleFlowTerminatedArgs(e)
if args.uniqueIdentifier == UNIQUE_MAIN_MODULE_KEYCARD_SYNC_IDENTIFIER:
@ -597,3 +597,9 @@ proc asyncGetRevealedAccountsForAllMembers*(self: Controller, communityId: strin
proc asyncReevaluateCommunityMembersPermissions*(self: Controller, communityId: string) =
self.communityService.asyncReevaluateCommunityMembersPermissions(communityId)
proc startTokenHoldersManagement*(self: Controller, chainId: int, contractAddress: string) =
self.communityTokensService.startTokenHoldersManagement(chainId, contractAddress)
proc stopTokenHoldersManagement*(self: Controller) =
self.communityTokensService.stopTokenHoldersManagement()

View File

@ -337,6 +337,9 @@ method onOwnerTokensDeploymentStarted*(self: AccessInterface, ownerToken: Commun
method onCommunityTokenOwnersFetched*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, owners: seq[CommunityCollectibleOwner]) {.base.} =
raise newException(ValueError, "No implementation available")
method errorLoadingTokenHolders*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, error: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onCommunityTokenDeployStateChanged*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, deployState: DeployState) {.base.} =
raise newException(ValueError, "No implementation available")
@ -421,6 +424,12 @@ method openSectionChatAndMessage*(self: AccessInterface, sectionId: string, chat
method updateRequestToJoinState*(self: AccessInterface, sectionId: string, requestToJoinState: RequestToJoinState) {.base.} =
raise newException(ValueError, "No implementation available")
method startTokenHoldersManagement*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string) {.base.} =
raise newException(ValueError, "No implementation available")
method stopTokenHoldersManagement*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
# This way (using concepts) is used only for the modules managed by AppController
type
DelegateInterface* = concept c

View File

@ -1213,6 +1213,20 @@ method onCommunityTokenRemoved*[T](self: Module[T], communityId: string, chainId
if item.id != "":
item.removeCommunityToken(chainId, address)
method startTokenHoldersManagement*[T](self: Module[T], communityId: string, chainId: int, contractAddress: string) =
self.controller.startTokenHoldersManagement(chainId, contractAddress)
let item = self.view.model().getItemById(communityId)
if item.id != "" and not item.communityTokens.hasTokenHolders(chainId, contractAddress):
item.setCommunityTokenHoldersLoading(chainId, contractAddress, value = true)
method stopTokenHoldersManagement*[T](self: Module[T]) =
self.controller.stopTokenHoldersManagement()
method errorLoadingTokenHolders*[T](self: Module[T], communityId: string, chainId: int, contractAddress: string, error: string) =
let item = self.view.model().getItemById(communityId)
if item.id != "":
item.setCommunityTokenHoldersLoading(chainId, contractAddress, value = false)
method onCommunityTokenOwnersFetched*[T](self: Module[T], communityId: string, chainId: int, contractAddress: string, owners: seq[CommunityCollectibleOwner]) =
let item = self.view.model().getItemById(communityId)
if item.id != "":

View File

@ -375,3 +375,9 @@ QtObject:
proc emitCommunityMemberStatusEphemeralNotification*(self:View, communityName: string, memberName: string,
membershipState: int) =
self.communityMemberStatusEphemeralNotification(communityName, memberName, membershipState)
proc startTokenHoldersManagement*(self: View, communityId: string, chainId: int, contractAddress: string) {.slot.} =
self.delegate.startTokenHoldersManagement(communityId, chainId, contractAddress)
proc stopTokenHoldersManagement*(self: View) {.slot.} =
self.delegate.stopTokenHoldersManagement()

View File

@ -373,6 +373,9 @@ proc updateRemoteDestructedAddresses*(self: SectionItem, chainId: int, contractA
proc setCommunityTokenOwners*(self: SectionItem, chainId: int, contractAddress: string, owners: seq[CommunityCollectibleOwner]) {.inline.} =
self.communityTokensModel.setCommunityTokenOwners(chainId, contractAddress, owners)
proc setCommunityTokenHoldersLoading*(self: SectionItem, chainId: int, contractAddress: string, value: bool) {.inline.} =
self.communityTokensModel.setCommunityTokenHoldersLoading(chainId, contractAddress, value)
proc communityTokens*(self: SectionItem): community_tokens_model.TokenModel {.inline.} =
self.communityTokensModel

View File

@ -156,6 +156,7 @@ type
contractAddress*: string
chainId*: int
owners*: seq[CommunityCollectibleOwner]
error*: string
type
CommunityTokensDetailsArgs* = ref object of Args
@ -259,6 +260,7 @@ const SIGNAL_COMPUTE_SELF_DESTRUCT_FEE* = "communityTokens-computeSelfDestructFe
const SIGNAL_COMPUTE_BURN_FEE* = "communityTokens-computeBurnFee"
const SIGNAL_COMPUTE_AIRDROP_FEE* = "communityTokens-computeAirdropFee"
const SIGNAL_COMMUNITY_TOKEN_OWNERS_FETCHED* = "communityTokens-communityTokenOwnersFetched"
const SIGNAL_COMMUNITY_TOKEN_OWNERS_LOADING_FAILED* = "communityTokens-communityTokenOwnersLoadingFailed"
const SIGNAL_REMOTE_DESTRUCT_STATUS* = "communityTokens-communityTokenRemoteDestructStatus"
const SIGNAL_BURN_STATUS* = "communityTokens-communityTokenBurnStatus"
const SIGNAL_BURN_ACTION_RECEIVED* = "communityTokens-communityTokenBurnActionReceived"
@ -1290,17 +1292,28 @@ QtObject:
proc onCommunityTokenOwnersFetched*(self:Service, response: string) {.slot.} =
let responseJson = response.parseJson()
if responseJson{"error"}.kind != JNull and responseJson{"error"}.getStr != "":
let errorMessage = responseJson["error"].getStr
error "Can't fetch community token owners", chainId=responseJson{"chainId"}, contractAddress=responseJson{"contractAddress"}, errorMsg=errorMessage
return
let chainId = responseJson{"chainId"}.getInt
let contractAddress = responseJson{"contractAddress"}.getStr
let communityId = responseJson{"communityId"}.getStr
let communityTokenOwners = toCommunityCollectibleOwners(responseJson{"result"})
self.tokenOwnersCache[(chainId, contractAddress)] = communityTokenOwners
let data = CommunityTokenOwnersArgs(chainId: chainId, contractAddress: contractAddress, communityId: communityId, owners: communityTokenOwners)
self.events.emit(SIGNAL_COMMUNITY_TOKEN_OWNERS_FETCHED, data)
try:
if responseJson{"error"}.kind != JNull and responseJson{"error"}.getStr != "":
raise newException(ValueError, responseJson["error"].getStr)
let communityTokenOwners = toCommunityCollectibleOwners(responseJson{"result"})
self.tokenOwnersCache[(chainId, contractAddress)] = communityTokenOwners
let data = CommunityTokenOwnersArgs(chainId: chainId, contractAddress: contractAddress, communityId: communityId, owners: communityTokenOwners)
self.events.emit(SIGNAL_COMMUNITY_TOKEN_OWNERS_FETCHED, data)
except Exception as e:
error "Can't fetch community token owners", chainId=responseJson{"chainId"}, contractAddress=responseJson{"contractAddress"}, errorMsg=e.msg
let data = CommunityTokenOwnersArgs(
chainId: chainId,
contractAddress: contractAddress,
communityId: communityId,
error: e.msg,
)
self.events.emit(SIGNAL_COMMUNITY_TOKEN_OWNERS_LOADING_FAILED, data)
# restart token holders timer
self.restartTokenHoldersTimer(chainId, contractAddress)
@ -1313,14 +1326,6 @@ QtObject:
let community = self.communityService.getCommunityById(communityId)
return community.isPrivilegedUser()
# used when community members changed
proc fetchCommunityTokenOwners*(self: Service, communityId: string) =
if not self.iAmCommunityPrivilegedUser(communityId):
return
let tokens = self.getCommunityTokens(communityId)
for token in tokens:
self.fetchCommunityOwners(token)
proc getOwnerToken*(self: Service, communityId: string): CommunityTokenDto =
let communityTokens = self.getCommunityTokens(communityId)
for token in communityTokens:

View File

@ -41,6 +41,7 @@ SplitView {
chainName: networksGroup.checkedButton.text
chainIcon: networksGroup.checkedButton.chainIcon
accountName: "helloworld"
tokenHoldersLoading: loadingTokenHolders.checked
// collectible-specific properties
remotelyDestructState: remotelyDestructStateBox.checked
@ -141,6 +142,16 @@ SplitView {
}
}
GroupBox {
Layout.fillWidth: true
CheckBox {
id: loadingTokenHolders
text: "Loading Token Holders"
checked: false
}
}
GroupBox {
Layout.fillWidth: true

View File

@ -51,4 +51,7 @@ QtObject {
// Asset-specific properties:
property int decimals: 2
// Loading indicators
property bool tokenHoldersLoading: false
}

View File

@ -1005,6 +1005,7 @@ StackView {
token.accountAddress: model.accountAddress
token.multiplierIndex: model.multiplierIndex
token.tokenAddress: model.tokenAddress
token.tokenHoldersLoading: model.tokenHoldersLoading
}
onCountChanged: {

View File

@ -375,7 +375,7 @@ StatusSectionLayout {
onRegisterBurnTokenFeesSubscriber: d.feesBroker.registerBurnFeesSubscriber(feeSubscriber)
onStartTokenHoldersManagement: communityTokensStore.startTokenHoldersManagement(chainId, address)
onStartTokenHoldersManagement: communityTokensStore.startTokenHoldersManagement(root.community.id, chainId, address)
onStopTokenHoldersManagement: communityTokensStore.stopTokenHoldersManagement()

View File

@ -96,6 +96,7 @@ StatusScrollView {
id: d
readonly property int iconSize: 20
property bool loadingTokenHolders: false
readonly property var renamedTokenOwnersModel: RolesRenamingModel {
sourceModel: root.tokenOwnersModel
@ -172,7 +173,7 @@ StatusScrollView {
wrapMode: Text.Wrap
font.pixelSize: Style.current.primaryTextFontSize
color: Theme.palette.baseColor1
text: qsTr("Review token details before minting it as they cant be edited later")
text: qsTr("Review token details before minting it as they can't be edited later")
}
}
@ -228,7 +229,15 @@ StatusScrollView {
id: tokenHolderLoader
visible: !root.preview && root.deploymentCompleted
sourceComponent: isOwnerTokenItem ? tokenHolderContact : sortableTokenHolderPanel
sourceComponent: isOwnerTokenItem ? tokenHolderContact : (token.tokenHoldersLoading ? tokenHoldersLoadingComponent : sortableTokenHolderPanel)
}
Component {
id: tokenHoldersLoadingComponent
StatusBaseText {
text: qsTr("Loading token holders...")
}
}
Component {

View File

@ -7,6 +7,7 @@ QtObject {
id: root
property var communityTokensModuleInst: communityTokensModule ?? null
property var mainModuleInst: mainModule ?? null
// Network selection properties:
property var flatNetworks: networksModule.flatNetworks
@ -231,11 +232,11 @@ QtObject {
communityTokensModuleInst.asyncGetOwnerTokenDetails(communityId)
}
function startTokenHoldersManagement(chainId, contractAddress) {
communityTokensModuleInst.startTokenHoldersManagement(chainId, contractAddress)
function startTokenHoldersManagement(communityId, chainId, contractAddress) {
mainModuleInst.startTokenHoldersManagement(communityId, chainId, contractAddress)
}
function stopTokenHoldersManagement() {
communityTokensModuleInst.stopTokenHoldersManagement()
mainModuleInst.stopTokenHoldersManagement()
}
}