diff --git a/qml/components/MessageListViewItem.qml b/qml/components/MessageListViewItem.qml index 65393b8..aa0ed3f 100644 --- a/qml/components/MessageListViewItem.qml +++ b/qml/components/MessageListViewItem.qml @@ -116,13 +116,18 @@ ListItem { Connections { target: chatModel - onUnreadCountUpdated: { - messageBackground.isUnread = index > ( chatView.count - unreadCount - 1 ); + onMessagesReceived: { + messageBackground.isUnread = index > chatModel.getLastReadMessageIndex(); + } + onMessagesIncrementalUpdate: { + messageBackground.isUnread = index > chatModel.getLastReadMessageIndex(); } onNewMessageReceived: { - messageBackground.isUnread = index > ( chatView.count - page.chatInformation.unread_count - 1 ); + messageBackground.isUnread = index > chatModel.getLastReadMessageIndex(); + } + onUnreadCountUpdated: { + messageBackground.isUnread = index > chatModel.getLastReadMessageIndex(); } - onLastReadSentMessageUpdated: { console.log("[ChatModel] Messages in this chat were read, new last read: " + lastReadSentIndex + ", updating description for index " + index + ", status: " + (index <= lastReadSentIndex)); messageDateText.text = getMessageStatusText(myMessage, index, lastReadSentIndex, messageDateText.useElapsed); @@ -216,6 +221,7 @@ ListItem { Rectangle { id: messageBackground + anchors { left: parent.left leftMargin: messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0 @@ -223,7 +229,7 @@ ListItem { } height: messageTextColumn.height + precalculatedValues.paddingMediumDouble width: precalculatedValues.backgroundWidth - property bool isUnread: index > ( chatView.count - page.chatInformation.unread_count - 1 ) + property bool isUnread: index > chatModel.getLastReadMessageIndex() color: isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor radius: parent.width / 50 opacity: isUnread ? 0.5 : 0.2 diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 2af3461..5b62c68 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -356,6 +356,11 @@ Page { chatView.lastReadSentIndex = lastReadSentIndex; chatView.scrollToIndex(modelIndex); chatPage.loading = false; + if (modelIndex >= (chatView.count - 10)) { + chatView.inCooldown = true; + chatModel.triggerLoadMoreFuture(); + } + if (chatView.height > chatView.contentHeight) { console.log("[ChatPage] Chat content quite small..."); viewMessageTimer.queueViewMessage(chatView.count - 1); @@ -438,7 +443,7 @@ Page { onTriggered: { if(chatInformation.unread_count > 0 && lastQueuedIndex > -1) { var messageToRead = chatModel.getMessage(lastQueuedIndex); - if(messageToRead && messageToRead.id) { + if (messageToRead && messageToRead.id) { tdLibWrapper.viewMessage(chatInformation.id, messageToRead.id, false); } lastQueuedIndex = -1 @@ -620,9 +625,9 @@ Page { function handleScrollPositionChanged() { console.log("Current position: " + chatView.contentY); - if(chatInformation.unread_count > 0) { + if (chatInformation.unread_count > 0) { var bottomIndex = chatView.indexAt(chatView.contentX, ( chatView.contentY + chatView.height - Theme.horizontalPageMargin )); - if(bottomIndex > -1) { + if (bottomIndex > -1) { viewMessageTimer.queueViewMessage(bottomIndex) } } @@ -640,10 +645,16 @@ Page { } onContentYChanged: { - if (!chatPage.loading && !chatView.inCooldown && chatView.indexAt(chatView.contentX, chatView.contentY) < 10) { - console.log("[ChatPage] Trying to get older history items..."); - chatView.inCooldown = true; - chatModel.triggerLoadMoreHistory(); + if (!chatPage.loading && !chatView.inCooldown) { + if (chatView.indexAt(chatView.contentX, chatView.contentY) < 10) { + console.log("[ChatPage] Trying to get older history items..."); + chatView.inCooldown = true; + chatModel.triggerLoadMoreHistory(); + } else if (chatView.indexAt(chatView.contentX, chatView.contentY) > ( count - 10)) { + console.log("[ChatPage] Trying to get newer history items..."); + chatView.inCooldown = true; + chatModel.triggerLoadMoreFuture(); + } } } diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index 5b6a0a8..cead6cf 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -30,6 +30,7 @@ namespace { const QString CHAT_ID("chat_id"); const QString PHOTO("photo"); const QString SMALL("small"); + const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id"); } ChatModel::ChatModel(TDLibWrapper *tdLibWrapper) : @@ -90,7 +91,7 @@ void ChatModel::initialize(const QVariantMap &chatInformation) this->messagesToBeAdded.clear(); endResetModel(); emit smallPhotoChanged(); - tdLibWrapper->getChatHistory(chatId); + tdLibWrapper->getChatHistory(chatId, this->chatInformation.value(LAST_READ_INBOX_MESSAGE_ID).toLongLong()); } void ChatModel::triggerLoadMoreHistory() @@ -102,6 +103,15 @@ void ChatModel::triggerLoadMoreHistory() } } +void ChatModel::triggerLoadMoreFuture() +{ + if (!this->inIncrementalUpdate && !messages.isEmpty()) { + LOG("Trigger loading newer future..."); + this->inIncrementalUpdate = true; + this->tdLibWrapper->getChatHistory(chatId, messages.last().toMap().value(ID).toLongLong(), -49); + } +} + QVariantMap ChatModel::getChatInformation() { return this->chatInformation; @@ -116,6 +126,11 @@ QVariantMap ChatModel::getMessage(int index) } } +int ChatModel::getLastReadMessageIndex() +{ + return this->messageIndexMap.value(this->chatInformation.value(LAST_READ_INBOX_MESSAGE_ID).toString()).toInt(); +} + QVariantMap ChatModel::smallPhoto() const { return chatInformation.value(PHOTO).toMap().value(SMALL).toMap(); @@ -149,17 +164,21 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCo QListIterator messagesIterator(messages); while (messagesIterator.hasNext()) { QVariantMap currentMessage = messagesIterator.next().toMap(); - if (currentMessage.value(CHAT_ID).toLongLong() == chatId) { + if (currentMessage.value(CHAT_ID).toLongLong() == chatId && !this->messageIndexMap.contains(currentMessage.value(ID).toString())) { + LOG("New message will be added: " + currentMessage.value(ID).toString()); this->messagesToBeAdded.append(currentMessage); } } + std::sort(this->messagesToBeAdded.begin(), this->messagesToBeAdded.end(), compareMessages); - this->insertMessages(); + if (!this->messagesToBeAdded.isEmpty()) { + this->insertMessages(); + } this->messagesMutex.unlock(); // First call only returns a few messages, we need to get a little more than that... - if (this->messagesToBeAdded.size() < 10 && !this->inReload) { + if ((this->messagesToBeAdded.size() + this->messages.size()) < 10 && !this->inReload) { LOG("Only a few messages received in first call, loading more..."); this->inReload = true; this->tdLibWrapper->getChatHistory(this->chatId, this->messagesToBeAdded.first().toMap().value(ID).toLongLong()); @@ -181,7 +200,7 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCo void ChatModel::handleNewMessageReceived(const QString &id, const QVariantMap &message) { - if (id.toLongLong() == chatId) { + if (id.toLongLong() == chatId && !this->messageIndexMap.contains(id)) { LOG("New message received for this chat"); this->messagesMutex.lock(); @@ -199,7 +218,7 @@ void ChatModel::handleChatReadInboxUpdated(const QString &id, const QString &las if (id.toLongLong() == chatId) { LOG("Updating chat unread count, unread messages" << unreadCount << ", last read message ID:" << lastReadInboxMessageId); this->chatInformation.insert("unread_count", unreadCount); - this->chatInformation.insert("last_read_inbox_message_id", lastReadInboxMessageId); + this->chatInformation.insert(LAST_READ_INBOX_MESSAGE_ID, lastReadInboxMessageId); emit unreadCountUpdated(unreadCount, lastReadInboxMessageId); } } @@ -299,11 +318,16 @@ void ChatModel::insertMessages() endResetModel(); } else { // There is only an append or a prepend, tertium non datur! (probably ;)) - if (this->messages.last().toMap().value(ID).toLongLong() < this->messagesToBeAdded.first().toMap().value(ID).toLongLong()) { + qlonglong lastKnownId = this->messages.last().toMap().value(ID).toLongLong(); + qlonglong firstNewId = this->messagesToBeAdded.first().toMap().value(ID).toLongLong(); + LOG("Inserting messages, last known ID: " + QString::number(lastKnownId) + ", first new ID: " + QString::number(firstNewId)); + if (lastKnownId < firstNewId) { // Append + LOG("Appending new messages..."); this->insertRows(rowCount(QModelIndex()), this->messagesToBeAdded.size()); } else { // Prepend + LOG("Prepending new messages..."); this->insertRows(0, this->messagesToBeAdded.size()); } } @@ -343,7 +367,7 @@ QVariantMap ChatModel::enhanceMessage(const QVariantMap &message) int ChatModel::calculateLastKnownMessageId() { LOG("calculateLastKnownMessageId"); - QString lastKnownMessageId = this->chatInformation.value("last_read_inbox_message_id").toString(); + QString lastKnownMessageId = this->chatInformation.value(LAST_READ_INBOX_MESSAGE_ID).toString(); LOG("lastKnownMessageId" << lastKnownMessageId); LOG("size messageIndexMap" << messageIndexMap.size()); LOG("contains ID?" << messageIndexMap.contains(lastKnownMessageId)); diff --git a/src/chatmodel.h b/src/chatmodel.h index 9cd1c40..11e2be2 100644 --- a/src/chatmodel.h +++ b/src/chatmodel.h @@ -41,8 +41,10 @@ public: Q_INVOKABLE void initialize(const QVariantMap &chatInformation); Q_INVOKABLE void triggerLoadMoreHistory(); + Q_INVOKABLE void triggerLoadMoreFuture(); Q_INVOKABLE QVariantMap getChatInformation(); Q_INVOKABLE QVariantMap getMessage(int index); + Q_INVOKABLE int getLastReadMessageIndex(); QVariantMap smallPhoto() const; signals: diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index c2f3861..31d5a90 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -321,14 +321,12 @@ %n Messages deleted - %n messages have been copied - @@ -336,7 +334,6 @@ number of messages selected - @@ -344,7 +341,6 @@ dialog header - @@ -941,7 +937,6 @@ Question (%n1 characters left) - @@ -957,7 +952,6 @@ Answer (%n1 characters left) - @@ -1006,7 +1000,6 @@ number of total votes - @@ -1033,7 +1026,6 @@ number of total votes - @@ -1051,7 +1043,6 @@ number of votes for option - @@ -1069,7 +1060,6 @@ number of votes for option -