diff --git a/src/app/chat/views/message_list.nim b/src/app/chat/views/message_list.nim index 7ec704f8d4..c2ab407b05 100644 --- a/src/app/chat/views/message_list.nim +++ b/src/app/chat/views/message_list.nim @@ -28,6 +28,8 @@ type ImageUrls = UserRole + 17 Timeout = UserRole + 18 Image = UserRole + 19 + Audio = UserRole + 20 + AudioDurationMs = UserRole + 21 QtObject: type @@ -111,6 +113,8 @@ QtObject: of ChatMessageRoles.ImageUrls: result = newQVariant(message.imageUrls) of ChatMessageRoles.Timeout: result = newQVariant(self.timedoutMessages.contains(message.id)) of ChatMessageRoles.Image: result = newQVariant(message.image) + of ChatMessageRoles.Audio: result = newQVariant(message.audio) + of ChatMessageRoles.AudioDurationMs: result = newQVariant(message.audioDurationMs) method roleNames(self: ChatMessageList): Table[int, string] = { @@ -132,7 +136,9 @@ QtObject: ChatMessageRoles.Index.int: "index", ChatMessageRoles.ImageUrls.int: "imageUrls", ChatMessageRoles.Timeout.int: "timeout", - ChatMessageRoles.Image.int: "image" + ChatMessageRoles.Image.int: "image", + ChatMessageRoles.Audio.int: "audio", + ChatMessageRoles.AudioDurationMs.int: "audioDurationMs" }.toTable proc getMessageIndex(self: ChatMessageList, messageId: string): int {.slot.} = diff --git a/src/signals/messages.nim b/src/signals/messages.nim index b7f54607e1..8872111fc3 100644 --- a/src/signals/messages.nim +++ b/src/signals/messages.nim @@ -146,7 +146,7 @@ proc toMessage*(jsonMsg: JsonNode): Message = contentType = ContentType(jsonMsg{"contentType"}.getInt) except: warn "Unknown content type received", type = jsonMsg{"contentType"}.getInt - contentType = ContentType.Unknown + contentType = ContentType.Message var message = Message( alias: jsonMsg{"alias"}.getStr, @@ -172,7 +172,9 @@ proc toMessage*(jsonMsg: JsonNode): Message = stickerHash: "", parsedText: @[], imageUrls: "", - image: $jsonMsg{"image"}.getStr + image: $jsonMsg{"image"}.getStr, + audio: $jsonMsg{"audio"}.getStr, + audioDurationMs: jsonMsg{"audioDurationMs"}.getInt, ) if jsonMsg["parsedText"].kind != JNull: diff --git a/src/status/chat/message.nim b/src/status/chat/message.nim index c57c6fdba6..0f5af90faf 100644 --- a/src/status/chat/message.nim +++ b/src/status/chat/message.nim @@ -9,7 +9,8 @@ type ContentType* {.pure.} = enum Emoji = 4, Transaction = 5, Group = 6, - Image = 7 + Image = 7, + Audio = 8 type TextItem* = object textType*: string @@ -33,7 +34,7 @@ type Message* = object parsedText*: seq[TextItem] # quotedMessage: # ??? replace*: string # ??? - responseTo*: string # ??? + responseTo*: string rtl*: bool # ??? seen*: bool # ??? sticker*: string @@ -45,7 +46,9 @@ type Message* = object outgoingStatus*: string imageUrls*: string image*: string + audio*: string + audioDurationMs*: int proc `$`*(self: Message): string = - result = fmt"Message(id:{self.id}, chatId:{self.chatId}, clock:{self.clock}, from:{self.fromAuthor}, type:{self.contentType})" + result = fmt"Message(id:{self.id}, chatId:{self.chatId}, clock:{self.clock}, from:{self.fromAuthor}, contentType:{self.contentType})" diff --git a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml index ea28949de0..e0ecfa136a 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml @@ -26,10 +26,11 @@ Item { property bool isEmoji: contentType === Constants.emojiType property bool isImage: contentType === Constants.imageType + 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 isMessage: isEmoji || isImage || isSticker || isText + property bool isMessage: isEmoji || isImage || isSticker || isText || isAudio property bool isExpired: (outgoingStatus == "sending" && (Math.floor(timestamp) + 180000) < Date.now()) diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/AudioPlayer.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/AudioPlayer.qml new file mode 100644 index 0000000000..7c12a092f3 --- /dev/null +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/AudioPlayer.qml @@ -0,0 +1,107 @@ +import QtQuick 2.3 +import QtMultimedia 5.14 +import "../../../../../shared" +import "../../../../../imports" + +Item { + property string audioSource: "" + + height: 20 + width: 350 + + Audio { + id: audioMessage + source: audioSource + notifyInterval: 150 + } + + SVGImage { + id: playButton + source: audioMessage.playbackState == Audio.PlayingState ? "../../../../img/icon-pause.svg" : "../../../../img/icon-play.svg" + width: 15 + height: 15 + anchors.left: parent.left + anchors.leftMargin: Style.current.padding + anchors.verticalCenter: parent.verticalCenter + MouseArea { + id: playArea + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onPressed: { + if(audioMessage.playbackState === Audio.PlayingState){ + audioMessage.pause(); + } else { + audioMessage.play(); + } + + } + } + } + + Rectangle { + height: 2 + width: 300 + color: Style.current.grey + anchors.verticalCenter: parent.verticalCenter + anchors.left: playButton.right + anchors.leftMargin: 20 + Rectangle { + id: progress + height: 2 + width: { + if(audioMessage.duration === 0) return 0; + if(audioMessage.playbackState === Audio.StoppedState) return 0; + return parent.width * audioMessage.position / audioMessage.duration; + } + color: Style.current.black + anchors.verticalCenter: parent.verticalCenter + } + + Rectangle { + id: handle + width: 10 + height: 10 + color: Style.current.black + radius: 10 + anchors.verticalCenter: parent.verticalCenter + x: progress.width + state: "default" + + states: State { + name: "pressed" + when: handleMouseArea.pressed + PropertyChanges { + target: handle; + scale: 1.2 + } + } + transitions: Transition { + NumberAnimation { + properties: "scale"; + duration: 100; + easing.type: Easing.InOutQuad + } + } + + MouseArea { + id: handleMouseArea + cursorShape: Qt.PointingHandCursor + anchors.fill: parent + drag.target: parent + drag.axis: Drag.XAxis + drag.minimumX: 0 + drag.maximumX: parent.parent.width + onPressed: { + handle.state = "pressed" + if(audioMessage.playbackState === Audio.PlayingState){ + audioMessage.pause(); + } + } + onReleased: { + handle.state = "default" + audioMessage.seek(audioMessage.duration * handle.x / parent.parent.width); + } + } + } + } +} \ No newline at end of file diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/CompactMessage.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/CompactMessage.qml index 70fe120c33..beb2c5490b 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/CompactMessage.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/CompactMessage.qml @@ -136,4 +136,19 @@ Item { chatHorizontalPadding: 0 } } + + Loader { + id: audioPlayerLoader + active: isAudio + sourceComponent: audioPlayer + anchors.top: chatName.visible ? chatName.bottom : parent.top + anchors.left: chatImage.right + } + + Component { + id: audioPlayer + AudioPlayer { + audioSource: audio + } + } } diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml index 4879825c05..cb7a32d846 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/NormalMessage.qml @@ -51,6 +51,9 @@ Item { case Constants.stickerType: h += stickerId.height; break; + case Constants.audioType: + h += audioPlayerLoader.height; + break; default: h += chatText.visible ? chatText.height : 0; h += chatImageContent.visible ? chatImageContent.height: 0; @@ -123,7 +126,21 @@ Item { imageWidth: 250 } } - + + Loader { + id: audioPlayerLoader + active: isAudio + sourceComponent: audioPlayer + anchors.verticalCenter: parent.verticalCenter + } + + Component { + id: audioPlayer + AudioPlayer { + audioSource: audio + } + } + Sticker { id: stickerId anchors.left: parent.left diff --git a/ui/app/img/icon-pause.svg b/ui/app/img/icon-pause.svg new file mode 100644 index 0000000000..c14a0b9724 --- /dev/null +++ b/ui/app/img/icon-pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/app/img/icon-play.svg b/ui/app/img/icon-play.svg new file mode 100644 index 0000000000..025862d630 --- /dev/null +++ b/ui/app/img/icon-play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/imports/Constants.qml b/ui/imports/Constants.qml index 1f6fdac418..7d6452b899 100644 --- a/ui/imports/Constants.qml +++ b/ui/imports/Constants.qml @@ -16,6 +16,7 @@ QtObject { readonly property int transactionType: 5 readonly property int systemMessagePrivateGroupType: 6 readonly property int imageType: 7 + readonly property int audioType: 8 readonly property string watchWalletType: "watch" readonly property string keyWalletType: "key" diff --git a/vendor/status-go b/vendor/status-go index 58fcf809ea..e6ae4409e4 160000 --- a/vendor/status-go +++ b/vendor/status-go @@ -1 +1 @@ -Subproject commit 58fcf809eaa5ad1f89253e1027bb8b5abf84c962 +Subproject commit e6ae4409e4cf1f248a459ddc8f98ae6a39364bc1