Add archived results in chats search.

This commit is contained in:
John Preston 2019-04-22 22:18:57 +04:00
parent 40532e32ab
commit 01d5589594
8 changed files with 99 additions and 133 deletions

View File

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_folder.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "lang/lang_keys.h"
@ -235,9 +236,7 @@ void ChatsListBoxController::prepare() {
}
Auth().data().chatsListChanges(
) | rpl::filter([=](Data::Folder *folder) {
return !folder;
}) | rpl::start_with_next([=] {
) | rpl::start_with_next([=] {
rebuildRows();
}, lifetime());
@ -267,6 +266,10 @@ void ChatsListBoxController::rebuildRows() {
}
}
added += appendList(Auth().data().chatsList()->indexed());
const auto id = Data::Folder::kId;
if (const auto folder = Auth().data().folderLoaded(id)) {
added += appendList(folder->chatsList()->indexed());
}
added += appendList(Auth().data().contactsNoChatsList());
if (!wasEmpty && added > 0) {
// Place dialogs list before contactsNoDialogs list.

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "data/data_folder.h"
#include "history/history.h"
#include "dialogs/dialogs_indexed_list.h"
#include "auth_session.h"
@ -1060,7 +1061,6 @@ void AddSpecialBoxSearchController::addChatsContacts() {
}
return true;
};
const auto getSmallestIndex = [&](not_null<Dialogs::IndexedList*> list)
-> const Dialogs::List* {
if (list->empty()) {
@ -1079,17 +1079,12 @@ void AddSpecialBoxSearchController::addChatsContacts() {
}
return result;
};
const auto dialogsIndex = getSmallestIndex(
_peer->owner().chatsList()->indexed());
const auto contactsIndex = getSmallestIndex(
_peer->owner().contactsNoChatsList());
const auto filterAndAppend = [&](const Dialogs::List *list) {
if (!list) {
const auto filterAndAppend = [&](not_null<Dialogs::IndexedList*> list) {
const auto index = getSmallestIndex(list);
if (!index) {
return;
}
for (const auto row : *list) {
for (const auto row : *index) {
if (const auto history = row->history()) {
if (const auto user = history->peer->asUser()) {
if (allWordsAreFound(user->nameWords())) {
@ -1099,7 +1094,11 @@ void AddSpecialBoxSearchController::addChatsContacts() {
}
}
};
filterAndAppend(dialogsIndex);
filterAndAppend(contactsIndex);
filterAndAppend(_peer->owner().chatsList()->indexed());
const auto id = Data::Folder::kId;
if (const auto folder = _peer->owner().folderLoaded(id)) {
filterAndAppend(folder->chatsList()->indexed());
}
filterAndAppend(_peer->owner().contactsNoChatsList());
delegate()->peerListSearchRefreshRows();
}

View File

@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "data/data_folder.h"
#include "auth_session.h"
#include "core/application.h"
#include "styles/style_boxes.h"
@ -131,7 +132,7 @@ private:
ShareBox::FilterCallback _filterCallback;
std::unique_ptr<Dialogs::IndexedList> _chatsIndexed;
QString _filter;
std::vector<Dialogs::Row*> _filtered;
std::vector<not_null<Dialogs::Row*>> _filtered;
std::map<not_null<PeerData*>, std::unique_ptr<Chat>> _dataMap;
base::flat_set<not_null<PeerData*>> _selected;
@ -489,19 +490,26 @@ ShareBox::Inner::Inner(
_rowHeight = st::shareRowHeight;
setAttribute(Qt::WA_OpaquePaintEvent);
const auto dialogs = Auth().data().chatsList()->indexed();
const auto self = Auth().user();
if (_filterCallback(self)) {
_chatsIndexed->addToEnd(self->owner().history(self));
}
for (const auto row : dialogs->all()) {
if (const auto history = row->history()) {
if (!history->peer->isSelf()
&& _filterCallback(history->peer)) {
_chatsIndexed->addToEnd(history);
const auto addList = [&](not_null<Dialogs::IndexedList*> list) {
for (const auto row : list->all()) {
if (const auto history = row->history()) {
if (!history->peer->isSelf()
&& _filterCallback(history->peer)) {
_chatsIndexed->addToEnd(history);
}
}
}
};
addList(Auth().data().chatsList()->indexed());
const auto id = Data::Folder::kId;
if (const auto folder = Auth().data().folderLoaded(id)) {
addList(folder->chatsList()->indexed());
}
addList(Auth().data().contactsNoChatsList());
_filter = qsl("a");
updateFilter();
@ -603,7 +611,7 @@ ShareBox::Inner::Chat *ShareBox::Inner::getChatAtIndex(int index) {
return _chatsIndexed->rowAtY(index, 1);
}
return (index < _filtered.size())
? _filtered[index]
? _filtered[index].get()
: nullptr;
}();
if (row) {
@ -944,45 +952,7 @@ void ShareBox::Inner::updateFilter(QString filter) {
if (_filter.isEmpty()) {
refresh();
} else {
QStringList::const_iterator fb = words.cbegin(), fe = words.cend(), fi;
_filtered.clear();
if (!words.isEmpty()) {
const Dialogs::List *toFilter = nullptr;
if (!_chatsIndexed->empty()) {
for (fi = fb; fi != fe; ++fi) {
const auto found = _chatsIndexed->filtered(fi->at(0));
if (!found || found->empty()) {
toFilter = nullptr;
break;
}
if (!toFilter || toFilter->size() > found->size()) {
toFilter = found;
}
}
}
if (toFilter) {
_filtered.reserve(toFilter->size());
for (const auto row : *toFilter) {
const auto &nameWords = row->entry()->chatListNameWords();
auto nb = nameWords.cbegin(), ne = nameWords.cend(), ni = nb;
for (fi = fb; fi != fe; ++fi) {
auto filterName = *fi;
for (ni = nb; ni != ne; ++ni) {
if (ni->startsWith(*fi)) {
break;
}
}
if (ni == ne) {
break;
}
}
if (fi == fe) {
_filtered.push_back(row);
}
}
}
}
_filtered = _chatsIndexed->filtered(words);
refresh();
_searching = true;

View File

@ -983,7 +983,7 @@ void Session::setupUserIsContactViewer() {
if (user->contactStatus() == UserData::ContactStatus::Contact) {
const auto history = user->owner().history(user->id);
_contactsList.addByName(history);
if (!_chatsList.indexed()->contains(history)) {
if (!history->inChatList()) {
_contactsNoChatsList.addByName(history);
}
} else if (const auto history = user->owner().historyLoaded(user)) {

View File

@ -200,6 +200,56 @@ void IndexedList::clear() {
_index.clear();
}
std::vector<not_null<Row*>> IndexedList::filtered(
const QStringList &words) const {
const auto minimal = [&]() -> const Dialogs::List* {
if (empty()) {
return nullptr;
}
auto result = (const Dialogs::List*)nullptr;
for (const auto &word : words) {
if (word.isEmpty()) {
continue;
}
const auto found = filtered(word[0]);
if (!found || found->empty()) {
return nullptr;
} else if (!result || result->size() > found->size()) {
result = found;
}
}
return result;
}();
auto result = std::vector<not_null<Row*>>();
if (!minimal || minimal->empty()) {
return result;
}
result.reserve(minimal->size());
for (const auto row : *minimal) {
const auto &nameWords = row->entry()->chatListNameWords();
const auto found = [&](const QString &word) {
for (const auto &name : nameWords) {
if (name.startsWith(word)) {
return true;
}
}
return false;
};
const auto allFound = [&] {
for (const auto &word : words) {
if (!found(word)) {
return false;
}
}
return true;
}();
if (allFound) {
result.push_back(row);
}
}
return result;
}
IndexedList::~IndexedList() {
clear();
}

View File

@ -47,6 +47,7 @@ public:
const auto i = _index.find(ch);
return (i != _index.end()) ? &i->second : nullptr;
}
std::vector<not_null<Row*>> filtered(const QStringList &words) const;
~IndexedList();

View File

@ -1685,81 +1685,24 @@ void DialogsInner::applyFilterUpdate(QString newFilter, bool force) {
if (_filter.isEmpty() && !_searchFromUser) {
clearFilter();
} else {
QStringList::const_iterator fb = words.cbegin(), fe = words.cend(), fi;
_state = State::Filtered;
_waitingForSearch = true;
_filterResults.clear();
_filterResultsGlobal.clear();
const auto append = [&](not_null<Dialogs::IndexedList*> list) {
const auto results = list->filtered(words);
_filterResults.insert(
end(_filterResults),
begin(results),
end(results));
};
if (!_searchInChat && !words.isEmpty()) {
const Dialogs::List *toFilter = nullptr;
if (const auto list = session().data().chatsList()->indexed(); !list->empty()) {
for (fi = fb; fi != fe; ++fi) {
const auto found = list->filtered(fi->at(0));
if (!found || found->empty()) {
toFilter = nullptr;
break;
}
if (!toFilter || toFilter->size() > found->size()) {
toFilter = found;
}
}
}
const Dialogs::List *toFilterContacts = nullptr;
if (const auto list = session().data().contactsNoChatsList(); !list->empty()) {
for (fi = fb; fi != fe; ++fi) {
const auto found = list->filtered(fi->at(0));
if (!found || found->empty()) {
toFilterContacts = nullptr;
break;
}
if (!toFilterContacts || toFilterContacts->size() > found->size()) {
toFilterContacts = found;
}
}
}
_filterResults.reserve((toFilter ? toFilter->size() : 0)
+ (toFilterContacts ? toFilterContacts->size() : 0));
if (toFilter) {
for (const auto row : *toFilter) {
const auto &nameWords = row->entry()->chatListNameWords();
auto nb = nameWords.cbegin(), ne = nameWords.cend(), ni = nb;
for (fi = fb; fi != fe; ++fi) {
auto filterWord = *fi;
for (ni = nb; ni != ne; ++ni) {
if (ni->startsWith(filterWord)) {
break;
}
}
if (ni == ne) {
break;
}
}
if (fi == fe) {
_filterResults.push_back(row);
}
}
}
if (toFilterContacts) {
for (const auto row : *toFilterContacts) {
const auto &nameWords = row->entry()->chatListNameWords();
auto nb = nameWords.cbegin(), ne = nameWords.cend(), ni = nb;
for (fi = fb; fi != fe; ++fi) {
auto filterWord = *fi;
for (ni = nb; ni != ne; ++ni) {
if (ni->startsWith(filterWord)) {
break;
}
}
if (ni == ne) {
break;
}
}
if (fi == fe) {
_filterResults.push_back(row);
}
}
append(session().data().chatsList()->indexed());
const auto id = Data::Folder::kId;
if (const auto folder = session().data().folderLoaded(id)) {
append(folder->chatsList()->indexed());
}
append(session().data().contactsNoChatsList());
}
refresh(true);
}

View File

@ -316,7 +316,7 @@ private:
bool _hashtagDeleteSelected = false;
bool _hashtagDeletePressed = false;
std::vector<Dialogs::Row*> _filterResults;
std::vector<not_null<Dialogs::Row*>> _filterResults;
base::flat_map<
not_null<PeerData*>,
std::unique_ptr<Dialogs::Row>> _filterResultsGlobal;