mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-09 13:56:10 +00:00
feat: edit messages
This commit is contained in:
parent
77e501c478
commit
c7750da267
@ -42,6 +42,8 @@ type
|
||||
PinnedBy = UserRole + 31
|
||||
GapFrom = UserRole + 32
|
||||
GapTo = UserRole + 33
|
||||
Replace = UserRole + 34
|
||||
IsEdited = UserRole + 35
|
||||
|
||||
QtObject:
|
||||
type
|
||||
@ -50,11 +52,13 @@ QtObject:
|
||||
status: Status
|
||||
id*: string
|
||||
messageIndex: Table[string, int]
|
||||
isEdited*: Table[string, bool]
|
||||
messageReactions*: Table[string, string]
|
||||
timedoutMessages: HashSet[string]
|
||||
|
||||
proc delete(self: ChatMessageList) =
|
||||
self.messages = @[]
|
||||
self.isEdited = initTable[string, bool]()
|
||||
self.messageIndex = initTable[string, int]()
|
||||
self.timedoutMessages = initHashSet[string]()
|
||||
self.QAbstractListModel.delete
|
||||
@ -85,9 +89,17 @@ QtObject:
|
||||
|
||||
result.messageIndex = initTable[string, int]()
|
||||
result.timedoutMessages = initHashSet[string]()
|
||||
result.isEdited = initTable[string, bool]()
|
||||
result.status = status
|
||||
result.setup
|
||||
|
||||
|
||||
proc hasMessage*(self: ChatMessageList, messageId: string): bool =
|
||||
return self.messageIndex.hasKey(messageId)
|
||||
|
||||
proc getMessage*(self: ChatMessageList, messageId: string): Message =
|
||||
return self.messages[self.messageIndex[messageId]]
|
||||
|
||||
proc deleteMessage*(self: ChatMessageList, messageId: string) =
|
||||
if not self.messageIndex.hasKey(messageId): return
|
||||
let messageIndex = self.messageIndex[messageId]
|
||||
@ -95,6 +107,9 @@ QtObject:
|
||||
self.messages.delete(messageIndex)
|
||||
self.messageIndex.del(messageId)
|
||||
self.messageReactions.del(messageId)
|
||||
# update indexes
|
||||
for i in countup(0, self.messages.len - 1):
|
||||
self.messageIndex[self.messages[i].id] = i
|
||||
self.endRemoveRows()
|
||||
|
||||
proc deleteMessagesByChatId*(self: ChatMessageList, chatId: string) =
|
||||
@ -102,6 +117,14 @@ QtObject:
|
||||
for message in messages:
|
||||
self.deleteMessage(message.id)
|
||||
|
||||
proc replaceMessage*(self: ChatMessageList, message: Message) =
|
||||
let msgIdx = self.messageIndex[message.id]
|
||||
let topLeft = self.createIndex(msgIdx, 0, nil)
|
||||
let bottomRight = self.createIndex(msgIdx, 0, nil)
|
||||
self.messages[msgIdx].parsedText = message.parsedText
|
||||
self.messages[msgIdx].text = message.text
|
||||
self.dataChanged(topLeft, bottomRight, @[ChatMessageRoles.Message.int, ChatMessageRoles.PlainText.int, ChatMessageRoles.IsEdited.int])
|
||||
|
||||
proc resetTimeOut*(self: ChatMessageList, messageId: string) =
|
||||
if not self.messageIndex.hasKey(messageId): return
|
||||
let msgIdx = self.messageIndex[messageId]
|
||||
@ -145,6 +168,7 @@ QtObject:
|
||||
return
|
||||
let message = self.messages[index.row]
|
||||
let chatMessageRole = role.ChatMessageRoles
|
||||
let isEdited = if self.isEdited.hasKey(message.id): self.isEdited[message.id] else: false
|
||||
case chatMessageRole:
|
||||
of ChatMessageRoles.UserName: result = newQVariant(message.userName)
|
||||
of ChatMessageRoles.Message: result = newQVariant(renderBlock(message, self.status.chat.contacts))
|
||||
@ -188,6 +212,8 @@ QtObject:
|
||||
of ChatMessageRoles.LocalName: result = newQVariant(message.localName)
|
||||
of ChatMessageRoles.GapFrom: result = newQVariant(message.gapFrom)
|
||||
of ChatMessageRoles.GapTo: result = newQVariant(message.gapTo)
|
||||
of ChatMessageRoles.Replace: result = newQVariant(message.replace)
|
||||
of ChatMessageRoles.IsEdited: result = newQVariant(isEdited)
|
||||
|
||||
method roleNames(self: ChatMessageList): Table[int, string] =
|
||||
{
|
||||
@ -222,7 +248,9 @@ QtObject:
|
||||
ChatMessageRoles.LocalName.int:"localName",
|
||||
ChatMessageRoles.StickerPackId.int:"stickerPackId",
|
||||
ChatMessageRoles.GapFrom.int:"gapFrom",
|
||||
ChatMessageRoles.GapTo.int:"gapTo"
|
||||
ChatMessageRoles.GapTo.int:"gapTo",
|
||||
ChatMessageRoles.Replace.int:"replaces",
|
||||
ChatMessageRoles.IsEdited.int:"isEdited"
|
||||
}.toTable
|
||||
|
||||
proc getMessageIndex*(self: ChatMessageList, messageId: string): int {.slot.} =
|
||||
@ -246,10 +274,17 @@ QtObject:
|
||||
of "image": result = $(message.image)
|
||||
of "contentType": result = $(message.contentType.int)
|
||||
of "sticker": result = $(message.stickerHash.decodeContentHash())
|
||||
of "isEdited": result = if self.isEdited.hasKey(message.id): $self.isEdited[message.id] else: $false
|
||||
else: result = ("")
|
||||
|
||||
proc add*(self: ChatMessageList, message: Message) =
|
||||
if self.messageIndex.hasKey(message.id): return # duplicated msg
|
||||
if self.messageIndex.hasKey(message.id) and message.editedAt == "0": return # duplicated msg
|
||||
|
||||
if message.editedAt != "0":
|
||||
self.isEdited[message.id] = true
|
||||
if self.messageIndex.hasKey(message.id):
|
||||
self.replaceMessage(message)
|
||||
return
|
||||
|
||||
self.beginInsertRows(newQModelIndex(), self.messages.len, self.messages.len)
|
||||
self.messageIndex[message.id] = self.messages.len
|
||||
|
@ -118,7 +118,9 @@ QtObject:
|
||||
|
||||
result = updatedMessage
|
||||
|
||||
proc sendMessage*(self: MessageView, message: string, replyTo: string, contentType: int = ContentType.Message.int, isStatusUpdate: bool = false, contactsString: string = "") {.slot.} =
|
||||
proc hideMessage(self: MessageView, mId: string) {.signal.}
|
||||
|
||||
proc sendOrEditMessage*(self: MessageView, message: string, replyTo: string, contentType: int = ContentType.Message.int, isStatusUpdate: bool = false, contactsString: string = "", isEdit: bool = false, messageId: string = "") {.slot.} =
|
||||
let aliasPattern = re(r"(@[A-z][a-z]+ [A-z][a-z]* [A-z][a-z]*)", flags = {reStudy, reIgnoreCase})
|
||||
let ensPattern = re(r"(@\w+(?=(\.stateofus)?\.eth))", flags = {reStudy, reIgnoreCase})
|
||||
let namePattern = re(r"(@\w+)", flags = {reStudy, reIgnoreCase})
|
||||
@ -149,7 +151,13 @@ QtObject:
|
||||
if isStatusUpdate:
|
||||
channelId = "@" & self.pubKey
|
||||
|
||||
if not isEdit:
|
||||
self.status.chat.sendMessage(channelId, m, replyTo, contentType)
|
||||
else:
|
||||
self.status.chat.editMessage(messageId, m)
|
||||
|
||||
proc sendMessage*(self: MessageView, message: string, replyTo: string, contentType: int = ContentType.Message.int, isStatusUpdate: bool = false, contactsString: string = "") {.slot.} =
|
||||
self.sendOrEditMessage(message, replyTo, contentType, isStatusUpdate, contactsString, false, "")
|
||||
|
||||
proc verifyMessageSent*(self: MessageView, data: string) {.slot.} =
|
||||
let messageData = data.parseJson
|
||||
@ -164,6 +172,12 @@ QtObject:
|
||||
|
||||
proc sendingMessageFailed*(self: MessageView) {.signal.}
|
||||
|
||||
proc messageEdited(self: MessageView, editedMessageId: string, editedMessageContent: string) {.signal.}
|
||||
|
||||
proc editMessage*(self: MessageView, messageId: string, originalMessageId: string, message: string, contactsString: string = "") {.slot.} =
|
||||
self.sendOrEditMessage(message, "", ContentType.Message.int, false, contactsString, true, originalMessageId)
|
||||
self.messageEdited(originalMessageId, message)
|
||||
|
||||
proc messagePushed*(self: MessageView, messageIndex: int) {.signal.}
|
||||
proc newMessagePushed*(self: MessageView) {.signal.}
|
||||
|
||||
@ -359,6 +373,7 @@ QtObject:
|
||||
|
||||
proc deleteMessage*(self: MessageView, channelId: string, messageId: string) =
|
||||
self.messageList[channelId].deleteMessage(messageId)
|
||||
self.hideMessage(messageId)
|
||||
|
||||
proc removeMessagesByUserId(self: MessageView, publicKey: string) {.slot.} =
|
||||
for k in self.messageList.keys:
|
||||
|
@ -261,7 +261,7 @@ proc setActiveChannel*(self: ChatModel, chatId: string) =
|
||||
proc processMessageUpdateAfterSend(self: ChatModel, response: string, forceActiveChat: bool = false): (seq[Chat], seq[Message]) =
|
||||
result = self.processChatUpdate(parseJson(response))
|
||||
var (chats, messages) = result
|
||||
if chats.len == 0 or messages.len == 0:
|
||||
if chats.len == 0 and messages.len == 0:
|
||||
self.events.emit("sendingMessageFailed", MessageArgs())
|
||||
else:
|
||||
if (forceActiveChat):
|
||||
@ -274,6 +274,10 @@ proc sendMessage*(self: ChatModel, chatId: string, msg: string, replyTo: string
|
||||
var response = status_chat.sendChatMessage(chatId, msg, replyTo, contentType, communityId)
|
||||
discard self.processMessageUpdateAfterSend(response, forceActiveChat)
|
||||
|
||||
proc editMessage*(self: ChatModel, messageId: string, msg: string) =
|
||||
var response = status_chat.editMessage(messageId, msg)
|
||||
discard self.processMessageUpdateAfterSend(response, false)
|
||||
|
||||
proc sendImage*(self: ChatModel, chatId: string, image: string) =
|
||||
var response = status_chat.sendImageMessage(chatId, image)
|
||||
discard self.processMessageUpdateAfterSend(response)
|
||||
|
@ -14,6 +14,7 @@ type ContentType* {.pure.} = enum
|
||||
Audio = 8
|
||||
Community = 9
|
||||
Gap = 10
|
||||
Edit = 11
|
||||
|
||||
type TextItem* = object
|
||||
textType*: string
|
||||
@ -58,6 +59,7 @@ type Message* = object
|
||||
stickerPackId*: int
|
||||
text*: string
|
||||
timestamp*: string
|
||||
editedAt*: string
|
||||
whisperTimestamp*: string
|
||||
isCurrentUser*: bool
|
||||
stickerHash*: string
|
||||
|
@ -119,6 +119,14 @@ proc parseReactionsResponse*(chatId: string, rpcResult: JsonNode): (string, seq[
|
||||
reactions.add(jsonMsg.toReaction)
|
||||
return (rpcResult{"cursor"}.getStr, reactions)
|
||||
|
||||
proc editMessage*(messageId: string, msg: string): string =
|
||||
callPrivateRPC("editMessage".prefix, %* [
|
||||
{
|
||||
"id": messageId,
|
||||
"text": msg
|
||||
}
|
||||
])
|
||||
|
||||
proc rpcReactions*(chatId: string, cursorVal: JsonNode, limit: int, success: var bool): string =
|
||||
success = true
|
||||
try:
|
||||
@ -238,6 +246,9 @@ proc leaveGroupChat*(chatId: string): string =
|
||||
proc clearChatHistory*(chatId: string): string =
|
||||
callPrivateRPC("deleteMessagesByChatID".prefix, %* [chatId])
|
||||
|
||||
proc deleteMessage*(messageId: string): string =
|
||||
callPrivateRPC("deleteMessage".prefix, %* [messageId])
|
||||
|
||||
proc renameGroup*(chatId: string, newName: string): string =
|
||||
callPrivateRPC("changeGroupChatName".prefix, %* [nil, chatId, newName])
|
||||
|
||||
|
@ -301,6 +301,7 @@ proc toMessage*(jsonMsg: JsonNode, pk: string): Message =
|
||||
localChatId: jsonMsg{"localChatId"}.getStr,
|
||||
messageType: jsonMsg{"messageType"}.getStr,
|
||||
replace: jsonMsg{"replace"}.getStr,
|
||||
editedAt: $jsonMsg{"editedAt"}.getInt,
|
||||
responseTo: jsonMsg{"responseTo"}.getStr,
|
||||
rtl: jsonMsg{"rtl"}.getBool,
|
||||
seen: jsonMsg{"seen"}.getBool,
|
||||
|
@ -317,6 +317,8 @@ ScrollView {
|
||||
sticker: model.sticker
|
||||
contentType: model.contentType
|
||||
outgoingStatus: model.outgoingStatus
|
||||
replaces: model.replaces
|
||||
isEdited: model.isEdited
|
||||
responseTo: model.responseTo
|
||||
authorCurrentMsg: msgDelegate.ListView.section
|
||||
// The previous message is actually the nextSection since we reversed the list order
|
||||
|
@ -38,6 +38,9 @@ Item {
|
||||
property int stickerPackId: -1
|
||||
property int gapFrom: 0
|
||||
property int gapTo: 0
|
||||
property bool isEdit: false
|
||||
property string replaces: ""
|
||||
property bool isEdited: false
|
||||
|
||||
z: {
|
||||
if (typeof chatLogView === "undefined") {
|
||||
@ -76,7 +79,7 @@ Item {
|
||||
property bool isAudio: contentType === Constants.audioType
|
||||
property bool isStatusMessage: contentType === Constants.systemMessagePrivateGroupType
|
||||
property bool isSticker: contentType === Constants.stickerType
|
||||
property bool isText: contentType === Constants.messageType
|
||||
property bool isText: contentType === Constants.messageType || contentType === Constants.editType
|
||||
property bool isMessage: isEmoji || isImage || isSticker || isText || isAudio
|
||||
|| contentType === Constants.communityInviteType || contentType === Constants.transactionType
|
||||
|
||||
@ -87,6 +90,7 @@ Item {
|
||||
property string repliedMessageAuthor: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "userName") : "";
|
||||
property string repliedMessageAuthorPubkey: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "publicKey") : "";
|
||||
property bool repliedMessageAuthorIsCurrentUser: replyMessageIndex > -1 ? repliedMessageAuthorPubkey === profileModel.profile.pubKey : "";
|
||||
property bool repliedMessageIsEdited: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "isEdited") === "true" : false;
|
||||
property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "message") : "";
|
||||
property int repliedMessageType: replyMessageIndex > -1 ? parseInt(chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "contentType")) : 0;
|
||||
property string repliedMessageImage: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "image") : "";
|
||||
@ -166,6 +170,17 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.messageView
|
||||
onHideMessage: {
|
||||
// This hack is used because message_list deleteMessage sometimes does not remove the messages (there might be an issue with the delegate model)
|
||||
if(mId === messageId){
|
||||
root.visible = 0;
|
||||
root.height = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id: root
|
||||
width: parent.width
|
||||
anchors.right: !isCurrentUser ? undefined : parent.right
|
||||
|
@ -101,6 +101,28 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: editBtn
|
||||
active: isText && !isEdit && isCurrentUser
|
||||
sourceComponent: StatusIconButton {
|
||||
id: btn
|
||||
icon.name: "edit-message"
|
||||
width: 32
|
||||
height: 32
|
||||
onClicked: {
|
||||
isEdit = true
|
||||
}
|
||||
onHoveredChanged: {
|
||||
buttonsContainer.hoverChanged(btn.hovered)
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: btn.hovered
|
||||
text: qsTr("Edit")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusIconButton {
|
||||
id: otherBtn
|
||||
icon.name: "dots-icon"
|
||||
|
@ -91,6 +91,15 @@ Loader {
|
||||
profileImage: repliedMessageUserImage
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.messageView
|
||||
onMessageEdited: {
|
||||
if (responseTo === editedMessageId){
|
||||
lblReplyMessage.text = Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(editedMessageContent + Constants.editLabel), Emoji.size.small), isCurrentUser, appSettings.useCompactMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledTextEdit {
|
||||
id: lblReplyAuthor
|
||||
text: repliedMessageAuthor
|
||||
@ -141,7 +150,14 @@ Loader {
|
||||
Component.onCompleted: textFieldImplicitWidth = implicitWidth
|
||||
anchors.top: lblReplyAuthor.bottom
|
||||
anchors.topMargin: nameMargin
|
||||
text: Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent), Emoji.size.small), isCurrentUser, appSettings.useCompactMode)
|
||||
text: {
|
||||
if (repliedMessageIsEdited){
|
||||
let index = repliedMessageContent.length - 4
|
||||
return Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent.slice(0, index) + Constants.editLabel + repliedMessageContent.slice(index)), Emoji.size.small), isCurrentUser, appSettings.useCompactMode)
|
||||
} else {
|
||||
return Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent), Emoji.size.small), isCurrentUser, appSettings.useCompactMode)
|
||||
}
|
||||
}
|
||||
textFormat: Text.RichText
|
||||
color: root.elementsColor
|
||||
readOnly: true
|
||||
|
@ -11,7 +11,7 @@ Item {
|
||||
property alias textField: chatText
|
||||
|
||||
id: root
|
||||
visible: contentType === Constants.messageType || isEmoji
|
||||
visible: isText || isEmoji
|
||||
z: 51
|
||||
|
||||
implicitHeight: visible ? (showMoreLoader.active ? childrenRect.height - 10 : chatText.height) : 0
|
||||
@ -87,6 +87,10 @@ Item {
|
||||
if(isEmoji) {
|
||||
return Emoji.parse(msg, Emoji.size.middle);
|
||||
} else {
|
||||
if(isEdited){
|
||||
let index = msg.length - 4
|
||||
return Utils.getMessageWithStyle(Emoji.parse(msg.slice(0, index) + Constants.editLabel + msg.slice(index)), appSettings.useCompactMode, isCurrentUser, hoveredLink)
|
||||
}
|
||||
return Utils.getMessageWithStyle(Emoji.parse(msg), appSettings.useCompactMode, isCurrentUser, hoveredLink)
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ Item {
|
||||
|
||||
ChatButtons {
|
||||
contentType: root.contentType
|
||||
parentIsHovered: root.isHovered
|
||||
parentIsHovered: !isEdit && root.isHovered
|
||||
onHoverChanged: hovered && setHovered(messageId, hovered)
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 20
|
||||
@ -73,9 +73,14 @@ Item {
|
||||
+ (emojiReactionLoader.active ? emojiReactionLoader.height: 0)
|
||||
+ (retry.visible && !chatTime.visible ? Style.current.smallPadding : 0)
|
||||
+ (pinnedRectangleLoader.active ? Style.current.smallPadding : 0)
|
||||
+ (isEdit ? 25 : 0)
|
||||
width: parent.width
|
||||
|
||||
color: {
|
||||
if (isEdit) {
|
||||
return Style.current.backgroundHoverLight
|
||||
}
|
||||
|
||||
if (activityCenterMessage) {
|
||||
return read ? Style.current.transparent : Utils.setColorAlpha(Style.current.blue, 0.1)
|
||||
}
|
||||
@ -157,7 +162,7 @@ Item {
|
||||
|
||||
UsernameLabel {
|
||||
id: chatName
|
||||
visible: isMessage && headerRepeatCondition
|
||||
visible: !isEdit && isMessage && headerRepeatCondition
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
anchors.top: chatImage.top
|
||||
anchors.left: chatImage.right
|
||||
@ -165,13 +170,68 @@ Item {
|
||||
|
||||
ChatTime {
|
||||
id: chatTime
|
||||
visible: headerRepeatCondition
|
||||
visible: !isEdit && headerRepeatCondition
|
||||
anchors.verticalCenter: chatName.verticalCenter
|
||||
anchors.left: chatName.right
|
||||
anchors.leftMargin: 4
|
||||
color: Style.current.secondaryText
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: editMessageLoader
|
||||
active: isEdit
|
||||
anchors.top: chatReply.active ? chatReply.bottom : parent.top
|
||||
anchors.left: chatImage.right
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: root.chatHorizontalPadding
|
||||
height: (item !== null && typeof(item)!== 'undefined')? item.height: 0
|
||||
sourceComponent: Item {
|
||||
id: editText
|
||||
height: childrenRect.height
|
||||
StatusChatInput {
|
||||
Component.onCompleted: {
|
||||
textInput.forceActiveFocus();
|
||||
textInput.cursorPosition = textInput.length
|
||||
}
|
||||
id: editTextInput
|
||||
chatInputPlaceholder: qsTrId("type-a-message-")
|
||||
chatType: chatsModel.channelView.activeChannel.chatType
|
||||
isEdit: true
|
||||
textInput.text: Emoji.parse(message.replace(/(<a href="\/\/0x[0-9A-Fa-f]+" class="mention">)/g, "$1@"))
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
id: cancelBtn
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.halfPadding
|
||||
anchors.top: editTextInput.bottom
|
||||
bgColor: Style.current.transparent
|
||||
text: qsTr("Cancel")
|
||||
onClicked: {
|
||||
isEdit = false
|
||||
editTextInput.textInput.text = Emoji.parse(message)
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
id: saveBtn
|
||||
anchors.left: cancelBtn.right
|
||||
anchors.leftMargin: Style.current.halfPadding
|
||||
anchors.top: editTextInput.bottom
|
||||
text: qsTr("Save")
|
||||
onClicked: {
|
||||
let msg = chatsModel.plainText(Emoji.deparse(editTextInput.textInput.text))
|
||||
if (msg.length > 0){
|
||||
msg = chatInput.interpretMessage(msg)
|
||||
isEdit = false
|
||||
chatsModel.messageView.editMessage(messageId, contentType == Constants.editType ? replaces : messageId, msg, JSON.stringify(suggestionsObj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: messageContent
|
||||
height: childrenRect.height + (isEmoji ? 2 : 0)
|
||||
@ -182,6 +242,7 @@ Item {
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: root.chatHorizontalPadding
|
||||
visible: !isEdit
|
||||
|
||||
ChatText {
|
||||
readonly property int leftPadding: chatImage.anchors.leftMargin + chatImage.width + root.chatHorizontalPadding
|
||||
|
@ -14,6 +14,8 @@ PopupMenu {
|
||||
property bool emojiOnly: false
|
||||
property bool hideEmojiPicker: false
|
||||
property bool pinnedMessage: false
|
||||
property bool isText: false
|
||||
property bool isCurrentUser: false
|
||||
property string linkUrls: ""
|
||||
property alias emojiContainer: emojiContainer
|
||||
|
||||
@ -26,6 +28,8 @@ PopupMenu {
|
||||
property var fromAuthor: ""
|
||||
property var text: ""
|
||||
property var emojiReactionsReactedByUser: []
|
||||
property var onClickEdit: function(){}
|
||||
|
||||
subMenuIcons: [
|
||||
{
|
||||
source: Qt.resolvedUrl("../../../../shared/img/copy-to-clipboard-icon"),
|
||||
@ -236,6 +240,19 @@ PopupMenu {
|
||||
icon.height: 16
|
||||
enabled: !emojiOnly && !copyLinkAction.enabled
|
||||
}
|
||||
|
||||
Action {
|
||||
id: editMessageAction
|
||||
text: qsTr("Edit message")
|
||||
onTriggered: {
|
||||
onClickEdit();
|
||||
}
|
||||
icon.source: "../../../img/profileActive.svg"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
enabled: isCurrentUser && isText
|
||||
}
|
||||
|
||||
Action {
|
||||
text: messageContextMenu.isProfile ?
|
||||
//% "Send message"
|
||||
|
3
ui/app/img/edit-message.svg
Normal file
3
ui/app/img/edit-message.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.8383 2.97542C15.9943 1.81939 17.8686 1.81939 19.0246 2.97542C20.1807 4.13145 20.1807 6.00574 19.0246 7.16177L8.25225 17.9342C7.86066 18.3257 7.37575 18.6111 6.84327 18.7632L2.98627 19.8652C2.74577 19.9339 2.48693 19.8669 2.31007 19.69C2.13321 19.5131 2.06614 19.2543 2.13485 19.0138L3.23686 15.1568C3.38899 14.6243 3.67432 14.1394 4.0659 13.7478L14.8383 2.97542ZM18.0507 3.9494C17.4325 3.33129 16.4304 3.33129 15.8123 3.9494L5.03988 14.7218C4.81382 14.9479 4.6491 15.2278 4.56128 15.5352C4.2294 16.6968 5.3033 17.7707 6.46487 17.4388C6.77226 17.351 7.0522 17.1862 7.27826 16.9602L18.0507 6.18779C18.6688 5.56967 18.6688 4.56751 18.0507 3.9494Z" fill="#4360DF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 818 B |
@ -68,6 +68,7 @@ QtObject {
|
||||
readonly property int audioType: 8
|
||||
readonly property int communityInviteType: 9
|
||||
readonly property int gapType: 10
|
||||
readonly property int editType: 11
|
||||
|
||||
readonly property string watchWalletType: "watch"
|
||||
readonly property string keyWalletType: "key"
|
||||
@ -147,6 +148,8 @@ QtObject {
|
||||
readonly property string ens_connected: "connected"
|
||||
readonly property string ens_connected_dkey: "connected-different-key"
|
||||
|
||||
readonly property string editLabel: ` <span class="isEdited">` + qsTr("(edited)") + `</span>`
|
||||
|
||||
readonly property var ensState: {
|
||||
//% "Username already taken :("
|
||||
"taken": qsTrId("ens-username-taken"),
|
||||
|
@ -29,6 +29,7 @@ Theme {
|
||||
property color green: "#4EBC60"
|
||||
property color turquoise: "#007b7d"
|
||||
property color tenPercentWhite: Qt.rgba(255, 255, 255, 0.1)
|
||||
property color fivePercentBlack: "#E5E5E5"
|
||||
property color tenPercentBlue: Qt.rgba(67, 96, 223, 0.1)
|
||||
|
||||
property color background: "#2C2C2C"
|
||||
@ -43,6 +44,7 @@ Theme {
|
||||
property color currentUserTextColor: white
|
||||
property color secondaryBackground: "#353a4d"
|
||||
property color inputBackground: darkGrey
|
||||
property color secondaryinputBackground: fivePercentBlack
|
||||
property color inputBorderFocus: blue
|
||||
property color secondaryMenuBorder: darkGrey
|
||||
property color inputColor: textColor
|
||||
|
@ -29,6 +29,7 @@ Theme {
|
||||
property color green: "#4EBC60"
|
||||
property color turquoise: "#007b7d"
|
||||
property color tenPercentBlack: Qt.rgba(0, 0, 0, 0.1)
|
||||
property color fivePercentBlack: "#E5E5E5"
|
||||
property color tenPercentBlue: Qt.rgba(67, 96, 223, 0.1)
|
||||
|
||||
property color background: white
|
||||
@ -43,6 +44,7 @@ Theme {
|
||||
property color currentUserTextColor: white
|
||||
property color secondaryBackground: lightBlue
|
||||
property color inputBackground: grey
|
||||
property color secondaryinputBackground: fivePercentBlack
|
||||
property color inputBorderFocus: blue
|
||||
property color secondaryMenuBorder: grey3
|
||||
property color inputColor: black
|
||||
|
@ -85,6 +85,10 @@ QtObject {
|
||||
`.emoji {` +
|
||||
`vertical-align: bottom;` +
|
||||
`}` +
|
||||
`span.isEdited {` +
|
||||
`color: ${Style.current.secondaryText};` +
|
||||
`margin-left: 5px` +
|
||||
`}` +
|
||||
`</style>` +
|
||||
`${msg}`
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ Rectangle {
|
||||
property bool isColonPressed: false;
|
||||
property bool isReply: false
|
||||
property bool isImage: false
|
||||
property bool isEdit: false
|
||||
|
||||
property var recentStickers
|
||||
property var stickerPackList
|
||||
@ -66,7 +67,7 @@ Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
color: Style.current.background
|
||||
color: Style.current.transparent
|
||||
|
||||
function calculateExtraHeightFactor() {
|
||||
const factor = (messageInputField.length / 500) + 1;
|
||||
@ -694,7 +695,7 @@ Rectangle {
|
||||
anchors.leftMargin: 4
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 16
|
||||
visible: control.chatType === Constants.chatTypeOneToOne && !control.isStatusUpdateInput
|
||||
visible: !isEdit && control.chatType === Constants.chatTypeOneToOne && !control.isStatusUpdateInput
|
||||
onClicked: {
|
||||
highlighted = true
|
||||
chatCommandsPopup.open()
|
||||
@ -710,7 +711,7 @@ Rectangle {
|
||||
anchors.leftMargin: chatCommandsBtn.visible ? 2 : 4
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 16
|
||||
visible: control.chatType !== Constants.chatTypePublic && !control.isStatusUpdateInput
|
||||
visible: !isEdit && control.chatType !== Constants.chatTypePublic && !control.isStatusUpdateInput
|
||||
|
||||
onClicked: {
|
||||
highlighted = true
|
||||
@ -739,7 +740,7 @@ Rectangle {
|
||||
return messageInputField.implicitHeight
|
||||
}
|
||||
|
||||
color: Style.current.inputBackground
|
||||
color: isEdit ? Style.current.secondaryinputBackground : Style.current.inputBackground
|
||||
radius: control.isStatusUpdateInput ? 36 :
|
||||
height > defaultInputFieldHeight + 1 || extendedArea.visible ? 16 : 32
|
||||
|
||||
@ -783,7 +784,7 @@ Rectangle {
|
||||
anchors.bottom: control.isStatusUpdateInput ? undefined : messageInput.top
|
||||
anchors.top: control.isStatusUpdateInput ? messageInput.bottom : undefined
|
||||
anchors.topMargin: control.isStatusUpdateInput ? -Style.current.halfPadding : 0
|
||||
color: Style.current.inputBackground
|
||||
color: isEdit ? Style.current.secondaryinputBackground : Style.current.inputBackground
|
||||
radius: control.isStatusUpdateInput ? 36 : 16
|
||||
|
||||
Rectangle {
|
||||
@ -1091,7 +1092,7 @@ Rectangle {
|
||||
anchors.leftMargin: 2
|
||||
anchors.bottom: parent.bottom
|
||||
icon.name: "stickers_icon"
|
||||
visible: profileModel.network.current === Constants.networkMainnet && emojiBtn.visible
|
||||
visible: !isEdit && profileModel.network.current === Constants.networkMainnet && emojiBtn.visible
|
||||
width: visible ? 32 : 0
|
||||
type: "secondary"
|
||||
onClicked: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user