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.
This commit is contained in:
Jonathan Rainville 2024-10-11 12:35:35 -04:00 committed by GitHub
parent 3e4e3591cd
commit d6031f8126
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 164 additions and 68 deletions

View File

@ -354,7 +354,7 @@ QtObject:
self.missingEncryptionKeyChanged() self.missingEncryptionKeyChanged()
proc requiresPermissionsChanged(self: ChatDetails) {.signal.} proc requiresPermissionsChanged(self: ChatDetails) {.signal.}
proc getRequiresPermissions(self: ChatDetails): bool {.slot.} = proc getRequiresPermissions*(self: ChatDetails): bool {.slot.} =
return self.requiresPermissions return self.requiresPermissions
QtProperty[bool] requiresPermissions: QtProperty[bool] requiresPermissions:
read = getRequiresPermissions read = getRequiresPermissions

View File

@ -401,7 +401,11 @@ method onCommunityChannelEdited*(self: Module, chatDto: ChatDto) =
self.view.chatDetails.setName(chatDto.name) self.view.chatDetails.setName(chatDto.name)
self.view.chatDetails.setIcon(chatDto.icon) self.view.chatDetails.setIcon(chatDto.icon)
self.view.chatDetails.setMissingEncryptionKey(chatDto.missingEncryptionKey) self.view.chatDetails.setMissingEncryptionKey(chatDto.missingEncryptionKey)
if self.view.chatDetails.getRequiresPermissions() != chatDto.tokenGated:
# The channel permission status changed. Update the member list
self.view.chatDetails.setRequiresPermissions(chatDto.tokenGated) self.view.chatDetails.setRequiresPermissions(chatDto.tokenGated)
self.usersModule.updateMembersList()
self.messagesModule.updateChatFetchMoreMessages() self.messagesModule.updateChatFetchMoreMessages()
self.messagesModule.updateChatIdentifier() self.messagesModule.updateChatIdentifier()

View File

@ -21,9 +21,6 @@ type
communityService: community_service.Service communityService: community_service.Service
messageService: message_service.Service messageService: message_service.Service
# Forward declaration
proc getChat*(self: Controller): ChatDto
proc newController*( proc newController*(
delegate: io_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string, delegate: io_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service,
@ -63,7 +60,7 @@ proc init*(self: Controller) =
self.delegate.loggedInUserImageChanged() self.delegate.loggedInUserImageChanged()
# Events only for the user list, so not needed in one to one chats # 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): self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args):
var args = TrustArgs(e) var args = TrustArgs(e)
self.delegate.contactUpdated(args.publicKey) self.delegate.contactUpdated(args.publicKey)
@ -118,19 +115,11 @@ proc belongsToCommunity*(self: Controller): bool =
proc getMyCommunity*(self: Controller): CommunityDto = proc getMyCommunity*(self: Controller): CommunityDto =
return self.communityService.getCommunityById(self.sectionId) return self.communityService.getCommunityById(self.sectionId)
proc getChat*(self: Controller): ChatDto = proc getMyChatId*(self: Controller): string =
return self.chatService.getChatById(self.chatId) return self.chatId
proc getChatMembers*(self: Controller): seq[ChatMember] = proc getMyChat*(self: Controller): ChatDto =
if self.belongsToCommunity: return self.chatService.getChatById(self.chatId)
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 getContactNameAndImage*(self: Controller, contactId: string): proc getContactNameAndImage*(self: Controller, contactId: string):
tuple[name: string, image: string, largeImage: string] = tuple[name: string, image: string, largeImage: string] =

View File

@ -20,6 +20,9 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} = method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available") 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.} = method onNewMessagesLoaded*(self: AccessInterface, messages: seq[MessageDto]) {.base.} =
raise newException(ValueError, "No implementation available") 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.} = method removeGroupMembers*(self: AccessInterface, pubKeys: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available") 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") raise newException(ValueError, "No implementation available")

View File

@ -4,13 +4,13 @@ import view, controller
import ../../../../shared_models/[member_model, member_item] import ../../../../shared_models/[member_model, member_item]
import ../../../../../global/global_singleton import ../../../../../global/global_singleton
import ../../../../../core/eventemitter import ../../../../../core/eventemitter
import ../../../../../../app_service/common/conversion
import ../../../../../../app_service/common/types import ../../../../../../app_service/common/types
import ../../../../../../app_service/service/contacts/dto/contacts import ../../../../../../app_service/service/contacts/dto/contacts
import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/contacts/service as contact_service
import ../../../../../../app_service/service/chat/service as chat_service import ../../../../../../app_service/service/chat/service as chat_service
import ../../../../../../app_service/service/community/service as community_service import ../../../../../../app_service/service/community/service as community_service
import ../../../../../../app_service/service/message/service as message_service import ../../../../../../app_service/service/message/service as message_service
from ../../../../../../app_service/common/conversion import intToEnum
export io_interface export io_interface
@ -20,15 +20,17 @@ type
viewVariant: QVariant viewVariant: QVariant
controller: Controller controller: Controller
moduleLoaded: bool moduleLoaded: bool
isPublicCommunityChannel: bool
isSectionMemberList: bool
# Forward declaration # 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*( proc newModule*(
events: EventEmitter, sectionId: string, chatId: string, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service, belongsToCommunity: bool, isUsersListAvailable: bool, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.Service, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service, messageService: message_service.Service, isSectionMemberList: bool = false,
): Module = ): Module =
result = Module() result = Module()
result.view = view.newView(result) result.view = view.newView(result)
@ -38,6 +40,8 @@ proc newModule*(
contactService, chatService, communityService, messageService, contactService, chatService, communityService, messageService,
) )
result.moduleLoaded = false result.moduleLoaded = false
result.isPublicCommunityChannel = false
result.isSectionMemberList = isSectionMemberList
method delete*(self: Module) = method delete*(self: Module) =
self.controller.delete self.controller.delete
@ -59,7 +63,12 @@ method viewDidLoad*(self: Module) =
method getModuleAsVariant*(self: Module): QVariant = method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant return self.viewVariant
method getUsersListVariant*(self: Module): QVariant =
self.view.getModel()
method contactNicknameChanged*(self: Module, publicKey: string) = method contactNicknameChanged*(self: Module, publicKey: string) =
if self.isPublicCommunityChannel:
return
let contactDetails = self.controller.getContactDetails(publicKey) let contactDetails = self.controller.getContactDetails(publicKey)
self.view.model().setName( self.view.model().setName(
publicKey, publicKey,
@ -69,11 +78,15 @@ method contactNicknameChanged*(self: Module, publicKey: string) =
) )
method contactsStatusUpdated*(self: Module, statusUpdates: seq[StatusUpdateDto]) = method contactsStatusUpdated*(self: Module, statusUpdates: seq[StatusUpdateDto]) =
if self.isPublicCommunityChannel:
return
for s in statusUpdates: for s in statusUpdates:
var status = toOnlineStatus(s.statusType) var status = toOnlineStatus(s.statusType)
self.view.model().setOnlineStatus(s.publicKey, status) self.view.model().setOnlineStatus(s.publicKey, status)
method contactUpdated*(self: Module, publicKey: string) = method contactUpdated*(self: Module, publicKey: string) =
if self.isPublicCommunityChannel:
return
let contactDetails = self.controller.getContactDetails(publicKey) let contactDetails = self.controller.getContactDetails(publicKey)
let isMe = publicKey == singletonInstance.userProfile.getPubKey() let isMe = publicKey == singletonInstance.userProfile.getPubKey()
self.view.model().updateItem( self.view.model().updateItem(
@ -90,37 +103,43 @@ method contactUpdated*(self: Module, publicKey: string) =
) )
method userProfileUpdated*(self: Module) = method userProfileUpdated*(self: Module) =
if self.isPublicCommunityChannel:
return
self.contactUpdated(singletonInstance.userProfile.getPubKey()) self.contactUpdated(singletonInstance.userProfile.getPubKey())
method loggedInUserImageChanged*(self: Module) = method loggedInUserImageChanged*(self: Module) =
if self.isPublicCommunityChannel:
return
self.view.model().setIcon(singletonInstance.userProfile.getPubKey(), singletonInstance.userProfile.getIcon()) 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, # 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 # 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 == "": if member.id == "":
return 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): if self.view.model().isContactWithIdAdded(member.id):
# Member is no longer joined # Member is no longer joined
self.view.model().removeItemById(member.id) self.view.model().removeItemById(member.id)
return return
if self.view.model().isContactWithIdAdded(member.id): if not reset and self.view.model().isContactWithIdAdded(member.id):
return return
let isMe = member.id == singletonInstance.userProfile.getPubKey() let isMe = member.id == singletonInstance.userProfile.getPubKey()
let contactDetails = self.controller.getContactDetails(member.id) let contactDetails = self.controller.getContactDetails(member.id)
var status = OnlineStatus.Online var status = OnlineStatus.Online
if (isMe): if isMe:
let currentUserStatus = intToEnum(singletonInstance.userProfile.getCurrentUserStatus(), StatusType.Unknown) let currentUserStatus = intToEnum(singletonInstance.userProfile.getCurrentUserStatus(), StatusType.Unknown)
status = toOnlineStatus(currentUserStatus) status = toOnlineStatus(currentUserStatus)
else: else:
let statusUpdateDto = self.controller.getStatusForContact(member.id) let statusUpdateDto = self.controller.getStatusForContact(member.id)
status = toOnlineStatus(statusUpdateDto.statusType) status = toOnlineStatus(statusUpdateDto.statusType)
return initMemberItem( result.doAdd = true
result.memberItem = initMemberItem(
pubKey = member.id, pubKey = member.id,
displayName = contactDetails.dto.displayName, displayName = contactDetails.dto.displayName,
ensName = contactDetails.dto.name, ensName = contactDetails.dto.name,
@ -139,35 +158,42 @@ proc processChatMember(self: Module, member: ChatMember): MemberItem =
) )
method onChatMembersAdded*(self: Module, ids: seq[string]) = method onChatMembersAdded*(self: Module, ids: seq[string]) =
if self.isPublicCommunityChannel:
return
var memberItems: seq[MemberItem] = @[] var memberItems: seq[MemberItem] = @[]
for memberId in ids: for memberId in ids:
let item = self.processChatMember(ChatMember(id: memberId, role: MemberRole.None, joined: true)) let (doAdd, item) = self.processChatMember(ChatMember(id: memberId, role: MemberRole.None, joined: true))
if item.pubKey != "": if doAdd:
memberItems.add(item) memberItems.add(item)
self.view.model().addItems(memberItems) self.view.model().addItems(memberItems)
method onChatMemberRemoved*(self: Module, id: string) = method onChatMemberRemoved*(self: Module, id: string) =
if self.isPublicCommunityChannel:
return
self.view.model().removeItemById(id) self.view.model().removeItemById(id)
method onMembersChanged*(self: Module, members: seq[ChatMember]) = method onMembersChanged*(self: Module, members: seq[ChatMember]) =
if self.isPublicCommunityChannel:
return
let modelIDs = self.view.model().getItemIds() let modelIDs = self.view.model().getItemIds()
let membersAdded = filter(members, member => not modelIDs.contains(member.id)) let membersAdded = filter(members, member => not modelIDs.contains(member.id))
let membersRemoved = filter(modelIDs, id => not members.any(member => member.id == id)) let membersRemoved = filter(modelIDs, id => not members.any(member => member.id == id))
var memberItems: seq[MemberItem] = @[] var memberItems: seq[MemberItem] = @[]
for member in membersAdded: for member in membersAdded:
let item = self.processChatMember(member) let (doAdd, item) = self.processChatMember(member)
if item.pubKey != "": if doAdd:
memberItems.add(item) memberItems.add(item)
self.view.model().addItems(memberItems) self.view.model().addItems(memberItems)
for id in membersRemoved: for id in membersRemoved:
self.onChatMemberRemoved(id) self.onChatMemberRemoved(id)
method onChatMemberUpdated*(self: Module, publicKey: string, memberRole: MemberRole, joined: bool) = method onChatMemberUpdated*(self: Module, publicKey: string, memberRole: MemberRole, joined: bool) =
if self.isPublicCommunityChannel:
return
let contactDetails = self.controller.getContactDetails(publicKey) let contactDetails = self.controller.getContactDetails(publicKey)
let isMe = publicKey == singletonInstance.userProfile.getPubKey() let isMe = publicKey == singletonInstance.userProfile.getPubKey()
self.view.model().updateItem( self.view.model().updateItem(
@ -191,13 +217,45 @@ method addGroupMembers*(self: Module, pubKeys: seq[string]) =
method removeGroupMembers*(self: Module, pubKeys: seq[string]) = method removeGroupMembers*(self: Module, pubKeys: seq[string]) =
self.controller.removeGroupMembers(pubKeys) self.controller.removeGroupMembers(pubKeys)
method updateMembersList*(self: Module) = method updateMembersList*(self: Module, membersToReset: seq[ChatMember] = @[]) =
let members = self.controller.getChatMembers() 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] = @[] var memberItems: seq[MemberItem] = @[]
for member in members: for member in members:
let item = self.processChatMember(member) let (doAdd, item) = self.processChatMember(member, reset)
if item.pubKey != "": if doAdd:
memberItems.add(item) memberItems.add(item)
if reset:
self.view.model().setItems(memberItems)
else:
self.view.model().addItems(memberItems) self.view.model().addItems(memberItems)

View File

@ -33,10 +33,10 @@ QtObject:
proc modelChanged*(self: View) {.signal.} proc modelChanged*(self: View) {.signal.}
proc getModel(self: View): QVariant {.slot.} = proc getModel*(self: View): QVariant {.slot.} =
return self.modelVariant return self.modelVariant
QtProperty[QVariant]model: QtProperty[QVariant] model:
read = getModel read = getModel
notify = modelChanged notify = modelChanged

View File

@ -342,6 +342,11 @@ proc init*(self: Controller) =
if args.communityId == self.sectionId: if args.communityId == self.sectionId:
self.delegate.onSectionMutedChanged() 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): self.events.on(SIGNAL_CONTACT_NICKNAME_CHANGED) do(e: Args):
var args = ContactArgs(e) var args = ContactArgs(e)
self.delegate.onContactDetailsUpdated(args.contactId) self.delegate.onContactDetailsUpdated(args.contactId)

View File

@ -46,6 +46,12 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} = method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available") 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.} = method onActiveSectionChange*(self: AccessInterface, sectionId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -17,6 +17,7 @@ import ../../shared_models/token_criteria_model
import ../../shared_models/token_permission_chat_list_model import ../../shared_models/token_permission_chat_list_model
import chat_content/module as chat_content_module import chat_content/module as chat_content_module
import chat_content/users/module as users_module
import ../../../global/global_singleton import ../../../global/global_singleton
import ../../../core/eventemitter import ../../../core/eventemitter
@ -53,6 +54,7 @@ type
chatContentModules: OrderedTable[string, chat_content_module.AccessInterface] chatContentModules: OrderedTable[string, chat_content_module.AccessInterface]
moduleLoaded: bool moduleLoaded: bool
chatsLoaded: bool chatsLoaded: bool
membersListModule: users_module.AccessInterface
# Forward declaration # Forward declaration
proc buildChatSectionUI( proc buildChatSectionUI(
@ -121,6 +123,11 @@ proc newModule*(
result.chatsLoaded = false result.chatsLoaded = false
result.chatContentModules = initOrderedTable[string, chat_content_module.AccessInterface]() 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 = proc currentUserWalletContainsAddress(self: Module, address: string): bool =
if (address.len == 0): if (address.len == 0):
@ -218,6 +225,8 @@ method delete*(self: Module) =
for cModule in self.chatContentModules.values: for cModule in self.chatContentModules.values:
cModule.delete cModule.delete
self.chatContentModules.clear self.chatContentModules.clear
if self.membersListModule != nil:
self.membersListModule.delete
method isCommunity*(self: Module): bool = method isCommunity*(self: Module): bool =
return self.controller.isCommunity() return self.controller.isCommunity()
@ -440,6 +449,10 @@ method onChatsLoaded*(
self.buildChatSectionUI(community, chats, events, settingsService, nodeConfigurationService, self.buildChatSectionUI(community, chats, events, settingsService, nodeConfigurationService,
contactService, chatService, communityService, messageService, mailserversService, sharedUrlsService) contactService, chatService, communityService, messageService, mailserversService, sharedUrlsService)
# Generate members list
if self.membersListModule != nil:
self.membersListModule.load()
if(not self.controller.isCommunity()): if(not self.controller.isCommunity()):
# we do this only in case of chat section (not in case of communities) # we do this only in case of chat section (not in case of communities)
self.initContactRequestsModel() self.initContactRequestsModel()
@ -480,6 +493,12 @@ proc checkIfModuleDidLoad(self: Module) =
method isLoaded*(self: Module): bool = method isLoaded*(self: Module): bool =
return self.moduleLoaded 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) = method viewDidLoad*(self: Module) =
self.checkIfModuleDidLoad() self.checkIfModuleDidLoad()

View File

@ -573,3 +573,11 @@ QtObject:
return return
self.communityMemberReevaluationStatus = value self.communityMemberReevaluationStatus = value
self.communityMemberReevaluationStatusChanged() self.communityMemberReevaluationStatusChanged()
proc membersModelChanged*(self: View) {.signal.}
proc getMembersModel(self: View): QVariant {.slot.} =
return self.delegate.getSectionMemberList()
QtProperty[QVariant] membersModel:
read = getMembersModel
notify = membersModelChanged

View File

@ -509,10 +509,7 @@ QtObject:
self.events.emit(SIGNAL_COMMUNITY_CATEGORY_NAME_EDITED, self.events.emit(SIGNAL_COMMUNITY_CATEGORY_NAME_EDITED,
CommunityCategoryArgs(communityId: community.id, category: category)) CommunityCategoryArgs(communityId: community.id, category: category))
self.events.emit(SIGNAL_COMMUNITY_MEMBERS_CHANGED, proc communityTokensChanged(community: CommunityDto, prev_community: CommunityDto): bool =
CommunityMembersArgs(communityId: community.id, members: community.members))
proc communityTokensChanged(self: Service, community: CommunityDto, prev_community: CommunityDto): bool =
let communityTokens = community.communityTokensMetadata let communityTokens = community.communityTokensMetadata
let prevCommunityTokens = prev_community.communityTokensMetadata let prevCommunityTokens = prev_community.communityTokensMetadata
# checking length is sufficient - communityTokensMetadata list can only extend # checking length is sufficient - communityTokensMetadata list can only extend
@ -536,6 +533,17 @@ QtObject:
let prevCommunity = self.communities[community.id] 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: try:
let currOwner = community.findOwner() let currOwner = community.findOwner()
let prevOwner = prevCommunity.findOwner() let prevOwner = prevCommunity.findOwner()
@ -551,23 +559,15 @@ QtObject:
let response = tokens_backend.registerLostOwnershipNotification(community.id) let response = tokens_backend.registerLostOwnershipNotification(community.id)
checkAndEmitACNotificationsFromResponse(self.events, response.result{"activityCenterNotifications"}) checkAndEmitACNotificationsFromResponse(self.events, response.result{"activityCenterNotifications"})
if self.communityTokensChanged(community, prevCommunity): if communityTokensChanged(community, prevCommunity):
self.events.emit(SIGNAL_COMMUNITY_TOKENS_CHANGED, nil) 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] = @[] var deletedCategories: seq[string] = @[]
# category was added # category was added
if(community.categories.len > prevCommunity.categories.len): if(community.categories.len > prevCommunity.categories.len):
for category in community.categories: for category in community.categories:
if findIndexById(category.id, prevCommunity.categories) == -1: if findIndexById(category.id, prevCommunity.categories) == -1:
self.communities[community.id].categories.add(category)
let chats = self.getChatsInCategory(community, category.id) let chats = self.getChatsInCategory(community, category.id)
self.events.emit(SIGNAL_COMMUNITY_CATEGORY_CREATED, self.events.emit(SIGNAL_COMMUNITY_CATEGORY_CREATED,
@ -671,7 +671,6 @@ QtObject:
if community.communityTokensMetadata.len > prevCommunity.communityTokensMetadata.len: if community.communityTokensMetadata.len > prevCommunity.communityTokensMetadata.len:
for tokenMetadata in community.communityTokensMetadata: for tokenMetadata in community.communityTokensMetadata:
if findIndexBySymbol(tokenMetadata.symbol, prevCommunity.communityTokensMetadata) == -1: if findIndexBySymbol(tokenMetadata.symbol, prevCommunity.communityTokensMetadata) == -1:
self.communities[community.id].communityTokensMetadata.add(tokenMetadata)
self.events.emit(SIGNAL_COMMUNITY_TOKEN_METADATA_ADDED, self.events.emit(SIGNAL_COMMUNITY_TOKEN_METADATA_ADDED,
CommunityTokenMetadataArgs(communityId: community.id, CommunityTokenMetadataArgs(communityId: community.id,
tokenMetadata: tokenMetadata)) tokenMetadata: tokenMetadata))
@ -680,14 +679,12 @@ QtObject:
if community.tokenPermissions.len > prevCommunity.tokenPermissions.len: if community.tokenPermissions.len > prevCommunity.tokenPermissions.len:
for id, tokenPermission in community.tokenPermissions: for id, tokenPermission in community.tokenPermissions:
if not prevCommunity.tokenPermissions.hasKey(id): if not prevCommunity.tokenPermissions.hasKey(id):
self.communities[community.id].tokenPermissions[id] = tokenPermission
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATED, 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: elif community.tokenPermissions.len < prevCommunity.tokenPermissions.len:
for id, prvTokenPermission in prevCommunity.tokenPermissions: for id, prvTokenPermission in prevCommunity.tokenPermissions:
if not community.tokenPermissions.hasKey(id): if not community.tokenPermissions.hasKey(id):
self.communities[community.id].tokenPermissions.del(id)
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETED, self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETED,
CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: prvTokenPermission)) CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: prvTokenPermission))
else: else:
@ -725,16 +722,13 @@ QtObject:
break break
if permissionUpdated: if permissionUpdated:
self.communities[community.id].tokenPermissions[id] = tokenPermission
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED, self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED,
CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: tokenPermission)) CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: tokenPermission))
let wasJoined = self.communities[community.id].joined let wasJoined = prevCommunity.joined
self.saveUpdatedCommunity(community)
# If the community was not joined before but is now, we signal it # 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_COMMUNITY_JOINED, CommunityArgs(community: community, fromUserAction: false))
self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community])) self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community]))

View File

@ -68,7 +68,7 @@ proc `$`(self: Images): string =
]""" ]"""
proc `$`*(self: ContactsDto): string = proc `$`*(self: ContactsDto): string =
result = fmt"""ContactDto( result = fmt"""ContactsDto(
id: {self.id}, id: {self.id},
name: {self.name}, name: {self.name},
ensVerified: {self.ensVerified}, ensVerified: {self.ensVerified},

View File

@ -15,7 +15,7 @@ proc `==`*(l, r: EnsUsernameDto): bool =
return l.chainId == r.chainid and l.username == r.username return l.chainId == r.chainid and l.username == r.username
proc `$`*(self: EnsUsernameDto): string = proc `$`*(self: EnsUsernameDto): string =
result = fmt"""ContactDto( result = fmt"""EnsUsernameDto(
chainId: {self.chainId}, chainId: {self.chainId},
username: {self.username}, username: {self.username},
txType: {self.txType}, txType: {self.txType},

View File

@ -179,7 +179,17 @@ StatusSectionLayout {
store: root.rootStore store: root.rootStore
label: qsTr("Members") label: qsTr("Members")
communityMemberReevaluationStatus: root.rootStore.communityMemberReevaluationStatus 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
}
} }
} }