feat(context-menu): add Copy message action in message context menu

Adds the action to copy the right-clicked message's text.

It copies the unparsed text (no html).
For that, I had to add it in the MessageItem and expose it in the model.

I also fixed the copy MessageId action that didn't show + didn't work even if it would have shown.

Plus some small cleanups.
This commit is contained in:
Jonathan Rainville 2023-01-06 15:19:27 -05:00 committed by Iuri Matias
parent acf67c33d5
commit af0c9767d1
10 changed files with 190 additions and 148 deletions

View File

@ -82,6 +82,7 @@ proc createMessageItemFromDto(self: Module, message: MessageDto, chatDetails: Ch
contactDetails.details.added, contactDetails.details.added,
message.outgoingStatus, message.outgoingStatus,
self.controller.getRenderedText(message.parsedText), self.controller.getRenderedText(message.parsedText),
message.text,
message.image, message.image,
message.containsContactMentions(), message.containsContactMentions(),
message.seen, message.seen,

View File

@ -86,6 +86,7 @@ proc createFetchMoreMessagesItem(self: Module): Item =
senderIsAdded = false, senderIsAdded = false,
outgoingStatus = "", outgoingStatus = "",
text = "", text = "",
unparsedText = "",
image = "", image = "",
messageContainsMentions = false, messageContainsMentions = false,
seen = true, seen = true,
@ -134,6 +135,7 @@ proc createChatIdentifierItem(self: Module): Item =
senderIsAdded, senderIsAdded,
outgoingStatus = "", outgoingStatus = "",
text = "", text = "",
unparsedText = "",
image = "", image = "",
messageContainsMentions = false, messageContainsMentions = false,
seen = true, seen = true,
@ -186,68 +188,69 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
var viewItems: seq[Item] var viewItems: seq[Item]
if(messages.len > 0): if(messages.len > 0):
for m in messages: for message in messages:
# https://github.com/status-im/status-desktop/issues/7632 will introduce deleteFroMe feature. # https://github.com/status-im/status-desktop/issues/7632 will introduce deleteFroMe feature.
# Now we just skip deleted messages # Now we just skip deleted messages
if m.deleted or m.deletedForMe: if message.deleted or message.deletedForMe:
continue continue
let sender = self.controller.getContactDetails(m.`from`) let sender = self.controller.getContactDetails(message.`from`)
let renderedMessageText = self.controller.getRenderedText(m.parsedText) let renderedMessageText = self.controller.getRenderedText(message.parsedText)
var transactionContract = m.transactionParameters.contract var transactionContract = message.transactionParameters.contract
var transactionValue = m.transactionParameters.value var transactionValue = message.transactionParameters.value
var isCurrentUser = sender.isCurrentUser var isCurrentUser = sender.isCurrentUser
if(m.contentType.ContentType == ContentType.Transaction): if(message.contentType.ContentType == ContentType.Transaction):
(transactionContract, transactionValue) = self.controller.getTransactionDetails(m) (transactionContract, transactionValue) = self.controller.getTransactionDetails(message)
if m.transactionParameters.fromAddress != "": if message.transactionParameters.fromAddress != "":
isCurrentUser = self.currentUserWalletContainsAddress(m.transactionParameters.fromAddress) isCurrentUser = self.currentUserWalletContainsAddress(message.transactionParameters.fromAddress)
var item = initItem( var item = initItem(
m.id, message.id,
m.communityId, message.communityId,
m.responseTo, message.responseTo,
m.`from`, message.`from`,
sender.defaultDisplayName, sender.defaultDisplayName,
sender.optionalName, sender.optionalName,
sender.icon, sender.icon,
(isCurrentUser and m.contentType.ContentType != ContentType.DiscordMessage), (isCurrentUser and message.contentType.ContentType != ContentType.DiscordMessage),
sender.details.added, sender.details.added,
m.outgoingStatus, message.outgoingStatus,
renderedMessageText, renderedMessageText,
m.image, message.text,
m.containsContactMentions(), message.image,
m.seen, message.containsContactMentions(),
timestamp = m.whisperTimestamp, message.seen,
clock = m.clock, timestamp = message.whisperTimestamp,
m.contentType.ContentType, clock = message.clock,
m.messageType, message.contentType.ContentType,
m.contactRequestState, message.messageType,
sticker = m.sticker.url, message.contactRequestState,
m.sticker.pack, sticker = message.sticker.url,
m.links, message.sticker.pack,
newTransactionParametersItem(m.transactionParameters.id, message.links,
m.transactionParameters.fromAddress, newTransactionParametersItem(message.transactionParameters.id,
m.transactionParameters.address, message.transactionParameters.fromAddress,
message.transactionParameters.address,
transactionContract, transactionContract,
transactionValue, transactionValue,
m.transactionParameters.transactionHash, message.transactionParameters.transactionHash,
m.transactionParameters.commandState, message.transactionParameters.commandState,
m.transactionParameters.signature), message.transactionParameters.signature),
m.mentionedUsersPks(), message.mentionedUsersPks(),
sender.details.trustStatus, sender.details.trustStatus,
sender.details.ensVerified, sender.details.ensVerified,
m.discordMessage, message.discordMessage,
resendError = "", resendError = "",
m.mentioned, message.mentioned,
m.quotedMessage.`from`, message.quotedMessage.`from`,
m.quotedMessage.text, message.quotedMessage.text,
self.controller.getRenderedText(m.quotedMessage.parsedText), self.controller.getRenderedText(message.quotedMessage.parsedText),
m.quotedMessage.contentType, message.quotedMessage.contentType,
m.quotedMessage.deleted, message.quotedMessage.deleted,
) )
for r in reactions: for r in reactions:
if(r.messageId == m.id): if(r.messageId == message.id):
var emojiIdAsEnum: EmojiId var emojiIdAsEnum: EmojiId
if(message_reaction_item.toEmojiIdAsEnum(r.emojiId, emojiIdAsEnum)): if(message_reaction_item.toEmojiIdAsEnum(r.emojiId, emojiIdAsEnum)):
let userWhoAddedThisReaction = self.controller.getContactById(r.`from`) let userWhoAddedThisReaction = self.controller.getContactById(r.`from`)
@ -258,16 +261,16 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
error "wrong emoji id found when loading messages", methodName="newMessagesLoaded" error "wrong emoji id found when loading messages", methodName="newMessagesLoaded"
for p in pinnedMessages: for p in pinnedMessages:
if(p.message.id == m.id): if(p.message.id == message.id):
item.pinned = true item.pinned = true
item.pinnedBy = p.pinnedBy item.pinnedBy = p.pinnedBy
if m.editedAt != 0: if message.editedAt != 0:
item.isEdited = true item.isEdited = true
if(m.contentType.ContentType == ContentType.Gap): if(message.contentType.ContentType == ContentType.Gap):
item.gapFrom = m.gapParameters.`from` item.gapFrom = message.gapParameters.`from`
item.gapTo = m.gapParameters.to item.gapTo = message.gapParameters.to
# messages are sorted from the most recent to the least recent one # messages are sorted from the most recent to the least recent one
viewItems.add(item) viewItems.add(item)
@ -320,6 +323,7 @@ method messageAdded*(self: Module, message: MessageDto) =
sender.details.added, sender.details.added,
message.outgoingStatus, message.outgoingStatus,
renderedMessageText, renderedMessageText,
message.text,
message.image, message.image,
message.containsContactMentions(), message.containsContactMentions(),
message.seen, message.seen,
@ -455,8 +459,8 @@ method getChatIcon*(self: Module): string =
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()
for m in chatDto.members: for member in chatDto.members:
if (m.id == singletonInstance.userProfile.getPubKey() and m.admin): if (member.id == singletonInstance.userProfile.getPubKey() and member.admin):
return true return true
return false return false
else: else:
@ -483,10 +487,10 @@ method updateContactDetails*(self: Module, contactId: string) =
item.senderTrustStatus = updatedContact.details.trustStatus item.senderTrustStatus = updatedContact.details.trustStatus
item.senderEnsVerified = updatedContact.details.ensVerified item.senderEnsVerified = updatedContact.details.ensVerified
if(item.messageContainsMentions): if(item.messageContainsMentions):
let (m, _, err) = self.controller.getMessageDetails(item.id) let (message, _, err) = self.controller.getMessageDetails(item.id)
if(err.len == 0): if(err.len == 0):
item.messageText = self.controller.getRenderedText(m.parsedText) item.messageText = self.controller.getRenderedText(message.parsedText)
item.messageContainsMentions = m.containsContactMentions() item.messageContainsMentions = message.containsContactMentions()
method deleteMessage*(self: Module, messageId: string) = method deleteMessage*(self: Module, messageId: string) =
self.controller.deleteMessage(messageId) self.controller.deleteMessage(messageId)
@ -582,60 +586,61 @@ method getMessages*(self: Module): seq[message_item.Item] =
return self.view.model().items return self.view.model().items
method getMessageById*(self: Module, messageId: string): message_item.Item = method getMessageById*(self: Module, messageId: string): message_item.Item =
let (m, _, err) = self.controller.getMessageDetails(messageId) let (message, _, err) = self.controller.getMessageDetails(messageId)
if(err.len == 0): if(err.len == 0):
let sender = self.controller.getContactDetails(m.`from`) let sender = self.controller.getContactDetails(message.`from`)
let renderedMessageText = self.controller.getRenderedText(m.parsedText) let renderedMessageText = self.controller.getRenderedText(message.parsedText)
var transactionContract = m.transactionParameters.contract var transactionContract = message.transactionParameters.contract
var transactionValue = m.transactionParameters.value var transactionValue = message.transactionParameters.value
var isCurrentUser = sender.isCurrentUser var isCurrentUser = sender.isCurrentUser
if(m.contentType.ContentType == ContentType.Transaction): if(message.contentType.ContentType == ContentType.Transaction):
(transactionContract, transactionValue) = self.controller.getTransactionDetails(m) (transactionContract, transactionValue) = self.controller.getTransactionDetails(message)
if m.transactionParameters.fromAddress != "": if message.transactionParameters.fromAddress != "":
isCurrentUser = self.currentUserWalletContainsAddress(m.transactionParameters.fromAddress) isCurrentUser = self.currentUserWalletContainsAddress(message.transactionParameters.fromAddress)
var item = initItem( var item = initItem(
m.id, message.id,
m.communityId, message.communityId,
m.responseTo, message.responseTo,
m.`from`, message.`from`,
sender.defaultDisplayName, sender.defaultDisplayName,
sender.optionalName, sender.optionalName,
sender.icon, sender.icon,
(isCurrentUser and m.contentType.ContentType != ContentType.DiscordMessage), (isCurrentUser and message.contentType.ContentType != ContentType.DiscordMessage),
sender.details.added, sender.details.added,
m.outgoingStatus, message.outgoingStatus,
renderedMessageText, renderedMessageText,
m.image, message.text,
m.containsContactMentions(), message.image,
m.seen, message.containsContactMentions(),
timestamp = m.whisperTimestamp, message.seen,
clock = m.clock, timestamp = message.whisperTimestamp,
m.contentType.ContentType, clock = message.clock,
m.messageType, message.contentType.ContentType,
m.contactRequestState, message.messageType,
sticker = m.sticker.url, message.contactRequestState,
m.sticker.pack, sticker = message.sticker.url,
m.links, message.sticker.pack,
newTransactionParametersItem(m.transactionParameters.id, message.links,
m.transactionParameters.fromAddress, newTransactionParametersItem(message.transactionParameters.id,
m.transactionParameters.address, message.transactionParameters.fromAddress,
message.transactionParameters.address,
transactionContract, transactionContract,
transactionValue, transactionValue,
m.transactionParameters.transactionHash, message.transactionParameters.transactionHash,
m.transactionParameters.commandState, message.transactionParameters.commandState,
m.transactionParameters.signature), message.transactionParameters.signature),
m.mentionedUsersPks(), message.mentionedUsersPks(),
sender.details.trustStatus, sender.details.trustStatus,
sender.details.ensVerified, sender.details.ensVerified,
m.discordMessage, message.discordMessage,
resendError = "", resendError = "",
m.mentioned, message.mentioned,
m.quotedMessage.`from`, message.quotedMessage.`from`,
m.quotedMessage.text, message.quotedMessage.text,
self.controller.getRenderedText(m.quotedMessage.parsedText), self.controller.getRenderedText(message.quotedMessage.parsedText),
m.quotedMessage.contentType, message.quotedMessage.contentType,
m.quotedMessage.deleted, message.quotedMessage.deleted,
) )
return item return item
return nil return nil

View File

@ -150,67 +150,68 @@ method currentUserWalletContainsAddress(self: Module, address: string): bool =
proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy: string, item: var pinned_msg_item.Item): proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy: string, item: var pinned_msg_item.Item):
bool = bool =
let (m, reactions, err) = self.controller.getMessageDetails(messageId) let (message, reactions, err) = self.controller.getMessageDetails(messageId)
if(err.len > 0): if(err.len > 0):
return false return false
let contactDetails = self.controller.getContactDetails(m.`from`) let contactDetails = self.controller.getContactDetails(message.`from`)
var transactionContract = m.transactionParameters.contract var transactionContract = message.transactionParameters.contract
var transactionValue = m.transactionParameters.value var transactionValue = message.transactionParameters.value
var isCurrentUser = contactDetails.isCurrentUser var isCurrentUser = contactDetails.isCurrentUser
if(m.contentType.ContentType == ContentType.Transaction): if(message.contentType.ContentType == ContentType.Transaction):
(transactionContract, transactionValue) = self.controller.getTransactionDetails(m) (transactionContract, transactionValue) = self.controller.getTransactionDetails(message)
if m.transactionParameters.fromAddress != "": if message.transactionParameters.fromAddress != "":
isCurrentUser = self.currentUserWalletContainsAddress(m.transactionParameters.fromAddress) isCurrentUser = self.currentUserWalletContainsAddress(message.transactionParameters.fromAddress)
item = pinned_msg_item.initItem( item = pinned_msg_item.initItem(
m.id, message.id,
m.communityId, message.communityId,
m.responseTo, message.responseTo,
m.`from`, message.`from`,
contactDetails.defaultDisplayName, contactDetails.defaultDisplayName,
contactDetails.optionalName, contactDetails.optionalName,
contactDetails.icon, contactDetails.icon,
isCurrentUser, isCurrentUser,
contactDetails.details.added, contactDetails.details.added,
m.outgoingStatus, message.outgoingStatus,
self.controller.getRenderedText(m.parsedText), self.controller.getRenderedText(message.parsedText),
m.image, message.text,
m.containsContactMentions(), message.image,
m.seen, message.containsContactMentions(),
timestamp = m.whisperTimestamp, message.seen,
clock = m.clock, timestamp = message.whisperTimestamp,
m.contentType.ContentType, clock = message.clock,
m.messageType, message.contentType.ContentType,
m.contactRequestState, message.messageType,
m.sticker.url, message.contactRequestState,
m.sticker.pack, message.sticker.url,
m.links, message.sticker.pack,
newTransactionParametersItem(m.transactionParameters.id, message.links,
m.transactionParameters.fromAddress, newTransactionParametersItem(message.transactionParameters.id,
m.transactionParameters.address, message.transactionParameters.fromAddress,
message.transactionParameters.address,
transactionContract, transactionContract,
transactionValue, transactionValue,
m.transactionParameters.transactionHash, message.transactionParameters.transactionHash,
m.transactionParameters.commandState, message.transactionParameters.commandState,
m.transactionParameters.signature), message.transactionParameters.signature),
m.mentionedUsersPks, message.mentionedUsersPks,
contactDetails.details.trustStatus, contactDetails.details.trustStatus,
contactDetails.details.ensVerified, contactDetails.details.ensVerified,
m.discordMessage, message.discordMessage,
resendError = "", resendError = "",
m.mentioned, message.mentioned,
m.quotedMessage.`from`, message.quotedMessage.`from`,
m.quotedMessage.text, message.quotedMessage.text,
self.controller.getRenderedText(m.quotedMessage.parsedText), self.controller.getRenderedText(message.quotedMessage.parsedText),
m.quotedMessage.contentType, message.quotedMessage.contentType,
m.quotedMessage.deleted, message.quotedMessage.deleted,
) )
item.pinned = true item.pinned = true
item.pinnedBy = actionInitiatedBy item.pinnedBy = actionInitiatedBy
for r in reactions: for r in reactions:
if(r.messageId == m.id): if(r.messageId == message.id):
var emojiIdAsEnum: pinned_msg_reaction_item.EmojiId var emojiIdAsEnum: pinned_msg_reaction_item.EmojiId
if(pinned_msg_reaction_item.toEmojiIdAsEnum(r.emojiId, emojiIdAsEnum)): if(pinned_msg_reaction_item.toEmojiIdAsEnum(r.emojiId, emojiIdAsEnum)):
let userWhoAddedThisReaction = self.controller.getContactById(r.`from`) let userWhoAddedThisReaction = self.controller.getContactById(r.`from`)
@ -318,8 +319,8 @@ method getCurrentFleet*(self: Module): string =
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()
for m in chatDto.members: for member in chatDto.members:
if (m.id == singletonInstance.userProfile.getPubKey() and m.admin): if (member.id == singletonInstance.userProfile.getPubKey() and member.admin):
return true return true
return false return false
else: else:
@ -336,10 +337,10 @@ method onContactDetailsUpdated*(self: Module, contactId: string) =
item.senderIcon = updatedContact.icon item.senderIcon = updatedContact.icon
item.senderTrustStatus = updatedContact.details.trustStatus item.senderTrustStatus = updatedContact.details.trustStatus
if(item.messageContainsMentions): if(item.messageContainsMentions):
let (m, _, err) = self.controller.getMessageDetails(item.id) let (message, _, err) = self.controller.getMessageDetails(item.id)
if(err.len == 0): if(err.len == 0):
item.messageText = self.controller.getRenderedText(m.parsedText) item.messageText = self.controller.getRenderedText(message.parsedText)
item.messageContainsMentions = m.containsContactMentions() item.messageContainsMentions = message.containsContactMentions()
if(self.controller.getMyChatId() == contactId): if(self.controller.getMyChatId() == contactId):
self.view.updateChatDetailsNameAndIcon(updatedContact.defaultDisplayName, updatedContact.icon) self.view.updateChatDetailsNameAndIcon(updatedContact.defaultDisplayName, updatedContact.icon)

View File

@ -20,6 +20,7 @@ type
seen: bool seen: bool
outgoingStatus: string outgoingStatus: string
messageText: string messageText: string
unparsedText: string
messageImage: string messageImage: string
messageContainsMentions: bool messageContainsMentions: bool
sticker: string sticker: string
@ -64,6 +65,7 @@ proc initItem*(
senderIsAdded: bool, senderIsAdded: bool,
outgoingStatus, outgoingStatus,
text, text,
unparsedText,
image: string, image: string,
messageContainsMentions, messageContainsMentions,
seen: bool, seen: bool,
@ -100,7 +102,8 @@ proc initItem*(
result.senderIcon = senderIcon result.senderIcon = senderIcon
result.seen = seen result.seen = seen
result.outgoingStatus = outgoingStatus result.outgoingStatus = outgoingStatus
result.messageText = if ContentType.Image == contentType: "" else: text result.messageText = if contentType == ContentType.Image : "" else: text
result.unparsedText = if contentType == ContentType.Image : "" else: unparsedText
result.messageImage = image result.messageImage = image
result.messageContainsMentions = messageContainsMentions result.messageContainsMentions = messageContainsMentions
result.timestamp = timestamp result.timestamp = timestamp
@ -131,9 +134,10 @@ proc initItem*(
result.quotedMessageDeleted = quotedMessageDeleted result.quotedMessageDeleted = quotedMessageDeleted
result.quotedMessageFromIterator = 0 result.quotedMessageFromIterator = 0
if ContentType.DiscordMessage == contentType: if contentType == ContentType.DiscordMessage :
if result.messageText == "": if result.messageText == "":
result.messageText = discordMessage.content result.messageText = discordMessage.content
result.unparsedText = discordMessage.content
result.senderId = discordMessage.author.id result.senderId = discordMessage.author.id
result.senderDisplayName = discordMessage.author.name result.senderDisplayName = discordMessage.author.name
result.senderIcon = discordMessage.author.localUrl result.senderIcon = discordMessage.author.localUrl
@ -162,6 +166,7 @@ proc initNewMessagesMarkerItem*(clock, timestamp: int64): Item =
senderIsAdded = false, senderIsAdded = false,
outgoingStatus = "", outgoingStatus = "",
text = "", text = "",
unparsedText = "",
image = "", image = "",
messageContainsMentions = false, messageContainsMentions = false,
seen = true, seen = true,
@ -201,6 +206,7 @@ proc `$`*(self: Item): string =
outgoingStatus:{$self.outgoingStatus}, outgoingStatus:{$self.outgoingStatus},
resendError:{$self.resendError}, resendError:{$self.resendError},
messageText:{self.messageText}, messageText:{self.messageText},
unparsedText:{self.unparsedText},
messageContainsMentions:{self.messageContainsMentions}, messageContainsMentions:{self.messageContainsMentions},
timestamp:{$self.timestamp}, timestamp:{$self.timestamp},
contentType:{$self.contentType.int}, contentType:{$self.contentType.int},
@ -287,6 +293,12 @@ proc messageText*(self: Item): string {.inline.} =
proc `messageText=`*(self: Item, value: string) {.inline.} = proc `messageText=`*(self: Item, value: string) {.inline.} =
self.messageText = value self.messageText = value
proc unparsedText*(self: Item): string {.inline.} =
self.unparsedText
proc `unparsedText=`*(self: Item, value: string) {.inline.} =
self.unparsedText = value
proc messageImage*(self: Item): string {.inline.} = proc messageImage*(self: Item): string {.inline.} =
self.messageImage self.messageImage
@ -383,6 +395,7 @@ proc toJsonNode*(self: Item): JsonNode =
"seen": self.seen, "seen": self.seen,
"outgoingStatus": self.outgoingStatus, "outgoingStatus": self.outgoingStatus,
"messageText": self.messageText, "messageText": self.messageText,
"unparsedText": self.unparsedText,
"messageImage": self.messageImage, "messageImage": self.messageImage,
"messageContainsMentions": self.messageContainsMentions, "messageContainsMentions": self.messageContainsMentions,
"sticker": self.sticker, "sticker": self.sticker,

View File

@ -97,6 +97,10 @@ QtObject:
QtProperty[string] messageText: QtProperty[string] messageText:
read = messageText read = messageText
proc unparsedText*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.unparsedText
QtProperty[string] unparsedText:
read = unparsedText
proc messageImage*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.messageImage proc messageImage*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.messageImage
QtProperty[string] messageImage: QtProperty[string] messageImage:
read = messageImage read = messageImage

View File

@ -21,6 +21,7 @@ type
Seen Seen
OutgoingStatus OutgoingStatus
MessageText MessageText
UnparsedText
MessageImage MessageImage
MessageContainsMentions # Actually we don't need to exposed this to qml since we only used it as an improved way to MessageContainsMentions # Actually we don't need to exposed this to qml since we only used it as an improved way to
# check whether we need to update mentioned contact name or not. # check whether we need to update mentioned contact name or not.
@ -114,6 +115,7 @@ QtObject:
ModelRole.ResendError.int:"resendError", ModelRole.ResendError.int:"resendError",
ModelRole.Mentioned.int:"mentioned", ModelRole.Mentioned.int:"mentioned",
ModelRole.MessageText.int:"messageText", ModelRole.MessageText.int:"messageText",
ModelRole.UnparsedText.int:"unparsedText",
ModelRole.MessageImage.int:"messageImage", ModelRole.MessageImage.int:"messageImage",
ModelRole.MessageContainsMentions.int:"messageContainsMentions", ModelRole.MessageContainsMentions.int:"messageContainsMentions",
ModelRole.Timestamp.int:"timestamp", ModelRole.Timestamp.int:"timestamp",
@ -205,6 +207,8 @@ QtObject:
result = newQVariant(item.quotedMessageDeleted) result = newQVariant(item.quotedMessageDeleted)
of ModelRole.MessageText: of ModelRole.MessageText:
result = newQVariant(item.messageText) result = newQVariant(item.messageText)
of ModelRole.UnparsedText:
result = newQVariant(item.unparsedText)
of ModelRole.MessageImage: of ModelRole.MessageImage:
result = newQVariant(item.messageImage) result = newQVariant(item.messageImage)
of ModelRole.MessageContainsMentions: of ModelRole.MessageContainsMentions:
@ -441,7 +445,7 @@ QtObject:
if(self.items[i].pinnedBy == contactId): if(self.items[i].pinnedBy == contactId):
roles.add(ModelRole.PinnedBy.int) roles.add(ModelRole.PinnedBy.int)
if(self.items[i].messageContainsMentions): if(self.items[i].messageContainsMentions):
roles.add(@[ModelRole.MessageText.int, ModelRole.MessageContainsMentions.int]) roles.add(@[ModelRole.MessageText.int, ModelRole.UnparsedText.int, ModelRole.MessageContainsMentions.int])
if (self.items[i].quotedMessageFrom == contactId): if (self.items[i].quotedMessageFrom == contactId):
# If there is a quoted message whom the author changed, increase the iterator to force # If there is a quoted message whom the author changed, increase the iterator to force
@ -496,6 +500,7 @@ QtObject:
let index = self.createIndex(ind, 0, nil) let index = self.createIndex(ind, 0, nil)
self.dataChanged(index, index, @[ self.dataChanged(index, index, @[
ModelRole.MessageText.int, ModelRole.MessageText.int,
ModelRole.UnparsedText.int,
ModelRole.MessageContainsMentions.int, ModelRole.MessageContainsMentions.int,
ModelRole.IsEdited.int, ModelRole.IsEdited.int,
ModelRole.Links.int, ModelRole.Links.int,

View File

@ -155,6 +155,8 @@ QtObject {
property var stickersModuleInst: stickersModule property var stickersModuleInst: stickersModule
property bool isDebugEnabled: advancedModule ? advancedModule.isDebugEnabled : false
property var stickersStore: StickersStore { property var stickersStore: StickersStore {
stickersModule: stickersModuleInst stickersModule: stickersModuleInst
} }

View File

@ -250,6 +250,7 @@ Item {
senderTrustStatus: model.senderTrustStatus senderTrustStatus: model.senderTrustStatus
amISender: model.amISender amISender: model.amISender
messageText: model.messageText messageText: model.messageText
unparsedText: model.unparsedText
messageImage: model.messageImage messageImage: model.messageImage
messageTimestamp: model.timestamp messageTimestamp: model.timestamp
messageOutgoingStatus: model.outgoingStatus messageOutgoingStatus: model.outgoingStatus

View File

@ -31,6 +31,7 @@ StatusMenu {
property int chatType: Constants.chatType.publicChat property int chatType: Constants.chatType.publicChat
property string messageId: "" property string messageId: ""
property string unparsedText: ""
property string messageSenderId: "" property string messageSenderId: ""
property int messageContentType: Constants.messageContentType.unknownContentType property int messageContentType: Constants.messageContentType.unknownContentType
property string imageSource: "" property string imageSource: ""
@ -39,7 +40,7 @@ StatusMenu {
property bool isRightClickOnImage: false property bool isRightClickOnImage: false
property bool pinnedPopup: false property bool pinnedPopup: false
property bool pinMessageAllowedForMembers: false property bool pinMessageAllowedForMembers: false
property bool isDebugEnabled: false property bool isDebugEnabled: store.isDebugEnabled
property bool isEmoji: false property bool isEmoji: false
property bool isSticker: false property bool isSticker: false
property bool hideEmojiPicker: true property bool hideEmojiPicker: true
@ -127,11 +128,6 @@ StatusMenu {
} }
root.emojiReactionsReactedByUser = newEmojiReactions; root.emojiReactionsReactedByUser = newEmojiReactions;
/* // copy link feature not ready yet
const numLinkUrls = root.linkUrls.split(" ").length
copyLinkMenu.enabled = numLinkUrls > 1
copyLinkAction.enabled = !!root.linkUrls && numLinkUrls === 1 && !isEmoji && !root.isProfile
*/
popup() popup()
} }
@ -361,13 +357,24 @@ StatusMenu {
!root.isRightClickOnImage !root.isRightClickOnImage
} }
StatusAction {
id: copyMessageMenuItem
text: qsTr("Copy message")
icon.name: "copy"
onTriggered: {
root.store.copyToClipboard(root.unparsedText)
close()
}
enabled: root.messageContentType === Constants.messageContentType.messageType
}
StatusAction { StatusAction {
id: copyMessageIdAction id: copyMessageIdAction
text: qsTr("Copy Message Id") text: qsTr("Copy Message Id")
icon.name: "chat" icon.name: "copy"
enabled: root.isDebugEnabled && !pinnedPopup enabled: root.isDebugEnabled && !pinnedPopup
onTriggered: { onTriggered: {
root.store.copyToClipboard(SelectedMessage.messageId) root.store.copyToClipboard(root.messageId)
close() close()
} }
} }
@ -425,6 +432,7 @@ StatusMenu {
(viewProfileAction.enabled || (viewProfileAction.enabled ||
sendMessageMenuItem.enabled || sendMessageMenuItem.enabled ||
replyToMenuItem.enabled || replyToMenuItem.enabled ||
copyMessageMenuItem.enabled ||
editMessageAction.enabled || editMessageAction.enabled ||
pinAction.enabled) pinAction.enabled)
} }

View File

@ -48,6 +48,7 @@ Loader {
property bool senderIsAdded: false property bool senderIsAdded: false
property int senderTrustStatus: Constants.trustStatus.unknown property int senderTrustStatus: Constants.trustStatus.unknown
property string messageText: "" property string messageText: ""
property string unparsedText: ""
property string messageImage: "" property string messageImage: ""
property double messageTimestamp: 0 // We use double, because QML's int is too small property double messageTimestamp: 0 // We use double, because QML's int is too small
property string messageOutgoingStatus: "" property string messageOutgoingStatus: ""
@ -141,6 +142,7 @@ Loader {
messageContextMenu.chatType = messageStore.getChatType() messageContextMenu.chatType = messageStore.getChatType()
messageContextMenu.messageId = root.messageId messageContextMenu.messageId = root.messageId
messageContextMenu.unparsedText = root.unparsedText
messageContextMenu.messageSenderId = root.senderId messageContextMenu.messageSenderId = root.senderId
messageContextMenu.messageContentType = root.messageContentType messageContextMenu.messageContentType = root.messageContentType
messageContextMenu.pinnedMessage = root.pinnedMessage messageContextMenu.pinnedMessage = root.pinnedMessage