From 45bcc4f33d1d6bf9619b8032a6999b4eb067a984 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Wed, 16 Dec 2020 23:32:42 +0100 Subject: [PATCH 1/9] Introduce filter capabilities for chat list --- qml/pages/OverviewPage.qml | 65 +++++++++++++- src/chatlistmodel.cpp | 93 +++++++++------------ src/chatlistmodel.h | 20 +++++ src/harbour-fernschreiber.cpp | 5 ++ 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 + 15 files changed, 171 insertions(+), 56 deletions(-) diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index 70ae2c7..cfd5fa1 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -65,6 +65,7 @@ Page { onTriggered: { overviewPage.chatListCreated = true; chatListModel.redrawModel(); + chatListView.model = chatListProxyModel; } } @@ -76,6 +77,16 @@ Page { } } + Timer { + id: searchChatTimer + interval: 300 + running: false + repeat: false + onTriggered: { + chatListProxyModel.setFilterWildcard("*" + chatSearchField.text + "*"); + } + } + function setPageStatus() { switch (overviewPage.connectionState) { case TelegramAPI.WaitingForNetwork: @@ -138,6 +149,14 @@ Page { } } + function resetFocus() { + chatSearchField.focus = false; + overviewPage.focus = true; + chatSearchField.visible = false; + pageHeader.visible = true; + searchChatButton.visible = overviewPage.connectionState === TelegramAPI.ConnectionReady; + } + Connections { target: tdLibWrapper onAuthorizationStateChanged: { @@ -217,7 +236,7 @@ Page { Row { id: headerRow - width: parent.width + width: parent.width - Theme.horizontalPageMargin GlassItem { id: pageStatus @@ -232,8 +251,50 @@ Page { PageHeader { id: pageHeader title: qsTr("Fernschreiber") - width: parent.width - pageStatus.width + width: visible ? ( parent.width - pageStatus.width - searchChatButton.width ) : 0 + opacity: visible ? 1 : 0 + Behavior on opacity { NumberAnimation {} } } + + IconButton { + id: searchChatButton + width: visible ? height : 0 + opacity: visible ? 1 : 0 + Behavior on opacity { NumberAnimation {} } + anchors.verticalCenter: parent.verticalCenter + icon { + source: "image://theme/icon-m-search?" + Theme.highlightColor + asynchronous: true + } + visible: overviewPage.connectionState === TelegramAPI.ConnectionReady + onClicked: { + chatSearchField.focus = true; + chatSearchField.visible = true; + pageHeader.visible = false; + searchChatButton.visible = false; + } + } + + SearchField { + id: chatSearchField + visible: false + opacity: visible ? 1 : 0 + Behavior on opacity { NumberAnimation {} } + width: visible ? ( parent.width - pageStatus.width ) : 0 + height: pageHeader.height + placeholderText: qsTr("Search a chat...") + active: searchHeaderItem.visible + + onTextChanged: { + searchChatTimer.restart(); + } + + EnterKey.iconSource: "image://theme/icon-m-enter-close" + EnterKey.onClicked: { + resetFocus(); + } + } + } Item { diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index 8e958f4..b73e381 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -54,23 +54,6 @@ namespace { class ChatListModel::ChatData { public: - enum Role { - RoleDisplay = Qt::DisplayRole, - RoleChatId, - RoleChatType, - RoleTitle, - RolePhotoSmall, - RoleUnreadCount, - RoleLastReadInboxMessageId, - RoleLastMessageSenderId, - RoleLastMessageDate, - RoleLastMessageText, - RoleLastMessageStatus, - RoleChatMemberStatus, - RoleSecretChatState, - RoleIsVerified, - RoleIsChannel - }; ChatData(const QVariantMap &data, const QVariantMap &userInformation); @@ -368,21 +351,22 @@ ChatListModel::~ChatListModel() QHash ChatListModel::roleNames() const { QHash roles; - roles.insert(ChatData::RoleDisplay, "display"); - roles.insert(ChatData::RoleChatId, "chat_id"); - roles.insert(ChatData::RoleChatType, "chat_type"); - roles.insert(ChatData::RoleTitle, "title"); - roles.insert(ChatData::RolePhotoSmall, "photo_small"); - roles.insert(ChatData::RoleUnreadCount, "unread_count"); - roles.insert(ChatData::RoleLastReadInboxMessageId, "last_read_inbox_message_id"); - roles.insert(ChatData::RoleLastMessageSenderId, "last_message_sender_id"); - roles.insert(ChatData::RoleLastMessageDate, "last_message_date"); - roles.insert(ChatData::RoleLastMessageText, "last_message_text"); - roles.insert(ChatData::RoleLastMessageStatus, "last_message_status"); - roles.insert(ChatData::RoleChatMemberStatus, "chat_member_status"); - roles.insert(ChatData::RoleSecretChatState, "secret_chat_state"); - roles.insert(ChatData::RoleIsVerified, "is_verified"); - roles.insert(ChatData::RoleIsChannel, "is_channel"); + roles.insert(ChatListModel::RoleDisplay, "display"); + roles.insert(ChatListModel::RoleChatId, "chat_id"); + roles.insert(ChatListModel::RoleChatType, "chat_type"); + roles.insert(ChatListModel::RoleTitle, "title"); + roles.insert(ChatListModel::RolePhotoSmall, "photo_small"); + roles.insert(ChatListModel::RoleUnreadCount, "unread_count"); + roles.insert(ChatListModel::RoleLastReadInboxMessageId, "last_read_inbox_message_id"); + roles.insert(ChatListModel::RoleLastMessageSenderId, "last_message_sender_id"); + roles.insert(ChatListModel::RoleLastMessageDate, "last_message_date"); + roles.insert(ChatListModel::RoleLastMessageText, "last_message_text"); + roles.insert(ChatListModel::RoleLastMessageStatus, "last_message_status"); + roles.insert(ChatListModel::RoleChatMemberStatus, "chat_member_status"); + roles.insert(ChatListModel::RoleSecretChatState, "secret_chat_state"); + roles.insert(ChatListModel::RoleIsVerified, "is_verified"); + roles.insert(ChatListModel::RoleIsChannel, "is_channel"); + roles.insert(ChatListModel::RoleFilter, "filter"); return roles; } @@ -396,22 +380,23 @@ QVariant ChatListModel::data(const QModelIndex &index, int role) const const int row = index.row(); if (row >= 0 && row < chatList.size()) { const ChatData *data = chatList.at(row); - switch ((ChatData::Role)role) { - case ChatData::RoleDisplay: return data->chatData; - case ChatData::RoleChatId: return data->chatId; - case ChatData::RoleChatType: return data->chatType; - case ChatData::RoleTitle: return data->title(); - case ChatData::RolePhotoSmall: return data->photoSmall(); - case ChatData::RoleUnreadCount: return data->unreadCount(); - case ChatData::RoleLastReadInboxMessageId: return data->lastReadInboxMessageId(); - case ChatData::RoleLastMessageSenderId: return data->senderUserId(); - case ChatData::RoleLastMessageText: return data->senderMessageText(); - case ChatData::RoleLastMessageDate: return data->senderMessageDate(); - case ChatData::RoleLastMessageStatus: return data->senderMessageStatus(); - case ChatData::RoleChatMemberStatus: return data->memberStatus; - case ChatData::RoleSecretChatState: return data->secretChatState; - case ChatData::RoleIsVerified: return data->verified; - case ChatData::RoleIsChannel: return data->isChannel(); + switch ((ChatListModel::Role)role) { + case ChatListModel::RoleDisplay: return data->chatData; + case ChatListModel::RoleChatId: return data->chatId; + case ChatListModel::RoleChatType: return data->chatType; + case ChatListModel::RoleTitle: return data->title(); + case ChatListModel::RolePhotoSmall: return data->photoSmall(); + case ChatListModel::RoleUnreadCount: return data->unreadCount(); + case ChatListModel::RoleLastReadInboxMessageId: return data->lastReadInboxMessageId(); + case ChatListModel::RoleLastMessageSenderId: return data->senderUserId(); + case ChatListModel::RoleLastMessageText: return data->senderMessageText(); + case ChatListModel::RoleLastMessageDate: return data->senderMessageDate(); + case ChatListModel::RoleLastMessageStatus: return data->senderMessageStatus(); + case ChatListModel::RoleChatMemberStatus: return data->memberStatus; + case ChatListModel::RoleSecretChatState: return data->secretChatState; + case ChatListModel::RoleIsVerified: return data->verified; + case ChatListModel::RoleIsChannel: return data->isChannel(); + case ChatListModel::RoleFilter: return QString(data->title() + " " + data->senderMessageText()).trimmed(); } } return QVariant(); @@ -677,12 +662,12 @@ void ChatListModel::handleChatReadInboxUpdated(const QString &id, const QString const int chatIndex = chatIndexMap.value(chatId); ChatData *chat = chatList.at(chatIndex); QVector changedRoles; - changedRoles.append(ChatData::RoleDisplay); + changedRoles.append(ChatListModel::RoleDisplay); if (chat->updateUnreadCount(unreadCount)) { - changedRoles.append(ChatData::RoleUnreadCount); + changedRoles.append(ChatListModel::RoleUnreadCount); } if (chat->updateLastReadInboxMessageId(messageId)) { - changedRoles.append(ChatData::RoleLastReadInboxMessageId); + changedRoles.append(ChatListModel::RoleLastReadInboxMessageId); } const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex, changedRoles); @@ -726,7 +711,7 @@ void ChatListModel::handleChatPhotoUpdated(qlonglong chatId, const QVariantMap & ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(PHOTO, photo); QVector changedRoles; - changedRoles.append(ChatData::RolePhotoSmall); + changedRoles.append(ChatListModel::RolePhotoSmall); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex, changedRoles); } else { @@ -815,7 +800,7 @@ void ChatListModel::handleChatTitleUpdated(const QString &chatId, const QString ChatData *chat = chatList.at(chatIndex); chat->chatData.insert(TITLE, title); QVector changedRoles; - changedRoles.append(ChatData::RoleTitle); + changedRoles.append(ChatListModel::RoleTitle); const QModelIndex modelIndex(index(chatIndex)); emit dataChanged(modelIndex, modelIndex, changedRoles); } else { @@ -831,6 +816,6 @@ void ChatListModel::handleRelativeTimeRefreshTimer() { LOG("Refreshing timestamps"); QVector roles; - roles.append(ChatData::RoleLastMessageDate); + roles.append(ChatListModel::RoleLastMessageDate); emit dataChanged(index(0), index(chatList.size() - 1), roles); } diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index 07b5523..734d51b 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -29,6 +29,26 @@ class ChatListModel : public QAbstractListModel Q_PROPERTY(bool showAllChats READ showAllChats WRITE setShowAllChats NOTIFY showAllChatsChanged) public: + + enum Role { + RoleDisplay = Qt::DisplayRole, + RoleChatId, + RoleChatType, + RoleTitle, + RolePhotoSmall, + RoleUnreadCount, + RoleLastReadInboxMessageId, + RoleLastMessageSenderId, + RoleLastMessageDate, + RoleLastMessageText, + RoleLastMessageStatus, + RoleChatMemberStatus, + RoleSecretChatState, + RoleIsVerified, + RoleIsChannel, + RoleFilter + }; + ChatListModel(TDLibWrapper *tdLibWrapper); ~ChatListModel() override; diff --git a/src/harbour-fernschreiber.cpp b/src/harbour-fernschreiber.cpp index a2efd4f..6efdf5d 100644 --- a/src/harbour-fernschreiber.cpp +++ b/src/harbour-fernschreiber.cpp @@ -88,6 +88,11 @@ int main(int argc, char *argv[]) ChatListModel chatListModel(tdLibWrapper); context->setContextProperty("chatListModel", &chatListModel); + QSortFilterProxyModel chatListProxyModel(view.data()); + chatListProxyModel.setSourceModel(&chatListModel); + chatListProxyModel.setFilterRole(ChatListModel::RoleFilter); + chatListProxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive); + context->setContextProperty("chatListProxyModel", &chatListProxyModel); ChatModel chatModel(tdLibWrapper); context->setContextProperty("chatModel", &chatModel); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 7a6cd82..b0e5ba2 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -1026,6 +1026,10 @@ New Chat Neuer Chat + + Search a chat... + Einen Chat suchen... + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 5d5ce04..3e58d99 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -1026,6 +1026,10 @@ New Chat New Chat + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index d03fc54..17a1554 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -1015,6 +1015,10 @@ New Chat Nueva charla + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 852b3db..7493979 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -1027,6 +1027,10 @@ New Chat Uusi keskustelu + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 1fe058b..4a59da0 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -1015,6 +1015,10 @@ New Chat + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 462b213..8cb9762 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -1026,6 +1026,10 @@ New Chat Nuova chat + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index b288bf1..108f37f 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -1037,6 +1037,10 @@ New Chat Nowy czat + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index db06186..f2130b0 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -1037,6 +1037,10 @@ New Chat Новый Чат + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 94844e1..fcaf8aa 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -1026,6 +1026,10 @@ New Chat Ny chatt + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 1e922cc..c6227d4 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -1015,6 +1015,10 @@ New Chat 新对话 + + Search a chat... + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 6251eb4..444ee1a 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -1026,6 +1026,10 @@ New Chat + + Search a chat... + + PinnedMessageItem From 1317f6532ea662fd9f88d86bb18ae4bef9c548a2 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Thu, 17 Dec 2020 09:24:20 +0100 Subject: [PATCH 2/9] Use chat list proxy model only if filtering is active --- qml/pages/OverviewPage.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index cfd5fa1..bf82fbe 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -65,7 +65,6 @@ Page { onTriggered: { overviewPage.chatListCreated = true; chatListModel.redrawModel(); - chatListView.model = chatListProxyModel; } } @@ -312,7 +311,7 @@ Page { opacity: overviewPage.chatListCreated ? 1 : 0 Behavior on opacity { NumberAnimation {} } - model: chatListModel + model: chatSearchField.text !== "" ? chatListProxyModel : chatListModel delegate: ChatListViewItem { ownUserId: overviewPage.ownUserId isVerified: is_verified From 19a17ed3f37433056188c23f359906236c6da7e6 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Sun, 27 Dec 2020 00:16:25 +0100 Subject: [PATCH 3/9] Now you can search in a chat... --- qml/pages/ChatPage.qml | 66 +++++++++++++++++++++ qml/pages/OverviewPage.qml | 15 +++-- src/chatmodel.cpp | 61 ++++++++++++++----- src/chatmodel.h | 5 +- src/tdlibwrapper.cpp | 14 +++++ src/tdlibwrapper.h | 1 + translations/harbour-fernschreiber-de.ts | 12 +++- translations/harbour-fernschreiber-en.ts | 12 +++- translations/harbour-fernschreiber-es.ts | 10 +++- translations/harbour-fernschreiber-fi.ts | 10 +++- translations/harbour-fernschreiber-hu.ts | 10 +++- translations/harbour-fernschreiber-it.ts | 10 +++- translations/harbour-fernschreiber-pl.ts | 10 +++- translations/harbour-fernschreiber-ru.ts | 10 +++- translations/harbour-fernschreiber-sv.ts | 10 +++- translations/harbour-fernschreiber-zh_CN.ts | 10 +++- translations/harbour-fernschreiber.ts | 10 +++- 17 files changed, 243 insertions(+), 33 deletions(-) diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index ef793a3..0387ef8 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -332,6 +332,14 @@ Page { return false; } + function resetFocus() { + if (searchInChatField.text === "") { + chatOverviewItem.visible = true; + } + searchInChatField.focus = false; + chatPage.focus = true; + } + Timer { id: forwardMessagesTimer interval: 200 @@ -348,6 +356,17 @@ Page { } } + Timer { + id: searchInChatTimer + interval: 300 + running: false + repeat: false + onTriggered: { + Debug.log("Searching for '" + searchInChatField.text + "'"); + chatModel.setSearchQuery(searchInChatField.text); + } + } + Component.onCompleted: { initializePage(); } @@ -627,6 +646,17 @@ Page { } text: chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat") } + + MenuItem { + id: searchInChatMenuItem + visible: !chatPage.isSecretChat + onClicked: { + // This automatically shows the search field as well + chatOverviewItem.visible = false; + searchInChatField.focus = true; + } + text: qsTr("Search in Chat") + } } BackgroundItem { @@ -700,6 +730,8 @@ Page { Item { id: chatOverviewItem + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } width: parent.width - chatPictureThumbnail.width - Theme.paddingMedium height: chatNameText.height + chatStatusText.height anchors.bottom: parent.bottom @@ -732,6 +764,40 @@ Page { maximumLineCount: 1 } } + + Item { + id: searchInChatItem + visible: !chatOverviewItem.visible + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + width: parent.width - chatPictureThumbnail.width - Theme.paddingMedium + height: searchInChatField.height + anchors.bottom: parent.bottom + anchors.bottomMargin: chatPage.isPortrait ? Theme.paddingMedium : Theme.paddingSmall + + SearchField { + id: searchInChatField + visible: false + width: visible ? parent.width : 0 + height: parent.height + placeholderText: qsTr("Search in chat...") + active: searchInChatItem.visible + canHide: text === "" + + onTextChanged: { + searchInChatTimer.restart(); + } + + onHideClicked: { + resetFocus(); + } + + EnterKey.iconSource: "image://theme/icon-m-enter-close" + EnterKey.onClicked: { + resetFocus(); + } + } + } } PinnedMessageItem { diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index 62e9342..cbb7775 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -156,11 +156,13 @@ Page { } function resetFocus() { + if (chatSearchField.text === "") { + chatSearchField.visible = false; + pageHeader.visible = true; + searchChatButton.visible = overviewPage.connectionState === TelegramAPI.ConnectionReady; + } chatSearchField.focus = false; overviewPage.focus = true; - chatSearchField.visible = false; - pageHeader.visible = true; - searchChatButton.visible = overviewPage.connectionState === TelegramAPI.ConnectionReady; } Connections { @@ -282,13 +284,18 @@ Page { Behavior on opacity { FadeAnimation {} } width: visible ? ( parent.width - pageStatus.width ) : 0 height: pageHeader.height - placeholderText: qsTr("Search a chat...") + placeholderText: qsTr("Filter your chats...") active: searchHeaderItem.visible + canHide: text === "" onTextChanged: { searchChatTimer.restart(); } + onHideClicked: { + resetFocus(); + } + EnterKey.iconSource: "image://theme/icon-m-enter-close" EnterKey.onClicked: { resetFocus(); diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index f7e85b3..2082e8d 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -149,11 +149,13 @@ QVariant ChatModel::data(const QModelIndex &index, int role) const return QVariant(); } -void ChatModel::clear() +void ChatModel::clear(bool contentOnly) { LOG("Clearing chat model"); inReload = false; inIncrementalUpdate = false; + searchModeActive = false; + searchQuery.clear(); if (!messages.isEmpty()) { beginResetModel(); qDeleteAll(messages); @@ -161,13 +163,16 @@ void ChatModel::clear() messageIndexMap.clear(); endResetModel(); } - if (!chatInformation.isEmpty()) { - chatInformation.clear(); - emit smallPhotoChanged(); - } - if (chatId) { - chatId = 0; - emit chatIdChanged(); + + if (!contentOnly) { + if (!chatInformation.isEmpty()) { + chatInformation.clear(); + emit smallPhotoChanged(); + } + if (chatId) { + chatId = 0; + emit chatIdChanged(); + } } } @@ -181,6 +186,7 @@ void ChatModel::initialize(const QVariantMap &chatInformation) this->chatId = chatId; this->messages.clear(); this->messageIndexMap.clear(); + this->searchQuery.clear(); endResetModel(); emit chatIdChanged(); emit smallPhotoChanged(); @@ -190,15 +196,21 @@ void ChatModel::initialize(const QVariantMap &chatInformation) void ChatModel::triggerLoadMoreHistory() { if (!this->inIncrementalUpdate && !messages.isEmpty()) { - LOG("Trigger loading older history..."); - this->inIncrementalUpdate = true; - this->tdLibWrapper->getChatHistory(chatId, messages.first()->messageId); + if (searchModeActive) { + LOG("Trigger loading older found messages..."); + this->inIncrementalUpdate = true; + this->tdLibWrapper->searchChatMessages(chatId, searchQuery, messages.first()->messageId); + } else { + LOG("Trigger loading older history..."); + this->inIncrementalUpdate = true; + this->tdLibWrapper->getChatHistory(chatId, messages.first()->messageId); + } } } void ChatModel::triggerLoadMoreFuture() { - if (!this->inIncrementalUpdate && !messages.isEmpty()) { + if (!this->inIncrementalUpdate && !messages.isEmpty() && !searchModeActive) { LOG("Trigger loading newer future..."); this->inIncrementalUpdate = true; this->tdLibWrapper->getChatHistory(chatId, messages.last()->messageId, -49); @@ -214,9 +226,8 @@ QVariantMap ChatModel::getMessage(int index) { if (index >= 0 && index < messages.size()) { return messages.at(index)->messageData; - } else { - return QVariantMap(); } + return QVariantMap(); } int ChatModel::getLastReadMessageIndex() @@ -240,6 +251,20 @@ int ChatModel::getLastReadMessageIndex() } } +void ChatModel::setSearchQuery(const QString newSearchQuery) +{ + if (this->searchQuery != newSearchQuery) { + this->clear(true); + this->searchQuery = newSearchQuery; + this->searchModeActive = !this->searchQuery.isEmpty(); + if (this->searchModeActive) { + this->tdLibWrapper->searchChatMessages(this->chatId, this->searchQuery); + } else { + this->tdLibWrapper->getChatHistory(chatId, this->chatInformation.value(LAST_READ_INBOX_MESSAGE_ID).toLongLong()); + } + } +} + QVariantMap ChatModel::smallPhoto() const { return chatInformation.value(PHOTO).toMap().value(SMALL).toMap(); @@ -253,6 +278,7 @@ qlonglong ChatModel::getChatId() const void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCount) { LOG("Receiving new messages :)" << messages.size()); + LOG("Received while search mode is" << searchModeActive); if (messages.size() == 0) { LOG("No additional messages loaded, notifying chat UI..."); @@ -269,6 +295,7 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCo if (this->isMostRecentMessageLoaded() || this->inIncrementalUpdate) { QList messagesToBeAdded; QListIterator messagesIterator(messages); + while (messagesIterator.hasNext()) { const QVariantMap messageData = messagesIterator.next().toMap(); const qlonglong messageId = messageData.value(ID).toLongLong(); @@ -288,7 +315,11 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCo if (!messagesToBeAdded.isEmpty() && (messagesToBeAdded.size() + messages.size()) < 10 && !inReload) { LOG("Only a few messages received in first call, loading more..."); this->inReload = true; - this->tdLibWrapper->getChatHistory(chatId, messagesToBeAdded.first()->messageId, 0); + if (this->searchModeActive) { + this->tdLibWrapper->searchChatMessages(chatId, searchQuery, messagesToBeAdded.first()->messageId); + } else { + this->tdLibWrapper->getChatHistory(chatId, messagesToBeAdded.first()->messageId, 0); + } } else { LOG("Messages loaded, notifying chat UI..."); this->inReload = false; diff --git a/src/chatmodel.h b/src/chatmodel.h index 9353037..e4ad47f 100644 --- a/src/chatmodel.h +++ b/src/chatmodel.h @@ -37,13 +37,14 @@ public: virtual int rowCount(const QModelIndex&) const override; virtual QVariant data(const QModelIndex &index, int role) const override; - Q_INVOKABLE void clear(); + Q_INVOKABLE void clear(bool contentOnly = false); Q_INVOKABLE void initialize(const QVariantMap &chatInformation); Q_INVOKABLE void triggerLoadMoreHistory(); Q_INVOKABLE void triggerLoadMoreFuture(); Q_INVOKABLE QVariantMap getChatInformation(); Q_INVOKABLE QVariantMap getMessage(int index); Q_INVOKABLE int getLastReadMessageIndex(); + Q_INVOKABLE void setSearchQuery(const QString newSearchQuery); QVariantMap smallPhoto() const; qlonglong getChatId() const; @@ -92,6 +93,8 @@ private: qlonglong chatId; bool inReload; bool inIncrementalUpdate; + bool searchModeActive; + QString searchQuery; }; #endif // CHATMODEL_H diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 42223a1..9df4e89 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -925,6 +925,20 @@ void TDLibWrapper::importContacts(const QVariantList &contacts) this->sendRequest(requestObject); } +void TDLibWrapper::searchChatMessages(const qlonglong &chatId, const QString &query, const qlonglong fromMessageId) +{ + LOG("Searching for messages" << chatId << query); + QVariantMap requestObject; + requestObject.insert(_TYPE, "searchChatMessages"); + requestObject.insert("chat_id", chatId); + requestObject.insert("query", query); + requestObject.insert("from_message_id", fromMessageId); + requestObject.insert("offset", 0); + requestObject.insert("limit", 100); + requestObject.insert(_EXTRA, "searchChatMessages"); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 50eb2fb..5e10408 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -178,6 +178,7 @@ public: Q_INVOKABLE void getSecretChat(qlonglong secretChatId); Q_INVOKABLE void closeSecretChat(qlonglong secretChatId); Q_INVOKABLE void importContacts(const QVariantList &contacts); + Q_INVOKABLE void searchChatMessages(const qlonglong &chatId, const QString &query, const qlonglong fromMessageId = 0); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 5e97037..eb1a53b 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -391,6 +391,14 @@ Close Chat Chat schließen + + Search in Chat + Im Chat suchen + + + Search in chat... + Im Chat suchen... + ChatSelectionPage @@ -1027,8 +1035,8 @@ Neuer Chat - Search a chat... - Einen Chat suchen... + Filter your chats... + Ihre Chats filtern... diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 3ec3f7f..37bbccd 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -391,6 +391,14 @@ Close Chat Close Chat + + Search in Chat + Search in Chat + + + Search in chat... + Search in chat... + ChatSelectionPage @@ -1027,8 +1035,8 @@ New Chat - Search a chat... - + Filter your chats... + Filter your chats... diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 0e89436..016a015 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -381,6 +381,14 @@ Close Chat Cerrar charla + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1016,7 +1024,7 @@ Nueva charla - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 871dce3..617a8b2 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -391,6 +391,14 @@ Close Chat Sulje keskustelu + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1028,7 +1036,7 @@ Uusi keskustelu - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index b44ac76..7c8f35e 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -381,6 +381,14 @@ Close Chat + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1016,7 +1024,7 @@ - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index c19d412..11ec827 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -391,6 +391,14 @@ Close Chat Chiudi chat + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1027,7 +1035,7 @@ Nuova chat - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 68d58b3..d279543 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -401,6 +401,14 @@ Close Chat Zamknij czat + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1038,7 +1046,7 @@ Nowy czat - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 8e1ee21..d76f441 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -401,6 +401,14 @@ Close Chat Закрыть чат + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1038,7 +1046,7 @@ Новый Чат - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 174b53b..8e64333 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -391,6 +391,14 @@ Close Chat Stäng chatten + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1027,7 +1035,7 @@ Ny chatt - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index f3c7d1d..a0b1304 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -381,6 +381,14 @@ Close Chat 关闭对话 + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1016,7 +1024,7 @@ 新对话 - Search a chat... + Filter your chats... diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index cf0789a..abe8bad 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -391,6 +391,14 @@ Close Chat + + Search in Chat + + + + Search in chat... + + ChatSelectionPage @@ -1027,7 +1035,7 @@ - Search a chat... + Filter your chats... From 23641b24a17d6ee19b722e3e3497d88dc38b5ded Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Sun, 27 Dec 2020 00:38:20 +0100 Subject: [PATCH 4/9] Proper height for chat page search field --- qml/pages/ChatPage.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 0387ef8..6765bab 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -779,7 +779,6 @@ Page { id: searchInChatField visible: false width: visible ? parent.width : 0 - height: parent.height placeholderText: qsTr("Search in chat...") active: searchInChatItem.visible canHide: text === "" From 2e970f2003185d75bbb807831b7355ea5807ec8e Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Sun, 27 Dec 2020 23:30:25 +0100 Subject: [PATCH 5/9] Search for public chats... --- harbour-fernschreiber.pro | 1 + qml/pages/OverviewPage.qml | 5 +- qml/pages/SearchChatsPage.qml | 258 ++++++++++++++++++++ src/tdlibreceiver.h | 2 +- src/tdlibwrapper.cpp | 10 + src/tdlibwrapper.h | 1 + translations/harbour-fernschreiber-de.ts | 47 ++++ translations/harbour-fernschreiber-en.ts | 47 ++++ translations/harbour-fernschreiber-es.ts | 47 ++++ translations/harbour-fernschreiber-fi.ts | 47 ++++ translations/harbour-fernschreiber-hu.ts | 47 ++++ translations/harbour-fernschreiber-it.ts | 47 ++++ translations/harbour-fernschreiber-pl.ts | 47 ++++ translations/harbour-fernschreiber-ru.ts | 47 ++++ translations/harbour-fernschreiber-sv.ts | 47 ++++ translations/harbour-fernschreiber-zh_CN.ts | 47 ++++ translations/harbour-fernschreiber.ts | 47 ++++ 17 files changed, 792 insertions(+), 2 deletions(-) create mode 100644 qml/pages/SearchChatsPage.qml diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index dc12009..f751a28 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -84,6 +84,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/pages/AboutPage.qml \ qml/pages/PollCreationPage.qml \ qml/pages/PollResultsPage.qml \ + qml/pages/SearchChatsPage.qml \ qml/pages/SettingsPage.qml \ qml/pages/VideoPage.qml \ rpm/harbour-fernschreiber.changes \ diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index cbb7775..4c24d69 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -230,6 +230,10 @@ Page { text: qsTr("Settings") onClicked: pageStack.push(Qt.resolvedUrl("../pages/SettingsPage.qml")) } + MenuItem { + text: qsTr("Search Chats") + onClicked: pageStack.push(Qt.resolvedUrl("../pages/SearchChatsPage.qml")) + } MenuItem { text: qsTr("New Chat") onClicked: pageStack.push(Qt.resolvedUrl("../pages/NewChatPage.qml")) @@ -285,7 +289,6 @@ Page { width: visible ? ( parent.width - pageStatus.width ) : 0 height: pageHeader.height placeholderText: qsTr("Filter your chats...") - active: searchHeaderItem.visible canHide: text === "" onTextChanged: { diff --git a/qml/pages/SearchChatsPage.qml b/qml/pages/SearchChatsPage.qml new file mode 100644 index 0000000..1bd590c --- /dev/null +++ b/qml/pages/SearchChatsPage.qml @@ -0,0 +1,258 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import WerkWolf.Fernschreiber 1.0 +import "../components" +import "../js/debug.js" as Debug +import "../js/twemoji.js" as Emoji +import "../js/functions.js" as Functions + +Page { + id: searchChatsPage + allowedOrientations: Orientation.All + + function resetFocus() { + publicChatsSearchField.focus = false; + searchChatsPage.focus = true; + } + + Timer { + id: searchPublicChatsTimer + interval: 800 + running: false + repeat: false + onTriggered: { + Debug.log("Searching for '" + publicChatsSearchField.text + "'"); + tdLibWrapper.searchPublicChats(publicChatsSearchField.text); + searchChatsPage.isLoading = true; + } + } + + Connections { + target: tdLibWrapper + onChatsReceived: { + searchChatsPage.isLoading = false; + Debug.log(JSON.stringify(chats)); + chatsFound = chats; + } + } + + property bool isLoading: false; + property var chatsFound; + readonly property var ownUserId: tdLibWrapper.getUserInformation().id; + + SilicaFlickable { + id: searchChatsContainer + contentHeight: searchChatsPage.height + anchors.fill: parent + + Column { + id: searchChatsPageColumn + width: searchChatsPage.width + height: searchChatsPage.height + + PageHeader { + id: searchChatsPageHeader + title: qsTr("Search Chats") + } + + Item { + id: publicChatsItem + + width: searchChatsPageColumn.width + height: searchChatsPageColumn.height - searchChatsPageHeader.height + + Column { + + width: parent.width + height: parent.height + + SearchField { + id: publicChatsSearchField + width: parent.width + placeholderText: qsTr("Search a chat...") + focus: true + + onTextChanged: { + searchPublicChatsTimer.restart(); + } + + EnterKey.iconSource: "image://theme/icon-m-enter-close" + EnterKey.onClicked: { + resetFocus(); + } + + } + + SilicaListView { + id: searchChatsListView + clip: true + width: parent.width + height: parent.height - publicChatsSearchField.height + visible: !searchChatsPage.isLoading + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + model: searchChatsPage.chatsFound.chat_ids + + ViewPlaceholder { + y: Theme.paddingLarge + enabled: searchChatsListView.count === 0 + text: publicChatsSearchField.text.length < 5 ? qsTr("Enter your query to start searching (at least 5 characters needed)") : qsTr("No chats found.") + } + + delegate: Item { + id: foundChatListDelegate + width: parent.width + height: foundChatListItem.height + + property var foundChatInformation: tdLibWrapper.getChat(modelData); + property var relatedInformation; + property bool isPrivateChat: false; + property bool isBasicGroup: false; + property bool isSupergroup: false; + + Component.onCompleted: { + switch (foundChatInformation.type["@type"]) { + case "chatTypePrivate": + relatedInformation = tdLibWrapper.getUserInformation(foundChatInformation.type.user_id); + foundChatListItem.prologSecondaryText.text = qsTr("Private Chat"); + foundChatListItem.secondaryText.text = "@" + ( relatedInformation.username !== "" ? relatedInformation.username : relatedInformation.user_id ); + tdLibWrapper.getUserFullInfo(foundChatInformation.type.user_id); + isPrivateChat = true; + break; + case "chatTypeBasicGroup": + relatedInformation = tdLibWrapper.getBasicGroup(foundChatInformation.type.basic_group_id); + foundChatListItem.prologSecondaryText.text = qsTr("Group"); + tdLibWrapper.getGroupFullInfo(foundChatInformation.type.basic_group_id, false); + isBasicGroup = true; + break; + case "chatTypeSupergroup": + relatedInformation = tdLibWrapper.getSuperGroup(foundChatInformation.type.supergroup_id); + if (relatedInformation.is_channel) { + foundChatListItem.prologSecondaryText.text = qsTr("Channel"); + } else { + foundChatListItem.prologSecondaryText.text = qsTr("Group"); + } + tdLibWrapper.getGroupFullInfo(foundChatInformation.type.supergroup_id, true); + isSupergroup = true; + break; + } + } + + Connections { + target: tdLibWrapper + onUserFullInfoUpdated: { + if (foundChatListDelegate.isPrivateChat && userId.toString() === foundChatListDelegate.foundChatInformation.type.user_id.toString()) { + foundChatListItem.tertiaryText.text = Emoji.emojify(userFullInfo.bio, foundChatListItem.tertiaryText.font.pixelSize, "../js/emoji/"); + } + } + onUserFullInfoReceived: { + if (foundChatListDelegate.isPrivateChat && userFullInfo["@extra"].toString() === foundChatListDelegate.foundChatInformation.type.user_id.toString()) { + foundChatListItem.tertiaryText.text = Emoji.emojify(userFullInfo.bio, foundChatListItem.tertiaryText.font.pixelSize, "../js/emoji/"); + } + } + + onBasicGroupFullInfoUpdated: { + if (foundChatListDelegate.isBasicGroup && groupId.toString() === foundChatListDelegate.foundChatInformation.type.basic_group_id.toString()) { + foundChatListItem.secondaryText.text = qsTr("%1 members").arg(Number(groupFullInfo.members.length).toLocaleString(Qt.locale(), "f", 0)); + foundChatListItem.tertiaryText.text = Emoji.emojify(groupFullInfo.description, foundChatListItem.tertiaryText.font.pixelSize, "../js/emoji/"); + } + } + onBasicGroupFullInfoReceived: { + if (foundChatListDelegate.isBasicGroup && groupId.toString() === foundChatListDelegate.foundChatInformation.type.basic_group_id.toString()) { + foundChatListItem.secondaryText.text = qsTr("%1 members").arg(Number(groupFullInfo.members.length).toLocaleString(Qt.locale(), "f", 0)); + foundChatListItem.tertiaryText.text = Emoji.emojify(groupFullInfo.description, foundChatListItem.tertiaryText.font.pixelSize, "../js/emoji/"); + } + } + + onSupergroupFullInfoUpdated: { + if (foundChatListDelegate.isSupergroup && groupId.toString() === foundChatListDelegate.foundChatInformation.type.supergroup_id.toString()) { + if (foundChatListDelegate.relatedInformation.is_channel) { + foundChatListItem.secondaryText.text = qsTr("%1 subscribers").arg(Number(groupFullInfo.member_count).toLocaleString(Qt.locale(), "f", 0)); + } else { + foundChatListItem.secondaryText.text = qsTr("%1 members").arg(Number(groupFullInfo.member_count).toLocaleString(Qt.locale(), "f", 0)); + } + foundChatListItem.tertiaryText.text = Emoji.emojify(groupFullInfo.description, foundChatListItem.tertiaryText.font.pixelSize, "../js/emoji/"); + } + } + onSupergroupFullInfoReceived: { + if (foundChatListDelegate.isSupergroup && groupId.toString() === foundChatListDelegate.foundChatInformation.type.supergroup_id.toString()) { + if (foundChatListDelegate.relatedInformation.is_channel) { + foundChatListItem.secondaryText.text = qsTr("%1 subscribers").arg(Number(groupFullInfo.member_count).toLocaleString(Qt.locale(), "f", 0)); + } else { + foundChatListItem.secondaryText.text = qsTr("%1 members").arg(Number(groupFullInfo.member_count).toLocaleString(Qt.locale(), "f", 0)); + } + foundChatListItem.tertiaryText.text = Emoji.emojify(groupFullInfo.description, foundChatListItem.tertiaryText.font.pixelSize, "../js/emoji/"); + } + } + } + + PhotoTextsListItem { + id: foundChatListItem + + pictureThumbnail { + photoData: typeof foundChatInformation.photo.small !== "undefined" ? foundChatInformation.photo.small : {} + } + width: parent.width + + primaryText.text: Emoji.emojify(foundChatInformation.title, primaryText.font.pixelSize, "../js/emoji/") + tertiaryText.maximumLineCount: 1 + + onClicked: { + pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), { "chatInformation" : foundChatInformation }); + } + } + } + + VerticalScrollDecorator {} + } + + } + + Column { + + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + visible: searchChatsPage.isLoading + width: parent.width + height: loadingLabel.height + loadingBusyIndicator.height + Theme.paddingMedium + + spacing: Theme.paddingMedium + + anchors.verticalCenter: parent.verticalCenter + + InfoLabel { + id: loadingLabel + text: qsTr("Searching chats...") + } + + BusyIndicator { + id: loadingBusyIndicator + anchors.horizontalCenter: parent.horizontalCenter + running: searchChatsPage.isLoading + size: BusyIndicatorSize.Large + } + } + + } + + } + } +} diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index aae67bc..6a3068d 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -74,7 +74,7 @@ signals: void stickerSet(const QVariantMap &stickerSet); void chatMembers(const QString &extra, const QVariantList &members, int totalMembers); void userFullInfo(const QVariantMap &userFullInfo); - void userFullInfoUpdated(const QString &userId,const QVariantMap &userFullInfo); + void userFullInfoUpdated(const QString &userId, const QVariantMap &userFullInfo); void basicGroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo); void basicGroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo); void supergroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo); diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index eb76c7a..6192505 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -951,6 +951,16 @@ void TDLibWrapper::searchChatMessages(const qlonglong &chatId, const QString &qu this->sendRequest(requestObject); } +void TDLibWrapper::searchPublicChats(const QString &query) +{ + LOG("Searching public chats" << query); + QVariantMap requestObject; + requestObject.insert(_TYPE, "searchPublicChats"); + requestObject.insert("query", query); + requestObject.insert(_EXTRA, "searchPublicChats"); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index ee808db..cf8053a 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -180,6 +180,7 @@ public: Q_INVOKABLE void closeSecretChat(qlonglong secretChatId); Q_INVOKABLE void importContacts(const QVariantList &contacts); Q_INVOKABLE void searchChatMessages(const qlonglong &chatId, const QString &query, const qlonglong fromMessageId = 0); + Q_INVOKABLE void searchPublicChats(const QString &query); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index eb1a53b..cc375b2 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -1038,6 +1038,10 @@ Filter your chats... Ihre Chats filtern... + + Search Chats + Chats suchen + PinnedMessageItem @@ -1232,6 +1236,49 @@ + + SearchChatsPage + + No chats found. + Keine Chats gefunden. + + + Searching chats... + Suche Chats... + + + Private Chat + Privater Chat + + + Group + Gruppe + + + Channel + Kanal + + + %1 members + %1 Mitglied + + + %1 subscribers + %1 Abonnent + + + Search Chats + Chats suchen + + + Search a chat... + Einen Chat suchen... + + + Enter your query to start searching (at least 5 characters needed) + Geben Sie Ihre Anfrage ein, um die Suche zu starten (mindestens 5 Zeichen benötigt) + + SettingsPage diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 37bbccd..900d55b 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -1038,6 +1038,10 @@ Filter your chats... Filter your chats... + + Search Chats + Search Chats + PinnedMessageItem @@ -1232,6 +1236,49 @@ + + SearchChatsPage + + No chats found. + No chats found. + + + Searching chats... + Searching chats... + + + Private Chat + Private Chat + + + Group + Group + + + Channel + Channel + + + %1 members + %1 member + + + %1 subscribers + %1 subscriber + + + Search Chats + Search Chats + + + Search a chat... + Search a chat... + + + Enter your query to start searching (at least 5 characters needed) + Enter your query to start searching (at least 5 characters needed) + + SettingsPage diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 016a015..f86dab6 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -1027,6 +1027,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1213,6 +1217,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + Privado + + + Group + + + + Channel + + + + %1 members + %1 miembros + + + %1 subscribers + %1 suscriptores + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 617a8b2..d6f435b 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -1039,6 +1039,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1233,6 +1237,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + Yksityinen keskustelu + + + Group + + + + Channel + + + + %1 members + %1 jäsen + + + %1 subscribers + %1 tilaaja + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 7c8f35e..6942ca8 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -1027,6 +1027,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1213,6 +1217,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + + + + Group + + + + Channel + + + + %1 members + %1 tag + + + %1 subscribers + %1 feliratkozott + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 11ec827..bb1740c 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -1038,6 +1038,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1232,6 +1236,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + Chat privata + + + Group + + + + Channel + + + + %1 members + %1 membro + + + %1 subscribers + %1 abbonato + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index d279543..2bfbaf1 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -1049,6 +1049,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1251,6 +1255,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + Prywatny czat + + + Group + + + + Channel + + + + %1 members + %1 członek + + + %1 subscribers + %1 subskrybent + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index d76f441..a3ee0c4 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -1049,6 +1049,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1251,6 +1255,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + Приватный Чат + + + Group + + + + Channel + + + + %1 members + %1 участников + + + %1 subscribers + %1 подписчиков + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 8e64333..95bb2ff 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -1038,6 +1038,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1232,6 +1236,49 @@ Valt av: + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + Privat chatt + + + Group + + + + Channel + + + + %1 members + %1 medlem + + + %1 subscribers + %1 prenumerant + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index a0b1304..f7113f7 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -1027,6 +1027,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1213,6 +1217,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + 个人对话 + + + Group + + + + Channel + + + + %1 members + %1 位成员 + + + %1 subscribers + %1 位订阅者 + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index abe8bad..c382b0a 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -1038,6 +1038,10 @@ Filter your chats... + + Search Chats + + PinnedMessageItem @@ -1232,6 +1236,49 @@ + + SearchChatsPage + + No chats found. + + + + Searching chats... + + + + Private Chat + + + + Group + + + + Channel + + + + %1 members + %1 member + + + %1 subscribers + %1 subscriber + + + Search Chats + + + + Search a chat... + + + + Enter your query to start searching (at least 5 characters needed) + + + SettingsPage From 225eb7689922eb0ba3dfae8fad342e98e6858db9 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Mon, 28 Dec 2020 14:35:27 +0100 Subject: [PATCH 6/9] Fix crash on incoming message deletions & minor other fixes --- qml/components/AudioPreview.qml | 8 ++++---- qml/pages/SearchChatsPage.qml | 4 ++++ src/chatmodel.cpp | 35 ++++++++++++++++++++++----------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/qml/components/AudioPreview.qml b/qml/components/AudioPreview.qml index 3901f6b..4c660cb 100644 --- a/qml/components/AudioPreview.qml +++ b/qml/components/AudioPreview.qml @@ -64,9 +64,9 @@ Item { audioType = ( audioData['@type'] === "voiceNote" ) ? "voice" : "audio"; audioFileId = audioData[audioType].id; if (typeof audioData.album_cover_thumbnail !== "undefined") { - previewFileId = audioData.album_cover_thumbnail.photo.id; - if (audioData.album_cover_thumbnail.photo.local.is_downloading_completed) { - placeholderImage.source = audioData.album_cover_thumbnail.photo.local.path; + previewFileId = audioData.album_cover_thumbnail.file.id; + if (audioData.album_cover_thumbnail.file.local.is_downloading_completed) { + placeholderImage.source = audioData.album_cover_thumbnail.file.local.path; } else { tdLibWrapper.downloadFile(previewFileId); } @@ -94,7 +94,7 @@ Item { if (typeof audioData === "object") { if (fileInformation.local.is_downloading_completed) { if (fileId === previewFileId) { - audioData.thumbnail.photo = fileInformation; + audioData.album_cover_thumbnail.file = fileInformation; placeholderImage.source = fileInformation.local.path; } if (fileId === audioFileId) { diff --git a/qml/pages/SearchChatsPage.qml b/qml/pages/SearchChatsPage.qml index 1bd590c..82fe385 100644 --- a/qml/pages/SearchChatsPage.qml +++ b/qml/pages/SearchChatsPage.qml @@ -52,6 +52,10 @@ Page { Debug.log(JSON.stringify(chats)); chatsFound = chats; } + onErrorReceived: { + searchChatsPage.isLoading = false; + Functions.handleErrorMessage(code, message); + } } property bool isLoading: false; diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index 4179db6..5d37916 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -480,27 +480,40 @@ void ChatModel::handleMessagesDeleted(qlonglong chatId, const QList & if (chatId == this->chatId) { const int count = messageIds.size(); LOG(count << "messages in this chat were deleted..."); - int firstDeleted = -1, lastDeleted = -2; - for (int i = 0; i < count; i++) { - const int pos = messageIndexMap.value(messageIds.at(i), -1); - if (pos >= 0) { - if (pos == lastDeleted + 1) { - lastDeleted = pos; // Extend the current range + + int firstPosition = count, lastPosition = count; + for (int i = (count - 1); i > -1; i--) { + const int position = messageIndexMap.value(messageIds.at(i), -1); + if (position >= 0) { + // We found at least one message in our list that needs to be deleted + if (lastPosition == count) { + lastPosition = position; + } + if (firstPosition == count) { + firstPosition = position; + } + if (position < (firstPosition - 1)) { + // Some gap in between, can remove previous range and reset positions + removeRange(firstPosition, lastPosition); + firstPosition = lastPosition = position; } else { - removeRange(firstDeleted, lastDeleted); - firstDeleted = lastDeleted = pos; // Start new range + // No gap in between, extend the range and continue loop + firstPosition = position; } } } - // Handle the last (and likely the only) range - removeRange(firstDeleted, lastDeleted); + // After all elements have been processed, there may be one last range to remove + // But only if we found at least one item to remove + if (firstPosition != count && lastPosition != count) { + removeRange(firstPosition, lastPosition); + } } } void ChatModel::removeRange(int firstDeleted, int lastDeleted) { if (firstDeleted >= 0 && firstDeleted <= lastDeleted) { - LOG("Removing range" << firstDeleted << "..." << lastDeleted); + LOG("Removing range" << firstDeleted << "..." << lastDeleted << "| current messages size" << messages.size()); beginRemoveRows(QModelIndex(), firstDeleted, lastDeleted); for (int i = firstDeleted; i <= lastDeleted; i++) { MessageData *message = messages.at(i); From 72fd008dfc556332e1578e7b472157502c3c0bff Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Mon, 28 Dec 2020 17:12:21 +0100 Subject: [PATCH 7/9] Disable some stuff that is not needed in search mode --- qml/pages/ChatPage.qml | 22 +++++++++++++--------- src/chatmodel.cpp | 2 +- src/tdlibwrapper.cpp | 4 ++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 7754eaf..8fe3eda 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -480,7 +480,7 @@ Page { chatView.lastReadSentIndex = lastReadSentIndex; chatView.scrollToIndex(modelIndex); chatPage.loading = false; - if (modelIndex >= (chatView.count - 10)) { + if (chatOverviewItem.visible && modelIndex >= (chatView.count - 10)) { chatView.inCooldown = true; chatModel.triggerLoadMoreFuture(); } @@ -489,6 +489,8 @@ Page { Debug.log("[ChatPage] Chat content quite small..."); viewMessageTimer.queueViewMessage(chatView.count - 1); } + + chatViewCooldownTimer.restart(); } onNewMessageReceived: { if (chatView.manuallyScrolledToBottom || message.sender.user_id === chatPage.myUserId) { @@ -499,7 +501,7 @@ Page { onUnreadCountUpdated: { Debug.log("[ChatPage] Unread count updated, new count: ", unreadCount); chatInformation.unread_count = unreadCount; - chatUnreadMessagesCountBackground.visible = ( !chatPage.loading && unreadCount > 0 ); + chatUnreadMessagesItem.visible = ( !chatPage.loading && chatInformation.unread_count > 0 && chatOverviewItem.visible ); chatUnreadMessagesCount.text = unreadCount > 99 ? "99+" : unreadCount; } onLastReadSentMessageUpdated: { @@ -509,7 +511,7 @@ Page { onMessagesIncrementalUpdate: { Debug.log("Incremental update received. View now has ", chatView.count, " messages, view is on index ", modelIndex, ", own messages were read before index ", lastReadSentIndex); chatView.lastReadSentIndex = lastReadSentIndex; - chatViewCooldownTimer.start(); + chatViewCooldownTimer.restart(); } onNotificationSettingsUpdated: { chatInformation = chatModel.getChatInformation(); @@ -649,7 +651,7 @@ Page { MenuItem { id: searchInChatMenuItem - visible: !chatPage.isSecretChat + visible: !chatPage.isSecretChat && chatOverviewItem.visible onClicked: { // This automatically shows the search field as well chatOverviewItem.visible = false; @@ -773,7 +775,7 @@ Page { width: parent.width - chatPictureThumbnail.width - Theme.paddingMedium height: searchInChatField.height anchors.bottom: parent.bottom - anchors.bottomMargin: chatPage.isPortrait ? Theme.paddingMedium : Theme.paddingSmall + anchors.bottomMargin: chatPage.isPortrait ? Theme.paddingSmall : 0 SearchField { id: searchInChatField @@ -885,7 +887,7 @@ Page { function handleScrollPositionChanged() { Debug.log("Current position: ", chatView.contentY); - if (chatInformation.unread_count > 0) { + if (chatOverviewItem.visible && chatInformation.unread_count > 0) { var bottomIndex = chatView.indexAt(chatView.contentX, ( chatView.contentY + chatView.height - Theme.horizontalPageMargin )); if (bottomIndex > -1) { viewMessageTimer.queueViewMessage(bottomIndex) @@ -905,12 +907,13 @@ Page { } onContentYChanged: { + Debug.log("In Cooldown: " + chatView.inCooldown); if (!chatPage.loading && !chatView.inCooldown) { if (chatView.indexAt(chatView.contentX, chatView.contentY) < 10) { Debug.log("[ChatPage] Trying to get older history items..."); chatView.inCooldown = true; chatModel.triggerLoadMoreHistory(); - } else if (chatView.indexAt(chatView.contentX, chatView.contentY) > ( count - 10)) { + } else if (chatOverviewItem.visible && chatView.indexAt(chatView.contentX, chatView.contentY) > ( count - 10)) { Debug.log("[ChatPage] Trying to get newer history items..."); chatView.inCooldown = true; chatModel.triggerLoadMoreFuture(); @@ -1046,12 +1049,13 @@ Page { anchors.rightMargin: Theme.paddingMedium anchors.bottom: parent.bottom anchors.bottomMargin: Theme.paddingMedium + visible: !chatPage.loading && chatInformation.unread_count > 0 && chatOverviewItem.visible Rectangle { id: chatUnreadMessagesCountBackground color: Theme.highlightBackgroundColor anchors.fill: parent radius: width / 2 - visible: !chatPage.loading && chatInformation.unread_count > 0 + visible: chatUnreadMessagesItem.visible } Text { @@ -1060,7 +1064,7 @@ Page { font.bold: true color: Theme.primaryColor anchors.centerIn: chatUnreadMessagesCountBackground - visible: chatUnreadMessagesCountBackground.visible + visible: chatUnreadMessagesItem.visible text: chatInformation.unread_count > 99 ? "99+" : chatInformation.unread_count } MouseArea { diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index 5d37916..72d994b 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -353,7 +353,7 @@ void ChatModel::handleNewMessageReceived(qlonglong chatId, const QVariantMap &me { const qlonglong messageId = message.value(ID).toLongLong(); if (chatId == this->chatId && !messageIndexMap.contains(messageId)) { - if (this->isMostRecentMessageLoaded()) { + if (this->isMostRecentMessageLoaded() && !this->searchModeActive) { LOG("New message received for this chat"); QList messagesToBeAdded; messagesToBeAdded.append(new MessageData(message, messageId)); diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 6192505..7a29cc7 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -939,14 +939,14 @@ void TDLibWrapper::importContacts(const QVariantList &contacts) void TDLibWrapper::searchChatMessages(const qlonglong &chatId, const QString &query, const qlonglong fromMessageId) { - LOG("Searching for messages" << chatId << query); + LOG("Searching for messages" << chatId << query << fromMessageId); QVariantMap requestObject; requestObject.insert(_TYPE, "searchChatMessages"); requestObject.insert("chat_id", chatId); requestObject.insert("query", query); requestObject.insert("from_message_id", fromMessageId); requestObject.insert("offset", 0); - requestObject.insert("limit", 100); + requestObject.insert("limit", 50); requestObject.insert(_EXTRA, "searchChatMessages"); this->sendRequest(requestObject); } From 2f52a87e2b7d9c11b2bd10c1e827128c07e2d4a0 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Mon, 28 Dec 2020 19:40:27 +0100 Subject: [PATCH 8/9] Remove debug log for cooldown --- qml/pages/ChatPage.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 8fe3eda..ab24711 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -907,7 +907,6 @@ Page { } onContentYChanged: { - Debug.log("In Cooldown: " + chatView.inCooldown); if (!chatPage.loading && !chatView.inCooldown) { if (chatView.indexAt(chatView.contentX, chatView.contentY) < 10) { Debug.log("[ChatPage] Trying to get older history items..."); From 283466ae95314eca3661cfed8b11445d2f2843b2 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Tue, 29 Dec 2020 09:12:57 +0100 Subject: [PATCH 9/9] Merging should be done right... :/ --- src/tdlibwrapper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index b538879..883658e 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -958,6 +958,7 @@ void TDLibWrapper::searchPublicChats(const QString &query) requestObject.insert(_TYPE, "searchPublicChats"); requestObject.insert("query", query); requestObject.insert(_EXTRA, "searchPublicChats"); + this->sendRequest(requestObject); } void TDLibWrapper::readAllChatMentions(qlonglong chatId)