diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index 5a8cf49..0ac6e7b 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -63,7 +63,6 @@ Page { repeat: false onTriggered: { overviewPage.chatListCreated = true; - chatListModel.enableDeltaUpdates(); } } diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index 22c1d54..f6e5de6 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -21,22 +21,76 @@ #include #include +#define LOG(x) qDebug() << "[ChatListModel]" << x + +namespace { + const QString ID("id"); + const QString ORDER("order"); + const QString CHAT_ID("chat_id"); + const QString LAST_MESSAGE("last_message"); + const QString UNREAD_COUNT("unread_count"); + const QString NOTIFICATION_SETTINGS("notification_settings"); + const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id"); + const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id"); +} + +class ChatListModel::ChatData +{ +public: + ChatData(const QVariantMap &data); + + int compareTo(const ChatData *chat) const; + bool setOrder(const QString &order); + +public: + QVariantMap chatData; + QString chatId; + qlonglong order; +}; + +ChatListModel::ChatData::ChatData(const QVariantMap &data) : + chatData(data), + chatId(data.value(ID).toString()), + order(data.value(ORDER).toLongLong()) +{ +} + +int ChatListModel::ChatData::compareTo(const ChatData *other) const +{ + if (order == other->order) { + return chatId.compare(other->chatId); + } else { + // This puts most recent ones to the top of the list + return (order < other->order) ? 1 : -1; + } +} + +bool ChatListModel::ChatData::setOrder(const QString &newOrder) +{ + if (!newOrder.isEmpty()) { + chatData.insert(ORDER, newOrder); + order = newOrder.toLongLong(); + return true; + } + return false; +} + ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) { - this->tdLibWrapper = tdLibWrapper; - this->deltaUpdates = false; - connect(this->tdLibWrapper, SIGNAL(newChatDiscovered(QString, QVariantMap)), this, SLOT(handleChatDiscovered(QString, QVariantMap))); - connect(this->tdLibWrapper, SIGNAL(chatLastMessageUpdated(QString, QString, QVariantMap)), this, SLOT(handleChatLastMessageUpdated(QString, QString, QVariantMap))); - connect(this->tdLibWrapper, SIGNAL(chatOrderUpdated(QString, QString)), this, SLOT(handleChatOrderUpdated(QString, QString))); - connect(this->tdLibWrapper, SIGNAL(chatReadInboxUpdated(QString, QString, int)), this, SLOT(handleChatReadInboxUpdated(QString, QString, int))); - connect(this->tdLibWrapper, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SLOT(handleChatReadOutboxUpdated(QString, QString))); - connect(this->tdLibWrapper, SIGNAL(messageSendSucceeded(QString, QString, QVariantMap)), this, SLOT(handleMessageSendSucceeded(QString, QString, QVariantMap))); - connect(this->tdLibWrapper, SIGNAL(chatNotificationSettingsUpdated(QString, QVariantMap)), this, SLOT(handleChatNotificationSettingsUpdated(QString, QVariantMap))); + tdLibWrapper = tdLibWrapper; + connect(tdLibWrapper, SIGNAL(newChatDiscovered(QString,QVariantMap)), this, SLOT(handleChatDiscovered(QString,QVariantMap))); + connect(tdLibWrapper, SIGNAL(chatLastMessageUpdated(QString,QString,QVariantMap)), this, SLOT(handleChatLastMessageUpdated(QString,QString,QVariantMap))); + connect(tdLibWrapper, SIGNAL(chatOrderUpdated(QString,QString)), this, SLOT(handleChatOrderUpdated(QString,QString))); + connect(tdLibWrapper, SIGNAL(chatReadInboxUpdated(QString,QString,int)), this, SLOT(handleChatReadInboxUpdated(QString,QString,int))); + connect(tdLibWrapper, SIGNAL(chatReadOutboxUpdated(QString,QString)), this, SLOT(handleChatReadOutboxUpdated(QString,QString))); + connect(tdLibWrapper, SIGNAL(messageSendSucceeded(QString,QString,QVariantMap)), this, SLOT(handleMessageSendSucceeded(QString,QString,QVariantMap))); + connect(tdLibWrapper, SIGNAL(chatNotificationSettingsUpdated(QString,QVariantMap)), this, SLOT(handleChatNotificationSettingsUpdated(QString,QVariantMap))); } ChatListModel::~ChatListModel() { - qDebug() << "[ChatListModel] Destroying myself..."; + LOG("Destroying myself..."); + qDeleteAll(chatList); } int ChatListModel::rowCount(const QModelIndex &) const @@ -46,185 +100,156 @@ int ChatListModel::rowCount(const QModelIndex &) const QVariant ChatListModel::data(const QModelIndex &index, int role) const { - if(index.isValid() && role == Qt::DisplayRole) { - return QVariant(chatList.value(index.row())); + const int row = index.row(); + if (row >= 0 && row < chatList.size() && role == Qt::DisplayRole) { + return chatList.at(row)->chatData; } return QVariant(); } -bool ChatListModel::insertRows(int row, int count, const QModelIndex &parent) -{ - qDebug() << "[ChatListModel] Inserting at " << row << ", row count: " << count; - beginInsertRows(parent, rowCount(QModelIndex()), rowCount(QModelIndex()) + count - 1); - this->chatList.append(this->chatToBeAdded); - this->chatIndexMap.insert(this->chatToBeAdded.value("id").toString(), row); - endInsertRows(); - return true; -} - -void ChatListModel::enableDeltaUpdates() -{ - qDebug() << "[ChatListModel] Enabling delta updates and enforcing UI redraw..."; - layoutChanged(); - this->deltaUpdates = true; -} - void ChatListModel::redrawModel() { - qDebug() << "[ChatListModel] Enforcing UI redraw..."; + LOG("Enforcing UI redraw..."); layoutChanged(); } -bool compareChats(const QVariant &chat1, const QVariant &chat2) +int ChatListModel::updateChatOrder(int chatIndex) { - QVariantMap chatMap1 = chat1.toMap(); - QVariantMap chatMap2 = chat2.toMap(); - // Order comes first... - if (chatMap1.value("order").toLongLong() > chatMap2.value("order").toLongLong()) { - return true; + ChatData* chat = chatList.at(chatIndex); + + const int n = chatList.size(); + int newIndex = chatIndex; + while (newIndex > 0 && chat->compareTo(chatList.at(newIndex-1)) < 0) { + newIndex--; } - // ID comes next... - if (chatMap1.value("order").toLongLong() == chatMap2.value("order").toLongLong() && chatMap1.value("id").toLongLong() > chatMap2.value("id").toLongLong()) { - return true; + if (newIndex == chatIndex) { + while (newIndex < n-1 && chat->compareTo(chatList.at(newIndex+1)) > 0) { + newIndex++; + } + } + if (newIndex != chatIndex) { + LOG("Moving chat" << chat->chatId << "from position" << chatIndex << "to" << newIndex); + beginMoveRows(QModelIndex(), chatIndex, chatIndex, QModelIndex(), (newIndex < chatIndex) ? newIndex : (newIndex+1)); + chatList.move(chatIndex, newIndex); + chatIndexMap.insert(chat->chatId, newIndex); + // Update damaged part of the map + const int last = qMax(chatIndex, newIndex); + if (newIndex < chatIndex) { + // First index is already correct + for (int i = newIndex + 1; i <= last; i++) { + chatIndexMap.insert(chatList.at(i)->chatId, i); + } + } else { + // Last index is already correct + for (int i = chatIndex; i < last; i++) { + chatIndexMap.insert(chatList.at(i)->chatId, i); + } + } + endMoveRows(); } else { - return false; + LOG("Chat" << chat->chatId << "stays at position" << chatIndex); } + + return newIndex; } -void ChatListModel::handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation) +void ChatListModel::handleChatDiscovered(const QString &chatId, const QVariantMap &chatToBeAdded) { - this->chatListMutex.lock(); - qDebug() << "[ChatListModel] Adding new chat " << chatId; - this->chatToBeAdded = chatInformation; - insertRows(rowCount(QModelIndex()), 1); - this->chatListMutex.unlock(); + ChatData* chat = new ChatData(chatToBeAdded); + const int n = chatList.size(); + int chatIndex; + for (chatIndex = 0; chatIndex < n && chat->compareTo(chatList.at(chatIndex)) >= 0; chatIndex++); + LOG("Adding new chat" << chatId << "at" << chatIndex); + beginInsertRows(QModelIndex(), chatIndex, chatIndex); + chatList.insert(chatIndex, chat); + chatIndexMap.insert(chat->chatId, chatIndex); + // Update damaged part of the map + for (int i = chatIndex + 1; i <= n; i++) { + chatIndexMap.insert(chatList.at(i)->chatId, i); + } + endInsertRows(); } - - void ChatListModel::handleChatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage) { - this->chatListMutex.lock(); - 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); - currentChat.insert("order", order); - this->chatList.replace(chatIndex, currentChat); - emit dataChanged(this->index(chatIndex), this->index(chatIndex)); - - this->updateChatOrder(chatIndex, currentChat); - emit chatChanged(chatId); - - this->chatListMutex.unlock(); + if (chatIndexMap.contains(chatId)) { + int chatIndex = chatIndexMap.value(chatId); + LOG("Updating last message for chat" << chatId <<" at index" << chatIndex << "new order" << order); + ChatData* chat = chatList.at(chatIndex); + chat->chatData.insert(LAST_MESSAGE, lastMessage); + if (chat->setOrder(order)) { + chatIndex = updateChatOrder(chatIndex); + } + const QModelIndex modelIndex(index(chatIndex)); + emit dataChanged(modelIndex, modelIndex); + emit chatChanged(chatId); + } } void ChatListModel::handleChatOrderUpdated(const QString &chatId, const QString &order) { - this->chatListMutex.lock(); - qDebug() << "[ChatListModel] Updating chat order because of " << chatId << " new order " << order; - int chatIndex = this->chatIndexMap.value(chatId).toInt(); - QVariantMap currentChat = this->chatList.at(chatIndex).toMap(); - currentChat.insert("order", order); - this->chatList.replace(chatIndex, currentChat); - emit dataChanged(this->index(chatIndex), this->index(chatIndex)); - - this->updateChatOrder(chatIndex, currentChat); - emit chatChanged(chatId); - - this->chatListMutex.unlock(); + if (chatIndexMap.contains(chatId)) { + LOG("Updating chat order of" << chatId << "to" << order); + int chatIndex = chatIndexMap.value(chatId); + if (chatList.at(chatIndex)->setOrder(order)) { + chatIndex = updateChatOrder(chatIndex); + } + const QModelIndex modelIndex(index(chatIndex)); + emit dataChanged(modelIndex, modelIndex); + emit chatChanged(chatId); + } } void ChatListModel::handleChatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, const int &unreadCount) { - this->chatListMutex.lock(); - qDebug() << "[ChatListModel] Updating chat unread count for " << chatId << " unread messages " << unreadCount << ", last read message ID: " << lastReadInboxMessageId; - int chatIndex = this->chatIndexMap.value(chatId).toInt(); - QVariantMap currentChat = this->chatList.at(chatIndex).toMap(); - currentChat.insert("unread_count", unreadCount); - currentChat.insert("last_read_inbox_message_id", lastReadInboxMessageId); - this->chatList.replace(chatIndex, currentChat); - emit dataChanged(this->index(chatIndex), this->index(chatIndex)); - emit chatChanged(chatId); - this->chatListMutex.unlock(); + if (chatIndexMap.contains(chatId)) { + LOG("Updating chat unread count for" << chatId << "unread messages" << unreadCount << ", last read message ID: " << lastReadInboxMessageId); + const int chatIndex = chatIndexMap.value(chatId); + ChatData* chat = chatList.at(chatIndex); + chat->chatData.insert(UNREAD_COUNT, unreadCount); + chat->chatData.insert(LAST_READ_INBOX_MESSAGE_ID, lastReadInboxMessageId); + const QModelIndex modelIndex(index(chatIndex)); + emit dataChanged(modelIndex, modelIndex); + emit chatChanged(chatId); + } } void ChatListModel::handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId) { - this->chatListMutex.lock(); - qDebug() << "[ChatListModel] Updating last read message for " << chatId << " last ID " << lastReadOutboxMessageId; - int chatIndex = this->chatIndexMap.value(chatId).toInt(); - QVariantMap currentChat = this->chatList.at(chatIndex).toMap(); - currentChat.insert("last_read_outbox_message_id", lastReadOutboxMessageId); - this->chatList.replace(chatIndex, currentChat); - emit dataChanged(this->index(chatIndex), this->index(chatIndex)); - emit chatChanged(chatId); - this->chatListMutex.unlock(); + if (chatIndexMap.contains(chatId)) { + LOG("Updating last read message for" << chatId << "last ID" << lastReadOutboxMessageId); + const int chatIndex = chatIndexMap.value(chatId); + ChatData* chat = chatList.at(chatIndex); + chat->chatData.insert(LAST_READ_OUTBOX_MESSAGE_ID, lastReadOutboxMessageId); + const QModelIndex modelIndex(index(chatIndex)); + emit dataChanged(modelIndex, modelIndex); + emit chatChanged(chatId); + } } void ChatListModel::handleMessageSendSucceeded(const QString &messageId, const QString &oldMessageId, const QVariantMap &message) { - this->chatListMutex.lock(); - QString chatId = message.value("chat_id").toString(); - int chatIndex = this->chatIndexMap.value(chatId).toInt(); - qDebug() << "[ChatListModel] Updating last message for chat " << chatId << " at index " << chatIndex << ", as message was sent, old ID: " << oldMessageId << ", new ID: " << messageId; - QVariantMap currentChat = this->chatList.value(chatIndex).toMap(); - currentChat.insert("last_message", message); - this->chatList.replace(chatIndex, currentChat); - emit dataChanged(this->index(chatIndex), this->index(chatIndex)); - emit chatChanged(chatId); - - this->chatListMutex.unlock(); + const QString chatId(message.value(CHAT_ID).toString()); + if (chatIndexMap.contains(chatId)) { + const int chatIndex = chatIndexMap.value(chatId); + LOG("Updating last message for chat" << chatId << "at index" << chatIndex << ", as message was sent, old ID:" << oldMessageId << ", new ID:" << messageId); + ChatData* chat = chatList.at(chatIndex); + chat->chatData.insert(LAST_MESSAGE, message); + const QModelIndex modelIndex(index(chatIndex)); + emit dataChanged(modelIndex, modelIndex); + emit chatChanged(chatId); + } } void ChatListModel::handleChatNotificationSettingsUpdated(const QString &chatId, const QVariantMap &chatNotificationSettings) { - this->chatListMutex.lock(); - int chatIndex = this->chatIndexMap.value(chatId).toInt(); - qDebug() << "[ChatListModel] Updating notification settings for chat " << chatId << " at index " << chatIndex; - QVariantMap currentChat = this->chatList.value(chatIndex).toMap(); - currentChat.insert("notification_settings", chatNotificationSettings); - this->chatList.replace(chatIndex, currentChat); - emit dataChanged(this->index(chatIndex), this->index(chatIndex)); - emit chatChanged(chatId); - - this->chatListMutex.unlock(); -} - -void ChatListModel::updateChatOrder(const int ¤tChatIndex, const QVariantMap &updatedChat) -{ - // Finding the new position manually as information is needed by beginMoveRows() - // This seems to be the most convenient way of persisting the list position while changing the items - // Other alternative layoutChanged() after sorting resets the index position - there we would need to calculate the new position as well - // If somebody has a better solution - go for it ;) - int newChatIndex = 0; - QVariantMap previousChat; - for (int i = 0; i < this->chatList.length(); i++) { - QVariantMap otherChat = this->chatList.at(i).toMap(); - if (compareChats(updatedChat, otherChat)) { - if (previousChat.value("id") == updatedChat.value("id")) { - newChatIndex = currentChatIndex; - } else { - newChatIndex = i; - } - break; - } - previousChat = otherChat; - } - if (newChatIndex != currentChatIndex) { - // The updated chat now needs to go to the position of the other chat - qDebug() << "[ChatListModel] Chat " << updatedChat.value("id").toString() << " will be moved from position " << currentChatIndex << " to " << newChatIndex; - if (deltaUpdates) { - beginMoveRows(QModelIndex(), currentChatIndex, currentChatIndex, QModelIndex(), (( newChatIndex < currentChatIndex ) ? newChatIndex : ( newChatIndex + 1 ))); - } - std::sort(this->chatList.begin(), this->chatList.end(), compareChats); - this->chatIndexMap.clear(); - for (int i = 0; i < this->chatList.length(); i++) { - this->chatIndexMap.insert(this->chatList.at(i).toMap().value("id").toString(), i); - } - if (deltaUpdates) { - endMoveRows(); - } - + if (chatIndexMap.contains(chatId)) { + const int chatIndex = chatIndexMap.value(chatId); + LOG("Updating notification settings for chat" << chatId << "at index" << chatIndex); + ChatData* chat = chatList.at(chatIndex); + chat->chatData.insert(NOTIFICATION_SETTINGS, chatNotificationSettings); + const QModelIndex modelIndex(index(chatIndex)); + emit dataChanged(modelIndex, modelIndex); + emit chatChanged(chatId); } } diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index be54536..00f084c 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -34,15 +34,13 @@ public: virtual int rowCount(const QModelIndex&) const override; virtual QVariant data(const QModelIndex &index, int role) const override; - virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; - Q_INVOKABLE void enableDeltaUpdates(); Q_INVOKABLE void redrawModel(); signals: void chatChanged(const QString &chatId); -public slots: +private slots: void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation); void handleChatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage); void handleChatOrderUpdated(const QString &chatId, const QString &order); @@ -52,15 +50,14 @@ public slots: void handleChatNotificationSettingsUpdated(const QString &chatId, const QVariantMap &chatNotificationSettings); private: + int updateChatOrder(int chatIndex); + +private: + class ChatData; + TDLibWrapper *tdLibWrapper; - QVariantList chatList; - QVariantMap chatToBeAdded; - QVariantMap chatIndexMap; - QMutex chatListMutex; - bool deltaUpdates; - - void updateChatOrder(const int ¤tChatIndex, const QVariantMap &updatedChat); - + QList chatList; + QHash chatIndexMap; }; #endif // CHATLISTMODEL_H diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index 61bc0c0..6c06030 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -18,25 +18,93 @@ */ #include "tdlibreceiver.h" +#define LOG(x) qDebug() << "[TDLibReceiver]" << x + +namespace { + const QString ID("id"); + const QString LIST("list"); + const QString CHAT_ID("chat_id"); + const QString POSITION("position"); + const QString POSITIONS("positions"); + const QString ORDER("order"); + const QString LAST_MESSAGE("last_message"); + const QString UNREAD_COUNT("unread_count"); + const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id"); + const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id"); + + const QString TYPE("@type"); + const QString TYPE_CHAT_POSITION("chatPosition"); + const QString TYPE_CHAT_LIST_MAIN("chatListMain"); +} + +static QString getChatPositionOrder(const QVariantMap &position) +{ + if (position.value(TYPE).toString() == TYPE_CHAT_POSITION && + position.value(LIST).toMap().value(TYPE) == TYPE_CHAT_LIST_MAIN) { + return position.value(ORDER).toString(); + } + return QString(); +} + +static QString findChatPositionOrder(const QVariantList &positions) +{ + const int n = positions.count(); + for (int i = 0; i < n; i++) { + const QString order(getChatPositionOrder(positions.at(i).toMap())); + if (!order.isEmpty()) { + return order; + } + } + return QString(); +} + TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(parent) { this->tdLibClient = tdLibClient; this->isActive = true; + + handlers.insert("updateOption", &TDLibReceiver::processUpdateOption); + handlers.insert("updateAuthorizationState", &TDLibReceiver::processUpdateAuthorizationState); + handlers.insert("updateConnectionState", &TDLibReceiver::processUpdateConnectionState); + handlers.insert("updateUser", &TDLibReceiver::processUpdateUser); + handlers.insert("updateUserStatus", &TDLibReceiver::processUpdateUserStatus); + handlers.insert("updateFile", &TDLibReceiver::processUpdateFile); + handlers.insert("file", &TDLibReceiver::processFile); + handlers.insert("updateNewChat", &TDLibReceiver::processUpdateNewChat); + handlers.insert("updateUnreadMessageCount", &TDLibReceiver::processUpdateUnreadMessageCount); + handlers.insert("updateUnreadChatCount", &TDLibReceiver::processUpdateUnreadChatCount); + handlers.insert("updateChatLastMessage", &TDLibReceiver::processUpdateChatLastMessage); + handlers.insert("updateChatOrder", &TDLibReceiver::processUpdateChatOrder); + handlers.insert("updateChatPosition", &TDLibReceiver::processUpdateChatPosition); + handlers.insert("updateChatReadInbox", &TDLibReceiver::processUpdateChatReadInbox); + handlers.insert("updateChatReadOutbox", &TDLibReceiver::processUpdateChatReadOutbox); + handlers.insert("updateBasicGroup", &TDLibReceiver::processUpdateBasicGroup); + handlers.insert("updateSupergroup", &TDLibReceiver::processUpdateSuperGroup); + handlers.insert("updateChatOnlineMemberCount", &TDLibReceiver::processChatOnlineMemberCountUpdated); + handlers.insert("messages", &TDLibReceiver::processMessages); + handlers.insert("updateNewMessage", &TDLibReceiver::processUpdateNewMessage); + handlers.insert("message", &TDLibReceiver::processMessage); + handlers.insert("updateMessageSendSucceeded", &TDLibReceiver::processMessageSendSucceeded); + handlers.insert("updateActiveNotifications", &TDLibReceiver::processUpdateActiveNotifications); + handlers.insert("updateNotificationGroup", &TDLibReceiver::processUpdateNotificationGroup); + handlers.insert("updateChatNotificationSettings", &TDLibReceiver::processUpdateChatNotificationSettings); + handlers.insert("updateMessageContent", &TDLibReceiver::processUpdateMessageContent); + handlers.insert("updateDeleteMessages", &TDLibReceiver::processUpdateDeleteMessages); } void TDLibReceiver::setActive(const bool &active) { if (active) { - qDebug() << "[TDLibReceiver] Activating receiver loop..."; + LOG("Activating receiver loop..."); } else { - qDebug() << "[TDLibReceiver] Deactivating receiver loop, this may take a while..."; + LOG("Deactivating receiver loop, this may take a while..."); } this->isActive = active; } void TDLibReceiver::receiverLoop() { - qDebug() << "[TDLibReceiver] Starting receiver loop"; + LOG("Starting receiver loop"); const double WAIT_TIMEOUT = 5.0; while (this->isActive) { const char *result = td_json_client_receive(this->tdLibClient, WAIT_TIMEOUT); @@ -46,7 +114,7 @@ void TDLibReceiver::receiverLoop() processReceivedDocument(receivedJsonDocument); } } - qDebug() << "[TDLibReceiver] Stopping receiver loop"; + LOG("Stopping receiver loop"); } void TDLibReceiver::processReceivedDocument(const QJsonDocument &receivedJsonDocument) @@ -54,32 +122,12 @@ void TDLibReceiver::processReceivedDocument(const QJsonDocument &receivedJsonDoc QVariantMap receivedInformation = receivedJsonDocument.object().toVariantMap(); QString objectTypeName = receivedInformation.value("@type").toString(); - if (objectTypeName == "updateOption") { this->processUpdateOption(receivedInformation); } - if (objectTypeName == "updateAuthorizationState") { this->processUpdateAuthorizationState(receivedInformation); } - if (objectTypeName == "updateConnectionState") { this->processUpdateConnectionState(receivedInformation); } - if (objectTypeName == "updateUser") { this->processUpdateUser(receivedInformation); } - if (objectTypeName == "updateUserStatus") { this->processUpdateUserStatus(receivedInformation); } - if (objectTypeName == "updateFile") { this->processUpdateFile(receivedInformation); } - if (objectTypeName == "file") { this->processFile(receivedInformation); } - if (objectTypeName == "updateNewChat") { this->processUpdateNewChat(receivedInformation); } - if (objectTypeName == "updateUnreadMessageCount") { this->processUpdateUnreadMessageCount(receivedInformation); } - if (objectTypeName == "updateUnreadChatCount") { this->processUpdateUnreadChatCount(receivedInformation); } - 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); } - if (objectTypeName == "messages") { this->processMessages(receivedInformation); } - if (objectTypeName == "updateNewMessage") { this->processUpdateNewMessage(receivedInformation); } - if (objectTypeName == "message") { this->processMessage(receivedInformation); } - if (objectTypeName == "updateMessageSendSucceeded") { this->processMessageSendSucceeded(receivedInformation); } - if (objectTypeName == "updateActiveNotifications") { this->processUpdateActiveNotifications(receivedInformation); } - if (objectTypeName == "updateNotificationGroup") { this->processUpdateNotificationGroup(receivedInformation); } - if (objectTypeName == "updateChatNotificationSettings") { this->processUpdateChatNotificationSettings(receivedInformation); } - if (objectTypeName == "updateMessageContent") { this->processUpdateMessageContent(receivedInformation); } - if (objectTypeName == "updateDeleteMessages") { this->processUpdateDeleteMessages(receivedInformation); } + Handler handler = handlers.value(objectTypeName); + if (handler) { + (this->*handler)(receivedInformation); + } else { + LOG("Unhandled object type" << objectTypeName); + } } void TDLibReceiver::processUpdateOption(const QVariantMap &receivedInformation) @@ -87,11 +135,11 @@ void TDLibReceiver::processUpdateOption(const QVariantMap &receivedInformation) QString currentOption = receivedInformation.value("name").toString(); if (currentOption == "version") { QString detectedVersion = receivedInformation.value("value").toMap().value("value").toString(); - qDebug() << "[TDLibReceiver] TD Lib version detected: " << detectedVersion; + LOG("TD Lib version detected: " << detectedVersion); emit versionDetected(detectedVersion); } else { QVariant currentValue = receivedInformation.value("value").toMap().value("value"); - qDebug() << "[TDLibReceiver] Option updated: " << currentOption << currentValue; + LOG("Option updated: " << currentOption << currentValue); emit optionUpdated(currentOption, currentValue); } } @@ -99,21 +147,21 @@ void TDLibReceiver::processUpdateOption(const QVariantMap &receivedInformation) void TDLibReceiver::processUpdateAuthorizationState(const QVariantMap &receivedInformation) { QString authorizationState = receivedInformation.value("authorization_state").toMap().value("@type").toString(); - qDebug() << "[TDLibReceiver] Authorization state changed: " << authorizationState; + LOG("Authorization state changed: " << authorizationState); emit authorizationStateChanged(authorizationState); } void TDLibReceiver::processUpdateConnectionState(const QVariantMap &receivedInformation) { QString connectionState = receivedInformation.value("state").toMap().value("@type").toString(); - qDebug() << "[TDLibReceiver] Connection state changed: " << connectionState; + LOG("Connection state changed: " << connectionState); emit connectionStateChanged(connectionState); } void TDLibReceiver::processUpdateUser(const QVariantMap &receivedInformation) { QVariantMap userInformation = receivedInformation.value("user").toMap(); - // qDebug() << "[TDLibReceiver] User was updated: " << userInformation.value("username").toString() << userInformation.value("first_name").toString() << userInformation.value("last_name").toString(); + // LOG("User was updated: " << userInformation.value("username").toString() << userInformation.value("first_name").toString() << userInformation.value("last_name").toString()); emit userUpdated(userInformation); } @@ -121,27 +169,27 @@ void TDLibReceiver::processUpdateUserStatus(const QVariantMap &receivedInformati { QString userId = receivedInformation.value("user_id").toString(); QVariantMap userStatusInformation = receivedInformation.value("status").toMap(); - // qDebug() << "[TDLibReceiver] User status was updated: " << receivedInformation.value("user_id").toString() << userStatusInformation.value("@type").toString(); + // LOG("User status was updated: " << receivedInformation.value("user_id").toString() << userStatusInformation.value("@type").toString()); emit userStatusUpdated(userId, userStatusInformation); } void TDLibReceiver::processUpdateFile(const QVariantMap &receivedInformation) { QVariantMap fileInformation = receivedInformation.value("file").toMap(); - qDebug() << "[TDLibReceiver] File was updated: " << fileInformation.value("id").toString(); + LOG("File was updated: " << fileInformation.value(ID).toString()); emit fileUpdated(fileInformation); } void TDLibReceiver::processFile(const QVariantMap &receivedInformation) { - qDebug() << "[TDLibReceiver] File was updated: " << receivedInformation.value("id").toString(); + LOG("File was updated: " << receivedInformation.value(ID).toString()); emit fileUpdated(receivedInformation); } void TDLibReceiver::processUpdateNewChat(const QVariantMap &receivedInformation) { QVariantMap chatInformation = receivedInformation.value("chat").toMap(); - qDebug() << "[TDLibReceiver] New chat discovered: " << chatInformation.value("id").toString() << chatInformation.value("title").toString(); + LOG("New chat discovered: " << chatInformation.value(ID).toString() << chatInformation.value("title").toString()); emit newChatDiscovered(chatInformation); } @@ -151,7 +199,7 @@ void TDLibReceiver::processUpdateUnreadMessageCount(const QVariantMap &receivedI messageCountInformation.insert("chat_list_type", receivedInformation.value("chat_list").toMap().value("@type")); messageCountInformation.insert("unread_count", receivedInformation.value("unread_count")); messageCountInformation.insert("unread_unmuted_count", receivedInformation.value("unread_unmuted_count")); - qDebug() << "[TDLibReceiver] Unread message count updated: " << messageCountInformation.value("chat_list_type").toString() << messageCountInformation.value("unread_count").toString(); + LOG("Unread message count updated: " << messageCountInformation.value("chat_list_type").toString() << messageCountInformation.value("unread_count").toString()); emit unreadMessageCountUpdated(messageCountInformation); } @@ -164,74 +212,90 @@ void TDLibReceiver::processUpdateUnreadChatCount(const QVariantMap &receivedInfo chatCountInformation.insert("total_count", receivedInformation.value("total_count")); chatCountInformation.insert("unread_count", receivedInformation.value("unread_count")); chatCountInformation.insert("unread_unmuted_count", receivedInformation.value("unread_unmuted_count")); - qDebug() << "[TDLibReceiver] Unread chat count updated: " << chatCountInformation.value("chat_list_type").toString() << chatCountInformation.value("unread_count").toString(); + LOG("Unread chat count updated: " << chatCountInformation.value("chat_list_type").toString() << chatCountInformation.value("unread_count").toString()); 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, order " << receivedInformation.value("order").toString() << " content: " << lastMessage.value("content").toString(); - emit chatLastMessageUpdated(receivedInformation.value("chat_id").toString(), receivedInformation.value("order").toString(), lastMessage); + const QString chat_id(receivedInformation.value(CHAT_ID).toString()); + const QString order(findChatPositionOrder(receivedInformation.value(POSITIONS).toList())); + const QVariantMap lastMessage = receivedInformation.value(LAST_MESSAGE).toMap(); + LOG("Last message of chat" << chat_id << "updated, order" << order << "type" << lastMessage.value("@type").toString()); + emit chatLastMessageUpdated(chat_id, order, 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()); + const QString chat_id(receivedInformation.value(CHAT_ID).toString()); + const QString order(receivedInformation.value(ORDER).toString()); + LOG("Chat order updated for ID" << chat_id << "to" << order); + emit chatOrderUpdated(chat_id, order); +} + +void TDLibReceiver::processUpdateChatPosition(const QVariantMap &receivedInformation) +{ + const QString chat_id(receivedInformation.value(CHAT_ID).toString()); + const QString order(receivedInformation.value(POSITION).toMap().value(ORDER).toString()); + LOG("Chat position updated for ID" << chat_id << "new order" << order); + emit chatOrderUpdated(chat_id, order); } void TDLibReceiver::processUpdateChatReadInbox(const QVariantMap &receivedInformation) { - qDebug() << "[TDLibReceiver] Chat read information updated for " << receivedInformation.value("chat_id").toString() << " unread count: " << receivedInformation.value("unread_count").toString(); - emit chatReadInboxUpdated(receivedInformation.value("chat_id").toString(), receivedInformation.value("last_read_inbox_message_id").toString(), receivedInformation.value("unread_count").toInt()); + const QString chat_id(receivedInformation.value(CHAT_ID).toString()); + const QString unread_count(receivedInformation.value(UNREAD_COUNT).toString()); + LOG("Chat read information updated for" << chat_id << "unread count:" << unread_count); + emit chatReadInboxUpdated(chat_id, receivedInformation.value(LAST_READ_INBOX_MESSAGE_ID).toString(), 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()); + const QString chat_id(receivedInformation.value(CHAT_ID).toString()); + const QString last_read_outbox_message_id(receivedInformation.value(LAST_READ_OUTBOX_MESSAGE_ID).toString()); + LOG("Sent messages read information updated for" << chat_id << "last read message ID:" << last_read_outbox_message_id); + emit chatReadOutboxUpdated(chat_id, last_read_outbox_message_id); } void TDLibReceiver::processUpdateBasicGroup(const QVariantMap &receivedInformation) { - QString basicGroupId = receivedInformation.value("basic_group").toMap().value("id").toString(); - qDebug() << "[TDLibReceiver] Basic group information updated for " << basicGroupId; + QString basicGroupId = receivedInformation.value("basic_group").toMap().value(ID).toString(); + LOG("Basic group information updated for " << basicGroupId); emit basicGroupUpdated(basicGroupId, receivedInformation.value("basic_group").toMap()); } void TDLibReceiver::processUpdateSuperGroup(const QVariantMap &receivedInformation) { - QString superGroupId = receivedInformation.value("supergroup").toMap().value("id").toString(); - qDebug() << "[TDLibReceiver] Super group information updated for " << superGroupId; + QString superGroupId = receivedInformation.value("supergroup").toMap().value(ID).toString(); + LOG("Super group information updated for " << superGroupId); emit superGroupUpdated(superGroupId, receivedInformation.value("supergroup").toMap()); } void TDLibReceiver::processChatOnlineMemberCountUpdated(const QVariantMap &receivedInformation) { - QString chatId = receivedInformation.value("chat_id").toString(); - qDebug() << "[TDLibReceiver] Online member count updated for chat " << chatId; + const QString chatId = receivedInformation.value(CHAT_ID).toString(); + LOG("Online member count updated for chat " << chatId); emit chatOnlineMemberCountUpdated(chatId, receivedInformation.value("online_member_count").toInt()); } void TDLibReceiver::processMessages(const QVariantMap &receivedInformation) { - qDebug() << "[TDLibReceiver] Received new messages, amount: " << receivedInformation.value("total_count").toString(); + LOG("Received new messages, amount: " << receivedInformation.value("total_count").toString()); emit messagesReceived(receivedInformation.value("messages").toList()); } void TDLibReceiver::processUpdateNewMessage(const QVariantMap &receivedInformation) { - QString chatId = receivedInformation.value("message").toMap().value("chat_id").toString(); - qDebug() << "[TDLibReceiver] Received new message for chat " << chatId; + const QString chatId = receivedInformation.value("message").toMap().value(CHAT_ID).toString(); + LOG("Received new message for chat " << chatId); emit newMessageReceived(chatId, receivedInformation.value("message").toMap()); } void TDLibReceiver::processMessage(const QVariantMap &receivedInformation) { - QString chatId = receivedInformation.value("chat_id").toString(); - QString messageId = receivedInformation.value("id").toString(); - qDebug() << "[TDLibReceiver] Received message " << chatId << messageId; + const QString chatId = receivedInformation.value(CHAT_ID).toString(); + const QString messageId = receivedInformation.value(ID).toString(); + LOG("Received message " << chatId << messageId); emit messageInformation(messageId, receivedInformation); } @@ -239,48 +303,48 @@ void TDLibReceiver::processMessageSendSucceeded(const QVariantMap &receivedInfor { QString oldMessageId = receivedInformation.value("old_message_id").toString(); QVariantMap message = receivedInformation.value("message").toMap(); - QString messageId = message.value("id").toString(); - qDebug() << "[TDLibReceiver] Message send succeeded " << messageId << oldMessageId; + const QString messageId = message.value(ID).toString(); + LOG("Message send succeeded " << messageId << oldMessageId); emit messageSendSucceeded(messageId, oldMessageId, message); } void TDLibReceiver::processUpdateActiveNotifications(const QVariantMap &receivedInformation) { - qDebug() << "[TDLibReceiver] Received active notification groups"; + LOG("Received active notification groups"); emit activeNotificationsUpdated(receivedInformation.value("groups").toList()); } void TDLibReceiver::processUpdateNotificationGroup(const QVariantMap &receivedInformation) { - qDebug() << "[TDLibReceiver] Received updated notification group"; + LOG("Received updated notification group"); emit notificationGroupUpdated(receivedInformation); } void TDLibReceiver::processUpdateNotification(const QVariantMap &receivedInformation) { - qDebug() << "[TDLibReceiver] Received notification update"; + LOG("Received notification update"); emit notificationUpdated(receivedInformation); } void TDLibReceiver::processUpdateChatNotificationSettings(const QVariantMap &receivedInformation) { - QString chatId = receivedInformation.value("chat_id").toString(); - qDebug() << "[TDLibReceiver] Received new notification settings for chat " << chatId; + const QString chatId = receivedInformation.value(CHAT_ID).toString(); + LOG("Received new notification settings for chat " << chatId); emit chatNotificationSettingsUpdated(chatId, receivedInformation.value("notification_settings").toMap()); } void TDLibReceiver::processUpdateMessageContent(const QVariantMap &receivedInformation) { - QString chatId = receivedInformation.value("chat_id").toString(); + const QString chatId = receivedInformation.value(CHAT_ID).toString(); QString messageId = receivedInformation.value("message_id").toString(); - qDebug() << "[TDLibReceiver] Message content updated " << chatId << messageId; + LOG("Message content updated " << chatId << messageId); emit messageContentUpdated(chatId, messageId, receivedInformation.value("new_content").toMap()); } void TDLibReceiver::processUpdateDeleteMessages(const QVariantMap &receivedInformation) { - QString chatId = receivedInformation.value("chat_id").toString(); + const QString chatId = receivedInformation.value(CHAT_ID).toString(); QVariantList messageIds = receivedInformation.value("message_ids").toList(); - qDebug() << "[TDLibReceiver] Some messages were deleted " << chatId; + LOG("Some messages were deleted " << chatId); emit messagesDeleted(chatId, messageIds); } diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index eda9838..3434710 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -65,6 +65,9 @@ signals: void messagesDeleted(const QString &chatId, const QVariantList &messageIds); private: + typedef void (TDLibReceiver::*Handler)(const QVariantMap &); + + QHash handlers; void *tdLibClient; bool isActive; @@ -82,6 +85,7 @@ private: void processUpdateUnreadChatCount(const QVariantMap &receivedInformation); void processUpdateChatLastMessage(const QVariantMap &receivedInformation); void processUpdateChatOrder(const QVariantMap &receivedInformation); + void processUpdateChatPosition(const QVariantMap &receivedInformation); void processUpdateChatReadInbox(const QVariantMap &receivedInformation); void processUpdateChatReadOutbox(const QVariantMap &receivedInformation); void processUpdateBasicGroup(const QVariantMap &receivedInformation);