diff --git a/qml/components/MessageListViewItem.qml b/qml/components/MessageListViewItem.qml
index 88ab301..b01a39a 100644
--- a/qml/components/MessageListViewItem.qml
+++ b/qml/components/MessageListViewItem.qml
@@ -64,6 +64,7 @@ ListItem {
readonly property bool showForwardMessageMenuItem: (baseContextMenuItemCount + 2) <= maxContextMenuItemCount
// And don't count "More Options..." for "Delete Message" if "Delete Message" is the only extra option
readonly property bool haveSpaceForDeleteMessageMenuItem: (baseContextMenuItemCount + 3 - (deleteMessageIsOnlyExtraOption ? 1 : 0)) <= maxContextMenuItemCount
+ property var chatReactions
property var messageReactions
highlighted: (down || isSelected || additionalOptionsOpened) && !menuOpen
@@ -94,15 +95,21 @@ ListItem {
}
}
- function getInteractionText(viewCount, reactions) {
+ function getInteractionText(viewCount, reactions, size, highlightColor) {
var interactionText = "";
if (viewCount > 0) {
- interactionText = Emoji.emojify("👁️", Theme.fontSizeTiny) + Functions.getShortenedCount(viewCount);
+ interactionText = Emoji.emojify("👁️ ", size) + 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) );
+ var reaction = reactions[i]
+ var reactionText = reaction.reaction ? reaction.reaction : (reaction.type && reaction.type.emoji) ? reaction.type.emoji : ""
+ if (reactionText) {
+ interactionText += ( " " + Emoji.emojify(reactionText, size) );
+ if (!chatPage.isPrivateChat) {
+ var count = Functions.getShortenedCount(reaction.total_count)
+ interactionText += " "
+ interactionText += (reaction.is_chosen ? ( "" + count + "" ) : count)
+ }
}
}
return interactionText;
@@ -125,6 +132,8 @@ ListItem {
if (messageListItem.messageReactions) {
messageListItem.messageReactions = null;
+ } else if (messageListItem.chatReactions) {
+ messageListItem.messageReactions = chatReactions
} else {
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId);
}
@@ -467,11 +476,12 @@ ListItem {
width: parent.width
Component.onCompleted: {
- if (myMessage.forward_info.origin["@type"] === "messageForwardOriginChannel") {
+ var originType = myMessage.forward_info.origin["@type"]
+ if (originType === "messageOriginChannel" || originType === "messageForwardOriginChannel") {
var otherChatInformation = tdLibWrapper.getChat(myMessage.forward_info.origin.chat_id);
forwardedThumbnail.photoData = (typeof otherChatInformation.photo !== "undefined") ? otherChatInformation.photo.small : {};
forwardedChannelText.text = Emoji.emojify(otherChatInformation.title, Theme.fontSizeExtraSmall);
- } else if (myMessage.forward_info.origin["@type"] === "messageForwardOriginUser") {
+ } else if (originType === "messageOriginUser" || originType === "messageForwardOriginUser") {
var otherUserInformation = tdLibWrapper.getUserInformation(myMessage.forward_info.origin.sender_user_id);
forwardedThumbnail.photoData = (typeof otherUserInformation.profile_photo !== "undefined") ? otherUserInformation.profile_photo.small : {};
forwardedChannelText.text = Emoji.emojify(Functions.getUserName(otherUserInformation), Theme.fontSizeExtraSmall);
@@ -625,7 +635,7 @@ ListItem {
height: ( ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0 ) ? ( Theme.fontSizeExtraSmall + Theme.paddingSmall ) : 0
sourceComponent: Component {
Label {
- text: getInteractionText(messageViewCount, reactions)
+ text: getInteractionText(messageViewCount, reactions, font.pixelSize, Theme.highlightColor)
width: parent.width
font.pixelSize: Theme.fontSizeTiny
color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor
diff --git a/qml/components/MessageOverlayFlickable.qml b/qml/components/MessageOverlayFlickable.qml
index 274a284..b5d8915 100644
--- a/qml/components/MessageOverlayFlickable.qml
+++ b/qml/components/MessageOverlayFlickable.qml
@@ -40,9 +40,11 @@ Flickable {
function getOriginalAuthor(forwardInformation, fontSize) {
switch (forwardInformation.origin["@type"]) {
+ case "messageOriginChannel":
case "messageForwardOriginChannel":
var otherChatInformation = tdLibWrapper.getChat(forwardInformation.origin.chat_id);
return Emoji.emojify(otherChatInformation.title, fontSize);
+ case "messageOriginUser":
case "messageForwardOriginUser":
var otherUserInformation = tdLibWrapper.getUserInformation(forwardInformation.origin.sender_id.user_id);
return Emoji.emojify(Functions.getUserName(otherUserInformation), fontSize);
diff --git a/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml
index b4280b5..2b12c6f 100644
--- a/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml
+++ b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml
@@ -79,7 +79,7 @@ ChatInformationTabItemBase {
// chat title
primaryText.text: Emoji.emojify(Functions.getUserName(user), primaryText.font.pixelSize)
// last user
- prologSecondaryText.text: "@"+(user.username !== "" ? user.username : member_id.user_id) + (member_id.user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "")
+ prologSecondaryText.text: "@"+(user.username ? user.username : member_id.user_id) + (member_id.user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "")
secondaryText {
horizontalAlignment: Text.AlignRight
property string statusText: Functions.getChatMemberStatusText(model.status["@type"])
@@ -180,6 +180,9 @@ ChatInformationTabItemBase {
for(var memberIndex in members) {
var memberData = members[memberIndex];
var userInfo = tdLibWrapper.getUserInformation(memberData.member_id.user_id) || {user:{}, bot_info:{}};
+ if (!userInfo.username && userInfo.usernames && userInfo.usernames.active_usernames) {
+ userInfo.username = userInfo.usernames.active_usernames[0]
+ }
memberData.user = userInfo;
memberData.bot_info = memberData.bot_info || {};
pageContent.membersList.append(memberData);
diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml
index acfec79..c4bb440 100644
--- a/qml/pages/ChatPage.qml
+++ b/qml/pages/ChatPage.qml
@@ -66,6 +66,7 @@ Page {
readonly property bool canSendMessages: hasSendPrivilege("can_send_messages")
property bool doSendBotStartMessage
property string sendBotStartMessageParameter
+ property var availableReactions
states: [
State {
@@ -184,7 +185,7 @@ Page {
}
tdLibWrapper.getChatPinnedMessage(chatInformation.id);
tdLibWrapper.toggleChatIsMarkedAsUnread(chatInformation.id, false);
-
+ availableReactions = tdLibWrapper.getChatReactions(chatInformation.id);
}
function getMessageStatusText(message, listItemIndex, lastReadSentIndex, useElapsed) {
@@ -1348,6 +1349,7 @@ Page {
messageId: model.message_id
messageViewCount: model.view_count
reactions: model.reactions
+ chatReactions: availableReactions
messageIndex: model.index
hasContentComponent: !!myMessage.content && chatView.delegateMessagesContent.indexOf(model.content_type) > -1
canReplyToMessage: chatPage.canSendMessages
diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp
index 985e7b7..ba035e9 100644
--- a/src/tdlibreceiver.cpp
+++ b/src/tdlibreceiver.cpp
@@ -60,6 +60,10 @@ namespace {
const QString CONTENT("content");
const QString NEW_CONTENT("new_content");
const QString SETS("sets");
+ const QString EMOJIS("emojis");
+ const QString REPLY_TO("reply_to");
+ const QString REPLY_IN_CHAT_ID("reply_in_chat_id");
+ const QString REPLY_TO_MESSAGE_ID("reply_to_message_id");
const QString _TYPE("@type");
const QString _EXTRA("@extra");
@@ -70,6 +74,7 @@ namespace {
const QString TYPE_MESSAGE("message");
const QString TYPE_STICKER("sticker");
const QString TYPE_MESSAGE_STICKER("messageSticker");
+ const QString TYPE_MESSAGE_REPLY_TO_MESSAGE("messageReplyToMessage");
const QString TYPE_MESSAGE_ANIMATED_EMOJI("messageAnimatedEmoji");
const QString TYPE_ANIMATED_EMOJI("animatedEmoji");
}
@@ -119,7 +124,8 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren
handlers.insert("updateSupergroup", &TDLibReceiver::processUpdateSuperGroup);
handlers.insert("updateChatOnlineMemberCount", &TDLibReceiver::processChatOnlineMemberCountUpdated);
handlers.insert("messages", &TDLibReceiver::processMessages);
- handlers.insert("sponsoredMessage", &TDLibReceiver::processSponsoredMessage);
+ handlers.insert("sponsoredMessage", &TDLibReceiver::processSponsoredMessage); // TdLib <= 1.8.7
+ handlers.insert("sponsoredMessages", &TDLibReceiver::processSponsoredMessages); // TdLib >= 1.8.8
handlers.insert("updateNewMessage", &TDLibReceiver::processUpdateNewMessage);
handlers.insert("message", &TDLibReceiver::processMessage);
handlers.insert("messageLinkInfo", &TDLibReceiver::processMessageLinkInfo);
@@ -167,6 +173,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren
handlers.insert("availableReactions", &TDLibReceiver::processAvailableReactions);
handlers.insert("updateChatUnreadMentionCount", &TDLibReceiver::processUpdateChatUnreadMentionCount);
handlers.insert("updateChatUnreadReactionCount", &TDLibReceiver::processUpdateChatUnreadReactionCount);
+ handlers.insert("updateActiveEmojiReactions", &TDLibReceiver::processUpdateActiveEmojiReactions);
}
void TDLibReceiver::setActive(bool active)
@@ -382,11 +389,24 @@ void TDLibReceiver::processMessages(const QVariantMap &receivedInformation)
void TDLibReceiver::processSponsoredMessage(const QVariantMap &receivedInformation)
{
+ // TdLib <= 1.8.7
const qlonglong chatId = receivedInformation.value(_EXTRA).toLongLong(); // See TDLibWrapper::getChatSponsoredMessage
LOG("Received sponsored message for chat" << chatId);
emit sponsoredMessageReceived(chatId, receivedInformation);
}
+void TDLibReceiver::processSponsoredMessages(const QVariantMap &receivedInformation)
+{
+ // TdLib >= 1.8.8
+ const qlonglong chatId = receivedInformation.value(_EXTRA).toLongLong(); // See TDLibWrapper::getChatSponsoredMessage
+ const QVariantList messages(receivedInformation.value(MESSAGES).toList());
+ LOG("Received" << messages.count() << "sponsored messages for chat" << chatId);
+ QListIterator it(messages);
+ while (it.hasNext()) {
+ emit sponsoredMessageReceived(chatId, it.next().toMap());
+ }
+}
+
void TDLibReceiver::processUpdateNewMessage(const QVariantMap &receivedInformation)
{
const QVariantMap message = receivedInformation.value(MESSAGE).toMap();
@@ -400,7 +420,7 @@ void TDLibReceiver::processMessage(const QVariantMap &receivedInformation)
const qlonglong chatId = receivedInformation.value(CHAT_ID).toLongLong();
const qlonglong messageId = receivedInformation.value(ID).toLongLong();
LOG("Received message " << chatId << messageId);
- emit messageInformation(chatId, messageId, receivedInformation);
+ emit messageInformation(chatId, messageId, cleanupMap(receivedInformation));
}
void TDLibReceiver::processMessageLinkInfo(const QVariantMap &receivedInformation)
@@ -718,6 +738,13 @@ void TDLibReceiver::processUpdateChatUnreadReactionCount(const QVariantMap &rece
emit chatUnreadReactionCountUpdated(chatId, unreadReactionCount);
}
+void TDLibReceiver::processUpdateActiveEmojiReactions(const QVariantMap &receivedInformation)
+{
+ // updateActiveEmojiReactions was introduced between 1.8.5 and 1.8.6
+ // See https://github.com/tdlib/td/commit/d29d367
+ emit activeEmojiReactionsUpdated(receivedInformation.value(EMOJIS).toStringList());
+}
+
// Recursively removes (some) unused entries from QVariantMaps to reduce
// memory usage. QStrings allocated by QVariantMaps are the top consumers
// of memory. The biggest saving is achieved by removing "outline" from
@@ -747,12 +774,42 @@ const QVariantMap TDLibReceiver::cleanupMap(const QVariantMap& map, bool *update
return animated_emoji;
}
} else if (type == TYPE_MESSAGE) {
- bool cleaned = false;
- const QVariantMap content(cleanupMap(map.value(CONTENT).toMap(), &cleaned));
- if (cleaned) {
- QVariantMap message(map);
+ QVariantMap message(map);
+ bool messageChanged = false;
+ const QVariantMap content(cleanupMap(map.value(CONTENT).toMap(), &messageChanged));
+ if (messageChanged) {
message.remove(CONTENT);
message.insert(CONTENT, content);
+ }
+ if (map.contains(REPLY_TO)) {
+ // In TdLib 1.8.15 reply_to_message_id and reply_in_chat_id attributes
+ // had been replaced with reply_to structure, e.g:
+ //
+ // "reply_to": {
+ // "@type": "messageReplyToMessage",
+ // "chat_id": -1001234567890,
+ // "is_quote_manual": false,
+ // "message_id": 234567890,
+ // "origin_send_date": 0
+ // }
+ //
+ QVariantMap reply_to(message.value(REPLY_TO).toMap());
+ if (reply_to.value(_TYPE).toString() == TYPE_MESSAGE_REPLY_TO_MESSAGE) {
+ if (reply_to.contains(MESSAGE_ID) &&
+ !message.contains(REPLY_TO_MESSAGE_ID)) {
+ message.insert(REPLY_TO_MESSAGE_ID, reply_to.value(MESSAGE_ID));
+ }
+ if (reply_to.contains(CHAT_ID) &&
+ !message.contains(REPLY_IN_CHAT_ID)) {
+ message.insert(REPLY_IN_CHAT_ID, reply_to.value(CHAT_ID));
+ }
+ reply_to.remove(_TYPE);
+ reply_to.insert(_TYPE, TYPE_MESSAGE_REPLY_TO_MESSAGE);
+ message.insert(REPLY_TO, reply_to);
+ messageChanged = true;
+ }
+ }
+ if (messageChanged) {
message.remove(_TYPE);
message.insert(_TYPE, TYPE_MESSAGE); // Replace with a shared value
if (updated) *updated = true;
diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h
index b033d9d..a13ae04 100644
--- a/src/tdlibreceiver.h
+++ b/src/tdlibreceiver.h
@@ -105,6 +105,7 @@ signals:
void availableReactionsReceived(qlonglong messageId, const QStringList &reactions);
void chatUnreadMentionCountUpdated(qlonglong chatId, int unreadMentionCount);
void chatUnreadReactionCountUpdated(qlonglong chatId, int unreadReactionCount);
+ void activeEmojiReactionsUpdated(const QStringList& emojis);
private:
typedef void (TDLibReceiver::*Handler)(const QVariantMap &);
@@ -139,6 +140,7 @@ private:
void processChatOnlineMemberCountUpdated(const QVariantMap &receivedInformation);
void processMessages(const QVariantMap &receivedInformation);
void processSponsoredMessage(const QVariantMap &receivedInformation);
+ void processSponsoredMessages(const QVariantMap &receivedInformation);
void processUpdateNewMessage(const QVariantMap &receivedInformation);
void processMessage(const QVariantMap &receivedInformation);
void processMessageLinkInfo(const QVariantMap &receivedInformation);
@@ -186,6 +188,7 @@ private:
void processAvailableReactions(const QVariantMap &receivedInformation);
void processUpdateChatUnreadMentionCount(const QVariantMap &receivedInformation);
void processUpdateChatUnreadReactionCount(const QVariantMap &receivedInformation);
+ void processUpdateActiveEmojiReactions(const QVariantMap &receivedInformation);
};
#endif // TDLIBRECEIVER_H
diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp
index 53be644..6cedc4d 100644
--- a/src/tdlibwrapper.cpp
+++ b/src/tdlibwrapper.cpp
@@ -36,6 +36,9 @@
#define DEBUG_MODULE TDLibWrapper
#include "debuglog.h"
+#define VERSION_NUMBER(x,y,z) \
+ ((((x) & 0x3ff) << 20) | (((y) & 0x3ff) << 10) | ((z) & 0x3ff))
+
namespace {
const QString STATUS("status");
const QString ID("id");
@@ -51,20 +54,28 @@ namespace {
const QString _TYPE("@type");
const QString _EXTRA("@extra");
const QString CHAT_LIST_MAIN("chatListMain");
+ const QString CHAT_AVAILABLE_REACTIONS("available_reactions");
+ const QString CHAT_AVAILABLE_REACTIONS_ALL("chatAvailableReactionsAll");
+ const QString CHAT_AVAILABLE_REACTIONS_SOME("chatAvailableReactionsSome");
+ const QString REACTIONS("reactions");
+ const QString REACTION_TYPE("reaction_type");
+ const QString REACTION_TYPE_EMOJI("reactionTypeEmoji");
+ const QString EMOJI("emoji");
}
-TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, QObject *parent)
+TDLibWrapper::TDLibWrapper(AppSettings *settings, MceInterface *mce, QObject *parent)
: QObject(parent)
+ , tdLibClient(td_json_client_create())
, manager(new QNetworkAccessManager(this))
, networkConfigurationManager(new QNetworkConfigurationManager(this))
+ , appSettings(settings)
+ , mceInterface(mce)
+ , authorizationState(AuthorizationState::Closed)
+ , versionNumber(0)
, joinChatRequested(false)
+ , isLoggingOut(false)
{
LOG("Initializing TD Lib...");
- this->appSettings = appSettings;
- this->mceInterface = mceInterface;
- this->tdLibClient = td_json_client_create();
- this->authorizationState = AuthorizationState::Closed;
- this->isLoggingOut = false;
initializeTDLibReceiver();
@@ -174,6 +185,7 @@ void TDLibWrapper::initializeTDLibReceiver() {
connect(this->tdLibReceiver, SIGNAL(availableReactionsReceived(qlonglong, QStringList)), this, SIGNAL(availableReactionsReceived(qlonglong, QStringList)));
connect(this->tdLibReceiver, SIGNAL(chatUnreadMentionCountUpdated(qlonglong, int)), this, SIGNAL(chatUnreadMentionCountUpdated(qlonglong, int)));
connect(this->tdLibReceiver, SIGNAL(chatUnreadReactionCountUpdated(qlonglong, int)), this, SIGNAL(chatUnreadReactionCountUpdated(qlonglong, int)));
+ connect(this->tdLibReceiver, SIGNAL(activeEmojiReactionsUpdated(QStringList)), this, SLOT(handleActiveEmojiReactionsUpdated(QStringList)));
this->tdLibReceiver->start();
}
@@ -192,7 +204,7 @@ void TDLibWrapper::sendRequest(const QVariantMap &requestObject)
QString TDLibWrapper::getVersion()
{
- return this->version;
+ return this->versionString;
}
TDLibWrapper::AuthorizationState TDLibWrapper::getAuthorizationState()
@@ -255,7 +267,7 @@ void TDLibWrapper::logout()
{
LOG("Logging out");
QVariantMap requestObject;
- requestObject.insert("@type", "logOut");
+ requestObject.insert(_TYPE, "logOut");
this->sendRequest(requestObject);
this->isLoggingOut = true;
@@ -436,7 +448,7 @@ void TDLibWrapper::sendTextMessage(const QString &chatId, const QString &message
QVariantMap entityType;
entityType.insert(_TYPE, "textEntityTypeMentionName");
entityType.insert("user_id", nextReplacement.value("userId").toString());
- entity.insert("type", entityType);
+ entity.insert(TYPE, entityType);
entities.append(entity);
offsetCorrection += replacementLength - replacementPlainText.length();
}
@@ -586,7 +598,7 @@ void TDLibWrapper::sendStickerMessage(const QString &chatId, const QString &file
QVariantMap stickerInputFile;
stickerInputFile.insert(_TYPE, "inputFileRemote");
- stickerInputFile.insert("id", fileId);
+ stickerInputFile.insert(ID, fileId);
inputMessageContent.insert("sticker", stickerInputFile);
@@ -620,7 +632,7 @@ void TDLibWrapper::sendPollMessage(const QString &chatId, const QString &questio
pollType.insert("allow_multiple_answers", multiple);
}
- inputMessageContent.insert("type", pollType);
+ inputMessageContent.insert(TYPE, pollType);
inputMessageContent.insert("question", question);
inputMessageContent.insert("options", options);
inputMessageContent.insert("is_anonymous", anonymous);
@@ -709,7 +721,11 @@ void TDLibWrapper::getChatSponsoredMessage(qlonglong chatId)
{
LOG("Retrieving sponsored message" << chatId);
QVariantMap requestObject;
- requestObject.insert(_TYPE, "getChatSponsoredMessage");
+ // getChatSponsoredMessage has been replaced with getChatSponsoredMessages
+ // between 1.8.7 and 1.8.8
+ // See https://github.com/tdlib/td/commit/ec1310a
+ requestObject.insert(_TYPE, QString((versionNumber > VERSION_NUMBER(1,8,7)) ?
+ "getChatSponsoredMessages" : "getChatSponsoredMessage"));
requestObject.insert(CHAT_ID, chatId);
requestObject.insert(_EXTRA, chatId); // see TDLibReceiver::processSponsoredMessage
this->sendRequest(requestObject);
@@ -1433,8 +1449,8 @@ void TDLibWrapper::getMessageAvailableReactions(qlonglong chatId, qlonglong mess
QVariantMap requestObject;
requestObject.insert(_TYPE, "getMessageAvailableReactions");
requestObject.insert(_EXTRA, QString::number(messageId));
- requestObject.insert("chat_id", chatId);
- requestObject.insert("message_id", messageId);
+ requestObject.insert(CHAT_ID, chatId);
+ requestObject.insert(MESSAGE_ID, messageId);
this->sendRequest(requestObject);
}
@@ -1457,11 +1473,23 @@ void TDLibWrapper::setMessageReaction(qlonglong chatId, qlonglong messageId, con
{
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(CHAT_ID, chatId);
+ requestObject.insert(MESSAGE_ID, messageId);
requestObject.insert("is_big", false);
+ if (versionNumber > VERSION_NUMBER(1,8,5)) {
+ // "reaction_type": {
+ // "@type": "reactionTypeEmoji",
+ // "emoji": "..."
+ // }
+ QVariantMap reactionType;
+ reactionType.insert(_TYPE, REACTION_TYPE_EMOJI);
+ reactionType.insert(EMOJI, reaction);
+ requestObject.insert(REACTION_TYPE, reactionType);
+ requestObject.insert(_TYPE, "addMessageReaction");
+ } else {
+ requestObject.insert("reaction", reaction);
+ requestObject.insert(_TYPE, "setMessageReaction");
+ }
this->sendRequest(requestObject);
}
@@ -1494,7 +1522,7 @@ void TDLibWrapper::setNetworkType(NetworkType networkType)
break;
}
- requestObject.insert("type", networkTypeObject);
+ requestObject.insert(TYPE, networkTypeObject);
this->sendRequest(requestObject);
}
@@ -1575,6 +1603,43 @@ QVariantMap TDLibWrapper::getChat(const QString &chatId)
return this->chats.value(chatId).toMap();
}
+QStringList TDLibWrapper::getChatReactions(const QString &chatId)
+{
+ const QVariant available_reactions(chats.value(chatId).toMap().value(CHAT_AVAILABLE_REACTIONS));
+ const QVariantMap map(available_reactions.toMap());
+ const QString reactions_type(map.value(_TYPE).toString());
+ if (reactions_type == CHAT_AVAILABLE_REACTIONS_ALL) {
+ return activeEmojiReactions;
+ } else if (reactions_type == CHAT_AVAILABLE_REACTIONS_SOME) {
+ const QVariantList reactions(map.value(REACTIONS).toList());
+ const int n = reactions.count();
+ QStringList emojis;
+
+ // "available_reactions": {
+ // "@type": "chatAvailableReactionsSome",
+ // "reactions": [
+ // {
+ // "@type": "reactionTypeEmoji",
+ // "emoji": "..."
+ // },
+ emojis.reserve(n);
+ for (int i = 0; i < n; i++) {
+ const QVariantMap reaction(reactions.at(i).toMap());
+ if (reaction.value(_TYPE).toString() == REACTION_TYPE_EMOJI) {
+ const QString emoji(reaction.value(EMOJI).toString());
+ if (!emoji.isEmpty()) {
+ emojis.append(emoji);
+ }
+ }
+ }
+ return emojis;
+ } else if (reactions_type.isEmpty()) {
+ return available_reactions.toStringList();
+ } else {
+ return QStringList();
+ }
+}
+
QVariantMap TDLibWrapper::getSecretChatFromCache(qlonglong secretChatId)
{
return this->secretChats.value(secretChatId);
@@ -1645,7 +1710,16 @@ DBusAdaptor *TDLibWrapper::getDBusAdaptor()
void TDLibWrapper::handleVersionDetected(const QString &version)
{
- this->version = version;
+ this->versionString = version;
+ const QStringList parts(version.split('.'));
+ uint major, minor, release;
+ bool ok;
+ if (parts.count() >= 3 &&
+ (major = parts.at(0).toInt(&ok), ok) &&
+ (minor = parts.at(1).toInt(&ok), ok) &&
+ (release = parts.at(2).toInt(&ok), ok)) {
+ versionNumber = VERSION_NUMBER(major, minor, release);
+ }
emit versionDetected(version);
}
@@ -1758,7 +1832,7 @@ void TDLibWrapper::handleConnectionStateChanged(const QString &connectionState)
void TDLibWrapper::handleUserUpdated(const QVariantMap &userInformation)
{
- QString updatedUserId = userInformation.value("id").toString();
+ QString updatedUserId = userInformation.value(ID).toString();
if (updatedUserId == this->options.value("my_id").toString()) {
LOG("Own user information updated :)");
this->userInformation = userInformation;
@@ -1774,11 +1848,11 @@ void TDLibWrapper::handleUserStatusUpdated(const QString &userId, const QVariant
{
if (userId == this->options.value("my_id").toString()) {
LOG("Own user status information updated :)");
- this->userInformation.insert("status", userStatusInformation);
+ this->userInformation.insert(STATUS, userStatusInformation);
}
LOG("User status information updated:" << userId << userStatusInformation.value(_TYPE).toString());
QVariantMap updatedUserInformation = this->allUsers.value(userId).toMap();
- updatedUserInformation.insert("status", userStatusInformation);
+ updatedUserInformation.insert(STATUS, userStatusInformation);
this->allUsers.insert(userId, updatedUserInformation);
this->allUserNames.insert(userInformation.value(USERNAME).toString(), userInformation);
emit userUpdated(userId, updatedUserInformation);
@@ -1786,12 +1860,12 @@ void TDLibWrapper::handleUserStatusUpdated(const QString &userId, const QVariant
void TDLibWrapper::handleFileUpdated(const QVariantMap &fileInformation)
{
- emit fileUpdated(fileInformation.value("id").toInt(), fileInformation);
+ emit fileUpdated(fileInformation.value(ID).toInt(), fileInformation);
}
void TDLibWrapper::handleNewChatDiscovered(const QVariantMap &chatInformation)
{
- QString chatId = chatInformation.value("id").toString();
+ QString chatId = chatInformation.value(ID).toString();
this->chats.insert(chatId, chatInformation);
emit newChatDiscovered(chatId, chatInformation);
}
@@ -1856,7 +1930,7 @@ void TDLibWrapper::handleStickerSets(const QVariantList &stickerSets)
QListIterator stickerSetIterator(stickerSets);
while (stickerSetIterator.hasNext()) {
QVariantMap stickerSet = stickerSetIterator.next().toMap();
- this->getStickerSet(stickerSet.value("id").toString());
+ this->getStickerSet(stickerSet.value(ID).toString());
}
emit this->stickerSetsReceived(stickerSets);
}
@@ -1988,6 +2062,13 @@ void TDLibWrapper::handleSponsoredMessage(qlonglong chatId, const QVariantMap &m
}
}
+void TDLibWrapper::handleActiveEmojiReactionsUpdated(const QStringList& emojis)
+{
+ if (activeEmojiReactions != emojis) {
+ activeEmojiReactions = emojis;
+ LOG(emojis.count() << "reaction(s) available");
+ }
+}
void TDLibWrapper::handleNetworkConfigurationChanged(const QNetworkConfiguration &config)
{
@@ -2077,28 +2158,40 @@ void TDLibWrapper::handleGetPageSourceFinished()
}
}
+QVariantMap& TDLibWrapper::fillTdlibParameters(QVariantMap& parameters)
+{
+ parameters.insert("api_id", TDLIB_API_ID);
+ parameters.insert("api_hash", TDLIB_API_HASH);
+ parameters.insert("database_directory", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/tdlib");
+ bool onlineOnlyMode = this->appSettings->onlineOnlyMode();
+ parameters.insert("use_file_database", !onlineOnlyMode);
+ parameters.insert("use_chat_info_database", !onlineOnlyMode);
+ parameters.insert("use_message_database", !onlineOnlyMode);
+ parameters.insert("use_secret_chats", true);
+ parameters.insert("system_language_code", QLocale::system().name());
+ QSettings hardwareSettings("/etc/hw-release", QSettings::NativeFormat);
+ parameters.insert("device_model", hardwareSettings.value("NAME", "Unknown Mobile Device").toString());
+ parameters.insert("system_version", QSysInfo::prettyProductName());
+ parameters.insert("application_version", "0.17");
+ parameters.insert("enable_storage_optimizer", appSettings->storageOptimizer());
+ // parameters.insert("use_test_dc", true);
+ return parameters;
+}
+
void TDLibWrapper::setInitialParameters()
{
LOG("Sending initial parameters to TD Lib");
QVariantMap requestObject;
requestObject.insert(_TYPE, "setTdlibParameters");
- QVariantMap initialParameters;
- initialParameters.insert("api_id", TDLIB_API_ID);
- initialParameters.insert("api_hash", TDLIB_API_HASH);
- initialParameters.insert("database_directory", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/tdlib");
- bool onlineOnlyMode = this->appSettings->onlineOnlyMode();
- initialParameters.insert("use_file_database", !onlineOnlyMode);
- initialParameters.insert("use_chat_info_database", !onlineOnlyMode);
- initialParameters.insert("use_message_database", !onlineOnlyMode);
- initialParameters.insert("use_secret_chats", true);
- initialParameters.insert("system_language_code", QLocale::system().name());
- QSettings hardwareSettings("/etc/hw-release", QSettings::NativeFormat);
- initialParameters.insert("device_model", hardwareSettings.value("NAME", "Unknown Mobile Device").toString());
- initialParameters.insert("system_version", QSysInfo::prettyProductName());
- initialParameters.insert("application_version", "0.17");
- initialParameters.insert("enable_storage_optimizer", appSettings->storageOptimizer());
- // initialParameters.insert("use_test_dc", true);
- requestObject.insert("parameters", initialParameters);
+ // tdlibParameters were inlined between 1.8.5 and 1.8.6
+ // See https://github.com/tdlib/td/commit/f6a2ecd
+ if (versionNumber > VERSION_NUMBER(1,8,5)) {
+ fillTdlibParameters(requestObject);
+ } else {
+ QVariantMap initialParameters;
+ fillTdlibParameters(initialParameters);
+ requestObject.insert("parameters", initialParameters);
+ }
this->sendRequest(requestObject);
}
diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h
index 1d1ec6d..4caff11 100644
--- a/src/tdlibwrapper.h
+++ b/src/tdlibwrapper.h
@@ -148,6 +148,7 @@ public:
Q_INVOKABLE QVariantMap getSuperGroup(qlonglong groupId) const;
Q_INVOKABLE QVariantMap getChat(const QString &chatId);
Q_INVOKABLE QVariantMap getSecretChatFromCache(qlonglong secretChatId);
+ Q_INVOKABLE QStringList getChatReactions(const QString &chatId);
Q_INVOKABLE QString getOptionString(const QString &optionName);
Q_INVOKABLE void copyFileToDownloads(const QString &filePath, bool openAfterCopy = false);
Q_INVOKABLE void openFileOnDevice(const QString &filePath);
@@ -364,7 +365,7 @@ public slots:
void handleUpdatedUserPrivacySettingRules(const QVariantMap &updatedRules);
void handleSponsoredMessage(qlonglong chatId, const QVariantMap &message);
void handleNetworkConfigurationChanged(const QNetworkConfiguration &config);
-
+ void handleActiveEmojiReactionsUpdated(const QStringList& emojis);
void handleGetPageSourceFinished();
private:
@@ -372,6 +373,7 @@ private:
void setInitialParameters();
void setEncryptionKey();
void setLogVerbosityLevel();
+ QVariantMap &fillTdlibParameters(QVariantMap ¶meters);
const Group *updateGroup(qlonglong groupId, const QVariantMap &groupInfo, QHash *groups);
void initializeTDLibReceiver();
@@ -383,7 +385,7 @@ private:
MceInterface *mceInterface;
TDLibReceiver *tdLibReceiver;
DBusInterface *dbusInterface;
- QString version;
+ QString versionString;
TDLibWrapper::AuthorizationState authorizationState;
QVariantMap authorizationStateData;
TDLibWrapper::ConnectionState connectionState;
@@ -399,7 +401,9 @@ private:
QHash basicGroups;
QHash superGroups;
EmojiSearchWorker emojiSearchWorker;
+ QStringList activeEmojiReactions;
+ int versionNumber;
QString activeChatSearchName;
bool joinChatRequested;
bool isLoggingOut;