diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index 458e74db38..c5dbdf1ab8 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -15,6 +15,8 @@ import web3/[conversions, ethtypes] import ../../status/threads import views/[channels_list, message_list, chat_item, suggestions_list, reactions, stickers, groups, transactions] import json_serialization +import ../../status/libstatus/utils +import ../utils/image_utils logScope: topics = "chats-view" @@ -149,10 +151,7 @@ QtObject: proc sendImage*(self: ChatsView, imagePath: string): string {.slot.} = result = "" try: - var image: string = replace(imagePath, "file://", "") - if defined(windows): - # Windows doesn't work with paths starting with a slash - image.removePrefix('/') + var image = image_utils.formatImagePath(imagePath) let tmpImagePath = image_resizer(image, 2000, TMPDIR) self.status.chat.sendImage(self.activeChannel.id, tmpImagePath) removeFile(tmpImagePath) diff --git a/src/app/login/view.nim b/src/app/login/view.nim index 5891fa7ff7..c4b9003f73 100644 --- a/src/app/login/view.nim +++ b/src/app/login/view.nim @@ -1,4 +1,4 @@ -import NimQml, Tables, json, nimcrypto, strformat, json_serialization +import NimQml, Tables, json, nimcrypto, strformat, json_serialization, chronicles import ../../status/signals/types import ../../status/libstatus/types as status_types import ../../status/libstatus/accounts as status_accounts @@ -9,9 +9,11 @@ import core type AccountRoles {.pure.} = enum - Username = UserRole + 1, - Identicon = UserRole + 2, + Username = UserRole + 1 + Identicon = UserRole + 2 Address = UserRole + 3 + ThumbnailImage = UserRole + 4 + LargeImage = UserRole + 5 QtObject: type LoginView* = ref object of QAbstractListModel @@ -41,7 +43,12 @@ QtObject: proc setCurrentAccount*(self: LoginView, selectedAccountIdx: int) {.slot.} = let currNodeAcct = self.accounts[selectedAccountIdx] - self.currentAccount.setAccount(GeneratedAccount(name: currNodeAcct.name, photoPath: currNodeAcct.photoPath, address: currNodeAcct.keyUid)) + self.currentAccount.setAccount(GeneratedAccount( + name: currNodeAcct.name, + identicon: currNodeAcct.identicon, + address: currNodeAcct.keyUid, + identityImage: currNodeAcct.identityImage + )) QtProperty[QVariant] currentAccount: read = getCurrentAccount @@ -72,13 +79,25 @@ QtObject: let assetRole = role.AccountRoles case assetRole: of AccountRoles.Username: result = newQVariant(asset.name) - of AccountRoles.Identicon: result = newQVariant(asset.photoPath) + of AccountRoles.Identicon: result = newQVariant(asset.identicon) of AccountRoles.Address: result = newQVariant(asset.keyUid) + of AccountRoles.ThumbnailImage: + if (not asset.identityImage.isNil): + result = newQVariant(asset.identityImage.thumbnail) + else: + result = newQVariant(asset.identicon) + of AccountRoles.LargeImage: + if (not asset.identityImage.isNil): + result = newQVariant(asset.identityImage.large) + else: + result = newQVariant(asset.identicon) method roleNames(self: LoginView): Table[int, string] = { AccountRoles.Username.int:"username", AccountRoles.Identicon.int:"identicon", - AccountRoles.Address.int:"address" }.toTable + AccountRoles.Address.int:"address", + AccountRoles.ThumbnailImage.int:"thumbnailImage", + AccountRoles.LargeImage.int:"largeImage" }.toTable proc login(self: LoginView, password: string): string {.slot.} = var currentAccountId = 0 diff --git a/src/app/onboarding/view.nim b/src/app/onboarding/view.nim index 4273c7c077..926358c460 100644 --- a/src/app/onboarding/view.nim +++ b/src/app/onboarding/view.nim @@ -57,7 +57,7 @@ QtObject: let assetRole = role.AccountRoles case assetRole: of AccountRoles.Username: result = newQVariant(asset.name) - of AccountRoles.Identicon: result = newQVariant(asset.photoPath) + of AccountRoles.Identicon: result = newQVariant(asset.identicon) of AccountRoles.Address: result = newQVariant(asset.keyUid) method roleNames(self: OnboardingView): Table[int, string] = diff --git a/src/app/onboarding/views/account_info.nim b/src/app/onboarding/views/account_info.nim index a9d555dacb..d773197e17 100644 --- a/src/app/onboarding/views/account_info.nim +++ b/src/app/onboarding/views/account_info.nim @@ -28,11 +28,29 @@ QtObject: read = username notify = accountChanged - proc identicon*(self: AccountInfoView): string {.slot.} = result = ?.self.account.photoPath + proc identicon*(self: AccountInfoView): string {.slot.} = result = ?.self.account.identicon QtProperty[string] identicon: read = identicon notify = accountChanged + proc thumbnailImage*(self: AccountInfoView): string {.slot.} = + if (not self.account.identityImage.isNil): + result = self.account.identityImage.thumbnail + else: + result = ?.self.account.identicon + QtProperty[string] thumbnailImage: + read = thumbnailImage + notify = identityImageChanged + + proc largeImage*(self: AccountInfoView): string {.slot.} = + if (not self.account.identityImage.isNil): + result = self.account.identityImage.large + else: + result = ?.self.account.identicon + QtProperty[string] largeImage: + read = largeImage + notify = identityImageChanged + proc address*(self: AccountInfoView): string {.slot.} = result = ?.self.account.address QtProperty[string] address: read = address diff --git a/src/app/profile/core.nim b/src/app/profile/core.nim index 80186dbeb9..168547a8ad 100644 --- a/src/app/profile/core.nim +++ b/src/app/profile/core.nim @@ -43,6 +43,11 @@ proc init*(self: ProfileController, account: Account) = profile.id = pubKey profile.address = account.keyUid + let identityImage = self.status.profile.getIdentityImage(profile.address) + + if (identityImage.thumbnail != ""): + profile.identityImage = identityImage + self.view.devices.addDevices(status_devices.getAllDevices()) self.view.devices.setDeviceSetup(status_devices.isDeviceSetup()) self.view.setNewProfile(profile) diff --git a/src/app/profile/view.nim b/src/app/profile/view.nim index 7d8df69733..a76c6604a3 100644 --- a/src/app/profile/view.nim +++ b/src/app/profile/view.nim @@ -1,4 +1,4 @@ -import NimQml, sequtils, strutils, sugar, os, json +import NimQml, sequtils, strutils, sugar, os, json, chronicles import views/[mailservers_list, ens_manager, contacts, devices, mailservers, mnemonic, network, fleets, profile_info, device_list, dapp_list] import ../chat/views/channels_list import ../../status/profile/profile @@ -13,6 +13,7 @@ import ../../status/threads import ../../status/libstatus/types import ../../status/libstatus/accounts/constants as accountConstants import qrcode/qrcode +import ../utils/image_utils QtObject: type ProfileView* = ref object of QObject @@ -209,3 +210,24 @@ QtObject: QtProperty[QVariant] network: read = getNetwork + + proc uploadNewProfilePic*(self: ProfileView, imageUrl: string, aX: int, aY: int, bX: int, bY: int): string {.slot.} = + var image = image_utils.formatImagePath(imageUrl) + # FIXME the function to get the file size is messed up + # var size = image_getFileSize(image) + # TODO find a way to i18n this (maybe send just a code and then QML sets the right string) + # return "Max file size is 20MB" + + try: + # TODO add crop tool for the image + let identityImage = self.status.profile.storeIdentityImage(self.profile.address, image, aX, aY, bX, bY) + self.profile.setIdentityImage(identityImage) + result = "" + except Exception as e: + error "Error storing identity image", msg=e.msg + result = "Error storing identity image: " & e.msg + + proc deleteProfilePic*(self: ProfileView): string {.slot.} = + result = self.status.profile.deleteIdentityImage(self.profile.address) + if (result == ""): + self.profile.removeIdentityImage() diff --git a/src/app/profile/views/contact_list.nim b/src/app/profile/views/contact_list.nim index 772c432e33..e23f69b5a3 100644 --- a/src/app/profile/views/contact_list.nim +++ b/src/app/profile/views/contact_list.nim @@ -1,4 +1,4 @@ -import NimQml +import NimQml, chronicles import Tables import ../../../status/profile/profile from ../../../status/ens import nil @@ -14,6 +14,8 @@ type Alias = UserRole + 7 EnsVerified = UserRole + 8 LocalNickname = UserRole + 9 + ThumbnailImage = UserRole + 10 + LargeImage = UserRole + 11 QtObject: type ContactList* = ref object of QAbstractListModel @@ -42,6 +44,14 @@ QtObject: return ens.userNameOrAlias(contact) return defaultValue + proc getContactIndexByPubkey(self: ContactList, pubkey: string): int {.slot.} = + var i = 0 + for contact in self.contacts: + if (contact.id == pubkey): + return i + i = i + 1 + return -1 + proc rowData(self: ContactList, index: int, column: string): string {.slot.} = let contact = self.contacts[index] case column: @@ -54,6 +64,8 @@ QtObject: of "alias": result = contact.alias of "ensVerified": result = $contact.ensVerified of "localNickname": result = $contact.localNickname + of "thumbnailImage": result = $contact.identityImage.thumbnail + of "largeImage": result = $contact.identityImage.large method data(self: ContactList, index: QModelIndex, role: int): QVariant = if not index.isValid: @@ -71,6 +83,8 @@ QtObject: of ContactRoles.Alias: result = newQVariant(contact.alias) of ContactRoles.EnsVerified: result = newQVariant(contact.ensVerified) of ContactRoles.LocalNickname: result = newQVariant(contact.localNickname) + of ContactRoles.ThumbnailImage: result = newQVariant(contact.identityImage.thumbnail) + of ContactRoles.LargeImage: result = newQVariant(contact.identityImage.large) method roleNames(self: ContactList): Table[int, string] = { @@ -82,7 +96,9 @@ QtObject: ContactRoles.IsBlocked.int:"isBlocked", ContactRoles.Alias.int:"alias", ContactRoles.LocalNickname.int:"localNickname", - ContactRoles.EnsVerified.int:"ensVerified" + ContactRoles.EnsVerified.int:"ensVerified", + ContactRoles.ThumbnailImage.int:"thumbnailImage", + ContactRoles.LargeImage.int:"largeImage" }.toTable proc addContactToList*(self: ContactList, contact: Profile) = @@ -95,6 +111,8 @@ QtObject: if(c.isContact()): return true return false + proc contactChanged*(self: ContactList, pubkey: string) {.signal.} + proc updateContact*(self: ContactList, contact: Profile) = var found = false let topLeft = self.createIndex(0, 0, nil) @@ -104,11 +122,13 @@ QtObject: found = true c.ensName = contact.ensName c.ensVerified = contact.ensVerified + c.identityImage = contact.identityImage if not found: self.addContactToList(contact) else: self.dataChanged(topLeft, bottomRight, @[ContactRoles.Name.int]) + self.contactChanged(contact.id) proc setNewData*(self: ContactList, contactList: seq[Profile]) = self.beginResetModel() diff --git a/src/app/profile/views/profile_info.nim b/src/app/profile/views/profile_info.nim index add9f1c74e..c4d6d49654 100644 --- a/src/app/profile/views/profile_info.nim +++ b/src/app/profile/views/profile_info.nim @@ -1,12 +1,15 @@ import NimQml import chronicles import ../../../status/profile/profile +import ../../../status/libstatus/types +import std/wrapnils QtObject: type ProfileInfoView* = ref object of QObject username*: string identicon*: string address*: string + identityImage*: IdentityImage pubKey*: string appearance*: int ensVerified*: bool @@ -24,11 +27,14 @@ QtObject: result.username = "" result.identicon = "" result.appearance = 0 + result.identityImage = IdentityImage() result.ensVerified = false result.setup proc profileChanged*(self: ProfileInfoView) {.signal.} + proc identityImageChanged*(self: ProfileInfoView) {.signal.} + proc setProfile*(self: ProfileInfoView, profile: Profile) = self.username = profile.username self.identicon = profile.identicon @@ -36,8 +42,17 @@ QtObject: self.pubKey = profile.id self.address = profile.address self.ensVerified = profile.ensVerified + self.identityImage = profile.identityImage self.profileChanged() + proc setIdentityImage*(self: ProfileInfoView, identityImage: IdentityImage) = + self.identityImage = identityImage + self.identityImageChanged() + + proc removeIdentityImage*(self: ProfileInfoView) = + self.identityImage = IdentityImage() + self.identityImageChanged() + proc username*(self: ProfileInfoView): string {.slot.} = result = self.username QtProperty[string] username: read = username @@ -59,6 +74,30 @@ QtObject: read = identicon notify = profileChanged + proc thumbnailImage*(self: ProfileInfoView): string {.slot.} = + if (?.self.identityImage.thumbnail != ""): + result = self.identityImage.thumbnail + else: + result = self.identicon + QtProperty[string] thumbnailImage: + read = thumbnailImage + notify = identityImageChanged + + proc largeImage*(self: ProfileInfoView): string {.slot.} = + if (?.self.identityImage.large != ""): + result = self.identityImage.large + else: + result = self.identicon + QtProperty[string] largeImage: + read = largeImage + notify = identityImageChanged + + proc hasIdentityImage*(self: ProfileInfoView): bool {.slot.} = + result = (?.self.identityImage.thumbnail != "") + QtProperty[bool] hasIdentityImage: + read = hasIdentityImage + notify = identityImageChanged + proc pubKey*(self: ProfileInfoView): string {.slot.} = self.pubKey QtProperty[string] pubKey: diff --git a/src/app/utils/image_utils.nim b/src/app/utils/image_utils.nim new file mode 100644 index 0000000000..1e794b64fa --- /dev/null +++ b/src/app/utils/image_utils.nim @@ -0,0 +1,8 @@ +import strutils, os + +proc formatImagePath*(imagePath: string): string = + var image: string = replace(imagePath, "file://", "") + if defined(windows): + # Windows doesn't work with paths starting with a slash + image.removePrefix('/') + return image \ No newline at end of file diff --git a/src/status/accounts.nim b/src/status/accounts.nim index 500e5303c8..85afe313ab 100644 --- a/src/status/accounts.nim +++ b/src/status/accounts.nim @@ -19,7 +19,7 @@ proc generateAddresses*(self: AccountModel): seq[GeneratedAccount] = var accounts = status_accounts.generateAddresses() for account in accounts.mitems: account.name = status_accounts.generateAlias(account.derived.whisper.publicKey) - account.photoPath = status_accounts.generateIdenticon(account.derived.whisper.publicKey) + account.identicon = status_accounts.generateIdenticon(account.derived.whisper.publicKey) self.generatedAddresses.add(account) result = self.generatedAddresses @@ -41,7 +41,7 @@ proc importMnemonic*(self: AccountModel, mnemonic: string): GeneratedAccount = let importedAccount = status_accounts.multiAccountImportMnemonic(mnemonic) importedAccount.derived = status_accounts.deriveAccounts(importedAccount.id) importedAccount.name = status_accounts.generateAlias(importedAccount.derived.whisper.publicKey) - importedAccount.photoPath = status_accounts.generateIdenticon(importedAccount.derived.whisper.publicKey) + importedAccount.identicon = status_accounts.generateIdenticon(importedAccount.derived.whisper.publicKey) result = importedAccount proc reset*(self: AccountModel) = diff --git a/src/status/libstatus/accounts.nim b/src/status/libstatus/accounts.nim index 0551253616..e125e546ba 100644 --- a/src/status/libstatus/accounts.nim +++ b/src/status/libstatus/accounts.nim @@ -67,9 +67,34 @@ proc initNode*() = discard $nim_status.initKeystore(KEYSTOREDIR) +proc parseIdentityImage*(images: JsonNode): IdentityImage = + result = IdentityImage() + if (images.kind != JNull): + for image in images: + if (image["type"].getStr == "thumbnail"): + # TODO check if this can be url or if it's always uri + result.thumbnail = image["uri"].getStr + elif (image["type"].getStr == "large"): + result.large = image["uri"].getStr + proc openAccounts*(): seq[NodeAccount] = - let strNodeAccounts = $nim_status.openAccounts(DATADIR) - result = Json.decode(strNodeAccounts, seq[NodeAccount]) + let strNodeAccounts = nim_status.openAccounts(DATADIR).parseJson + # FIXME fix serialization + result = @[] + if (strNodeAccounts.kind != JNull): + for account in strNodeAccounts: + let nodeAccount = NodeAccount( + name: account["name"].getStr, + timestamp: account["timestamp"].getInt, + keyUid: account["key-uid"].getStr, + identicon: account["identicon"].getStr, + keycardPairing: account["keycard-pairing"].getStr + ) + if (account{"images"}.kind != JNull): + nodeAccount.identityImage = parseIdentityImage(account["images"]) + + result.add(nodeAccount) + proc saveAccountAndLogin*( account: GeneratedAccount, @@ -91,7 +116,7 @@ proc saveAccountAndLogin*( "public-key": account.derived.whisper.publicKey, "address": account.derived.whisper.address, "name": account.name, - "photo-path": account.photoPath, + "identicon": account.identicon, "path": constants.PATH_WHISPER, "chat": true } @@ -127,7 +152,7 @@ proc getAccountData*(account: GeneratedAccount): JsonNode = result = %* { "name": account.name, "address": account.address, - "photo-path": account.photoPath, + "identicon": account.identicon, "key-uid": account.keyUid, "keycard-pairing": nil } @@ -148,7 +173,7 @@ proc getAccountSettings*(account: GeneratedAccount, defaultNetworks: JsonNode, i "latest-derived-path": 0, "networks/networks": defaultNetworks, "currency": "usd", - "photo-path": account.photoPath, + "identicon": account.identicon, "waku-enabled": true, "wallet/visible-tokens": { "mainnet": ["SNT"] @@ -336,3 +361,22 @@ proc deriveAccounts*(accountId: string): MultiAccounts = proc logout*(): StatusGoError = result = Json.decode($nim_status.logout(), StatusGoError) + +proc storeIdentityImage*(keyUID: string, imagePath: string, aX, aY, bX, bY: int): IdentityImage = + let response = callPrivateRPC("multiaccounts_storeIdentityImage", %* [keyUID, imagePath, aX, aY, bX, bY]).parseJson + result = parseIdentityImage(response{"result"}) + +proc getIdentityImage*(keyUID: string): IdentityImage = + try: + let response = callPrivateRPC("multiaccounts_getIdentityImages", %* [keyUID]).parseJson + result = parseIdentityImage(response{"result"}) + except Exception as e: + error "Error getting identity image", msg=e.msg + +proc deleteIdentityImage*(keyUID: string): string = + try: + let response = callPrivateRPC("multiaccounts_deleteIdentityImage", %* [keyUID]).parseJson + result = "" + except Exception as e: + error "Error getting identity image", msg=e.msg + result = e.msg diff --git a/src/status/libstatus/installations.nim b/src/status/libstatus/installations.nim index 6f8159fd9f..b2bc301188 100644 --- a/src/status/libstatus/installations.nim +++ b/src/status/libstatus/installations.nim @@ -15,6 +15,7 @@ proc getOurInstallations*(useCached: bool = true): JsonNode = result = installations proc syncDevices*(preferredName: string): string = + # TODO change this to identicon when status-go is updated let photoPath = "" result = callPrivateRPC("syncDevices".prefix, %* [preferredName, photoPath]) diff --git a/src/status/libstatus/types.nim b/src/status/libstatus/types.nim index e906de6955..ac7049f0f3 100644 --- a/src/status/libstatus/types.nim +++ b/src/status/libstatus/types.nim @@ -42,12 +42,17 @@ type MultiAccounts* = object defaultWallet* {.serializedFieldName(PATH_DEFAULT_WALLET).}: DerivedAccount eip1581* {.serializedFieldName(PATH_EIP_1581).}: DerivedAccount +type + IdentityImage* = ref object + thumbnail*: string + large*: string type Account* = ref object of RootObj name*: string keyUid* {.serializedFieldName("key-uid").}: string - photoPath* {.serializedFieldName("photo-path").}: string + identityImage*: IdentityImage + identicon*: string type NodeAccount* = ref object of Account @@ -66,7 +71,8 @@ type # serializedFieldName pragma would need to be different name*: string keyUid*: string - photoPath*: string + identicon*: string + identityImage*: IdentityImage type RpcError* = ref object code*: int @@ -88,10 +94,10 @@ type error*: RpcError proc toAccount*(account: GeneratedAccount): Account = - result = Account(name: account.name, photoPath: account.photoPath, keyUid: account.address) + result = Account(name: account.name, identityImage: account.identityImage, identicon: account.identicon, keyUid: account.address) proc toAccount*(account: NodeAccount): Account = - result = Account(name: account.name, photoPath: account.photoPath, keyUid: account.keyUid) + result = Account(name: account.name, identityImage: account.identityImage, identicon: account.identicon, keyUid: account.keyUid) type AccountArgs* = ref object of Args account*: Account @@ -247,4 +253,4 @@ proc getNodes*(self: FleetConfig, fleet: Fleet, nodeType: FleetNodes = FleetNode result = toSeq(self.fleet[$fleet][$nodeType].values) proc getMailservers*(self: FleetConfig, fleet: Fleet): Table[string, string] = - result = self.fleet[$fleet][$FleetNodes.Mailservers] \ No newline at end of file + result = self.fleet[$fleet][$FleetNodes.Mailservers] diff --git a/src/status/profile.nim b/src/status/profile.nim index 31873e73dd..0bd0cc8bd0 100644 --- a/src/status/profile.nim +++ b/src/status/profile.nim @@ -17,3 +17,12 @@ proc logout*(self: ProfileModel) = proc getLinkPreviewWhitelist*(self: ProfileModel): JsonNode = result = status_settings.getLinkPreviewWhitelist() + +proc storeIdentityImage*(self: ProfileModel, keyUID: string, imagePath: string, aX, aY, bX, bY: int): IdentityImage = + result = status_accounts.storeIdentityImage(keyUID, imagePath, aX, aY, bX, bY) + +proc getIdentityImage*(self: ProfileModel, keyUID: string): IdentityImage = + result = status_accounts.getIdentityImage(keyUID) + +proc deleteIdentityImage*(self: ProfileModel, keyUID: string): string = + result = status_accounts.deleteIdentityImage(keyUID) diff --git a/src/status/profile/profile.nim b/src/status/profile/profile.nim index deed64eca0..3459ac5c91 100644 --- a/src/status/profile/profile.nim +++ b/src/status/profile/profile.nim @@ -4,6 +4,7 @@ import ../libstatus/types type Profile* = ref object id*, alias*, username*, identicon*, address*, ensName*, localNickname*: string ensVerified*: bool + identityImage*: IdentityImage ensVerifiedAt*, ensVerificationRetries*, appearance*: int systemTags*: seq[string] @@ -17,7 +18,7 @@ proc toProfileModel*(account: Account): Profile = result = Profile( id: "", username: account.name, - identicon: account.photoPath, + identicon: account.identicon, alias: account.name, ensName: "", ensVerified: false, @@ -36,6 +37,7 @@ proc toProfileModel*(profile: JsonNode): Profile = id: profile["id"].str, username: profile["alias"].str, identicon: profile["identicon"].str, + identityImage: IdentityImage(), address: profile["id"].str, alias: profile["alias"].str, ensName: "", @@ -51,3 +53,8 @@ proc toProfileModel*(profile: JsonNode): Profile = if profile.hasKey("localNickname"): result.localNickname = profile["localNickname"].str + if profile.hasKey("images"): + if profile["images"].hasKey("thumbnail"): + result.identityImage.thumbnail = profile["images"]["thumbnail"]["uri"].str + if profile["images"].hasKey("large"): + result.identityImage.large = profile["images"]["large"]["uri"].str diff --git a/ui/app/AppLayouts/Chat/ChatColumn/EmptyChat.qml b/ui/app/AppLayouts/Chat/ChatColumn/EmptyChat.qml index bd31394510..f286a96842 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/EmptyChat.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/EmptyChat.qml @@ -41,7 +41,7 @@ Item { onLinkActivated: function (linkClicked) { switch (linkClicked) { case "shareKey": - openProfilePopup(profileModel.profile.username, profileModel.profile.pubKey, profileModel.profile.identicon); + openProfilePopup(profileModel.profile.username, profileModel.profile.pubKey, profileModel.profile.thumbnailImage); break; case "invite": inviteFriendsPopup.open(); break; default: //no idea what was clicked diff --git a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml index 67f619d6da..7650da939c 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.13 import "../../../../shared" import "../../../../imports" import "./MessageComponents" @@ -25,6 +25,7 @@ Item { property bool timeout: false property string linkUrls: "" property string imageUrls: "" + property bool placeholderMessage: false property string authorCurrentMsg: "authorCurrentMsg" property string authorPrevMsg: "authorPrevMsg" @@ -48,6 +49,25 @@ Item { property var imageClick: function () {} property var scrollToBottom: function () {} + property string userPubKey: { + if (contentType === Constants.chatIdentifier) { + return chatId + } + return fromAuthor + } + property bool useLargeImage: contentType === Constants.chatIdentifier + + property string profileImageSource: !placeholderMessage && chatView.getProfileImage(userPubKey, isCurrentUser, useLargeImage) || "" + + Connections { + enabled: !placeholderMessage + target: profileModel.contacts.list + onContactChanged: { + if (pubkey === fromAuthor) { + profileImageSource = chatView.getProfileImage(userPubKey, isCurrentUser, useLargeImage) + } + } + } id: root width: parent.width @@ -82,13 +102,13 @@ Item { messageContextMenu.isProfile = !!isProfileClick messageContextMenu.isSticker = isSticker messageContextMenu.emojiOnly = emojiOnly - messageContextMenu.show(userName, fromAuthor, identicon, "", nickname) + messageContextMenu.show(userName, fromAuthor, root.profileImageSource || identicon, "", nickname) // Position the center of the menu where the mouse is messageContextMenu.x = messageContextMenu.x - messageContextMenu.width / 2 } Loader { - active :true + active: true width: parent.width sourceComponent: { switch(contentType) { @@ -165,6 +185,7 @@ Item { id: channelIdentifierComponent ChannelIdentifier { authorCurrentMsg: root.authorCurrentMsg + profileImage: profileImageSource } } @@ -173,7 +194,7 @@ Item { id: privateGroupHeaderComponent StyledText { wrapMode: Text.Wrap - text: { + text: { return ``+ ``+ `