Fix some bugs in new chats search.

This commit is contained in:
John Preston 2024-05-19 12:05:32 +04:00
parent dd5643ac67
commit 6a8edefc87
6 changed files with 188 additions and 231 deletions

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "dialogs/dialogs_inner_widget.h"
#include "dialogs/dialogs_three_state_icon.h"
#include "dialogs/ui/chat_search_tabs.h"
#include "dialogs/ui/dialogs_layout.h"
#include "dialogs/ui/dialogs_stories_content.h"
#include "dialogs/ui/dialogs_video_userpic.h"
@ -747,6 +748,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
p.fillRect(dialogsClip, currentBg());
}
} else if (_state == WidgetState::Filtered) {
auto top = 0;
if (!_hashtagResults.empty()) {
auto from = floorclamp(r.y(), st::mentionHeight, 0, _hashtagResults.size());
auto to = ceilclamp(r.y() + r.height(), st::mentionHeight, 0, _hashtagResults.size());
@ -791,6 +793,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
p.drawText(htagleft + firstwidth, st::mentionTop + st::mentionFont->ascent, second);
}
p.translate(0, st::mentionHeight);
top += st::mentionHeight;
}
}
}
@ -800,7 +803,9 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
auto to = std::min(
filteredIndex(r.y() + r.height() - skip) + 1,
int(_filterResults.size()));
p.translate(0, filteredHeight(from));
const auto height = filteredHeight(from);
p.translate(0, height);
top += height;
for (; from < to; ++from) {
const auto selected = isPressed()
? (from == _filteredPressed)
@ -808,6 +813,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
const auto row = _filterResults[from].row;
paintRow(row, selected, !activeEntry.fullId);
p.translate(0, row->height());
top += row->height();
}
}
@ -817,11 +823,13 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
p.setPen(st::searchedBarFg);
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), tr::lng_search_global_results(tr::now));
p.translate(0, st::searchedBarHeight);
top += st::searchedBarHeight;
auto skip = peerSearchOffset();
auto from = floorclamp(r.y() - skip, st::dialogsRowHeight, 0, _peerSearchResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _peerSearchResults.size());
p.translate(0, from * st::dialogsRowHeight);
top += from * st::dialogsRowHeight;
if (from < _peerSearchResults.size()) {
const auto activePeer = activeEntry.key.peer();
for (; from < to; ++from) {
@ -844,6 +852,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
.paused = videoPaused,
});
p.translate(0, st::dialogsRowHeight);
top += st::dialogsRowHeight;
}
}
}
@ -857,29 +866,15 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
.paused = videoPaused,
});
p.translate(0, searchInChatSkip());
if (_waitingForSearch && _searchResults.empty()) {
p.fillRect(
0,
0,
fullWidth,
st::searchedBarHeight,
st::searchedBarBg);
p.setFont(st::searchedBarFont);
p.setPen(st::searchedBarFg);
p.drawTextLeft(
st::searchedBarPosition.x(),
st::searchedBarPosition.y(),
width(),
tr::lng_dlg_search_for_messages(tr::now));
p.translate(0, st::searchedBarHeight);
top += searchInChatSkip();
if (_searchResults.empty()) {
p.fillRect(0, 0, fullWidth, st::lineWidth, st::shadowFg);
}
}
const auto showUnreadInSearchResults = uniqueSearchResults();
if (!_waitingForSearch || !_searchResults.empty()) {
const auto text = _searchResults.empty()
? tr::lng_search_no_results(tr::now)
: showUnreadInSearchResults
if (!_searchResults.empty()) {
const auto text = showUnreadInSearchResults
? u"Search results"_q
: tr::lng_search_found_results(
tr::now,
@ -890,11 +885,13 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
p.setPen(st::searchedBarFg);
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), text);
p.translate(0, st::searchedBarHeight);
top += st::searchedBarHeight;
auto skip = searchedOffset();
auto from = floorclamp(r.y() - skip, _st->height, 0, _searchResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, _st->height, 0, _searchResults.size());
p.translate(0, from * _st->height);
top += from * _st->height;
if (from < _searchResults.size()) {
for (; from < to; ++from) {
const auto &result = _searchResults[from];
@ -920,6 +917,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
.displayUnreadInfo = showUnreadInSearchResults,
});
p.translate(0, _st->height);
top += _st->height;
}
}
}
@ -1127,10 +1125,11 @@ void InnerWidget::paintSearchInChat(
auto top = 0;
if (_searchTags) {
const auto height = _searchTags->height();
top += st::dialogsSearchTagBottom;
p.fillRect(0, top, width(), height, currentBg());
const auto position = QPoint(_searchTagsLeft, 0);
const auto position = QPoint(_searchTagsLeft, top);
_searchTags->paint(p, position, context.now, context.paused);
top += height;
top += height - st::dialogsSearchTagBottom;
}
p.setFont(st::searchedBarFont);
auto fullRect = QRect(0, top, width(), height - top);
@ -1279,7 +1278,9 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
_lastMousePosition = globalPosition;
_lastRowLocalMouseX = local.x();
const auto tagBase = QPoint(_searchTagsLeft, searchInChatOffset());
const auto tagBase = QPoint(
_searchTagsLeft,
searchInChatOffset() + st::dialogsSearchTagBottom);
const auto tagPoint = local - tagBase;
const auto inTags = _searchTags
&& QRect(
@ -1895,7 +1896,7 @@ void InnerWidget::moveCancelSearchButtons() {
st::columnMinimalWidthLeft - _narrowWidth);
const auto left = widthForCancelButton - st::dialogsSearchInSkip - _cancelSearchFromUser->width();
const auto top = (st::dialogsSearchInHeight - st::dialogsCancelSearchInPeer.height) / 2;
const auto skip = st::searchedBarHeight + (_searchTags ? _searchTags->height() : 0);
const auto skip = (_searchTags ? _searchTags->height() : 0);
_cancelSearchFromUser->moveToLeft(left, skip + top);
}
@ -2460,6 +2461,74 @@ void InnerWidget::applySearchState(SearchState state) {
withSameQuery.query = _searchState.query;
const auto otherChanged = (_searchState != withSameQuery);
const auto ignoreInChat = (state.tab == ChatSearchTab::MyMessages)
|| (state.tab == ChatSearchTab::PublicPosts);
const auto sublist = ignoreInChat ? nullptr : state.inChat.sublist();
const auto peer = ignoreInChat
? nullptr
: sublist
? session().user().get()
: state.inChat.peer();
if (const auto migrateFrom = peer ? peer->migrateFrom() : nullptr) {
_searchInMigrated = peer->owner().history(migrateFrom);
} else {
_searchInMigrated = nullptr;
}
if (peer && peer->isSelf()) {
const auto reactions = &peer->owner().reactions();
_searchTags = std::make_unique<SearchTags>(
&peer->owner(),
reactions->myTagsValue(sublist),
state.tags);
_searchTags->selectedChanges(
) | rpl::start_with_next([=](std::vector<Data::ReactionId> &&list) {
_searchState.tags = std::move(list);
}, _searchTags->lifetime());
_searchTags->repaintRequests() | rpl::start_with_next([=] {
const auto height = _searchTags->height();
update(0, searchInChatOffset(), width(), height);
}, _searchTags->lifetime());
_searchTags->menuRequests(
) | rpl::start_with_next([=](Data::ReactionId id) {
HistoryView::ShowTagInListMenu(
&_menu,
_lastMousePosition.value_or(QCursor::pos()),
this,
id,
_controller);
}, _searchTags->lifetime());
_searchTags->heightValue() | rpl::skip(
1
) | rpl::start_with_next([=] {
refresh();
moveCancelSearchButtons();
}, _searchTags->lifetime());
} else {
_searchTags = nullptr;
state.tags.clear();
}
_searchFromShown = ignoreInChat
? nullptr
: sublist
? sublist->peer().get()
: state.fromPeer;
if (state.inChat) {
onHashtagFilterUpdate(QStringView());
}
if (_searchFromShown) {
_cancelSearchFromUser->show();
_searchFromUserUserpic = _searchFromShown->createUserpicView();
} else {
_cancelSearchFromUser->hide();
_searchFromUserUserpic = {};
}
refreshSearchInChatLabel();
moveCancelSearchButtons();
_searchState = std::move(state);
auto newFilter = _searchState.query;
const auto mentionsSearch = (newFilter == u"@"_q);
@ -2569,7 +2638,9 @@ InnerWidget::~InnerWidget() {
}
void InnerWidget::clearSearchResults(bool clearPeerSearchResults) {
if (clearPeerSearchResults) _peerSearchResults.clear();
if (clearPeerSearchResults) {
_peerSearchResults.clear();
}
_searchResults.clear();
_searchResultsLifetime.destroy();
_searchResultsHistories.clear();
@ -2807,7 +2878,8 @@ void InnerWidget::searchReceived(
SearchRequestType type,
int fullCount) {
const auto uniquePeers = uniqueSearchResults();
if (type == SearchRequestType::FromStart || type == SearchRequestType::PeerFromStart) {
if (type == SearchRequestType::FromStart
|| type == SearchRequestType::PeerFromStart) {
clearSearchResults(false);
}
const auto isMigratedSearch = (type == SearchRequestType::MigratedFromStart)
@ -3066,81 +3138,6 @@ bool InnerWidget::hasFilteredResults() const {
return !_filterResults.empty() && _hashtagResults.empty();
}
void InnerWidget::searchInChat(
Key key,
PeerData *from,
std::vector<Data::ReactionId> tags) {
_searchInMigrated = nullptr;
const auto sublist = key.sublist();
const auto peer = sublist ? session().user().get() : key.peer();
if (peer) {
if (const auto migrateTo = peer->migrateTo()) {
const auto to = peer->owner().history(migrateTo);
return searchInChat(to, from, tags);
} else if (const auto migrateFrom = peer->migrateFrom()) {
_searchInMigrated = peer->owner().history(migrateFrom);
}
if (peer->isSelf()) {
const auto reactions = &peer->owner().reactions();
_searchTags = std::make_unique<SearchTags>(
&peer->owner(),
reactions->myTagsValue(sublist),
tags);
_searchTags->selectedChanges(
) | rpl::start_with_next([=](std::vector<Data::ReactionId> &&list) {
_searchState.tags = std::move(list);
}, _searchTags->lifetime());
_searchTags->repaintRequests() | rpl::start_with_next([=] {
const auto height = _searchTags->height();
update(0, searchInChatOffset(), width(), height);
}, _searchTags->lifetime());
_searchTags->menuRequests(
) | rpl::start_with_next([=](Data::ReactionId id) {
HistoryView::ShowTagInListMenu(
&_menu,
_lastMousePosition.value_or(QCursor::pos()),
this,
id,
_controller);
}, _searchTags->lifetime());
_searchTags->heightValue() | rpl::skip(
1
) | rpl::start_with_next([=] {
refresh();
moveCancelSearchButtons();
}, _searchTags->lifetime());
} else {
_searchTags = nullptr;
_searchState.tags.clear();
}
} else {
_searchTags = nullptr;
_searchState.tags.clear();
}
_searchState.inChat = key;
_searchState.fromPeer = from;
_searchFromShown = key.sublist() ? key.sublist()->peer().get() : from;
if (_searchState.inChat) {
onHashtagFilterUpdate(QStringView());
}
if (_searchFromShown) {
_cancelSearchFromUser->show();
_searchFromUserUserpic = _searchFromShown->createUserpicView();
} else {
_cancelSearchFromUser->hide();
_searchFromUserUserpic = {};
}
if (_searchState.inChat || _searchState.fromPeer) {
refreshSearchInChatLabel();
}
moveCancelSearchButtons();
}
auto InnerWidget::searchTagsChanges() const
-> rpl::producer<std::vector<Data::ReactionId>> {
return _searchTags

View file

@ -146,10 +146,6 @@ public:
[[nodiscard]] bool hasFilteredResults() const;
void applySearchState(SearchState state);
void searchInChat(
Key key,
PeerData *from,
std::vector<Data::ReactionId> tags);
[[nodiscard]] auto searchTagsChanges() const
-> rpl::producer<std::vector<Data::ReactionId>>;
@ -386,6 +382,7 @@ private:
const Ui::Text::String &text) const;
void refreshSearchInChatLabel();
void repaintSearchResult(int index);
void paintEmpty(QPainter &p, int top);
Ui::VideoUserpic *validateVideoUserpic(not_null<Row*> row);
Ui::VideoUserpic *validateVideoUserpic(not_null<History*> history);

View file

@ -375,7 +375,7 @@ Widget::Widget(
_search->changes(
) | rpl::start_with_next([=] {
applySearchUpdate();
crl::on_main(this, [=] { applySearchUpdate(); });
}, _search->lifetime());
_search->submits(
@ -524,7 +524,7 @@ Widget::Widget(
void Widget::chosenRow(const ChosenRow &row) {
storiesToggleExplicitExpand(false);
if (!currentSearchQuery().isEmpty()) {
if (!_searchState.query.isEmpty()) {
if (const auto history = row.key.history()) {
session().recentPeers().bump(history->peer);
}
@ -1240,6 +1240,7 @@ void Widget::updateSearchTabs() {
applySearchState(std::move(copy));
}, _searchTabs->lifetime());
}
const auto sublist = _searchState.inChat.sublist();
const auto topic = _searchState.inChat.topic();
const auto peer = _searchState.inChat.owningHistory()
? _searchState.inChat.owningHistory()->peer.get()
@ -1258,6 +1259,10 @@ void Widget::updateSearchTabs() {
? Ui::Text::SingleCustomEmoji(
session().data().customEmojiManager().peerUserpicEmojiData(
peer))
: sublist
? Ui::Text::SingleCustomEmoji(
session().data().customEmojiManager().peerUserpicEmojiData(
sublist->peer()))
: TextWithEntities();
const auto myShortLabel = DefaultShortLabel(ChatSearchTab::MyMessages);
const auto publicShortLabel = _searchingHashtag
@ -1275,12 +1280,17 @@ void Widget::updateSearchTabs() {
? ChatSearchTab::ThisPeer
: ChatSearchTab::MyMessages;
}
const auto peerTabType = (peer && peer->isBroadcast())
? ChatSearchPeerTabType::Channel
: (peer && (peer->isChat() || peer->isMegagroup()))
? ChatSearchPeerTabType::Group
: ChatSearchPeerTabType::Chat;
_searchTabs->setTabShortLabels({
{ ChatSearchTab::ThisTopic, topicShortLabel },
{ ChatSearchTab::ThisPeer, peerShortLabel },
{ ChatSearchTab::MyMessages, myShortLabel },
{ ChatSearchTab::PublicPosts, publicShortLabel },
}, _searchState.tab);
}, _searchState.tab, peerTabType);
updateControlsGeometry();
}
@ -1611,7 +1621,7 @@ void Widget::jumpToTop(bool belowPinned) {
if (session().supportMode()) {
return;
}
if ((currentSearchQuery().trimmed().isEmpty() && !_searchState.inChat)) {
if ((_searchState.query.trimmed().isEmpty() && !_searchState.inChat)) {
auto to = 0;
if (belowPinned) {
const auto list = _openedForum
@ -1749,7 +1759,7 @@ void Widget::updateStoriesVisibility() {
|| _childList
|| _searchHasFocus
|| _searchSuggestionsLocked
|| !currentSearchQuery().isEmpty()
|| !_searchState.query.isEmpty()
|| _searchState.inChat
|| _stories->empty();
if (_stories->isHidden() != hidden) {
@ -1952,16 +1962,22 @@ void Widget::loadMoreBlockedByDate() {
bool Widget::search(bool inCache) {
auto result = false;
const auto query = currentSearchQuery().trimmed();
const auto query = _searchState.query.trimmed();
const auto inPeer = searchInPeer();
const auto fromPeer = searchFromPeer();
const auto &inTags = searchInTags();
const auto tab = _searchState.tab;
const auto fromStartType = inPeer
? SearchRequestType::PeerFromStart
: SearchRequestType::FromStart;
const auto skipRequest = (query.isEmpty() && !fromPeer && inTags.empty())
|| (tab == ChatSearchTab::PublicPosts && query.size() < 2);
if (skipRequest) {
cancelSearchRequest();
searchApplyEmpty(fromStartType, 0);
_api.request(base::take(_peerSearchRequest)).cancel();
_peerSearchQuery = QString();
peerSearchApplyEmpty(0);
_api.request(base::take(_topicSearchRequest)).cancel();
return true;
} else if (inCache) {
@ -1981,9 +1997,7 @@ bool Widget::search(bool inCache) {
_searchFull = _searchFullMigrated = false;
cancelSearchRequest();
searchReceived(
(inPeer
? SearchRequestType::PeerFromStart
: SearchRequestType::FromStart),
fromStartType,
i->second,
0);
result = true;
@ -2109,21 +2123,14 @@ bool Widget::search(bool inCache) {
)).done([=](const MTPcontacts_Found &result, mtpRequestId requestId) {
peerSearchReceived(result, requestId);
}).fail([=](const MTP::Error &error, mtpRequestId requestId) {
peopleFailed(error, requestId);
peerSearchFailed(error, requestId);
}).send();
_peerSearchQueries.emplace(_peerSearchRequest, _peerSearchQuery);
}
} else {
_api.request(base::take(_peerSearchRequest)).cancel();
_peerSearchQuery = peerQuery;
_peerSearchFull = true;
peerSearchReceived(
MTP_contacts_found(
MTP_vector<MTPPeer>(0),
MTP_vector<MTPPeer>(0),
MTP_vector<MTPChat>(0),
MTP_vector<MTPUser>(0)),
0);
peerSearchApplyEmpty(0);
}
if (searchForTopicsRequired(peerQuery)) {
if (inCache) {
@ -2170,64 +2177,7 @@ void Widget::showMainMenu() {
void Widget::searchMessages(SearchState state) {
applySearchState(std::move(state));
session().local().saveRecentSearchHashtags(state.query);
//if (_childList) {
// const auto forum = controller()->shownForum().current();
// const auto topic = inChat.topic();
// if ((forum && forum->channel() == inChat.peer())
// || (topic && topic->forum() == forum)) {
// _childList->searchMessages(query, inChat);
// return;
// }
// hideChildList();
//}
//if (_openedFolder) {
// controller()->closeFolder();
//}
//auto tags = Data::SearchTagsFromQuery(query);
//if (!tags.empty()) {
// if (!inChat.sublist()) {
// inChat = session().data().history(session().user());
// }
// query = QString();
//}
//const auto inChatChanged = [&] {
// const auto inPeer = inChat.peer();
// const auto inTopic = inChat.topic();
// if (!inTopic
// && _openedForum
// && inPeer == _openedForum->channel()
// && _subsectionTopBar
// && _subsectionTopBar->searchMode()) {
// return false;
// } else if ((inTopic || (inPeer && !inPeer->isForum()))
// && (inChat == _searchState.inChat)) {
// return false;
// } else if (inPeer) {
// if (const auto to = inPeer->migrateTo()) {
// if (to == _searchState.inChat.peer()
// && !_searchState.inChat.topic()) {
// return false;
// }
// }
// }
// return true;
//}();
//if ((currentSearchQuery() != query)
// || inChatChanged
// || _searchState.tags != tags) {
// if (inChat) {
// cancelSearch();
// setSearchInChat(inChat, nullptr, tags);
// }
// setSearchQuery(query);
// applySearchUpdate(true);
// _searchTimer.cancel();
// searchMessages();
// session().local().saveRecentSearchHashtags(query);
//}
session().local().saveRecentSearchHashtags(_searchState.query);
}
void Widget::searchTopics() {
@ -2574,18 +2524,34 @@ void Widget::peerSearchReceived(
}
}
void Widget::searchApplyEmpty(SearchRequestType type, mtpRequestId id) {
_searchFull = _searchFullMigrated = true;
searchReceived(
type,
MTP_messages_messages(
MTP_vector<MTPMessage>(),
MTP_vector<MTPChat>(),
MTP_vector<MTPUser>()),
id);
}
void Widget::peerSearchApplyEmpty(mtpRequestId id) {
_peerSearchFull = true;
peerSearchReceived(
MTP_contacts_found(
MTP_vector<MTPPeer>(0),
MTP_vector<MTPPeer>(0),
MTP_vector<MTPChat>(0),
MTP_vector<MTPUser>(0)),
id);
}
void Widget::searchFailed(
SearchRequestType type,
const MTP::Error &error,
mtpRequestId requestId) {
if (error.type() == u"SEARCH_QUERY_EMPTY"_q) {
searchReceived(
type,
MTP_messages_messages(
MTP_vector<MTPMessage>(),
MTP_vector<MTPChat>(),
MTP_vector<MTPUser>()),
requestId);
searchApplyEmpty(type, requestId);
} else if (_searchRequest == requestId) {
_searchRequest = 0;
if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) {
@ -2596,8 +2562,8 @@ void Widget::searchFailed(
}
}
void Widget::peopleFailed(const MTP::Error &error, mtpRequestId requestId) {
if (_peerSearchRequest == requestId) {
void Widget::peerSearchFailed(const MTP::Error &error, mtpRequestId id) {
if (_peerSearchRequest == id) {
_peerSearchRequest = 0;
_peerSearchFull = true;
}
@ -2702,40 +2668,33 @@ void Widget::listScrollUpdated() {
}
void Widget::updateCancelSearch() {
const auto shown = !_search->getLastText().isEmpty()
const auto shown = !_searchState.query.isEmpty()
|| (!_searchState.inChat
&& (_searchHasFocus || _searchSuggestionsLocked));
_cancelSearch->toggle(shown, anim::type::normal);
}
bool Widget::fixSearchQuery() {
if (_fixingSearchQuery) {
return false;
}
_fixingSearchQuery = true;
QString Widget::validateSearchQuery() {
const auto query = currentSearchQuery();
if (_searchState.tab == ChatSearchTab::PublicPosts) {
_searchingHashtag = true;
const auto fixed = FixHashtagSearchQuery(
query,
currentSearchQueryCursorPosition());
if (fixed.text != query) {
setSearchQuery(fixed.text, fixed.cursorPosition);
}
_searchingHashtag = true;
return fixed.text;
} else if (_searchingHashtag != IsHashtagSearchQuery(query)) {
_searchingHashtag = !_searchingHashtag;
updateSearchTabs();
}
_fixingSearchQuery = false;
return true;
return query;
}
void Widget::applySearchUpdate() {
if (!fixSearchQuery()) {
return;
}
auto copy = _searchState;
copy.query = currentSearchQuery();
copy.query = validateSearchQuery();
applySearchState(std::move(copy));
if (_chooseFromUser->toggled()
@ -2755,7 +2714,7 @@ void Widget::updateForceDisplayWide() {
controller()->setChatsForceDisplayWide(_searchHasFocus
|| (_subsectionTopBar && _subsectionTopBar->searchHasFocus())
|| _searchSuggestionsLocked
|| !currentSearchQuery().isEmpty()
|| !_searchState.query.isEmpty()
|| _searchState.inChat);
}
@ -2961,12 +2920,10 @@ bool Widget::applySearchState(SearchState state) {
updateSearchTabs();
}
if (queryChanged || inChatChanged) {
updateJumpToDateVisibility();
updateStoriesVisibility();
}
if (fromPeerChanged) {
updateSearchFromVisibility();
}
updateJumpToDateVisibility();
updateSearchFromVisibility();
updateLockUnlockPosition();
if ((state.query.isEmpty() && !state.fromPeer && state.tags.empty())
@ -2988,6 +2945,7 @@ bool Widget::applySearchState(SearchState state) {
controller()->closeFolder();
}
setSearchQuery(_searchState.query);
_inner->applySearchState(_searchState);
if (!_postponeProcessSearchFocusChange) {
@ -3009,7 +2967,7 @@ bool Widget::applySearchState(SearchState state) {
&& _lastSearchText == HistoryView::SwitchToChooseFromQuery()) {
cancelSearch();
}
if (_searchState.inChat || !_search->getLastText().isEmpty()) {
if (_searchState.inChat || !_searchState.query.isEmpty()) {
_search->setFocus();
} else {
setInnerFocus();
@ -3138,7 +3096,7 @@ void Widget::updateLockUnlockVisibility(anim::type animated) {
|| _searchHasFocus
|| _searchSuggestionsLocked
|| _searchState.inChat
|| !_search->getLastText().isEmpty();
|| !_searchState.query.isEmpty();
if (_lockUnlock->toggled() == hidden) {
const auto stories = _stories && !_stories->empty();
_lockUnlock->toggle(
@ -3157,7 +3115,7 @@ void Widget::updateLoadMoreChatsVisibility() {
}
const auto hidden = (_openedFolder != nullptr)
|| (_openedForum != nullptr)
|| !currentSearchQuery().isEmpty();
|| !_searchState.query.isEmpty();
if (_loadMoreChats->isHidden() != hidden) {
_loadMoreChats->setVisible(!hidden);
updateControlsGeometry();
@ -3170,7 +3128,7 @@ void Widget::updateJumpToDateVisibility(bool fast) {
}
_jumpToDate->toggle(
(_searchState.inChat && _search->getLastText().isEmpty()),
(searchInPeer() && _searchState.query.isEmpty()),
fast ? anim::type::instant : anim::type::normal);
}
@ -3617,6 +3575,10 @@ void Widget::clearSearchField() {
}
void Widget::setSearchQuery(const QString &query, int cursorPosition) {
if (query.isEmpty()) {
clearSearchField();
return;
}
if (cursorPosition < 0) {
cursorPosition = query.size();
}
@ -3666,7 +3628,6 @@ bool Widget::cancelSearch() {
_lastSearchPeer = nullptr;
_lastSearchId = _lastSearchMigratedId = 0;
_inner->clearFilter();
clearSearchField();
applySearchState(std::move(updatedState));
if (_suggestions && clearSearchFocus) {
setInnerFocus(true);

View file

@ -232,7 +232,7 @@ private:
void fullSearchRefreshOn(rpl::producer<> events);
void updateCancelSearch();
bool fixSearchQuery();
[[nodiscard]] QString validateSearchQuery();
void applySearchUpdate();
void refreshLoadMoreButton(bool mayBlock, bool isBlocked);
void loadMoreBlockedByDate();
@ -241,7 +241,9 @@ private:
SearchRequestType type,
const MTP::Error &error,
mtpRequestId requestId);
void peopleFailed(const MTP::Error &error, mtpRequestId requestId);
void peerSearchFailed(const MTP::Error &error, mtpRequestId requestId);
void searchApplyEmpty(SearchRequestType type, mtpRequestId id);
void peerSearchApplyEmpty(mtpRequestId id);
void updateForceDisplayWide();
void scrollToDefault(bool verytop = false);
@ -307,7 +309,6 @@ private:
object_ptr<Ui::JumpDownButton> _scrollToTop;
bool _scrollToTopIsShown = false;
bool _forumSearchRequested = false;
bool _fixingSearchQuery = false;
bool _searchingHashtag = false;
Data::Folder *_openedFolder = nullptr;

View file

@ -77,6 +77,10 @@ FixedHashtagSearchQuery FixHashtagSearchQuery(
result += ch;
}
}
if (result.size() == start) {
result += '#';
++cursorPosition;
}
return { result, cursorPosition };
}
@ -123,23 +127,17 @@ ChatSearchTabs::ChatSearchTabs(QWidget *parent, ChatSearchTab active)
ChatSearchTabs::~ChatSearchTabs() = default;
void ChatSearchTabs::setPeerTabType(ChatSearchPeerTabType type) {
_type = type;
const auto i = ranges::find(_list, ChatSearchTab::ThisPeer, &Tab::value);
Assert(i != end(_list));
i->label = TabLabel(ChatSearchTab::ThisPeer, type);
if (!i->shortLabel.empty()) {
refreshTabs(_active.current());
}
}
void ChatSearchTabs::setTabShortLabels(
std::vector<ShortLabel> labels,
ChatSearchTab active) {
ChatSearchTab active,
ChatSearchPeerTabType peerTabType) {
for (const auto &label : labels) {
const auto i = ranges::find(_list, label.tab, &Tab::value);
Assert(i != end(_list));
i->shortLabel = std::move(label.label);
if (i->value == ChatSearchTab::ThisPeer) {
i->label = TabLabel(label.tab, peerTabType);
}
}
refreshTabs(active);
}
@ -175,4 +173,8 @@ int ChatSearchTabs::resizeGetHeight(int newWidth) {
return _tabs->height();
}
void ChatSearchTabs::paintEvent(QPaintEvent *e) {
QPainter(this).fillRect(e->rect(), st::dialogsBg);
}
} // namespace Dialogs

View file

@ -37,8 +37,6 @@ public:
ChatSearchTabs(QWidget *parent, ChatSearchTab active);
~ChatSearchTabs();
void setPeerTabType(ChatSearchPeerTabType type);
// A [custom] emoji to use when there is not enough space for text.
// Only tabs with available short labels are shown.
struct ShortLabel {
@ -47,7 +45,8 @@ public:
};
void setTabShortLabels(
std::vector<ShortLabel> labels,
ChatSearchTab active);
ChatSearchTab active,
ChatSearchPeerTabType peerTabType);
[[nodiscard]] rpl::producer<ChatSearchTab> tabChanges() const;
@ -60,13 +59,13 @@ private:
void refreshTabs(ChatSearchTab active);
int resizeGetHeight(int newWidth) override;
void paintEvent(QPaintEvent *e) override;
const std::unique_ptr<Ui::SettingsSlider> _tabs;
const std::unique_ptr<Ui::PlainShadow> _shadow;
std::vector<Tab> _list;
rpl::variable<ChatSearchTab> _active;
ChatSearchPeerTabType _type = {};
};