Now you can search in a chat...

This commit is contained in:
Sebastian Wolf 2020-12-27 00:16:25 +01:00
parent 461b724d15
commit 19a17ed3f3
No known key found for this signature in database
GPG key ID: CEA9522B5F38A90A
17 changed files with 243 additions and 33 deletions

View file

@ -332,6 +332,14 @@ Page {
return false; return false;
} }
function resetFocus() {
if (searchInChatField.text === "") {
chatOverviewItem.visible = true;
}
searchInChatField.focus = false;
chatPage.focus = true;
}
Timer { Timer {
id: forwardMessagesTimer id: forwardMessagesTimer
interval: 200 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: { Component.onCompleted: {
initializePage(); initializePage();
} }
@ -627,6 +646,17 @@ Page {
} }
text: chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat") 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 { BackgroundItem {
@ -700,6 +730,8 @@ Page {
Item { Item {
id: chatOverviewItem id: chatOverviewItem
opacity: visible ? 1 : 0
Behavior on opacity { FadeAnimation {} }
width: parent.width - chatPictureThumbnail.width - Theme.paddingMedium width: parent.width - chatPictureThumbnail.width - Theme.paddingMedium
height: chatNameText.height + chatStatusText.height height: chatNameText.height + chatStatusText.height
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -732,6 +764,40 @@ Page {
maximumLineCount: 1 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 { PinnedMessageItem {

View file

@ -156,12 +156,14 @@ Page {
} }
function resetFocus() { function resetFocus() {
chatSearchField.focus = false; if (chatSearchField.text === "") {
overviewPage.focus = true;
chatSearchField.visible = false; chatSearchField.visible = false;
pageHeader.visible = true; pageHeader.visible = true;
searchChatButton.visible = overviewPage.connectionState === TelegramAPI.ConnectionReady; searchChatButton.visible = overviewPage.connectionState === TelegramAPI.ConnectionReady;
} }
chatSearchField.focus = false;
overviewPage.focus = true;
}
Connections { Connections {
target: tdLibWrapper target: tdLibWrapper
@ -282,13 +284,18 @@ Page {
Behavior on opacity { FadeAnimation {} } Behavior on opacity { FadeAnimation {} }
width: visible ? ( parent.width - pageStatus.width ) : 0 width: visible ? ( parent.width - pageStatus.width ) : 0
height: pageHeader.height height: pageHeader.height
placeholderText: qsTr("Search a chat...") placeholderText: qsTr("Filter your chats...")
active: searchHeaderItem.visible active: searchHeaderItem.visible
canHide: text === ""
onTextChanged: { onTextChanged: {
searchChatTimer.restart(); searchChatTimer.restart();
} }
onHideClicked: {
resetFocus();
}
EnterKey.iconSource: "image://theme/icon-m-enter-close" EnterKey.iconSource: "image://theme/icon-m-enter-close"
EnterKey.onClicked: { EnterKey.onClicked: {
resetFocus(); resetFocus();

View file

@ -149,11 +149,13 @@ QVariant ChatModel::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
} }
void ChatModel::clear() void ChatModel::clear(bool contentOnly)
{ {
LOG("Clearing chat model"); LOG("Clearing chat model");
inReload = false; inReload = false;
inIncrementalUpdate = false; inIncrementalUpdate = false;
searchModeActive = false;
searchQuery.clear();
if (!messages.isEmpty()) { if (!messages.isEmpty()) {
beginResetModel(); beginResetModel();
qDeleteAll(messages); qDeleteAll(messages);
@ -161,6 +163,8 @@ void ChatModel::clear()
messageIndexMap.clear(); messageIndexMap.clear();
endResetModel(); endResetModel();
} }
if (!contentOnly) {
if (!chatInformation.isEmpty()) { if (!chatInformation.isEmpty()) {
chatInformation.clear(); chatInformation.clear();
emit smallPhotoChanged(); emit smallPhotoChanged();
@ -170,6 +174,7 @@ void ChatModel::clear()
emit chatIdChanged(); emit chatIdChanged();
} }
} }
}
void ChatModel::initialize(const QVariantMap &chatInformation) void ChatModel::initialize(const QVariantMap &chatInformation)
{ {
@ -181,6 +186,7 @@ void ChatModel::initialize(const QVariantMap &chatInformation)
this->chatId = chatId; this->chatId = chatId;
this->messages.clear(); this->messages.clear();
this->messageIndexMap.clear(); this->messageIndexMap.clear();
this->searchQuery.clear();
endResetModel(); endResetModel();
emit chatIdChanged(); emit chatIdChanged();
emit smallPhotoChanged(); emit smallPhotoChanged();
@ -190,15 +196,21 @@ void ChatModel::initialize(const QVariantMap &chatInformation)
void ChatModel::triggerLoadMoreHistory() void ChatModel::triggerLoadMoreHistory()
{ {
if (!this->inIncrementalUpdate && !messages.isEmpty()) { if (!this->inIncrementalUpdate && !messages.isEmpty()) {
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..."); LOG("Trigger loading older history...");
this->inIncrementalUpdate = true; this->inIncrementalUpdate = true;
this->tdLibWrapper->getChatHistory(chatId, messages.first()->messageId); this->tdLibWrapper->getChatHistory(chatId, messages.first()->messageId);
} }
} }
}
void ChatModel::triggerLoadMoreFuture() void ChatModel::triggerLoadMoreFuture()
{ {
if (!this->inIncrementalUpdate && !messages.isEmpty()) { if (!this->inIncrementalUpdate && !messages.isEmpty() && !searchModeActive) {
LOG("Trigger loading newer future..."); LOG("Trigger loading newer future...");
this->inIncrementalUpdate = true; this->inIncrementalUpdate = true;
this->tdLibWrapper->getChatHistory(chatId, messages.last()->messageId, -49); this->tdLibWrapper->getChatHistory(chatId, messages.last()->messageId, -49);
@ -214,9 +226,8 @@ QVariantMap ChatModel::getMessage(int index)
{ {
if (index >= 0 && index < messages.size()) { if (index >= 0 && index < messages.size()) {
return messages.at(index)->messageData; return messages.at(index)->messageData;
} else {
return QVariantMap();
} }
return QVariantMap();
} }
int ChatModel::getLastReadMessageIndex() 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 QVariantMap ChatModel::smallPhoto() const
{ {
return chatInformation.value(PHOTO).toMap().value(SMALL).toMap(); return chatInformation.value(PHOTO).toMap().value(SMALL).toMap();
@ -253,6 +278,7 @@ qlonglong ChatModel::getChatId() const
void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCount) void ChatModel::handleMessagesReceived(const QVariantList &messages, int totalCount)
{ {
LOG("Receiving new messages :)" << messages.size()); LOG("Receiving new messages :)" << messages.size());
LOG("Received while search mode is" << searchModeActive);
if (messages.size() == 0) { if (messages.size() == 0) {
LOG("No additional messages loaded, notifying chat UI..."); 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) { if (this->isMostRecentMessageLoaded() || this->inIncrementalUpdate) {
QList<MessageData*> messagesToBeAdded; QList<MessageData*> messagesToBeAdded;
QListIterator<QVariant> messagesIterator(messages); QListIterator<QVariant> messagesIterator(messages);
while (messagesIterator.hasNext()) { while (messagesIterator.hasNext()) {
const QVariantMap messageData = messagesIterator.next().toMap(); const QVariantMap messageData = messagesIterator.next().toMap();
const qlonglong messageId = messageData.value(ID).toLongLong(); 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) { if (!messagesToBeAdded.isEmpty() && (messagesToBeAdded.size() + messages.size()) < 10 && !inReload) {
LOG("Only a few messages received in first call, loading more..."); LOG("Only a few messages received in first call, loading more...");
this->inReload = true; this->inReload = true;
if (this->searchModeActive) {
this->tdLibWrapper->searchChatMessages(chatId, searchQuery, messagesToBeAdded.first()->messageId);
} else {
this->tdLibWrapper->getChatHistory(chatId, messagesToBeAdded.first()->messageId, 0); this->tdLibWrapper->getChatHistory(chatId, messagesToBeAdded.first()->messageId, 0);
}
} else { } else {
LOG("Messages loaded, notifying chat UI..."); LOG("Messages loaded, notifying chat UI...");
this->inReload = false; this->inReload = false;

View file

@ -37,13 +37,14 @@ public:
virtual int rowCount(const QModelIndex&) const override; virtual int rowCount(const QModelIndex&) const override;
virtual QVariant data(const QModelIndex &index, int role) 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 initialize(const QVariantMap &chatInformation);
Q_INVOKABLE void triggerLoadMoreHistory(); Q_INVOKABLE void triggerLoadMoreHistory();
Q_INVOKABLE void triggerLoadMoreFuture(); Q_INVOKABLE void triggerLoadMoreFuture();
Q_INVOKABLE QVariantMap getChatInformation(); Q_INVOKABLE QVariantMap getChatInformation();
Q_INVOKABLE QVariantMap getMessage(int index); Q_INVOKABLE QVariantMap getMessage(int index);
Q_INVOKABLE int getLastReadMessageIndex(); Q_INVOKABLE int getLastReadMessageIndex();
Q_INVOKABLE void setSearchQuery(const QString newSearchQuery);
QVariantMap smallPhoto() const; QVariantMap smallPhoto() const;
qlonglong getChatId() const; qlonglong getChatId() const;
@ -92,6 +93,8 @@ private:
qlonglong chatId; qlonglong chatId;
bool inReload; bool inReload;
bool inIncrementalUpdate; bool inIncrementalUpdate;
bool searchModeActive;
QString searchQuery;
}; };
#endif // CHATMODEL_H #endif // CHATMODEL_H

View file

@ -925,6 +925,20 @@ void TDLibWrapper::importContacts(const QVariantList &contacts)
this->sendRequest(requestObject); 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) void TDLibWrapper::searchEmoji(const QString &queryString)
{ {
LOG("Searching emoji" << queryString); LOG("Searching emoji" << queryString);

View file

@ -178,6 +178,7 @@ public:
Q_INVOKABLE void getSecretChat(qlonglong secretChatId); Q_INVOKABLE void getSecretChat(qlonglong secretChatId);
Q_INVOKABLE void closeSecretChat(qlonglong secretChatId); Q_INVOKABLE void closeSecretChat(qlonglong secretChatId);
Q_INVOKABLE void importContacts(const QVariantList &contacts); 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 ;)) // Others (candidates for extraction ;))
Q_INVOKABLE void searchEmoji(const QString &queryString); Q_INVOKABLE void searchEmoji(const QString &queryString);

View file

@ -391,6 +391,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Chat schließen</translation> <translation>Chat schließen</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation>Im Chat suchen</translation>
</message>
<message>
<source>Search in chat...</source>
<translation>Im Chat suchen...</translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1027,8 +1035,8 @@
<translation>Neuer Chat</translation> <translation>Neuer Chat</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation>Einen Chat suchen...</translation> <translation>Ihre Chats filtern...</translation>
</message> </message>
</context> </context>
<context> <context>

View file

@ -391,6 +391,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Close Chat</translation> <translation>Close Chat</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation>Search in Chat</translation>
</message>
<message>
<source>Search in chat...</source>
<translation>Search in chat...</translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1027,8 +1035,8 @@
<translation>New Chat</translation> <translation>New Chat</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation>Filter your chats...</translation>
</message> </message>
</context> </context>
<context> <context>

View file

@ -381,6 +381,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Cerrar charla</translation> <translation>Cerrar charla</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1016,7 +1024,7 @@
<translation>Nueva charla</translation> <translation>Nueva charla</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -391,6 +391,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Sulje keskustelu</translation> <translation>Sulje keskustelu</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1028,7 +1036,7 @@
<translation>Uusi keskustelu</translation> <translation>Uusi keskustelu</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -381,6 +381,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1016,7 +1024,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -391,6 +391,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Chiudi chat</translation> <translation>Chiudi chat</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1027,7 +1035,7 @@
<translation>Nuova chat</translation> <translation>Nuova chat</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -401,6 +401,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Zamknij czat</translation> <translation>Zamknij czat</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1038,7 +1046,7 @@
<translation>Nowy czat</translation> <translation>Nowy czat</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -401,6 +401,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Закрыть чат</translation> <translation>Закрыть чат</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1038,7 +1046,7 @@
<translation>Новый Чат</translation> <translation>Новый Чат</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -391,6 +391,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation>Stäng chatten</translation> <translation>Stäng chatten</translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1027,7 +1035,7 @@
<translation>Ny chatt</translation> <translation>Ny chatt</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -381,6 +381,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1016,7 +1024,7 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>

View file

@ -391,6 +391,14 @@
<source>Close Chat</source> <source>Close Chat</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Search in Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search in chat...</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1027,7 +1035,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Filter your chats...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>