feat: play audio messages
This commit is contained in:
parent
484c647f39
commit
5ab1088f7c
|
@ -28,6 +28,8 @@ type
|
||||||
ImageUrls = UserRole + 17
|
ImageUrls = UserRole + 17
|
||||||
Timeout = UserRole + 18
|
Timeout = UserRole + 18
|
||||||
Image = UserRole + 19
|
Image = UserRole + 19
|
||||||
|
Audio = UserRole + 20
|
||||||
|
AudioDurationMs = UserRole + 21
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
|
@ -111,6 +113,8 @@ QtObject:
|
||||||
of ChatMessageRoles.ImageUrls: result = newQVariant(message.imageUrls)
|
of ChatMessageRoles.ImageUrls: result = newQVariant(message.imageUrls)
|
||||||
of ChatMessageRoles.Timeout: result = newQVariant(self.timedoutMessages.contains(message.id))
|
of ChatMessageRoles.Timeout: result = newQVariant(self.timedoutMessages.contains(message.id))
|
||||||
of ChatMessageRoles.Image: result = newQVariant(message.image)
|
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] =
|
method roleNames(self: ChatMessageList): Table[int, string] =
|
||||||
{
|
{
|
||||||
|
@ -132,7 +136,9 @@ QtObject:
|
||||||
ChatMessageRoles.Index.int: "index",
|
ChatMessageRoles.Index.int: "index",
|
||||||
ChatMessageRoles.ImageUrls.int: "imageUrls",
|
ChatMessageRoles.ImageUrls.int: "imageUrls",
|
||||||
ChatMessageRoles.Timeout.int: "timeout",
|
ChatMessageRoles.Timeout.int: "timeout",
|
||||||
ChatMessageRoles.Image.int: "image"
|
ChatMessageRoles.Image.int: "image",
|
||||||
|
ChatMessageRoles.Audio.int: "audio",
|
||||||
|
ChatMessageRoles.AudioDurationMs.int: "audioDurationMs"
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
proc getMessageIndex(self: ChatMessageList, messageId: string): int {.slot.} =
|
proc getMessageIndex(self: ChatMessageList, messageId: string): int {.slot.} =
|
||||||
|
|
|
@ -146,7 +146,7 @@ proc toMessage*(jsonMsg: JsonNode): Message =
|
||||||
contentType = ContentType(jsonMsg{"contentType"}.getInt)
|
contentType = ContentType(jsonMsg{"contentType"}.getInt)
|
||||||
except:
|
except:
|
||||||
warn "Unknown content type received", type = jsonMsg{"contentType"}.getInt
|
warn "Unknown content type received", type = jsonMsg{"contentType"}.getInt
|
||||||
contentType = ContentType.Unknown
|
contentType = ContentType.Message
|
||||||
|
|
||||||
var message = Message(
|
var message = Message(
|
||||||
alias: jsonMsg{"alias"}.getStr,
|
alias: jsonMsg{"alias"}.getStr,
|
||||||
|
@ -172,7 +172,9 @@ proc toMessage*(jsonMsg: JsonNode): Message =
|
||||||
stickerHash: "",
|
stickerHash: "",
|
||||||
parsedText: @[],
|
parsedText: @[],
|
||||||
imageUrls: "",
|
imageUrls: "",
|
||||||
image: $jsonMsg{"image"}.getStr
|
image: $jsonMsg{"image"}.getStr,
|
||||||
|
audio: $jsonMsg{"audio"}.getStr,
|
||||||
|
audioDurationMs: jsonMsg{"audioDurationMs"}.getInt,
|
||||||
)
|
)
|
||||||
|
|
||||||
if jsonMsg["parsedText"].kind != JNull:
|
if jsonMsg["parsedText"].kind != JNull:
|
||||||
|
|
|
@ -9,7 +9,8 @@ type ContentType* {.pure.} = enum
|
||||||
Emoji = 4,
|
Emoji = 4,
|
||||||
Transaction = 5,
|
Transaction = 5,
|
||||||
Group = 6,
|
Group = 6,
|
||||||
Image = 7
|
Image = 7,
|
||||||
|
Audio = 8
|
||||||
|
|
||||||
type TextItem* = object
|
type TextItem* = object
|
||||||
textType*: string
|
textType*: string
|
||||||
|
@ -33,7 +34,7 @@ type Message* = object
|
||||||
parsedText*: seq[TextItem]
|
parsedText*: seq[TextItem]
|
||||||
# quotedMessage: # ???
|
# quotedMessage: # ???
|
||||||
replace*: string # ???
|
replace*: string # ???
|
||||||
responseTo*: string # ???
|
responseTo*: string
|
||||||
rtl*: bool # ???
|
rtl*: bool # ???
|
||||||
seen*: bool # ???
|
seen*: bool # ???
|
||||||
sticker*: string
|
sticker*: string
|
||||||
|
@ -45,7 +46,9 @@ type Message* = object
|
||||||
outgoingStatus*: string
|
outgoingStatus*: string
|
||||||
imageUrls*: string
|
imageUrls*: string
|
||||||
image*: string
|
image*: string
|
||||||
|
audio*: string
|
||||||
|
audioDurationMs*: int
|
||||||
|
|
||||||
|
|
||||||
proc `$`*(self: Message): string =
|
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})"
|
||||||
|
|
|
@ -26,10 +26,11 @@ Item {
|
||||||
|
|
||||||
property bool isEmoji: contentType === Constants.emojiType
|
property bool isEmoji: contentType === Constants.emojiType
|
||||||
property bool isImage: contentType === Constants.imageType
|
property bool isImage: contentType === Constants.imageType
|
||||||
|
property bool isAudio: contentType === Constants.audioType
|
||||||
property bool isStatusMessage: contentType === Constants.systemMessagePrivateGroupType
|
property bool isStatusMessage: contentType === Constants.systemMessagePrivateGroupType
|
||||||
property bool isSticker: contentType === Constants.stickerType
|
property bool isSticker: contentType === Constants.stickerType
|
||||||
property bool isText: contentType === Constants.messageType
|
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())
|
property bool isExpired: (outgoingStatus == "sending" && (Math.floor(timestamp) + 180000) < Date.now())
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -136,4 +136,19 @@ Item {
|
||||||
chatHorizontalPadding: 0
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,9 @@ Item {
|
||||||
case Constants.stickerType:
|
case Constants.stickerType:
|
||||||
h += stickerId.height;
|
h += stickerId.height;
|
||||||
break;
|
break;
|
||||||
|
case Constants.audioType:
|
||||||
|
h += audioPlayerLoader.height;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
h += chatText.visible ? chatText.height : 0;
|
h += chatText.visible ? chatText.height : 0;
|
||||||
h += chatImageContent.visible ? chatImageContent.height: 0;
|
h += chatImageContent.visible ? chatImageContent.height: 0;
|
||||||
|
@ -123,7 +126,21 @@ Item {
|
||||||
imageWidth: 250
|
imageWidth: 250
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: audioPlayerLoader
|
||||||
|
active: isAudio
|
||||||
|
sourceComponent: audioPlayer
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: audioPlayer
|
||||||
|
AudioPlayer {
|
||||||
|
audioSource: audio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Sticker {
|
Sticker {
|
||||||
id: stickerId
|
id: stickerId
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 23 29" height="29px" id="Layer_1" version="1.1" viewBox="0 0 23 29" width="23px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><rect fill="#231F20" height="29" width="9"/><rect fill="#231F20" height="29" width="9" x="14"/></g></svg>
|
After Width: | Height: | Size: 442 B |
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 23 29" height="29px" id="Layer_1" version="1.1" viewBox="0 0 23 29" width="23px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><polygon fill="#231F20" points="0,28.524 23,14.175 0,-0.175 "/></svg>
|
After Width: | Height: | Size: 403 B |
|
@ -16,6 +16,7 @@ QtObject {
|
||||||
readonly property int transactionType: 5
|
readonly property int transactionType: 5
|
||||||
readonly property int systemMessagePrivateGroupType: 6
|
readonly property int systemMessagePrivateGroupType: 6
|
||||||
readonly property int imageType: 7
|
readonly property int imageType: 7
|
||||||
|
readonly property int audioType: 8
|
||||||
|
|
||||||
readonly property string watchWalletType: "watch"
|
readonly property string watchWalletType: "watch"
|
||||||
readonly property string keyWalletType: "key"
|
readonly property string keyWalletType: "key"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 58fcf809eaa5ad1f89253e1027bb8b5abf84c962
|
Subproject commit e6ae4409e4cf1f248a459ddc8f98ae6a39364bc1
|
Loading…
Reference in New Issue