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:
parent
3e4e3591cd
commit
d6031f8126
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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] =
|
||||||
|
|
|
@ -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")
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]))
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue