Load last read messages, enable lazy-loading the future, might fix #136

This commit is contained in:
Sebastian Wolf 2020-11-15 23:05:22 +01:00
parent 5e7d62982f
commit 85d1bebc3a
5 changed files with 63 additions and 30 deletions

View file

@ -116,13 +116,18 @@ ListItem {
Connections { Connections {
target: chatModel target: chatModel
onUnreadCountUpdated: { onMessagesReceived: {
messageBackground.isUnread = index > ( chatView.count - unreadCount - 1 ); messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
}
onMessagesIncrementalUpdate: {
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
} }
onNewMessageReceived: { onNewMessageReceived: {
messageBackground.isUnread = index > ( chatView.count - page.chatInformation.unread_count - 1 ); messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
}
onUnreadCountUpdated: {
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
} }
onLastReadSentMessageUpdated: { onLastReadSentMessageUpdated: {
console.log("[ChatModel] Messages in this chat were read, new last read: " + lastReadSentIndex + ", updating description for index " + index + ", status: " + (index <= lastReadSentIndex)); 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); messageDateText.text = getMessageStatusText(myMessage, index, lastReadSentIndex, messageDateText.useElapsed);
@ -216,6 +221,7 @@ ListItem {
Rectangle { Rectangle {
id: messageBackground id: messageBackground
anchors { anchors {
left: parent.left left: parent.left
leftMargin: messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0 leftMargin: messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0
@ -223,7 +229,7 @@ ListItem {
} }
height: messageTextColumn.height + precalculatedValues.paddingMediumDouble height: messageTextColumn.height + precalculatedValues.paddingMediumDouble
width: precalculatedValues.backgroundWidth 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 color: isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor
radius: parent.width / 50 radius: parent.width / 50
opacity: isUnread ? 0.5 : 0.2 opacity: isUnread ? 0.5 : 0.2

View file

@ -356,6 +356,11 @@ Page {
chatView.lastReadSentIndex = lastReadSentIndex; chatView.lastReadSentIndex = lastReadSentIndex;
chatView.scrollToIndex(modelIndex); chatView.scrollToIndex(modelIndex);
chatPage.loading = false; chatPage.loading = false;
if (modelIndex >= (chatView.count - 10)) {
chatView.inCooldown = true;
chatModel.triggerLoadMoreFuture();
}
if (chatView.height > chatView.contentHeight) { if (chatView.height > chatView.contentHeight) {
console.log("[ChatPage] Chat content quite small..."); console.log("[ChatPage] Chat content quite small...");
viewMessageTimer.queueViewMessage(chatView.count - 1); viewMessageTimer.queueViewMessage(chatView.count - 1);
@ -438,7 +443,7 @@ Page {
onTriggered: { onTriggered: {
if(chatInformation.unread_count > 0 && lastQueuedIndex > -1) { if(chatInformation.unread_count > 0 && lastQueuedIndex > -1) {
var messageToRead = chatModel.getMessage(lastQueuedIndex); var messageToRead = chatModel.getMessage(lastQueuedIndex);
if(messageToRead && messageToRead.id) { if (messageToRead && messageToRead.id) {
tdLibWrapper.viewMessage(chatInformation.id, messageToRead.id, false); tdLibWrapper.viewMessage(chatInformation.id, messageToRead.id, false);
} }
lastQueuedIndex = -1 lastQueuedIndex = -1
@ -620,9 +625,9 @@ Page {
function handleScrollPositionChanged() { function handleScrollPositionChanged() {
console.log("Current position: " + chatView.contentY); 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 )); var bottomIndex = chatView.indexAt(chatView.contentX, ( chatView.contentY + chatView.height - Theme.horizontalPageMargin ));
if(bottomIndex > -1) { if (bottomIndex > -1) {
viewMessageTimer.queueViewMessage(bottomIndex) viewMessageTimer.queueViewMessage(bottomIndex)
} }
} }
@ -640,10 +645,16 @@ Page {
} }
onContentYChanged: { onContentYChanged: {
if (!chatPage.loading && !chatView.inCooldown && chatView.indexAt(chatView.contentX, chatView.contentY) < 10) { if (!chatPage.loading && !chatView.inCooldown) {
if (chatView.indexAt(chatView.contentX, chatView.contentY) < 10) {
console.log("[ChatPage] Trying to get older history items..."); console.log("[ChatPage] Trying to get older history items...");
chatView.inCooldown = true; chatView.inCooldown = true;
chatModel.triggerLoadMoreHistory(); 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();
}
} }
} }

View file

@ -30,6 +30,7 @@ namespace {
const QString CHAT_ID("chat_id"); const QString CHAT_ID("chat_id");
const QString PHOTO("photo"); const QString PHOTO("photo");
const QString SMALL("small"); const QString SMALL("small");
const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id");
} }
ChatModel::ChatModel(TDLibWrapper *tdLibWrapper) : ChatModel::ChatModel(TDLibWrapper *tdLibWrapper) :
@ -90,7 +91,7 @@ void ChatModel::initialize(const QVariantMap &chatInformation)
this->messagesToBeAdded.clear(); this->messagesToBeAdded.clear();
endResetModel(); endResetModel();
emit smallPhotoChanged(); emit smallPhotoChanged();
tdLibWrapper->getChatHistory(chatId); tdLibWrapper->getChatHistory(chatId, this->chatInformation.value(LAST_READ_INBOX_MESSAGE_ID).toLongLong());
} }
void ChatModel::triggerLoadMoreHistory() 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() QVariantMap ChatModel::getChatInformation()
{ {
return this->chatInformation; 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 QVariantMap ChatModel::smallPhoto() const
{ {
return chatInformation.value(PHOTO).toMap().value(SMALL).toMap(); return chatInformation.value(PHOTO).toMap().value(SMALL).toMap();
@ -149,17 +164,21 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCo
QListIterator<QVariant> messagesIterator(messages); QListIterator<QVariant> messagesIterator(messages);
while (messagesIterator.hasNext()) { while (messagesIterator.hasNext()) {
QVariantMap currentMessage = messagesIterator.next().toMap(); 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); this->messagesToBeAdded.append(currentMessage);
} }
} }
std::sort(this->messagesToBeAdded.begin(), this->messagesToBeAdded.end(), compareMessages); std::sort(this->messagesToBeAdded.begin(), this->messagesToBeAdded.end(), compareMessages);
if (!this->messagesToBeAdded.isEmpty()) {
this->insertMessages(); this->insertMessages();
}
this->messagesMutex.unlock(); this->messagesMutex.unlock();
// First call only returns a few messages, we need to get a little more than that... // 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..."); LOG("Only a few messages received in first call, loading more...");
this->inReload = true; this->inReload = true;
this->tdLibWrapper->getChatHistory(this->chatId, this->messagesToBeAdded.first().toMap().value(ID).toLongLong()); 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) 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"); LOG("New message received for this chat");
this->messagesMutex.lock(); this->messagesMutex.lock();
@ -199,7 +218,7 @@ void ChatModel::handleChatReadInboxUpdated(const QString &id, const QString &las
if (id.toLongLong() == chatId) { if (id.toLongLong() == chatId) {
LOG("Updating chat unread count, unread messages" << unreadCount << ", last read message ID:" << lastReadInboxMessageId); LOG("Updating chat unread count, unread messages" << unreadCount << ", last read message ID:" << lastReadInboxMessageId);
this->chatInformation.insert("unread_count", unreadCount); 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); emit unreadCountUpdated(unreadCount, lastReadInboxMessageId);
} }
} }
@ -299,11 +318,16 @@ void ChatModel::insertMessages()
endResetModel(); endResetModel();
} else { } else {
// There is only an append or a prepend, tertium non datur! (probably ;)) // 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 // Append
LOG("Appending new messages...");
this->insertRows(rowCount(QModelIndex()), this->messagesToBeAdded.size()); this->insertRows(rowCount(QModelIndex()), this->messagesToBeAdded.size());
} else { } else {
// Prepend // Prepend
LOG("Prepending new messages...");
this->insertRows(0, this->messagesToBeAdded.size()); this->insertRows(0, this->messagesToBeAdded.size());
} }
} }
@ -343,7 +367,7 @@ QVariantMap ChatModel::enhanceMessage(const QVariantMap &message)
int ChatModel::calculateLastKnownMessageId() int ChatModel::calculateLastKnownMessageId()
{ {
LOG("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("lastKnownMessageId" << lastKnownMessageId);
LOG("size messageIndexMap" << messageIndexMap.size()); LOG("size messageIndexMap" << messageIndexMap.size());
LOG("contains ID?" << messageIndexMap.contains(lastKnownMessageId)); LOG("contains ID?" << messageIndexMap.contains(lastKnownMessageId));

View file

@ -41,8 +41,10 @@ public:
Q_INVOKABLE void initialize(const QVariantMap &chatInformation); Q_INVOKABLE void initialize(const QVariantMap &chatInformation);
Q_INVOKABLE void triggerLoadMoreHistory(); Q_INVOKABLE void triggerLoadMoreHistory();
Q_INVOKABLE void triggerLoadMoreFuture();
Q_INVOKABLE QVariantMap getChatInformation(); Q_INVOKABLE QVariantMap getChatInformation();
Q_INVOKABLE QVariantMap getMessage(int index); Q_INVOKABLE QVariantMap getMessage(int index);
Q_INVOKABLE int getLastReadMessageIndex();
QVariantMap smallPhoto() const; QVariantMap smallPhoto() const;
signals: signals:

View file

@ -321,14 +321,12 @@
<source>%n Messages deleted</source> <source>%n Messages deleted</source>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<source>%n messages have been copied</source> <source>%n messages have been copied</source>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
@ -336,7 +334,6 @@
<comment>number of messages selected</comment> <comment>number of messages selected</comment>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
@ -344,7 +341,6 @@
<comment>dialog header</comment> <comment>dialog header</comment>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
</context> </context>
@ -941,7 +937,6 @@
<source>Question (%n1 characters left)</source> <source>Question (%n1 characters left)</source>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message> <message>
@ -957,7 +952,6 @@
<source>Answer (%n1 characters left)</source> <source>Answer (%n1 characters left)</source>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message> <message>
@ -1006,7 +1000,6 @@
<comment>number of total votes</comment> <comment>number of total votes</comment>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message> <message>
@ -1033,7 +1026,6 @@
<comment>number of total votes</comment> <comment>number of total votes</comment>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message> <message>
@ -1051,7 +1043,6 @@
<comment>number of votes for option</comment> <comment>number of votes for option</comment>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
<message> <message>
@ -1069,7 +1060,6 @@
<comment>number of votes for option</comment> <comment>number of votes for option</comment>
<translation type="unfinished"> <translation type="unfinished">
<numerusform></numerusform> <numerusform></numerusform>
<numerusform></numerusform>
</translation> </translation>
</message> </message>
</context> </context>