diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 8d97b5a..4aa6ef8 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -87,6 +87,7 @@ Page { function initializePage() { console.log("[ChatPage] Initializing chat page..."); chatView.currentIndex = -1; + chatView.lastReadSentIndex = 0; var chatType = chatInformation.type['@type']; isPrivateChat = ( chatType === "chatTypePrivate" ); isBasicGroup = ( chatType === "chatTypeBasicGroup" ); @@ -157,8 +158,9 @@ Page { Connections { target: chatModel onMessagesReceived: { - console.log("[ChatPage] Messages received, view has " + chatView.count + " messages, setting view to index " + modelIndex); + console.log("[ChatPage] Messages received, view has " + chatView.count + " messages, setting view to index " + modelIndex + ", own messages were read before index " + lastReadSentIndex); chatView.currentIndex = modelIndex; + chatView.lastReadSentIndex = lastReadSentIndex; chatViewLoadingTimer.stop(); chatViewLoadingTimer.start(); } @@ -171,6 +173,10 @@ Page { chatUnreadMessagesCountBackground.visible = ( !chatPage.loading && unreadCount > 0 ) chatUnreadMessagesCount.text = unreadCount > 99 ? "99+" : unreadCount } + onLastReadSentMessageUpdated: { + console.log("[ChatPage] Updating last read sent index, new index: " + lastReadSentIndex); + chatView.lastReadSentIndex = lastReadSentIndex; + } } Timer { @@ -275,6 +281,8 @@ Page { clip: true highlightFollowsCurrentItem: true + property int lastReadSentIndex: 0 + function handleScrollPositionChanged() { console.log("Current position: " + chatView.contentY); tdLibWrapper.viewMessage(chatInformation.id, chatView.itemAt(chatView.contentX, ( chatView.contentY + chatView.height - Theme.horizontalPageMargin )).myMessage.id); @@ -284,7 +292,7 @@ Page { chatViewLoadingTimer.stop(); chatViewLoadingTimer.start(); if (!chatPage.loading) { - if (chatView.indexAt(chatView.contentX, chatView.contentY) < 20) { + if (chatView.indexAt(chatView.contentX, chatView.contentY) < 10) { console.log("Trying to get older history items..."); chatModel.triggerLoadMoreHistory(); } @@ -474,7 +482,15 @@ Page { running: true repeat: true onTriggered: { - messageDateText.text = Functions.getDateTimeElapsed(display.date); + messageDateText.text = Functions.getDateTimeElapsed(display.date) + ( (chatPage.myUserId === display.sender_user_id) ? ( index <= chatView.lastReadSentIndex ? Emoji.emojify(" - ✅", Theme.fontSizeTiny) : Emoji.emojify(" - ☑️", Theme.fontSizeTiny) ) : "" ); + } + } + + Connections { + target: chatModel + onLastReadSentMessageUpdated: { + console.log("[ChatModel] Messages in this chat were read, new last read: " + lastReadSentIndex + ", updating description for index " + index + ", status: " + index <= lastReadSentIndex); + messageDateText.text = Functions.getDateTimeElapsed(display.date) + ( (chatPage.myUserId === display.sender_user_id) ? ( index <= lastReadSentIndex ? Emoji.emojify(" - ✅", Theme.fontSizeTiny) : Emoji.emojify(" - ☑️", Theme.fontSizeTiny) ) : "" ); } } @@ -482,7 +498,7 @@ Page { width: parent.width id: messageDateText - text: Functions.getDateTimeElapsed(display.date) + text: Functions.getDateTimeElapsed(display.date) + ( (chatPage.myUserId === display.sender_user_id) ? ( index <= chatView.lastReadSentIndex ? Emoji.emojify(" - ✅", Theme.fontSizeTiny) : Emoji.emojify(" - ☑️", Theme.fontSizeTiny) ) : "" ); font.pixelSize: Theme.fontSizeTiny color: (chatPage.myUserId === display.sender_user_id) ? Theme.secondaryHighlightColor : Theme.secondaryColor horizontalAlignment: (chatPage.myUserId === display.sender_user_id) ? Text.AlignRight : Text.AlignLeft diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index ff17af6..fb7fabc 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -12,6 +12,7 @@ ChatModel::ChatModel(TDLibWrapper *tdLibWrapper) connect(this->tdLibWrapper, SIGNAL(messagesReceived(QVariantList)), this, SLOT(handleMessagesReceived(QVariantList))); connect(this->tdLibWrapper, SIGNAL(newMessageReceived(QString, QVariantMap)), this, SLOT(handleNewMessageReceived(QString, QVariantMap))); connect(this->tdLibWrapper, SIGNAL(chatReadInboxUpdated(QString, int)), this, SLOT(handleChatReadInboxUpdated(QString, int))); + connect(this->tdLibWrapper, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SLOT(handleChatReadOutboxUpdated(QString, QString))); } ChatModel::~ChatModel() @@ -39,16 +40,14 @@ bool ChatModel::insertRows(int row, int count, const QModelIndex &parent) for (int i = 0; i < count; i++) { this->messages.insert(row + i, this->messagesToBeAdded.at(i)); } - this->messageIndexMap.clear(); - for (int i = 0; i < this->messages.size(); i++) { - this->messageIndexMap.insert(this->messages.at(i).toMap().value("id").toString(), i); - } + this->calculateMessageIndexMap(); endInsertRows(); return true; } void ChatModel::initialize(const QVariantMap &chatInformation) { + qDebug() << "[ChatModel] Initializing chat model..."; this->chatInformation = chatInformation; this->messages.clear(); this->messageIndexMap.clear(); @@ -84,11 +83,13 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages) if (messages.size() == 0) { qDebug() << "[ChatModel] No additional messages loaded, notifying chat UI..."; this->inReload = false; + int listInboxPosition = this->calculateLastKnownMessageId(); + int listOutboxPosition = this->calculateLastReadSentMessageId(); if (this->inIncrementalUpdate) { this->inIncrementalUpdate = false; - emit messagesIncrementalUpdate(this->messages.size() - 1); + emit messagesIncrementalUpdate(listInboxPosition, listOutboxPosition); } else { - emit messagesReceived(this->messages.size() - 1); + emit messagesReceived(listInboxPosition, listOutboxPosition); } } else { this->messagesMutex.lock(); @@ -105,10 +106,6 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages) this->insertMessages(); this->messagesMutex.unlock(); - QString lastKnownMessageId = this->chatInformation.value("last_read_inbox_message_id").toString(); - int listPosition = this->messageIndexMap.value(lastKnownMessageId, this->messages.size() - 1).toInt(); - qDebug() << "[ChatModel] Last known message is at position" << listPosition; - // First call only returns a few messages, we need to get a little more than that... if (this->messagesToBeAdded.size() < 10 && !this->inReload) { qDebug() << "[ChatModel] Only a few messages received in first call, loading more..."; @@ -117,11 +114,13 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages) } else { qDebug() << "[ChatModel] Messages loaded, notifying chat UI..."; this->inReload = false; + int listInboxPosition = this->calculateLastKnownMessageId(); + int listOutboxPosition = this->calculateLastReadSentMessageId(); if (this->inIncrementalUpdate) { this->inIncrementalUpdate = false; - emit messagesIncrementalUpdate(listPosition); + emit messagesIncrementalUpdate(listInboxPosition, listOutboxPosition); } else { - emit messagesReceived(listPosition); + emit messagesReceived(listInboxPosition, listOutboxPosition); } } } @@ -152,11 +151,22 @@ void ChatModel::handleChatReadInboxUpdated(const QString &chatId, const int &unr } } +void ChatModel::handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId) +{ + if (chatId == this->chatId) { + this->chatInformation.insert("last_read_outbox_message_id", lastReadOutboxMessageId); + int sentIndex = calculateLastReadSentMessageId(); + qDebug() << "[ChatModel] Updating sent message ID, new index " << sentIndex; + emit lastReadSentMessageUpdated(sentIndex); + } +} + void ChatModel::insertMessages() { if (this->messages.isEmpty()) { beginResetModel(); this->messages.append(this->messagesToBeAdded); + this->calculateMessageIndexMap(); endResetModel(); } else { // There is only an append or a prepend, tertium non datur! (probably ;)) @@ -200,3 +210,36 @@ QVariantMap ChatModel::enhanceMessage(const QVariantMap &message) } return enhancedMessage; } + +int ChatModel::calculateLastKnownMessageId() +{ + qDebug() << "[ChatModel] calculateLastKnownMessageId"; + QString lastKnownMessageId = this->chatInformation.value("last_read_inbox_message_id").toString(); + qDebug() << "[ChatModel] lastKnownMessageId" << lastKnownMessageId; + qDebug() << "[ChatModel] size messageIndexMap" << this->messageIndexMap.size(); + qDebug() << "[ChatModel] contains ID?" << this->messageIndexMap.contains(lastKnownMessageId); + int listInboxPosition = this->messageIndexMap.value(lastKnownMessageId, this->messages.size() - 1).toInt(); + qDebug() << "[ChatModel] Last known message is at position" << listInboxPosition; + return listInboxPosition; +} + +int ChatModel::calculateLastReadSentMessageId() +{ + qDebug() << "[ChatModel] calculateLastReadSentMessageId"; + QString lastReadSentMessageId = this->chatInformation.value("last_read_outbox_message_id").toString(); + qDebug() << "[ChatModel] lastReadSentMessageId" << lastReadSentMessageId; + qDebug() << "[ChatModel] size messageIndexMap" << this->messageIndexMap.size(); + qDebug() << "[ChatModel] contains ID?" << this->messageIndexMap.contains(lastReadSentMessageId); + int listOutboxPosition = this->messageIndexMap.value(lastReadSentMessageId, this->messages.size() - 1).toInt(); + qDebug() << "[ChatModel] Last read sent message is at position" << listOutboxPosition; + return listOutboxPosition; +} + +void ChatModel::calculateMessageIndexMap() +{ + qDebug() << "[ChatModel] calculateMessageIndexMap"; + this->messageIndexMap.clear(); + for (int i = 0; i < this->messages.size(); i++) { + this->messageIndexMap.insert(this->messages.at(i).toMap().value("id").toString(), i); + } +} diff --git a/src/chatmodel.h b/src/chatmodel.h index 288bc10..bf656d6 100644 --- a/src/chatmodel.h +++ b/src/chatmodel.h @@ -21,15 +21,17 @@ public: Q_INVOKABLE void triggerLoadMoreHistory(); signals: - void messagesReceived(const int &modelIndex); - void messagesIncrementalUpdate(const int &modelIndex); + void messagesReceived(const int &modelIndex, const int &lastReadSentIndex); + void messagesIncrementalUpdate(const int &modelIndex, const int &lastReadSentIndex); void newMessageReceived(); void unreadCountUpdated(const int &unreadCount); + void lastReadSentMessageUpdated(const int &lastReadSentIndex); public slots: void handleMessagesReceived(const QVariantList &messages); void handleNewMessageReceived(const QString &chatId, const QVariantMap &message); void handleChatReadInboxUpdated(const QString &chatId, const int &unreadCount); + void handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId); private: @@ -45,6 +47,9 @@ private: void insertMessages(); QVariantMap enhanceMessage(const QVariantMap &message); + int calculateLastKnownMessageId(); + int calculateLastReadSentMessageId(); + void calculateMessageIndexMap(); }; #endif // CHATMODEL_H diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index d8c51f5..2ef63af 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -67,6 +67,7 @@ void TDLibReceiver::processReceivedDocument(const QJsonDocument &receivedJsonDoc if (objectTypeName == "updateChatLastMessage") { this->processUpdateChatLastMessage(receivedInformation); } if (objectTypeName == "updateChatOrder") { this->processUpdateChatOrder(receivedInformation); } if (objectTypeName == "updateChatReadInbox") { this->processUpdateChatReadInbox(receivedInformation); } + if (objectTypeName == "updateChatReadOutbox") { this->processUpdateChatReadOutbox(receivedInformation); } if (objectTypeName == "updateBasicGroup") { this->processUpdateBasicGroup(receivedInformation); } if (objectTypeName == "updateSupergroup") { this->processUpdateSuperGroup(receivedInformation); } if (objectTypeName == "updateChatOnlineMemberCount") { this->processChatOnlineMemberCountUpdated(receivedInformation); } @@ -180,6 +181,12 @@ void TDLibReceiver::processUpdateChatReadInbox(const QVariantMap &receivedInform emit chatReadInboxUpdated(receivedInformation.value("chat_id").toString(), receivedInformation.value("unread_count").toInt()); } +void TDLibReceiver::processUpdateChatReadOutbox(const QVariantMap &receivedInformation) +{ + qDebug() << "[TDLibReceiver] Sent messages read information updated for " << receivedInformation.value("chat_id").toString() << " last read message ID: " << receivedInformation.value("last_read_outbox_message_id").toString(); + emit chatReadOutboxUpdated(receivedInformation.value("chat_id").toString(), receivedInformation.value("last_read_outbox_message_id").toString()); +} + void TDLibReceiver::processUpdateBasicGroup(const QVariantMap &receivedInformation) { QString basicGroupId = receivedInformation.value("basic_group").toMap().value("id").toString(); diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index cf779b6..98f04d1 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -49,6 +49,7 @@ signals: void chatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage); void chatOrderUpdated(const QString &chatId, const QString &order); void chatReadInboxUpdated(const QString &chatId, const int &unreadCount); + void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId); void basicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation); void superGroupUpdated(const QString &groupId, const QVariantMap &groupInformation); void chatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount); @@ -75,6 +76,7 @@ private: void processUpdateChatLastMessage(const QVariantMap &receivedInformation); void processUpdateChatOrder(const QVariantMap &receivedInformation); void processUpdateChatReadInbox(const QVariantMap &receivedInformation); + void processUpdateChatReadOutbox(const QVariantMap &receivedInformation); void processUpdateBasicGroup(const QVariantMap &receivedInformation); void processUpdateSuperGroup(const QVariantMap &receivedInformation); void processChatOnlineMemberCountUpdated(const QVariantMap &receivedInformation); diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index ec245ad..09d7dbe 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -55,6 +55,7 @@ TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent) connect(this->tdLibReceiver, SIGNAL(chatLastMessageUpdated(QString, QString, QVariantMap)), this, SLOT(handleChatLastMessageUpdated(QString, QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chatOrderUpdated(QString, QString)), this, SLOT(handleChatOrderUpdated(QString, QString))); connect(this->tdLibReceiver, SIGNAL(chatReadInboxUpdated(QString, int)), this, SLOT(handleChatReadInboxUpdated(QString, int))); + connect(this->tdLibReceiver, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SLOT(handleChatReadOutboxUpdated(QString, QString))); connect(this->tdLibReceiver, SIGNAL(basicGroupUpdated(QString, QVariantMap)), this, SLOT(handleBasicGroupUpdated(QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(superGroupUpdated(QString, QVariantMap)), this, SLOT(handleSuperGroupUpdated(QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chatOnlineMemberCountUpdated(QString, int)), this, SLOT(handleChatOnlineMemberCountUpdated(QString, int))); @@ -449,6 +450,11 @@ void TDLibWrapper::handleChatReadInboxUpdated(const QString &chatId, const int & emit chatReadInboxUpdated(chatId, unreadCount); } +void TDLibWrapper::handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId) +{ + emit chatReadOutboxUpdated(chatId, lastReadOutboxMessageId); +} + void TDLibWrapper::handleBasicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation) { this->basicGroups.insert(groupId, groupInformation); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 880d3a7..c062076 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -97,6 +97,7 @@ signals: void chatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage); void chatOrderUpdated(const QString &chatId, const QString &order); void chatReadInboxUpdated(const QString &chatId, const int &unreadCount); + void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId); void userUpdated(const QString &userId, const QVariantMap &userInformation); void basicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation); void superGroupUpdated(const QString &groupId, const QVariantMap &groupInformation); @@ -121,6 +122,7 @@ public slots: void handleChatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage); void handleChatOrderUpdated(const QString &chatId, const QString &order); void handleChatReadInboxUpdated(const QString &chatId, const int &unreadCount); + void handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId); void handleBasicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation); void handleSuperGroupUpdated(const QString &groupId, const QVariantMap &groupInformation); void handleChatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount);