From df28674ced43b829093651ab85e707804a7e13d3 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 17 Jan 2022 18:20:54 +0100 Subject: [PATCH] Unread message event and unread message reset rework. --- .../src/components/chat-events/ChatEvent.cpp | 7 ++ .../src/components/chat-events/ChatEvent.hpp | 7 +- .../components/chat-room/ChatRoomModel.cpp | 66 +++++++++++-------- .../components/chat-room/ChatRoomModel.hpp | 6 +- .../chat-room/ChatRoomProxyModel.cpp | 11 ++-- .../src/components/timeline/TimelineModel.cpp | 4 +- .../ui/modules/Linphone/Chat/Chat.qml | 14 +++- 7 files changed, 78 insertions(+), 37 deletions(-) diff --git a/linphone-app/src/components/chat-events/ChatEvent.cpp b/linphone-app/src/components/chat-events/ChatEvent.cpp index 2964946ab..2765b0783 100644 --- a/linphone-app/src/components/chat-events/ChatEvent.cpp +++ b/linphone-app/src/components/chat-events/ChatEvent.cpp @@ -32,5 +32,12 @@ ChatEvent::ChatEvent (ChatRoomModel::EntryType type, QObject * parent) : QObject ChatEvent::~ChatEvent(){ } +QDateTime ChatEvent::getTimestamp() const{ + return mTimestamp; +} +void ChatEvent::setTimestamp(const QDateTime& timestamp){ + mTimestamp = timestamp; +} + void ChatEvent::deleteEvent(){ } \ No newline at end of file diff --git a/linphone-app/src/components/chat-events/ChatEvent.hpp b/linphone-app/src/components/chat-events/ChatEvent.hpp index 3c43b81ef..a977c8e7d 100644 --- a/linphone-app/src/components/chat-events/ChatEvent.hpp +++ b/linphone-app/src/components/chat-events/ChatEvent.hpp @@ -32,9 +32,14 @@ public: ChatEvent (ChatRoomModel::EntryType type, QObject * parent = nullptr); virtual ~ChatEvent(); ChatRoomModel::EntryType mType; - QDateTime mTimestamp; + + virtual QDateTime getTimestamp() const; + virtual void setTimestamp(const QDateTime& timestamp); virtual void deleteEvent(); + +protected: + QDateTime mTimestamp; }; Q_DECLARE_METATYPE(ChatEvent*) #endif diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index 717feb4ad..83d7f46c8 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -196,12 +196,12 @@ ChatRoomModel::ChatRoomModel (std::shared_ptr chatRoom, QObj mChatRoomModelListener = std::make_shared(this, parent); mChatRoom->addListener(mChatRoomModelListener); - setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); - setMissedCallsCount(0); - // Get messages. mEntries.clear(); + setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); + setMissedCallsCount(0); + QElapsedTimer timer; timer.start(); CoreHandlers *coreHandlers = mCoreHandlers.get(); @@ -297,7 +297,7 @@ QVariant ChatRoomModel::data (const QModelIndex &index, int role) const { return QVariant(); } case Roles::SectionDate: - return QVariant::fromValue(mEntries[row]->mTimestamp.date()); + return QVariant::fromValue(mEntries[row]->getTimestamp().date()); } return QVariant(); @@ -581,14 +581,15 @@ void ChatRoomModel::updateLastUpdateTime(){ QDateTime lastDateTime = QDateTime::fromMSecsSinceEpoch(mChatRoom->getLastUpdateTime()*1000); QDateTime lastCallTime = lastDateTime; for(auto e : mEntries){ - if(e->mType == CallEntry && e->mTimestamp > lastCallTime) - lastCallTime = e->mTimestamp; + if(e->mType == CallEntry && e->getTimestamp() > lastCallTime) + lastCallTime = e->getTimestamp(); } setLastUpdateTime(lastCallTime); } } void ChatRoomModel::setUnreadMessagesCount(const int& count){ + updateNewMessageNotice(count); if(count != mUnreadMessagesCount){ mUnreadMessagesCount = count; emit unreadMessagesCountChanged(); @@ -771,12 +772,6 @@ void ChatRoomModel::resetMessageCount () { if (mChatRoom->getUnreadMessagesCount() > 0){ mChatRoom->markAsRead();// Marking as read is only for messages. Not for calls. } - if(!mUnreadMessageNotice.first) - mUnreadMessageNotice.first = true; - else if( mUnreadMessageNotice.second){ - removeEntry(mUnreadMessageNotice.second.get()); - mUnreadMessageNotice.second = nullptr; - } setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); setMissedCallsCount(0); emit messageCountReset(); @@ -855,24 +850,47 @@ public: } } }else{ - auto entry = ChatNoticeModel::create(std::dynamic_pointer_cast(itEntries->mObject), chatRoomModel); - if(entry) + auto entry = ChatNoticeModel::create(std::dynamic_pointer_cast(itEntries->mObject), chatRoomModel); + if(entry) { *resultEntries << entry; + } } } } }; + +void ChatRoomModel::updateNewMessageNotice(const int& count){ + if( mChatRoom ) { + if(mUnreadMessageNotice ) { + removeEntry(mUnreadMessageNotice.get()); + mUnreadMessageNotice = nullptr; + } + if(count > 0){ + QDateTime lastUnreadMessage = QDateTime::currentDateTime(); + enableMarkAsRead(false); +// Get chat messages + for (auto &message : mChatRoom->getHistory(mLastEntriesStep)) { + if( !message->isRead()) { + lastUnreadMessage = min(lastUnreadMessage, QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000 - 1 )); //-1 to be sure that event will be before the message + } + } + mUnreadMessageNotice = ChatNoticeModel::create(ChatNoticeModel::NoticeType::NoticeUnreadMessages, lastUnreadMessage, QString::number(count)); + beginInsertRows(QModelIndex(), 0, 0); + mEntries.prepend(mUnreadMessageNotice); + endInsertRows(); + qWarning() << "New message notice timestamp to :" << lastUnreadMessage.toString(); + } + //emit layoutChanged(); + } +} + void ChatRoomModel::initEntries(){ // On call : reinitialize all entries. This allow to free up memory QList > entries; QList prepareEntries; - QDateTime lastUnreadMessage = QDateTime::currentDateTime(); // Get chat messages for (auto &message : mChatRoom->getHistory(mLastEntriesStep)) { prepareEntries << EntrySorterHelper(message->getTime() ,MessageEntry, message); - if( !message->isRead()) { - lastUnreadMessage = min(lastUnreadMessage, QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000)); - } } // Get events for(auto &eventLog : mChatRoom->getHistoryEvents(mLastEntriesStep)) @@ -892,16 +910,11 @@ void ChatRoomModel::initEntries(){ } EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mLastEntriesStep, this); - if( mChatRoom->getUnreadMessagesCount() > 0) { - mUnreadMessageNotice.first = false; - mUnreadMessageNotice.second = ChatNoticeModel::create(ChatNoticeModel::NoticeType::NoticeUnreadMessages, lastUnreadMessage, QString::number(mChatRoom->getUnreadMessagesCount())); - entries.push_front(mUnreadMessageNotice.second); - } - mIsInitialized = true; if(entries.size() >0){ beginResetModel(); mEntries = entries; + updateNewMessageNotice(mChatRoom->getUnreadMessagesCount()); endResetModel(); } } @@ -1062,11 +1075,11 @@ void ChatRoomModel::insertMessages (const QList 0){ - setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); beginInsertRows(QModelIndex(), 0, entries.size()-1); entries << mEntries; mEntries = entries; endInsertRows(); + setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); emit layoutChanged(); } } @@ -1090,8 +1103,9 @@ void ChatRoomModel::insertNotices (const QList model = ChatNoticeModel::create(eventLog, this); - if(model) + if(model) { entries << model; + } } if(entries.size() > 0){ diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp index 77bab8021..2a56a06f2 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp @@ -36,6 +36,7 @@ class ChatEvent; class ContactModel; class ChatRoomModel; class ChatMessageModel; +class ChatNoticeModel; class ChatRoomModelListener : public QObject, public linphone::ChatRoomListener { Q_OBJECT @@ -232,6 +233,7 @@ public: Q_INVOKABLE void initEntries(); Q_INVOKABLE int loadMoreEntries(); // return new entries count void callEnded(std::shared_ptr call); + void updateNewMessageNotice(const int& count); QDateTime mLastUpdateTime; int mUnreadMessagesCount = 0; @@ -318,7 +320,7 @@ signals: void canBeEphemeralChanged(); void markAsReadEnabledChanged(); void chatRoomDeleted();// Must be connected with DirectConnection mode - void replyChanged(); + void replyChanged(); // Chat Room listener callbacks @@ -342,7 +344,7 @@ private: //void handleMessageReceived (const std::shared_ptr &message); //bool mIsRemoteComposing = false; - QPair > mUnreadMessageNotice; + std::shared_ptr mUnreadMessageNotice; QList > mEntries; std::shared_ptr mParticipantListModel; std::shared_ptr mCoreHandlers; diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp index f20894b87..b5012e025 100644 --- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp @@ -197,7 +197,7 @@ bool ChatRoomProxyModel::lessThan (const QModelIndex &left, const QModelIndex &r return true; if(!a) return false; - return a->mTimestamp < b->mTimestamp; + return a->getTimestamp() < b->getTimestamp(); } // ----------------------------------------------------------------------------- @@ -242,11 +242,12 @@ void ChatRoomProxyModel::setFullLocalAddress (const QString &localAddress) { } bool ChatRoomProxyModel::markAsReadEnabled() const{ - return mChatRoomModel->markAsReadEnabled(); + return (mChatRoomModel ? mChatRoomModel->markAsReadEnabled() : false); } void ChatRoomProxyModel::enableMarkAsRead(const bool& enable){ - mChatRoomModel->enableMarkAsRead(enable); + if(mChatRoomModel) + mChatRoomModel->enableMarkAsRead(enable); } QList ChatRoomProxyModel::getComposers() const{ @@ -300,7 +301,7 @@ void ChatRoomProxyModel::resetMessageCount(){ } void ChatRoomProxyModel::setFilterText(const QString& text){ - if( mFilterText != text){ + if( mFilterText != text && mChatRoomModel){ mFilterText = text; int currentRowCount = rowCount(); int newEntries = 0; @@ -351,7 +352,7 @@ void ChatRoomProxyModel::handleIsRemoteComposingChanged () { void ChatRoomProxyModel::handleMessageReceived (const shared_ptr &) { QWindow *window = getParentWindow(this); - if (window && window->isActive()) + if (window && window->isActive() && mChatRoomModel) mChatRoomModel->resetMessageCount(); } diff --git a/linphone-app/src/components/timeline/TimelineModel.cpp b/linphone-app/src/components/timeline/TimelineModel.cpp index 36355e497..b710c057c 100644 --- a/linphone-app/src/components/timeline/TimelineModel.cpp +++ b/linphone-app/src/components/timeline/TimelineModel.cpp @@ -109,8 +109,8 @@ void TimelineModel::setSelected(const bool& selected){ } void TimelineModel::updateUnreadCount(){ - if(mSelected){ - mChatRoomModel->resetMessageCount(); + if(!mSelected){// updateUnreadCount is called when selected has changed;: So if mSelected is false then we are going out of it. + mChatRoomModel->resetMessageCount();// The reset will appear when the chat room has "mark as read enabled", that means that we should have read messages when going out. } } void TimelineModel::onDefaultProxyChanged(){ diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.qml b/linphone-app/ui/modules/Linphone/Chat/Chat.qml index 1010450a4..4dc90d61d 100644 --- a/linphone-app/ui/modules/Linphone/Chat/Chat.qml +++ b/linphone-app/ui/modules/Linphone/Chat/Chat.qml @@ -383,12 +383,24 @@ Rectangle { } ActionButton{ + id: gotToBottomButton anchors.bottom: messageBlock.top anchors.bottomMargin: 10 anchors.right: parent.right anchors.rightMargin: 40 visible: chat.isIndexAfter(chat.count-1) - onVisibleChanged: container.proxyModel.markAsReadEnabled = !visible + onVisibleChanged: updateMarkAsRead() + Component.onCompleted: updateMarkAsRead() + function updateMarkAsRead(){ + if(!visible) + container.proxyModel.markAsReadEnabled = true + } + + Connections{ + target: container.proxyModel + onMarkAsReadEnabledChanged: if( !container.proxyModel.markAsReadEnabled) + gotToBottomButton.updateMarkAsRead() + } isCustom: true backgroundRadius: width/2