2020-09-02 23:49:15 +03:00
|
|
|
/*
|
2020-10-19 20:34:47 +03:00
|
|
|
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
2020-09-02 23:49:15 +03:00
|
|
|
|
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
|
2020-08-19 10:55:13 +03:00
|
|
|
#include "chatlistmodel.h"
|
2020-10-03 23:58:45 +03:00
|
|
|
#include "fernschreiberutils.h"
|
2021-01-10 15:35:34 +03:00
|
|
|
#include <QListIterator>
|
2020-08-19 10:55:13 +03:00
|
|
|
|
2020-11-22 06:58:47 +03:00
|
|
|
#define DEBUG_MODULE ChatListModel
|
|
|
|
#include "debuglog.h"
|
2020-09-27 17:18:14 +03:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
const QString ID("id");
|
2020-10-01 00:59:12 +03:00
|
|
|
const QString DATE("date");
|
|
|
|
const QString TEXT("text");
|
2020-10-04 04:27:49 +03:00
|
|
|
const QString TYPE("type");
|
2020-10-01 00:59:12 +03:00
|
|
|
const QString TITLE("title");
|
|
|
|
const QString PHOTO("photo");
|
|
|
|
const QString SMALL("small");
|
2020-09-27 17:18:14 +03:00
|
|
|
const QString ORDER("order");
|
|
|
|
const QString CHAT_ID("chat_id");
|
2020-10-01 00:59:12 +03:00
|
|
|
const QString CONTENT("content");
|
2020-09-27 17:18:14 +03:00
|
|
|
const QString LAST_MESSAGE("last_message");
|
2020-12-31 02:59:05 +03:00
|
|
|
const QString DRAFT_MESSAGE("draft_message");
|
2020-12-07 23:43:09 +03:00
|
|
|
const QString SENDER("sender");
|
|
|
|
const QString USER_ID("user_id");
|
2020-10-04 04:27:49 +03:00
|
|
|
const QString BASIC_GROUP_ID("basic_group_id");
|
|
|
|
const QString SUPERGROUP_ID("supergroup_id");
|
2020-09-27 17:18:14 +03:00
|
|
|
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");
|
2020-11-14 16:10:24 +03:00
|
|
|
const QString SENDING_STATE("sending_state");
|
2020-10-03 22:06:50 +03:00
|
|
|
const QString IS_CHANNEL("is_channel");
|
2020-12-03 02:50:38 +03:00
|
|
|
const QString IS_VERIFIED("is_verified");
|
2020-12-31 02:19:36 +03:00
|
|
|
const QString IS_MARKED_AS_UNREAD("is_marked_as_unread");
|
2021-01-06 12:42:12 +03:00
|
|
|
const QString IS_PINNED("is_pinned");
|
2020-11-17 14:18:46 +03:00
|
|
|
const QString PINNED_MESSAGE_ID("pinned_message_id");
|
2020-10-04 04:27:49 +03:00
|
|
|
const QString _TYPE("@type");
|
2020-11-26 02:25:15 +03:00
|
|
|
const QString SECRET_CHAT_ID("secret_chat_id");
|
2020-09-27 17:18:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
class ChatListModel::ChatData
|
|
|
|
{
|
|
|
|
public:
|
2020-10-01 00:59:12 +03:00
|
|
|
|
2020-12-29 18:32:39 +03:00
|
|
|
ChatData(TDLibWrapper *tdLibWrapper, const QVariantMap &data);
|
2020-09-27 17:18:14 +03:00
|
|
|
|
|
|
|
int compareTo(const ChatData *chat) const;
|
|
|
|
bool setOrder(const QString &order);
|
2020-10-01 00:59:12 +03:00
|
|
|
const QVariant lastMessage(const QString &key) const;
|
|
|
|
QString title() const;
|
|
|
|
int unreadCount() const;
|
|
|
|
QVariant photoSmall() const;
|
|
|
|
qlonglong lastReadInboxMessageId() const;
|
|
|
|
qlonglong senderUserId() const;
|
2020-12-07 23:43:09 +03:00
|
|
|
qlonglong senderChatId() const;
|
|
|
|
bool senderIsChat() const;
|
2020-10-01 00:59:12 +03:00
|
|
|
qlonglong senderMessageDate() const;
|
|
|
|
QString senderMessageText() const;
|
2020-11-14 16:10:24 +03:00
|
|
|
QString senderMessageStatus() const;
|
2020-12-31 02:59:05 +03:00
|
|
|
qlonglong draftMessageDate() const;
|
|
|
|
QString draftMessageText() const;
|
2020-10-03 22:06:50 +03:00
|
|
|
bool isChannel() const;
|
2020-10-04 04:27:49 +03:00
|
|
|
bool isHidden() const;
|
2020-12-31 02:19:36 +03:00
|
|
|
bool isMarkedAsUnread() const;
|
2021-01-06 12:42:12 +03:00
|
|
|
bool isPinned() const;
|
2020-10-01 00:59:12 +03:00
|
|
|
bool updateUnreadCount(int unreadCount);
|
|
|
|
bool updateLastReadInboxMessageId(qlonglong messageId);
|
|
|
|
QVector<int> updateLastMessage(const QVariantMap &message);
|
2020-10-04 04:27:49 +03:00
|
|
|
QVector<int> updateGroup(const TDLibWrapper::Group *group);
|
2020-11-26 00:09:47 +03:00
|
|
|
QVector<int> updateSecretChat(const QVariantMap &secretChatDetails);
|
2020-12-29 18:32:39 +03:00
|
|
|
TDLibWrapper *tdLibWrapper;
|
2020-09-27 17:18:14 +03:00
|
|
|
|
|
|
|
public:
|
|
|
|
QVariantMap chatData;
|
2020-10-04 04:27:49 +03:00
|
|
|
qlonglong chatId;
|
2020-09-27 17:18:14 +03:00
|
|
|
qlonglong order;
|
2020-10-04 04:27:49 +03:00
|
|
|
qlonglong groupId;
|
2020-12-03 02:50:38 +03:00
|
|
|
bool verified;
|
2020-10-04 04:27:49 +03:00
|
|
|
TDLibWrapper::ChatType chatType;
|
|
|
|
TDLibWrapper::ChatMemberStatus memberStatus;
|
2020-11-26 00:09:47 +03:00
|
|
|
TDLibWrapper::SecretChatState secretChatState;
|
2021-01-30 00:53:28 +03:00
|
|
|
|
2020-09-27 17:18:14 +03:00
|
|
|
};
|
|
|
|
|
2020-12-29 18:32:39 +03:00
|
|
|
ChatListModel::ChatData::ChatData(TDLibWrapper *tdLibWrapper, const QVariantMap &data) :
|
|
|
|
tdLibWrapper(tdLibWrapper),
|
2020-09-27 17:18:14 +03:00
|
|
|
chatData(data),
|
2020-10-04 04:27:49 +03:00
|
|
|
chatId(data.value(ID).toLongLong()),
|
|
|
|
order(data.value(ORDER).toLongLong()),
|
|
|
|
groupId(0),
|
2020-12-03 02:50:38 +03:00
|
|
|
verified(false),
|
2020-10-04 04:27:49 +03:00
|
|
|
memberStatus(TDLibWrapper::ChatMemberStatusUnknown),
|
2021-01-30 00:53:28 +03:00
|
|
|
secretChatState(TDLibWrapper::SecretChatStateUnknown)
|
2020-09-27 17:18:14 +03:00
|
|
|
{
|
2020-10-04 04:27:49 +03:00
|
|
|
const QVariantMap type(data.value(TYPE).toMap());
|
2020-10-31 22:18:12 +03:00
|
|
|
switch (chatType = TDLibWrapper::chatTypeFromString(type.value(_TYPE).toString())) {
|
2020-10-04 04:27:49 +03:00
|
|
|
case TDLibWrapper::ChatTypeBasicGroup:
|
|
|
|
groupId = type.value(BASIC_GROUP_ID).toLongLong();
|
|
|
|
break;
|
|
|
|
case TDLibWrapper::ChatTypeSupergroup:
|
|
|
|
groupId = type.value(SUPERGROUP_ID).toLongLong();
|
|
|
|
break;
|
|
|
|
case TDLibWrapper::ChatTypeUnknown:
|
|
|
|
case TDLibWrapper::ChatTypePrivate:
|
|
|
|
case TDLibWrapper::ChatTypeSecret:
|
|
|
|
break;
|
|
|
|
}
|
2020-09-27 17:18:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int ChatListModel::ChatData::compareTo(const ChatData *other) const
|
|
|
|
{
|
|
|
|
if (order == other->order) {
|
2020-10-04 04:27:49 +03:00
|
|
|
return (chatId < other->chatId) ? 1 : -1;
|
2020-09-27 17:18:14 +03:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
2020-10-01 00:59:12 +03:00
|
|
|
inline const QVariant ChatListModel::ChatData::lastMessage(const QString &key) const
|
|
|
|
{
|
|
|
|
return chatData.value(LAST_MESSAGE).toMap().value(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ChatListModel::ChatData::title() const
|
|
|
|
{
|
|
|
|
return chatData.value(TITLE).toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ChatListModel::ChatData::unreadCount() const
|
|
|
|
{
|
|
|
|
return chatData.value(UNREAD_COUNT).toInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant ChatListModel::ChatData::photoSmall() const
|
|
|
|
{
|
|
|
|
return chatData.value(PHOTO).toMap().value(SMALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
qlonglong ChatListModel::ChatData::lastReadInboxMessageId() const
|
|
|
|
{
|
|
|
|
return chatData.value(LAST_READ_INBOX_MESSAGE_ID).toLongLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
qlonglong ChatListModel::ChatData::senderUserId() const
|
|
|
|
{
|
2020-12-07 23:43:09 +03:00
|
|
|
return lastMessage(SENDER).toMap().value(USER_ID).toLongLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
qlonglong ChatListModel::ChatData::senderChatId() const
|
|
|
|
{
|
|
|
|
return lastMessage(SENDER).toMap().value(CHAT_ID).toLongLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ChatListModel::ChatData::senderIsChat() const
|
|
|
|
{
|
|
|
|
return lastMessage(SENDER).toMap().value(_TYPE).toString() == "messageSenderChat";
|
2020-10-01 00:59:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
qlonglong ChatListModel::ChatData::senderMessageDate() const
|
|
|
|
{
|
|
|
|
return lastMessage(DATE).toLongLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ChatListModel::ChatData::senderMessageText() const
|
|
|
|
{
|
2021-01-30 00:53:28 +03:00
|
|
|
qlonglong myUserId = tdLibWrapper->getUserInformation().value(ID).toLongLong();
|
|
|
|
return FernschreiberUtils::getMessageShortText(tdLibWrapper, lastMessage(CONTENT).toMap(), isChannel(), myUserId, lastMessage(SENDER).toMap() );
|
2020-10-01 00:59:12 +03:00
|
|
|
}
|
|
|
|
|
2020-12-31 02:59:05 +03:00
|
|
|
|
2020-11-14 16:10:24 +03:00
|
|
|
QString ChatListModel::ChatData::senderMessageStatus() const
|
|
|
|
{
|
2021-01-30 00:53:28 +03:00
|
|
|
qlonglong myUserId = tdLibWrapper->getUserInformation().value(ID).toLongLong();
|
|
|
|
if (isChannel() || myUserId != senderUserId() || myUserId == chatId) {
|
2020-11-14 16:10:24 +03:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
if (lastMessage(ID) == chatData.value(LAST_READ_OUTBOX_MESSAGE_ID)) {
|
|
|
|
return " ✅";
|
|
|
|
} else {
|
|
|
|
QVariantMap lastMessage = chatData.value(LAST_MESSAGE).toMap();
|
|
|
|
if (lastMessage.contains(SENDING_STATE)) {
|
|
|
|
QVariantMap sendingState = lastMessage.value(SENDING_STATE).toMap();
|
|
|
|
if (sendingState.value(_TYPE).toString() == "messageSendingStatePending") {
|
|
|
|
return " 🕙";
|
|
|
|
} else {
|
|
|
|
return " ❌";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return " ☑️";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-31 02:59:05 +03:00
|
|
|
qlonglong ChatListModel::ChatData::draftMessageDate() const
|
|
|
|
{
|
|
|
|
QVariantMap draft = chatData.value(DRAFT_MESSAGE).toMap();
|
|
|
|
if(draft.isEmpty()) {
|
|
|
|
return qlonglong(0);
|
|
|
|
}
|
|
|
|
return draft.value(DATE).toLongLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ChatListModel::ChatData::draftMessageText() const
|
|
|
|
{
|
|
|
|
QVariantMap draft = chatData.value(DRAFT_MESSAGE).toMap();
|
|
|
|
if(draft.isEmpty()) {
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
return draft.value("input_message_text").toMap().value(TEXT).toMap().value(TEXT).toString();
|
|
|
|
}
|
2020-11-14 16:10:24 +03:00
|
|
|
|
2020-10-03 22:06:50 +03:00
|
|
|
bool ChatListModel::ChatData::isChannel() const
|
|
|
|
{
|
2020-10-04 15:21:28 +03:00
|
|
|
return chatData.value(TYPE).toMap().value(IS_CHANNEL).toBool();
|
2020-10-03 22:06:50 +03:00
|
|
|
}
|
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
bool ChatListModel::ChatData::isHidden() const
|
|
|
|
{
|
|
|
|
// Cover all enum values so that compiler warns us when/if enum gets extended
|
|
|
|
switch (chatType) {
|
|
|
|
case TDLibWrapper::ChatTypeBasicGroup:
|
|
|
|
case TDLibWrapper::ChatTypeSupergroup:
|
|
|
|
switch (memberStatus) {
|
|
|
|
case TDLibWrapper::ChatMemberStatusLeft:
|
|
|
|
case TDLibWrapper::ChatMemberStatusUnknown:
|
|
|
|
return true;
|
|
|
|
case TDLibWrapper::ChatMemberStatusCreator:
|
|
|
|
case TDLibWrapper::ChatMemberStatusAdministrator:
|
|
|
|
case TDLibWrapper::ChatMemberStatusMember:
|
|
|
|
case TDLibWrapper::ChatMemberStatusRestricted:
|
|
|
|
case TDLibWrapper::ChatMemberStatusBanned:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TDLibWrapper::ChatTypeUnknown:
|
2021-02-07 20:23:59 +03:00
|
|
|
break;
|
2020-10-04 04:27:49 +03:00
|
|
|
case TDLibWrapper::ChatTypePrivate:
|
2021-02-14 14:55:54 +03:00
|
|
|
if (chatData.value(LAST_MESSAGE).isNull()
|
|
|
|
&& chatData.value(LAST_READ_INBOX_MESSAGE_ID).toLongLong() == 0
|
|
|
|
&& chatData.value(LAST_READ_OUTBOX_MESSAGE_ID).toLongLong() == 0) {
|
2021-02-07 20:23:59 +03:00
|
|
|
return true;
|
|
|
|
}
|
2020-11-26 00:09:47 +03:00
|
|
|
break;
|
2020-10-04 04:27:49 +03:00
|
|
|
case TDLibWrapper::ChatTypeSecret:
|
2020-11-26 00:09:47 +03:00
|
|
|
if (secretChatState == TDLibWrapper::SecretChatStateClosed) {
|
|
|
|
return true;
|
|
|
|
}
|
2020-10-04 04:27:49 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-12-31 02:19:36 +03:00
|
|
|
bool ChatListModel::ChatData::isMarkedAsUnread() const
|
|
|
|
{
|
|
|
|
return chatData.value(IS_MARKED_AS_UNREAD).toBool();
|
|
|
|
}
|
|
|
|
|
2021-01-06 12:42:12 +03:00
|
|
|
bool ChatListModel::ChatData::isPinned() const
|
|
|
|
{
|
|
|
|
return chatData.value(IS_PINNED).toBool();
|
|
|
|
}
|
|
|
|
|
2020-10-01 00:59:12 +03:00
|
|
|
bool ChatListModel::ChatData::updateUnreadCount(int count)
|
|
|
|
{
|
|
|
|
const int prevUnreadCount(unreadCount());
|
|
|
|
chatData.insert(UNREAD_COUNT, count);
|
|
|
|
return prevUnreadCount != unreadCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ChatListModel::ChatData::updateLastReadInboxMessageId(qlonglong messageId)
|
|
|
|
{
|
|
|
|
const qlonglong prevLastReadInboxMessageId(lastReadInboxMessageId());
|
|
|
|
chatData.insert(LAST_READ_INBOX_MESSAGE_ID, messageId);
|
|
|
|
return prevLastReadInboxMessageId != lastReadInboxMessageId();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVector<int> ChatListModel::ChatData::updateLastMessage(const QVariantMap &message)
|
|
|
|
{
|
|
|
|
const qlonglong prevSenderUserId(senderUserId());
|
|
|
|
const qlonglong prevSenderMessageDate(senderMessageDate());
|
|
|
|
const QString prevSenderMessageText(senderMessageText());
|
2020-11-14 16:10:24 +03:00
|
|
|
const QString prevSenderMessageStatus(senderMessageStatus());
|
|
|
|
|
2020-10-01 00:59:12 +03:00
|
|
|
|
|
|
|
chatData.insert(LAST_MESSAGE, message);
|
|
|
|
|
|
|
|
QVector<int> changedRoles;
|
|
|
|
changedRoles.append(RoleDisplay);
|
|
|
|
if (prevSenderUserId != senderUserId()) {
|
|
|
|
changedRoles.append(RoleLastMessageSenderId);
|
|
|
|
}
|
|
|
|
if (prevSenderMessageDate != senderMessageDate()) {
|
|
|
|
changedRoles.append(RoleLastMessageDate);
|
|
|
|
}
|
|
|
|
if (prevSenderMessageText != senderMessageText()) {
|
2021-12-09 02:46:04 +03:00
|
|
|
changedRoles.append(RoleFilter);
|
2020-10-01 00:59:12 +03:00
|
|
|
changedRoles.append(RoleLastMessageText);
|
|
|
|
}
|
2020-11-14 16:10:24 +03:00
|
|
|
if (prevSenderMessageStatus != senderMessageStatus()) {
|
|
|
|
changedRoles.append(RoleLastMessageStatus);
|
|
|
|
}
|
2020-10-01 00:59:12 +03:00
|
|
|
return changedRoles;
|
|
|
|
}
|
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
QVector<int> ChatListModel::ChatData::updateGroup(const TDLibWrapper::Group *group)
|
|
|
|
{
|
|
|
|
QVector<int> changedRoles;
|
|
|
|
|
|
|
|
if (group && groupId == group->groupId) {
|
|
|
|
const TDLibWrapper::ChatMemberStatus groupMemberStatus = group->chatMemberStatus();
|
|
|
|
if (memberStatus != groupMemberStatus) {
|
|
|
|
memberStatus = groupMemberStatus;
|
|
|
|
changedRoles.append(RoleChatMemberStatus);
|
|
|
|
}
|
2020-12-03 02:50:38 +03:00
|
|
|
// There's no "is_verified" in "basic_group" but that's ok since
|
|
|
|
// it naturally becomes false
|
|
|
|
const bool groupIsVerified = group->groupInfo.value(IS_VERIFIED).toBool();
|
|
|
|
if (verified != groupIsVerified) {
|
|
|
|
verified = groupIsVerified;
|
|
|
|
changedRoles.append(RoleIsVerified);
|
|
|
|
}
|
2020-10-04 04:27:49 +03:00
|
|
|
}
|
|
|
|
return changedRoles;
|
|
|
|
}
|
|
|
|
|
2020-11-26 00:09:47 +03:00
|
|
|
QVector<int> ChatListModel::ChatData::updateSecretChat(const QVariantMap &secretChatDetails)
|
|
|
|
{
|
|
|
|
QVector<int> changedRoles;
|
|
|
|
|
|
|
|
TDLibWrapper::SecretChatState newSecretChatState = TDLibWrapper::secretChatStateFromString(secretChatDetails.value("state").toMap().value(_TYPE).toString());
|
|
|
|
if (newSecretChatState != secretChatState) {
|
|
|
|
secretChatState = newSecretChatState;
|
|
|
|
changedRoles.append(RoleSecretChatState);
|
|
|
|
}
|
|
|
|
return changedRoles;
|
|
|
|
}
|
|
|
|
|
2021-01-10 15:35:34 +03:00
|
|
|
ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper, AppSettings *appSettings) : showHiddenChats(false)
|
2020-08-19 10:55:13 +03:00
|
|
|
{
|
2020-09-28 21:47:03 +03:00
|
|
|
this->tdLibWrapper = tdLibWrapper;
|
2021-01-10 15:35:34 +03:00
|
|
|
this->appSettings = appSettings;
|
2020-09-28 21:47:03 +03:00
|
|
|
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)));
|
2020-11-15 07:11:10 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(chatPhotoUpdated(qlonglong, QVariantMap)), this, SLOT(handleChatPhotoUpdated(qlonglong, QVariantMap)));
|
2020-11-17 14:18:46 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)), this, SLOT(handleChatPinnedMessageUpdated(qlonglong, qlonglong)));
|
2020-12-06 07:38:03 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(messageSendSucceeded(qlonglong, qlonglong, QVariantMap)), this, SLOT(handleMessageSendSucceeded(qlonglong, qlonglong, QVariantMap)));
|
2020-09-28 21:47:03 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(chatNotificationSettingsUpdated(QString, QVariantMap)), this, SLOT(handleChatNotificationSettingsUpdated(QString, QVariantMap)));
|
2020-10-04 04:27:49 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(superGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong)));
|
|
|
|
connect(tdLibWrapper, SIGNAL(basicGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong)));
|
2020-11-27 21:42:39 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(secretChatUpdated(qlonglong, QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong, QVariantMap)));
|
|
|
|
connect(tdLibWrapper, SIGNAL(secretChatReceived(qlonglong, QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong, QVariantMap)));
|
2020-11-27 00:18:51 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(chatTitleUpdated(QString, QString)), this, SLOT(handleChatTitleUpdated(QString, QString)));
|
2020-12-31 02:19:36 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(chatIsMarkedAsUnreadUpdated(qlonglong, bool)), this, SLOT(handleChatIsMarkedAsUnreadUpdated(qlonglong, bool)));
|
2021-01-06 12:42:12 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(chatPinnedUpdated(qlonglong, bool)), this, SLOT(handleChatPinnedUpdated(qlonglong, bool)));
|
2020-12-31 02:59:05 +03:00
|
|
|
connect(tdLibWrapper, SIGNAL(chatDraftMessageUpdated(qlonglong, QVariantMap, QString)), this, SLOT(handleChatDraftMessageUpdated(qlonglong, QVariantMap, QString)));
|
2020-10-01 00:59:12 +03:00
|
|
|
|
|
|
|
// 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()));
|
2021-12-09 02:46:04 +03:00
|
|
|
connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));
|
|
|
|
connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged()));
|
|
|
|
connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
|
2020-08-19 10:55:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ChatListModel::~ChatListModel()
|
|
|
|
{
|
2020-09-27 17:18:14 +03:00
|
|
|
LOG("Destroying myself...");
|
|
|
|
qDeleteAll(chatList);
|
2020-10-04 04:27:49 +03:00
|
|
|
qDeleteAll(hiddenChats.values());
|
2020-08-19 10:55:13 +03:00
|
|
|
}
|
|
|
|
|
2021-01-11 21:05:55 +03:00
|
|
|
void ChatListModel::reset()
|
|
|
|
{
|
|
|
|
chatList.clear();
|
|
|
|
hiddenChats.clear();
|
|
|
|
}
|
|
|
|
|
2020-10-01 00:59:12 +03:00
|
|
|
QHash<int,QByteArray> ChatListModel::roleNames() const
|
|
|
|
{
|
|
|
|
QHash<int,QByteArray> roles;
|
2020-12-17 01:32:42 +03:00
|
|
|
roles.insert(ChatListModel::RoleDisplay, "display");
|
|
|
|
roles.insert(ChatListModel::RoleChatId, "chat_id");
|
|
|
|
roles.insert(ChatListModel::RoleChatType, "chat_type");
|
|
|
|
roles.insert(ChatListModel::RoleTitle, "title");
|
|
|
|
roles.insert(ChatListModel::RolePhotoSmall, "photo_small");
|
|
|
|
roles.insert(ChatListModel::RoleUnreadCount, "unread_count");
|
|
|
|
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::RoleIsChannel, "is_channel");
|
2020-12-31 02:19:36 +03:00
|
|
|
roles.insert(ChatListModel::RoleIsMarkedAsUnread, "is_marked_as_unread");
|
2021-01-06 12:42:12 +03:00
|
|
|
roles.insert(ChatListModel::RoleIsPinned, "is_pinned");
|
2020-12-17 01:32:42 +03:00
|
|
|
roles.insert(ChatListModel::RoleFilter, "filter");
|
2020-12-31 02:59:05 +03:00
|
|
|
roles.insert(ChatListModel::RoleDraftMessageDate, "draft_message_date");
|
|
|
|
roles.insert(ChatListModel::RoleDraftMessageText, "draft_message_text");
|
2020-10-01 00:59:12 +03:00
|
|
|
return roles;
|
|
|
|
}
|
|
|
|
|
2020-08-19 10:55:13 +03:00
|
|
|
int ChatListModel::rowCount(const QModelIndex &) const
|
|
|
|
{
|
|
|
|
return chatList.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant ChatListModel::data(const QModelIndex &index, int role) const
|
|
|
|
{
|
2020-09-27 17:18:14 +03:00
|
|
|
const int row = index.row();
|
2020-10-01 00:59:12 +03:00
|
|
|
if (row >= 0 && row < chatList.size()) {
|
|
|
|
const ChatData *data = chatList.at(row);
|
2020-12-17 01:32:42 +03:00
|
|
|
switch ((ChatListModel::Role)role) {
|
|
|
|
case ChatListModel::RoleDisplay: return data->chatData;
|
|
|
|
case ChatListModel::RoleChatId: return data->chatId;
|
|
|
|
case ChatListModel::RoleChatType: return data->chatType;
|
|
|
|
case ChatListModel::RoleTitle: return data->title();
|
|
|
|
case ChatListModel::RolePhotoSmall: return data->photoSmall();
|
|
|
|
case ChatListModel::RoleUnreadCount: return data->unreadCount();
|
|
|
|
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::RoleIsChannel: return data->isChannel();
|
2020-12-31 02:19:36 +03:00
|
|
|
case ChatListModel::RoleIsMarkedAsUnread: return data->isMarkedAsUnread();
|
2021-01-06 12:42:12 +03:00
|
|
|
case ChatListModel::RoleIsPinned: return data->isPinned();
|
2021-12-09 02:46:04 +03:00
|
|
|
case ChatListModel::RoleFilter: return data->title() + " " + data->senderMessageText();
|
2020-12-31 02:59:05 +03:00
|
|
|
case ChatListModel::RoleDraftMessageText: return data->draftMessageText();
|
|
|
|
case ChatListModel::RoleDraftMessageDate: return data->draftMessageDate();
|
2020-10-01 00:59:12 +03:00
|
|
|
}
|
2020-08-19 10:55:13 +03:00
|
|
|
}
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
2020-09-20 01:13:42 +03:00
|
|
|
void ChatListModel::redrawModel()
|
|
|
|
{
|
2020-09-27 17:18:14 +03:00
|
|
|
LOG("Enforcing UI redraw...");
|
2020-09-20 01:13:42 +03:00
|
|
|
layoutChanged();
|
|
|
|
}
|
|
|
|
|
2020-10-19 13:20:02 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-11-20 21:08:05 +03:00
|
|
|
QVariantMap ChatListModel::getById(qlonglong chatId)
|
|
|
|
{
|
|
|
|
if (chatIndexMap.contains(chatId)) {
|
|
|
|
return chatList.value(chatIndexMap.value(chatId))->chatData;
|
|
|
|
}
|
|
|
|
return QVariantMap();
|
|
|
|
}
|
|
|
|
|
2020-09-27 17:18:14 +03:00
|
|
|
int ChatListModel::updateChatOrder(int chatIndex)
|
2020-08-20 11:50:47 +03:00
|
|
|
{
|
2020-10-01 00:59:12 +03:00
|
|
|
ChatData *chat = chatList.at(chatIndex);
|
2020-09-27 17:18:14 +03:00
|
|
|
|
|
|
|
const int n = chatList.size();
|
|
|
|
int newIndex = chatIndex;
|
|
|
|
while (newIndex > 0 && chat->compareTo(chatList.at(newIndex-1)) < 0) {
|
|
|
|
newIndex--;
|
2020-08-20 11:50:47 +03:00
|
|
|
}
|
2020-09-27 17:18:14 +03:00
|
|
|
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();
|
2020-08-20 11:50:47 +03:00
|
|
|
} else {
|
2020-09-27 17:18:14 +03:00
|
|
|
LOG("Chat" << chat->chatId << "stays at position" << chatIndex);
|
2020-08-20 11:50:47 +03:00
|
|
|
}
|
2020-09-27 17:18:14 +03:00
|
|
|
|
|
|
|
return newIndex;
|
2020-08-20 11:50:47 +03:00
|
|
|
}
|
|
|
|
|
2021-01-10 15:35:34 +03:00
|
|
|
void ChatListModel::calculateUnreadState()
|
|
|
|
{
|
|
|
|
if (this->appSettings->onlineOnlyMode()) {
|
|
|
|
LOG("Online-only mode: Calculating unread state on my own...");
|
|
|
|
int unreadMessages = 0;
|
|
|
|
int unreadChats = 0;
|
|
|
|
QListIterator<ChatData*> chatIterator(this->chatList);
|
|
|
|
while (chatIterator.hasNext()) {
|
|
|
|
ChatData *currentChat = chatIterator.next();
|
|
|
|
int unreadCount = currentChat->unreadCount();
|
|
|
|
if (unreadCount > 0) {
|
|
|
|
unreadChats++;
|
|
|
|
unreadMessages += unreadCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LOG("Online-only mode: New unread state:" << unreadMessages << unreadChats);
|
|
|
|
emit unreadStateChanged(unreadMessages, unreadChats);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
void ChatListModel::addVisibleChat(ChatData *chat)
|
2020-08-19 10:55:13 +03:00
|
|
|
{
|
2020-09-27 17:18:14 +03:00
|
|
|
const int n = chatList.size();
|
2020-10-04 04:27:49 +03:00
|
|
|
int pos;
|
|
|
|
for (pos = 0; pos < n && chat->compareTo(chatList.at(pos)) >= 0; pos++);
|
|
|
|
LOG("Adding chat" << chat->chatId << "at" << pos);
|
|
|
|
beginInsertRows(QModelIndex(), pos, pos);
|
|
|
|
chatList.insert(pos, chat);
|
|
|
|
chatIndexMap.insert(chat->chatId, pos);
|
2020-09-27 17:18:14 +03:00
|
|
|
// Update damaged part of the map
|
2020-10-04 04:27:49 +03:00
|
|
|
for (int i = pos + 1; i <= n; i++) {
|
2020-09-27 17:18:14 +03:00
|
|
|
chatIndexMap.insert(chatList.at(i)->chatId, i);
|
|
|
|
}
|
|
|
|
endInsertRows();
|
2020-11-10 01:22:24 +03:00
|
|
|
if (this->tdLibWrapper->getJoinChatRequested()) {
|
|
|
|
this->tdLibWrapper->registerJoinChat();
|
|
|
|
emit chatJoined(chat->chatId, chat->chatData.value("title").toString());
|
|
|
|
}
|
2020-10-04 04:27:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void ChatListModel::updateChatVisibility(const TDLibWrapper::Group *group)
|
|
|
|
{
|
2020-12-16 16:51:06 +03:00
|
|
|
LOG("Updating chat visibility" << (group ? qPrintable(QString::number(group->groupId)) : ""));
|
2020-10-04 04:27:49 +03:00
|
|
|
// 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) {
|
|
|
|
LOG("Hiding chat" << chat->chatId << "at" << i);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2020-10-01 00:59:12 +03:00
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
// 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);
|
|
|
|
}
|
2020-10-01 00:59:12 +03:00
|
|
|
}
|
2020-08-19 10:55:13 +03:00
|
|
|
}
|
2020-08-20 01:24:24 +03:00
|
|
|
|
2020-11-26 00:09:47 +03:00
|
|
|
void ChatListModel::updateSecretChatVisibility(const QVariantMap secretChatDetails)
|
|
|
|
{
|
2020-11-26 02:25:15 +03:00
|
|
|
LOG("Updating secret chat visibility" << secretChatDetails.value(ID).toString());
|
|
|
|
// See if any secret chat has been closed
|
2020-11-26 00:09:47 +03:00
|
|
|
for (int i = 0; i < chatList.size(); i++) {
|
|
|
|
ChatData *chat = chatList.at(i);
|
|
|
|
if (chat->chatType != TDLibWrapper::ChatTypeSecret) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-11-27 21:42:39 +03:00
|
|
|
if (chat->chatData.value(TYPE).toMap().value(SECRET_CHAT_ID).toLongLong() != secretChatDetails.value(ID).toLongLong()) {
|
2020-11-26 02:25:15 +03:00
|
|
|
continue;
|
|
|
|
}
|
2020-11-26 00:09:47 +03:00
|
|
|
const QVector<int> changedRoles(chat->updateSecretChat(secretChatDetails));
|
|
|
|
if (chat->isHidden() && !showHiddenChats) {
|
|
|
|
LOG("Hiding chat" << chat->chatId << "at" << i);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
bool ChatListModel::showAllChats() const
|
|
|
|
{
|
|
|
|
return showHiddenChats;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ChatListModel::setShowAllChats(bool showAll)
|
2020-08-20 01:24:24 +03:00
|
|
|
{
|
2020-10-04 04:27:49 +03:00
|
|
|
if (showHiddenChats != showAll) {
|
|
|
|
showHiddenChats = showAll;
|
|
|
|
updateChatVisibility(Q_NULLPTR);
|
|
|
|
emit showAllChatsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ChatListModel::handleChatDiscovered(const QString &, const QVariantMap &chatToBeAdded)
|
|
|
|
{
|
2020-12-29 18:32:39 +03:00
|
|
|
ChatData *chat = new ChatData(tdLibWrapper, chatToBeAdded);
|
2020-11-26 00:09:47 +03:00
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
const TDLibWrapper::Group *group = tdLibWrapper->getGroup(chat->groupId);
|
|
|
|
if (group) {
|
|
|
|
chat->updateGroup(group);
|
|
|
|
}
|
2020-11-26 00:09:47 +03:00
|
|
|
|
|
|
|
if (chat->chatType == TDLibWrapper::ChatTypeSecret) {
|
2020-11-27 21:42:39 +03:00
|
|
|
QVariantMap secretChatDetails = tdLibWrapper->getSecretChatFromCache(chatToBeAdded.value(TYPE).toMap().value(SECRET_CHAT_ID).toLongLong());
|
2020-11-26 00:09:47 +03:00
|
|
|
if (!secretChatDetails.isEmpty()) {
|
|
|
|
chat->updateSecretChat(secretChatDetails);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-26 22:53:10 +03:00
|
|
|
if (chat->isHidden() && !showHiddenChats) {
|
2020-10-04 04:27:49 +03:00
|
|
|
LOG("Hidden chat" << chat->chatId);
|
|
|
|
hiddenChats.insert(chat->chatId, chat);
|
|
|
|
} else {
|
|
|
|
addVisibleChat(chat);
|
|
|
|
|
|
|
|
// Start timestamp refresh timer when the first visible chat is discovered
|
|
|
|
if (!relativeTimeRefreshTimer->isActive()) {
|
|
|
|
relativeTimeRefreshTimer->start();
|
2020-09-27 17:18:14 +03:00
|
|
|
}
|
|
|
|
}
|
2020-08-20 01:24:24 +03:00
|
|
|
}
|
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
void ChatListModel::handleChatLastMessageUpdated(const QString &id, const QString &order, const QVariantMap &lastMessage)
|
2020-08-20 01:24:24 +03:00
|
|
|
{
|
2020-10-04 04:27:49 +03:00
|
|
|
bool ok;
|
|
|
|
const qlonglong chatId = id.toLongLong(&ok);
|
|
|
|
if (ok) {
|
|
|
|
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);
|
|
|
|
if (chat->setOrder(order)) {
|
|
|
|
chatIndex = updateChatOrder(chatIndex);
|
|
|
|
}
|
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, chat->updateLastMessage(lastMessage));
|
2020-10-04 17:06:20 +03:00
|
|
|
emit chatChanged(chatId);
|
2020-10-04 04:27:49 +03:00
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating last message for hidden chat" << chatId << "new order" << order);
|
|
|
|
chat->setOrder(order);
|
|
|
|
chat->chatData.insert(LAST_MESSAGE, lastMessage);
|
2021-05-26 22:53:10 +03:00
|
|
|
// 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);
|
|
|
|
}
|
2020-10-04 04:27:49 +03:00
|
|
|
}
|
2020-09-27 17:18:14 +03:00
|
|
|
}
|
|
|
|
}
|
2020-08-20 01:24:24 +03:00
|
|
|
}
|
2020-08-20 18:06:47 +03:00
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
void ChatListModel::handleChatOrderUpdated(const QString &id, const QString &order)
|
2020-08-21 00:56:21 +03:00
|
|
|
{
|
2020-10-04 04:27:49 +03:00
|
|
|
bool ok;
|
|
|
|
const qlonglong chatId = id.toLongLong(&ok);
|
|
|
|
if (ok) {
|
|
|
|
if (chatIndexMap.contains(chatId)) {
|
|
|
|
LOG("Updating chat order of" << chatId << "to" << order);
|
|
|
|
int chatIndex = chatIndexMap.value(chatId);
|
|
|
|
if (chatList.at(chatIndex)->setOrder(order)) {
|
|
|
|
updateChatOrder(chatIndex);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating order of hidden chat" << chatId << "to" << order);
|
|
|
|
chat->setOrder(order);
|
|
|
|
}
|
2020-10-01 00:59:12 +03:00
|
|
|
}
|
2020-10-04 04:27:49 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ChatListModel::handleChatReadInboxUpdated(const QString &id, const QString &lastReadInboxMessageId, int unreadCount)
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
const qlonglong chatId = id.toLongLong(&ok);
|
|
|
|
if (ok) {
|
|
|
|
const qlonglong messageId = lastReadInboxMessageId.toLongLong();
|
|
|
|
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);
|
|
|
|
QVector<int> changedRoles;
|
2020-12-17 01:32:42 +03:00
|
|
|
changedRoles.append(ChatListModel::RoleDisplay);
|
2020-10-04 04:27:49 +03:00
|
|
|
if (chat->updateUnreadCount(unreadCount)) {
|
2020-12-17 01:32:42 +03:00
|
|
|
changedRoles.append(ChatListModel::RoleUnreadCount);
|
2020-10-04 04:27:49 +03:00
|
|
|
}
|
|
|
|
if (chat->updateLastReadInboxMessageId(messageId)) {
|
2020-12-17 01:32:42 +03:00
|
|
|
changedRoles.append(ChatListModel::RoleLastReadInboxMessageId);
|
2020-10-04 04:27:49 +03:00
|
|
|
}
|
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, changedRoles);
|
2021-01-10 15:35:34 +03:00
|
|
|
this->calculateUnreadState();
|
2020-10-04 04:27:49 +03:00
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating unread count for hidden chat" << chatId << "unread messages" << unreadCount << ", last read message ID: " << lastReadInboxMessageId);
|
|
|
|
chat->updateUnreadCount(unreadCount);
|
|
|
|
chat->updateLastReadInboxMessageId(messageId);
|
|
|
|
}
|
2020-10-01 00:59:12 +03:00
|
|
|
}
|
2020-09-27 17:18:14 +03:00
|
|
|
}
|
2020-08-21 00:56:21 +03:00
|
|
|
}
|
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
void ChatListModel::handleChatReadOutboxUpdated(const QString &id, const QString &lastReadOutboxMessageId)
|
2020-08-31 22:51:52 +03:00
|
|
|
{
|
2020-10-04 04:27:49 +03:00
|
|
|
bool ok;
|
|
|
|
const qlonglong chatId = id.toLongLong(&ok);
|
|
|
|
if (ok) {
|
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
chat->chatData.insert(LAST_READ_OUTBOX_MESSAGE_ID, lastReadOutboxMessageId);
|
|
|
|
}
|
|
|
|
}
|
2020-09-27 17:18:14 +03:00
|
|
|
}
|
2020-08-31 22:51:52 +03:00
|
|
|
}
|
|
|
|
|
2020-11-15 07:11:10 +03:00
|
|
|
void ChatListModel::handleChatPhotoUpdated(qlonglong chatId, const QVariantMap &photo)
|
|
|
|
{
|
|
|
|
if (chatIndexMap.contains(chatId)) {
|
|
|
|
LOG("Updating chat photo for" << chatId);
|
|
|
|
const int chatIndex = chatIndexMap.value(chatId);
|
|
|
|
ChatData *chat = chatList.at(chatIndex);
|
|
|
|
chat->chatData.insert(PHOTO, photo);
|
|
|
|
QVector<int> changedRoles;
|
2020-12-17 01:32:42 +03:00
|
|
|
changedRoles.append(ChatListModel::RolePhotoSmall);
|
2020-11-15 07:11:10 +03:00
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, changedRoles);
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating photo for hidden chat" << chatId);
|
|
|
|
chat->chatData.insert(PHOTO, photo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 14:18:46 +03:00
|
|
|
void ChatListModel::handleChatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId)
|
|
|
|
{
|
|
|
|
if (chatIndexMap.contains(chatId)) {
|
|
|
|
LOG("Updating pinned message for" << 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) {
|
|
|
|
LOG("Updating pinned message for hidden chat" << chatId);
|
|
|
|
chat->chatData.insert(PINNED_MESSAGE_ID, pinnedMessageId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-06 07:38:03 +03:00
|
|
|
void ChatListModel::handleMessageSendSucceeded(qlonglong messageId, qlonglong oldMessageId, const QVariantMap &message)
|
2020-08-31 22:51:52 +03:00
|
|
|
{
|
2020-10-04 04:27:49 +03:00
|
|
|
bool ok;
|
|
|
|
const qlonglong chatId(message.value(CHAT_ID).toLongLong(&ok));
|
|
|
|
if (ok) {
|
|
|
|
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);
|
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, chatList.at(chatIndex)->updateLastMessage(message));
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating last message for hidden chat" << chatId << ", as message was sent, old ID:" << oldMessageId << ", new ID:" << messageId);
|
|
|
|
chat->chatData.insert(LAST_MESSAGE, message);
|
|
|
|
}
|
|
|
|
}
|
2020-09-27 17:18:14 +03:00
|
|
|
}
|
2020-08-31 22:51:52 +03:00
|
|
|
}
|
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
void ChatListModel::handleChatNotificationSettingsUpdated(const QString &id, const QVariantMap &chatNotificationSettings)
|
2020-09-16 21:43:36 +03:00
|
|
|
{
|
2020-10-04 04:27:49 +03:00
|
|
|
bool ok;
|
|
|
|
const qlonglong chatId = id.toLongLong(&ok);
|
|
|
|
if (ok) {
|
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
chat->chatData.insert(NOTIFICATION_SETTINGS, chatNotificationSettings);
|
|
|
|
}
|
|
|
|
}
|
2020-08-20 18:06:47 +03:00
|
|
|
}
|
|
|
|
}
|
2020-10-01 00:59:12 +03:00
|
|
|
|
2020-10-04 04:27:49 +03:00
|
|
|
void ChatListModel::handleGroupUpdated(qlonglong groupId)
|
|
|
|
{
|
|
|
|
updateChatVisibility(tdLibWrapper->getGroup(groupId));
|
|
|
|
}
|
|
|
|
|
2020-11-27 21:42:39 +03:00
|
|
|
void ChatListModel::handleSecretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat)
|
2020-11-26 00:09:47 +03:00
|
|
|
{
|
|
|
|
LOG("Updating visibility of secret chat " << secretChatId);
|
|
|
|
updateSecretChatVisibility(secretChat);
|
|
|
|
}
|
|
|
|
|
2020-11-27 00:18:51 +03:00
|
|
|
void ChatListModel::handleChatTitleUpdated(const QString &chatId, const QString &title)
|
|
|
|
{
|
|
|
|
qlonglong chatIdLongLong = chatId.toLongLong();
|
|
|
|
if (chatIndexMap.contains(chatIdLongLong)) {
|
|
|
|
LOG("Updating title for" << chatId);
|
|
|
|
const int chatIndex = chatIndexMap.value(chatIdLongLong);
|
|
|
|
ChatData *chat = chatList.at(chatIndex);
|
|
|
|
chat->chatData.insert(TITLE, title);
|
|
|
|
QVector<int> changedRoles;
|
2020-12-17 01:32:42 +03:00
|
|
|
changedRoles.append(ChatListModel::RoleTitle);
|
2021-12-09 02:46:04 +03:00
|
|
|
changedRoles.append(ChatListModel::RoleFilter);
|
2020-11-27 00:18:51 +03:00
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, changedRoles);
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId.toLongLong());
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating title for hidden chat" << chatId);
|
|
|
|
chat->chatData.insert(TITLE, title);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-06 12:42:12 +03:00
|
|
|
void ChatListModel::handleChatPinnedUpdated(qlonglong chatId, bool chatIsPinned)
|
|
|
|
{
|
|
|
|
if (chatIndexMap.contains(chatId)) {
|
|
|
|
LOG("Updating chat is pinned for" << chatId << chatIsPinned);
|
|
|
|
const int chatIndex = chatIndexMap.value(chatId);
|
|
|
|
ChatData *chat = chatList.at(chatIndex);
|
|
|
|
chat->chatData.insert(IS_PINNED, chatIsPinned);
|
|
|
|
QVector<int> changedRoles;
|
|
|
|
changedRoles.append(ChatListModel::RoleIsPinned);
|
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, changedRoles);
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating chat is pinned for hidden chat" << chatId);
|
|
|
|
chat->chatData.insert(IS_PINNED, chatIsPinned);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-31 02:19:36 +03:00
|
|
|
void ChatListModel::handleChatIsMarkedAsUnreadUpdated(qlonglong chatId, bool chatIsMarkedAsUnread)
|
|
|
|
{
|
|
|
|
if (chatIndexMap.contains(chatId)) {
|
|
|
|
LOG("Updating chat is marked as unread for" << chatId << chatIsMarkedAsUnread);
|
|
|
|
const int chatIndex = chatIndexMap.value(chatId);
|
|
|
|
ChatData *chat = chatList.at(chatIndex);
|
|
|
|
chat->chatData.insert(IS_MARKED_AS_UNREAD, chatIsMarkedAsUnread);
|
|
|
|
QVector<int> changedRoles;
|
|
|
|
changedRoles.append(ChatListModel::RoleIsMarkedAsUnread);
|
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, changedRoles);
|
|
|
|
} else {
|
|
|
|
ChatData *chat = hiddenChats.value(chatId);
|
|
|
|
if (chat) {
|
|
|
|
LOG("Updating chat is marked as unread for hidden chat" << chatId);
|
|
|
|
chat->chatData.insert(IS_MARKED_AS_UNREAD, chatIsMarkedAsUnread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-31 02:59:05 +03:00
|
|
|
void ChatListModel::handleChatDraftMessageUpdated(qlonglong chatId, const QVariantMap &draftMessage, const QString &order)
|
|
|
|
{
|
|
|
|
LOG("Updating draft message for" << chatId);
|
|
|
|
if (chatIndexMap.contains(chatId)) {
|
|
|
|
const int chatIndex = chatIndexMap.value(chatId);
|
|
|
|
ChatData *chat = chatList.at(chatIndex);
|
|
|
|
chat->chatData.insert(DRAFT_MESSAGE, draftMessage);
|
|
|
|
|
|
|
|
QVector<int> changedRoles;
|
|
|
|
changedRoles.append(ChatListModel::RoleDraftMessageDate);
|
|
|
|
changedRoles.append(ChatListModel::RoleDraftMessageText);
|
|
|
|
const QModelIndex modelIndex(index(chatIndex));
|
|
|
|
emit dataChanged(modelIndex, modelIndex, changedRoles);
|
|
|
|
if (chat->setOrder(order)) {
|
|
|
|
updateChatOrder(chatIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-01 00:59:12 +03:00
|
|
|
void ChatListModel::handleRelativeTimeRefreshTimer()
|
|
|
|
{
|
|
|
|
LOG("Refreshing timestamps");
|
|
|
|
QVector<int> roles;
|
2020-12-17 01:32:42 +03:00
|
|
|
roles.append(ChatListModel::RoleLastMessageDate);
|
2020-10-01 00:59:12 +03:00
|
|
|
emit dataChanged(index(0), index(chatList.size() - 1), roles);
|
|
|
|
}
|