2b3dc3d8b9
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.
165 lines
3.7 KiB
QML
165 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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|