matrixion/resources/qml/delegates/PlayableMediaMessage.qml
Nicolas Werner 2b3dc3d8b9 Implement fancy reply rendering
This currently assumes the event, that is replied to, is already
fetched. If it isn't, it will render an empty reply. In the future we
should fetch replies before rendering them.
2020-01-11 14:07:51 +01:00

164 lines
3.7 KiB
QML

import QtQuick 2.6
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.1
import QtMultimedia 5.6
import im.nheko 1.0
Rectangle {
id: bg
radius: 10
color: colors.dark
height: content.height + 24
width: parent ? parent.width : undefined
Column {
id: content
width: parent.width - 24
anchors.centerIn: parent
Rectangle {
id: videoContainer
visible: model.data.type == MtxEvent.VideoMessage
width: Math.min(parent.width, model.data.width ? model.data.width : 400) // some media has 0 as size...
height: width*model.data.proportionalHeight
Image {
anchors.fill: parent
source: model.data.thumbnailUrl.replace("mxc://", "image://MxcImage/")
asynchronous: true
fillMode: Image.PreserveAspectFit
VideoOutput {
anchors.fill: parent
fillMode: VideoOutput.PreserveAspectFit
source: media
}
}
}
RowLayout {
width: parent.width
Text {
id: positionText
text: "--:--:--"
color: colors.text
}
Slider {
Layout.fillWidth: true
id: progress
value: media.position
from: 0
to: media.duration
onMoved: media.seek(value)
//indeterminate: true
function updatePositionTexts() {
function formatTime(date) {
var hh = date.getUTCHours();
var mm = date.getUTCMinutes();
var ss = date.getSeconds();
if (hh < 10) {hh = "0"+hh;}
if (mm < 10) {mm = "0"+mm;}
if (ss < 10) {ss = "0"+ss;}
return hh+":"+mm+":"+ss;
}
positionText.text = formatTime(new Date(media.position))
durationText.text = formatTime(new Date(media.duration))
}
onValueChanged: updatePositionTexts()
}
Text {
id: durationText
text: "--:--:--"
color: colors.text
}
}
RowLayout {
width: parent.width
spacing: 15
Rectangle {
id: button
color: colors.light
radius: 22
height: 44
width: 44
Image {
id: img
anchors.centerIn: parent
source: "image://colorimage/:/icons/icons/ui/arrow-pointing-down.png?"+colors.dark
fillMode: Image.Pad
}
MouseArea {
anchors.fill: parent
onClicked: {
switch (button.state) {
case "": timelineManager.timeline.cacheMedia(model.data.id); break;
case "stopped":
media.play(); console.log("play");
button.state = "playing"
break
case "playing":
media.pause(); console.log("pause");
button.state = "stopped"
break
}
}
cursorShape: Qt.PointingHandCursor
}
MediaPlayer {
id: media
onError: console.log(errorString)
onStatusChanged: if(status == MediaPlayer.Loaded) progress.updatePositionTexts()
onStopped: button.state = "stopped"
}
Connections {
target: timelineManager.timeline
onMediaCached: {
if (mxcUrl == model.data.url) {
media.source = "file://" + cacheUrl
button.state = "stopped"
console.log("media loaded: " + mxcUrl + " at " + cacheUrl)
}
console.log("media cached: " + mxcUrl + " at " + cacheUrl)
}
}
states: [
State {
name: "stopped"
PropertyChanges { target: img; source: "image://colorimage/:/icons/icons/ui/play-sign.png?"+colors.dark }
},
State {
name: "playing"
PropertyChanges { target: img; source: "image://colorimage/:/icons/icons/ui/pause-symbol.png?"+colors.dark }
}
]
}
ColumnLayout {
id: col
Text {
Layout.fillWidth: true
text: model.data.body
textFormat: Text.PlainText
elide: Text.ElideRight
color: colors.text
}
Text {
Layout.fillWidth: true
text: model.data.filesize
textFormat: Text.PlainText
elide: Text.ElideRight
color: colors.text
}
}
}
}
}