linphone-desktop/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml
Julien Wadel f4f92094b3 - Add auto download mode and use 10Mb as default.
- Fix notification thumbnail display on receiving file
- Fix empty name on uploading files
- Fix readonly chat room when someone is leaving
- Remove downloaded file on ephemerals
- Reduce iteration on background
2022-03-18 13:00:14 +01:00

283 lines
8.9 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 LinphoneEnums 1.0
import Linphone.Styles 1.0
import Utils 1.0
import Units 1.0
import ColorsList 1.0
// =============================================================================
// TODO : into Loader
Row {
id:mainRow
property ChatMessageModel chatMessageModel: contentModel && contentModel.chatMessageModel
property ContentModel contentModel
property bool isOutgoing : chatMessageModel && ( chatMessageModel.isOutgoing || chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
property int fitWidth: visible ? Math.max(fileName.implicitWidth + 5 + thumbnailProvider.width + 3*ChatStyle.entry.message.file.margins
, Math.max(ChatStyle.entry.message.file.width, ChatStyle.entry.message.outgoing.areaSize)) : 0
property int fitHeight: visible ? rectangle.height : 0
signal copyAllDone()
signal copySelectionDone()
signal forwardClicked()
height: fitHeight
visible: contentModel && (contentModel.isFile() || contentModel.isFileTransfer()) && !contentModel.isVoiceRecording()
// ---------------------------------------------------------------------------
// File message.
// ---------------------------------------------------------------------------
Row {
spacing: ChatStyle.entry.message.extraContent.leftMargin
Item{
width: mainRow.width
height:rectangle.height
Rectangle {
id: rectangle
readonly property bool isError: chatMessageModel && Utils.includes([
LinphoneEnums.ChatMessageStateFileTransferError,
LinphoneEnums.ChatMessageStateNotDelivered,
], chatMessageModel.state)
readonly property bool isUploaded: chatMessageModel && chatMessageModel.state == LinphoneEnums.ChatMessageStateDelivered
readonly property bool isDelivered: chatMessageModel && chatMessageModel.state == LinphoneEnums.ChatMessageStateDeliveredToUser
readonly property bool isRead: chatMessageModel && chatMessageModel.state == LinphoneEnums.ChatMessageStateDisplayed
property string thumbnail : mainRow.contentModel ? mainRow.contentModel.thumbnail : ''
color: 'transparent'
height: ChatStyle.entry.message.file.height
width: mainRow.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: thumbnailImage
Image {
id: thumbnailImageSource
mipmap: SettingsModel.mipmapEnabled
source: mainRow.contentModel.thumbnail
fillMode: Image.PreserveAspectFit
sourceSize.width: 100
sourceSize.height: 100
}
}
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: (mainRow.contentModel?Utils.getExtension(mainRow.contentModel.name).toUpperCase():'')
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
Loader {
id: thumbnailProvider
Layout.fillHeight: true
Layout.preferredWidth: parent.height
sourceComponent: (mainRow.contentModel ? (mainRow.contentModel.thumbnail ? thumbnailImage : extension ): undefined)
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.
// ---------------------------------------------------------------------
Item{
Layout.fillWidth: true
Layout.fillHeight: true
Column {
anchors.fill: parent
spacing: ChatStyle.entry.message.file.status.spacing
Text {
id: fileName
color: isOutgoing
? ChatStyle.entry.message.outgoing.text.color
: ChatStyle.entry.message.incoming.text.color
elide: Text.ElideRight
font {
bold: true
pointSize: isOutgoing
? ChatStyle.entry.message.outgoing.text.pointSize
: ChatStyle.entry.message.incoming.text.pointSize
}
text: (mainRow.contentModel ? mainRow.contentModel.name : '')
width: parent.width
}
ProgressBar {
id: progressBar
height: ChatStyle.entry.message.file.status.bar.height
width: parent.width
to: (mainRow.contentModel ? mainRow.contentModel.fileSize : 0)
value: mainRow.contentModel ? mainRow.contentModel.fileOffset || to : to
visible: value != to
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 {
visible: progressBar.value != progressBar.to
color: fileName.color
elide: Text.ElideRight
font.pointSize: fileName.font.pointSize
text: {
if(mainRow.contentModel){
var fileSize = Utils.formatSize(mainRow.contentModel.fileSize)
return progressBar.visible
? Utils.formatSize(mainRow.contentModel.fileOffset) + '/' + fileSize
: fileSize
}else
return ''
}
}
}
}
}
Icon {
id:downloadButton
anchors {
bottom: parent.bottom
bottomMargin: ChatStyle.entry.message.file.margins
right: parent.right
rightMargin: ChatStyle.entry.message.file.margins
}
icon: ChatStyle.entry.message.file.download.icon
iconSize: ChatStyle.entry.message.file.download.iconSize
overwriteColor: isOutgoing ? ChatStyle.entry.message.file.download.outgoingColor : ChatStyle.entry.message.file.download.incomingColor
visible: !progressBar.visible && (mainRow.contentModel? !mainRow.contentModel.wasDownloaded : false)
}
MouseArea {
function handleMouseMove (mouse) {
thumbnailProvider.state = Utils.pointIsInItem(this, thumbnailProvider, mouse)
? 'hovered'
: ''
}
anchors.fill: parent
visible: true
//downloadButton.visible || ((rectangle.isUploaded || rectangle.isRead) && !isOutgoing) || isOutgoing
//onVisibleChanged: console.log("Mouse of "+mainRow.contentModel.name+" / "+downloadButton.visible
// +"/"+rectangle.isUploaded +"/"+rectangle.isRead)
onClicked: {
if (Utils.pointIsInItem(this, thumbnailProvider, mouse)) {
mainRow.contentModel.openFile()
} else if (mainRow.contentModel && mainRow.contentModel.wasDownloaded) {
mainRow.contentModel.openFile(true)// Show directory
thumbnailProvider.state = ''
} else {
mainRow.contentModel.downloadFile()
thumbnailProvider.state = ''
}
}
onExited: thumbnailProvider.state = ''
onMouseXChanged: handleMouseMove.call(this, mouse)
onMouseYChanged: handleMouseMove.call(this, mouse)
}
}
}
}
}