From d6031f8126edf6e403e920359ae8f60843e8c70b Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 11 Oct 2024 12:35:35 -0400 Subject: [PATCH] refactor(members): use a single members list for public community chats (#16301) Fixes #16288 Introduces a new instance of the users module, but managed by the section module. This user module is managing the "public" community members list. Meaning that everytime we have a public channel in a community, we use that module instead. The channel's user module is empty for public channels to reduce the amount of processing and memory used. If the channel becomes private, we update the member list and populate it. --- .../chat_content/chat_details.nim | 2 +- .../main/chat_section/chat_content/module.nim | 6 +- .../chat_content/users/controller.nim | 21 +--- .../chat_content/users/io_interface.nim | 5 +- .../chat_content/users/module.nim | 96 +++++++++++++++---- .../chat_section/chat_content/users/view.nim | 4 +- .../modules/main/chat_section/controller.nim | 5 + .../main/chat_section/io_interface.nim | 6 ++ src/app/modules/main/chat_section/module.nim | 19 ++++ src/app/modules/main/chat_section/view.nim | 10 +- src/app_service/service/community/service.nim | 42 ++++---- .../service/contacts/dto/contacts.nim | 2 +- .../service/ens/dto/ens_username_dto.nim | 2 +- ui/app/AppLayouts/Chat/views/ChatView.qml | 12 ++- 14 files changed, 164 insertions(+), 68 deletions(-) diff --git a/src/app/modules/main/chat_section/chat_content/chat_details.nim b/src/app/modules/main/chat_section/chat_content/chat_details.nim index f1f454e69b..6534cee2ec 100644 --- a/src/app/modules/main/chat_section/chat_content/chat_details.nim +++ b/src/app/modules/main/chat_section/chat_content/chat_details.nim @@ -354,7 +354,7 @@ QtObject: self.missingEncryptionKeyChanged() proc requiresPermissionsChanged(self: ChatDetails) {.signal.} - proc getRequiresPermissions(self: ChatDetails): bool {.slot.} = + proc getRequiresPermissions*(self: ChatDetails): bool {.slot.} = return self.requiresPermissions QtProperty[bool] requiresPermissions: read = getRequiresPermissions diff --git a/src/app/modules/main/chat_section/chat_content/module.nim b/src/app/modules/main/chat_section/chat_content/module.nim index fc8f72a054..16a7ff5a71 100644 --- a/src/app/modules/main/chat_section/chat_content/module.nim +++ b/src/app/modules/main/chat_section/chat_content/module.nim @@ -401,7 +401,11 @@ method onCommunityChannelEdited*(self: Module, chatDto: ChatDto) = self.view.chatDetails.setName(chatDto.name) self.view.chatDetails.setIcon(chatDto.icon) self.view.chatDetails.setMissingEncryptionKey(chatDto.missingEncryptionKey) - self.view.chatDetails.setRequiresPermissions(chatDto.tokenGated) + + if self.view.chatDetails.getRequiresPermissions() != chatDto.tokenGated: + # The channel permission status changed. Update the member list + self.view.chatDetails.setRequiresPermissions(chatDto.tokenGated) + self.usersModule.updateMembersList() self.messagesModule.updateChatFetchMoreMessages() self.messagesModule.updateChatIdentifier() diff --git a/src/app/modules/main/chat_section/chat_content/users/controller.nim b/src/app/modules/main/chat_section/chat_content/users/controller.nim index 906ceaa858..5f893807e1 100644 --- a/src/app/modules/main/chat_section/chat_content/users/controller.nim +++ b/src/app/modules/main/chat_section/chat_content/users/controller.nim @@ -21,9 +21,6 @@ type communityService: community_service.Service messageService: message_service.Service -# Forward declaration -proc getChat*(self: Controller): ChatDto - proc newController*( delegate: io_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, @@ -63,7 +60,7 @@ proc init*(self: Controller) = self.delegate.loggedInUserImageChanged() # Events only for the user list, so not needed in one to one chats - if(self.isUsersListAvailable): + if self.isUsersListAvailable: self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args): var args = TrustArgs(e) self.delegate.contactUpdated(args.publicKey) @@ -118,19 +115,11 @@ proc belongsToCommunity*(self: Controller): bool = proc getMyCommunity*(self: Controller): CommunityDto = return self.communityService.getCommunityById(self.sectionId) -proc getChat*(self: Controller): ChatDto = - return self.chatService.getChatById(self.chatId) +proc getMyChatId*(self: Controller): string = + return self.chatId -proc getChatMembers*(self: Controller): seq[ChatMember] = - if self.belongsToCommunity: - let myCommunity = self.getMyCommunity() - # TODO: when a new channel is added, chat may arrive earlier and we have no up to date community yet - # see log here: https://github.com/status-im/status-desktop/issues/14442#issuecomment-2120756598 - # should be resolved in https://github.com/status-im/status-desktop/issues/14219 - let members = myCommunity.getCommunityChat(self.chatId).members - if members.len > 0: - return members - return self.chatService.getChatById(self.chatId).members +proc getMyChat*(self: Controller): ChatDto = + return self.chatService.getChatById(self.chatId) proc getContactNameAndImage*(self: Controller, contactId: string): tuple[name: string, image: string, largeImage: string] = diff --git a/src/app/modules/main/chat_section/chat_content/users/io_interface.nim b/src/app/modules/main/chat_section/chat_content/users/io_interface.nim index bce4b8c36b..ed47348666 100644 --- a/src/app/modules/main/chat_section/chat_content/users/io_interface.nim +++ b/src/app/modules/main/chat_section/chat_content/users/io_interface.nim @@ -20,6 +20,9 @@ method isLoaded*(self: AccessInterface): bool {.base.} = method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} = raise newException(ValueError, "No implementation available") +method getUsersListVariant*(self: AccessInterface): QVariant {.base.} = + raise newException(ValueError, "No implementation available") + method onNewMessagesLoaded*(self: AccessInterface, messages: seq[MessageDto]) {.base.} = raise newException(ValueError, "No implementation available") @@ -59,5 +62,5 @@ method addGroupMembers*(self: AccessInterface, pubKeys: seq[string]) {.base.} = method removeGroupMembers*(self: AccessInterface, pubKeys: seq[string]) {.base.} = raise newException(ValueError, "No implementation available") -method updateMembersList*(self: AccessInterface) {.base.} = +method updateMembersList*(self: AccessInterface, membersToReset: seq[ChatMember] = @[]) {.base.} = raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/main/chat_section/chat_content/users/module.nim b/src/app/modules/main/chat_section/chat_content/users/module.nim index 557f25fbe6..5f70a87022 100644 --- a/src/app/modules/main/chat_section/chat_content/users/module.nim +++ b/src/app/modules/main/chat_section/chat_content/users/module.nim @@ -4,13 +4,13 @@ import view, controller import ../../../../shared_models/[member_model, member_item] import ../../../../../global/global_singleton import ../../../../../core/eventemitter -import ../../../../../../app_service/common/conversion import ../../../../../../app_service/common/types import ../../../../../../app_service/service/contacts/dto/contacts import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/chat/service as chat_service import ../../../../../../app_service/service/community/service as community_service import ../../../../../../app_service/service/message/service as message_service +from ../../../../../../app_service/common/conversion import intToEnum export io_interface @@ -20,15 +20,17 @@ type viewVariant: QVariant controller: Controller moduleLoaded: bool + isPublicCommunityChannel: bool + isSectionMemberList: bool # Forward declaration -proc processChatMember(self: Module, member: ChatMember): MemberItem +proc processChatMember(self: Module, member: ChatMember, reset: bool = false): tuple[doAdd: bool, memberItem: MemberItem] proc newModule*( events: EventEmitter, sectionId: string, chatId: string, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, chatService: chat_service.Service, communityService: community_service.Service, - messageService: message_service.Service, + messageService: message_service.Service, isSectionMemberList: bool = false, ): Module = result = Module() result.view = view.newView(result) @@ -38,6 +40,8 @@ proc newModule*( contactService, chatService, communityService, messageService, ) result.moduleLoaded = false + result.isPublicCommunityChannel = false + result.isSectionMemberList = isSectionMemberList method delete*(self: Module) = self.controller.delete @@ -59,7 +63,12 @@ method viewDidLoad*(self: Module) = method getModuleAsVariant*(self: Module): QVariant = return self.viewVariant +method getUsersListVariant*(self: Module): QVariant = + self.view.getModel() + method contactNicknameChanged*(self: Module, publicKey: string) = + if self.isPublicCommunityChannel: + return let contactDetails = self.controller.getContactDetails(publicKey) self.view.model().setName( publicKey, @@ -69,11 +78,15 @@ method contactNicknameChanged*(self: Module, publicKey: string) = ) method contactsStatusUpdated*(self: Module, statusUpdates: seq[StatusUpdateDto]) = + if self.isPublicCommunityChannel: + return for s in statusUpdates: var status = toOnlineStatus(s.statusType) self.view.model().setOnlineStatus(s.publicKey, status) method contactUpdated*(self: Module, publicKey: string) = + if self.isPublicCommunityChannel: + return let contactDetails = self.controller.getContactDetails(publicKey) let isMe = publicKey == singletonInstance.userProfile.getPubKey() self.view.model().updateItem( @@ -90,37 +103,43 @@ method contactUpdated*(self: Module, publicKey: string) = ) method userProfileUpdated*(self: Module) = + if self.isPublicCommunityChannel: + return self.contactUpdated(singletonInstance.userProfile.getPubKey()) method loggedInUserImageChanged*(self: Module) = + if self.isPublicCommunityChannel: + return self.view.model().setIcon(singletonInstance.userProfile.getPubKey(), singletonInstance.userProfile.getIcon()) # This function either removes the member if it is no longer part of the community, # does nothing if the member is already in the model or creates the MemberItem -proc processChatMember(self: Module, member: ChatMember): MemberItem = +proc processChatMember(self: Module, member: ChatMember, reset: bool = false): tuple[doAdd: bool, memberItem: MemberItem] = + result.doAdd = false if member.id == "": return - if not self.controller.belongsToCommunity() and not member.joined: + if not reset and not self.controller.belongsToCommunity() and not member.joined: if self.view.model().isContactWithIdAdded(member.id): # Member is no longer joined self.view.model().removeItemById(member.id) return - if self.view.model().isContactWithIdAdded(member.id): + if not reset and self.view.model().isContactWithIdAdded(member.id): return let isMe = member.id == singletonInstance.userProfile.getPubKey() let contactDetails = self.controller.getContactDetails(member.id) var status = OnlineStatus.Online - if (isMe): + if isMe: let currentUserStatus = intToEnum(singletonInstance.userProfile.getCurrentUserStatus(), StatusType.Unknown) status = toOnlineStatus(currentUserStatus) else: let statusUpdateDto = self.controller.getStatusForContact(member.id) status = toOnlineStatus(statusUpdateDto.statusType) - return initMemberItem( + result.doAdd = true + result.memberItem = initMemberItem( pubKey = member.id, displayName = contactDetails.dto.displayName, ensName = contactDetails.dto.name, @@ -136,38 +155,45 @@ proc processChatMember(self: Module, member: ChatMember): MemberItem = memberRole = member.role, joined = member.joined, isUntrustworthy = contactDetails.dto.trustStatus == TrustStatus.Untrustworthy, - ) + ) method onChatMembersAdded*(self: Module, ids: seq[string]) = + if self.isPublicCommunityChannel: + return var memberItems: seq[MemberItem] = @[] for memberId in ids: - let item = self.processChatMember(ChatMember(id: memberId, role: MemberRole.None, joined: true)) - if item.pubKey != "": + let (doAdd, item) = self.processChatMember(ChatMember(id: memberId, role: MemberRole.None, joined: true)) + if doAdd: memberItems.add(item) self.view.model().addItems(memberItems) method onChatMemberRemoved*(self: Module, id: string) = + if self.isPublicCommunityChannel: + return self.view.model().removeItemById(id) method onMembersChanged*(self: Module, members: seq[ChatMember]) = + if self.isPublicCommunityChannel: + return let modelIDs = self.view.model().getItemIds() let membersAdded = filter(members, member => not modelIDs.contains(member.id)) let membersRemoved = filter(modelIDs, id => not members.any(member => member.id == id)) var memberItems: seq[MemberItem] = @[] for member in membersAdded: - let item = self.processChatMember(member) - if item.pubKey != "": + let (doAdd, item) = self.processChatMember(member) + if doAdd: memberItems.add(item) self.view.model().addItems(memberItems) for id in membersRemoved: self.onChatMemberRemoved(id) - method onChatMemberUpdated*(self: Module, publicKey: string, memberRole: MemberRole, joined: bool) = + if self.isPublicCommunityChannel: + return let contactDetails = self.controller.getContactDetails(publicKey) let isMe = publicKey == singletonInstance.userProfile.getPubKey() self.view.model().updateItem( @@ -191,13 +217,45 @@ method addGroupMembers*(self: Module, pubKeys: seq[string]) = method removeGroupMembers*(self: Module, pubKeys: seq[string]) = self.controller.removeGroupMembers(pubKeys) -method updateMembersList*(self: Module) = - let members = self.controller.getChatMembers() +method updateMembersList*(self: Module, membersToReset: seq[ChatMember] = @[]) = + let reset = membersToReset.len > 0 + var members: seq[ChatMember] + if reset: + members = membersToReset + else: + if self.controller.belongsToCommunity(): + let myCommunity = self.controller.getMyCommunity() + + if self.isSectionMemberList: + members = myCommunity.members + else: + # TODO: when a new channel is added, chat may arrive earlier and we have no up to date community yet + # see log here: https://github.com/status-im/status-desktop/issues/14442#issuecomment-2120756598 + # should be resolved in https://github.com/status-im/status-desktop/issues/11694 + let myChatId = self.controller.getMyChatId() + let chat = myCommunity.getCommunityChat(myChatId) + if not chat.tokenGated: + # No need to get the members, this channel is not encrypted and can use the section member list + self.isPublicCommunityChannel = true + return + self.isPublicCommunityChannel = false + if chat.members.len > 0: + members = chat.members + else: + # The channel now has a permisison, but the re-eval wasn't performed yet. Show all members for now + members = myCommunity.members + + if members.len == 0: + members = self.controller.getMyChat().members + var memberItems: seq[MemberItem] = @[] for member in members: - let item = self.processChatMember(member) - if item.pubKey != "": + let (doAdd, item) = self.processChatMember(member, reset) + if doAdd: memberItems.add(item) - self.view.model().addItems(memberItems) + if reset: + self.view.model().setItems(memberItems) + else: + self.view.model().addItems(memberItems) diff --git a/src/app/modules/main/chat_section/chat_content/users/view.nim b/src/app/modules/main/chat_section/chat_content/users/view.nim index 0b1e5d1501..3f83dab687 100644 --- a/src/app/modules/main/chat_section/chat_content/users/view.nim +++ b/src/app/modules/main/chat_section/chat_content/users/view.nim @@ -33,10 +33,10 @@ QtObject: proc modelChanged*(self: View) {.signal.} - proc getModel(self: View): QVariant {.slot.} = + proc getModel*(self: View): QVariant {.slot.} = return self.modelVariant - QtProperty[QVariant]model: + QtProperty[QVariant] model: read = getModel notify = modelChanged diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index 3ed2bb12e6..d264d56f8c 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -342,6 +342,11 @@ proc init*(self: Controller) = if args.communityId == self.sectionId: self.delegate.onSectionMutedChanged() + self.events.on(SIGNAL_COMMUNITY_MEMBERS_CHANGED) do(e: Args): + let args = CommunityMembersArgs(e) + if args.communityId == self.sectionId: + self.delegate.updateCommunityMemberList(args.members) + self.events.on(SIGNAL_CONTACT_NICKNAME_CHANGED) do(e: Args): var args = ContactArgs(e) self.delegate.onContactDetailsUpdated(args.contactId) diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim index 4614faf4d5..e1174a0d98 100644 --- a/src/app/modules/main/chat_section/io_interface.nim +++ b/src/app/modules/main/chat_section/io_interface.nim @@ -46,6 +46,12 @@ method isLoaded*(self: AccessInterface): bool {.base.} = method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} = raise newException(ValueError, "No implementation available") +method updateCommunityMemberList*(self: AccessInterface, members: seq[ChatMember]) {.base.} = + raise newException(ValueError, "No implementation available") + +method getSectionMemberList*(self: AccessInterface): QVariant {.base.} = + raise newException(ValueError, "No implementation available") + method onActiveSectionChange*(self: AccessInterface, sectionId: string) {.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 a3a8e22062..3d960cda6f 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -17,6 +17,7 @@ import ../../shared_models/token_criteria_model import ../../shared_models/token_permission_chat_list_model import chat_content/module as chat_content_module +import chat_content/users/module as users_module import ../../../global/global_singleton import ../../../core/eventemitter @@ -53,6 +54,7 @@ type chatContentModules: OrderedTable[string, chat_content_module.AccessInterface] moduleLoaded: bool chatsLoaded: bool + membersListModule: users_module.AccessInterface # Forward declaration proc buildChatSectionUI( @@ -121,6 +123,11 @@ proc newModule*( result.chatsLoaded = false result.chatContentModules = initOrderedTable[string, chat_content_module.AccessInterface]() + if isCommunity: + result.membersListModule = users_module.newModule(events, sectionId, chatId = "", isCommunity, + isUsersListAvailable = true, contactService, chatService, communityService, messageService, isSectionMemberList = true) + else: + result.membersListModule = nil proc currentUserWalletContainsAddress(self: Module, address: string): bool = if (address.len == 0): @@ -218,6 +225,8 @@ method delete*(self: Module) = for cModule in self.chatContentModules.values: cModule.delete self.chatContentModules.clear + if self.membersListModule != nil: + self.membersListModule.delete method isCommunity*(self: Module): bool = return self.controller.isCommunity() @@ -440,6 +449,10 @@ method onChatsLoaded*( self.buildChatSectionUI(community, chats, events, settingsService, nodeConfigurationService, contactService, chatService, communityService, messageService, mailserversService, sharedUrlsService) + # Generate members list + if self.membersListModule != nil: + self.membersListModule.load() + if(not self.controller.isCommunity()): # we do this only in case of chat section (not in case of communities) self.initContactRequestsModel() @@ -480,6 +493,12 @@ proc checkIfModuleDidLoad(self: Module) = method isLoaded*(self: Module): bool = return self.moduleLoaded +method getSectionMemberList*(self: Module): QVariant = + return self.membersListModule.getUsersListVariant() + +method updateCommunityMemberList*(self: Module, members: seq[ChatMember]) = + self.membersListModule.updateMembersList(members) + method viewDidLoad*(self: Module) = self.checkIfModuleDidLoad() diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim index e526602a89..85da4e93fe 100644 --- a/src/app/modules/main/chat_section/view.nim +++ b/src/app/modules/main/chat_section/view.nim @@ -572,4 +572,12 @@ QtObject: if self.communityMemberReevaluationStatus == value: return self.communityMemberReevaluationStatus = value - self.communityMemberReevaluationStatusChanged() \ No newline at end of file + self.communityMemberReevaluationStatusChanged() + + proc membersModelChanged*(self: View) {.signal.} + proc getMembersModel(self: View): QVariant {.slot.} = + return self.delegate.getSectionMemberList() + + QtProperty[QVariant] membersModel: + read = getMembersModel + notify = membersModelChanged diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim index ea8caa206a..dd2936a3de 100644 --- a/src/app_service/service/community/service.nim +++ b/src/app_service/service/community/service.nim @@ -509,10 +509,7 @@ QtObject: self.events.emit(SIGNAL_COMMUNITY_CATEGORY_NAME_EDITED, CommunityCategoryArgs(communityId: community.id, category: category)) - self.events.emit(SIGNAL_COMMUNITY_MEMBERS_CHANGED, - CommunityMembersArgs(communityId: community.id, members: community.members)) - - proc communityTokensChanged(self: Service, community: CommunityDto, prev_community: CommunityDto): bool = + proc communityTokensChanged(community: CommunityDto, prev_community: CommunityDto): bool = let communityTokens = community.communityTokensMetadata let prevCommunityTokens = prev_community.communityTokensMetadata # checking length is sufficient - communityTokensMetadata list can only extend @@ -536,6 +533,17 @@ QtObject: let prevCommunity = self.communities[community.id] + # If there's settings without `id` it means the original + # signal didn't include actual communitySettings, hence we + # assign the settings we already have, otherwise we risk our + # settings to be overridden with wrong defaults. + if community.settings.id == "": + community.settings = prevCommunity.settings + + # Save the updated community before calling events, because some events triggers look ups on the new community + # We will save again at the end if other properties were updated + self.saveUpdatedCommunity(community) + try: let currOwner = community.findOwner() let prevOwner = prevCommunity.findOwner() @@ -551,23 +559,15 @@ QtObject: let response = tokens_backend.registerLostOwnershipNotification(community.id) checkAndEmitACNotificationsFromResponse(self.events, response.result{"activityCenterNotifications"}) - if self.communityTokensChanged(community, prevCommunity): + if communityTokensChanged(community, prevCommunity): self.events.emit(SIGNAL_COMMUNITY_TOKENS_CHANGED, nil) - # If there's settings without `id` it means the original - # signal didn't include actual communitySettings, hence we - # assign the settings we already have, otherwise we risk our - # settings to be overridden with wrong defaults. - if community.settings.id == "": - community.settings = prevCommunity.settings - var deletedCategories: seq[string] = @[] # category was added if(community.categories.len > prevCommunity.categories.len): for category in community.categories: if findIndexById(category.id, prevCommunity.categories) == -1: - self.communities[community.id].categories.add(category) let chats = self.getChatsInCategory(community, category.id) self.events.emit(SIGNAL_COMMUNITY_CATEGORY_CREATED, @@ -665,13 +665,12 @@ QtObject: # members list was changed if community.members != prevCommunity.members: self.events.emit(SIGNAL_COMMUNITY_MEMBERS_CHANGED, - CommunityMembersArgs(communityId: community.id, members: community.members)) + CommunityMembersArgs(communityId: community.id, members: community.members)) # token metadata was added if community.communityTokensMetadata.len > prevCommunity.communityTokensMetadata.len: for tokenMetadata in community.communityTokensMetadata: if findIndexBySymbol(tokenMetadata.symbol, prevCommunity.communityTokensMetadata) == -1: - self.communities[community.id].communityTokensMetadata.add(tokenMetadata) self.events.emit(SIGNAL_COMMUNITY_TOKEN_METADATA_ADDED, CommunityTokenMetadataArgs(communityId: community.id, tokenMetadata: tokenMetadata)) @@ -680,16 +679,14 @@ QtObject: if community.tokenPermissions.len > prevCommunity.tokenPermissions.len: for id, tokenPermission in community.tokenPermissions: if not prevCommunity.tokenPermissions.hasKey(id): - self.communities[community.id].tokenPermissions[id] = tokenPermission self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATED, - CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: tokenPermission)) + CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: tokenPermission)) elif community.tokenPermissions.len < prevCommunity.tokenPermissions.len: for id, prvTokenPermission in prevCommunity.tokenPermissions: if not community.tokenPermissions.hasKey(id): - self.communities[community.id].tokenPermissions.del(id) self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETED, - CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: prvTokenPermission)) + CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: prvTokenPermission)) else: for id, tokenPermission in community.tokenPermissions: if not prevCommunity.tokenPermissions.hasKey(id): @@ -725,16 +722,13 @@ QtObject: break if permissionUpdated: - self.communities[community.id].tokenPermissions[id] = tokenPermission self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED, CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: tokenPermission)) - let wasJoined = self.communities[community.id].joined - - self.saveUpdatedCommunity(community) + let wasJoined = prevCommunity.joined # If the community was not joined before but is now, we signal it - if(not wasJoined and community.joined and community.isMember): + if not wasJoined and community.joined and community.isMember: self.events.emit(SIGNAL_COMMUNITY_JOINED, CommunityArgs(community: community, fromUserAction: false)) self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community])) diff --git a/src/app_service/service/contacts/dto/contacts.nim b/src/app_service/service/contacts/dto/contacts.nim index e973c02f5d..3363b75783 100644 --- a/src/app_service/service/contacts/dto/contacts.nim +++ b/src/app_service/service/contacts/dto/contacts.nim @@ -68,7 +68,7 @@ proc `$`(self: Images): string = ]""" proc `$`*(self: ContactsDto): string = - result = fmt"""ContactDto( + result = fmt"""ContactsDto( id: {self.id}, name: {self.name}, ensVerified: {self.ensVerified}, diff --git a/src/app_service/service/ens/dto/ens_username_dto.nim b/src/app_service/service/ens/dto/ens_username_dto.nim index 8f4b3ceaf6..1cdef21361 100644 --- a/src/app_service/service/ens/dto/ens_username_dto.nim +++ b/src/app_service/service/ens/dto/ens_username_dto.nim @@ -15,7 +15,7 @@ proc `==`*(l, r: EnsUsernameDto): bool = return l.chainId == r.chainid and l.username == r.username proc `$`*(self: EnsUsernameDto): string = - result = fmt"""ContactDto( + result = fmt"""EnsUsernameDto( chainId: {self.chainId}, username: {self.username}, txType: {self.txType}, diff --git a/ui/app/AppLayouts/Chat/views/ChatView.qml b/ui/app/AppLayouts/Chat/views/ChatView.qml index a27b6a96ff..6bf897db64 100644 --- a/ui/app/AppLayouts/Chat/views/ChatView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatView.qml @@ -179,7 +179,17 @@ StatusSectionLayout { store: root.rootStore label: qsTr("Members") communityMemberReevaluationStatus: root.rootStore.communityMemberReevaluationStatus - usersModel: root.chatContentModule && root.chatContentModule.usersModule ? root.chatContentModule.usersModule.model : null + usersModel: { + if (!root.chatContentModule || !root.chatContentModule.chatDetails) { + return null + } + let isFullCommunityList = !root.chatContentModule.chatDetails.requiresPermissions + if (root.chatContentModule.chatDetails.belongsToCommunity && isFullCommunityList) { + // Community channel with no permisisons. We can use the section's membersModel + return root.rootStore.chatCommunitySectionModule.membersModel + } + return root.chatContentModule.usersModule ? root.chatContentModule.usersModule.model : null + } } }