fix: YouTube unfurling

YouTube link unfurling was not working for a couple reasons.

There were two main parts fixed:
1. QML context for messages pertaining to linkUrls and imageUrls was changed from implicit to explicit. By this, I mean that any time we referenced linkUrls/imageUrls, we were relying on the knowledge that those values would be populated by some parent context several levels up. Now, we are referring to properties that have been explicitly defined on the components. This offers the ability to reuse components, and makes reading the code and debugging much easier.
2. Error handling has been added to getting link preview data. An unhandled "error" was thrown each time a link that wasn't whitelisted was passed in, causing the app to crash. For example, when a link to a tenor gif was posted in the chat, that URL was not whitelisted, causing the app to crash.
This commit is contained in:
emizzle 2020-12-08 10:38:53 +11:00 committed by Iuri Matias
parent 04bf8e7a03
commit 5953031bfc
12 changed files with 130 additions and 75 deletions

View File

@ -312,7 +312,10 @@ QtObject:
setClipBoardText(content) setClipBoardText(content)
proc getLinkPreviewData*(self: ChatsView, link: string): string {.slot.} = proc getLinkPreviewData*(self: ChatsView, link: string): string {.slot.} =
result = $self.status.chat.getLinkPreviewData(link) try:
$self.status.chat.getLinkPreviewData(link)
except RpcException as e:
$ %* { "error": e.msg }
proc joinChat*(self: ChatsView, channel: string, chatTypeInt: int): int {.slot.} = proc joinChat*(self: ChatsView, channel: string, chatTypeInt: int): int {.slot.} =
self.status.chat.join(channel, ChatType(chatTypeInt)) self.status.chat.join(channel, ChatType(chatTypeInt))

View File

@ -1,4 +1,4 @@
import json, times, strutils, sequtils, chronicles, json_serialization, algorithm import json, times, strutils, sequtils, chronicles, json_serialization, algorithm, strformat
import core, utils import core, utils
import ../chat/[chat, message] import ../chat/[chat, message]
import ../signals/messages import ../signals/messages
@ -200,4 +200,11 @@ proc unmuteChat*(chatId: string): string =
result = callPrivateRPC("unmuteChat".prefix, %*[chatId]) result = callPrivateRPC("unmuteChat".prefix, %*[chatId])
proc getLinkPreviewData*(link: string): JsonNode = proc getLinkPreviewData*(link: string): JsonNode =
result = callPrivateRPC("getLinkPreviewData".prefix, %*[link]).parseJSON()["result"] let
responseStr = callPrivateRPC("getLinkPreviewData".prefix, %*[link])
response = Json.decode(responseStr, RpcResponseTyped[JsonNode], allowUnknownFields = false)
if not response.error.isNil:
raise newException(RpcException, fmt"""Error getting link preview data for '{link}': {response.error.message}""")
response.result

View File

@ -78,6 +78,14 @@ type
result*: string result*: string
id*: int id*: int
error*: RpcError error*: RpcError
# TODO: replace all RpcResponse and RpcResponseTyped occurances with a generic
# form of RpcReponse. IOW, rename RpceResponseTyped*[T] to RpcResponse*[T] and
# remove RpcResponse.
RpcResponseTyped*[T] = object
jsonrpc*: string
result*: T
id*: int
error*: RpcError
proc toAccount*(account: GeneratedAccount): Account = proc toAccount*(account: GeneratedAccount): Account =
result = Account(name: account.name, photoPath: account.photoPath, keyUid: account.address) result = Account(name: account.name, photoPath: account.photoPath, keyUid: account.address)

View File

@ -299,6 +299,8 @@ ScrollView {
imageClick: imagePopup.openPopup.bind(imagePopup) imageClick: imagePopup.openPopup.bind(imagePopup)
messageId: model.messageId messageId: model.messageId
emojiReactions: model.emojiReactions emojiReactions: model.emojiReactions
linkUrls: model.linkUrls
imageUrls: model.imageUrls
prevMessageIndex: { prevMessageIndex: {
// This is used in order to have access to the previous message and determine the timestamp // This is used in order to have access to the previous message and determine the timestamp
// we can't rely on the index because the sequence of messages is not ordered on the nim side // we can't rely on the index because the sequence of messages is not ordered on the nim side

View File

@ -24,6 +24,7 @@ Item {
property int prevMessageIndex: -1 property int prevMessageIndex: -1
property bool timeout: false property bool timeout: false
property string linkUrls: "" property string linkUrls: ""
property string imageUrls: ""
property string authorCurrentMsg: "authorCurrentMsg" property string authorCurrentMsg: "authorCurrentMsg"
property string authorPrevMsg: "authorPrevMsg" property string authorPrevMsg: "authorPrevMsg"
@ -47,7 +48,7 @@ Item {
property var imageClick: function () {} property var imageClick: function () {}
property var scrollToBottom: function () {} property var scrollToBottom: function () {}
id: messageItem id: root
width: parent.width width: parent.width
anchors.right: !isCurrentUser ? undefined : parent.right anchors.right: !isCurrentUser ? undefined : parent.right
height: { height: {
@ -161,7 +162,7 @@ Item {
Component { Component {
id: channelIdentifierComponent id: channelIdentifierComponent
ChannelIdentifier { ChannelIdentifier {
authorCurrentMsg: messageItem.authorCurrentMsg authorCurrentMsg: root.authorCurrentMsg
} }
} }
@ -192,7 +193,7 @@ Item {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
textFormat: Text.RichText textFormat: Text.RichText
topPadding: messageItem.prevMessageIndex === 1 ? Style.current.bigPadding : 0 topPadding: root.prevMessageIndex === 1 ? Style.current.bigPadding : 0
} }
} }
@ -200,7 +201,11 @@ Item {
Component { Component {
id: messageComponent id: messageComponent
NormalMessage { NormalMessage {
clickMessage: messageItem.clickMessage clickMessage: root.clickMessage
linkUrls: root.linkUrls
imageUrls: root.imageUrls
isCurrentUser: root.isCurrentUser
contentType: root.contentType
} }
} }
@ -208,7 +213,10 @@ Item {
Component { Component {
id: compactMessageComponent id: compactMessageComponent
CompactMessage { CompactMessage {
clickMessage: messageItem.clickMessage clickMessage: root.clickMessage
linkUrls: root.linkUrls
imageUrls: root.imageUrls
contentType: root.contentType
} }
} }

View File

@ -6,9 +6,12 @@ Item {
property var clickMessage: function () {} property var clickMessage: function () {}
property int chatHorizontalPadding: 12 property int chatHorizontalPadding: 12
property int chatVerticalPadding: 7 property int chatVerticalPadding: 7
property bool showImages: appSettings.displayChatImages && imageUrls != "" property string imageUrls: ""
property bool showImages: appSettings.displayChatImages && root.imageUrls != ""
property string linkUrls: ""
property int contentType: 2
id: chatTextItem id: root
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: authorCurrentMsg != authorPrevMsg ? Style.current.smallPadding : 0 anchors.topMargin: authorCurrentMsg != authorPrevMsg ? Style.current.smallPadding : 0
height: childrenRect.height + this.anchors.topMargin height: childrenRect.height + this.anchors.topMargin
@ -29,7 +32,7 @@ Item {
UsernameLabel { UsernameLabel {
id: chatName id: chatName
anchors.leftMargin: chatTextItem.chatHorizontalPadding anchors.leftMargin: root.chatHorizontalPadding
// anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top // anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top
anchors.top: parent.top anchors.top: parent.top
anchors.left: chatImage.right anchors.left: chatImage.right
@ -42,21 +45,21 @@ Item {
id: chatReply id: chatReply
// anchors.top: chatName.visible ? chatName.bottom : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top) // anchors.top: chatName.visible ? chatName.bottom : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top)
anchors.top: chatName.visible ? chatName.bottom : parent.top anchors.top: chatName.visible ? chatName.bottom : parent.top
anchors.topMargin: chatName.visible && this.visible ? chatTextItem.chatVerticalPadding : 0 anchors.topMargin: chatName.visible && this.visible ? root.chatVerticalPadding : 0
anchors.left: chatImage.right anchors.left: chatImage.right
anchors.leftMargin: chatTextItem.chatHorizontalPadding anchors.leftMargin: root.chatHorizontalPadding
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: chatTextItem.chatHorizontalPadding anchors.rightMargin: root.chatHorizontalPadding
} }
ChatText { ChatText {
id: chatText id: chatText
anchors.top: chatReply.bottom anchors.top: chatReply.bottom
anchors.topMargin: chatName.visible && this.visible ? chatTextItem.chatVerticalPadding : 0 anchors.topMargin: chatName.visible && this.visible ? root.chatVerticalPadding : 0
anchors.left: chatImage.right anchors.left: chatImage.right
anchors.leftMargin: chatTextItem.chatHorizontalPadding anchors.leftMargin: root.chatHorizontalPadding
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: chatTextItem.chatHorizontalPadding anchors.rightMargin: root.chatHorizontalPadding
} }
Loader { Loader {
@ -71,7 +74,7 @@ Item {
ChatImage { ChatImage {
imageSource: image imageSource: image
imageWidth: 200 imageWidth: 200
onClicked: chatTextItem.clickMessage(false, false, true, image) onClicked: root.clickMessage(false, false, true, image)
} }
} }
} }
@ -81,7 +84,7 @@ Item {
active: contentType === Constants.stickerType active: contentType === Constants.stickerType
anchors.left: chatText.left anchors.left: chatText.left
anchors.top: chatName.visible ? chatName.bottom : parent.top anchors.top: chatName.visible ? chatName.bottom : parent.top
anchors.topMargin: this.visible && chatName.visible ? chatTextItem.chatVerticalPadding : 0 anchors.topMargin: this.visible && chatName.visible ? root.chatVerticalPadding : 0
sourceComponent: Component { sourceComponent: Component {
Rectangle { Rectangle {
@ -90,15 +93,17 @@ Item {
border.color: Style.current.grey border.color: Style.current.grey
border.width: 1 border.width: 1
radius: 16 radius: 16
width: stickerId.width + 2 * chatTextItem.chatVerticalPadding width: stickerId.width + 2 * root.chatVerticalPadding
height: stickerId.height + 2 * chatTextItem.chatVerticalPadding height: stickerId.height + 2 * root.chatVerticalPadding
Sticker { Sticker {
id: stickerId id: stickerId
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: chatTextItem.chatVerticalPadding anchors.topMargin: root.chatVerticalPadding
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: chatTextItem.chatVerticalPadding anchors.leftMargin: root.chatVerticalPadding
contentType: root.contentType
container: root.parent
} }
} }
} }
@ -133,7 +138,7 @@ Item {
Loader { Loader {
id: imageLoader id: imageLoader
active: showImages active: root.showImages
anchors.left: chatText.left anchors.left: chatText.left
anchors.leftMargin: 8 anchors.leftMargin: 8
anchors.top: chatText.bottom anchors.top: chatText.bottom
@ -142,22 +147,26 @@ Item {
ImageMessage { ImageMessage {
color: Style.current.transparent color: Style.current.transparent
chatHorizontalPadding: 0 chatHorizontalPadding: 0
imageUrls: root.imageUrls
onClicked: { onClicked: {
chatTextItem.clickMessage(false, false, true, image) root.clickMessage(false, false, true, image)
} }
container: root.parent
} }
} }
} }
Loader { Loader {
id: linksLoader id: linksLoader
active: !!linkUrls active: !!root.linkUrls
anchors.left: chatText.left anchors.left: chatText.left
anchors.leftMargin: 8 anchors.leftMargin: 8
anchors.top: chatText.bottom anchors.top: chatText.bottom
sourceComponent: Component { sourceComponent: Component {
LinksMessage {} LinksMessage {
linkUrls: root.linkUrls
}
} }
} }

View File

@ -11,6 +11,7 @@ Item {
property bool playing: true property bool playing: true
property bool isAnimated: !!source && source.toString().endsWith('.gif') property bool isAnimated: !!source && source.toString().endsWith('.gif')
signal clicked(var image) signal clicked(var image)
property var container
id: imageContainer id: imageContainer
width: loadingImage.visible ? loadingImage.width : imageMessage.width width: loadingImage.visible ? loadingImage.width : imageMessage.width
@ -61,7 +62,7 @@ Item {
imageMessage.visible = false imageMessage.visible = false
} else if (imageMessage.status === Image.Ready) { } else if (imageMessage.status === Image.Ready) {
loadingImage.visible = false loadingImage.visible = false
scrollToBottom(true, messageItem) scrollToBottom(true, root.container)
} }
} }

View File

@ -4,8 +4,10 @@ import "../../../../../imports"
Rectangle { Rectangle {
property int chatVerticalPadding: 12 property int chatVerticalPadding: 12
property int chatHorizontalPadding: 12 property int chatHorizontalPadding: 12
property bool isCurrentUser: bool property bool isCurrentUser: false
signal clicked(var image) signal clicked(var image)
property var container
property string imageUrls: ""
id: imageChatBox id: imageChatBox
height: { height: {
@ -32,11 +34,11 @@ Rectangle {
Repeater { Repeater {
id: imageRepeater id: imageRepeater
model: { model: {
if (!imageUrls) { if (!root.imageUrls) {
return [] return []
} }
return imageUrls.split(" ") return root.imageUrls.split(" ")
} }
ImageLoader { ImageLoader {
@ -49,6 +51,7 @@ Rectangle {
onClicked: { onClicked: {
imageChatBox.clicked(image) imageChatBox.clicked(image)
} }
container: root.container
} }
} }

View File

@ -6,7 +6,9 @@ import "../../../../../shared/status"
import "../../../Profile/LeftTab/constants.js" as ProfileConstants import "../../../Profile/LeftTab/constants.js" as ProfileConstants
Item { Item {
id: linksItem id: root
property string linkUrls: ""
height: { height: {
let h = 0 let h = 0
for (let i = 0; i < linksRepeater.count; i++) { for (let i = 0; i < linksRepeater.count; i++) {
@ -27,11 +29,11 @@ Item {
Repeater { Repeater {
id: linksRepeater id: linksRepeater
model: { model: {
if (!linkUrls) { if (!root.linkUrls) {
return [] return []
} }
return linkUrls.split(" ") return root.linkUrls.split(" ")
} }
@ -82,15 +84,15 @@ Item {
id: unfurledLinkComponent id: unfurledLinkComponent
Loader { Loader {
property var linkData: { property var linkData: {
try {
const data = chatsModel.getLinkPreviewData(linkString) const data = chatsModel.getLinkPreviewData(linkString)
return JSON.parse(data) const result = JSON.parse(data)
} catch (e) { if (result.error) {
console.error("Error parsing link data", e) console.error(result.error)
return undfined return undefined
} }
return result
} }
enabled: linkData !== undefined && !!linkData.title active: linkData !== undefined && !!linkData.title
sourceComponent: Component { sourceComponent: Component {
Rectangle { Rectangle {
id: rectangle id: rectangle

View File

@ -4,9 +4,13 @@ import "../../../../../imports"
Item { Item {
property var clickMessage: function () {} property var clickMessage: function () {}
property bool showImages: appSettings.displayChatImages && imageUrls !== "" property string imageUrls: ""
property bool showImages: appSettings.displayChatImages && root.imageUrls !== ""
property string linkUrls: ""
property bool isCurrentUser: false
property int contentType: 2
id: chatTextItem id: root
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: authorCurrentMsg !== authorPrevMsg ? Style.current.smallPadding : 0 anchors.topMargin: authorCurrentMsg !== authorPrevMsg ? Style.current.smallPadding : 0
height: childrenRect.height + this.anchors.topMargin + (dateGroupLbl.visible ? dateGroupLbl.height : 0) height: childrenRect.height + this.anchors.topMargin + (dateGroupLbl.visible ? dateGroupLbl.height : 0)
@ -18,7 +22,7 @@ Item {
UserImage { UserImage {
id: chatImage id: chatImage
visible: chatsModel.activeChannel.chatType !== Constants.chatTypeOneToOne && isMessage && authorCurrentMsg != authorPrevMsg && !isCurrentUser visible: chatsModel.activeChannel.chatType !== Constants.chatTypeOneToOne && isMessage && authorCurrentMsg != authorPrevMsg && !root.isCurrentUser
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: Style.current.padding anchors.leftMargin: Style.current.padding
anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top
@ -27,7 +31,7 @@ Item {
UsernameLabel { UsernameLabel {
id: chatName id: chatName
visible: chatsModel.activeChannel.chatType !== Constants.chatTypeOneToOne && isMessage && authorCurrentMsg != authorPrevMsg && !isCurrentUser visible: chatsModel.activeChannel.chatType !== Constants.chatTypeOneToOne && isMessage && authorCurrentMsg != authorPrevMsg && !root.isCurrentUser
anchors.leftMargin: 20 anchors.leftMargin: 20
anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top
anchors.topMargin: 0 anchors.topMargin: 0
@ -57,7 +61,7 @@ Item {
if (isImage) { if (isImage) {
return "transparent" return "transparent"
} }
return isCurrentUser ? Style.current.primary : Style.current.secondaryBackground return root.isCurrentUser ? Style.current.primary : Style.current.secondaryBackground
} }
border.color: isSticker ? Style.current.border : Style.current.transparent border.color: isSticker ? Style.current.border : Style.current.transparent
border.width: 1 border.width: 1
@ -100,11 +104,11 @@ Item {
} }
radius: 16 radius: 16
anchors.left: !isCurrentUser ? chatImage.right : undefined anchors.left: !root.isCurrentUser ? chatImage.right : undefined
anchors.leftMargin: !isCurrentUser ? 8 : 0 anchors.leftMargin: !root.isCurrentUser ? 8 : 0
anchors.right: !isCurrentUser ? undefined : parent.right anchors.right: !root.isCurrentUser ? undefined : parent.right
anchors.rightMargin: !isCurrentUser ? 0 : Style.current.padding anchors.rightMargin: !root.isCurrentUser ? 0 : Style.current.padding
anchors.top: authorCurrentMsg != authorPrevMsg && !isCurrentUser ? chatImage.top : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top) anchors.top: authorCurrentMsg != authorPrevMsg && !root.isCurrentUser ? chatImage.top : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top)
anchors.topMargin: 0 anchors.topMargin: 0
visible: isMessage visible: isMessage
@ -128,7 +132,7 @@ Item {
anchors.leftMargin: chatBox.chatHorizontalPadding anchors.leftMargin: chatBox.chatHorizontalPadding
anchors.right: chatBox.longChatText ? parent.right : undefined anchors.right: chatBox.longChatText ? parent.right : undefined
anchors.rightMargin: chatBox.longChatText ? chatBox.chatHorizontalPadding : 0 anchors.rightMargin: chatBox.longChatText ? chatBox.chatHorizontalPadding : 0
textField.color: !isCurrentUser ? Style.current.textColor : Style.current.currentUserTextColor textField.color: !root.isCurrentUser ? Style.current.textColor : Style.current.currentUserTextColor
Connections { Connections {
target: appSettings.compactMode ? null : chatBox target: appSettings.compactMode ? null : chatBox
onLongChatTextChanged: { onLongChatTextChanged: {
@ -155,8 +159,8 @@ Item {
id: chatImageComponent id: chatImageComponent
imageSource: image imageSource: image
imageWidth: 250 imageWidth: 250
isCurrentUser: messageItem.isCurrentUser isCurrentUser: root.isCurrentUser
onClicked: chatTextItem.clickMessage(false, false, true, image) onClicked: root.clickMessage(false, false, true, image)
} }
} }
} }
@ -183,6 +187,8 @@ Item {
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: chatBox.chatVerticalPadding anchors.topMargin: chatBox.chatVerticalPadding
color: Style.current.transparent color: Style.current.transparent
container: root.parent
contentType: root.contentType
} }
MessageMouseArea { MessageMouseArea {
@ -197,16 +203,16 @@ Item {
ChatTime { ChatTime {
id: chatTime id: chatTime
anchors.top: showImages ? imageLoader.bottom : chatBox.bottom anchors.top: root.showImages ? imageLoader.bottom : chatBox.bottom
anchors.topMargin: 4 anchors.topMargin: 4
anchors.bottomMargin: Style.current.padding anchors.bottomMargin: Style.current.padding
anchors.right: showImages ? imageLoader.right : chatBox.right anchors.right: root.showImages ? imageLoader.right : chatBox.right
anchors.rightMargin: isCurrentUser ? 5 : Style.current.padding anchors.rightMargin: root.isCurrentUser ? 5 : Style.current.padding
} }
SentMessage { SentMessage {
id: sentMessage id: sentMessage
visible: isCurrentUser && !timeout && !isExpired && isMessage && outgoingStatus !== "sent" visible: root.isCurrentUser && !timeout && !isExpired && isMessage && outgoingStatus !== "sent"
anchors.top: chatTime.top anchors.top: chatTime.top
anchors.bottomMargin: Style.current.padding anchors.bottomMargin: Style.current.padding
anchors.right: chatTime.left anchors.right: chatTime.left
@ -223,12 +229,12 @@ Item {
Loader { Loader {
id: imageLoader id: imageLoader
active: showImages active: root.showImages
sourceComponent: imageComponent sourceComponent: imageComponent
anchors.left: !isCurrentUser ? chatImage.right : undefined anchors.left: !root.isCurrentUser ? chatImage.right : undefined
anchors.leftMargin: !isCurrentUser ? 8 : 0 anchors.leftMargin: !root.isCurrentUser ? 8 : 0
anchors.right: !isCurrentUser ? undefined : parent.right anchors.right: !root.isCurrentUser ? undefined : parent.right
anchors.rightMargin: !isCurrentUser ? 0 : Style.current.padding anchors.rightMargin: !root.isCurrentUser ? 0 : Style.current.padding
anchors.top: chatBox.bottom anchors.top: chatBox.bottom
anchors.topMargin: Style.current.smallPadding anchors.topMargin: Style.current.smallPadding
} }
@ -236,25 +242,29 @@ Item {
Component { Component {
id: imageComponent id: imageComponent
ImageMessage { ImageMessage {
isCurrentUser: messageItem.isCurrentUser isCurrentUser: root.isCurrentUser
container: root.parent
imageUrls: root.imageUrls
onClicked: { onClicked: {
chatTextItem.clickMessage(false, false, true, image) root.clickMessage(false, false, true, image)
} }
} }
} }
Loader { Loader {
id: linksLoader id: linksLoader
active: !!linkUrls active: !!root.linkUrls
anchors.left: !isCurrentUser ? chatImage.right : undefined anchors.left: !root.isCurrentUser ? chatImage.right : undefined
anchors.leftMargin: !isCurrentUser ? 8 : 0 anchors.leftMargin: !root.isCurrentUser ? 8 : 0
anchors.right: !isCurrentUser ? undefined : parent.right anchors.right: !root.isCurrentUser ? undefined : parent.right
anchors.rightMargin: !isCurrentUser ? 0 : Style.current.padding anchors.rightMargin: !root.isCurrentUser ? 0 : Style.current.padding
anchors.top: chatBox.bottom anchors.top: chatBox.bottom
anchors.topMargin: Style.current.smallPadding anchors.topMargin: Style.current.smallPadding
sourceComponent: Component { sourceComponent: Component {
LinksMessage {} LinksMessage {
linkUrls: root.linkUrls
}
} }
} }
@ -262,8 +272,8 @@ Item {
id: emojiReactionLoader id: emojiReactionLoader
active: emojiReactions !== "" active: emojiReactions !== ""
sourceComponent: emojiReactionsComponent sourceComponent: emojiReactionsComponent
anchors.left: !isCurrentUser ? chatBox.left : undefined anchors.left: !root.isCurrentUser ? chatBox.left : undefined
anchors.right: !isCurrentUser ? undefined : chatBox.right anchors.right: !root.isCurrentUser ? undefined : chatBox.right
anchors.top: chatBox.bottom anchors.top: chatBox.bottom
anchors.topMargin: 2 anchors.topMargin: 2
} }

View File

@ -4,6 +4,8 @@ import "../../../../../imports"
Loader { Loader {
property color color property color color
property var container
property int contentType: -1
id: root id: root
active: contentType === Constants.stickerType active: contentType === Constants.stickerType
@ -12,7 +14,7 @@ Loader {
Shared.ImageLoader { Shared.ImageLoader {
color: root.color color: root.color
onLoaded: { onLoaded: {
scrollToBottom(true, messageItem) scrollToBottom(true, root.container)
} }
width: 140 width: 140

2
vendor/nim-status vendored

@ -1 +1 @@
Subproject commit fcf81af89f5c5f3203b9b35214dd478afec71560 Subproject commit f56f8834d2e9cfaebcf1742bd7f74af003ef087d