diff --git a/qml/components/MessageListViewItem.qml b/qml/components/MessageListViewItem.qml index ecb465f..31e0e66 100644 --- a/qml/components/MessageListViewItem.qml +++ b/qml/components/MessageListViewItem.qml @@ -32,6 +32,7 @@ ListItem { property int messageIndex property int messageViewCount property var myMessage + property var reactions property bool canReplyToMessage readonly property bool isAnonymous: myMessage.sender_id["@type"] === "messageSenderChat" readonly property var userInformation: tdLibWrapper.getUserInformation(myMessage.sender_id.user_id) @@ -93,6 +94,20 @@ ListItem { } } + function getInteractionText(viewCount, reactions) { + var interactionText = ""; + if (viewCount > 0) { + interactionText = Emoji.emojify("👁️", Theme.fontSizeTiny) + Functions.getShortenedCount(viewCount); + } + for (var i = 0; i < reactions.length; i++) { + interactionText += ( " " + Emoji.emojify(reactions[i].reaction, Theme.fontSizeTiny) ); + if (!chatPage.isPrivateChat) { + interactionText += ( " " + Functions.getShortenedCount(reactions[i].total_count) ); + } + } + return interactionText; + } + onClicked: { if (messageListItem.precalculatedValues.pageIsSelecting) { page.toggleMessageSelection(myMessage); @@ -269,6 +284,8 @@ ListItem { tdLibWrapper.getMessage(myMessage.reply_in_chat_id ? myMessage.reply_in_chat_id : page.chatInformation.id, myMessage.reply_to_message_id) } + + console.log("HUGGA: " + messageViewCount + " | " + JSON.stringify(reactions)); } onMyMessageChanged: { @@ -590,7 +607,6 @@ ListItem { color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor horizontalAlignment: messageListItem.textAlign text: getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed) - rightPadding: interactionLoader.active ? interactionLoader.width : 0 MouseArea { anchors.fill: parent enabled: !messageListItem.precalculatedValues.pageIsSelecting @@ -599,33 +615,24 @@ ListItem { messageDateText.text = getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed); } } + } - Loader { - id: interactionLoader - height: parent.height - anchors.right: parent.right - asynchronous: true - active: chatPage.isChannel && messageViewCount - sourceComponent: Component { - Label { - text: Functions.getShortenedCount(messageViewCount) - leftPadding: Theme.iconSizeSmall - font.pixelSize: Theme.fontSizeTiny - color: Theme.secondaryColor - Icon { - anchors.verticalCenter: parent.verticalCenter - width: Theme.iconSizeExtraSmall - height: Theme.iconSizeExtraSmall - opacity: 0.6 - source: "../../images/icon-s-eye.svg" - sourceSize { - width: Theme.iconSizeExtraSmall - height: Theme.iconSizeExtraSmall - } - } - } + Loader { + id: interactionLoader + width: parent.width + asynchronous: true + active: ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0 + sourceComponent: Component { + Label { + text: getInteractionText(messageViewCount, reactions) + width: parent.width + font.pixelSize: Theme.fontSizeTiny + color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor + horizontalAlignment: messageListItem.textAlign + textFormat: Text.StyledText + maximumLineCount: 1 + elide: Text.ElideRight } - } } @@ -678,7 +685,7 @@ ListItem { MouseArea { anchors.fill: parent onClicked: { - Debug.log("Reaction clicked: " + modelData); + tdLibWrapper.setMessageReaction(messageListItem.chatId, messageListItem.messageId, modelData); messageListItem.messageReactions = null; } } diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 05df3a7..072103a 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -1345,6 +1345,7 @@ Page { myMessage: model.display messageId: model.message_id messageViewCount: model.view_count + reactions: model.reactions messageIndex: model.index hasContentComponent: !!myMessage.content && chatView.delegateMessagesContent.indexOf(model.content_type) > -1 canReplyToMessage: chatPage.canSendMessages diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index a89c5d0..2d182f1 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -50,6 +50,7 @@ namespace { const QString TYPE_MESSAGE_INTERACTION_INFO("messageInteractionInfo"); const QString INTERACTION_INFO("interaction_info"); const QString VIEW_COUNT("view_count"); + const QString REACTIONS("reactions"); const QString TYPE_SPONSORED_MESSAGE("sponsoredMessage"); } @@ -61,14 +62,16 @@ public: RoleDisplay = Qt::DisplayRole, RoleMessageId, RoleMessageContentType, - RoleMessageViewCount + RoleMessageViewCount, + RoleMessageReactions }; enum RoleFlag { RoleFlagDisplay = 0x01, RoleFlagMessageId = 0x02, RoleFlagMessageContentType = 0x04, - RoleFlagMessageViewCount = 0x08 + RoleFlagMessageViewCount = 0x08, + RoleFlagMessageReactions = 0x16 }; MessageData(const QVariantMap &data, qlonglong msgid); @@ -82,6 +85,7 @@ public: uint updateReplyMarkup(const QVariantMap &replyMarkup); uint updateViewCount(const QVariantMap &interactionInfo); uint updateInteractionInfo(const QVariantMap &interactionInfo); + uint updateReactions(const QVariantMap &interactionInfo); QVector diff(const MessageData *message) const; QVector setMessageData(const QVariantMap &data); @@ -99,6 +103,7 @@ public: QString messageType; QString messageContentType; int viewCount; + QVariantList reactions; }; ChatModel::MessageData::MessageData(const QVariantMap &data, qlonglong msgid) : @@ -106,7 +111,8 @@ ChatModel::MessageData::MessageData(const QVariantMap &data, qlonglong msgid) : messageId(msgid), messageType(data.value(_TYPE).toString()), messageContentType(data.value(CONTENT).toMap().value(_TYPE).toString()), - viewCount(data.value(INTERACTION_INFO).toMap().value(VIEW_COUNT).toInt()) + viewCount(data.value(INTERACTION_INFO).toMap().value(VIEW_COUNT).toInt()), + reactions(data.value(INTERACTION_INFO).toMap().value(REACTIONS).toList()) { } @@ -125,6 +131,9 @@ QVector ChatModel::MessageData::flagsToRoles(uint flags) if (flags & RoleFlagMessageViewCount) { roles.append(RoleMessageViewCount); } + if (flags & RoleFlagMessageReactions) { + roles.append(RoleMessageReactions); + } return roles; } @@ -157,6 +166,9 @@ QVector ChatModel::MessageData::diff(const MessageData *message) const if (message->viewCount != viewCount) { roles.append(RoleMessageViewCount); } + if (message->reactions != reactions) { + roles.append(RoleMessageReactions); + } } return roles; } @@ -167,7 +179,7 @@ uint ChatModel::MessageData::updateMessageData(const QVariantMap &data) messageType = data.value(_TYPE).toString(); return RoleFlagDisplay | updateContentType(data.value(CONTENT).toMap()) | - updateViewCount(data.value(INTERACTION_INFO).toMap()); + updateInteractionInfo(data.value(INTERACTION_INFO).toMap()); } QVector ChatModel::MessageData::setMessageData(const QVariantMap &data) @@ -215,11 +227,18 @@ uint ChatModel::MessageData::updateInteractionInfo(const QVariantMap &interactio { if (interactionInfo.value(_TYPE) == TYPE_MESSAGE_INTERACTION_INFO) { messageData.insert(INTERACTION_INFO, interactionInfo); - return RoleFlagDisplay | updateViewCount(interactionInfo); + return RoleFlagDisplay | updateViewCount(interactionInfo) | updateReactions(interactionInfo); } return 0; } +uint ChatModel::MessageData::updateReactions(const QVariantMap &interactionInfo) +{ + const QVariantList oldReactions = reactions; + reactions = interactionInfo.value(REACTIONS).toList(); + return (reactions == oldReactions) ? 0 : RoleFlagMessageReactions; +} + QVector ChatModel::MessageData::setInteractionInfo(const QVariantMap &info) { return flagsToRoles(updateInteractionInfo(info)); @@ -277,6 +296,7 @@ QHash ChatModel::roleNames() const roles.insert(MessageData::RoleMessageId, "message_id"); roles.insert(MessageData::RoleMessageContentType, "content_type"); roles.insert(MessageData::RoleMessageViewCount, "view_count"); + roles.insert(MessageData::RoleMessageReactions, "reactions"); return roles; } @@ -295,6 +315,7 @@ QVariant ChatModel::data(const QModelIndex &index, int role) const case MessageData::RoleMessageId: return message->messageId; case MessageData::RoleMessageContentType: return message->messageContentType; case MessageData::RoleMessageViewCount: return message->viewCount; + case MessageData::RoleMessageReactions: return message->reactions; } } return QVariant(); diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index a00ed7b..974819a 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -1436,6 +1436,18 @@ void TDLibWrapper::getPageSource(const QString &address) connect(reply, SIGNAL(finished()), this, SLOT(handleGetPageSourceFinished())); } +void TDLibWrapper::setMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction) +{ + LOG("Set message reaction" << chatId << messageId << reaction); + QVariantMap requestObject; + requestObject.insert(_TYPE, "setMessageReaction"); + requestObject.insert("chat_id", chatId); + requestObject.insert("message_id", messageId); + requestObject.insert("reaction", reaction); + requestObject.insert("is_big", false); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 76924e8..5545318 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -237,6 +237,7 @@ public: Q_INVOKABLE void terminateSession(const QString &sessionId); Q_INVOKABLE void getMessageAvailableReactions(qlonglong chatId, qlonglong messageId); Q_INVOKABLE void getPageSource(const QString &address); + Q_INVOKABLE void setMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString);