From 753f322053e5b43b5504aa1469c61df4d3394908 Mon Sep 17 00:00:00 2001 From: John Gibbon Date: Thu, 31 Dec 2020 00:59:05 +0100 Subject: [PATCH] implement message drafts --- qml/components/ChatListViewItem.qml | 8 ++-- qml/pages/ChatPage.qml | 13 ++++++ src/chatlistmodel.cpp | 45 +++++++++++++++++++++ src/chatlistmodel.h | 5 ++- src/tdlibreceiver.cpp | 8 ++++ src/tdlibreceiver.h | 2 + src/tdlibwrapper.cpp | 26 ++++++++++++ src/tdlibwrapper.h | 2 + translations/harbour-fernschreiber-de.ts | 4 ++ translations/harbour-fernschreiber-en.ts | 4 ++ translations/harbour-fernschreiber-es.ts | 4 ++ translations/harbour-fernschreiber-fi.ts | 4 ++ translations/harbour-fernschreiber-hu.ts | 4 ++ translations/harbour-fernschreiber-it.ts | 4 ++ translations/harbour-fernschreiber-pl.ts | 4 ++ translations/harbour-fernschreiber-ru.ts | 4 ++ translations/harbour-fernschreiber-sv.ts | 4 ++ translations/harbour-fernschreiber-zh_CN.ts | 4 ++ translations/harbour-fernschreiber.ts | 4 ++ 19 files changed, 149 insertions(+), 4 deletions(-) diff --git a/qml/components/ChatListViewItem.qml b/qml/components/ChatListViewItem.qml index 74afedd..b01c487 100644 --- a/qml/components/ChatListViewItem.qml +++ b/qml/components/ChatListViewItem.qml @@ -11,15 +11,17 @@ PhotoTextsListItem { photoData: photo_small || ({}) } property int ownUserId + property bool showDraft: !!draft_message_text && draft_message_date > last_message_date + property string previewText: showDraft ? draft_message_text : last_message_text // chat title primaryText.text: title ? Emoji.emojify(title + ( display.notification_settings.mute_for > 0 ? " 🔇" : "" ), Theme.fontSizeMedium) : qsTr("Unknown") // last user - prologSecondaryText.text: is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), primaryText.font.pixelSize) : qsTr("You") ) : "" ) + prologSecondaryText.text: showDraft ? ""+qsTr("Draft")+"" : (is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), primaryText.font.pixelSize) : qsTr("You") ) : "" )) // last message - secondaryText.text: last_message_text ? Emoji.emojify(Functions.enhanceHtmlEntities(last_message_text), Theme.fontSizeExtraSmall) : "" + qsTr("No message in this chat.") + "" + secondaryText.text: previewText ? Emoji.emojify(Functions.enhanceHtmlEntities(previewText), Theme.fontSizeExtraSmall) : "" + qsTr("No message in this chat.") + "" // message date - tertiaryText.text: ( last_message_date ? ( last_message_date.length === 0 ? "" : Functions.getDateTimeElapsed(last_message_date) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) ) : "" ) + tertiaryText.text: showDraft ? Functions.getDateTimeElapsed(draft_message_date) : ( last_message_date ? ( last_message_date.length === 0 ? "" : Functions.getDateTimeElapsed(last_message_date) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) ) : "" ) unreadCount: unread_count isSecret: ( chat_type === TelegramAPI.ChatTypeSecret ) isMarkedAsUnread: is_marked_as_unread diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index cc2f9d8..961d643 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -373,6 +373,7 @@ Page { } Component.onDestruction: { + tdLibWrapper.setChatDraftMessage(chatInformation.id, 0, newMessageColumn.replyToMessageId, newMessageTextField.text); tdLibWrapper.closeChat(chatInformation.id); } @@ -387,6 +388,15 @@ Page { pageStack.pushAttached(Qt.resolvedUrl("ChatInformationPage.qml"), { "chatInformation" : chatInformation, "privateChatUserInformation": chatPartnerInformation, "groupInformation": chatGroupInformation, "chatOnlineMemberCount": chatOnlineMemberCount}); chatPage.isInitialized = true; + + if(chatInformation.draft_message) { + if(chatInformation.draft_message && chatInformation.draft_message.input_message_text) { + newMessageTextField.text = chatInformation.draft_message.input_message_text.text.text; + if(chatInformation.draft_message.reply_to_message_id) { + tdLibWrapper.getMessage(chatInformation.id, chatInformation.draft_message.reply_to_message_id); + } + } + } } break; case PageStatus.Inactive: @@ -443,6 +453,9 @@ Page { Debug.log("[ChatPage] Received pinned message"); pinnedMessageItem.pinnedMessage = message; } + if (messageId === chatInformation.draft_message.reply_to_message_id) { + newMessageInReplyToRow.inReplyToMessage = message; + } } onSecretChatReceived: { if (secretChatId === chatInformation.type.secret_chat_id) { diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index 64ad690..a3b9d23 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -35,6 +35,7 @@ namespace { const QString CHAT_ID("chat_id"); const QString CONTENT("content"); const QString LAST_MESSAGE("last_message"); + const QString DRAFT_MESSAGE("draft_message"); const QString SENDER("sender"); const QString USER_ID("user_id"); const QString BASIC_GROUP_ID("basic_group_id"); @@ -71,6 +72,8 @@ public: qlonglong senderMessageDate() const; QString senderMessageText() const; QString senderMessageStatus() const; + qlonglong draftMessageDate() const; + QString draftMessageText() const; bool isChannel() const; bool isHidden() const; bool isMarkedAsUnread() const; @@ -189,6 +192,7 @@ QString ChatListModel::ChatData::senderMessageText() const return FernschreiberUtils::getMessageShortText(tdLibWrapper, lastMessage(CONTENT).toMap(), isChannel(), this->userInformation.value(ID).toLongLong(), lastMessage(SENDER).toMap() ); } + QString ChatListModel::ChatData::senderMessageStatus() const { if (isChannel() || this->userInformation.value(ID).toLongLong() != senderUserId() || this->userInformation.value(ID).toLongLong() == chatId) { @@ -210,6 +214,23 @@ QString ChatListModel::ChatData::senderMessageStatus() const } } } +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(); +} bool ChatListModel::ChatData::isChannel() const { @@ -343,6 +364,7 @@ ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) : showHiddenChats(false connect(tdLibWrapper, SIGNAL(secretChatReceived(qlonglong, QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong, QVariantMap))); connect(tdLibWrapper, SIGNAL(chatTitleUpdated(QString, QString)), this, SLOT(handleChatTitleUpdated(QString, QString))); connect(tdLibWrapper, SIGNAL(chatIsMarkedAsUnreadUpdated(qlonglong, bool)), this, SLOT(handleChatIsMarkedAsUnreadUpdated(qlonglong, bool))); + connect(tdLibWrapper, SIGNAL(chatDraftMessageUpdated(qlonglong, QVariantMap, QString)), this, SLOT(handleChatDraftMessageUpdated(qlonglong, QVariantMap, QString))); // Don't start the timer until we have at least one chat relativeTimeRefreshTimer = new QTimer(this); @@ -378,6 +400,8 @@ QHash ChatListModel::roleNames() const roles.insert(ChatListModel::RoleIsChannel, "is_channel"); roles.insert(ChatListModel::RoleIsMarkedAsUnread, "is_marked_as_unread"); roles.insert(ChatListModel::RoleFilter, "filter"); + roles.insert(ChatListModel::RoleDraftMessageDate, "draft_message_date"); + roles.insert(ChatListModel::RoleDraftMessageText, "draft_message_text"); return roles; } @@ -409,6 +433,8 @@ QVariant ChatListModel::data(const QModelIndex &index, int role) const case ChatListModel::RoleIsChannel: return data->isChannel(); case ChatListModel::RoleIsMarkedAsUnread: return data->isMarkedAsUnread(); case ChatListModel::RoleFilter: return QString(data->title() + " " + data->senderMessageText()).trimmed(); + case ChatListModel::RoleDraftMessageText: return data->draftMessageText(); + case ChatListModel::RoleDraftMessageDate: return data->draftMessageDate(); } } return QVariant(); @@ -844,6 +870,25 @@ void ChatListModel::handleChatIsMarkedAsUnreadUpdated(qlonglong chatId, bool cha } } +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 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); + } + } +} + void ChatListModel::handleRelativeTimeRefreshTimer() { LOG("Refreshing timestamps"); diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index 0768859..51b8ce0 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -47,7 +47,9 @@ public: RoleIsVerified, RoleIsChannel, RoleIsMarkedAsUnread, - RoleFilter + RoleFilter, + RoleDraftMessageText, + RoleDraftMessageDate }; ChatListModel(TDLibWrapper *tdLibWrapper); @@ -78,6 +80,7 @@ private slots: void handleSecretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat); void handleChatTitleUpdated(const QString &chatId, const QString &title); void handleChatIsMarkedAsUnreadUpdated(qlonglong chatId, bool chatIsMarkedAsUnread); + void handleChatDraftMessageUpdated(qlonglong chatId, const QVariantMap &draftMessage, const QString &order); void handleRelativeTimeRefreshTimer(); signals: diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index 6d754dd..a367937 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -43,6 +43,7 @@ namespace { const QString LAST_MESSAGE("last_message"); const QString TOTAL_COUNT("total_count"); const QString UNREAD_COUNT("unread_count"); + const QString TEXT("text"); 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"); @@ -134,6 +135,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren handlers.insert("importedContacts", &TDLibReceiver::processImportedContacts); handlers.insert("updateMessageEdited", &TDLibReceiver::processUpdateMessageEdited); handlers.insert("updateChatIsMarkedAsUnread", &TDLibReceiver::processUpdateChatIsMarkedAsUnread); + handlers.insert("updateChatDraftMessage", &TDLibReceiver::processUpdateChatDraftMessage); } void TDLibReceiver::setActive(bool active) @@ -576,3 +578,9 @@ void TDLibReceiver::processUpdateChatIsMarkedAsUnread(const QVariantMap &receive LOG("The unread state of a chat was updated"); emit chatIsMarkedAsUnreadUpdated(receivedInformation.value(CHAT_ID).toLongLong(), receivedInformation.value("is_marked_as_unread").toBool()); } + +void TDLibReceiver::processUpdateChatDraftMessage(const QVariantMap &receivedInformation) +{ + LOG("Draft message was updated"); + emit chatDraftMessageUpdated(receivedInformation.value(CHAT_ID).toLongLong(), receivedInformation.value("draft_message").toMap(), findChatPositionOrder(receivedInformation.value(POSITIONS).toList())); +} diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index f466a5b..311610b 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -91,6 +91,7 @@ signals: void secretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat); void contactsImported(const QVariantList &importerCount, const QVariantList &userIds); void chatIsMarkedAsUnreadUpdated(qlonglong chatId, bool chatIsMarkedAsUnread); + void chatDraftMessageUpdated(qlonglong chatId, const QVariantMap &draftMessage, const QString &order); private: typedef void (TDLibReceiver::*Handler)(const QVariantMap &); @@ -157,6 +158,7 @@ private: void processUpdateMessageEdited(const QVariantMap &receivedInformation); void processImportedContacts(const QVariantMap &receivedInformation); void processUpdateChatIsMarkedAsUnread(const QVariantMap &receivedInformation); + void processUpdateChatDraftMessage(const QVariantMap &receivedInformation); }; #endif // TDLIBRECEIVER_H diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index b6d1b20..fe436c8 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -45,6 +45,7 @@ namespace { const QString LAST_NAME("last_name"); const QString FIRST_NAME("first_name"); const QString USERNAME("username"); + const QString THREAD_ID("thread_id"); const QString VALUE("value"); const QString _TYPE("@type"); const QString _EXTRA("@extra"); @@ -126,6 +127,7 @@ TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, connect(this->tdLibReceiver, SIGNAL(contactsImported(QVariantList, QVariantList)), this, SIGNAL(contactsImported(QVariantList, QVariantList))); connect(this->tdLibReceiver, SIGNAL(messageEditedUpdated(qlonglong, qlonglong, QVariantMap)), this, SIGNAL(messageEditedUpdated(qlonglong, qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chatIsMarkedAsUnreadUpdated(qlonglong, bool)), this, SIGNAL(chatIsMarkedAsUnreadUpdated(qlonglong, bool))); + connect(this->tdLibReceiver, SIGNAL(chatDraftMessageUpdated(qlonglong, QVariantMap, QString)), this, SIGNAL(chatDraftMessageUpdated(qlonglong, QVariantMap, QString))); connect(&emojiSearchWorker, SIGNAL(searchCompleted(QString, QVariantList)), this, SLOT(handleEmojiSearchCompleted(QString, QVariantList))); @@ -982,6 +984,30 @@ void TDLibWrapper::toggleChatIsMarkedAsUnread(qlonglong chatId, bool isMarkedAsU this->sendRequest(requestObject); } +void TDLibWrapper::setChatDraftMessage(qlonglong chatId, qlonglong threadId, qlonglong replyToMessageId, const QString &draft) +{ + LOG("Set Draft Message" << chatId); + QVariantMap requestObject; + requestObject.insert(_TYPE, "setChatDraftMessage"); + requestObject.insert(CHAT_ID, chatId); + requestObject.insert(THREAD_ID, threadId); + QVariantMap draftMessage; + QVariantMap inputMessageContent; + QVariantMap formattedText; + + formattedText.insert("text", draft); + formattedText.insert("clear_draft", draft.isEmpty()); + formattedText.insert(_TYPE, "formattedText"); + inputMessageContent.insert(_TYPE, "inputMessageText"); + inputMessageContent.insert("text", formattedText); + draftMessage.insert(_TYPE, "draftMessage"); + draftMessage.insert("reply_to_message_id", replyToMessageId); + draftMessage.insert("input_message_text", inputMessageContent); + + requestObject.insert("draft_message", draftMessage); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index db7b2a6..c24941b 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -183,6 +183,7 @@ public: Q_INVOKABLE void searchPublicChats(const QString &query); Q_INVOKABLE void readAllChatMentions(qlonglong chatId); Q_INVOKABLE void toggleChatIsMarkedAsUnread(qlonglong chatId, bool isMarkedAsUnread); + Q_INVOKABLE void setChatDraftMessage(qlonglong chatId, qlonglong threadId, qlonglong replyToMessageId, const QString &draft); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); @@ -253,6 +254,7 @@ signals: void contactsImported(const QVariantList &importerCount, const QVariantList &userIds); void messageNotFound(qlonglong chatId, qlonglong messageId); void chatIsMarkedAsUnreadUpdated(qlonglong chatId, bool chatIsMarkedAsUnread); + void chatDraftMessageUpdated(qlonglong chatId, const QVariantMap &draftMessage, const QString &order); public slots: void handleVersionDetected(const QString &version); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index bafe6fa..489527b 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -272,6 +272,10 @@ Mark chat as read Chat als gelesen markieren + + Draft + Entwurf + ChatPage diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 0c0e109..701afc6 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -272,6 +272,10 @@ Mark chat as read Mark chat as read + + Draft + Draft + ChatPage diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 44f4e5c..828b71c 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -265,6 +265,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index b4f1e6f..0882c32 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -268,6 +268,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 5e1fe8f..7ca1400 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -265,6 +265,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 3781db2..3c2baf9 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -268,6 +268,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 0e7796e..c2b925d 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -271,6 +271,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 5583389..72454c2 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -271,6 +271,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index d036298..63d8f75 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -268,6 +268,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 56924ea..8e4f8f9 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -265,6 +265,10 @@ Mark chat as unread + + Draft + + Mark chat as read diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 5f1a8da..8005242 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -272,6 +272,10 @@ Mark chat as read + + Draft + + ChatPage