/
lmaxyz
/
telegraf
Обзор
Документация
Войти
/
lmaxyz
/
telegraf
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
src/data/chatlistmodel.cpp
914 строк
36 KB
Nikolay Sinyov
Сделал правильный вывод кол-ва непрочитанных тем в форумах в списке чатов
14 сен 2025, 16:12
14 сен 2025, 16:12
b98158c
Код
Авторство
О чём код?
#include "chatlistmodel.h" #include "../util/telegrafutils.h" #include "groupsmodel.h" #include "usersmodel.h" #include <QListIterator> #include "../debuglog.h" ChatListModel* ChatListModel::instance; ChatListModel::ChatListModel(QObject *parent) : QAbstractListModel(parent), showHiddenChats(false) { connect(GroupsModel::getInstance(), SIGNAL(superGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong))); connect(GroupsModel::getInstance(), SIGNAL(basicGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong))); connect(UsersModel::getInstance(), SIGNAL(userUpdated(qlonglong)), this, SLOT(handleUserUpdated(qlonglong))); connect(TDLibResponseHandler::getInstance(), SIGNAL(newChatDiscovered(QString,QVariantMap)), this, SLOT(handleChatDiscovered(QString,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatLastMessageUpdated(QString,QString,QVariantMap)), this, SLOT(handleChatLastMessageUpdated(QString,QString,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatOrderUpdated(QString,QString,QString)), this, SLOT(handleChatOrderUpdated(QString,QString,QString))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatReadInboxUpdated(QString,QString,int)), this, SLOT(handleChatReadInboxUpdated(QString,QString,int))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatReadOutboxUpdated(QString,QString)), this, SLOT(handleChatReadOutboxUpdated(QString,QString))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatPhotoUpdated(qlonglong,QVariantMap)), this, SLOT(handleChatPhotoUpdated(qlonglong,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatPinnedMessageUpdated(qlonglong,qlonglong)), this, SLOT(handleChatPinnedMessageUpdated(qlonglong,qlonglong))); connect(TDLibResponseHandler::getInstance(), SIGNAL(messageSendSucceeded(qlonglong,qlonglong,QVariantMap)), this, SLOT(handleMessageSendSucceeded(qlonglong,qlonglong,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatNotificationSettingsUpdated(QString,QVariantMap)), this, SLOT(handleChatNotificationSettingsUpdated(QString,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(secretChatUpdated(qlonglong,QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(secretChatReceived(qlonglong,QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatTitleUpdated(QString,QString)), this, SLOT(handleChatTitleUpdated(QString,QString))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatIsMarkedAsUnreadUpdated(qlonglong,bool)), this, SLOT(handleChatIsMarkedAsUnreadUpdated(qlonglong,bool))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatPinnedUpdated(qlonglong,bool,QString)), this, SLOT(handleChatPinnedUpdated(qlonglong,bool,QString))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatDraftMessageUpdated(qlonglong,QVariantMap,QString)), this, SLOT(handleChatDraftMessageUpdated(qlonglong,QVariantMap,QString))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatUnreadMentionCountUpdated(qlonglong,int)), this, SLOT(handleChatUnreadMentionCountUpdated(qlonglong,int))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatUnreadReactionCountUpdated(qlonglong,int)), this, SLOT(handleChatUnreadReactionCountUpdated(qlonglong,int))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatAvailableReactionsUpdated(qlonglong,QVariantMap)), this, SLOT(handleChatAvailableReactionsUpdated(qlonglong,QVariantMap))); connect(TDLibResponseHandler::getInstance(), SIGNAL(chatInArchive(qlonglong)), this, SLOT(handleUpdateChatInArchive(qlonglong))); connect(TDLibResponseHandler::getInstance(), SIGNAL(receivedForumTopics(QVariantMap)), this, SLOT(handleReceivedForumTopics(QVariantMap))); // Don't start the timer until we have at least one chat relativeTimeRefreshTimer = new QTimer(this); relativeTimeRefreshTimer->setSingleShot(false); relativeTimeRefreshTimer->setInterval(30000); connect(relativeTimeRefreshTimer, SIGNAL(timeout()), SLOT(handleRelativeTimeRefreshTimer())); connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged())); connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged())); connect(this, SIGNAL(modelReset()), SIGNAL(countChanged())); requestSortTimer = new QTimer(this); requestSortTimer->setSingleShot(true); requestSortTimer->setInterval(300); connect(requestSortTimer, SIGNAL(timeout()), SLOT(handleRequestSortTimer())); chatInsertionLessThanBufferTimer = new QTimer(this); chatInsertionLessThanBufferTimer->setSingleShot(true); chatInsertionLessThanBufferTimer->setInterval(1000); connect(chatInsertionLessThanBufferTimer, SIGNAL(timeout()), SLOT(handleChatInsertionLessThanBufferTimer())); ChatListModel::instance = this; } ChatListModel::~ChatListModel() { qDeleteAll(chatList); qDeleteAll(hiddenChats); } ChatListModel* ChatListModel::clone() { ChatListModel* res = new ChatListModel(); res->relativeTimeRefreshTimer->stop(); for(int i = 0; i < chatList.count(); i++) { res->chatList.append(chatList.at(i)->clone()); } return res; } void ChatListModel::reset() { chatList.clear(); hiddenChats.clear(); } QHash<int,QByteArray> ChatListModel::roleNames() const { QHash<int,QByteArray> roles; roles.insert(ChatListModel::RoleDisplay, "display"); roles.insert(ChatListModel::RoleChatId, "chat_id"); roles.insert(ChatListModel::RoleOrder, "order"); roles.insert(ChatListModel::RoleChatType, "chat_type"); roles.insert(ChatListModel::RoleGroupId, "group_id"); roles.insert(ChatListModel::RoleTitle, "title"); roles.insert(ChatListModel::RolePhotoSmall, "photo_small"); roles.insert(ChatListModel::RoleUnreadCount, "unread_count"); roles.insert(ChatListModel::RoleUnreadMentionCount, "unread_mention_count"); roles.insert(ChatListModel::RoleUnreadReactionCount, "unread_reaction_count"); roles.insert(ChatListModel::RoleAvailableReactions, "available_reactions"); roles.insert(ChatListModel::RoleLastReadInboxMessageId, "last_read_inbox_message_id"); roles.insert(ChatListModel::RoleLastMessageSenderId, "last_message_sender_id"); roles.insert(ChatListModel::RoleLastMessageDate, "last_message_date"); roles.insert(ChatListModel::RoleLastMessageText, "last_message_text"); roles.insert(ChatListModel::RoleLastMessageStatus, "last_message_status"); roles.insert(ChatListModel::RoleChatMemberStatus, "chat_member_status"); roles.insert(ChatListModel::RoleSecretChatState, "secret_chat_state"); roles.insert(ChatListModel::RoleIsVerified, "is_verified"); roles.insert(ChatListModel::RoleIsRKNVerified, "is_rkn_verified"); roles.insert(ChatListModel::RoleIsChannel, "is_channel"); roles.insert(ChatListModel::RoleIsForum, "is_forum"); roles.insert(ChatListModel::RoleIsGroup, "is_group"); roles.insert(ChatListModel::RoleIsBasicGroup, "is_basic_group"); roles.insert(ChatListModel::RoleIsSuperGroup, "is_super_group"); roles.insert(ChatListModel::RoleIsPrivateChat, "is_private_chat"); roles.insert(ChatListModel::RoleIsContact, "is_contact"); roles.insert(ChatListModel::RoleIsBot, "is_bot"); roles.insert(ChatListModel::RoleIsMarkedAsUnread, "is_marked_as_unread"); roles.insert(ChatListModel::RoleIsPinned, "is_pinned"); roles.insert(ChatListModel::RoleIsArchived, "is_archived"); roles.insert(ChatListModel::RoleIsMuted, "is_muted"); roles.insert(ChatListModel::RoleFilter, "filter"); roles.insert(ChatListModel::RoleDraftMessageDate, "draft_message_date"); roles.insert(ChatListModel::RoleDraftMessageText, "draft_message_text"); return roles; } int ChatListModel::rowCount(const QModelIndex &) const { return chatList.size(); } QVariant ChatListModel::data(const QModelIndex &index, int role) const { const int row = index.row(); if (row >= 0 && row < chatList.size()) { const ChatData *data = chatList.at(row); switch ((ChatListModel::Role)role) { case ChatListModel::RoleDisplay: return data->chatData; case ChatListModel::RoleOrder: return data->order; case ChatListModel::RoleChatId: return data->chatId; case ChatListModel::RoleChatType: return data->chatType; case ChatListModel::RoleGroupId: return data->groupId; case ChatListModel::RoleTitle: return data->title(); case ChatListModel::RolePhotoSmall: return data->photoSmall(); case ChatListModel::RoleUnreadCount: return data->unreadCount(); case ChatListModel::RoleUnreadMentionCount: return data->unreadMentionCount(); case ChatListModel::RoleAvailableReactions: return data->availableReactions(); case ChatListModel::RoleUnreadReactionCount: return data->unreadReactionCount(); case ChatListModel::RoleLastReadInboxMessageId: return data->lastReadInboxMessageId(); case ChatListModel::RoleLastMessageSenderId: return data->senderUserId(); case ChatListModel::RoleLastMessageText: return data->senderMessageText(); case ChatListModel::RoleLastMessageDate: return data->senderMessageDate(); case ChatListModel::RoleLastMessageStatus: return data->senderMessageStatus(); case ChatListModel::RoleChatMemberStatus: return data->memberStatus; case ChatListModel::RoleSecretChatState: return data->secretChatState; case ChatListModel::RoleIsVerified: return data->verified; case ChatListModel::RoleIsRKNVerified: return data->rkn_verified; case ChatListModel::RoleIsChannel: return data->isChannel(); case ChatListModel::RoleIsForum: return data->isForum(); case ChatListModel::RoleIsGroup: return data->isGroup(); case ChatListModel::RoleIsBasicGroup: return data->isBasicGroup(); case ChatListModel::RoleIsSuperGroup: return data->isSuperGroup(); case ChatListModel::RoleIsPrivateChat: return data->isPrivate(); case ChatListModel::RoleIsContact: return data->isContact(); case ChatListModel::RoleIsBot: return data->isBot(); case ChatListModel::RoleIsMarkedAsUnread: return data->isMarkedAsUnread(); case ChatListModel::RoleIsPinned: return pinnedChats[data->chatId]; case ChatListModel::RoleIsArchived: return data->archived; case ChatListModel::RoleIsMuted: return data->isMute(); case ChatListModel::RoleFilter: return data->title() + " " + data->senderMessageText(); case ChatListModel::RoleDraftMessageText: return data->draftMessageText(); case ChatListModel::RoleDraftMessageDate: return data->draftMessageDate(); } } return QVariant(); } QVariantMap ChatListModel::get(int row) { QHash<int,QByteArray> names = roleNames(); QHashIterator<int, QByteArray> i(names); QVariantMap res; QModelIndex idx = index(row, 0); while (i.hasNext()) { i.next(); QVariant data = idx.data(i.key()); res[i.value()] = data; } return res; } QVariantMap ChatListModel::getById(qlonglong chatId) { if (chatIndexMap.contains(chatId)) { return chatList.value(chatIndexMap.value(chatId))->chatData; } return QVariantMap(); } void ChatListModel::enableRefreshTimer() { // Start timestamp refresh timer if not yet active (usually when the first visible chat is discovered) if (!relativeTimeRefreshTimer->isActive()) { relativeTimeRefreshTimer->start(); } } void ChatListModel::addChatsFromBuffer() { if(chatInsertionLessThanBufferTimer->isActive()) { chatInsertionLessThanBufferTimer->stop(); } auto bufferSize = addedChatBuffer.size(); auto currentSize = chatList.size(); beginInsertRows(QModelIndex(), currentSize, currentSize + bufferSize - 1); for(const auto bufferedChat: std::as_const(addedChatBuffer)) { chatList.append(bufferedChat); chatIndexMap.insert(bufferedChat->chatId, chatList.size() - 1); if (bufferedChat->isForum()) { TDLibRequestSender::getInstance()->callGetForumTopicsRequest(bufferedChat->chatId); } emitUnmutedChatLastMessageChangedIfNeeded(bufferedChat); } endInsertRows(); addedChatBuffer.clear(); if(!sortRequestedOnce) { lastChatCount = chatList.size(); requestSortTimer->start(); } } void ChatListModel::addVisibleChat(ChatData *chat) { if (TDLibState::getInstance()->getJoinChatRequested()) { TDLibState::getInstance()->registerJoinChat(); emit chatJoined(chat->chatId, chat->chatData.value("title").toString()); } addedChatBuffer.append(chat); if(addedChatBuffer.size() < chatBufferSize) { chatInsertionLessThanBufferTimer->start(); return; } addChatsFromBuffer(); } ChatData* ChatListModel::getChatData(int row) { return chatList.at(row); } void ChatListModel::updateChatVisibility(const GroupModel *group) { // See if any group has been removed from from view for (int i = 0; i < chatList.size(); i++) { ChatData *chat = chatList.at(i); const QVector<int> changedRoles(chat->updateGroup(group)); if (chat->isHidden() && !showHiddenChats) { beginRemoveRows(QModelIndex(), i, i); chatList.removeAt(i); // Update damaged part of the map const int n = chatList.size(); for (int pos = i; pos < n; pos++) { chatIndexMap.insert(chatList.at(pos)->chatId, pos); } i--; hiddenChats.insert(chat->chatId, chat); endRemoveRows(); } else if (!changedRoles.isEmpty()) { const QModelIndex modelIndex(index(i)); emit dataChanged(modelIndex, modelIndex, changedRoles); } } // And see if any group been added to the view const QList<ChatData*> hiddenChatList = hiddenChats.values(); const int n = hiddenChatList.size(); for (int j = 0; j < n; j++) { ChatData *chat = hiddenChatList.at(j); chat->updateGroup(group); if (!chat->isHidden() || showHiddenChats) { hiddenChats.remove(chat->chatId); addVisibleChat(chat); } } } void ChatListModel::updateSecretChatVisibility(const QVariantMap secretChatDetails) { // See if any secret chat has been closed for (int i = 0; i < chatList.size(); i++) { ChatData *chat = chatList.at(i); if (chat->chatType != TDLibConstants::ChatTypeSecret) { continue; } if (chat->chatData.value(TYPE).toMap().value(SECRET_CHAT_ID).toLongLong() != secretChatDetails.value(ID).toLongLong()) { continue; } const QVector<int> changedRoles(chat->updateSecretChat(secretChatDetails)); if (chat->isHidden() && !showHiddenChats) { beginRemoveRows(QModelIndex(), i, i); chatList.removeAt(i); // Update damaged part of the map const int n = chatList.size(); for (int pos = i; pos < n; pos++) { chatIndexMap.insert(chatList.at(pos)->chatId, pos); } i--; hiddenChats.insert(chat->chatId, chat); endRemoveRows(); } else if (!changedRoles.isEmpty()) { const QModelIndex modelIndex(index(i)); emit dataChanged(modelIndex, modelIndex, changedRoles); } } } bool ChatListModel::showAllChats() const { return showHiddenChats; } void ChatListModel::setShowAllChats(bool showAll) { if (showHiddenChats != showAll) { showHiddenChats = showAll; updateChatVisibility(Q_NULLPTR); emit showAllChatsChanged(); } } void ChatListModel::handleChatDiscovered(const QString &, const QVariantMap &chatToBeAdded) { ChatData *chat = new ChatData(chatToBeAdded); const auto *group = GroupsModel::getInstance()->getGroup(chat->groupId); if (group) { chat->updateGroup(group); } if (chat->chatType == TDLibConstants::ChatTypeSecret) { QVariantMap secretChatDetails = TDLibDataRepository::getInstance()->getSecretChat(chatToBeAdded.value(TYPE).toMap().value(SECRET_CHAT_ID).toLongLong()); if (!secretChatDetails.isEmpty()) { chat->updateSecretChat(secretChatDetails); } } if (chat->isHidden() && !showHiddenChats) { hiddenChats.insert(chat->chatId, chat); } else { addVisibleChat(chat); } } void ChatListModel::emitUnmutedChatLastMessageChangedIfNeeded(const ChatData* chat) { auto shouldCareAboutChat = false; if(!chat->isMute() && chat->unreadCount() > 0) { shouldCareAboutChat = true; } if(!shouldCareAboutChat) { if(chat->unreadMentionCount() > 0 && chat->lastMessageContainsUnreadMention()) { shouldCareAboutChat = true; } } if(shouldCareAboutChat && chat->senderUserId() != TDLibState::getInstance()->getMyUserId()) { emit unmutedChatLastMessageUpdated(new ChatData(chat->chatData)); } } void ChatListModel::handleChatLastMessageUpdated(const QString &id, const QString &order, const QVariantMap &lastMessage) { bool ok; const qlonglong chatId = id.toLongLong(&ok); if (ok) { if (chatIndexMap.contains(chatId)) { int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); const QModelIndex modelIndex(index(chatIndex)); chat->updateLastMessage(lastMessage); emitUnmutedChatLastMessageChangedIfNeeded(chat); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->setOrder(order); chat->chatData.insert(LAST_MESSAGE, lastMessage); // A chat can become visible (e.g. when a known contact joins Telegram) // When the private chat is discovered it doesn't have any messages, now it could be there... if (!chat->isHidden() || showHiddenChats) { hiddenChats.remove(chatId); addVisibleChat(chat); } } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->updateLastMessage(lastMessage); break; } } } } } } void ChatListModel::handleChatOrderUpdated(const QString &id, const QString &order, const QString &chatListName) { bool ok; const qlonglong chatId = id.toLongLong(&ok); if (ok) { if (chatIndexMap.contains(chatId)) { int chatIndex = chatIndexMap.value(chatId); if (chatList.at(chatIndex)->setOrder(order)) { if (chatListName.contains("chatListArchive")) { chatList.at(chatIndex)->archived = true; } } } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->setOrder(order); if (chatListName.contains("chatListArchive")) { chat->archived = true; } } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { if (chat->setOrder(order)) { if (chatListName.contains("chatListArchive")) { chat->archived = true; } } break; } } } } } } void ChatListModel::handleChatReadInboxUpdated(const QString &id, const QString &lastReadInboxMessageId, int unreadCount) { bool ok; const qlonglong chatId = id.toLongLong(&ok); isGetForumTopics(chatId); if (ok) { const qlonglong messageId = lastReadInboxMessageId.toLongLong(); if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); const QModelIndex modelIndex(index(chatIndex)); ChatData *chat = chatList.at(chatIndex); chat->updateUnreadCount(unreadCount); chat->updateLastReadInboxMessageId(messageId); if(unreadCount == 0){ emit unmutedChatLastMessageCleared(chatId); } emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->updateUnreadCount(unreadCount); chat->updateLastReadInboxMessageId(messageId); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->updateUnreadCount(unreadCount); chat->updateLastReadInboxMessageId(messageId); break; } } } } } } void ChatListModel::handleChatReadOutboxUpdated(const QString &id, const QString &lastReadOutboxMessageId) { bool ok; const qlonglong chatId = id.toLongLong(&ok); isGetForumTopics(chatId); if (ok) { if (chatIndexMap.contains(chatId)) { 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); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(LAST_READ_OUTBOX_MESSAGE_ID, lastReadOutboxMessageId); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(LAST_READ_OUTBOX_MESSAGE_ID, lastReadOutboxMessageId); break; } } } } } } void ChatListModel::handleChatPhotoUpdated(qlonglong chatId, const QVariantMap &photo) { isGetForumTopics(chatId); if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(PHOTO, photo); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(PHOTO, photo); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(PHOTO, photo); break; } } } } } void ChatListModel::handleChatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(PINNED_MESSAGE_ID, pinnedMessageId); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(PINNED_MESSAGE_ID, pinnedMessageId); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(PINNED_MESSAGE_ID, pinnedMessageId); break; } } } } } void ChatListModel::handleReceivedForumTopics(const QVariantMap &fullTopicList) { qlonglong chatId = fullTopicList.value(CHAT_ID).toLongLong(); qlonglong unreadForumTopicCouns = fullTopicList.value("unread_forum_topic_count").toLongLong(); if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->updateUnreadCount(unreadForumTopicCouns); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->updateUnreadCount(unreadForumTopicCouns); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->updateUnreadCount(unreadForumTopicCouns); break; } } } } } bool ChatListModel::isGetForumTopics(qlonglong id) { ChatData *chat; if (chatIndexMap.contains(id)) { const int chatIndex = chatIndexMap.value(id); chat = chatList.at(chatIndex); } else { chat = hiddenChats.value(id); } if (chat) { if (chat->isForum()) { TDLibRequestSender::getInstance()->callGetForumTopicsRequest(id); return true; } } return false; } void ChatListModel::handleMessageSendSucceeded(qlonglong, qlonglong, const QVariantMap &message) { bool ok; const qlonglong chatId(message.value(CHAT_ID).toLongLong(&ok)); if (ok) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); const QModelIndex modelIndex(index(chatIndex)); chatList.at(chatIndex)->updateLastMessage(message); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(LAST_MESSAGE, message); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->updateLastMessage(message); break; } } } } } } void ChatListModel::handleChatNotificationSettingsUpdated(const QString &id, const QVariantMap &chatNotificationSettings) { bool ok; const qlonglong chatId = id.toLongLong(&ok); if (ok) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(NOTIFICATION_SETTINGS, chatNotificationSettings); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(NOTIFICATION_SETTINGS, chatNotificationSettings); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(NOTIFICATION_SETTINGS, chatNotificationSettings); break; } } } } } } void ChatListModel::handleGroupUpdated(qlonglong groupId) { updateChatVisibility(GroupsModel::getInstance()->getGroup(groupId)); } void ChatListModel::handleUserUpdated(qlonglong userId) { for (int i = 0; i < chatList.size(); i++) { ChatData *chat = chatList.at(i); if(chat->chatId == userId) { auto changedRoles = chat->updateVerification(); if(!changedRoles.isEmpty()) { const QModelIndex modelIndex(index(i)); emit dataChanged(modelIndex, modelIndex, changedRoles); } } } for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == userId) { chat->updateVerification(); } } } void ChatListModel::handleSecretChatUpdated(qlonglong, const QVariantMap &secretChat) { updateSecretChatVisibility(secretChat); } void ChatListModel::handleChatTitleUpdated(const QString &chatId, const QString &title) { qlonglong chatIdLongLong = chatId.toLongLong(); if (chatIndexMap.contains(chatIdLongLong)) { const int chatIndex = chatIndexMap.value(chatIdLongLong); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(TITLE, title); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId.toLongLong()); if (chat) { chat->chatData.insert(TITLE, title); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatIdLongLong) { chat->chatData.insert(TITLE, title); break; } } } } } void ChatListModel::handleChatPinnedUpdated(qlonglong chatId, bool chatIsPinned, const QString &chatListName) { auto isChanged = false; if(chatIsPinned != pinnedChats[chatId]) { isChanged = true; pinnedChats.insert(chatId, chatIsPinned); } if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); if (chatListName.contains("chatListArchive")) { chatList.at(chatIndex)->archived = true; } if(isChanged) { const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(IS_PINNED, chatIsPinned); if (chatListName.contains("chatListArchive")) { chat->archived = true; } } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { if (chatListName.contains("chatListArchive")) { chat->archived = true; } break; } } } } } void ChatListModel::handleChatIsMarkedAsUnreadUpdated(qlonglong chatId, bool chatIsMarkedAsUnread) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(IS_MARKED_AS_UNREAD, chatIsMarkedAsUnread); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(IS_MARKED_AS_UNREAD, chatIsMarkedAsUnread); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(IS_MARKED_AS_UNREAD, chatIsMarkedAsUnread); break; } } } } } void ChatListModel::handleChatDraftMessageUpdated(qlonglong chatId, const QVariantMap &draftMessage, const QString &order) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(DRAFT_MESSAGE, draftMessage); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); if (chat->setOrder(order)) { //updateChatOrder(chatIndex); } } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(DRAFT_MESSAGE, draftMessage); break; } } } } void ChatListModel::handleChatUnreadMentionCountUpdated(qlonglong chatId, int unreadMentionCount) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(UNREAD_MENTION_COUNT, unreadMentionCount); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(UNREAD_MENTION_COUNT, unreadMentionCount); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(UNREAD_MENTION_COUNT, unreadMentionCount); break; } } } } } void ChatListModel::handleChatUnreadReactionCountUpdated(qlonglong chatId, int unreadReactionCount) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(UNREAD_REACTION_COUNT, unreadReactionCount); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(UNREAD_REACTION_COUNT, unreadReactionCount); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(UNREAD_REACTION_COUNT, unreadReactionCount); break; } } } } } void ChatListModel::handleChatAvailableReactionsUpdated(qlonglong chatId, const QVariantMap availableReactions) { if (chatIndexMap.contains(chatId)) { const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(AVAILABLE_REACTIONS, availableReactions); } else { ChatData *chat = hiddenChats.value(chatId); if (chat) { chat->chatData.insert(AVAILABLE_REACTIONS, availableReactions); } else { for (int i = 0; i < addedChatBuffer.size(); i++) { ChatData *chat = addedChatBuffer.at(i); if(chat->chatId == chatId) { chat->chatData.insert(AVAILABLE_REACTIONS, availableReactions); break; } } } } } void ChatListModel::handleRelativeTimeRefreshTimer() { emit dataChanged(index(0), index(chatList.size() - 1)); } void ChatListModel::handleChatInsertionLessThanBufferTimer() { addChatsFromBuffer(); } void ChatListModel::handleRequestSortTimer() { if(chatList.size() - lastChatCount < chatBufferSize) { sortRequestedOnce = true; emit requestSort(); } } void ChatListModel::handleUpdateChatInArchive(const qlonglong chatID) { if (!hiddenChats.contains(chatID)) { auto index = chatIndexMap.value(chatID); if (index < chatList.size()) { chatList.at(chatIndexMap.value(chatID))->archived = true; } } else { hiddenChats.value(chatID)->archived = true; } }