From 28fa8271a61013ca00801a48edd4473072cdf495 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Wed, 21 Jun 2023 10:20:39 -0400 Subject: [PATCH] feat(communities): update communities token list on token deploy Fixes #11125 Updates the communities asset and collectibles lists when a new token is deployed. Also refactors the section module to remove all that code and use the communities token list instead. Adds community ID to the token list model so that we can show only the global tokens and the tokens from the community are shown in the community --- .../modules/main/chat_section/controller.nim | 5 -- .../main/chat_section/io_interface.nim | 3 -- src/app/modules/main/chat_section/module.nim | 54 ------------------- src/app/modules/main/chat_section/view.nim | 38 ------------- .../modules/main/communities/controller.nim | 4 ++ .../modules/main/communities/io_interface.nim | 3 ++ src/app/modules/main/communities/module.nim | 27 ++++++++-- .../modules/shared_models/token_list_item.nim | 12 ++++- .../shared_models/token_list_model.nim | 4 ++ .../community/ExtendedDropdownContent.qml | 13 +++++ .../controls/community/HoldingsDropdown.qml | 2 + .../CommunityAirdropsSettingsPanel.qml | 4 ++ .../CommunityPermissionsSettingsPanel.qml | 2 +- ui/app/AppLayouts/Chat/stores/RootStore.qml | 4 +- .../Chat/views/CommunitySettingsView.qml | 18 ++++--- .../communities/CommunityNewAirdropView.qml | 4 ++ .../CommunityNewPermissionView.qml | 4 +- .../communities/CommunityPermissionsView.qml | 2 +- 18 files changed, 86 insertions(+), 117 deletions(-) diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index 9018805c1d..8ac131e402 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -317,11 +317,6 @@ proc init*(self: Controller) = if args.communityId == self.sectionId: self.delegate.onCommunityCheckAllChannelsPermissionsResponse(args.checkAllChannelsPermissionsResponse) - self.events.on(SIGNAL_COMMUNITY_TOKEN_METADATA_ADDED) do(e: Args): - let args = CommunityTokenMetadataArgs(e) - if (args.communityId == self.sectionId): - self.delegate.onCommunityTokenMetadataAdded(args.communityId, args.tokenMetadata) - self.events.on(SIGNAL_OWNED_COLLECTIBLES_UPDATE_FINISHED) do(e: Args): self.delegate.onOwnedCollectiblesUpdated() self.asyncCheckPermissions() diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim index 79d16dcc90..6a14a88c79 100644 --- a/src/app/modules/main/chat_section/io_interface.nim +++ b/src/app/modules/main/chat_section/io_interface.nim @@ -367,9 +367,6 @@ method onCommunityTokenPermissionDeleted*(self: AccessInterface, communityId: st method onCommunityTokenPermissionDeletionFailed*(self: AccessInterface, communityId: string) {.base.} = raise newException(ValueError, "No implementation available") -method onCommunityTokenMetadataAdded*(self: AccessInterface, communityId: string, tokenMetadata: CommunityTokensMetadataDto) {.base.} = - raise newException(ValueError, "No implementation available") - method onWalletAccountTokensRebuilt*(self: AccessInterface) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index b696fa10f0..fb3f0fe083 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -90,8 +90,6 @@ proc addOrUpdateChat(self: Module, insertIntoModel: bool = true, ): Item -proc buildTokenList*(self: Module) - proc newModule*( delegate: delegate_interface.AccessInterface, events: EventEmitter, @@ -279,8 +277,6 @@ proc initContactRequestsModel(self: Module) = self.view.contactRequestsModel().addItems(contactsWhoAddedMe) proc rebuildCommunityTokenPermissionsModel(self: Module) = - self.buildTokenList() - let community = self.controller.getMyCommunity() var tokenPermissionsItems: seq[TokenPermissionItem] = @[] @@ -308,39 +304,6 @@ proc reevaluateRequiresTokenPermissionToJoin(self: Module) = proc initCommunityTokenPermissionsModel(self: Module, channelGroup: ChannelGroupDto) = self.rebuildCommunityTokenPermissionsModel() -proc buildTokenList(self: Module) = - var tokenListItems: seq[TokenListItem] - var collectiblesListItems: seq[TokenListItem] - - let community = self.controller.getMyCommunity() - let erc20Tokens = self.controller.getTokenList() - - for token in erc20Tokens: - let tokenListItem = initTokenListItem( - key = token.symbol, - name = token.name, - symbol = token.symbol, - color = token.color, - image = "", - category = ord(TokenListItemCategory.General) - ) - - tokenListItems.add(tokenListItem) - - for token in community.communityTokensMetadata: - let tokenListItem = initTokenListItem( - key = token.symbol, - name = token.name, - symbol = token.symbol, - color = "", # community tokens don't have `color` - image = token.image, - category = ord(TokenListItemCategory.Community) - ) - collectiblesListItems.add(tokenListItem) - - self.view.setTokenListItems(tokenListItems) - self.view.setCollectiblesListItems(collectiblesListItems) - method onWalletAccountTokensRebuilt*(self: Module) = self.rebuildCommunityTokenPermissionsModel() @@ -934,23 +897,6 @@ method onCommunityCheckAllChannelsPermissionsResponse*(self: Module, checkAllCha for chatId, permissionResult in checkAllChannelsPermissionsResponse.channels: self.updateChannelPermissionViewData(chatId, permissionResult.viewOnlyPermissions, permissionResult.viewAndPostPermissions, community) -method onCommunityTokenMetadataAdded*(self: Module, communityId: string, tokenMetadata: CommunityTokensMetadataDto) = - let tokenListItem = initTokenListItem( - key = tokenMetadata.symbol, - name = tokenMetadata.name, - symbol = tokenMetadata.symbol, - color = "", # tokenMetadata doesn't provide a color - image = tokenMetadata.image, - category = ord(TokenListItemCategory.Community) - ) - - if tokenMetadata.tokenType == community_dto.TokenType.ERC721 and not self.view.collectiblesListModel().hasItem(tokenMetadata.symbol): - self.view.collectiblesListModel.addItems(@[tokenListItem]) - return - - if tokenMetadata.tokenType == community_dto.TokenType.ERC20 and not self.view.tokenListModel().hasItem(tokenMetadata.symbol): - self.view.tokenListModel.addItems(@[tokenListItem]) - method onKickedFromCommunity*(self: Module) = self.view.setAmIMember(false) diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim index a7031ab1dd..9bfa893b5f 100644 --- a/src/app/modules/main/chat_section/view.nim +++ b/src/app/modules/main/chat_section/view.nim @@ -3,8 +3,6 @@ import model as chats_model import item, active_item import ../../shared_models/user_model as user_model import ../../shared_models/token_permissions_model -import ../../shared_models/token_list_model -import ../../shared_models/token_list_item import io_interface QtObject: @@ -25,10 +23,6 @@ QtObject: loadingHistoryMessagesInProgress: bool tokenPermissionsModel: TokenPermissionsModel tokenPermissionsVariant: QVariant - tokenListModel: TokenListModel - tokenListModelVariant: QVariant - collectiblesListModel: TokenListModel - collectiblesListModelVariant: QVariant allTokenRequirementsMet: bool requiresTokenPermissionToJoin: bool amIMember: bool @@ -47,10 +41,6 @@ QtObject: self.editCategoryChannelsVariant.delete self.tokenPermissionsModel.delete self.tokenPermissionsVariant.delete - self.tokenListModel.delete - self.tokenListModelVariant.delete - self.collectiblesListModel.delete - self.collectiblesListModelVariant.delete self.QObject.delete @@ -71,10 +61,6 @@ QtObject: result.loadingHistoryMessagesInProgress = false result.tokenPermissionsModel = newTokenPermissionsModel() result.tokenPermissionsVariant = newQVariant(result.tokenPermissionsModel) - result.tokenListModel = newTokenListModel() - result.tokenListModelVariant = newQVariant(result.tokenListModel) - result.collectiblesListModel = newTokenListModel() - result.collectiblesListModelVariant = newQVariant(result.collectiblesListModel) result.amIMember = false result.requiresTokenPermissionToJoin = false result.chatsLoaded = false @@ -368,30 +354,6 @@ QtObject: proc downloadMessages*(self: View, chatId: string, filePath: string) {.slot.} = self.delegate.downloadMessages(chatId, filePath) - proc tokenListModel*(self: View): TokenListModel = - result = self.tokenListModel - - proc getTokenListModel(self: View): QVariant{.slot.} = - return self.tokenListModelVariant - - QtProperty[QVariant] tokenList: - read = getTokenListModel - - proc setTokenListItems*(self: View, tokenListItems: seq[TokenListItem]) = - self.tokenListModel.setItems(tokenListItems) - - proc collectiblesListModel*(self: View): TokenListModel = - result = self.collectiblesListModel - - proc getCollectiblesListModel(self: View): QVariant{.slot.} = - return self.collectiblesListModelVariant - - QtProperty[QVariant] collectiblesModel: - read = getCollectiblesListModel - - proc setCollectiblesListItems*(self: View, tokenListItems: seq[TokenListItem]) = - self.collectiblesListModel.setItems(tokenListItems) - proc tokenPermissionsModel*(self: View): TokenPermissionsModel = result = self.tokenPermissionsModel diff --git a/src/app/modules/main/communities/controller.nim b/src/app/modules/main/communities/controller.nim index e605657caf..59f26b5b02 100644 --- a/src/app/modules/main/communities/controller.nim +++ b/src/app/modules/main/communities/controller.nim @@ -116,6 +116,10 @@ proc init*(self: Controller) = let args = CommunitiesArgs(e) self.delegate.curatedCommunitiesLoaded(args.communities) + self.events.on(SIGNAL_COMMUNITY_TOKEN_METADATA_ADDED) do(e: Args): + let args = CommunityTokenMetadataArgs(e) + self.delegate.onCommunityTokenMetadataAdded(args.communityId, args.tokenMetadata) + proc getCommunityTags*(self: Controller): string = result = self.communityService.getCommunityTags() diff --git a/src/app/modules/main/communities/io_interface.nim b/src/app/modules/main/communities/io_interface.nim index 24055f6690..f7c2122bf2 100644 --- a/src/app/modules/main/communities/io_interface.nim +++ b/src/app/modules/main/communities/io_interface.nim @@ -150,3 +150,6 @@ method curatedCommunitiesLoaded*(self: AccessInterface, curatedCommunities: seq[ method communityInfoAlreadyRequested*(self: AccessInterface) {.base.} = raise newException(ValueError, "No implementation available") + +method onCommunityTokenMetadataAdded*(self: AccessInterface, communityId: string, tokenMetadata: CommunityTokensMetadataDto) {.base.} = + raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/communities/module.nim b/src/app/modules/main/communities/module.nim index 72ff717db0..6c00b5373b 100644 --- a/src/app/modules/main/communities/module.nim +++ b/src/app/modules/main/communities/module.nim @@ -13,7 +13,7 @@ import ./models/discord_file_list_model import ./models/discord_import_task_item import ./models/discord_import_tasks_model import ../../shared_models/[member_item, section_model, section_item, token_permissions_model, token_permission_item, - token_list_item, token_criteria_item] + token_list_item, token_list_model, token_criteria_item] import ../../../global/global_singleton import ../../../core/eventemitter import ../../../../app_service/common/types @@ -416,9 +416,30 @@ proc buildTokenList(self: Module) = symbol = token.symbol, color = "", # community tokens don't have `color` image = token.image, - category = ord(TokenListItemCategory.Community) + category = ord(TokenListItemCategory.Community), + communityId = community.id, ) collectiblesListItems.add(tokenListItem) self.view.setTokenListItems(tokenListItems) - self.view.setCollectiblesListItems(collectiblesListItems) \ No newline at end of file + self.view.setCollectiblesListItems(collectiblesListItems) + +method onCommunityTokenMetadataAdded*(self: Module, communityId: string, tokenMetadata: CommunityTokensMetadataDto) = + let tokenListItem = initTokenListItem( + key = tokenMetadata.symbol, + name = tokenMetadata.name, + symbol = tokenMetadata.symbol, + color = "", # tokenMetadata doesn't provide a color + image = tokenMetadata.image, + category = ord(TokenListItemCategory.Community), + communityId, + ) + + if tokenMetadata.tokenType == community_dto.TokenType.ERC721 and + not self.view.collectiblesListModel().hasItem(tokenMetadata.symbol): + self.view.collectiblesListModel.addItems(@[tokenListItem]) + return + + if tokenMetadata.tokenType == community_dto.TokenType.ERC20 and + not self.view.tokenListModel().hasItem(tokenMetadata.symbol): + self.view.tokenListModel.addItems(@[tokenListItem]) \ No newline at end of file diff --git a/src/app/modules/shared_models/token_list_item.nim b/src/app/modules/shared_models/token_list_item.nim index 22a452ddfb..c319aca62f 100644 --- a/src/app/modules/shared_models/token_list_item.nim +++ b/src/app/modules/shared_models/token_list_item.nim @@ -13,6 +13,7 @@ type color*: string image*: string category*: int + communityId*: string proc initTokenListItem*( key: string, @@ -20,7 +21,8 @@ proc initTokenListItem*( symbol: string, color: string, image: string, - category: int + category: int, + communityId: string = "" ): TokenListItem = result.key = key result.symbol = symbol @@ -28,13 +30,16 @@ proc initTokenListItem*( result.color = color result.image = image result.category = category + result.communityId = communityId proc `$`*(self: TokenListItem): string = result = fmt"""TokenListItem( key: {self.key}, name: {self.name}, color: {self.color}, - symbol: {self.symbol} + symbol: {self.symbol}, + category: {self.category}, + communityId: {self.communityId}, ]""" proc getKey*(self: TokenListItem): string = @@ -54,3 +59,6 @@ proc getImage*(self: TokenListItem): string = proc getCategory*(self: TokenListItem): int = return self.category + +proc getCommunityId*(self: TokenListItem): string = + return self.communityId diff --git a/src/app/modules/shared_models/token_list_model.nim b/src/app/modules/shared_models/token_list_model.nim index 8ee2480f5a..bcccc1f6ea 100644 --- a/src/app/modules/shared_models/token_list_model.nim +++ b/src/app/modules/shared_models/token_list_model.nim @@ -10,6 +10,7 @@ type Color Image Category + CommunityId QtObject: type TokenListModel* = ref object of QAbstractListModel @@ -74,6 +75,7 @@ QtObject: ModelRole.Color.int:"color", ModelRole.Image.int:"icon", ModelRole.Category.int:"category", + ModelRole.CommunityId.int:"communityId", }.toTable method rowCount(self: TokenlistModel, index: QModelIndex = nil): int = @@ -101,3 +103,5 @@ QtObject: result = newQVariant(item.getImage()) of ModelRole.Category: result = newQVariant(item.getCategory()) + of ModelRole.CommunityId: + result = newQVariant(item.getCommunityId()) diff --git a/ui/app/AppLayouts/Chat/controls/community/ExtendedDropdownContent.qml b/ui/app/AppLayouts/Chat/controls/community/ExtendedDropdownContent.qml index 7658a33510..5ed2b36f68 100644 --- a/ui/app/AppLayouts/Chat/controls/community/ExtendedDropdownContent.qml +++ b/ui/app/AppLayouts/Chat/controls/community/ExtendedDropdownContent.qml @@ -18,6 +18,7 @@ import SortFilterProxyModel 0.2 Item { id: root + property string communityId property var assetsModel property var collectiblesModel @@ -134,6 +135,18 @@ Item { value: TokenCategories.Category.General } }, + AnyOf { + // We accept tokens from this community or general (empty community ID) + ValueFilter { + roleName: "communityId" + value: "" + } + + ValueFilter { + roleName: "communityId" + value: root.communityId + } + }, ExpressionFilter { expression: { searcher.text diff --git a/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml b/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml index 62c382dc49..ee6344fbfe 100644 --- a/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml +++ b/ui/app/AppLayouts/Chat/controls/community/HoldingsDropdown.qml @@ -14,6 +14,7 @@ import utils 1.0 StatusDropdown { id: root + property string communityId property var assetsModel property var collectiblesModel property bool isENSTab: true @@ -265,6 +266,7 @@ StatusDropdown { ExtendedDropdownContent { id: listPanel + communityId: root.communityId assetsModel: root.assetsModel collectiblesModel: root.collectiblesModel noDataText: root.noDataText diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml index b9badf3baa..db70c8404e 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityAirdropsSettingsPanel.qml @@ -13,6 +13,9 @@ import utils 1.0 SettingsPageLayout { id: root + // id, name, image, color, owner properties expected + required property var communityDetails + // Token models: required property var assetsModel required property var collectiblesModel @@ -115,6 +118,7 @@ SettingsPageLayout { CommunityNewAirdropView { id: view + communityDetails: root.communityDetails assetsModel: root.assetsModel collectiblesModel: root.collectiblesModel membersModel: root.membersModel diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml index b33a502b02..f9484702ef 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityPermissionsSettingsPanel.qml @@ -16,7 +16,7 @@ SettingsPageLayout { required property var collectiblesModel required property var channelsModel - // name, image, color, owner properties expected + // id, name, image, color, owner properties expected required property var communityDetails property int viewWidth: 560 // by design diff --git a/ui/app/AppLayouts/Chat/stores/RootStore.qml b/ui/app/AppLayouts/Chat/stores/RootStore.qml index 6bd628910f..ed235d1f8d 100644 --- a/ui/app/AppLayouts/Chat/stores/RootStore.qml +++ b/ui/app/AppLayouts/Chat/stores/RootStore.qml @@ -33,7 +33,7 @@ QtObject { property var communityItemsModel: chatCommunitySectionModule.model property var assetsModel: SortFilterProxyModel { - sourceModel: chatCommunitySectionModule.tokenList + sourceModel: communitiesModuleInst.tokenList proxyRoles: ExpressionRole { function tokenIcon(symbol) { @@ -45,7 +45,7 @@ QtObject { } property var collectiblesModel: SortFilterProxyModel { - sourceModel: chatCommunitySectionModule.collectiblesModel + sourceModel: communitiesModuleInst.collectiblesModel proxyRoles: ExpressionRole { function icon(icon) { diff --git a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml index 6e3bd85118..423c78ff27 100644 --- a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml +++ b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml @@ -251,12 +251,7 @@ StatusSectionLayout { collectiblesModel: rootStore.collectiblesModel channelsModel: rootStore.chatCommunitySectionModule.model - communityDetails: QtObject { - readonly property string name: root.community.name - readonly property string image: root.community.image - readonly property string color: root.community.color - readonly property bool owner: root.community.memberRole === Constants.memberRole.owner - } + communityDetails: d.communityDetails onCreatePermissionRequested: permissionsStore.createPermission(holdings, permissionType, @@ -480,6 +475,7 @@ StatusSectionLayout { CommunityAirdropsSettingsPanel { id: airdropPanel + communityDetails: d.communityDetails readonly property CommunityTokensStore communityTokensStore: rootStore.communityTokensStore @@ -500,7 +496,7 @@ StatusSectionLayout { ExpressionRole { name: "category" - // Singleton cannot be used directly in the epression + // Singleton cannot be used directly in the expression readonly property int category: TokenCategories.Category.Own expression: category }, @@ -604,6 +600,14 @@ StatusSectionLayout { ? centerPanelContentLoader.item.children[d.currentIndex] : null + readonly property QtObject communityDetails: QtObject { + readonly property string id: root.community.id + readonly property string name: root.community.name + readonly property string image: root.community.image + readonly property string color: root.community.color + readonly property bool owner: root.community.memberRole === Constants.memberRole.owner + } + function goTo(section: int, subSection: int) { //find and enable section const matchingIndex = listView.model.findIndex((modelItem, index) => modelItem.id === section && modelItem.enabled) diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml index 322fda311a..4baed26a88 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewAirdropView.qml @@ -22,6 +22,9 @@ import SortFilterProxyModel 0.2 StatusScrollView { id: root + // id, name, image, color, owner properties expected + required property var communityDetails + // Token models: required property var assetsModel required property var collectiblesModel @@ -315,6 +318,7 @@ StatusScrollView { HoldingsDropdown { id: dropdown + communityId: communityDetails.id assetsModel: root.assetsModel collectiblesModel: root.collectiblesModel isENSTab: false diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml index c227809f92..816120e1f7 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml @@ -23,7 +23,7 @@ StatusScrollView { required property var collectiblesModel required property var channelsModel - // name, image, color, owner properties expected + // id, name, image, color, owner properties expected required property var communityDetails property int viewWidth: 560 // by design @@ -232,6 +232,8 @@ StatusScrollView { HoldingsDropdown { id: dropdown + communityId: root.communityDetails.id + assetsModel: root.assetsModel collectiblesModel: root.collectiblesModel diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityPermissionsView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityPermissionsView.qml index e7c5dc1bc5..c59a3a8b32 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityPermissionsView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityPermissionsView.qml @@ -16,7 +16,7 @@ StatusScrollView { required property var collectiblesModel required property var channelsModel - // name, image, color, owner properties expected + // id, name, image, color, owner properties expected required property var communityDetails property int viewWidth: 560 // by design