diff --git a/Linphone/core/chat/message/ChatMessageCore.cpp b/Linphone/core/chat/message/ChatMessageCore.cpp index c85dea4fd..a86131b16 100644 --- a/Linphone/core/chat/message/ChatMessageCore.cpp +++ b/Linphone/core/chat/message/ChatMessageCore.cpp @@ -230,9 +230,11 @@ void ChatMessageCore::setSelf(QSharedPointer me) { }); } }); - mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageRead, [this]() { - mChatMessageModelConnection->invokeToCore([this] { setIsRead(true); }); - }); + mChatMessageModelConnection->makeConnectToModel( + &ChatMessageModel::messageRead, [this](const std::shared_ptr &chatMessage) { + bool isRead = chatMessage->isRead(); + mChatMessageModelConnection->invokeToCore([this, isRead] { setIsRead(isRead); }); + }); mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lSendReaction, [this](const QString &reaction) { mChatMessageModelConnection->invokeToModel([this, reaction] { mChatMessageModel->sendReaction(reaction); }); }); diff --git a/Linphone/core/chat/message/EventLogList.cpp b/Linphone/core/chat/message/EventLogList.cpp index 18be0c573..ee5e94b92 100644 --- a/Linphone/core/chat/message/EventLogList.cpp +++ b/Linphone/core/chat/message/EventLogList.cpp @@ -298,12 +298,14 @@ void EventLogList::setSelf(QSharedPointer me) { if (!mChatCore) { endResetModel(); setIsUpdating(false); + emit modelUpdated(); return; } auto chatModel = mChatCore->getModel(); if (!chatModel) { endResetModel(); setIsUpdating(false); + emit modelUpdated(); return; } mCoreModelConnection->invokeToModel([this, chatModel]() { @@ -321,6 +323,7 @@ void EventLogList::setSelf(QSharedPointer me) { } endResetModel(); setIsUpdating(false); + emit modelUpdated(); }); }); }); diff --git a/Linphone/core/chat/message/EventLogList.hpp b/Linphone/core/chat/message/EventLogList.hpp index deec5b88e..a9393ba5d 100644 --- a/Linphone/core/chat/message/EventLogList.hpp +++ b/Linphone/core/chat/message/EventLogList.hpp @@ -67,6 +67,7 @@ public: signals: void lUpdate(); + void modelUpdated(); void filterChanged(QString filter); void eventInsertedByUser(int index); void messageWithFilterFound(int index); diff --git a/Linphone/core/chat/message/EventLogProxy.cpp b/Linphone/core/chat/message/EventLogProxy.cpp index a1e45850d..5bc86365c 100644 --- a/Linphone/core/chat/message/EventLogProxy.cpp +++ b/Linphone/core/chat/message/EventLogProxy.cpp @@ -57,6 +57,7 @@ void EventLogProxy::setSourceModel(QAbstractItemModel *model) { int proxyIndex = mapFromSource(newEventLogList->index(i, 0)).row(); emit eventInsertedByUser(proxyIndex); }); + connect(newEventLogList, &EventLogList::modelUpdated, this, &EventLogProxy::modelUpdated); } QSortFilterProxyModel::setSourceModel(model); } diff --git a/Linphone/core/chat/message/EventLogProxy.hpp b/Linphone/core/chat/message/EventLogProxy.hpp index 093c19543..dde4f67c2 100644 --- a/Linphone/core/chat/message/EventLogProxy.hpp +++ b/Linphone/core/chat/message/EventLogProxy.hpp @@ -87,6 +87,7 @@ signals: void maxDisplayItemsChanged(); void displayItemsStepChanged(); void filterTextChanged(); + void modelUpdated(); protected: QSharedPointer mList; diff --git a/Linphone/core/search/MagicSearchList.cpp b/Linphone/core/search/MagicSearchList.cpp index 984ae9c16..922e6d7ba 100644 --- a/Linphone/core/search/MagicSearchList.cpp +++ b/Linphone/core/search/MagicSearchList.cpp @@ -49,7 +49,7 @@ MagicSearchList::~MagicSearchList() { mustBeInMainThread("~" + getClassName()); } -void MagicSearchList::setSelf(QSharedPointer me) { +void MagicSearchList::setSelf(const QSharedPointer &me) { mCoreModelConnection = SafeConnection::create(me, CoreModel::getInstance()); mCoreModelConnection->makeConnectToModel( &CoreModel::friendCreated, [this](const std::shared_ptr &f) { diff --git a/Linphone/core/search/MagicSearchList.hpp b/Linphone/core/search/MagicSearchList.hpp index ea61dec1d..bcb33bb41 100644 --- a/Linphone/core/search/MagicSearchList.hpp +++ b/Linphone/core/search/MagicSearchList.hpp @@ -40,7 +40,7 @@ public: MagicSearchList(QObject *parent = Q_NULLPTR); ~MagicSearchList(); - void setSelf(QSharedPointer me); + void setSelf(const QSharedPointer &me); void connectContact(FriendCore *data); void setSearch(const QString &search); void setResults(const QList> &contacts); diff --git a/Linphone/data/languages/de.ts b/Linphone/data/languages/de.ts index 4476b8ddc..5719add64 100644 --- a/Linphone/data/languages/de.ts +++ b/Linphone/data/languages/de.ts @@ -2472,44 +2472,44 @@ Error ChatMessagesListView - - + + popup_info_find_message_title Find message Nachricht suchen - + info_popup_no_result_message No result found Keine Ergebnisse gefunden - + info_popup_first_result_message First result reached Erstes Ergebnis erreicht - + info_popup_last_result_message Last result reached Letztes Ergebnis erreicht - + chat_message_list_encrypted_header_title End to end encrypted chat Ende-zu-Ende-verschlüsselter Chat - + unencrypted_conversation_warning This conversation is not encrypted ! Dieser Chat ist nicht verschlüsselt! - + chat_message_list_encrypted_header_message Messages in this conversation are e2e encrypted. Only your correspondent can decrypt them. @@ -2517,7 +2517,7 @@ Error Nur Ihr Gesprächspartner kann sie entschlüsseln. - + chat_message_list_not_encrypted_header_message Messages are not end to end encrypted, may sure you don't share any sensitive information ! @@ -2525,7 +2525,7 @@ Nur Ihr Gesprächspartner kann sie entschlüsseln. Stellen Sie sicher, dass Sie keine sensiblen Informationen teilen! - + chat_message_is_writing_info %1 is writing… %1 schreibt… diff --git a/Linphone/data/languages/en.ts b/Linphone/data/languages/en.ts index 06b9bf94c..1e2b3c5b6 100644 --- a/Linphone/data/languages/en.ts +++ b/Linphone/data/languages/en.ts @@ -2430,44 +2430,44 @@ Error ChatMessagesListView - - + + popup_info_find_message_title Find message Find message - + info_popup_no_result_message No result found No result found - + info_popup_first_result_message First result reached First result reached - + info_popup_last_result_message Last result reached Last result reached - + chat_message_list_encrypted_header_title End to end encrypted chat End to end encrypted chat - + unencrypted_conversation_warning This conversation is not encrypted ! This conversation is not encrypted ! - + chat_message_list_encrypted_header_message Messages in this conversation are e2e encrypted. Only your correspondent can decrypt them. @@ -2475,7 +2475,7 @@ Error Only your correspondent can decrypt them. - + chat_message_list_not_encrypted_header_message Messages are not end to end encrypted, may sure you don't share any sensitive information ! @@ -2483,7 +2483,7 @@ Only your correspondent can decrypt them. may sure you don't share any sensitive information ! - + chat_message_is_writing_info %1 is writing… %1 is writing… diff --git a/Linphone/data/languages/fr.ts b/Linphone/data/languages/fr.ts index 86aec6f51..b2b65988a 100644 --- a/Linphone/data/languages/fr.ts +++ b/Linphone/data/languages/fr.ts @@ -2405,44 +2405,44 @@ Error ChatMessagesListView - - + + popup_info_find_message_title Find message Trouver un message - + info_popup_no_result_message No result found Aucun résultat trouvé - + info_popup_first_result_message First result reached Premier résultat atteint - + info_popup_last_result_message Last result reached Dernier résultat atteint - + chat_message_list_encrypted_header_title End to end encrypted chat Conversation chiffrée de bout en bout - + unencrypted_conversation_warning This conversation is not encrypted ! Cette conversation n'est pas chiffrée ! - + chat_message_list_encrypted_header_message Messages in this conversation are e2e encrypted. Only your correspondent can decrypt them. @@ -2450,7 +2450,7 @@ Error en bout. Seul votre correspondant peut les déchiffrer. - + chat_message_list_not_encrypted_header_message Messages are not end to end encrypted, may sure you don't share any sensitive information ! @@ -2458,7 +2458,7 @@ en bout. Seul votre correspondant peut les déchiffrer. assurez-vous de ne pas partager d’informations sensibles ! - + chat_message_is_writing_info %1 is writing… %1 est en train d'écrire… diff --git a/Linphone/model/chat/message/ChatMessageModel.cpp b/Linphone/model/chat/message/ChatMessageModel.cpp index 5e1622de5..733768f2a 100644 --- a/Linphone/model/chat/message/ChatMessageModel.cpp +++ b/Linphone/model/chat/message/ChatMessageModel.cpp @@ -44,6 +44,15 @@ ChatMessageModel::ChatMessageModel(const std::shared_ptr mEphemeralTimer.stop(); deleteMessageFromChatRoom(false); }); + // We need to force this signal sending because there is no callback to know when a message has been read + connect(CoreModel::getInstance().get(), &CoreModel::chatRoomRead, this, + [this](const std::shared_ptr &core, const std::shared_ptr &chatRoom) { + if (chatRoom == mMonitor->getChatRoom()) { + if (mMonitor->isRead()) { + emit messageRead(mMonitor); + } + } + }); } ChatMessageModel::~ChatMessageModel() { @@ -91,7 +100,7 @@ bool ChatMessageModel::isRead() const { void ChatMessageModel::markAsRead() { mMonitor->markAsRead(); - emit messageRead(); + emit messageRead(mMonitor); emit CoreModel::getInstance()->messageReadInChatRoom(mMonitor->getChatRoom()); } diff --git a/Linphone/model/chat/message/ChatMessageModel.hpp b/Linphone/model/chat/message/ChatMessageModel.hpp index 5ad9b71b2..80c000a4c 100644 --- a/Linphone/model/chat/message/ChatMessageModel.hpp +++ b/Linphone/model/chat/message/ChatMessageModel.hpp @@ -65,7 +65,7 @@ public: signals: void messageDeleted(bool deletedByUser); - void messageRead(); + void messageRead(const std::shared_ptr &chatMessage); void msgStateChanged(const std::shared_ptr &message, linphone::ChatMessage::State state); void newMessageReaction(const std::shared_ptr &message, @@ -99,6 +99,7 @@ signals: private: linphone::ChatMessage::State mMessageState; QTimer mEphemeralTimer; + std::weak_ptr mChatRoom; DECLARE_ABSTRACT_OBJECT diff --git a/Linphone/model/conference/ConferenceInfoModel.cpp b/Linphone/model/conference/ConferenceInfoModel.cpp index 65c229a21..4542c17a1 100644 --- a/Linphone/model/conference/ConferenceInfoModel.cpp +++ b/Linphone/model/conference/ConferenceInfoModel.cpp @@ -32,7 +32,8 @@ DEFINE_ABSTRACT_OBJECT(ConferenceInfoModel) ConferenceInfoModel::ConferenceInfoModel(const std::shared_ptr &conferenceInfo, QObject *parent) - : mConferenceInfo(conferenceInfo) { + // TODO : remove cloning when a fix will be done in SDK (#SDK-1001 ticket) + : mConferenceInfo(conferenceInfo->clone()) { mustBeInLinphoneThread(getClassName()); } diff --git a/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml b/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml index a152f0285..4696c9ce8 100644 --- a/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml +++ b/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml @@ -18,7 +18,7 @@ ListView { property real busyIndicatorSize: Utils.getSizeWithScreenRatio(60) property bool loading: false property bool isEncrypted: chat && chat.core.isEncrypted - highlightFollowsCurrentItem: false + highlightFollowsCurrentItem: true verticalLayoutDirection: ListView.BottomToTop signal showReactionsForMessageRequested(ChatMessageGui chatMessage) @@ -73,7 +73,7 @@ ListView { onAtYBeginningChanged: if (atYBeginning && count !== 0) { eventLogProxy.displayMore() } - onAtYEndChanged: if (atYEnd && chat) { + onAtYEndChanged: if (atYEnd && chat && count !== 0) { chat.core.lMarkAsRead() } @@ -86,10 +86,13 @@ ListView { onModelAboutToBeReset: { loading = true } - onModelReset: { + onModelUpdated: { loading = false var index = eventLogProxy.findFirstUnreadIndex() - mainItem.positionViewAtIndex(index, ListView.Contain) + var itemToSelect = mainItem.itemAtIndex(index) + mainItem.positionViewAtIndex(index, ListView.Beginning) + var lastMessage = itemAtIndex(0) + mainItem.lastItemVisible = lastMessage.isFullyVisible eventLogProxy.markIndexAsRead(index) } onEventInsertedByUser: (index) => { @@ -224,7 +227,7 @@ ListView { indicatorWidth: mainItem.busyIndicatorSize indicatorColor: DefaultStyle.main1_500_main } - + delegate: DelegateChooser { role: "eventType" DelegateChoice {