From 33afd2a17a558f56ef3ac8a4292c3edaefd7fb4d Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 12 May 2022 19:58:07 +0200 Subject: [PATCH] Add Animated images to chat and notifications. Higher chat bubbles when thumbnails can be shown. --- linphone-app/src/utils/Utils.cpp | 8 + linphone-app/src/utils/Utils.hpp | 1 + .../modules/Linphone/Chat/ChatFileMessage.qml | 27 +++- .../NotificationReceivedFileMessage.qml | 151 ++++++++++-------- .../Linphone/Styles/Chat/ChatStyle.qml | 1 + 5 files changed, 117 insertions(+), 71 deletions(-) diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index f9527a218..f0a92cb27 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -527,3 +527,11 @@ bool Utils::isMe(const QString& address){ bool Utils::isMe(const std::shared_ptr& address){ return address ? CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(address) : false; } + +bool Utils::isAnimatedImage(const QString& path){ + QFileInfo info(path); + if( !info.exists()) + return false; + QImageReader reader(path); + return reader.supportsAnimation() && reader.imageCount() > 1; +} diff --git a/linphone-app/src/utils/Utils.hpp b/linphone-app/src/utils/Utils.hpp index 4bb7ceb16..204ca2f8e 100644 --- a/linphone-app/src/utils/Utils.hpp +++ b/linphone-app/src/utils/Utils.hpp @@ -60,6 +60,7 @@ public: Q_INVOKABLE static QString getDisplayName(const QString& address); Q_INVOKABLE static QString toString(const LinphoneEnums::TunnelMode& mode); Q_INVOKABLE static bool isMe(const QString& address); + Q_INVOKABLE static bool isAnimatedImage(const QString& path); //---------------------------------------------------------------------------------- static inline QString coreStringToAppString (const std::string &str) { diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml index a1a649142..7c3907c38 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml @@ -9,6 +9,7 @@ import Linphone.Styles 1.0 import Utils 1.0 import Units 1.0 import ColorsList 1.0 +import UtilsCpp 1.0 // ============================================================================= // TODO : into Loader @@ -51,7 +52,7 @@ Row { property string thumbnail : mainRow.contentModel ? mainRow.contentModel.thumbnail : '' color: 'transparent' - height: ChatStyle.entry.message.file.height + height: thumbnail ? ChatStyle.entry.message.file.heightWithThumbnail : ChatStyle.entry.message.file.height width: mainRow.width radius: ChatStyle.entry.message.radius @@ -77,8 +78,20 @@ Row { mipmap: SettingsModel.mipmapEnabled source: mainRow.contentModel.thumbnail fillMode: Image.PreserveAspectFit - sourceSize.width: 100 - sourceSize.height: 100 + //sourceSize.width: 200 + //sourceSize.height: 100 + } + } + Component { + id: animatedImage + + AnimatedImage { + id: animatedImageSource + mipmap: SettingsModel.mipmapEnabled + source: 'file:/'+mainRow.contentModel.filePath + fillMode: Image.PreserveAspectFit + //width: 200 + //height: 100 } } @@ -105,9 +118,13 @@ Row { id: thumbnailProvider Layout.fillHeight: true - Layout.preferredWidth: parent.height + Layout.preferredWidth: parent.height*4/3 - sourceComponent: (mainRow.contentModel ? (mainRow.contentModel.thumbnail ? thumbnailImage : extension ): undefined) + sourceComponent: (mainRow.contentModel ? + (mainRow.contentModel.wasDownloaded && UtilsCpp.isAnimatedImage(mainRow.contentModel.filePath) + ? animatedImage + : (mainRow.contentModel.thumbnail ? thumbnailImage : extension ) + ) : undefined) ScaleAnimator { id: thumbnailProviderAnimator diff --git a/linphone-app/ui/modules/Linphone/Notifications/NotificationReceivedFileMessage.qml b/linphone-app/ui/modules/Linphone/Notifications/NotificationReceivedFileMessage.qml index b8cfe2dd1..2cc628768 100644 --- a/linphone-app/ui/modules/Linphone/Notifications/NotificationReceivedFileMessage.qml +++ b/linphone-app/ui/modules/Linphone/Notifications/NotificationReceivedFileMessage.qml @@ -6,73 +6,92 @@ import Linphone 1.0 import Linphone.Styles 1.0 import Utils 1.0 +import UtilsCpp 1.0 + // ============================================================================= Notification { - id: notification - - icon: 'file_sign' - overrodeHeight: NotificationReceivedFileMessageStyle.overrodeHeight - - // --------------------------------------------------------------------------- - - readonly property string fileUri: notificationData && notificationData.fileUri || '' - readonly property string imageUri: notificationData && notificationData.imageUri || '' - - // --------------------------------------------------------------------------- - - Loader { - active: Boolean(notification.fileUri) - anchors { - fill: parent - - leftMargin: NotificationReceivedFileMessageStyle.leftMargin - rightMargin: NotificationReceivedFileMessageStyle.rightMargin - } - - sourceComponent: RowLayout { - anchors.fill: parent - spacing: NotificationReceivedFileMessageStyle.spacing - - Text { - Layout.fillWidth: true - - color: NotificationReceivedFileMessageStyle.fileName.color - elide: Text.ElideRight - font.pointSize: NotificationReceivedFileMessageStyle.fileName.pointSize - text: Utils.basename(notification.fileUri) - visible:!image.visible - } - Image{ - id:image - mipmap: SettingsModel.mipmapEnabled - Layout.fillHeight: true - Layout.fillWidth: true - fillMode: Image.PreserveAspectFit - source: (imageUri ?"image://external/"+notification.imageUri : '') - visible: image.status == Image.Ready - } - - Text { - Layout.preferredWidth: NotificationReceivedFileMessageStyle.fileSize.width - - color: NotificationReceivedFileMessageStyle.fileSize.color - elide: Text.ElideRight - font.pointSize: NotificationReceivedFileMessageStyle.fileSize.pointSize - horizontalAlignment: Text.AlignRight - text: Utils.formatSize(notification.notificationData.fileSize) - } - } - - MouseArea { - anchors.fill: parent - - onClicked: notification._close(function () { - var uri = Utils.getUriFromSystemPath(notification.fileUri) - if (!Qt.openUrlExternally(uri)) { - Qt.openUrlExternally(Utils.dirname(uri)) - } - }) - } - } + id: notification + + icon: 'file_sign' + overrodeHeight: NotificationReceivedFileMessageStyle.overrodeHeight + + // --------------------------------------------------------------------------- + + readonly property string fileUri: notificationData && notificationData.fileUri || '' + readonly property string imageUri: notificationData && notificationData.imageUri || '' + property string systemFileUri: Utils.getUriFromSystemPath(notification.fileUri) + + // --------------------------------------------------------------------------- + + Loader { + active: Boolean(notification.fileUri) + anchors { + fill: parent + + leftMargin: NotificationReceivedFileMessageStyle.leftMargin + rightMargin: NotificationReceivedFileMessageStyle.rightMargin + } + + sourceComponent: RowLayout { + anchors.fill: parent + spacing: NotificationReceivedFileMessageStyle.spacing + + Text { + Layout.fillWidth: true + + color: NotificationReceivedFileMessageStyle.fileName.color + elide: Text.ElideRight + font.pointSize: NotificationReceivedFileMessageStyle.fileName.pointSize + text: Utils.basename(notification.fileUri) + visible:!normalImage.visible && !animatedImage.visible + } + Loader{ + Layout.fillHeight: true + Layout.fillWidth: true + + sourceComponent: notification.fileUri && UtilsCpp.isAnimatedImage(notification.fileUri) ? animatedImage : normalImage + active: fileUri || imageUri + Component{ + id: normalImage + Image{ + id:image + mipmap: SettingsModel.mipmapEnabled + fillMode: Image.PreserveAspectFit + source: (imageUri ?"image://external/"+notification.imageUri : '') + visible: image.status == Image.Ready + } + } + Component{ + id: animatedImage + AnimatedImage{ + id:image + mipmap: SettingsModel.mipmapEnabled + fillMode: Image.PreserveAspectFit + source: (systemFileUri ? systemFileUri: '') + } + } + } + + Text { + Layout.preferredWidth: NotificationReceivedFileMessageStyle.fileSize.width + + color: NotificationReceivedFileMessageStyle.fileSize.color + elide: Text.ElideRight + font.pointSize: NotificationReceivedFileMessageStyle.fileSize.pointSize + horizontalAlignment: Text.AlignRight + text: Utils.formatSize(notification.notificationData.fileSize) + } + } + + MouseArea { + anchors.fill: parent + + onClicked: notification._close(function () { + if (!Qt.openUrlExternally(systemFileUri)) { + Qt.openUrlExternally(Utils.dirname(systemFileUri)) + } + }) + } + } } diff --git a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml index 88f96cf02..55262dee7 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml @@ -183,6 +183,7 @@ QtObject { property QtObject file: QtObject { property int height: 64 + property int heightWithThumbnail: 200 property int iconSize: 18 property int margins: 8 property int spacing: 8