fix(MessageView): Changed visual borders of message
This commit is contained in:
parent
e11d522e8e
commit
5ff2976e80
|
@ -61,7 +61,6 @@ Rectangle {
|
|||
property double timestamp: 0
|
||||
property var reactionsModel: []
|
||||
|
||||
readonly property bool dateGroupVisible: dateGroupLabel.visible
|
||||
property bool showHeader: true
|
||||
property bool isActiveMessage: false
|
||||
property bool disableHover: false
|
||||
|
@ -71,9 +70,6 @@ Rectangle {
|
|||
property bool profileClickable: true
|
||||
property bool hideMessage: false
|
||||
|
||||
property alias previousMessageIndex: dateGroupLabel.previousMessageIndex
|
||||
property alias previousMessageTimestamp: dateGroupLabel.previousMessageTimestamp
|
||||
|
||||
property StatusMessageDetails messageDetails: StatusMessageDetails {}
|
||||
property StatusMessageDetails replyDetails: StatusMessageDetails {}
|
||||
|
||||
|
@ -216,14 +212,6 @@ Rectangle {
|
|||
anchors.topMargin: 8
|
||||
anchors.bottomMargin: 8
|
||||
|
||||
StatusDateGroupLabel {
|
||||
id: dateGroupLabel
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
messageTimestamp: root.timestamp
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
Loader {
|
||||
Layout.fillWidth: true
|
||||
active: isAReply
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import utils 1.0
|
||||
import shared.panels 1.0
|
||||
|
@ -364,476 +365,492 @@ Loader {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: messageComponent
|
||||
|
||||
StatusMessage {
|
||||
id: delegate
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
function convertContentType(value) {
|
||||
switch (value) {
|
||||
case Constants.messageContentType.messageType:
|
||||
return StatusMessage.ContentType.Text;
|
||||
case Constants.messageContentType.stickerType:
|
||||
return StatusMessage.ContentType.Sticker;
|
||||
case Constants.messageContentType.emojiType:
|
||||
return StatusMessage.ContentType.Emoji;
|
||||
case Constants.messageContentType.transactionType:
|
||||
return StatusMessage.ContentType.Transaction;
|
||||
case Constants.messageContentType.imageType:
|
||||
return StatusMessage.ContentType.Image;
|
||||
case Constants.messageContentType.audioType:
|
||||
return StatusMessage.ContentType.Audio;
|
||||
case Constants.messageContentType.communityInviteType:
|
||||
return StatusMessage.ContentType.Invitation;
|
||||
case Constants.messageContentType.fetchMoreMessagesButton:
|
||||
case Constants.messageContentType.chatIdentifier:
|
||||
case Constants.messageContentType.unknownContentType:
|
||||
case Constants.messageContentType.statusType:
|
||||
case Constants.messageContentType.systemMessagePrivateGroupType:
|
||||
case Constants.messageContentType.gapType:
|
||||
case Constants.messageContentType.editType:
|
||||
default:
|
||||
return StatusMessage.ContentType.Unknown;
|
||||
}
|
||||
StatusDateGroupLabel {
|
||||
id: dateGroupLabel
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
Layout.bottomMargin: 16
|
||||
messageTimestamp: root.messageTimestamp
|
||||
previousMessageIndex: root.prevMessageIndex
|
||||
previousMessageTimestamp: root.prevMsgTimestamp
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
readonly property int contentType: convertContentType(root.messageContentType)
|
||||
readonly property bool isReply: root.responseTo !== ""
|
||||
StatusMessage {
|
||||
id: delegate
|
||||
Layout.fillWidth: true
|
||||
|
||||
property var replyMessage: getReplyMessage()
|
||||
|
||||
readonly property string replySenderId: replyMessage ? replyMessage.senderId : ""
|
||||
|
||||
function getReplyMessage() {
|
||||
return root.messageStore && isReply && root.responseToExistingMessage ? root.messageStore.getMessageByIdAsJson(root.responseTo) : null
|
||||
}
|
||||
|
||||
function editCompletedHandler(newMessageText) {
|
||||
const message = root.rootStore.plainText(StatusQUtils.Emoji.deparse(newMessageText))
|
||||
if (message.length <= 0)
|
||||
return;
|
||||
|
||||
const interpretedMessage = root.messageStore.interpretMessage(message)
|
||||
root.messageStore.setEditModeOff(root.messageId)
|
||||
root.messageStore.editMessage(root.messageId, interpretedMessage)
|
||||
}
|
||||
|
||||
audioMessageInfoText: qsTr("Audio Message")
|
||||
cancelButtonText: qsTr("Cancel")
|
||||
saveButtonText: qsTr("Save")
|
||||
loadingImageText: qsTr("Loading image...")
|
||||
errorLoadingImageText: qsTr("Error loading the image")
|
||||
resendText: qsTr("Resend")
|
||||
pinnedMsgInfoText: root.isDiscordMessage ? qsTr("Pinned") : qsTr("Pinned by")
|
||||
reactionIcons: [
|
||||
Style.svg("emojiReactions/heart"),
|
||||
Style.svg("emojiReactions/thumbsUp"),
|
||||
Style.svg("emojiReactions/thumbsDown"),
|
||||
Style.svg("emojiReactions/laughing"),
|
||||
Style.svg("emojiReactions/sad"),
|
||||
Style.svg("emojiReactions/angry"),
|
||||
]
|
||||
|
||||
timestamp: root.messageTimestamp
|
||||
editMode: root.editModeOn
|
||||
isAReply: delegate.isReply
|
||||
isEdited: root.isEdited
|
||||
hasMention: root.hasMention
|
||||
isPinned: root.pinnedMessage
|
||||
pinnedBy: root.pinnedMessage && !root.isDiscordMessage ? Utils.getContactDetailsAsJson(root.messagePinnedBy).displayName : ""
|
||||
hasExpired: root.isExpired
|
||||
reactionsModel: root.reactionsModel
|
||||
|
||||
previousMessageIndex: root.prevMessageIndex
|
||||
previousMessageTimestamp: root.prevMsgTimestamp
|
||||
|
||||
showHeader: root.authorCurrentMsg !== root.authorPrevMsg ||
|
||||
root.shouldRepeatHeader || dateGroupVisible || isAReply
|
||||
isActiveMessage: d.isMessageActive
|
||||
|
||||
disableHover: root.disableHover ||
|
||||
(root.chatLogView && root.chatLogView.flickingVertically) ||
|
||||
activityCenterMessage ||
|
||||
root.messageContextMenu.opened ||
|
||||
!!Global.profilePopupOpened ||
|
||||
!!Global.popupOpened
|
||||
|
||||
hideQuickActions: root.isChatBlocked ||
|
||||
root.placeholderMessage ||
|
||||
root.activityCenterMessage ||
|
||||
root.isInPinnedPopup
|
||||
hideMessage: d.isSingleImage && d.unfurledLinksCount === 1
|
||||
|
||||
overrideBackground: root.activityCenterMessage || root.placeholderMessage
|
||||
overrideBackgroundColor: {
|
||||
if (root.activityCenterMessage && root.activityCenterMessageRead)
|
||||
return Utils.setColorAlpha(Style.current.blue, 0.1);
|
||||
return "transparent";
|
||||
}
|
||||
profileClickable: !root.isDiscordMessage
|
||||
messageAttachments: root.messageAttachments
|
||||
|
||||
timestampString: Utils.formatShortTime(timestamp,
|
||||
localAccountSensitiveSettings.is24hTimeFormat)
|
||||
|
||||
timestampTooltipString: Utils.formatLongDateTime(timestamp,
|
||||
localAccountSensitiveSettings.isDDMMYYDateFormat,
|
||||
localAccountSensitiveSettings.is24hTimeFormat);
|
||||
|
||||
onEditCancelled: {
|
||||
root.messageStore.setEditModeOff(root.messageId)
|
||||
}
|
||||
|
||||
onEditCompleted: {
|
||||
delegate.editCompletedHandler(newMsgText)
|
||||
}
|
||||
|
||||
onImageClicked: {
|
||||
switch (mouse.button) {
|
||||
case Qt.LeftButton:
|
||||
root.imageClicked(image, mouse);
|
||||
break;
|
||||
case Qt.RightButton:
|
||||
root.messageClickHandler(image, Qt.point(mouse.x, mouse.y), false, false, true, image, false, true, false, true, imageSource)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onLinkActivated: {
|
||||
if (link.startsWith('//')) {
|
||||
const pubkey = link.replace("//", "");
|
||||
Global.openProfilePopup(pubkey)
|
||||
return;
|
||||
} else if (link.startsWith('#')) {
|
||||
rootStore.chatCommunitySectionModule.switchToChannel(link.replace("#", ""))
|
||||
return;
|
||||
function convertContentType(value) {
|
||||
switch (value) {
|
||||
case Constants.messageContentType.messageType:
|
||||
return StatusMessage.ContentType.Text;
|
||||
case Constants.messageContentType.stickerType:
|
||||
return StatusMessage.ContentType.Sticker;
|
||||
case Constants.messageContentType.emojiType:
|
||||
return StatusMessage.ContentType.Emoji;
|
||||
case Constants.messageContentType.transactionType:
|
||||
return StatusMessage.ContentType.Transaction;
|
||||
case Constants.messageContentType.imageType:
|
||||
return StatusMessage.ContentType.Image;
|
||||
case Constants.messageContentType.audioType:
|
||||
return StatusMessage.ContentType.Audio;
|
||||
case Constants.messageContentType.communityInviteType:
|
||||
return StatusMessage.ContentType.Invitation;
|
||||
case Constants.messageContentType.fetchMoreMessagesButton:
|
||||
case Constants.messageContentType.chatIdentifier:
|
||||
case Constants.messageContentType.unknownContentType:
|
||||
case Constants.messageContentType.statusType:
|
||||
case Constants.messageContentType.systemMessagePrivateGroupType:
|
||||
case Constants.messageContentType.gapType:
|
||||
case Constants.messageContentType.editType:
|
||||
default:
|
||||
return StatusMessage.ContentType.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
Global.openLink(link)
|
||||
}
|
||||
readonly property int contentType: convertContentType(root.messageContentType)
|
||||
readonly property bool isReply: root.responseTo !== ""
|
||||
|
||||
property var replyMessage: getReplyMessage()
|
||||
|
||||
onProfilePictureClicked: {
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), true);
|
||||
}
|
||||
readonly property string replySenderId: replyMessage ? replyMessage.senderId : ""
|
||||
|
||||
onReplyProfileClicked: {
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), true, false, false, null, false, false, true);
|
||||
}
|
||||
|
||||
onSenderNameClicked: {
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), true);
|
||||
}
|
||||
|
||||
onToggleReactionClicked: {
|
||||
if (root.isChatBlocked)
|
||||
return
|
||||
|
||||
if (!root.messageStore) {
|
||||
console.error("Reaction can not be toggled, message store is not valid")
|
||||
return
|
||||
function getReplyMessage() {
|
||||
return root.messageStore && isReply && root.responseToExistingMessage ? root.messageStore.getMessageByIdAsJson(root.responseTo) : null
|
||||
}
|
||||
|
||||
root.messageStore.toggleReaction(root.messageId, emojiId)
|
||||
}
|
||||
function editCompletedHandler(newMessageText) {
|
||||
const message = root.rootStore.plainText(StatusQUtils.Emoji.deparse(newMessageText))
|
||||
if (message.length <= 0)
|
||||
return;
|
||||
|
||||
onAddReactionClicked: {
|
||||
if (root.isChatBlocked)
|
||||
return;
|
||||
const interpretedMessage = root.messageStore.interpretMessage(message)
|
||||
root.messageStore.setEditModeOff(root.messageId)
|
||||
root.messageStore.editMessage(root.messageId, interpretedMessage)
|
||||
}
|
||||
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), false, false, false, null, true, false);
|
||||
}
|
||||
audioMessageInfoText: qsTr("Audio Message")
|
||||
cancelButtonText: qsTr("Cancel")
|
||||
saveButtonText: qsTr("Save")
|
||||
loadingImageText: qsTr("Loading image...")
|
||||
errorLoadingImageText: qsTr("Error loading the image")
|
||||
resendText: qsTr("Resend")
|
||||
pinnedMsgInfoText: root.isDiscordMessage ? qsTr("Pinned") : qsTr("Pinned by")
|
||||
reactionIcons: [
|
||||
Style.svg("emojiReactions/heart"),
|
||||
Style.svg("emojiReactions/thumbsUp"),
|
||||
Style.svg("emojiReactions/thumbsDown"),
|
||||
Style.svg("emojiReactions/laughing"),
|
||||
Style.svg("emojiReactions/sad"),
|
||||
Style.svg("emojiReactions/angry"),
|
||||
]
|
||||
|
||||
onStickerClicked: {
|
||||
root.openStickerPackPopup(root.stickerPack);
|
||||
}
|
||||
timestamp: root.messageTimestamp
|
||||
editMode: root.editModeOn
|
||||
isAReply: delegate.isReply
|
||||
isEdited: root.isEdited
|
||||
hasMention: root.hasMention
|
||||
isPinned: root.pinnedMessage
|
||||
pinnedBy: root.pinnedMessage && !root.isDiscordMessage ? Utils.getContactDetailsAsJson(root.messagePinnedBy).displayName : ""
|
||||
hasExpired: root.isExpired
|
||||
reactionsModel: root.reactionsModel
|
||||
|
||||
mouseArea {
|
||||
acceptedButtons: root.activityCenterMessage ? Qt.LeftButton : Qt.RightButton
|
||||
enabled: !root.isChatBlocked &&
|
||||
!root.placeholderMessage &&
|
||||
delegate.contentType !== StatusMessage.ContentType.Image
|
||||
onClicked: {
|
||||
showHeader: root.authorCurrentMsg !== root.authorPrevMsg ||
|
||||
root.shouldRepeatHeader || dateGroupLabel.visible || isAReply
|
||||
isActiveMessage: d.isMessageActive
|
||||
|
||||
disableHover: root.disableHover ||
|
||||
(root.chatLogView && root.chatLogView.flickingVertically) ||
|
||||
activityCenterMessage ||
|
||||
root.messageContextMenu.opened ||
|
||||
!!Global.profilePopupOpened ||
|
||||
!!Global.popupOpened
|
||||
|
||||
hideQuickActions: root.isChatBlocked ||
|
||||
root.placeholderMessage ||
|
||||
root.activityCenterMessage ||
|
||||
root.isInPinnedPopup
|
||||
hideMessage: d.isSingleImage && d.unfurledLinksCount === 1
|
||||
|
||||
overrideBackground: root.activityCenterMessage || root.placeholderMessage
|
||||
overrideBackgroundColor: {
|
||||
if (root.activityCenterMessage && root.activityCenterMessageRead)
|
||||
return Utils.setColorAlpha(Style.current.blue, 0.1);
|
||||
return "transparent";
|
||||
}
|
||||
profileClickable: !root.isDiscordMessage
|
||||
messageAttachments: root.messageAttachments
|
||||
|
||||
timestampString: Utils.formatShortTime(timestamp,
|
||||
localAccountSensitiveSettings.is24hTimeFormat)
|
||||
|
||||
timestampTooltipString: Utils.formatLongDateTime(timestamp,
|
||||
localAccountSensitiveSettings.isDDMMYYDateFormat,
|
||||
localAccountSensitiveSettings.is24hTimeFormat);
|
||||
|
||||
onEditCancelled: {
|
||||
root.messageStore.setEditModeOff(root.messageId)
|
||||
}
|
||||
|
||||
onEditCompleted: {
|
||||
delegate.editCompletedHandler(newMsgText)
|
||||
}
|
||||
|
||||
onImageClicked: {
|
||||
switch (mouse.button) {
|
||||
case Qt.LeftButton:
|
||||
root.imageClicked(image, mouse);
|
||||
break;
|
||||
case Qt.RightButton:
|
||||
root.messageClickHandler(image, Qt.point(mouse.x, mouse.y), false, false, true, image, false, true, false, true, imageSource)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onLinkActivated: {
|
||||
if (link.startsWith('//')) {
|
||||
const pubkey = link.replace("//", "");
|
||||
Global.openProfilePopup(pubkey)
|
||||
return;
|
||||
}
|
||||
|
||||
if (link.startsWith('#')) {
|
||||
rootStore.chatCommunitySectionModule.switchToChannel(link.replace("#", ""))
|
||||
return;
|
||||
}
|
||||
|
||||
Global.openLink(link)
|
||||
}
|
||||
|
||||
onProfilePictureClicked: {
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(this, Qt.point(mouse.x, mouse.y),
|
||||
false, false, false, null, root.isEmoji, false, false, false, "");
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), true);
|
||||
}
|
||||
}
|
||||
|
||||
messageDetails: StatusMessageDetails {
|
||||
contentType: delegate.contentType
|
||||
messageOriginInfo: isDiscordMessage ? qsTr("Imported from discord") : ""
|
||||
messageText: root.messageText
|
||||
messageContent: {
|
||||
switch (delegate.contentType)
|
||||
{
|
||||
case StatusMessage.ContentType.Sticker:
|
||||
return root.sticker;
|
||||
case StatusMessage.ContentType.Image:
|
||||
return root.messageImage;
|
||||
onReplyProfileClicked: {
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), true, false, false, null, false, false, true);
|
||||
}
|
||||
|
||||
onSenderNameClicked: {
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), true);
|
||||
}
|
||||
|
||||
onToggleReactionClicked: {
|
||||
if (root.isChatBlocked)
|
||||
return
|
||||
|
||||
if (!root.messageStore) {
|
||||
console.error("Reaction can not be toggled, message store is not valid")
|
||||
return
|
||||
}
|
||||
if (root.isDiscordMessage && root.messageImage != "") {
|
||||
return root.messageImage
|
||||
|
||||
root.messageStore.toggleReaction(root.messageId, emojiId)
|
||||
}
|
||||
|
||||
onAddReactionClicked: {
|
||||
if (root.isChatBlocked)
|
||||
return;
|
||||
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(sender, Qt.point(mouse.x, mouse.y), false, false, false, null, true, false);
|
||||
}
|
||||
|
||||
onStickerClicked: {
|
||||
root.openStickerPackPopup(root.stickerPack);
|
||||
}
|
||||
|
||||
mouseArea {
|
||||
acceptedButtons: root.activityCenterMessage ? Qt.LeftButton : Qt.RightButton
|
||||
enabled: !root.isChatBlocked &&
|
||||
!root.placeholderMessage &&
|
||||
delegate.contentType !== StatusMessage.ContentType.Image
|
||||
onClicked: {
|
||||
d.setMessageActive(root.messageId, true);
|
||||
root.messageClickHandler(this, Qt.point(mouse.x, mouse.y),
|
||||
false, false, false, null, root.isEmoji, false, false, false, "");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
amISender: root.amISender
|
||||
sender.id: root.senderIsEnsVerified ? "" : Utils.getCompressedPk(root.senderId)
|
||||
sender.displayName: root.senderDisplayName
|
||||
sender.secondaryName: root.senderOptionalName
|
||||
sender.isEnsVerified: root.senderIsEnsVerified
|
||||
sender.isContact: root.senderIsAdded
|
||||
sender.trustIndicator: root.senderTrustStatus
|
||||
sender.profileImage {
|
||||
width: 40
|
||||
height: 40
|
||||
name: root.senderIcon || ""
|
||||
assetSettings.isImage: root.isDiscordMessage || root.senderIcon.startsWith("data")
|
||||
pubkey: root.senderId
|
||||
colorId: Utils.colorIdForPubkey(root.senderId)
|
||||
colorHash: Utils.getColorHashAsJson(root.senderId, false, !root.isDiscordMessage)
|
||||
showRing: !root.isDiscordMessage
|
||||
}
|
||||
}
|
||||
messageDetails: StatusMessageDetails {
|
||||
contentType: delegate.contentType
|
||||
messageOriginInfo: isDiscordMessage ? qsTr("Imported from discord") : ""
|
||||
messageText: root.messageText
|
||||
messageContent: {
|
||||
switch (delegate.contentType)
|
||||
{
|
||||
case StatusMessage.ContentType.Sticker:
|
||||
return root.sticker;
|
||||
case StatusMessage.ContentType.Image:
|
||||
return root.messageImage;
|
||||
}
|
||||
if (root.isDiscordMessage && root.messageImage != "") {
|
||||
return root.messageImage
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
replyDetails: StatusMessageDetails {
|
||||
messageText: delegate.replyMessage ? delegate.replyMessage.messageText
|
||||
amISender: root.amISender
|
||||
sender.id: root.senderIsEnsVerified ? "" : Utils.getCompressedPk(root.senderId)
|
||||
sender.displayName: root.senderDisplayName
|
||||
sender.secondaryName: root.senderOptionalName
|
||||
sender.isEnsVerified: root.senderIsEnsVerified
|
||||
sender.isContact: root.senderIsAdded
|
||||
sender.trustIndicator: root.senderTrustStatus
|
||||
sender.profileImage {
|
||||
width: 40
|
||||
height: 40
|
||||
name: root.senderIcon || ""
|
||||
assetSettings.isImage: root.isDiscordMessage || root.senderIcon.startsWith("data")
|
||||
pubkey: root.senderId
|
||||
colorId: Utils.colorIdForPubkey(root.senderId)
|
||||
colorHash: Utils.getColorHashAsJson(root.senderId, false, !root.isDiscordMessage)
|
||||
showRing: !root.isDiscordMessage
|
||||
}
|
||||
}
|
||||
|
||||
replyDetails: StatusMessageDetails {
|
||||
messageText: delegate.replyMessage ? delegate.replyMessage.messageText
|
||||
//: There is should be a message for reply which source message was deleted
|
||||
: qsTr("<deleted>")
|
||||
contentType: delegate.replyMessage ? delegate.convertContentType(delegate.replyMessage.contentType) : 0
|
||||
messageContent: {
|
||||
if (!delegate.replyMessage)
|
||||
contentType: delegate.replyMessage ? delegate.convertContentType(delegate.replyMessage.contentType) : 0
|
||||
messageContent: {
|
||||
if (!delegate.replyMessage)
|
||||
return "";
|
||||
switch (contentType) {
|
||||
case StatusMessage.ContentType.Sticker:
|
||||
return delegate.replyMessage.sticker;
|
||||
case StatusMessage.ContentType.Image:
|
||||
return delegate.replyMessage.messageImage;
|
||||
}
|
||||
return "";
|
||||
switch (contentType) {
|
||||
case StatusMessage.ContentType.Sticker:
|
||||
return delegate.replyMessage.sticker;
|
||||
case StatusMessage.ContentType.Image:
|
||||
return delegate.replyMessage.messageImage;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
amISender: delegate.replyMessage && delegate.replyMessage.amISender
|
||||
sender.id: delegate.replyMessage ? delegate.replyMessage.senderId : ""
|
||||
sender.isContact: delegate.replyMessage && delegate.replyMessage.senderIsAdded
|
||||
sender.displayName: delegate.replyMessage ? delegate.replyMessage.senderDisplayName: ""
|
||||
sender.isEnsVerified: delegate.replyMessage && delegate.replyMessage.senderEnsVerified
|
||||
sender.secondaryName: delegate.replyMessage ? delegate.replyMessage.senderOptionalName : ""
|
||||
sender.profileImage {
|
||||
width: 20
|
||||
height: 20
|
||||
name: delegate.replyMessage ? delegate.replyMessage.senderIcon : ""
|
||||
assetSettings.isImage: delegate.replyMessage && (delegate.replyMessage.messageContentType == Constants.discordMessageType || delegate.replyMessage.senderIcon.startsWith("data"))
|
||||
showRing: delegate.replyMessage && delegate.replyMessage.messageContentType != Constants.discordMessageType
|
||||
pubkey: delegate.replySenderId
|
||||
colorId: Utils.colorIdForPubkey(delegate.replySenderId)
|
||||
colorHash: Utils.getColorHashAsJson(delegate.replySenderId, false, !root.isDiscordMessage)
|
||||
}
|
||||
}
|
||||
|
||||
statusChatInput: StatusChatInput {
|
||||
id: editTextInput
|
||||
objectName: "editMessageInput"
|
||||
|
||||
readonly property string messageText: editTextInput.textInput.text
|
||||
|
||||
// TODO: Move this property and Escape handler to StatusChatInput
|
||||
property bool suggestionsOpened: false
|
||||
|
||||
width: parent.width
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
if (!suggestionsOpened) {
|
||||
delegate.editCancelled()
|
||||
}
|
||||
suggestionsOpened = false
|
||||
}
|
||||
|
||||
store: root.rootStore
|
||||
usersStore: root.usersStore
|
||||
emojiPopup: root.emojiPopup
|
||||
messageContextMenu: root.messageContextMenu
|
||||
|
||||
chatType: root.messageStore.getChatType()
|
||||
isEdit: true
|
||||
|
||||
onSendMessage: {
|
||||
delegate.editCompletedHandler(editTextInput.textInput.text)
|
||||
}
|
||||
|
||||
suggestions.onVisibleChanged: {
|
||||
if (suggestions.visible) {
|
||||
suggestionsOpened = true
|
||||
amISender: delegate.replyMessage && delegate.replyMessage.amISender
|
||||
sender.id: delegate.replyMessage ? delegate.replyMessage.senderId : ""
|
||||
sender.isContact: delegate.replyMessage && delegate.replyMessage.senderIsAdded
|
||||
sender.displayName: delegate.replyMessage ? delegate.replyMessage.senderDisplayName: ""
|
||||
sender.isEnsVerified: delegate.replyMessage && delegate.replyMessage.senderEnsVerified
|
||||
sender.secondaryName: delegate.replyMessage ? delegate.replyMessage.senderOptionalName : ""
|
||||
sender.profileImage {
|
||||
width: 20
|
||||
height: 20
|
||||
name: delegate.replyMessage ? delegate.replyMessage.senderIcon : ""
|
||||
assetSettings.isImage: delegate.replyMessage && (delegate.replyMessage.messageContentType == Constants.discordMessageType || delegate.replyMessage.senderIcon.startsWith("data"))
|
||||
showRing: delegate.replyMessage && delegate.replyMessage.messageContentType != Constants.discordMessageType
|
||||
pubkey: delegate.replySenderId
|
||||
colorId: Utils.colorIdForPubkey(delegate.replySenderId)
|
||||
colorHash: Utils.getColorHashAsJson(delegate.replySenderId, false, !root.isDiscordMessage)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
parseMessage(root.messageText);
|
||||
}
|
||||
}
|
||||
statusChatInput: StatusChatInput {
|
||||
id: editTextInput
|
||||
objectName: "editMessageInput"
|
||||
|
||||
readonly property string messageText: editTextInput.textInput.text
|
||||
|
||||
// TODO: Move this property and Escape handler to StatusChatInput
|
||||
property bool suggestionsOpened: false
|
||||
|
||||
width: parent.width
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
if (!suggestionsOpened) {
|
||||
delegate.editCancelled()
|
||||
}
|
||||
suggestionsOpened = false
|
||||
}
|
||||
|
||||
linksComponent: Component {
|
||||
LinksMessageView {
|
||||
linksModel: linkUrlsModel
|
||||
container: root
|
||||
messageStore: root.messageStore
|
||||
store: root.rootStore
|
||||
isCurrentUser: root.amISender
|
||||
onImageClicked: {
|
||||
root.imageClicked(image);
|
||||
usersStore: root.usersStore
|
||||
emojiPopup: root.emojiPopup
|
||||
messageContextMenu: root.messageContextMenu
|
||||
|
||||
chatType: root.messageStore.getChatType()
|
||||
isEdit: true
|
||||
|
||||
onSendMessage: {
|
||||
delegate.editCompletedHandler(editTextInput.textInput.text)
|
||||
}
|
||||
|
||||
Component.onCompleted: d.unfurledLinksCount = Qt.binding(() => unfurledLinksCount)
|
||||
Component.onDestruction: d.unfurledLinksCount = 0
|
||||
suggestions.onVisibleChanged: {
|
||||
if (suggestions.visible) {
|
||||
suggestionsOpened = true
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
parseMessage(root.messageText);
|
||||
}
|
||||
}
|
||||
|
||||
linksComponent: Component {
|
||||
LinksMessageView {
|
||||
linksModel: linkUrlsModel
|
||||
container: root
|
||||
messageStore: root.messageStore
|
||||
store: root.rootStore
|
||||
isCurrentUser: root.amISender
|
||||
onImageClicked: {
|
||||
root.imageClicked(image);
|
||||
}
|
||||
|
||||
Component.onCompleted: d.unfurledLinksCount = Qt.binding(() => unfurledLinksCount)
|
||||
Component.onDestruction: d.unfurledLinksCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
transcationComponent: Component {
|
||||
TransactionBubbleView {
|
||||
transactionParams: root.transactionParams
|
||||
store: root.rootStore
|
||||
contactsStore: root.contactsStore
|
||||
}
|
||||
}
|
||||
|
||||
invitationComponent: Component {
|
||||
InvitationBubbleView {
|
||||
store: root.rootStore
|
||||
communityId: root.communityId
|
||||
}
|
||||
}
|
||||
|
||||
quickActions: [
|
||||
Loader {
|
||||
active: !root.isInPinnedPopup
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "reaction-b"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Add reaction")
|
||||
onClicked: {
|
||||
d.setMessageActive(root.messageId, true)
|
||||
root.messageClickHandler(this, Qt.point(mouse.x, mouse.y), false, false, false, null, true, false)
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: !root.isInPinnedPopup
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "replyToMessageButton"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "reply"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Reply")
|
||||
onClicked: {
|
||||
root.showReplyArea(root.messageId, root.senderId)
|
||||
if (messageContextMenu.closeParentPopup) {
|
||||
messageContextMenu.closeParentPopup()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: !root.isInPinnedPopup && root.isText && !root.editModeOn && root.amISender
|
||||
visible: active
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "editMessageButton"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "edit_pencil"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Edit")
|
||||
onClicked: {
|
||||
root.messageStore.setEditModeOn(root.messageId)
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: {
|
||||
if (!root.messageStore)
|
||||
return false
|
||||
|
||||
const chatType = root.messageStore.getChatType();
|
||||
const amIChatAdmin = root.messageStore.amIChatAdmin();
|
||||
const pinMessageAllowedForMembers = root.messageStore.pinMessageAllowedForMembers()
|
||||
|
||||
return chatType === Constants.chatType.oneToOne ||
|
||||
chatType === Constants.chatType.privateGroupChat && amIChatAdmin ||
|
||||
chatType === Constants.chatType.communityChat && (amIChatAdmin || pinMessageAllowedForMembers);
|
||||
|
||||
}
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "MessageView_toggleMessagePin"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: root.pinnedMessage ? "unpin" : "pin"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: root.pinnedMessage ? qsTr("Unpin") : qsTr("Pin")
|
||||
onClicked: {
|
||||
if (root.pinnedMessage) {
|
||||
messageStore.unpinMessage(root.messageId)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!!root.messageStore && root.messageStore.getNumberOfPinnedMessages() < Constants.maxNumberOfPins) {
|
||||
messageStore.pinMessage(root.messageId)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chatContentModule) {
|
||||
console.warn("error on open pinned messages limit reached from message context menu - chat content module is not set")
|
||||
return;
|
||||
}
|
||||
|
||||
Global.openPopup(Global.pinnedMessagesPopup, {
|
||||
store: root.rootStore,
|
||||
messageStore: messageStore,
|
||||
pinnedMessagesModel: chatContentModule.pinnedMessagesModel,
|
||||
messageToPin: root.messageId
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: {
|
||||
if (root.isInPinnedPopup)
|
||||
return false;
|
||||
if (!root.messageStore)
|
||||
return false;
|
||||
const isMyMessage = senderId !== "" && senderId === userProfile.pubKey;
|
||||
const chatType = root.messageStore.getChatType();
|
||||
return isMyMessage &&
|
||||
(messageContentType === Constants.messageContentType.messageType ||
|
||||
messageContentType === Constants.messageContentType.stickerType ||
|
||||
messageContentType === Constants.messageContentType.emojiType ||
|
||||
messageContentType === Constants.messageContentType.imageType ||
|
||||
messageContentType === Constants.messageContentType.audioType);
|
||||
}
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "chatDeleteMessageButton"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "delete"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Delete")
|
||||
onClicked: {
|
||||
if (!localAccountSensitiveSettings.showDeleteMessageWarning) {
|
||||
messageStore.deleteMessage(root.messageId)
|
||||
}
|
||||
else {
|
||||
Global.openPopup(deleteMessageConfirmationDialogComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
transcationComponent: Component {
|
||||
TransactionBubbleView {
|
||||
transactionParams: root.transactionParams
|
||||
store: root.rootStore
|
||||
contactsStore: root.contactsStore
|
||||
}
|
||||
}
|
||||
|
||||
invitationComponent: Component {
|
||||
InvitationBubbleView {
|
||||
store: root.rootStore
|
||||
communityId: root.communityId
|
||||
}
|
||||
}
|
||||
|
||||
quickActions: [
|
||||
Loader {
|
||||
active: !root.isInPinnedPopup
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "reaction-b"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Add reaction")
|
||||
onClicked: {
|
||||
d.setMessageActive(root.messageId, true)
|
||||
root.messageClickHandler(this, Qt.point(mouse.x, mouse.y), false, false, false, null, true, false)
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: !root.isInPinnedPopup
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "replyToMessageButton"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "reply"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Reply")
|
||||
onClicked: {
|
||||
root.showReplyArea(root.messageId, root.senderId)
|
||||
if (messageContextMenu.closeParentPopup) {
|
||||
messageContextMenu.closeParentPopup()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: !root.isInPinnedPopup && root.isText && !root.editModeOn && root.amISender
|
||||
visible: active
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "editMessageButton"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "edit_pencil"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Edit")
|
||||
onClicked: {
|
||||
root.messageStore.setEditModeOn(root.messageId)
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: {
|
||||
if (!root.messageStore)
|
||||
return false
|
||||
|
||||
const chatType = root.messageStore.getChatType();
|
||||
const amIChatAdmin = root.messageStore.amIChatAdmin();
|
||||
const pinMessageAllowedForMembers = root.messageStore.pinMessageAllowedForMembers()
|
||||
|
||||
return chatType === Constants.chatType.oneToOne ||
|
||||
chatType === Constants.chatType.privateGroupChat && amIChatAdmin ||
|
||||
chatType === Constants.chatType.communityChat && (amIChatAdmin || pinMessageAllowedForMembers);
|
||||
|
||||
}
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "MessageView_toggleMessagePin"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: root.pinnedMessage ? "unpin" : "pin"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: root.pinnedMessage ? qsTr("Unpin") : qsTr("Pin")
|
||||
onClicked: {
|
||||
if (root.pinnedMessage) {
|
||||
messageStore.unpinMessage(root.messageId)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!!root.messageStore && root.messageStore.getNumberOfPinnedMessages() < Constants.maxNumberOfPins) {
|
||||
messageStore.pinMessage(root.messageId)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chatContentModule) {
|
||||
console.warn("error on open pinned messages limit reached from message context menu - chat content module is not set")
|
||||
return;
|
||||
}
|
||||
|
||||
Global.openPopup(Global.pinnedMessagesPopup, {
|
||||
store: root.rootStore,
|
||||
messageStore: messageStore,
|
||||
pinnedMessagesModel: chatContentModule.pinnedMessagesModel,
|
||||
messageToPin: root.messageId
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: {
|
||||
if (root.isInPinnedPopup)
|
||||
return false;
|
||||
if (!root.messageStore)
|
||||
return false;
|
||||
const isMyMessage = senderId !== "" && senderId === userProfile.pubKey;
|
||||
const chatType = root.messageStore.getChatType();
|
||||
return isMyMessage &&
|
||||
(messageContentType === Constants.messageContentType.messageType ||
|
||||
messageContentType === Constants.messageContentType.stickerType ||
|
||||
messageContentType === Constants.messageContentType.emojiType ||
|
||||
messageContentType === Constants.messageContentType.imageType ||
|
||||
messageContentType === Constants.messageContentType.audioType);
|
||||
}
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "chatDeleteMessageButton"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "delete"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Delete")
|
||||
onClicked: {
|
||||
if (!localAccountSensitiveSettings.showDeleteMessageWarning) {
|
||||
messageStore.deleteMessage(root.messageId)
|
||||
}
|
||||
else {
|
||||
Global.openPopup(deleteMessageConfirmationDialogComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue