Fix(@chat): add special cases for group chat

fixes #4612
fixes #4613
This commit is contained in:
Anthony Laibe 2022-02-03 10:44:35 +01:00 committed by Anthony Laibe
parent 5c034f545d
commit 5ebafb1c0c
9 changed files with 145 additions and 41 deletions

View File

@ -53,8 +53,10 @@ proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitt
result.inputAreaModule = input_area_module.newModule(result, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService)
result.messagesModule = messages_module.newModule(result, events, sectionId, chatId, belongsToCommunity,
contactService, communityService, chatService, messageService, mailserversService)
result.usersModule = users_module.newModule(result, events, sectionId, chatId, belongsToCommunity, isUsersListAvailable,
contactService, chatService, communityService, messageService)
result.usersModule = users_module.newModule(
result, events, sectionId, chatId, belongsToCommunity, isUsersListAvailable,
contactService, chat_service, communityService, messageService,
)
method delete*(self: Module) =
self.inputAreaModule.delete

View File

@ -25,11 +25,12 @@ type
communityService: community_service.Service
messageService: message_service.Service
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
proc newController*(
delegate: io_interface.AccessInterface, 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):
Controller =
messageService: message_service.Service
): Controller =
result = Controller()
result.delegate = delegate
result.events = events
@ -41,6 +42,7 @@ proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter
result.chatService = chatService
result.communityService = communityService
result.messageService = messageService
result.chatService = chatService
method delete*(self: Controller) =
discard
@ -80,20 +82,36 @@ method init*(self: Controller) =
if (args.chatId == self.chatId):
self.delegate.onChatMemberRemoved(args.id)
self.events.on(SIGNAL_CHAT_MEMBER_UPDATED) do(e: Args):
let args = ChatMemberUpdatedArgs(e)
if (args.chatId == self.chatId):
self.delegate.onChatMemberUpdated(args.id, args.admin, args.joined)
if (self.belongsToCommunity):
self.events.on(SIGNAL_COMMUNITY_MEMBER_APPROVED) do(e: Args):
let args = CommunityMemberArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onChatMembersAdded(@[args.pubKey])
method getChat*(self: Controller): ChatDto =
return self.chatService.getChatById(self.chatId)
method getChatMemberInfo*(self: Controller, id: string): (bool, bool) =
let chat = self.getChat()
for member in chat.members:
if (member.id == id):
return (member.admin, member.joined)
return (false, false)
method getMembersPublicKeys*(self: Controller): seq[string] =
if(not self.belongsToCommunity):
let chatDto = self.chatService.getChatById(self.chatId)
return chatDto.members.map(x => x.id)
else:
if(self.belongsToCommunity):
let communityDto = self.communityService.getCommunityById(self.sectionId)
return communityDto.members.map(x => x.id)
else:
let chatDto = self.getChat()
return chatDto.members.map(x => x.id)
method getContactNameAndImage*(self: Controller, contactId: string):
tuple[name: string, image: string, isIdenticon: bool] =
return self.contactService.getContactNameAndImage(contactId)

View File

@ -1,4 +1,5 @@
import ../../../../../../app_service/service/contacts/service as contacts_service
import ../../../../../../app_service/service/chat/service as chat_service
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -21,4 +22,10 @@ method getContactNameAndImage*(self: AccessInterface, contactId: string):
raise newException(ValueError, "No implementation available")
method getStatusForContact*(self: AccessInterface, contactId: string): StatusUpdateDto {.base.} =
raise newException(ValueError, "No implementation available")
raise newException(ValueError, "No implementation available")
method getChat*(self: AccessInterface): ChatDto {.base.} =
raise newException(ValueError, "No implementation available")
method getChatMemberInfo*(self: AccessInterface, id: string): (bool, bool) =
raise newException(ValueError, "No implementation available")

View File

@ -20,17 +20,20 @@ type
controller: controller.AccessInterface
moduleLoaded: bool
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
proc newModule*(
delegate: delegate_interface.AccessInterface, 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):
Module =
chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, sectionId, chatId, belongsToCommunity, isUsersListAvailable,
contactService, chatService, communityService, messageService)
result.controller = controller.newController(
result, events, sectionId, chatId, belongsToCommunity, isUsersListAvailable,
contactService, chatService, communityService, messageService,
)
result.moduleLoaded = false
method delete*(self: Module) =
@ -47,19 +50,29 @@ method isLoaded*(self: Module): bool =
method viewDidLoad*(self: Module) =
# add me as the first user to the list
let (admin, joined) = self.controller.getChatMemberInfo(singletonInstance.userProfile.getPubKey())
let loggedInUserDisplayName = singletonInstance.userProfile.getName() & "(You)"
self.view.model().addItem(initItem(singletonInstance.userProfile.getPubKey(), loggedInUserDisplayName,
OnlineStatus.Online, singletonInstance.userProfile.getIcon(), singletonInstance.userProfile.getIsIdenticon()))
self.view.model().addItem(initItem(
singletonInstance.userProfile.getPubKey(),
loggedInUserDisplayName,
OnlineStatus.Online,
singletonInstance.userProfile.getIcon(),
singletonInstance.userProfile.getIsIdenticon(),
admin,
joined,
))
# add other memebers
let usersKeys = self.controller.getMembersPublicKeys()
for k in usersKeys:
if (k == singletonInstance.userProfile.getPubKey()):
# add other memebers
let publicKeys = self.controller.getMembersPublicKeys()
for publicKey in publicKeys:
if (publicKey == singletonInstance.userProfile.getPubKey()):
continue
let (name, image, isIdenticon) = self.controller.getContactNameAndImage(k)
let statusUpdateDto = self.controller.getStatusForContact(k)
let (admin, joined) = self.controller.getChatMemberInfo(publicKey)
let (name, image, isIdenticon) = self.controller.getContactNameAndImage(publicKey)
let statusUpdateDto = self.controller.getStatusForContact(publicKey)
let status = statusUpdateDto.statusType.int.OnlineStatus
self.view.model().addItem(initItem(k, name, status, image, isidenticon))
self.view.model().addItem(initItem(publicKey, name, status, image, isidenticon, admin, joined))
self.moduleLoaded = true
self.delegate.usersDidLoad()
@ -67,7 +80,11 @@ method viewDidLoad*(self: Module) =
method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant
method newMessagesLoaded*(self: Module, messages: seq[MessageDto]) =
method newMessagesLoaded*(self: Module, messages: seq[MessageDto]) =
let chat = self.controller.getChat()
if not chat.isPublicChat():
return
for m in messages:
if(self.view.model().isContactWithIdAdded(m.`from`)):
continue
@ -98,11 +115,16 @@ method onChatMembersAdded*(self: Module, ids: seq[string]) =
for id in ids:
if(self.view.model().isContactWithIdAdded(id)):
continue
let (admin, joined) = self.controller.getChatMemberInfo(id)
let (name, image, isIdenticon) = self.controller.getContactNameAndImage(id)
let statusUpdateDto = self.controller.getStatusForContact(id)
let status = statusUpdateDto.statusType.int.OnlineStatus
self.view.model().addItem(initItem(id, name, status, image, isidenticon))
self.view.model().addItem(initItem(id, name, status, image, isidenticon, admin, joined))
method onChatMemberRemoved*(self: Module, id: string) =
self.view.model().removeItemById(id)
self.view.model().removeItemById(id)
method onChatMemberUpdated*(self: Module, publicKey: string, admin: bool, joined: bool) =
let (name, image, isIdenticon) = self.controller.getContactNameAndImage(publicKey)
self.view.model().updateItem(publicKey, name, image, isIdenticon, admin, joined)

View File

@ -20,4 +20,7 @@ method onChatMembersAdded*(self: AccessInterface, ids: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available")
method onChatMemberRemoved*(self: AccessInterface, ids: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onChatMemberUpdated*(self: AccessInterface, id: string, admin: bool, joined: bool) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -16,20 +16,26 @@ type
onlineStatus: OnlineStatus
icon: string
isIdenticon: bool
isAdmin: bool
joined: bool
proc initItem*(
id: string,
name: string,
onlineStatus: OnlineStatus,
icon: string,
isidenticon: bool
): Item =
id: string,
name: string,
onlineStatus: OnlineStatus,
icon: string,
isidenticon: bool,
isAdmin: bool = false,
joined: bool = false,
): Item =
result = Item()
result.id = id
result.name = name
result.onlineStatus = onlineStatus
result.icon = icon
result.isIdenticon = isidenticon
result.isAdmin = isAdmin
result.joined = joined
proc `$`*(self: Item): string =
result = fmt"""User Item(
@ -38,6 +44,8 @@ proc `$`*(self: Item): string =
onlineStatus: {$self.onlineStatus.int},
icon: {self.icon},
isIdenticon: {$self.isIdenticon}
isAdmin: {$self.isAdmin}
joined: {$self.joined}
]"""
proc id*(self: Item): string {.inline.} =
@ -65,4 +73,16 @@ proc isIdenticon*(self: Item): bool {.inline.} =
self.isIdenticon
proc `isIdenticon=`*(self: Item, value: bool) {.inline.} =
self.isIdenticon = value
self.isIdenticon = value
proc isAdmin*(self: Item): bool {.inline.} =
self.isAdmin
proc `isAdmin=`*(self: Item, value: bool) {.inline.} =
self.isAdmin = value
proc joined*(self: Item): bool {.inline.} =
self.joined
proc `joined=`*(self: Item, value: bool) {.inline.} =
self.joined = value

View File

@ -9,6 +9,8 @@ type
OnlineStatus
Icon
IsIdenticon
IsAdmin
Joined
QtObject:
type
@ -55,6 +57,8 @@ QtObject:
ModelRole.OnlineStatus.int:"onlineStatus",
ModelRole.Icon.int:"icon",
ModelRole.IsIdenticon.int:"isIdenticon",
ModelRole.IsAdmin.int:"isAdmin",
ModelRole.Joined.int:"joined",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -78,6 +82,10 @@ QtObject:
result = newQVariant(item.icon)
of ModelRole.IsIdenticon:
result = newQVariant(item.isIdenticon)
of ModelRole.IsAdmin:
result = newQVariant(item.isAdmin)
of ModelRole.Joined:
result = newQVariant(item.joined)
proc addItem*(self: Model, item: Item) =
# we need to maintain online contact on top, that means
@ -140,7 +148,10 @@ QtObject:
let index = self.createIndex(ind, 0, nil)
self.dataChanged(index, index, @[ModelRole.Icon.int, ModelRole.IsIdenticon.int])
proc updateItem*(self: Model, id: string, name: string, icon: string, isIdenticon: bool) =
proc updateItem*(
self: Model, id: string, name: string, icon: string, isIdenticon: bool,
isAdmin: bool = false, joined: bool = false
) =
let ind = self.findIndexForMessageId(id)
if(ind == -1):
return
@ -148,9 +159,13 @@ QtObject:
self.items[ind].name = name
self.items[ind].icon = icon
self.items[ind].isIdenticon = isIdenticon
self.items[ind].isAdmin = isAdmin
self.items[ind].joined = joined
let index = self.createIndex(ind, 0, nil)
self.dataChanged(index, index, @[ModelRole.Name.int, ModelRole.Icon.int, ModelRole.IsIdenticon.int])
self.dataChanged(index, index, @[
ModelRole.Name.int, ModelRole.Icon.int, ModelRole.IsIdenticon.int, ModelRole.IsAdmin.int, ModelRole.Joined.int,
])
proc setOnlineStatus*(self: Model, id: string, onlineStatus: OnlineStatus) =
let ind = self.findIndexForMessageId(id)

View File

@ -112,4 +112,7 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
var membersObj: JsonNode
if(jsonObj.getProp("members", membersObj) and membersObj.kind == JArray):
for memberObj in membersObj:
result.members.add(toChatMember(memberObj))
result.members.add(toChatMember(memberObj))
proc isPublicChat*(chatDto: ChatDto): bool =
return chatDto.chatType == ChatType.Public

View File

@ -56,6 +56,12 @@ type
ChatMemberRemovedArgs* = ref object of Args
chatId*: string
id*: string
ChatMemberUpdatedArgs* = ref object of Args
chatId*: string
id*: string
admin*: bool
joined*: bool
# Signals which may be emitted by this service:
@ -70,6 +76,7 @@ const SIGNAL_CHAT_HISTORY_CLEARED* = "chatHistoryCleared"
const SIGNAL_CHAT_RENAMED* = "chatRenamed"
const SIGNAL_CHAT_MEMBERS_ADDED* = "chatMemberAdded"
const SIGNAL_CHAT_MEMBER_REMOVED* = "chatMemberRemoved"
const SIGNAL_CHAT_MEMBER_UPDATED* = "chatMemberUpdated"
QtObject:
type Service* = ref object of QObject
@ -405,7 +412,14 @@ QtObject:
method makeAdmin*(self: Service, chatId: string, pubKey: string) =
try:
let response = status_chat.makeAdmin(chatId, pubKey)
self.emitUpdate(response)
for member in self.chats[chatId].members.mitems:
if (member.id == pubKey):
member.admin = true
self.events.emit(
SIGNAL_CHAT_MEMBER_UPDATED,
ChatMemberUpdatedArgs(id: member.id, admin: member.admin, chatId: chatId, joined: member.joined)
)
break
except Exception as e:
error "error while making user admin: ", msg = e.msg