feat(@desktop/chat): Add setting image in group chat

Image and cropping information are sent to status-go.

Issue #6466
This commit is contained in:
Michal Iskierko 2022-08-11 12:58:09 +02:00 committed by Michał Iskierko
parent a01e0822b7
commit d6a061a517
21 changed files with 80 additions and 26 deletions

View File

@ -86,6 +86,9 @@ method getChatType*(self: AccessInterface): int {.base.} =
method getChatColor*(self: AccessInterface): string {.base.} = method getChatColor*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getChatIcon*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method amIChatAdmin*(self: AccessInterface): bool {.base.} = method amIChatAdmin*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -379,6 +379,10 @@ method getChatColor*(self: Module): string =
let chatDto = self.controller.getChatDetails() let chatDto = self.controller.getChatDetails()
return chatDto.color return chatDto.color
method getChatIcon*(self: Module): string =
let chatDto = self.controller.getChatDetails()
return chatDto.icon
method amIChatAdmin*(self: Module): bool = method amIChatAdmin*(self: Module): bool =
if(not self.controller.belongsToCommunity()): if(not self.controller.belongsToCommunity()):
let chatDto = self.controller.getChatDetails() let chatDto = self.controller.getChatDetails()

View File

@ -68,6 +68,9 @@ QtObject:
proc getChatColor*(self: View): string {.slot.} = proc getChatColor*(self: View): string {.slot.} =
return self.delegate.getChatColor() return self.delegate.getChatColor()
proc getChatIcon*(self: View): string {.slot.} =
return self.delegate.getChatIcon()
proc amIChatAdmin*(self: View): bool {.slot.} = proc amIChatAdmin*(self: View): bool {.slot.} =
return self.delegate.amIChatAdmin() return self.delegate.amIChatAdmin()

View File

@ -338,7 +338,7 @@ method onNotificationsUpdated*(self: Module, hasUnreadMessages: bool, notificati
self.view.updateChatDetailsNotifications(hasUnreadMessages, notificationCount) self.view.updateChatDetailsNotifications(hasUnreadMessages, notificationCount)
method onChatEdited*(self: Module, chatDto: ChatDto) = method onChatEdited*(self: Module, chatDto: ChatDto) =
self.view.updateChatDetails(chatDto.name, chatDto.description, chatDto.emoji, chatDto.color, chatDto.chatType == ChatType.OneToOne) self.view.updateChatDetails(chatDto.name, chatDto.description, chatDto.emoji, chatDto.color, chatDto.icon, chatDto.chatType == ChatType.OneToOne)
self.messagesModule.updateChatIdentifier() self.messagesModule.updateChatIdentifier()
method onChatRenamed*(self: Module, newName: string) = method onChatRenamed*(self: Module, newName: string) =

View File

@ -122,12 +122,13 @@ QtObject:
proc amIChatAdmin*(self: View): bool {.slot.} = proc amIChatAdmin*(self: View): bool {.slot.} =
return self.delegate.amIChatAdmin() return self.delegate.amIChatAdmin()
proc updateChatDetails*(self: View, name, description, emoji, color: string, ignoreName: bool) = proc updateChatDetails*(self: View, name, description, emoji, color, icon: string, ignoreName: bool) =
if not ignoreName: if not ignoreName:
self.chatDetails.setName(name) self.chatDetails.setName(name)
self.chatDetails.setDescription(description) self.chatDetails.setDescription(description)
self.chatDetails.setEmoji(emoji) self.chatDetails.setEmoji(emoji)
self.chatDetails.setColor(color) self.chatDetails.setColor(color)
self.chatDetails.setIcon(icon)
self.chatDetailsChanged() self.chatDetailsChanged()
proc updateChatDetailsName*(self: View, name: string) = proc updateChatDetailsName*(self: View, name: string) =

View File

@ -345,9 +345,9 @@ proc renameGroupChat*(self: Controller, chatId: string, newName: string) =
let communityId = if self.isCommunitySection: self.sectionId else: "" let communityId = if self.isCommunitySection: self.sectionId else: ""
self.chatService.renameGroupChat(communityId, chatId, newName) self.chatService.renameGroupChat(communityId, chatId, newName)
proc updateGroupChatDetails*(self: Controller, chatId: string, newGroupName: string, newGroupColor: string, newGroupImage: string) = proc updateGroupChatDetails*(self: Controller, chatId: string, newGroupName: string, newGroupColor: string, newGroupImageJson: string) =
let communityId = if self.isCommunitySection: self.sectionId else: "" let communityId = if self.isCommunitySection: self.sectionId else: ""
self.chatService.updateGroupChatDetails(communityId, chatId, newGroupName, newGroupColor, newGroupImage) self.chatService.updateGroupChatDetails(communityId, chatId, newGroupName, newGroupColor, newGroupImageJson)
proc makeAdmin*(self: Controller, communityID: string, chatId: string, pubKey: string) = proc makeAdmin*(self: Controller, communityID: string, chatId: string, pubKey: string) =
self.chatService.makeAdmin(communityID, chatId, pubKey) self.chatService.makeAdmin(communityID, chatId, pubKey)

View File

@ -115,7 +115,7 @@ method onCommunityChannelDeletedOrChatLeft*(self: AccessInterface, chatId: strin
method onChatRenamed*(self: AccessInterface, chatId: string, newName: string) {.base.} = method onChatRenamed*(self: AccessInterface, chatId: string, newName: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method onGroupChatDetailsUpdated*(self: AccessInterface, chatId: string, newName: string, newColor: string, newImage: string) {.base.} = method onGroupChatDetailsUpdated*(self: AccessInterface, chatId: string, newName: string, newColor: string, newImageJson: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method onCommunityChannelEdited*(self: AccessInterface, chat: ChatDto) {.base.} = method onCommunityChannelEdited*(self: AccessInterface, chat: ChatDto) {.base.} =

View File

@ -146,6 +146,8 @@ proc buildChatSectionUI(
blocked = contactDetails.details.isBlocked() blocked = contactDetails.details.isBlocked()
colorHash = self.controller.getColorHash(chatDto.id) colorHash = self.controller.getColorHash(chatDto.id)
colorId = self.controller.getColorId(chatDto.id) colorId = self.controller.getColorId(chatDto.id)
elif(chatDto.chatType == ChatType.PrivateGroupChat):
chatImage = chatDto.icon
# for group chats only member.admin should be checked, # for group chats only member.admin should be checked,
# because channelGroup.admin is alway true # because channelGroup.admin is alway true
@ -726,8 +728,8 @@ method removeMembersFromGroupChat*(self: Module, communityID: string, chatId: st
method renameGroupChat*(self: Module, chatId: string, newName: string) = method renameGroupChat*(self: Module, chatId: string, newName: string) =
self.controller.renameGroupChat(chatId, newName) self.controller.renameGroupChat(chatId, newName)
method updateGroupChatDetails*(self: Module, chatId: string, newGroupName: string, newGroupColor: string, newGroupImage: string) = method updateGroupChatDetails*(self: Module, chatId: string, newGroupName: string, newGroupColor: string, newGroupImageJson: string) =
self.controller.updateGroupChatDetails(chatId, newGroupName, newGroupColor, newGroupImage) self.controller.updateGroupChatDetails(chatId, newGroupName, newGroupColor, newGroupImageJson)
method makeAdmin*(self: Module, communityID: string, chatId: string, pubKey: string) = method makeAdmin*(self: Module, communityID: string, chatId: string, pubKey: string) =
self.controller.makeAdmin(communityID, chatId, pubKey) self.controller.makeAdmin(communityID, chatId, pubKey)

View File

@ -207,7 +207,6 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
discard jsonObj.getProp("unviewedMentionsCount", result.unviewedMentionsCount) discard jsonObj.getProp("unviewedMentionsCount", result.unviewedMentionsCount)
discard jsonObj.getProp("canPost", result.canPost) discard jsonObj.getProp("canPost", result.canPost)
discard jsonObj.getProp("alias", result.alias) discard jsonObj.getProp("alias", result.alias)
discard jsonObj.getProp("identicon", result.icon)
discard jsonObj.getProp("muted", result.muted) discard jsonObj.getProp("muted", result.muted)
discard jsonObj.getProp("categoryId", result.categoryId) discard jsonObj.getProp("categoryId", result.categoryId)
if (result.categoryId == ""): if (result.categoryId == ""):
@ -231,6 +230,13 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
(chatTypeInt >= ord(low(ChatType)) or chatTypeInt <= ord(high(ChatType)))): (chatTypeInt >= ord(low(ChatType)) or chatTypeInt <= ord(high(ChatType)))):
result.chatType = ChatType(chatTypeInt) result.chatType = ChatType(chatTypeInt)
var chatImage: string
discard jsonObj.getProp("image", chatImage)
if (result.chatType == ChatType.PrivateGroupChat and len(chatImage) > 0):
result.icon = chatImage
else:
discard jsonObj.getProp("identicon", result.icon)
var membersObj: JsonNode var membersObj: JsonNode
if(jsonObj.getProp("members", membersObj)): if(jsonObj.getProp("members", membersObj)):
if(membersObj.kind == JArray): if(membersObj.kind == JArray):

View File

@ -509,21 +509,23 @@ QtObject:
except Exception as e: except Exception as e:
error "error while renaming group chat: ", msg = e.msg error "error while renaming group chat: ", msg = e.msg
proc updateGroupChatDetails*(self: Service, communityID: string, chatID: string, name: string, color: string, image: string) = proc updateGroupChatDetails*(self: Service, communityID: string, chatID: string, name: string, color: string, imageJson: string) =
try: try:
let response = status_chat.editChat(communityID, chatID, name, color, image) let response = status_chat.editChat(communityID, chatID, name, color, imageJson)
if (not response.error.isNil): if (not response.error.isNil):
let msg = response.error.message & " chatId=" & chatId let msg = response.error.message & " chatId=" & chatId
error "error while editing group chat details", msg error "error while editing group chat details", msg
return return
let resultedChat = response.result.toChatDto()
var chat = self.chats[chatID] var chat = self.chats[chatID]
chat.name = name chat.name = name
chat.color = color chat.color = color
# TODO set image chat.icon = resultedChat.icon
self.updateOrAddChat(chat) self.updateOrAddChat(chat)
self.events.emit(SIGNAL_GROUP_CHAT_DETAILS_UPDATED, ChatUpdateDetailsArgs(id: chatID, newName: name, newColor: color, newImage: image)) self.events.emit(SIGNAL_GROUP_CHAT_DETAILS_UPDATED, ChatUpdateDetailsArgs(id: chatID, newName: name, newColor: color, newImage: resultedChat.icon))
except Exception as e: except Exception as e:
error "error while updating group chat: ", msg = e.msg error "error while updating group chat: ", msg = e.msg

View File

@ -1,6 +1,7 @@
import json, sequtils, sugar, strutils import json, sequtils, sugar, strutils
import core, utils import core, utils
import response_type import response_type
import interpret/cropped_image
export response_type export response_type
@ -134,6 +135,7 @@ proc getLinkPreviewData*(link: string): RpcResponse[JsonNode] {.raises: [Excepti
proc getMembers*(communityId, chatId: string): RpcResponse[JsonNode] {.raises: [Exception].} = proc getMembers*(communityId, chatId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("chat_getMembers", %* [communityId, chatId]) result = callPrivateRPC("chat_getMembers", %* [communityId, chatId])
proc editChat*(communityID: string, chatID: string, name: string, color: string, image: string): RpcResponse[JsonNode] {.raises: [Exception].} = proc editChat*(communityID: string, chatID: string, name: string, color: string, imageJson: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [communityID, chatID, name, color, image] let croppedImage = newCroppedImage(imageJson)
let payload = %* [communityID, chatID, name, color, croppedImage]
return core.callPrivateRPC("chat_editChat", payload) return core.callPrivateRPC("chat_editChat", payload)

View File

@ -66,11 +66,19 @@ StatusModal {
} }
} }
header.editable: !addMembers && popup.isAdmin header.editable: !addMembers && popup.isAdmin
header.icon.isLetterIdenticon: true header.icon.isLetterIdenticon: {
if (popup.chatDetails && popup.chatDetails.icon !== "") {
return false
}
return true
}
header.icon.name: popup.chatDetails ? popup.chatDetails.name : "" header.icon.name: popup.chatDetails ? popup.chatDetails.name : ""
header.icon.background.color: popup.chatDetails ? popup.chatDetails.color : "transparent" header.icon.background.color: popup.chatDetails ? popup.chatDetails.color : "transparent"
header.image.source: popup.chatDetails ? popup.chatDetails.icon : ""
onEditButtonClicked: renameGroupPopup.open() onEditButtonClicked: {
renameGroupPopup.open()
}
onClosed: { onClosed: {
chatSectionModule.clearMyContacts() chatSectionModule.clearMyContacts()
@ -284,6 +292,7 @@ StatusModal {
id: renameGroupPopup id: renameGroupPopup
activeGroupName: popup.chatDetails ? popup.chatDetails.name : "" activeGroupName: popup.chatDetails ? popup.chatDetails.name : ""
activeGroupColor: popup.chatDetails ? popup.chatDetails.color: "" activeGroupColor: popup.chatDetails ? popup.chatDetails.color: ""
activeGroupImageData: popup.chatDetails ? popup.chatDetails.icon: ""
onUpdateGroupChatDetails: { onUpdateGroupChatDetails: {
popup.chatSectionModule.updateGroupChatDetails(popup.chatSectionModule.activeItem.id, groupName, groupColor, groupImage) popup.chatSectionModule.updateGroupChatDetails(popup.chatSectionModule.activeItem.id, groupName, groupColor, groupImage)
popup.header.title = groupName popup.header.title = groupName

View File

@ -43,9 +43,7 @@ StatusDialog {
colorSelectionGrid.selectedColorIndex = i colorSelectionGrid.selectedColorIndex = i
} }
// TODO next phase imageEditor.dataImage = activeGroupImageData
// imageEditor.dataImage: root.activeGroupImageData
} }
ColumnLayout { ColumnLayout {
@ -142,9 +140,12 @@ StatusDialog {
id: saveBtn id: saveBtn
text: qsTr("Save changes") text: qsTr("Save changes")
enabled: groupName.text.trim().length > 0 && enabled: groupName.text.trim().length > 0 &&
((groupName.text != root.activeGroupName) || (root.activeGroupColor != colorSelectionGrid.selectedColor)) ((groupName.text != root.activeGroupName) ||
(root.activeGroupColor != colorSelectionGrid.selectedColor) ||
(String(imageEditor.source).length > 0))
onClicked : { onClicked : {
updateGroupChatDetails(groupName.text, colorSelectionGrid.selectedColor, ""/*imageEditor.dataImage*/) updateGroupChatDetails(groupName.text, colorSelectionGrid.selectedColor,
Utils.getImageAndCropInfoJson(imageEditor.source, imageEditor.cropRect))
} }
} }
} }

View File

@ -93,6 +93,13 @@ QtObject {
return messageModule.getChatColor() return messageModule.getChatColor()
} }
function getChatIcon () {
if(!messageModule)
return ""
return messageModule.getChatIcon()
}
function amIChatAdmin () { function amIChatAdmin () {
if(!messageModule) if(!messageModule)
return false return false

View File

@ -209,6 +209,7 @@ ColumnLayout {
chatDescription = chatContentModule.chatDetails.description chatDescription = chatContentModule.chatDetails.description
chatEmoji = chatContentModule.chatDetails.emoji chatEmoji = chatContentModule.chatDetails.emoji
chatColor = chatContentModule.chatDetails.color chatColor = chatContentModule.chatDetails.color
chatIcon = chatContentModule.chatDetails.icon
chatType = chatContentModule.chatDetails.type chatType = chatContentModule.chatDetails.type
chatMuted = chatContentModule.chatDetails.muted chatMuted = chatContentModule.chatDetails.muted
channelPosition = chatContentModule.chatDetails.position channelPosition = chatContentModule.chatDetails.position

View File

@ -92,7 +92,8 @@ StatusPopupMenu {
onTriggered: { onTriggered: {
Global.openPopup(renameGroupPopupComponent, { Global.openPopup(renameGroupPopupComponent, {
activeGroupName: root.chatName, activeGroupName: root.chatName,
activeGroupColor: root.chatColor activeGroupColor: root.chatColor,
activeGroupImageData: root.chatIcon
}); });
} }
} }

View File

@ -313,7 +313,7 @@ Item {
chatId = obj.itemId chatId = obj.itemId
chatName = obj.name chatName = obj.name
chatDescription = obj.description chatDescription = obj.description
chatIcon = obj.icon
chatEmoji = obj.emoji chatEmoji = obj.emoji
chatColor = obj.color chatColor = obj.color
chatType = obj.type chatType = obj.type

View File

@ -156,8 +156,8 @@ StatusAppTwoPanelLayout {
item.options.requestToJoinEnabled ? Constants.communityChatOnRequestAccess : Constants.communityChatPublicAccess, item.options.requestToJoinEnabled ? Constants.communityChatOnRequestAccess : Constants.communityChatPublicAccess,
item.color.toString().toUpperCase(), item.color.toString().toUpperCase(),
item.selectedTags, item.selectedTags,
JSON.stringify({imagePath: String(item.logoImagePath).replace("file://", ""), cropRect: item.logoCropRect}), Utils.getImageAndCropInfoJson(item.logoImagePath, item.logoCropRect),
JSON.stringify({imagePath: String(item.bannerPath).replace("file://", ""), cropRect: item.bannerCropRect}), Utils.getImageAndCropInfoJson(item.bannerPath, item.bannerCropRect),
item.options.archiveSupportEnabled, item.options.archiveSupportEnabled,
item.options.pinMessagesEnabled item.options.pinMessagesEnabled
) )

View File

@ -184,6 +184,7 @@ Item {
chatDescription = obj.description chatDescription = obj.description
chatEmoji = obj.emoji chatEmoji = obj.emoji
chatColor = obj.color chatColor = obj.color
chatIcon = obj.icon
chatType = obj.type chatType = obj.type
chatMuted = obj.muted chatMuted = obj.muted
} }

View File

@ -298,7 +298,13 @@ Loader {
chatColor: root.messageStore.getChatColor() chatColor: root.messageStore.getChatColor()
chatEmoji: root.channelEmoji chatEmoji: root.channelEmoji
amIChatAdmin: root.messageStore.amIChatAdmin() amIChatAdmin: root.messageStore.amIChatAdmin()
chatIcon: root.senderIconToShow chatIcon: {
if ((root.messageStore.getChatType() === Constants.chatType.privateGroupChat) &&
root.messageStore.getChatIcon() !== "") {
return root.messageStore.getChatIcon()
}
return root.senderIconToShow
}
} }
} }

View File

@ -697,6 +697,11 @@ QtObject {
return msg.includes("account already exists") return msg.includes("account already exists")
} }
// See also: backend/interpret/cropped_image.nim
function getImageAndCropInfoJson(imgPath, cropRect) {
return JSON.stringify({imagePath: String(imgPath).replace("file://", ""), cropRect: cropRect})
}
// Leave this function at the bottom of the file as QT Creator messes up the code color after this // Leave this function at the bottom of the file as QT Creator messes up the code color after this
function isPunct(c) { function isPunct(c) {
return /(!|\@|#|\$|%|\^|&|\*|\(|\)|_|\+|\||-|=|\\|{|}|[|]|"|;|'|<|>|\?|,|\.|\/)/.test(c) return /(!|\@|#|\$|%|\^|&|\*|\(|\)|_|\+|\||-|=|\\|{|}|[|]|"|;|'|<|>|\?|,|\.|\/)/.test(c)