diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 4fce9a75..bbe61ee9 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -376,6 +376,7 @@ Item {
required property string filesize
required property string url
required property string thumbnailUrl
+ required property string duration
required property bool isOnlyEmoji
required property bool isSender
required property bool isEncrypted
@@ -492,6 +493,7 @@ Item {
filesize: wrapper.filesize
url: wrapper.url
thumbnailUrl: wrapper.thumbnailUrl
+ duration: wrapper.duration
isOnlyEmoji: wrapper.isOnlyEmoji
isSender: wrapper.isSender
isEncrypted: wrapper.isEncrypted
diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml
index bb6514d1..032821ba 100644
--- a/resources/qml/TimelineRow.qml
+++ b/resources/qml/TimelineRow.qml
@@ -41,6 +41,7 @@ Item {
required property var reactions
required property int trustlevel
required property int encryptionError
+ required property int duration
required property var timestamp
required property int status
required property int relatedEventCacheBuster
@@ -128,6 +129,7 @@ Item {
userId: r.relatedEventCacheBuster, fromModel(Room.UserId) ?? ""
userName: r.relatedEventCacheBuster, fromModel(Room.UserName) ?? ""
thumbnailUrl: r.relatedEventCacheBuster, fromModel(Room.ThumbnailUrl) ?? ""
+ duration: r.relatedEventCacheBuster, fromModel(Room.Duration) ?? ""
roomTopic: r.relatedEventCacheBuster, fromModel(Room.RoomTopic) ?? ""
roomName: r.relatedEventCacheBuster, fromModel(Room.RoomName) ?? ""
callType: r.relatedEventCacheBuster, fromModel(Room.CallType) ?? ""
@@ -154,6 +156,7 @@ Item {
typeString: r.typeString ?? ""
url: r.url
thumbnailUrl: r.thumbnailUrl
+ duration: r.duration
originalWidth: r.originalWidth
isOnlyEmoji: r.isOnlyEmoji
isStateEvent: r.isStateEvent
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index 1933baeb..c4820077 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -124,6 +124,10 @@ Item {
color: Nheko.theme.separator
}
+
+ UploadBox {
+ }
+
NotificationWarning {
}
diff --git a/resources/qml/UploadBox.qml b/resources/qml/UploadBox.qml
new file mode 100644
index 00000000..ba00f205
--- /dev/null
+++ b/resources/qml/UploadBox.qml
@@ -0,0 +1,89 @@
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import "./components"
+import "./ui"
+
+import QtQuick 2.9
+import QtQuick.Controls 2.5
+import QtQuick.Layouts 1.3
+import im.nheko 1.0
+
+Page {
+ id: uploadPopup
+ visible: room && room.input.uploads.length > 0
+ Layout.preferredHeight: 200
+ clip: true
+
+ Layout.fillWidth: true
+
+ padding: Nheko.paddingMedium
+
+ contentItem: ListView {
+ id: uploadsList
+ anchors.horizontalCenter: parent.horizontalCenter
+ boundsBehavior: Flickable.StopAtBounds
+
+ ScrollBar.horizontal: ScrollBar {
+ id: scr
+ }
+
+ orientation: ListView.Horizontal
+ width: Math.min(contentWidth, parent.availableWidth)
+ model: room ? room.input.uploads : undefined
+ spacing: Nheko.paddingMedium
+
+ delegate: Pane {
+ padding: Nheko.paddingSmall
+ height: uploadPopup.availableHeight - buttons.height - (scr.visible? scr.height : 0)
+ width: uploadPopup.availableHeight - buttons.height
+
+ background: Rectangle {
+ color: Nheko.colors.window
+ radius: Nheko.paddingMedium
+ }
+ contentItem: ColumnLayout {
+ Image {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ sourceSize.height: height
+ sourceSize.width: width
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ mipmap: true
+
+ property string typeStr: switch(modelData.mediaType) {
+ case MediaUpload.Video: return "video-file";
+ case MediaUpload.Audio: return "music";
+ case MediaUpload.Image: return "image";
+ default: return "zip";
+ }
+ source: (modelData.thumbnail != "") ? modelData.thumbnail : ("image://colorimage/:/icons/icons/ui/"+typeStr+".svg?" + Nheko.colors.buttonText)
+ }
+ MatrixTextField {
+ Layout.fillWidth: true
+ text: modelData.filename
+ onTextEdited: modelData.filename = text
+ }
+ }
+ }
+ }
+
+ footer: DialogButtonBox {
+ id: buttons
+
+ standardButtons: DialogButtonBox.Cancel
+ Button {
+ text: qsTr("Upload %n file(s)", "", (room ? room.input.uploads.length : 0))
+ DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
+ }
+ onAccepted: room.input.acceptUploads()
+ onRejected: room.input.declineUploads()
+ }
+
+ background: Rectangle {
+ color: Nheko.colors.base
+ }
+}
diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml
index 08b2098e..0e211ded 100644
--- a/resources/qml/delegates/MessageDelegate.qml
+++ b/resources/qml/delegates/MessageDelegate.qml
@@ -18,6 +18,7 @@ Item {
required property int type
required property string typeString
required property int originalWidth
+ required property int duration
required property string blurhash
required property string body
required property string formattedBody
@@ -161,6 +162,7 @@ Item {
url: d.url
body: d.body
filesize: d.filesize
+ duration: d.duration
metadataWidth: d.metadataWidth
}
@@ -178,6 +180,7 @@ Item {
url: d.url
body: d.body
filesize: d.filesize
+ duration: d.duration
metadataWidth: d.metadataWidth
}
diff --git a/resources/qml/delegates/PlayableMediaMessage.qml b/resources/qml/delegates/PlayableMediaMessage.qml
index 5d7beaad..4828843c 100644
--- a/resources/qml/delegates/PlayableMediaMessage.qml
+++ b/resources/qml/delegates/PlayableMediaMessage.qml
@@ -17,6 +17,7 @@ Item {
required property double proportionalHeight
required property int type
required property int originalWidth
+ required property int duration
required property string thumbnailUrl
required property string eventId
required property string url
@@ -57,7 +58,7 @@ Item {
Image {
anchors.fill: parent
- source: thumbnailUrl.replace("mxc://", "image://MxcImage/") + "?scale"
+ source: thumbnailUrl ? thumbnailUrl.replace("mxc://", "image://MxcImage/") + "?scale" : ""
asynchronous: true
fillMode: Image.PreserveAspectFit
@@ -85,7 +86,7 @@ Item {
anchors.bottom: fileInfoLabel.top
playingVideo: type == MtxEvent.VideoMessage
positionValue: mxcmedia.position
- duration: mxcmedia.duration
+ duration: mediaLoaded ? mxcmedia.duration : content.duration
mediaLoaded: mxcmedia.loaded
mediaState: mxcmedia.state
onPositionChanged: mxcmedia.position = position
diff --git a/resources/qml/delegates/Reply.qml b/resources/qml/delegates/Reply.qml
index 513b7c0b..27fb4e07 100644
--- a/resources/qml/delegates/Reply.qml
+++ b/resources/qml/delegates/Reply.qml
@@ -34,6 +34,7 @@ Item {
property string roomTopic
property string roomName
property string callType
+ property int duration
property int encryptionError
property int relatedEventCacheBuster
property int maxWidth
@@ -112,6 +113,7 @@ Item {
typeString: r.typeString ?? ""
url: r.url
thumbnailUrl: r.thumbnailUrl
+ duration: r.duration
originalWidth: r.originalWidth
isOnlyEmoji: r.isOnlyEmoji
isStateEvent: r.isStateEvent
diff --git a/resources/qml/ui/media/MediaControls.qml b/resources/qml/ui/media/MediaControls.qml
index 1844af73..d73957ee 100644
--- a/resources/qml/ui/media/MediaControls.qml
+++ b/resources/qml/ui/media/MediaControls.qml
@@ -214,7 +214,7 @@ Rectangle {
Label {
Layout.alignment: Qt.AlignRight
- text: (!control.mediaLoaded) ? "-- / --" : (durationToString(control.positionValue) + " / " + durationToString(control.duration))
+ text: (!control.mediaLoaded ? "-- " : durationToString(control.positionValue)) + " / " + durationToString(control.duration)
color: Nheko.colors.text
}
|