linphone-desktop/ui/modules/Linphone/Chat/FileMessage.qml
Ronan Abhamon 23939aaa2a feat(core): supports H264 download
Co-authored-by: Danmei Chen <danmei.chen@belledonne-communications.com>
2018-03-23 10:43:48 +01:00

341 lines
9.5 KiB
QML

import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import LinphoneUtils 1.0
import Linphone.Styles 1.0
import Utils 1.0
// =============================================================================
Row {
// ---------------------------------------------------------------------------
// Avatar if it's an incoming message.
// ---------------------------------------------------------------------------
Item {
height: ChatStyle.entry.lineHeight
width: ChatStyle.entry.metaWidth
Component {
id: avatar
Avatar {
height: ChatStyle.entry.message.incoming.avatarSize
width: ChatStyle.entry.message.incoming.avatarSize
image: chat.sipAddressObserver.contact ? chat.sipAddressObserver.contact.vcard.avatar : ''
username: LinphoneUtils.getContactUsername(chat.sipAddressObserver)
}
}
Loader {
anchors.centerIn: parent
sourceComponent: !$chatEntry.isOutgoing ? avatar : undefined
}
}
// ---------------------------------------------------------------------------
// File message.
// ---------------------------------------------------------------------------
Row {
spacing: ChatStyle.entry.message.extraContent.leftMargin
Rectangle {
id: rectangle
readonly property bool isNotDelivered: Utils.includes([
ChatModel.MessageStatusFileTransferError,
ChatModel.MessageStatusIdle,
ChatModel.MessageStatusInProgress,
ChatModel.MessageStatusNotDelivered
], $chatEntry.status)
readonly property bool isRead: $chatEntry.status === ChatModel.MessageStatusDisplayed
color: $chatEntry.isOutgoing
? ChatStyle.entry.message.outgoing.backgroundColor
: ChatStyle.entry.message.incoming.backgroundColor
height: ChatStyle.entry.message.file.height
width: ChatStyle.entry.message.file.width
radius: ChatStyle.entry.message.radius
RowLayout {
anchors {
fill: parent
margins: ChatStyle.entry.message.file.margins
}
spacing: ChatStyle.entry.message.file.spacing
// ---------------------------------------------------------------------
// Thumbnail or extension.
// ---------------------------------------------------------------------
Component {
id: thumbnail
Image {
source: $chatEntry.thumbnail
}
}
Component {
id: extension
Rectangle {
color: ChatStyle.entry.message.file.extension.background.color
Text {
anchors.fill: parent
color: ChatStyle.entry.message.file.extension.text.color
font.bold: true
elide: Text.ElideRight
text: Utils.getExtension($chatEntry.fileName).toUpperCase()
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
Loader {
id: thumbnailProvider
Layout.fillHeight: true
Layout.preferredWidth: parent.height
sourceComponent: $chatEntry.thumbnail ? thumbnail : extension
ScaleAnimator {
id: thumbnailProviderAnimator
target: thumbnailProvider
duration: ChatStyle.entry.message.file.animation.duration
easing.type: Easing.InOutQuad
from: 1.0
}
states: State {
name: 'hovered'
}
transitions: [
Transition {
from: ''
to: 'hovered'
ScriptAction {
script: {
if (thumbnailProviderAnimator.running) {
thumbnailProviderAnimator.running = false
}
thumbnailProvider.z = Constants.zPopup
thumbnailProviderAnimator.to = ChatStyle.entry.message.file.animation.to
thumbnailProviderAnimator.running = true
}
}
},
Transition {
from: 'hovered'
to: ''
ScriptAction {
script: {
if (thumbnailProviderAnimator.running) {
thumbnailProviderAnimator.running = false
}
thumbnailProviderAnimator.to = 1.0
thumbnailProviderAnimator.running = true
thumbnailProvider.z = 0
}
}
}
]
}
// ---------------------------------------------------------------------
// Upload or file status.
// ---------------------------------------------------------------------
Column {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: ChatStyle.entry.message.file.status.spacing
Text {
id: fileName
color: $chatEntry.isOutgoing
? ChatStyle.entry.message.outgoing.text.color
: ChatStyle.entry.message.incoming.text.color
elide: Text.ElideRight
font {
bold: true
pointSize: $chatEntry.isOutgoing
? ChatStyle.entry.message.outgoing.text.pointSize
: ChatStyle.entry.message.incoming.text.pointSize
}
text: $chatEntry.fileName
width: parent.width
}
ProgressBar {
id: progressBar
height: ChatStyle.entry.message.file.status.bar.height
width: parent.width
to: $chatEntry.fileSize
value: $chatEntry.fileOffset || 0
visible: $chatEntry.status === ChatModel.MessageStatusInProgress
background: Rectangle {
color: ChatStyle.entry.message.file.status.bar.background.color
radius: ChatStyle.entry.message.file.status.bar.radius
}
contentItem: Item {
Rectangle {
color: ChatStyle.entry.message.file.status.bar.contentItem.color
height: parent.height
width: progressBar.visualPosition * parent.width
radius: ChatStyle.entry.message.file.status.bar.radius
}
}
}
Text {
color: fileName.color
elide: Text.ElideRight
font.pointSize: fileName.font.pointSize
text: {
var fileSize = Utils.formatSize($chatEntry.fileSize)
return progressBar.visible
? Utils.formatSize($chatEntry.fileOffset) + '/' + fileSize
: fileSize
}
}
}
}
Icon {
anchors {
bottom: parent.bottom
bottomMargin: ChatStyle.entry.message.file.margins
right: parent.right
rightMargin: ChatStyle.entry.message.file.margins
}
icon: 'download'
iconSize: ChatStyle.entry.message.file.iconSize
visible: !$chatEntry.isOutgoing && !$chatEntry.wasDownloaded
}
MouseArea {
function handleMouseMove (mouse) {
thumbnailProvider.state = Utils.pointIsInItem(this, thumbnailProvider, mouse)
? 'hovered'
: ''
}
anchors.fill: parent
cursorShape: containsMouse
? Qt.PointingHandCursor
: Qt.ArrowCursor
hoverEnabled: true
visible: !rectangle.isNotDelivered && !$chatEntry.isOutgoing
onClicked: {
if (Utils.pointIsInItem(this, thumbnailProvider, mouse)) {
proxyModel.openFile(index)
} else if ($chatEntry.wasDownloaded) {
proxyModel.openFileDirectory(index)
} else {
proxyModel.downloadFile(index)
}
}
onExited: thumbnailProvider.state = ''
onMouseXChanged: handleMouseMove.call(this, mouse)
onMouseYChanged: handleMouseMove.call(this, mouse)
}
}
// -------------------------------------------------------------------------
// Resend/Remove file message.
// -------------------------------------------------------------------------
Row {
spacing: ChatStyle.entry.message.extraContent.spacing
Component {
id: icon
Icon {
anchors.centerIn: parent
icon: rectangle.isNotDelivered
? 'chat_error'
: (rectangle.isRead ? 'chat_read' : 'chat_delivered')
iconSize: ChatStyle.entry.message.outgoing.sendIconSize
MouseArea {
anchors.fill: parent
onClicked: isNotDelivered && proxyModel.resendMessage(index)
}
}
}
Component {
id: indicator
Item {
anchors.fill: parent
BusyIndicator {
anchors.centerIn: parent
height: ChatStyle.entry.message.outgoing.busyIndicatorSize
width: ChatStyle.entry.message.outgoing.busyIndicatorSize
}
}
}
Loader {
height: ChatStyle.entry.lineHeight
width: ChatStyle.entry.message.outgoing.areaSize
sourceComponent: $chatEntry.isOutgoing
? (
$chatEntry.status === ChatModel.MessageStatusInProgress
? indicator
: icon
) : undefined
}
ActionButton {
height: ChatStyle.entry.lineHeight
icon: 'delete'
iconSize: ChatStyle.entry.deleteIconSize
visible: isHoverEntry()
onClicked: removeEntry()
}
}
}
}