From 8a2e842cd74c5ef34efde3cf7aa95414958e572f Mon Sep 17 00:00:00 2001 From: Gaelle Braud Date: Thu, 2 Oct 2025 11:38:07 +0200 Subject: [PATCH] enlarge video size if single file sent wait for chat messages model to be reset before changing chat (fix #LINQT-2011) --- Linphone/core/chat/message/EventLogList.cpp | 73 +++++++++++++------ Linphone/core/chat/message/EventLogList.hpp | 4 + Linphone/view/CMakeLists.txt | 1 + .../Display/Chat/ChatMessageContent.qml | 17 +++++ .../Display/Chat/ChatMessagesListView.qml | 9 ++- .../Control/Display/Chat/VideoFileView.qml | 72 ++++++++++++++++++ .../Layout/Chat/MessageImdnStatusInfos.qml | 2 +- 7 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 Linphone/view/Control/Display/Chat/VideoFileView.qml diff --git a/Linphone/core/chat/message/EventLogList.cpp b/Linphone/core/chat/message/EventLogList.cpp index b9fd9a496..e796658c0 100644 --- a/Linphone/core/chat/message/EventLogList.cpp +++ b/Linphone/core/chat/message/EventLogList.cpp @@ -81,31 +81,53 @@ void EventLogList::connectItem(const QSharedPointer &item) { } } +void EventLogList::setIsUpdating(bool updating) { + if (mIsUpdating != updating) { + mIsUpdating = updating; + emit isUpdatingChanged(); + } +} + void EventLogList::setChatCore(QSharedPointer core) { - if (mChatCore != core) { - if (mChatCore) { - disconnect(mChatCore.get(), &ChatCore::eventsInserted, this, nullptr); + auto updateChatCore = [this](QSharedPointer core) { + if (mChatCore != core) { + if (mChatCore) { + disconnect(mChatCore.get(), &ChatCore::eventsInserted, this, nullptr); + disconnect(mChatCore.get(), &ChatCore::eventListCleared, this, nullptr); + } + mChatCore = core; + if (mChatCore) { + connect(mChatCore.get(), &ChatCore::eventListCleared, this, [this] { resetData(); }); + connect(mChatCore.get(), &ChatCore::eventsInserted, this, + [this](QList> list) { + auto eventsList = getSharedList(); + for (auto &event : list) { + auto it = std::find_if( + eventsList.begin(), eventsList.end(), + [event](const QSharedPointer item) { return item == event; }); + if (it == eventsList.end()) { + connectItem(event); + add(event); + int index; + get(event.get(), &index); + emit eventInserted(index, new EventLogGui(event)); + } + } + }); + } + lUpdate(); + emit chatGuiChanged(); } - mChatCore = core; - if (mChatCore) { - connect(mChatCore.get(), &ChatCore::eventListCleared, this, [this] { resetData(); }); - connect(mChatCore.get(), &ChatCore::eventsInserted, this, [this](QList> list) { - auto eventsList = getSharedList(); - for (auto &event : list) { - auto it = std::find_if(eventsList.begin(), eventsList.end(), - [event](const QSharedPointer item) { return item == event; }); - if (it == eventsList.end()) { - connectItem(event); - add(event); - int index; - get(event.get(), &index); - emit eventInserted(index, new EventLogGui(event)); - } - } - }); - } - lUpdate(); - emit chatGuiChanged(); + }; + if (mIsUpdating) { + connect(this, &EventLogList::isUpdatingChanged, this, [this, core, updateChatCore] { + if (!mIsUpdating) { + updateChatCore(core); + disconnect(this, &EventLogList::isUpdatingChanged, this, nullptr); + } + }); + } else { + updateChatCore(core); } } @@ -160,15 +182,19 @@ void EventLogList::setSelf(QSharedPointer me) { mCoreModelConnection->makeConnectToCore(&EventLogList::lUpdate, [this]() { mustBeInMainThread(log().arg(Q_FUNC_INFO)); + if (mChatCore) qDebug() << "reset messages model for chat core" << mChatCore << mChatCore->getTitle(); + setIsUpdating(true); beginResetModel(); mList.clear(); if (!mChatCore) { endResetModel(); + setIsUpdating(false); return; } auto chatModel = mChatCore->getModel(); if (!chatModel) { endResetModel(); + setIsUpdating(false); return; } mCoreModelConnection->invokeToModel([this, chatModel]() { @@ -193,6 +219,7 @@ void EventLogList::setSelf(QSharedPointer me) { for (auto i : *events) mList << i.template objectCast(); endResetModel(); + setIsUpdating(false); }); }); }); diff --git a/Linphone/core/chat/message/EventLogList.hpp b/Linphone/core/chat/message/EventLogList.hpp index 94b2e04e8..f1efe26c2 100644 --- a/Linphone/core/chat/message/EventLogList.hpp +++ b/Linphone/core/chat/message/EventLogList.hpp @@ -48,6 +48,8 @@ public: void connectItem(const QSharedPointer &item); void disconnectItem(const QSharedPointer &item); + void setIsUpdating(bool updating); + int findFirstUnreadIndex(); void findChatMessageWithFilter(QString filter, @@ -66,12 +68,14 @@ signals: void messageWithFilterFound(int index); void listAboutToBeReset(); void chatGuiChanged(); + void isUpdatingChanged(); private: QString mFilter; QSharedPointer mChatCore; QSharedPointer> mChatModelConnection; QSharedPointer> mCoreModelConnection; + bool mIsUpdating = false; DECLARE_ABSTRACT_OBJECT }; diff --git a/Linphone/view/CMakeLists.txt b/Linphone/view/CMakeLists.txt index 9e7d1f520..e63776d9c 100644 --- a/Linphone/view/CMakeLists.txt +++ b/Linphone/view/CMakeLists.txt @@ -69,6 +69,7 @@ list(APPEND _LINPHONEAPP_QML_FILES view/Control/Display/Chat/FileView.qml view/Control/Display/Chat/ImageFileView.qml view/Control/Display/Chat/AnimatedImageFileView.qml + view/Control/Display/Chat/VideoFileView.qml view/Control/Display/Contact/Avatar.qml view/Control/Display/Contact/Contact.qml view/Control/Display/Contact/Presence.qml diff --git a/Linphone/view/Control/Display/Chat/ChatMessageContent.qml b/Linphone/view/Control/Display/Chat/ChatMessageContent.qml index 80f3f38bf..834fdfc84 100644 --- a/Linphone/view/Control/Display/Chat/ChatMessageContent.qml +++ b/Linphone/view/Control/Display/Chat/ChatMessageContent.qml @@ -2,6 +2,8 @@ import QtQuick import QtQuick.Effects import QtQuick.Layouts import QtQuick.Controls.Basic as Control +import QtMultimedia + import Linphone import UtilsCpp @@ -98,12 +100,27 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter fillMode: Image.PreserveAspectFit } + VideoFileView { + id: singleVideoFile + visible: mainItem.filescontentProxy.count === 1 && UtilsCpp.isVideo(contentGui.core.filePath) + contentGui: mainItem.filescontentProxy.count === 1 + ? mainItem.filescontentProxy.getChatMessageContentAtIndex(0) + : null + width: Math.round(285 * DefaultStyle.dp) + height: Math.round(285 * DefaultStyle.dp) + Layout.preferredWidth: videoOutput.contentRect.width + Layout.preferredHeight: videoOutput.contentRect.height + Layout.alignment: Qt.AlignHCenter + fillMode: VideoOutput.PreserveAspectFit + } + // FILES ChatFilesGridLayout { id: messageFilesList visible: mainItem.filescontentProxy.count > 0 && !singleImageFile.visible && !singleAnimatedImageFile.visible + && !singleVideoFile.visible Layout.fillWidth: visible Layout.fillHeight: visible maxWidth: Math.round(115*3 * DefaultStyle.dp) diff --git a/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml b/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml index f953a95fe..4d3475643 100644 --- a/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml +++ b/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml @@ -93,13 +93,16 @@ ListView { markIndexAsRead(index) } } - onModelAboutToBeReset: loading = true - onModelReset: Qt.callLater(function() { + onModelAboutToBeReset: { + loading = true + } + onModelReset: { loading = false var index = eventLogProxy.findFirstUnreadIndex() positionViewAtIndex(index, ListView.Beginning) eventLogProxy.markIndexAsRead(index) - }) + } + onChatGuiChanged: forceLayout() onIndexWithFilterFound: (index) => { if (index !== -1) { currentIndex = index diff --git a/Linphone/view/Control/Display/Chat/VideoFileView.qml b/Linphone/view/Control/Display/Chat/VideoFileView.qml new file mode 100644 index 000000000..90a3dc4b0 --- /dev/null +++ b/Linphone/view/Control/Display/Chat/VideoFileView.qml @@ -0,0 +1,72 @@ +import QtQuick +import QtQuick.Controls as Control +import QtQuick.Layouts +import QtMultimedia + +import Linphone +import UtilsCpp +import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils + +// ============================================================================= + +Rectangle { + id: mainItem + color: "transparent"//DefaultStyle.grey_1000 + property ChatMessageContentGui contentGui + property string filePath: contentGui && contentGui.core.filePath + property var fillMode: playbackState === MediaPlayer.PlayingState ? VideoOutput.PreserveAspectFit : VideoOutput.PreserveAspectCrop + property alias videoOutput: output + property string source: mediaPlayer.source + MediaPlayer { + id: mediaPlayer + source: UtilsCpp.isVideo(mainItem.filePath) ? "file:///" + mainItem.filePath : "" + position: 100 + videoOutput: output + } + VideoOutput { + id: output + fillMode: mainItem.fillMode + endOfStreamPolicy: VideoOutput.KeepLastFrame + width: mainItem.width + height: mainItem.height + Component.onCompleted: { + // We need to start the video so the content rect of the + // video output is updated + mediaPlayer.play() + mediaPlayer.pause() + } + Text { + z: parent.z + 1 + property int timeDisplayed: mediaPlayer.playbackState === MediaPlayer.PlayingState ? mediaPlayer.position : mediaPlayer.duration + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.bottomMargin: Math.round(6 * DefaultStyle.dp) + anchors.leftMargin: Math.round(6 * DefaultStyle.dp) + text: UtilsCpp.formatDuration(timeDisplayed) + color: DefaultStyle.grey_0 + font { + pixelSize: Typography.d1.pixelSize + weight: Typography.d1.weight + } + } + } + MouseArea { + propagateComposedEvents: false + enabled: mainItem.visible + anchors.fill: parent + hoverEnabled: false + acceptedButtons: Qt.LeftButton + onClicked: (mouse) => { + mouse.accepted = true + mediaPlayer.playbackState === MediaPlayer.PlayingState ? mediaPlayer.pause() : mediaPlayer.play() + } + } + EffectImage { + anchors.centerIn: parent + visible: mediaPlayer.playbackState !== MediaPlayer.PlayingState + width: Math.round(24 * DefaultStyle.dp) + height: Math.round(24 * DefaultStyle.dp) + imageSource: AppIcons.playFill + colorizationColor: DefaultStyle.main2_0 + } +} \ No newline at end of file diff --git a/Linphone/view/Page/Layout/Chat/MessageImdnStatusInfos.qml b/Linphone/view/Page/Layout/Chat/MessageImdnStatusInfos.qml index 5eb8d6e2d..362b91dc9 100644 --- a/Linphone/view/Page/Layout/Chat/MessageImdnStatusInfos.qml +++ b/Linphone/view/Page/Layout/Chat/MessageImdnStatusInfos.qml @@ -12,7 +12,7 @@ MessageInfosLayout { tabbarModel: chatMessageGui ? chatMessageGui.core.imdnStatusListAsString : [] listModel: ImdnStatusProxy { imdnStatusList: chatMessageGui ? chatMessageGui.core.imdnStatusList : [] - filter: chatMessageGui && chatMessageGui.core.imdnStatusAsSingletons[mainItem.tabbar.currentIndex]?.state || "" + filter: chatMessageGui && chatMessageGui.core.imdnStatusAsSingletons[mainItem.tabbar.currentIndex]?.state || LinphoneEnums.ChatMessageState.StateIdle } listView.delegate: Item {