- display caption independent of filename (consistancy to File) - fix audio seeking not working - change two comments and a variable name
175 lines
5.0 KiB
QML
175 lines
5.0 KiB
QML
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
|
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import QtQuick
|
|
import QtQuick.Controls as QQC2
|
|
import QtQuick.Layouts
|
|
import QtMultimedia
|
|
|
|
import org.kde.coreaddons
|
|
import org.kde.kirigami as Kirigami
|
|
|
|
import org.kde.neochat
|
|
|
|
/**
|
|
* @brief A component to show audio from a message.
|
|
*/
|
|
ColumnLayout {
|
|
id: root
|
|
|
|
/**
|
|
* @brief The NeoChatRoom the delegate is being displayed in.
|
|
*/
|
|
required property NeoChatRoom room
|
|
|
|
/**
|
|
* @brief The matrix ID of the message event.
|
|
*/
|
|
required property string eventId
|
|
|
|
/**
|
|
* @brief The media info for the event.
|
|
*
|
|
* This should consist of the following:
|
|
* - source - The mxc URL for the media.
|
|
* - mimeType - The MIME type of the media (should be image/xxx for this delegate).
|
|
* - mimeIcon - The MIME icon name (should be image-xxx).
|
|
* - size - The file size in bytes.
|
|
* - width - The width in pixels of the audio media.
|
|
* - height - The height in pixels of the audio media.
|
|
* - tempInfo - mediaInfo (with the same properties as this except no tempInfo) for a temporary image while the file downloads.
|
|
* - filename - original filename of the media
|
|
*/
|
|
required property var mediaInfo
|
|
|
|
/**
|
|
* @brief FileTransferInfo for any downloading files.
|
|
*/
|
|
required property var fileTransferInfo
|
|
|
|
/**
|
|
* @brief Whether the media has been downloaded.
|
|
*/
|
|
readonly property bool downloaded: root.fileTransferInfo && root.fileTransferInfo.completed
|
|
onDownloadedChanged: if (downloaded) {
|
|
audio.play();
|
|
}
|
|
|
|
/**
|
|
* @brief The maximum width that the bubble's content can be.
|
|
*/
|
|
property real maxContentWidth: -1
|
|
|
|
MediaPlayer {
|
|
id: audio
|
|
onErrorOccurred: (error, errorString) => console.warn("Audio playback error:" + error + errorString)
|
|
audioOutput: AudioOutput {}
|
|
}
|
|
|
|
states: [
|
|
State {
|
|
name: "notDownloaded"
|
|
when: !root.fileTransferInfo.completed && !root.fileTransferInfo.active
|
|
|
|
PropertyChanges {
|
|
target: playButton
|
|
icon.name: "media-playback-start"
|
|
onClicked: root.room.downloadFile(root.eventId)
|
|
}
|
|
},
|
|
State {
|
|
name: "downloading"
|
|
when: root.fileTransferInfo.active && !root.fileTransferInfo.completed
|
|
PropertyChanges {
|
|
target: downloadBar
|
|
visible: true
|
|
}
|
|
PropertyChanges {
|
|
target: playButton
|
|
icon.name: "media-playback-stop"
|
|
onClicked: {
|
|
root.room.cancelFileTransfer(root.eventId);
|
|
}
|
|
}
|
|
},
|
|
State {
|
|
name: "paused"
|
|
when: root.fileTransferInfo.completed && (audio.playbackState === MediaPlayer.StoppedState || audio.playbackState === MediaPlayer.PausedState)
|
|
PropertyChanges {
|
|
target: playButton
|
|
icon.name: "media-playback-start"
|
|
onClicked: {
|
|
audio.source = root.fileTransferInfo.localPath;
|
|
MediaManager.startPlayback();
|
|
audio.play();
|
|
}
|
|
}
|
|
},
|
|
State {
|
|
name: "playing"
|
|
when: root.fileTransferInfo.completed && audio.playbackState === MediaPlayer.PlayingState
|
|
|
|
PropertyChanges {
|
|
target: playButton
|
|
|
|
icon.name: "media-playback-pause"
|
|
|
|
onClicked: audio.pause()
|
|
}
|
|
}
|
|
]
|
|
|
|
Connections {
|
|
target: MediaManager
|
|
function onPlaybackStarted() {
|
|
if (audio.playbackState === MediaPlayer.PlayingState) {
|
|
audio.pause();
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
QQC2.ToolButton {
|
|
id: playButton
|
|
}
|
|
QQC2.Label {
|
|
text: root.mediaInfo.filename
|
|
wrapMode: Text.Wrap
|
|
Layout.fillWidth: true
|
|
}
|
|
}
|
|
QQC2.ProgressBar {
|
|
id: downloadBar
|
|
visible: false
|
|
Layout.fillWidth: true
|
|
from: 0
|
|
to: root.mediaInfo.size
|
|
value: root.fileTransferInfo.progress
|
|
}
|
|
RowLayout {
|
|
visible: audio.hasAudio
|
|
|
|
QQC2.Slider {
|
|
Layout.fillWidth: true
|
|
from: 0
|
|
to: audio.duration
|
|
value: audio.position
|
|
onMoved: audio.setPosition(value)
|
|
}
|
|
|
|
QQC2.Label {
|
|
visible: root.maxContentWidth > Kirigami.Units.gridUnit * 12
|
|
|
|
text: Format.formatDuration(audio.position) + "/" + Format.formatDuration(audio.duration)
|
|
}
|
|
}
|
|
QQC2.Label {
|
|
Layout.alignment: Qt.AlignRight
|
|
Layout.rightMargin: Kirigami.Units.smallSpacing
|
|
visible: audio.hasAudio && root.maxContentWidth < Kirigami.Units.gridUnit * 12
|
|
|
|
text: Format.formatDuration(audio.position) + "/" + Format.formatDuration(audio.duration)
|
|
}
|
|
}
|