Display last message in chat list, start ordering them

This commit is contained in:
Sebastian J. Wolf 2020-08-20 00:24:24 +02:00
parent ddd894bdfa
commit 8555716113
10 changed files with 140 additions and 15 deletions

View file

@ -1,3 +1,32 @@
/*
Copyright (C) 2020 Sebastian J. Wolf
This file is part of Fernschreiber.
Fernschreiber is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Fernschreiber is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
*/
function getUserName(userInformation) { function getUserName(userInformation) {
return userInformation.first_name + " " + userInformation.last_name; return userInformation.first_name + " " + userInformation.last_name;
} }
function getSimpleMessageText(message) {
if (message.content['@type'] === 'messageText') {
return message.content.text.text;
}
return "?";
}
function getDateTimeElapsed(timestamp) {
return Format.formatDate(new Date(timestamp * 1000), Formatter.DurationElapsed);
}

View file

@ -34,6 +34,7 @@ Page {
property bool loading: true; property bool loading: true;
property int authorizationState: TelegramAPI.Closed property int authorizationState: TelegramAPI.Closed
property int connectionState: TelegramAPI.WaitingForNetwork property int connectionState: TelegramAPI.WaitingForNetwork
property int ownUserId;
onStatusChanged: { onStatusChanged: {
console.log("[OverviewPage] Status changed: " + status + ", initialization completed: " + initializationCompleted); console.log("[OverviewPage] Status changed: " + status + ", initialization completed: " + initializationCompleted);
@ -113,6 +114,9 @@ Page {
overviewPage.connectionState = connectionState; overviewPage.connectionState = connectionState;
setPageStatus(); setPageStatus();
} }
onOwnUserIdFound: {
overviewPage.ownUserId = ownUserId;
}
} }
Component.onCompleted: { Component.onCompleted: {
@ -195,13 +199,14 @@ Page {
Row { Row {
id: chatListRow id: chatListRow
width: parent.width width: parent.width
height: chatListContentColumn.height
spacing: Theme.paddingMedium spacing: Theme.paddingMedium
Column { Column {
id: chatListPictureColumn id: chatListPictureColumn
width: chatListContentColumn.height width: chatListContentColumn.height - Theme.paddingSmall
height: chatListContentColumn.height height: chatListContentColumn.height - Theme.paddingSmall
spacing: Theme.paddingSmall anchors.verticalCenter: parent.verticalCenter
ProfileThumbnail { ProfileThumbnail {
id: chatListPictureThumbnail id: chatListPictureThumbnail
@ -215,6 +220,7 @@ Page {
Column { Column {
id: chatListContentColumn id: chatListContentColumn
width: parent.width * 5 / 6 - Theme.horizontalPageMargin width: parent.width * 5 / 6 - Theme.horizontalPageMargin
spacing: Theme.paddingSmall
Text { Text {
id: chatListNameText id: chatListNameText
@ -239,7 +245,7 @@ Page {
spacing: Theme.paddingMedium spacing: Theme.paddingMedium
Text { Text {
id: chatListLastUserText id: chatListLastUserText
text: Emoji.emojify("Unknown", Theme.fontSizeExtraSmall) text: (typeof display.last_message !== "undefined") ? ( display.last_message.sender_user_id !== overviewPage.ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(display.last_message.sender_user_id)), font.pixelSize) : qsTr("You") ) : qsTr("Unknown")
font.pixelSize: Theme.fontSizeExtraSmall font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor color: Theme.highlightColor
textFormat: Text.StyledText textFormat: Text.StyledText
@ -253,7 +259,7 @@ Page {
} }
Text { Text {
id: chatListLastMessageText id: chatListLastMessageText
text: Emoji.emojify("Unknown", Theme.fontSizeExtraSmall) text: (typeof display.last_message !== "undefined") ? Emoji.emojify(Functions.getSimpleMessageText(display.last_message), Theme.fontSizeExtraSmall) : qsTr("Unknown")
font.pixelSize: Theme.fontSizeExtraSmall font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor color: Theme.primaryColor
width: parent.width - Theme.paddingMedium - chatListLastUserText.width width: parent.width - Theme.paddingMedium - chatListLastUserText.width
@ -275,16 +281,17 @@ Page {
running: true running: true
repeat: true repeat: true
onTriggered: { onTriggered: {
//messageContactTimeElapsedText.text = getConversationTimeElapsed(display.messages); if (typeof display.last_message !== "undefined") {
messageContactTimeElapsedText.text = Functions.getDateTimeElapsed(display.last_message.date);
}
} }
} }
Text { Text {
id: messageContactTimeElapsedText id: messageContactTimeElapsedText
//text: getConversationTimeElapsed(display.messages) text: (typeof display.last_message !== "undefined") ? Functions.getDateTimeElapsed(display.last_message.date) : qsTr("Unknown")
text: "somewhen"
font.pixelSize: Theme.fontSizeTiny font.pixelSize: Theme.fontSizeTiny
color: Theme.primaryColor color: Theme.secondaryColor
} }
} }
} }

View file

@ -1,9 +1,12 @@
#include "chatlistmodel.h" #include "chatlistmodel.h"
#include <QListIterator>
ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper)
{ {
this->tdLibWrapper = tdLibWrapper; this->tdLibWrapper = tdLibWrapper;
connect(this->tdLibWrapper, SIGNAL(newChatDiscovered(QString, QVariantMap)), this, SLOT(handleChatDiscovered(QString, QVariantMap))); connect(this->tdLibWrapper, SIGNAL(newChatDiscovered(QString, QVariantMap)), this, SLOT(handleChatDiscovered(QString, QVariantMap)));
connect(this->tdLibWrapper, SIGNAL(chatLastMessageUpdated(QString, QVariantMap)), this, SLOT(handleChatLastMessageUpdated(QString, QVariantMap)));
// connect(this->tdLibWrapper, SIGNAL(chatOrderUpdated(QString, QString)), this, SLOT(handleChatOrderUpdated(QString, QString)));
} }
ChatListModel::~ChatListModel() ChatListModel::~ChatListModel()
@ -29,6 +32,7 @@ bool ChatListModel::insertRows(int row, int count, const QModelIndex &parent)
qDebug() << "[ChatListModel] Inserting at " << row << ", row count: " << count; qDebug() << "[ChatListModel] Inserting at " << row << ", row count: " << count;
beginInsertRows(parent, rowCount(QModelIndex()), rowCount(QModelIndex()) + count - 1); beginInsertRows(parent, rowCount(QModelIndex()), rowCount(QModelIndex()) + count - 1);
this->chatList.append(this->chatToBeAdded); this->chatList.append(this->chatToBeAdded);
this->chatIndexMap.insert(this->chatToBeAdded.value("id").toString(), row);
endInsertRows(); endInsertRows();
return true; return true;
} }
@ -39,3 +43,40 @@ void ChatListModel::handleChatDiscovered(const QString &chatId, const QVariantMa
this->chatToBeAdded = chatInformation; this->chatToBeAdded = chatInformation;
insertRows(rowCount(QModelIndex()), 1); insertRows(rowCount(QModelIndex()), 1);
} }
void ChatListModel::handleChatLastMessageUpdated(const QString &chatId, const QVariantMap &lastMessage)
{
int chatIndex = this->chatIndexMap.value(chatId).toInt();
qDebug() << "[ChatListModel] Updating last message for chat " << chatId << " at index " << chatIndex;
QVariantMap currentChat = this->chatList.value(chatIndex).toMap();
currentChat.insert("last_message", lastMessage);
this->chatList.replace(chatIndex, currentChat);
emit dataChanged(this->index(chatIndex), this->index(chatIndex));
}
void ChatListModel::handleChatOrderUpdated(const QString &chatId, const QString &order)
{
qDebug() << "[ChatListModel] Updating chat order because of " << chatId << " , new order " << order;
int currentChatIndex = this->chatIndexMap.value(chatId).toInt();
int otherChatIndex = 0;
QListIterator<QVariant> currentChatIterator(this->chatList);
while (currentChatIterator.hasNext()) {
QVariantMap otherChat = currentChatIterator.next().toMap();
QString otherOrder = otherChat.value("order").toString();
if (otherOrder < order) {
// Our chat gets reordered to the position of the other chat
otherChatIndex = this->chatIndexMap.value(otherChat.value("id").toString()).toInt();
qDebug() << "[ChatListModel] Old position: " << currentChatIndex << "- new position " << otherChatIndex;
break;
}
}
this->chatList.move(currentChatIndex, otherChatIndex);
this->chatIndexMap.clear();
QListIterator<QVariant> newChatIterator(this->chatList);
int currentIndex = 0;
while (newChatIterator.hasNext()) {
QVariantMap currentChat = newChatIterator.next().toMap();
this->chatIndexMap.insert(currentChat.value("id").toString(), currentIndex);
currentIndex++;
}
}

View file

@ -18,11 +18,14 @@ public:
public slots: public slots:
void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation); void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation);
void handleChatLastMessageUpdated(const QString &chatId, const QVariantMap &lastMessage);
void handleChatOrderUpdated(const QString &chatId, const QString &order);
private: private:
TDLibWrapper *tdLibWrapper; TDLibWrapper *tdLibWrapper;
QVariantList chatList; QVariantList chatList;
QVariantMap chatToBeAdded; QVariantMap chatToBeAdded;
QVariantMap chatIndexMap;
}; };
#endif // CHATLISTMODEL_H #endif // CHATLISTMODEL_H

View file

@ -62,6 +62,8 @@ void TDLibReceiver::processReceivedDocument(const QJsonDocument &receivedJsonDoc
if (objectTypeName == "updateNewChat") { this->processUpdateNewChat(receivedInformation); } if (objectTypeName == "updateNewChat") { this->processUpdateNewChat(receivedInformation); }
if (objectTypeName == "updateUnreadMessageCount") { this->processUpdateUnreadMessageCount(receivedInformation); } if (objectTypeName == "updateUnreadMessageCount") { this->processUpdateUnreadMessageCount(receivedInformation); }
if (objectTypeName == "updateUnreadChatCount") { this->processUpdateUnreadChatCount(receivedInformation); } if (objectTypeName == "updateUnreadChatCount") { this->processUpdateUnreadChatCount(receivedInformation); }
if (objectTypeName == "updateChatLastMessage") { this->processUpdateChatLastMessage(receivedInformation); }
if (objectTypeName == "updateChatOrder") { this->processUpdateChatOrder(receivedInformation); }
} }
void TDLibReceiver::processUpdateOption(const QVariantMap &receivedInformation) void TDLibReceiver::processUpdateOption(const QVariantMap &receivedInformation)
@ -135,3 +137,16 @@ void TDLibReceiver::processUpdateUnreadChatCount(const QVariantMap &receivedInfo
qDebug() << "[TDLibReceiver] Unread chat count updated: " << chatCountInformation.value("chat_list_type").toString() << chatCountInformation.value("unread_count").toString(); qDebug() << "[TDLibReceiver] Unread chat count updated: " << chatCountInformation.value("chat_list_type").toString() << chatCountInformation.value("unread_count").toString();
emit unreadChatCountUpdated(chatCountInformation); emit unreadChatCountUpdated(chatCountInformation);
} }
void TDLibReceiver::processUpdateChatLastMessage(const QVariantMap &receivedInformation)
{
QVariantMap lastMessage = receivedInformation.value("last_message").toMap();
qDebug() << "[TDLibReceiver] Last message of chat " << receivedInformation.value("chat_id").toString() << " updated, content: " << lastMessage.value("content").toString();
emit chatLastMessageUpdated(receivedInformation.value("chat_id").toString(), lastMessage);
}
void TDLibReceiver::processUpdateChatOrder(const QVariantMap &receivedInformation)
{
qDebug() << "[TDLibReceiver] Chat order updated for ID " << receivedInformation.value("chat_id").toString() << " new order: " << receivedInformation.value("order").toString();
emit chatOrderUpdated(receivedInformation.value("chat_id").toString(), receivedInformation.value("order").toString());
}

View file

@ -45,6 +45,8 @@ signals:
void newChatDiscovered(const QVariantMap &chatInformation); void newChatDiscovered(const QVariantMap &chatInformation);
void unreadMessageCountUpdated(const QVariantMap &messageCountInformation); void unreadMessageCountUpdated(const QVariantMap &messageCountInformation);
void unreadChatCountUpdated(const QVariantMap &chatCountInformation); void unreadChatCountUpdated(const QVariantMap &chatCountInformation);
void chatLastMessageUpdated(const QString &chatId, const QVariantMap &lastMessage);
void chatOrderUpdated(const QString &chatId, const QString &order);
private: private:
void *tdLibClient; void *tdLibClient;
@ -60,6 +62,8 @@ private:
void processUpdateNewChat(const QVariantMap &receivedInformation); void processUpdateNewChat(const QVariantMap &receivedInformation);
void processUpdateUnreadMessageCount(const QVariantMap &receivedInformation); void processUpdateUnreadMessageCount(const QVariantMap &receivedInformation);
void processUpdateUnreadChatCount(const QVariantMap &receivedInformation); void processUpdateUnreadChatCount(const QVariantMap &receivedInformation);
void processUpdateChatLastMessage(const QVariantMap &receivedInformation);
void processUpdateChatOrder(const QVariantMap &receivedInformation);
}; };
#endif // TDLIBRECEIVER_H #endif // TDLIBRECEIVER_H

View file

@ -45,6 +45,8 @@ TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent)
connect(this->tdLibReceiver, SIGNAL(newChatDiscovered(QVariantMap)), this, SLOT(handleNewChatDiscovered(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(newChatDiscovered(QVariantMap)), this, SLOT(handleNewChatDiscovered(QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(unreadMessageCountUpdated(QVariantMap)), this, SLOT(handleUnreadMessageCountUpdated(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(unreadMessageCountUpdated(QVariantMap)), this, SLOT(handleUnreadMessageCountUpdated(QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(unreadChatCountUpdated(QVariantMap)), this, SLOT(handleUnreadChatCountUpdated(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(unreadChatCountUpdated(QVariantMap)), this, SLOT(handleUnreadChatCountUpdated(QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(chatLastMessageUpdated(QString, QVariantMap)), this, SLOT(handleChatLastMessageUpdated(QString, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(chatOrderUpdated(QString, QString)), this, SLOT(handleChatOrderUpdated(QString, QString)));
this->tdLibReceiver->start(); this->tdLibReceiver->start();
@ -135,7 +137,7 @@ QVariantMap TDLibWrapper::getUserInformation()
QVariantMap TDLibWrapper::getUserInformation(const QString &userId) QVariantMap TDLibWrapper::getUserInformation(const QString &userId)
{ {
qDebug() << "[TDLibWrapper] Returning user information for ID " << userId; qDebug() << "[TDLibWrapper] Returning user information for ID " << userId;
return this->otherUsers.value(userId).toMap(); return this->allUsers.value(userId).toMap();
} }
QVariantMap TDLibWrapper::getUnreadMessageInformation() QVariantMap TDLibWrapper::getUnreadMessageInformation()
@ -210,6 +212,9 @@ void TDLibWrapper::handleOptionUpdated(const QString &optionName, const QVariant
{ {
this->options.insert(optionName, optionValue); this->options.insert(optionName, optionValue);
emit optionUpdated(optionName, optionValue); emit optionUpdated(optionName, optionValue);
if (optionName == "my_id") {
emit ownUserIdFound(optionValue.toString());
}
} }
void TDLibWrapper::handleConnectionStateChanged(const QString &connectionState) void TDLibWrapper::handleConnectionStateChanged(const QString &connectionState)
@ -239,10 +244,9 @@ void TDLibWrapper::handleUserUpdated(const QVariantMap &userInformation)
if (updatedUserId == this->options.value("my_id").toString()) { if (updatedUserId == this->options.value("my_id").toString()) {
qDebug() << "[TDLibWrapper] Own user information updated :)"; qDebug() << "[TDLibWrapper] Own user information updated :)";
this->userInformation = userInformation; this->userInformation = userInformation;
} else {
qDebug() << "[TDLibWrapper] Other user information updated: " << userInformation.value("username").toString() << userInformation.value("first_name").toString() << userInformation.value("last_name").toString();
this->otherUsers.insert(updatedUserId, userInformation);
} }
qDebug() << "[TDLibWrapper] User information updated: " << userInformation.value("username").toString() << userInformation.value("first_name").toString() << userInformation.value("last_name").toString();
this->allUsers.insert(updatedUserId, userInformation);
} }
void TDLibWrapper::handleFileUpdated(const QVariantMap &fileInformation) void TDLibWrapper::handleFileUpdated(const QVariantMap &fileInformation)
@ -273,6 +277,16 @@ void TDLibWrapper::handleUnreadChatCountUpdated(const QVariantMap &chatCountInfo
} }
} }
void TDLibWrapper::handleChatLastMessageUpdated(const QString &chatId, const QVariantMap &lastMessage)
{
emit chatLastMessageUpdated(chatId, lastMessage);
}
void TDLibWrapper::handleChatOrderUpdated(const QString &chatId, const QString &order)
{
emit chatOrderUpdated(chatId, order);
}
void TDLibWrapper::setInitialParameters() void TDLibWrapper::setInitialParameters()
{ {
qDebug() << "[TDLibWrapper] Sending initial parameters to TD Lib"; qDebug() << "[TDLibWrapper] Sending initial parameters to TD Lib";

View file

@ -75,6 +75,7 @@ public:
signals: signals:
void versionDetected(const QString &version); void versionDetected(const QString &version);
void ownUserIdFound(const QString &ownUserId);
void authorizationStateChanged(const TDLibWrapper::AuthorizationState &authorizationState); void authorizationStateChanged(const TDLibWrapper::AuthorizationState &authorizationState);
void optionUpdated(const QString &optionName, const QVariant &optionValue); void optionUpdated(const QString &optionName, const QVariant &optionValue);
void connectionStateChanged(const TDLibWrapper::ConnectionState &connectionState); void connectionStateChanged(const TDLibWrapper::ConnectionState &connectionState);
@ -82,6 +83,8 @@ signals:
void newChatDiscovered(const QString &chatId, const QVariantMap &chatInformation); void newChatDiscovered(const QString &chatId, const QVariantMap &chatInformation);
void unreadMessageCountUpdated(const QVariantMap &messageCountInformation); void unreadMessageCountUpdated(const QVariantMap &messageCountInformation);
void unreadChatCountUpdated(const QVariantMap &chatCountInformation); void unreadChatCountUpdated(const QVariantMap &chatCountInformation);
void chatLastMessageUpdated(const QString &chatId, const QVariantMap &lastMessage);
void chatOrderUpdated(const QString &chatId, const QString &order);
public slots: public slots:
void handleVersionDetected(const QString &version); void handleVersionDetected(const QString &version);
@ -93,7 +96,8 @@ public slots:
void handleNewChatDiscovered(const QVariantMap &chatInformation); void handleNewChatDiscovered(const QVariantMap &chatInformation);
void handleUnreadMessageCountUpdated(const QVariantMap &messageCountInformation); void handleUnreadMessageCountUpdated(const QVariantMap &messageCountInformation);
void handleUnreadChatCountUpdated(const QVariantMap &chatCountInformation); void handleUnreadChatCountUpdated(const QVariantMap &chatCountInformation);
void handleChatLastMessageUpdated(const QString &chatId, const QVariantMap &lastMessage);
void handleChatOrderUpdated(const QString &chatId, const QString &order);
private: private:
void *tdLibClient; void *tdLibClient;
TDLibReceiver *tdLibReceiver; TDLibReceiver *tdLibReceiver;
@ -102,7 +106,7 @@ private:
TDLibWrapper::ConnectionState connectionState; TDLibWrapper::ConnectionState connectionState;
QVariantMap options; QVariantMap options;
QVariantMap userInformation; QVariantMap userInformation;
QVariantMap otherUsers; QVariantMap allUsers;
QVariantMap chats; QVariantMap chats;
QVariantMap unreadMessageInformation; QVariantMap unreadMessageInformation;
QVariantMap unreadChatInformation; QVariantMap unreadChatInformation;

View file

@ -192,5 +192,9 @@
<source>Unknown</source> <source>Unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>You</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -192,5 +192,9 @@
<source>Unknown</source> <source>Unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>You</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
</TS> </TS>