Merge pull request #353 from monich/view_count

Update message view counts in real time
This commit is contained in:
Sebastian Wolf 2021-01-31 22:42:18 +01:00 committed by GitHub
commit 55ce5c36d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 22 deletions

View file

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

View file

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

View file

@ -40,6 +40,15 @@ namespace {
const QString PINNED_MESSAGE_ID("pinned_message_id"); const QString PINNED_MESSAGE_ID("pinned_message_id");
const QString REPLY_MARKUP("reply_markup"); const QString REPLY_MARKUP("reply_markup");
const QString _TYPE("@type"); 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 class ChatModel::MessageData
@ -48,16 +57,35 @@ public:
enum Role { enum Role {
RoleDisplay = Qt::DisplayRole, RoleDisplay = Qt::DisplayRole,
RoleMessageId, RoleMessageId,
RoleMessageContentType RoleMessageContentType,
RoleMessageViewCount
};
enum RoleFlag {
RoleFlagDisplay = 0x01,
RoleFlagMessageId = 0x02,
RoleFlagMessageContentType = 0x04,
RoleFlagMessageViewCount = 0x08
}; };
MessageData(const QVariantMap &data, qlonglong msgid); MessageData(const QVariantMap &data, qlonglong msgid);
static bool lessThan(const MessageData *message1, const MessageData *message2); 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> diff(const MessageData *message) const;
QVector<int> setMessageData(const QVariantMap &data); QVector<int> setMessageData(const QVariantMap &data);
QVector<int> setContent(const QVariantMap &content); QVector<int> setContent(const QVariantMap &content);
QVector<int> setReplyMarkup(const QVariantMap &replyMarkup); QVector<int> setReplyMarkup(const QVariantMap &replyMarkup);
QVector<int> setInteractionInfo(const QVariantMap &interactionInfo);
int senderUserId() const; int senderUserId() const;
qlonglong senderChatId() const; qlonglong senderChatId() const;
bool senderIsChat() const; bool senderIsChat() const;
@ -66,15 +94,35 @@ public:
QVariantMap messageData; QVariantMap messageData;
const qlonglong messageId; const qlonglong messageId;
QString messageContentType; QString messageContentType;
int viewCount;
}; };
ChatModel::MessageData::MessageData(const QVariantMap &data, qlonglong msgid) : ChatModel::MessageData::MessageData(const QVariantMap &data, qlonglong msgid) :
messageData(data), messageData(data),
messageId(msgid), 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 int ChatModel::MessageData::senderUserId() const
{ {
return messageData.value(SENDER).toMap().value(USER_ID).toInt(); 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) { if (message->messageContentType != messageContentType) {
roles.append(RoleMessageContentType); roles.append(RoleMessageContentType);
} }
if (message->viewCount != viewCount) {
roles.append(RoleMessageViewCount);
}
} }
return roles; return roles;
} }
QVector<int> ChatModel::MessageData::setMessageData(const QVariantMap &data) uint ChatModel::MessageData::updateMessageData(const QVariantMap &data)
{ {
messageData = data; messageData = data;
QVector<int> changedRoles; return RoleFlagDisplay |
changedRoles.append(RoleDisplay); updateContentType(data.value(CONTENT).toMap()) |
return changedRoles; 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) QVector<int> ChatModel::MessageData::setContent(const QVariantMap &content)
{ {
const QString oldContentType(messageContentType); return flagsToRoles(updateContent(content));
messageData.insert(CONTENT, content); }
messageContentType = content.value(_TYPE).toString();
QVector<int> changedRoles; uint ChatModel::MessageData::updateReplyMarkup(const QVariantMap &replyMarkup)
if (oldContentType != messageContentType) { {
changedRoles.append(RoleMessageContentType); messageData.insert(REPLY_MARKUP, replyMarkup);
} return RoleFlagDisplay;
changedRoles.append(RoleDisplay);
return changedRoles;
} }
QVector<int> ChatModel::MessageData::setReplyMarkup(const QVariantMap &replyMarkup) QVector<int> ChatModel::MessageData::setReplyMarkup(const QVariantMap &replyMarkup)
{ {
messageData.insert(REPLY_MARKUP, replyMarkup); return flagsToRoles(updateReplyMarkup(replyMarkup));
QVector<int> changedRoles; }
changedRoles.append(RoleDisplay);
return changedRoles; 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) 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(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(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(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>))); 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::RoleDisplay, "display");
roles.insert(MessageData::RoleMessageId, "message_id"); roles.insert(MessageData::RoleMessageId, "message_id");
roles.insert(MessageData::RoleMessageContentType, "content_type"); roles.insert(MessageData::RoleMessageContentType, "content_type");
roles.insert(MessageData::RoleMessageViewCount, "view_count");
return roles; return roles;
} }
@ -189,6 +276,7 @@ QVariant ChatModel::data(const QModelIndex &index, int role) const
case MessageData::RoleDisplay: return message->messageData; case MessageData::RoleDisplay: return message->messageData;
case MessageData::RoleMessageId: return message->messageId; case MessageData::RoleMessageId: return message->messageId;
case MessageData::RoleMessageContentType: return message->messageContentType; case MessageData::RoleMessageContentType: return message->messageContentType;
case MessageData::RoleMessageViewCount: return message->viewCount;
} }
} }
return QVariant(); 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) void ChatModel::handleMessageEditedUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &replyMarkup)
{ {
LOG("Message edited updated" << chatId << messageId); LOG("Message edited updated" << chatId << messageId);

View file

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

View file

@ -48,6 +48,7 @@ namespace {
const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id"); 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 LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id");
const QString SECRET_CHAT("secret_chat"); const QString SECRET_CHAT("secret_chat");
const QString INTERACTION_INFO("interaction_info");
const QString TYPE("@type"); const QString TYPE("@type");
const QString EXTRA("@extra"); const QString EXTRA("@extra");
@ -141,6 +142,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren
handlers.insert("callbackQueryAnswer", &TDLibReceiver::processCallbackQueryAnswer); handlers.insert("callbackQueryAnswer", &TDLibReceiver::processCallbackQueryAnswer);
handlers.insert("userPrivacySettingRules", &TDLibReceiver::processUserPrivacySettingRules); handlers.insert("userPrivacySettingRules", &TDLibReceiver::processUserPrivacySettingRules);
handlers.insert("updateUserPrivacySettingRules", &TDLibReceiver::processUpdateUserPrivacySettingRules); handlers.insert("updateUserPrivacySettingRules", &TDLibReceiver::processUpdateUserPrivacySettingRules);
handlers.insert("updateMessageInteractionInfo", &TDLibReceiver::processUpdateMessageInteractionInfo);
} }
void TDLibReceiver::setActive(bool active) void TDLibReceiver::setActive(bool active)
@ -628,3 +630,11 @@ void TDLibReceiver::processUpdateUserPrivacySettingRules(const QVariantMap &rece
LOG("User privacy setting rules updated"); LOG("User privacy setting rules updated");
emit userPrivacySettingRulesUpdated(receivedInformation); 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 callbackQueryAnswer(const QString &text, bool alert, const QString &url);
void userPrivacySettingRules(const QVariantMap &rules); void userPrivacySettingRules(const QVariantMap &rules);
void userPrivacySettingRulesUpdated(const QVariantMap &updatedRules); void userPrivacySettingRulesUpdated(const QVariantMap &updatedRules);
void messageInteractionInfoUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &updatedInfo);
void okReceived(const QString &request); void okReceived(const QString &request);
private: private:
@ -107,6 +108,7 @@ private:
bool isActive; bool isActive;
void receiverLoop(); void receiverLoop();
void nop(const QVariantMap &receivedInformation);
void processReceivedDocument(const QJsonDocument &receivedJsonDocument); void processReceivedDocument(const QJsonDocument &receivedJsonDocument);
void processUpdateOption(const QVariantMap &receivedInformation); void processUpdateOption(const QVariantMap &receivedInformation);
void processUpdateAuthorizationState(const QVariantMap &receivedInformation); void processUpdateAuthorizationState(const QVariantMap &receivedInformation);
@ -158,7 +160,6 @@ private:
void processUpdateMessageIsPinned(const QVariantMap &receivedInformation); void processUpdateMessageIsPinned(const QVariantMap &receivedInformation);
void processUsers(const QVariantMap &receivedInformation); void processUsers(const QVariantMap &receivedInformation);
void processError(const QVariantMap &receivedInformation); void processError(const QVariantMap &receivedInformation);
void nop(const QVariantMap &receivedInformation);
void processSecretChat(const QVariantMap &receivedInformation); void processSecretChat(const QVariantMap &receivedInformation);
void processUpdateSecretChat(const QVariantMap &receivedInformation); void processUpdateSecretChat(const QVariantMap &receivedInformation);
void processUpdateMessageEdited(const QVariantMap &receivedInformation); void processUpdateMessageEdited(const QVariantMap &receivedInformation);
@ -169,6 +170,7 @@ private:
void processCallbackQueryAnswer(const QVariantMap &receivedInformation); void processCallbackQueryAnswer(const QVariantMap &receivedInformation);
void processUserPrivacySettingRules(const QVariantMap &receivedInformation); void processUserPrivacySettingRules(const QVariantMap &receivedInformation);
void processUpdateUserPrivacySettingRules(const QVariantMap &receivedInformation); void processUpdateUserPrivacySettingRules(const QVariantMap &receivedInformation);
void processUpdateMessageInteractionInfo(const QVariantMap &receivedInformation);
}; };
#endif // TDLIBRECEIVER_H #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(callbackQueryAnswer(QString, bool, QString)), this, SIGNAL(callbackQueryAnswer(QString, bool, QString)));
connect(this->tdLibReceiver, SIGNAL(userPrivacySettingRules(QVariantMap)), this, SLOT(handleUserPrivacySettingRules(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(userPrivacySettingRules(QVariantMap)), this, SLOT(handleUserPrivacySettingRules(QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(userPrivacySettingRulesUpdated(QVariantMap)), this, SLOT(handleUpdatedUserPrivacySettingRules(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))); connect(this->tdLibReceiver, SIGNAL(okReceived(QString)), this, SIGNAL(okReceived(QString)));
this->tdLibReceiver->start(); 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 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 callbackQueryAnswer(const QString &text, bool alert, const QString &url);
void userPrivacySettingUpdated(UserPrivacySetting setting, UserPrivacySettingRule rule); void userPrivacySettingUpdated(UserPrivacySetting setting, UserPrivacySettingRule rule);
void messageInteractionInfoUpdated(qlonglong chatId, qlonglong messageId, const QVariantMap &updatedInfo);
void okReceived(const QString &request); void okReceived(const QString &request);
public slots: public slots: