Update message view counts in real time

This commit is contained in:
Slava Monich 2021-01-31 22:08:39 +02:00
parent 444649c3b2
commit b1c4311990
8 changed files with 140 additions and 22 deletions

View file

@ -29,6 +29,7 @@ ListItem {
property var chatId
property var messageId
property int messageIndex
property int messageViewCount
property var myMessage
property bool canReplyToMessage
readonly property bool isAnonymous: myMessage.sender["@type"] === "messageSenderChat"
@ -490,10 +491,10 @@ ListItem {
height: parent.height
anchors.right: parent.right
asynchronous: true
active: chatPage.isChannel && myMessage.interaction_info && myMessage.interaction_info.view_count
active: chatPage.isChannel && messageViewCount
sourceComponent: Component {
Label {
text: Functions.getShortenedCount(myMessage.interaction_info.view_count)
text: Functions.getShortenedCount(messageViewCount)
leftPadding: Theme.iconSizeSmall
font.pixelSize: Theme.fontSizeTiny
color: Theme.secondaryColor

View file

@ -1131,6 +1131,7 @@ Page {
chatId: chatModel.chatId
myMessage: model.display
messageId: model.message_id
messageViewCount: model.view_count
messageIndex: model.index
hasContentComponent: !!myMessage.content && chatView.delegateMessagesContent.indexOf(model.content_type) > -1
canReplyToMessage: chatPage.canSendMessages

View file

@ -40,6 +40,15 @@ namespace {
const QString PINNED_MESSAGE_ID("pinned_message_id");
const QString REPLY_MARKUP("reply_markup");
const QString _TYPE("@type");
// "interaction_info": {
// "@type": "messageInteractionInfo",
// "forward_count": 0,
// "view_count": 47
// }
const QString TYPE_MESSAGE_INTERACTION_INFO("messageInteractionInfo");
const QString INTERACTION_INFO("interaction_info");
const QString VIEW_COUNT("view_count");
}
class ChatModel::MessageData
@ -48,16 +57,35 @@ public:
enum Role {
RoleDisplay = Qt::DisplayRole,
RoleMessageId,
RoleMessageContentType
RoleMessageContentType,
RoleMessageViewCount
};
enum RoleFlag {
RoleFlagDisplay = 0x01,
RoleFlagMessageId = 0x02,
RoleFlagMessageContentType = 0x04,
RoleFlagMessageViewCount = 0x08
};
MessageData(const QVariantMap &data, qlonglong msgid);
static bool lessThan(const MessageData *message1, const MessageData *message2);
static QVector<int> flagsToRoles(uint flags);
uint updateMessageData(const QVariantMap &data);
uint updateContent(const QVariantMap &content);
uint updateContentType(const QVariantMap &content);
uint updateReplyMarkup(const QVariantMap &replyMarkup);
uint updateViewCount(const QVariantMap &interactionInfo);
uint updateInteractionInfo(const QVariantMap &interactionInfo);
QVector<int> diff(const MessageData *message) const;
QVector<int> setMessageData(const QVariantMap &data);
QVector<int> setContent(const QVariantMap &content);
QVector<int> setReplyMarkup(const QVariantMap &replyMarkup);
QVector<int> setInteractionInfo(const QVariantMap &interactionInfo);
int senderUserId() const;
qlonglong senderChatId() const;
bool senderIsChat() const;
@ -66,15 +94,35 @@ public:
QVariantMap messageData;
const qlonglong messageId;
QString messageContentType;
int viewCount;
};
ChatModel::MessageData::MessageData(const QVariantMap &data, qlonglong msgid) :
messageData(data),
messageId(msgid),
messageContentType(data.value(CONTENT).toMap().value(_TYPE).toString())
messageContentType(data.value(CONTENT).toMap().value(_TYPE).toString()),
viewCount(data.value(INTERACTION_INFO).toMap().value(VIEW_COUNT).toInt())
{
}
QVector<int> ChatModel::MessageData::flagsToRoles(uint flags)
{
QVector<int> roles;
if (flags & RoleFlagDisplay) {
roles.append(RoleDisplay);
}
if (flags & RoleFlagMessageId) {
roles.append(RoleMessageId);
}
if (flags & RoleFlagMessageContentType) {
roles.append(RoleMessageContentType);
}
if (flags & RoleFlagMessageViewCount) {
roles.append(RoleMessageViewCount);
}
return roles;
}
int ChatModel::MessageData::senderUserId() const
{
return messageData.value(SENDER).toMap().value(USER_ID).toInt();
@ -101,37 +149,74 @@ QVector<int> ChatModel::MessageData::diff(const MessageData *message) const
if (message->messageContentType != messageContentType) {
roles.append(RoleMessageContentType);
}
if (message->viewCount != viewCount) {
roles.append(RoleMessageViewCount);
}
}
return roles;
}
QVector<int> ChatModel::MessageData::setMessageData(const QVariantMap &data)
uint ChatModel::MessageData::updateMessageData(const QVariantMap &data)
{
messageData = data;
QVector<int> changedRoles;
changedRoles.append(RoleDisplay);
return changedRoles;
return RoleFlagDisplay |
updateContentType(data.value(CONTENT).toMap()) |
updateViewCount(data.value(INTERACTION_INFO).toMap());
}
QVector<int> ChatModel::MessageData::setMessageData(const QVariantMap &data)
{
return flagsToRoles(updateMessageData(data));
}
uint ChatModel::MessageData::updateContentType(const QVariantMap &content)
{
const QString oldContentType(messageContentType);
messageContentType = content.value(_TYPE).toString();
return (oldContentType == messageContentType) ? 0 : RoleFlagMessageContentType;
}
uint ChatModel::MessageData::updateContent(const QVariantMap &content)
{
messageData.insert(CONTENT, content);
return RoleFlagDisplay | updateContentType(content);
}
QVector<int> ChatModel::MessageData::setContent(const QVariantMap &content)
{
const QString oldContentType(messageContentType);
messageData.insert(CONTENT, content);
messageContentType = content.value(_TYPE).toString();
QVector<int> changedRoles;
if (oldContentType != messageContentType) {
changedRoles.append(RoleMessageContentType);
return flagsToRoles(updateContent(content));
}
changedRoles.append(RoleDisplay);
return changedRoles;
uint ChatModel::MessageData::updateReplyMarkup(const QVariantMap &replyMarkup)
{
messageData.insert(REPLY_MARKUP, replyMarkup);
return RoleFlagDisplay;
}
QVector<int> ChatModel::MessageData::setReplyMarkup(const QVariantMap &replyMarkup)
{
messageData.insert(REPLY_MARKUP, replyMarkup);
QVector<int> changedRoles;
changedRoles.append(RoleDisplay);
return changedRoles;
return flagsToRoles(updateReplyMarkup(replyMarkup));
}
uint ChatModel::MessageData::updateViewCount(const QVariantMap &interactionInfo)
{
const int oldViewCount = viewCount;
viewCount = interactionInfo.value(VIEW_COUNT).toInt();
return (viewCount == oldViewCount) ? 0 : RoleFlagMessageViewCount;
}
uint ChatModel::MessageData::updateInteractionInfo(const QVariantMap &interactionInfo)
{
if (interactionInfo.value(_TYPE) == TYPE_MESSAGE_INTERACTION_INFO) {
messageData.insert(INTERACTION_INFO, interactionInfo);
return RoleFlagDisplay | updateViewCount(interactionInfo);
}
return 0;
}
QVector<int> ChatModel::MessageData::setInteractionInfo(const QVariantMap &info)
{
return flagsToRoles(updateInteractionInfo(info));
}
bool ChatModel::MessageData::lessThan(const MessageData *message1, const MessageData *message2)
@ -157,6 +242,7 @@ ChatModel::ChatModel(TDLibWrapper *tdLibWrapper) :
connect(this->tdLibWrapper, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)), this, SLOT(handleChatPinnedMessageUpdated(qlonglong, qlonglong)));
connect(this->tdLibWrapper, SIGNAL(messageContentUpdated(qlonglong, qlonglong, QVariantMap)), this, SLOT(handleMessageContentUpdated(qlonglong, qlonglong, QVariantMap)));
connect(this->tdLibWrapper, SIGNAL(messageEditedUpdated(qlonglong, qlonglong, QVariantMap)), this, SLOT(handleMessageEditedUpdated(qlonglong, qlonglong, QVariantMap)));
connect(this->tdLibWrapper, SIGNAL(messageInteractionInfoUpdated(qlonglong, qlonglong, QVariantMap)), this, SLOT(handleMessageInteractionInfoUpdated(qlonglong, qlonglong, QVariantMap)));
connect(this->tdLibWrapper, SIGNAL(messagesDeleted(qlonglong, QList<qlonglong>)), this, SLOT(handleMessagesDeleted(qlonglong, QList<qlonglong>)));
}
@ -172,6 +258,7 @@ QHash<int,QByteArray> ChatModel::roleNames() const
roles.insert(MessageData::RoleDisplay, "display");
roles.insert(MessageData::RoleMessageId, "message_id");
roles.insert(MessageData::RoleMessageContentType, "content_type");
roles.insert(MessageData::RoleMessageViewCount, "view_count");
return roles;
}
@ -189,6 +276,7 @@ QVariant ChatModel::data(const QModelIndex &index, int role) const
case MessageData::RoleDisplay: return message->messageData;
case MessageData::RoleMessageId: return message->messageId;
case MessageData::RoleMessageContentType: return message->messageContentType;
case MessageData::RoleMessageViewCount: return message->viewCount;
}
}
return QVariant();
@ -497,6 +585,19 @@ void ChatModel::handleMessageContentUpdated(qlonglong chatId, qlonglong messageI
}
}
void ChatModel::handleMessageInteractionInfoUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &updatedInfo)
{
if (chatId == this->chatId && messageIndexMap.contains(messageId)) {
const int pos = messageIndexMap.value(messageId, -1);
if (pos >= 0) {
LOG("Message interaction info was updated at index" << pos);
const QVector<int> changedRoles(messages.at(pos)->setInteractionInfo(updatedInfo));
const QModelIndex messageIndex(index(pos));
emit dataChanged(messageIndex, messageIndex, changedRoles);
}
}
}
void ChatModel::handleMessageEditedUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &replyMarkup)
{
LOG("Message edited updated" << chatId << messageId);

View file

@ -73,6 +73,7 @@ private slots:
void handleChatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId);
void handleMessageContentUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &newContent);
void handleMessageEditedUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &replyMarkup);
void handleMessageInteractionInfoUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &updatedInfo);
void handleMessagesDeleted(qlonglong chatId, const QList<qlonglong> &messageIds);
private:

View file

@ -48,6 +48,7 @@ namespace {
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 SECRET_CHAT("secret_chat");
const QString INTERACTION_INFO("interaction_info");
const QString TYPE("@type");
const QString EXTRA("@extra");
@ -141,6 +142,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren
handlers.insert("callbackQueryAnswer", &TDLibReceiver::processCallbackQueryAnswer);
handlers.insert("userPrivacySettingRules", &TDLibReceiver::processUserPrivacySettingRules);
handlers.insert("updateUserPrivacySettingRules", &TDLibReceiver::processUpdateUserPrivacySettingRules);
handlers.insert("updateMessageInteractionInfo", &TDLibReceiver::processUpdateMessageInteractionInfo);
}
void TDLibReceiver::setActive(bool active)
@ -628,3 +630,11 @@ void TDLibReceiver::processUpdateUserPrivacySettingRules(const QVariantMap &rece
LOG("User privacy setting rules updated");
emit userPrivacySettingRulesUpdated(receivedInformation);
}
void TDLibReceiver::processUpdateMessageInteractionInfo(const QVariantMap &receivedInformation)
{
const qlonglong chatId = receivedInformation.value(CHAT_ID).toLongLong();
const qlonglong messageId = receivedInformation.value(MESSAGE_ID).toLongLong();
LOG("Message interaction info updated" << chatId << messageId);
emit messageInteractionInfoUpdated(chatId, messageId, receivedInformation.value(INTERACTION_INFO).toMap());
}

View file

@ -97,6 +97,7 @@ signals:
void callbackQueryAnswer(const QString &text, bool alert, const QString &url);
void userPrivacySettingRules(const QVariantMap &rules);
void userPrivacySettingRulesUpdated(const QVariantMap &updatedRules);
void messageInteractionInfoUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &updatedInfo);
void okReceived(const QString &request);
private:
@ -107,6 +108,7 @@ private:
bool isActive;
void receiverLoop();
void nop(const QVariantMap &receivedInformation);
void processReceivedDocument(const QJsonDocument &receivedJsonDocument);
void processUpdateOption(const QVariantMap &receivedInformation);
void processUpdateAuthorizationState(const QVariantMap &receivedInformation);
@ -158,7 +160,6 @@ private:
void processUpdateMessageIsPinned(const QVariantMap &receivedInformation);
void processUsers(const QVariantMap &receivedInformation);
void processError(const QVariantMap &receivedInformation);
void nop(const QVariantMap &receivedInformation);
void processSecretChat(const QVariantMap &receivedInformation);
void processUpdateSecretChat(const QVariantMap &receivedInformation);
void processUpdateMessageEdited(const QVariantMap &receivedInformation);
@ -169,6 +170,7 @@ private:
void processCallbackQueryAnswer(const QVariantMap &receivedInformation);
void processUserPrivacySettingRules(const QVariantMap &receivedInformation);
void processUpdateUserPrivacySettingRules(const QVariantMap &receivedInformation);
void processUpdateMessageInteractionInfo(const QVariantMap &receivedInformation);
};
#endif // TDLIBRECEIVER_H

View file

@ -160,6 +160,7 @@ void TDLibWrapper::initializeTDLibReciever() {
connect(this->tdLibReceiver, SIGNAL(callbackQueryAnswer(QString, bool, QString)), this, SIGNAL(callbackQueryAnswer(QString, bool, QString)));
connect(this->tdLibReceiver, SIGNAL(userPrivacySettingRules(QVariantMap)), this, SLOT(handleUserPrivacySettingRules(QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(userPrivacySettingRulesUpdated(QVariantMap)), this, SLOT(handleUpdatedUserPrivacySettingRules(QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(messageInteractionInfoUpdated(qlonglong, qlonglong, QVariantMap)), this, SIGNAL(messageInteractionInfoUpdated(qlonglong, qlonglong, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(okReceived(QString)), this, SIGNAL(okReceived(QString)));
this->tdLibReceiver->start();

View file

@ -297,6 +297,7 @@ signals:
void inlineQueryResults(const QString &inlineQueryId, const QString &nextOffset, const QVariantList &results, const QString &switchPmText, const QString &switchPmParameter, const QString &extra);
void callbackQueryAnswer(const QString &text, bool alert, const QString &url);
void userPrivacySettingUpdated(UserPrivacySetting setting, UserPrivacySettingRule rule);
void messageInteractionInfoUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &updatedInfo);
void okReceived(const QString &request);
public slots: