mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Implement search in topics / forum messages.
This commit is contained in:
parent
c8ed8e0e5f
commit
88d1a502a5
8 changed files with 357 additions and 103 deletions
|
@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Api {
|
namespace Api {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kSearchPerPage = 50;
|
||||||
|
|
||||||
[[nodiscard]] MessageIdsList HistoryItemsFromTL(
|
[[nodiscard]] MessageIdsList HistoryItemsFromTL(
|
||||||
not_null<Data::Session*> data,
|
not_null<Data::Session*> data,
|
||||||
const QVector<MTPMessage> &messages) {
|
const QVector<MTPMessage> &messages) {
|
||||||
|
@ -94,7 +96,7 @@ void MessagesSearch::searchRequest() {
|
||||||
MTP_int(0), // max_date
|
MTP_int(0), // max_date
|
||||||
MTP_int(_offsetId), // offset_id
|
MTP_int(_offsetId), // offset_id
|
||||||
MTP_int(0), // add_offset
|
MTP_int(0), // add_offset
|
||||||
MTP_int(SearchPerPage),
|
MTP_int(kSearchPerPage),
|
||||||
MTP_int(0), // max_id
|
MTP_int(0), // max_id
|
||||||
MTP_int(0), // min_id
|
MTP_int(0), // min_id
|
||||||
MTP_long(0) // hash
|
MTP_long(0) // hash
|
||||||
|
|
|
@ -20,10 +20,6 @@ enum {
|
||||||
RecentInlineBotsLimit = 10,
|
RecentInlineBotsLimit = 10,
|
||||||
|
|
||||||
AutoSearchTimeout = 900, // 0.9 secs
|
AutoSearchTimeout = 900, // 0.9 secs
|
||||||
SearchPerPage = 50,
|
|
||||||
SearchManyPerPage = 100,
|
|
||||||
LinksOverviewPerPage = 12,
|
|
||||||
MediaOverviewStartPerPage = 5,
|
|
||||||
|
|
||||||
PreloadHeightsCount = 3, // when 3 screens to scroll left make a preload request
|
PreloadHeightsCount = 3, // when 3 screens to scroll left make a preload request
|
||||||
|
|
||||||
|
|
|
@ -2011,12 +2011,16 @@ void InnerWidget::applyFilterUpdate(QString newFilter, bool force) {
|
||||||
end(results));
|
end(results));
|
||||||
};
|
};
|
||||||
if (!_searchInChat && !words.isEmpty()) {
|
if (!_searchInChat && !words.isEmpty()) {
|
||||||
append(session().data().chatsList()->indexed());
|
if (_openedForum) {
|
||||||
const auto id = Data::Folder::kId;
|
append(_openedForum->topicsList()->indexed());
|
||||||
if (const auto folder = session().data().folderLoaded(id)) {
|
} else {
|
||||||
append(folder->chatsList()->indexed());
|
append(session().data().chatsList()->indexed());
|
||||||
|
const auto id = Data::Folder::kId;
|
||||||
|
if (const auto add = session().data().folderLoaded(id)) {
|
||||||
|
append(add->chatsList()->indexed());
|
||||||
|
}
|
||||||
|
append(session().data().contactsNoChatsList());
|
||||||
}
|
}
|
||||||
append(session().data().contactsNoChatsList());
|
|
||||||
}
|
}
|
||||||
refresh(true);
|
refresh(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/event_filter.h"
|
#include "base/event_filter.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/update_checker.h"
|
#include "core/update_checker.h"
|
||||||
|
#include "core/shortcuts.h"
|
||||||
#include "boxes/peer_list_box.h"
|
#include "boxes/peer_list_box.h"
|
||||||
#include "boxes/peers/edit_participants_box.h"
|
#include "boxes/peers/edit_participants_box.h"
|
||||||
#include "window/window_adaptive.h"
|
#include "window/window_adaptive.h"
|
||||||
|
@ -72,8 +73,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Dialogs {
|
namespace Dialogs {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
QString SwitchToChooseFromQuery() {
|
constexpr auto kSearchPerPage = 50;
|
||||||
return qsl("from:");
|
|
||||||
|
[[nodiscard]] QString SwitchToChooseFromQuery() {
|
||||||
|
return u"from:"_q;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -296,12 +299,12 @@ Widget::Widget(
|
||||||
Ui::PostponeCall(this, [=] { listScrollUpdated(); });
|
Ui::PostponeCall(this, [=] { listScrollUpdated(); });
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
QObject::connect(_filter, &Ui::InputField::cancelled, [=] {
|
|
||||||
escape();
|
|
||||||
});
|
|
||||||
QObject::connect(_filter, &Ui::InputField::changed, [=] {
|
QObject::connect(_filter, &Ui::InputField::changed, [=] {
|
||||||
applyFilterUpdate();
|
applyFilterUpdate();
|
||||||
});
|
});
|
||||||
|
QObject::connect(_filter, &Ui::InputField::submitted, [=] {
|
||||||
|
submit();
|
||||||
|
});
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
_filter->rawTextEdit().get(),
|
_filter->rawTextEdit().get(),
|
||||||
&QTextEdit::cursorPositionChanged,
|
&QTextEdit::cursorPositionChanged,
|
||||||
|
@ -339,6 +342,7 @@ Widget::Widget(
|
||||||
});
|
});
|
||||||
|
|
||||||
setupMainMenuToggle();
|
setupMainMenuToggle();
|
||||||
|
setupShortcuts();
|
||||||
|
|
||||||
_searchForNarrowFilters->setClickedCallback([=] { Ui::showChatsList(&session()); });
|
_searchForNarrowFilters->setClickedCallback([=] { Ui::showChatsList(&session()); });
|
||||||
|
|
||||||
|
@ -616,6 +620,29 @@ void Widget::setupMainMenuToggle() {
|
||||||
}, _mainMenuToggle->lifetime());
|
}, _mainMenuToggle->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::setupShortcuts() {
|
||||||
|
Shortcuts::Requests(
|
||||||
|
) | rpl::filter([=] {
|
||||||
|
return isActiveWindow()
|
||||||
|
&& Ui::InFocusChain(this)
|
||||||
|
&& !Ui::isLayerShown()
|
||||||
|
&& !controller()->window().locked();
|
||||||
|
}) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) {
|
||||||
|
using Command = Shortcuts::Command;
|
||||||
|
|
||||||
|
if (controller()->selectingPeer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_openedForum && !controller()->activeChatCurrent()) {
|
||||||
|
request->check(Command::Search) && request->handle([=] {
|
||||||
|
const auto history = _openedForum->forum()->history();
|
||||||
|
controller()->content()->searchInChat(history);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::fullSearchRefreshOn(rpl::producer<> events) {
|
void Widget::fullSearchRefreshOn(rpl::producer<> events) {
|
||||||
std::move(
|
std::move(
|
||||||
events
|
events
|
||||||
|
@ -642,14 +669,14 @@ void Widget::updateControlsVisibility(bool fast) {
|
||||||
_forwardCancel->show();
|
_forwardCancel->show();
|
||||||
}
|
}
|
||||||
if ((_openedFolder || _openedForum) && _filter->hasFocus()) {
|
if ((_openedFolder || _openedForum) && _filter->hasFocus()) {
|
||||||
setFocus();
|
setInnerFocus();
|
||||||
}
|
}
|
||||||
if (_updateTelegram) {
|
if (_updateTelegram) {
|
||||||
_updateTelegram->show();
|
_updateTelegram->show();
|
||||||
}
|
}
|
||||||
_searchControls->setVisible(!_openedFolder && !_openedForum);
|
_searchControls->setVisible(!_openedFolder && !_openedForum);
|
||||||
if (_openedFolder || _openedForum) {
|
if (_openedFolder || _openedForum) {
|
||||||
_folderTopBar->show();
|
_subsectionTopBar->show();
|
||||||
if (_forumTopShadow) {
|
if (_forumTopShadow) {
|
||||||
_forumTopShadow->show();
|
_forumTopShadow->show();
|
||||||
}
|
}
|
||||||
|
@ -694,6 +721,7 @@ void Widget::changeOpenedSubsection(
|
||||||
change();
|
change();
|
||||||
refreshTopBars();
|
refreshTopBars();
|
||||||
updateControlsVisibility(true);
|
updateControlsVisibility(true);
|
||||||
|
_peerSearchRequest = 0;
|
||||||
if (animated == anim::type::normal) {
|
if (animated == anim::type::normal) {
|
||||||
_connecting->setForceHidden(true);
|
_connecting->setForceHidden(true);
|
||||||
_cacheOver = grabForFolderSlideAnimation();
|
_cacheOver = grabForFolderSlideAnimation();
|
||||||
|
@ -721,23 +749,42 @@ void Widget::changeOpenedForum(ChannelData *forum, anim::type animated) {
|
||||||
|
|
||||||
void Widget::refreshTopBars() {
|
void Widget::refreshTopBars() {
|
||||||
if (_openedFolder || _openedForum) {
|
if (_openedFolder || _openedForum) {
|
||||||
if (!_folderTopBar) {
|
if (!_subsectionTopBar) {
|
||||||
_folderTopBar.create(this, controller());
|
_subsectionTopBar.create(this, controller());
|
||||||
|
_subsectionTopBar->searchCancelled(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
escape();
|
||||||
|
}, _subsectionTopBar->lifetime());
|
||||||
|
_subsectionTopBar->searchSubmitted(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
submit();
|
||||||
|
}, _subsectionTopBar->lifetime());
|
||||||
|
_subsectionTopBar->searchQuery(
|
||||||
|
) | rpl::start_with_next([=](QString query) {
|
||||||
|
applyFilterUpdate();
|
||||||
|
}, lifetime());
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
}
|
}
|
||||||
const auto history = _openedForum
|
const auto history = _openedForum
|
||||||
? session().data().history(_openedForum).get()
|
? session().data().history(_openedForum).get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
_folderTopBar->setActiveChat(
|
_subsectionTopBar->setActiveChat(
|
||||||
HistoryView::TopBarWidget::ActiveChat{
|
HistoryView::TopBarWidget::ActiveChat{
|
||||||
.key = (_openedForum
|
.key = (_openedForum
|
||||||
? Dialogs::Key(history)
|
? Dialogs::Key(history)
|
||||||
: Dialogs::Key(_openedFolder)),
|
: Dialogs::Key(_openedFolder)),
|
||||||
.section = Dialogs::EntryState::Section::ChatsList,
|
.section = Dialogs::EntryState::Section::ChatsList,
|
||||||
}, history ? history->sendActionPainter().get() : nullptr);
|
}, history ? history->sendActionPainter().get() : nullptr);
|
||||||
} else {
|
if (_forumSearchRequested) {
|
||||||
_folderTopBar.destroy();
|
_subsectionTopBar->toggleSearch(true, anim::type::instant);
|
||||||
|
}
|
||||||
|
} else if (_subsectionTopBar) {
|
||||||
|
if (_subsectionTopBar->searchHasFocus()) {
|
||||||
|
setFocus();
|
||||||
|
}
|
||||||
|
_subsectionTopBar.destroy();
|
||||||
}
|
}
|
||||||
|
_forumSearchRequested = false;
|
||||||
if (_openedForum) {
|
if (_openedForum) {
|
||||||
_openedForum->updateFull();
|
_openedForum->updateFull();
|
||||||
|
|
||||||
|
@ -857,10 +904,10 @@ void Widget::checkUpdateStatus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::setInnerFocus() {
|
void Widget::setInnerFocus() {
|
||||||
if (_openedFolder || _openedForum) {
|
if (!_openedFolder && !_openedForum) {
|
||||||
setFocus();
|
|
||||||
} else {
|
|
||||||
_filter->setFocus();
|
_filter->setFocus();
|
||||||
|
} else if (!_subsectionTopBar->searchSetFocus()) {
|
||||||
|
setFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,7 +915,7 @@ void Widget::jumpToTop(bool belowPinned) {
|
||||||
if (session().supportMode()) {
|
if (session().supportMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((_filter->getLastText().trimmed().isEmpty() && !_searchInChat)) {
|
if ((currentSearchQuery().trimmed().isEmpty() && !_searchInChat)) {
|
||||||
auto to = 0;
|
auto to = 0;
|
||||||
if (belowPinned) {
|
if (belowPinned) {
|
||||||
const auto list = _openedForum
|
const auto list = _openedForum
|
||||||
|
@ -981,8 +1028,8 @@ void Widget::startSlideAnimation() {
|
||||||
_forwardCancel->hide();
|
_forwardCancel->hide();
|
||||||
}
|
}
|
||||||
_searchControls->hide();
|
_searchControls->hide();
|
||||||
if (_folderTopBar) {
|
if (_subsectionTopBar) {
|
||||||
_folderTopBar->hide();
|
_subsectionTopBar->hide();
|
||||||
}
|
}
|
||||||
if (_forumTopShadow) {
|
if (_forumTopShadow) {
|
||||||
_forumTopShadow->hide();
|
_forumTopShadow->hide();
|
||||||
|
@ -1018,19 +1065,20 @@ void Widget::animationCallback() {
|
||||||
|
|
||||||
updateControlsVisibility(true);
|
updateControlsVisibility(true);
|
||||||
|
|
||||||
if (!_filter->hasFocus()) {
|
if ((!_subsectionTopBar || !_subsectionTopBar->searchHasFocus())
|
||||||
|
&& !_filter->hasFocus()) {
|
||||||
controller()->widget()->setInnerFocus();
|
controller()->widget()->setInnerFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::escape() {
|
void Widget::escape() {
|
||||||
if (controller()->openedFolder().current()) {
|
if (!cancelSearch()) {
|
||||||
controller()->closeFolder();
|
if (controller()->openedFolder().current()) {
|
||||||
} else if (controller()->openedForum().current()) {
|
controller()->closeFolder();
|
||||||
controller()->closeForum();
|
} else if (controller()->openedForum().current()) {
|
||||||
} else if (!cancelSearch()) {
|
controller()->closeForum();
|
||||||
if (controller()->activeChatEntryCurrent().key) {
|
} else if (controller()->activeChatEntryCurrent().key) {
|
||||||
controller()->content()->dialogsCancelled();
|
controller()->content()->dialogsCancelled();
|
||||||
} else {
|
} else {
|
||||||
const auto filters = &session().data().chatsFilters();
|
const auto filters = &session().data().chatsFilters();
|
||||||
|
@ -1047,6 +1095,21 @@ void Widget::escape() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::submit() {
|
||||||
|
if (_inner->chooseRow()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto state = _inner->state();
|
||||||
|
if (state == WidgetState::Default
|
||||||
|
|| (state == WidgetState::Filtered
|
||||||
|
&& (!_inner->waitingForSearch() || _inner->hasFilteredResults()))) {
|
||||||
|
_inner->selectSkip(1);
|
||||||
|
_inner->chooseRow();
|
||||||
|
} else {
|
||||||
|
searchMessages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::refreshLoadMoreButton(bool mayBlock, bool isBlocked) {
|
void Widget::refreshLoadMoreButton(bool mayBlock, bool isBlocked) {
|
||||||
if (!mayBlock) {
|
if (!mayBlock) {
|
||||||
if (_loadMoreChats) {
|
if (_loadMoreChats) {
|
||||||
|
@ -1084,7 +1147,7 @@ void Widget::loadMoreBlockedByDate() {
|
||||||
|
|
||||||
bool Widget::searchMessages(bool searchCache) {
|
bool Widget::searchMessages(bool searchCache) {
|
||||||
auto result = false;
|
auto result = false;
|
||||||
auto q = _filter->getLastText().trimmed();
|
auto q = currentSearchQuery().trimmed();
|
||||||
if (q.isEmpty() && !_searchFromAuthor) {
|
if (q.isEmpty() && !_searchFromAuthor) {
|
||||||
cancelSearchRequest();
|
cancelSearchRequest();
|
||||||
_api.request(base::take(_peerSearchRequest)).cancel();
|
_api.request(base::take(_peerSearchRequest)).cancel();
|
||||||
|
@ -1105,9 +1168,9 @@ bool Widget::searchMessages(bool searchCache) {
|
||||||
_searchFull = _searchFullMigrated = false;
|
_searchFull = _searchFullMigrated = false;
|
||||||
cancelSearchRequest();
|
cancelSearchRequest();
|
||||||
searchReceived(
|
searchReceived(
|
||||||
_searchInChat
|
((_searchInChat || _openedForum)
|
||||||
? SearchRequestType::PeerFromStart
|
? SearchRequestType::PeerFromStart
|
||||||
: SearchRequestType::FromStart,
|
: SearchRequestType::FromStart),
|
||||||
i->second,
|
i->second,
|
||||||
0);
|
0);
|
||||||
result = true;
|
result = true;
|
||||||
|
@ -1118,29 +1181,29 @@ bool Widget::searchMessages(bool searchCache) {
|
||||||
_searchNextRate = 0;
|
_searchNextRate = 0;
|
||||||
_searchFull = _searchFullMigrated = false;
|
_searchFull = _searchFullMigrated = false;
|
||||||
cancelSearchRequest();
|
cancelSearchRequest();
|
||||||
if (const auto peer = _searchInChat.peer()) {
|
if (const auto peer = searchInPeer()) {
|
||||||
|
const auto topic = searchInTopic();
|
||||||
auto &histories = session().data().histories();
|
auto &histories = session().data().histories();
|
||||||
const auto type = Data::Histories::RequestType::History;
|
const auto type = Data::Histories::RequestType::History;
|
||||||
const auto history = session().data().history(peer);
|
const auto history = session().data().history(peer);
|
||||||
_searchInHistoryRequest = histories.sendRequest(history, type, [=](Fn<void()> finish) {
|
_searchInHistoryRequest = histories.sendRequest(history, type, [=](Fn<void()> finish) {
|
||||||
const auto type = SearchRequestType::PeerFromStart;
|
const auto type = SearchRequestType::PeerFromStart;
|
||||||
const auto flags = _searchQueryFrom
|
using Flag = MTPmessages_Search::Flag;
|
||||||
? MTP_flags(MTPmessages_Search::Flag::f_from_id)
|
|
||||||
: MTP_flags(0);
|
|
||||||
_searchRequest = session().api().request(MTPmessages_Search(
|
_searchRequest = session().api().request(MTPmessages_Search(
|
||||||
flags,
|
MTP_flags((topic ? Flag::f_top_msg_id : Flag())
|
||||||
|
| (_searchQueryFrom ? Flag::f_from_id : Flag())),
|
||||||
peer->input,
|
peer->input,
|
||||||
MTP_string(_searchQuery),
|
MTP_string(_searchQuery),
|
||||||
(_searchQueryFrom
|
(_searchQueryFrom
|
||||||
? _searchQueryFrom->input
|
? _searchQueryFrom->input
|
||||||
: MTP_inputPeerEmpty()),
|
: MTP_inputPeerEmpty()),
|
||||||
MTPint(), // top_msg_id
|
MTP_int(topic ? topic->rootId() : 0),
|
||||||
MTP_inputMessagesFilterEmpty(),
|
MTP_inputMessagesFilterEmpty(),
|
||||||
MTP_int(0), // min_date
|
MTP_int(0), // min_date
|
||||||
MTP_int(0), // max_date
|
MTP_int(0), // max_date
|
||||||
MTP_int(0), // offset_id
|
MTP_int(0), // offset_id
|
||||||
MTP_int(0), // add_offset
|
MTP_int(0), // add_offset
|
||||||
MTP_int(SearchPerPage),
|
MTP_int(kSearchPerPage),
|
||||||
MTP_int(0), // max_id
|
MTP_int(0), // max_id
|
||||||
MTP_int(0), // min_id
|
MTP_int(0), // min_id
|
||||||
MTP_long(0) // hash
|
MTP_long(0) // hash
|
||||||
|
@ -1172,7 +1235,7 @@ bool Widget::searchMessages(bool searchCache) {
|
||||||
MTP_int(0),
|
MTP_int(0),
|
||||||
MTP_inputPeerEmpty(),
|
MTP_inputPeerEmpty(),
|
||||||
MTP_int(0),
|
MTP_int(0),
|
||||||
MTP_int(SearchPerPage)
|
MTP_int(kSearchPerPage)
|
||||||
)).done([=](const MTPmessages_Messages &result) {
|
)).done([=](const MTPmessages_Messages &result) {
|
||||||
searchReceived(type, result, _searchRequest);
|
searchReceived(type, result, _searchRequest);
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
@ -1219,7 +1282,7 @@ bool Widget::searchMessages(bool searchCache) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::searchForPeersRequired(const QString &query) const {
|
bool Widget::searchForPeersRequired(const QString &query) const {
|
||||||
if (_searchInChat || query.isEmpty()) {
|
if (_searchInChat || _openedForum || query.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (query[0] != '#');
|
return (query[0] != '#');
|
||||||
|
@ -1238,11 +1301,17 @@ void Widget::showMainMenu() {
|
||||||
void Widget::searchMessages(
|
void Widget::searchMessages(
|
||||||
const QString &query,
|
const QString &query,
|
||||||
Key inChat) {
|
Key inChat) {
|
||||||
auto inChatChanged = [&] {
|
const auto inChatChanged = [&] {
|
||||||
if (inChat == _searchInChat) {
|
const auto inPeer = inChat.peer();
|
||||||
|
const auto inTopic = inChat.topic();
|
||||||
|
if (!inTopic && inPeer == _openedForum) {
|
||||||
|
return false;
|
||||||
|
} else if ((inTopic || (inPeer && !inPeer->isForum()))
|
||||||
|
&& (inChat == _searchInChat)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (const auto inPeer = inChat.peer()) {
|
} else if (const auto inPeer = inChat.peer()) {
|
||||||
if (inPeer->migrateTo() == _searchInChat.peer()) {
|
if (inPeer->migrateTo() == _searchInChat.peer()
|
||||||
|
&& !_searchInChat.topic()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1269,19 +1338,19 @@ void Widget::searchMore() {
|
||||||
if (!_searchFull) {
|
if (!_searchFull) {
|
||||||
auto offsetPeer = _inner->lastSearchPeer();
|
auto offsetPeer = _inner->lastSearchPeer();
|
||||||
auto offsetId = _inner->lastSearchId();
|
auto offsetId = _inner->lastSearchId();
|
||||||
if (const auto peer = _searchInChat.peer()) {
|
if (const auto peer = searchInPeer()) {
|
||||||
auto &histories = session().data().histories();
|
auto &histories = session().data().histories();
|
||||||
|
const auto topic = searchInTopic();
|
||||||
const auto type = Data::Histories::RequestType::History;
|
const auto type = Data::Histories::RequestType::History;
|
||||||
const auto history = session().data().history(peer);
|
const auto history = session().data().history(peer);
|
||||||
_searchInHistoryRequest = histories.sendRequest(history, type, [=](Fn<void()> finish) {
|
_searchInHistoryRequest = histories.sendRequest(history, type, [=](Fn<void()> finish) {
|
||||||
const auto type = offsetId
|
const auto type = offsetId
|
||||||
? SearchRequestType::PeerFromOffset
|
? SearchRequestType::PeerFromOffset
|
||||||
: SearchRequestType::PeerFromStart;
|
: SearchRequestType::PeerFromStart;
|
||||||
auto flags = _searchQueryFrom
|
using Flag = MTPmessages_Search::Flag;
|
||||||
? MTP_flags(MTPmessages_Search::Flag::f_from_id)
|
|
||||||
: MTP_flags(0);
|
|
||||||
_searchRequest = session().api().request(MTPmessages_Search(
|
_searchRequest = session().api().request(MTPmessages_Search(
|
||||||
flags,
|
MTP_flags((topic ? Flag::f_top_msg_id : Flag())
|
||||||
|
| (_searchQueryFrom ? Flag::f_from_id : Flag())),
|
||||||
peer->input,
|
peer->input,
|
||||||
MTP_string(_searchQuery),
|
MTP_string(_searchQuery),
|
||||||
(_searchQueryFrom
|
(_searchQueryFrom
|
||||||
|
@ -1293,7 +1362,7 @@ void Widget::searchMore() {
|
||||||
MTP_int(0), // max_date
|
MTP_int(0), // max_date
|
||||||
MTP_int(offsetId),
|
MTP_int(offsetId),
|
||||||
MTP_int(0), // add_offset
|
MTP_int(0), // add_offset
|
||||||
MTP_int(SearchPerPage),
|
MTP_int(kSearchPerPage),
|
||||||
MTP_int(0), // max_id
|
MTP_int(0), // max_id
|
||||||
MTP_int(0), // min_id
|
MTP_int(0), // min_id
|
||||||
MTP_long(0) // hash
|
MTP_long(0) // hash
|
||||||
|
@ -1331,7 +1400,7 @@ void Widget::searchMore() {
|
||||||
? offsetPeer->input
|
? offsetPeer->input
|
||||||
: MTP_inputPeerEmpty(),
|
: MTP_inputPeerEmpty(),
|
||||||
MTP_int(offsetId),
|
MTP_int(offsetId),
|
||||||
MTP_int(SearchPerPage)
|
MTP_int(kSearchPerPage)
|
||||||
)).done([=](const MTPmessages_Messages &result) {
|
)).done([=](const MTPmessages_Messages &result) {
|
||||||
searchReceived(type, result, _searchRequest);
|
searchReceived(type, result, _searchRequest);
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
@ -1366,7 +1435,7 @@ void Widget::searchMore() {
|
||||||
MTP_int(0), // max_date
|
MTP_int(0), // max_date
|
||||||
MTP_int(offsetMigratedId),
|
MTP_int(offsetMigratedId),
|
||||||
MTP_int(0), // add_offset
|
MTP_int(0), // add_offset
|
||||||
MTP_int(SearchPerPage),
|
MTP_int(kSearchPerPage),
|
||||||
MTP_int(0), // max_id
|
MTP_int(0), // max_id
|
||||||
MTP_int(0), // min_id
|
MTP_int(0), // min_id
|
||||||
MTP_long(0) // hash
|
MTP_long(0) // hash
|
||||||
|
@ -1451,7 +1520,7 @@ void Widget::searchReceived(
|
||||||
|
|
||||||
case mtpc_messages_channelMessages: {
|
case mtpc_messages_channelMessages: {
|
||||||
auto &d = result.c_messages_channelMessages();
|
auto &d = result.c_messages_channelMessages();
|
||||||
if (const auto peer = _searchInChat.peer()) {
|
if (const auto peer = _openedForum ? _openedForum : _searchInChat.peer()) {
|
||||||
if (const auto channel = peer->asChannel()) {
|
if (const auto channel = peer->asChannel()) {
|
||||||
channel->ptsReceived(d.vpts().v);
|
channel->ptsReceived(d.vpts().v);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1642,7 +1711,7 @@ void Widget::applyFilterUpdate(bool force) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto filterText = _filter->getLastText();
|
const auto filterText = currentSearchQuery();
|
||||||
_inner->applyFilterUpdate(filterText, force);
|
_inner->applyFilterUpdate(filterText, force);
|
||||||
if (filterText.isEmpty() && !_searchFromAuthor) {
|
if (filterText.isEmpty() && !_searchFromAuthor) {
|
||||||
clearSearchCache();
|
clearSearchCache();
|
||||||
|
@ -1677,6 +1746,16 @@ void Widget::searchInChat(Key chat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::setSearchInChat(Key chat, PeerData *from) {
|
void Widget::setSearchInChat(Key chat, PeerData *from) {
|
||||||
|
const auto peer = chat.peer();
|
||||||
|
if (const auto forum = peer ? peer->forum() : nullptr) {
|
||||||
|
if (controller()->openedForum().current() == peer) {
|
||||||
|
_subsectionTopBar->toggleSearch(true, anim::type::normal);
|
||||||
|
} else {
|
||||||
|
_forumSearchRequested = true;
|
||||||
|
controller()->openForum(forum->channel());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (chat.folder()) {
|
if (chat.folder()) {
|
||||||
chat = Key();
|
chat = Key();
|
||||||
}
|
}
|
||||||
|
@ -1685,7 +1764,9 @@ void Widget::setSearchInChat(Key chat, PeerData *from) {
|
||||||
if (const auto migrateTo = peer->migrateTo()) {
|
if (const auto migrateTo = peer->migrateTo()) {
|
||||||
return setSearchInChat(peer->owner().history(migrateTo), from);
|
return setSearchInChat(peer->owner().history(migrateTo), from);
|
||||||
} else if (const auto migrateFrom = peer->migrateFrom()) {
|
} else if (const auto migrateFrom = peer->migrateFrom()) {
|
||||||
_searchInMigrated = peer->owner().history(migrateFrom);
|
if (!chat.topic()) {
|
||||||
|
_searchInMigrated = peer->owner().history(migrateFrom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto searchInPeerUpdated = (_searchInChat != chat);
|
const auto searchInPeerUpdated = (_searchInChat != chat);
|
||||||
|
@ -1816,7 +1897,7 @@ void Widget::updateLoadMoreChatsVisibility() {
|
||||||
}
|
}
|
||||||
const auto hidden = (_openedFolder != nullptr)
|
const auto hidden = (_openedFolder != nullptr)
|
||||||
|| (_openedForum != nullptr)
|
|| (_openedForum != nullptr)
|
||||||
|| !_filter->getLastText().isEmpty();
|
|| !currentSearchQuery().isEmpty();
|
||||||
if (_loadMoreChats->isHidden() != hidden) {
|
if (_loadMoreChats->isHidden() != hidden) {
|
||||||
_loadMoreChats->setVisible(!hidden);
|
_loadMoreChats->setVisible(!hidden);
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
|
@ -1866,8 +1947,8 @@ void Widget::updateControlsGeometry() {
|
||||||
auto filterWidth = qMax(width(), st::columnMinimalWidthLeft) - filterLeft - filterRight;
|
auto filterWidth = qMax(width(), st::columnMinimalWidthLeft) - filterLeft - filterRight;
|
||||||
auto filterAreaHeight = st::topBarHeight;
|
auto filterAreaHeight = st::topBarHeight;
|
||||||
_searchControls->setGeometry(0, filterAreaTop, width(), filterAreaHeight);
|
_searchControls->setGeometry(0, filterAreaTop, width(), filterAreaHeight);
|
||||||
if (_folderTopBar) {
|
if (_subsectionTopBar) {
|
||||||
_folderTopBar->setGeometry(_searchControls->geometry());
|
_subsectionTopBar->setGeometry(_searchControls->geometry());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto filterTop = (filterAreaHeight - _filter->height()) / 2;
|
auto filterTop = (filterAreaHeight - _filter->height()) / 2;
|
||||||
|
@ -1983,25 +2064,16 @@ RowDescriptor Widget::resolveChatPrevious(RowDescriptor from) const {
|
||||||
|
|
||||||
void Widget::keyPressEvent(QKeyEvent *e) {
|
void Widget::keyPressEvent(QKeyEvent *e) {
|
||||||
if (e->key() == Qt::Key_Escape) {
|
if (e->key() == Qt::Key_Escape) {
|
||||||
if (_openedForum) {
|
escape();
|
||||||
controller()->closeForum();
|
//if (_openedForum) {
|
||||||
} else if (_openedFolder) {
|
// controller()->closeForum();
|
||||||
controller()->closeFolder();
|
//} else if (_openedFolder) {
|
||||||
} else {
|
// controller()->closeFolder();
|
||||||
e->ignore();
|
//} else {
|
||||||
}
|
// e->ignore();
|
||||||
|
//}
|
||||||
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
||||||
if (!_inner->chooseRow()) {
|
submit();
|
||||||
const auto state = _inner->state();
|
|
||||||
if (state == WidgetState::Default
|
|
||||||
|| (state == WidgetState::Filtered
|
|
||||||
&& (!_inner->waitingForSearch() || _inner->hasFilteredResults()))) {
|
|
||||||
_inner->selectSkip(1);
|
|
||||||
_inner->chooseRow();
|
|
||||||
} else {
|
|
||||||
searchMessages();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e->key() == Qt::Key_Down) {
|
} else if (e->key() == Qt::Key_Down) {
|
||||||
_inner->selectSkip(1);
|
_inner->selectSkip(1);
|
||||||
} else if (e->key() == Qt::Key_Up) {
|
} else if (e->key() == Qt::Key_Up) {
|
||||||
|
@ -2082,22 +2154,51 @@ void Widget::cancelSearchRequest() {
|
||||||
base::take(_searchInHistoryRequest));
|
base::take(_searchInHistoryRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PeerData *Widget::searchInPeer() const {
|
||||||
|
return _openedForum ? _openedForum : _searchInChat.peer();
|
||||||
|
}
|
||||||
|
|
||||||
|
Data::ForumTopic *Widget::searchInTopic() const {
|
||||||
|
return _searchInChat.topic();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Widget::currentSearchQuery() const {
|
||||||
|
return _subsectionTopBar
|
||||||
|
? _subsectionTopBar->searchQueryCurrent()
|
||||||
|
: _filter->getLastText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::clearSearchField() {
|
||||||
|
if (_subsectionTopBar) {
|
||||||
|
_subsectionTopBar->searchClear();
|
||||||
|
} else {
|
||||||
|
_filter->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Widget::cancelSearch() {
|
bool Widget::cancelSearch() {
|
||||||
bool clearing = !_filter->getLastText().isEmpty();
|
bool clearing = !currentSearchQuery().isEmpty();
|
||||||
cancelSearchRequest();
|
cancelSearchRequest();
|
||||||
if (_searchInChat && !clearing) {
|
if (!clearing && _searchInChat) {
|
||||||
if (controller()->adaptive().isOneColumn()) {
|
if (controller()->adaptive().isOneColumn()) {
|
||||||
if (const auto peer = _searchInChat.peer()) {
|
if (const auto topic = _searchInChat.topic()) {
|
||||||
Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
|
//controller()->showTopic(topic); // #TODO forum search
|
||||||
|
} else if (const auto peer = _searchInChat.peer()) {
|
||||||
|
controller()->showPeer(peer, ShowAtUnreadMsgId);
|
||||||
} else {
|
} else {
|
||||||
Unexpected("Empty key in cancelSearch().");
|
Unexpected("Empty key in cancelSearch().");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setSearchInChat(Key());
|
setSearchInChat(Key());
|
||||||
clearing = true;
|
clearing = true;
|
||||||
|
} else if (!clearing
|
||||||
|
&& _subsectionTopBar
|
||||||
|
&& _subsectionTopBar->toggleSearch(false, anim::type::normal)) {
|
||||||
|
setFocus();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
_inner->clearFilter();
|
_inner->clearFilter();
|
||||||
_filter->clear();
|
clearSearchField();
|
||||||
applyFilterUpdate();
|
applyFilterUpdate();
|
||||||
return clearing;
|
return clearing;
|
||||||
}
|
}
|
||||||
|
@ -2108,8 +2209,10 @@ void Widget::cancelSearchInChat() {
|
||||||
if (_searchInChat) {
|
if (_searchInChat) {
|
||||||
if (isOneColumn
|
if (isOneColumn
|
||||||
&& !controller()->selectingPeer()
|
&& !controller()->selectingPeer()
|
||||||
&& _filter->getLastText().trimmed().isEmpty()) {
|
&& currentSearchQuery().trimmed().isEmpty()) {
|
||||||
if (const auto peer = _searchInChat.peer()) {
|
if (const auto topic = _searchInChat.topic()) {
|
||||||
|
// #TODO forum search
|
||||||
|
} else if (const auto peer = _searchInChat.peer()) {
|
||||||
Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
|
Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
|
||||||
} else {
|
} else {
|
||||||
Unexpected("Empty key in cancelSearchInPeer().");
|
Unexpected("Empty key in cancelSearchInPeer().");
|
||||||
|
|
|
@ -126,6 +126,8 @@ private:
|
||||||
void filterCursorMoved();
|
void filterCursorMoved();
|
||||||
void completeHashtag(QString tag);
|
void completeHashtag(QString tag);
|
||||||
|
|
||||||
|
[[nodiscard]] QString currentSearchQuery() const;
|
||||||
|
void clearSearchField();
|
||||||
bool searchMessages(bool searchCache = false);
|
bool searchMessages(bool searchCache = false);
|
||||||
void needSearchMessages();
|
void needSearchMessages();
|
||||||
|
|
||||||
|
@ -138,12 +140,16 @@ private:
|
||||||
const MTPcontacts_Found &result,
|
const MTPcontacts_Found &result,
|
||||||
mtpRequestId requestId);
|
mtpRequestId requestId);
|
||||||
void escape();
|
void escape();
|
||||||
|
void submit();
|
||||||
void cancelSearchRequest();
|
void cancelSearchRequest();
|
||||||
|
[[nodiscard]] PeerData *searchInPeer() const;
|
||||||
|
[[nodiscard]] Data::ForumTopic *searchInTopic() const;
|
||||||
|
|
||||||
void setupSupportMode();
|
void setupSupportMode();
|
||||||
void setupConnectingWidget();
|
void setupConnectingWidget();
|
||||||
void setupMainMenuToggle();
|
void setupMainMenuToggle();
|
||||||
void setupDownloadBar();
|
void setupDownloadBar();
|
||||||
|
void setupShortcuts();
|
||||||
bool searchForPeersRequired(const QString &query) const;
|
bool searchForPeersRequired(const QString &query) const;
|
||||||
void setSearchInChat(Key chat, PeerData *from = nullptr);
|
void setSearchInChat(Key chat, PeerData *from = nullptr);
|
||||||
void showCalendar();
|
void showCalendar();
|
||||||
|
@ -192,7 +198,7 @@ private:
|
||||||
|
|
||||||
object_ptr<Ui::IconButton> _forwardCancel = { nullptr };
|
object_ptr<Ui::IconButton> _forwardCancel = { nullptr };
|
||||||
object_ptr<Ui::RpWidget> _searchControls;
|
object_ptr<Ui::RpWidget> _searchControls;
|
||||||
object_ptr<HistoryView::TopBarWidget> _folderTopBar = { nullptr } ;
|
object_ptr<HistoryView::TopBarWidget> _subsectionTopBar = { nullptr } ;
|
||||||
object_ptr<Ui::IconButton> _mainMenuToggle;
|
object_ptr<Ui::IconButton> _mainMenuToggle;
|
||||||
object_ptr<Ui::IconButton> _searchForNarrowFilters;
|
object_ptr<Ui::IconButton> _searchForNarrowFilters;
|
||||||
object_ptr<Ui::InputField> _filter;
|
object_ptr<Ui::InputField> _filter;
|
||||||
|
@ -221,8 +227,9 @@ private:
|
||||||
ShowAnimation _showAnimationType = ShowAnimation::External;
|
ShowAnimation _showAnimationType = ShowAnimation::External;
|
||||||
|
|
||||||
Ui::Animations::Simple _scrollToTopShown;
|
Ui::Animations::Simple _scrollToTopShown;
|
||||||
bool _scrollToTopIsShown = false;
|
|
||||||
object_ptr<Ui::HistoryDownButton> _scrollToTop;
|
object_ptr<Ui::HistoryDownButton> _scrollToTop;
|
||||||
|
bool _scrollToTopIsShown = false;
|
||||||
|
bool _forumSearchRequested = false;
|
||||||
|
|
||||||
Data::Folder *_openedFolder = nullptr;
|
Data::Folder *_openedFolder = nullptr;
|
||||||
ChannelData *_openedForum = nullptr;
|
ChannelData *_openedForum = nullptr;
|
||||||
|
|
|
@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/core_settings.h"
|
#include "core/core_settings.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "ui/widgets/input_fields.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
||||||
#include "ui/effects/radial_animation.h"
|
#include "ui/effects/radial_animation.h"
|
||||||
|
@ -426,12 +427,16 @@ void TopBarWidget::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
auto selectedButtonsTop = countSelectedButtonsTop(
|
const auto selectedButtonsTop = countSelectedButtonsTop(
|
||||||
_selectedShown.value(showSelectedActions() ? 1. : 0.));
|
_selectedShown.value(showSelectedActions() ? 1. : 0.));
|
||||||
|
const auto searchFieldTop = _searchField
|
||||||
|
? countSelectedButtonsTop(_searchShown.value(_searchMode ? 1. : 0.))
|
||||||
|
: -st::topBarHeight;
|
||||||
|
const auto slidingTop = std::max(selectedButtonsTop, searchFieldTop);
|
||||||
|
|
||||||
p.fillRect(QRect(0, 0, width(), st::topBarHeight), st::topBarBg);
|
p.fillRect(QRect(0, 0, width(), st::topBarHeight), st::topBarBg);
|
||||||
if (selectedButtonsTop < 0) {
|
if (slidingTop < 0) {
|
||||||
p.translate(0, selectedButtonsTop + st::topBarHeight);
|
p.translate(0, slidingTop + st::topBarHeight);
|
||||||
paintTopBar(p);
|
paintTopBar(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -883,9 +888,19 @@ void TopBarWidget::updateControlsGeometry() {
|
||||||
if (!_activeChat.key) {
|
if (!_activeChat.key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto hasSelected = showSelectedActions();
|
const auto hasSelected = showSelectedActions();
|
||||||
auto selectedButtonsTop = countSelectedButtonsTop(_selectedShown.value(hasSelected ? 1. : 0.));
|
auto selectedButtonsTop = countSelectedButtonsTop(
|
||||||
auto otherButtonsTop = selectedButtonsTop + st::topBarHeight;
|
_selectedShown.value(hasSelected ? 1. : 0.));
|
||||||
|
if (!_searchMode && !_searchShown.animating() && _searchField) {
|
||||||
|
_searchField.destroy();
|
||||||
|
_searchCancel.destroy();
|
||||||
|
}
|
||||||
|
auto searchFieldTop = _searchField
|
||||||
|
? countSelectedButtonsTop(_searchShown.value(_searchMode ? 1. : 0.))
|
||||||
|
: -st::topBarHeight;
|
||||||
|
const auto otherButtonsTop = std::max(selectedButtonsTop, searchFieldTop)
|
||||||
|
+ st::topBarHeight;
|
||||||
|
const auto backButtonTop = selectedButtonsTop + st::topBarHeight;
|
||||||
auto buttonsLeft = st::topBarActionSkip
|
auto buttonsLeft = st::topBarActionSkip
|
||||||
+ (_controller->adaptive().isOneColumn() ? 0 : st::lineWidth);
|
+ (_controller->adaptive().isOneColumn() ? 0 : st::lineWidth);
|
||||||
auto buttonsWidth = (_forward->isHidden() ? 0 : _forward->contentWidth())
|
auto buttonsWidth = (_forward->isHidden() ? 0 : _forward->contentWidth())
|
||||||
|
@ -923,7 +938,7 @@ void TopBarWidget::updateControlsGeometry() {
|
||||||
_leftTaken = st::topBarArrowPadding.right();
|
_leftTaken = st::topBarArrowPadding.right();
|
||||||
} else {
|
} else {
|
||||||
_leftTaken = _narrowMode ? (width() - _back->width()) / 2 : 0;
|
_leftTaken = _narrowMode ? (width() - _back->width()) / 2 : 0;
|
||||||
_back->moveToLeft(_leftTaken, otherButtonsTop);
|
_back->moveToLeft(_leftTaken, backButtonTop);
|
||||||
_leftTaken += _back->width();
|
_leftTaken += _back->width();
|
||||||
}
|
}
|
||||||
if (_info && !_info->isHidden()) {
|
if (_info && !_info->isHidden()) {
|
||||||
|
@ -934,6 +949,26 @@ void TopBarWidget::updateControlsGeometry() {
|
||||||
_leftTaken += st::normalFont->spacew;
|
_leftTaken += st::normalFont->spacew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_searchField) {
|
||||||
|
const auto fieldLeft = _leftTaken;
|
||||||
|
const auto fieldTop = searchFieldTop
|
||||||
|
+ (height() - _searchField->height()) / 2;
|
||||||
|
const auto fieldRight = st::dialogsFilterSkip
|
||||||
|
+ st::dialogsFilterPadding.x();
|
||||||
|
const auto fieldWidth = width() - fieldLeft - fieldRight;
|
||||||
|
_searchField->setGeometryToLeft(
|
||||||
|
fieldLeft,
|
||||||
|
fieldTop,
|
||||||
|
fieldWidth,
|
||||||
|
_searchField->height());
|
||||||
|
|
||||||
|
auto right = fieldLeft + fieldWidth;
|
||||||
|
_searchCancel->moveToLeft(
|
||||||
|
right - _searchCancel->width(),
|
||||||
|
_searchField->y());
|
||||||
|
right -= _searchCancel->width();
|
||||||
|
}
|
||||||
|
|
||||||
_rightTaken = 0;
|
_rightTaken = 0;
|
||||||
_menuToggle->moveToRight(_rightTaken, otherButtonsTop);
|
_menuToggle->moveToRight(_rightTaken, otherButtonsTop);
|
||||||
if (_menuToggle->isHidden()) {
|
if (_menuToggle->isHidden()) {
|
||||||
|
@ -1146,9 +1181,86 @@ void TopBarWidget::showSelected(SelectedState state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TopBarWidget::toggleSearch(bool shown, anim::type animated) {
|
||||||
|
if (_searchMode == shown) {
|
||||||
|
if (animated == anim::type::instant) {
|
||||||
|
_searchShown.stop();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_searchMode = shown;
|
||||||
|
if (shown && !_searchField) {
|
||||||
|
_searchField.create(this, st::dialogsFilter, tr::lng_dlg_filter());
|
||||||
|
_searchField->setFocusPolicy(Qt::StrongFocus);
|
||||||
|
_searchField->customUpDown(true);
|
||||||
|
_searchField->show();
|
||||||
|
_searchCancel.create(this, st::dialogsCancelSearch);
|
||||||
|
_searchCancel->show(anim::type::instant);
|
||||||
|
_searchCancel->setClickedCallback([=] { _searchCancelled.fire({}); });
|
||||||
|
QObject::connect(_searchField, &Ui::InputField::submitted, [=] {
|
||||||
|
_searchSubmitted.fire({});
|
||||||
|
});
|
||||||
|
QObject::connect(_searchField, &Ui::InputField::changed, [=] {
|
||||||
|
_searchQuery = _searchField->getLastText();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Assert(_searchField != nullptr);
|
||||||
|
}
|
||||||
|
_searchQuery = shown ? _searchField->getLastText() : QString();
|
||||||
|
if (animated == anim::type::normal) {
|
||||||
|
_searchShown.start(
|
||||||
|
[=] { slideAnimationCallback(); },
|
||||||
|
shown ? 0. : 1.,
|
||||||
|
shown ? 1. : 0.,
|
||||||
|
st::slideWrapDuration,
|
||||||
|
anim::easeOutCirc);
|
||||||
|
} else {
|
||||||
|
_searchShown.stop();
|
||||||
|
slideAnimationCallback();
|
||||||
|
}
|
||||||
|
if (shown) {
|
||||||
|
_searchField->setFocusFast();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TopBarWidget::searchSetFocus() {
|
||||||
|
if (!_searchMode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_searchField->setFocus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TopBarWidget::searchHasFocus() const {
|
||||||
|
return _searchMode && _searchField->hasFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> TopBarWidget::searchCancelled() const {
|
||||||
|
return _searchCancelled.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> TopBarWidget::searchSubmitted() const {
|
||||||
|
return _searchSubmitted.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<QString> TopBarWidget::searchQuery() const {
|
||||||
|
return _searchQuery.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TopBarWidget::searchQueryCurrent() const {
|
||||||
|
return _searchQuery.current();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopBarWidget::searchClear() {
|
||||||
|
if (_searchMode) {
|
||||||
|
_searchField->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TopBarWidget::toggleSelectedControls(bool shown) {
|
void TopBarWidget::toggleSelectedControls(bool shown) {
|
||||||
_selectedShown.start(
|
_selectedShown.start(
|
||||||
[this] { selectedShowCallback(); },
|
[this] { slideAnimationCallback(); },
|
||||||
shown ? 0. : 1.,
|
shown ? 0. : 1.,
|
||||||
shown ? 1. : 0.,
|
shown ? 1. : 0.,
|
||||||
st::slideWrapDuration,
|
st::slideWrapDuration,
|
||||||
|
@ -1159,7 +1271,7 @@ bool TopBarWidget::showSelectedActions() const {
|
||||||
return showSelectedState() && !_chooseForReportReason;
|
return showSelectedState() && !_chooseForReportReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopBarWidget::selectedShowCallback() {
|
void TopBarWidget::slideAnimationCallback() {
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,12 @@ class RoundButton;
|
||||||
class IconButton;
|
class IconButton;
|
||||||
class PopupMenu;
|
class PopupMenu;
|
||||||
class UnreadBadge;
|
class UnreadBadge;
|
||||||
|
class InputField;
|
||||||
|
class CrossButton;
|
||||||
class InfiniteRadialAnimation;
|
class InfiniteRadialAnimation;
|
||||||
enum class ReportReason;
|
enum class ReportReason;
|
||||||
|
template <typename Widget>
|
||||||
|
class FadeWrapScaled;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
|
@ -72,6 +76,15 @@ public:
|
||||||
void showChooseMessagesForReport(Ui::ReportReason reason);
|
void showChooseMessagesForReport(Ui::ReportReason reason);
|
||||||
void clearChooseMessagesForReport();
|
void clearChooseMessagesForReport();
|
||||||
|
|
||||||
|
bool toggleSearch(bool shown, anim::type animated);
|
||||||
|
bool searchSetFocus();
|
||||||
|
[[nodiscard]] bool searchHasFocus() const;
|
||||||
|
[[nodiscard]] rpl::producer<> searchCancelled() const;
|
||||||
|
[[nodiscard]] rpl::producer<> searchSubmitted() const;
|
||||||
|
[[nodiscard]] rpl::producer<QString> searchQuery() const;
|
||||||
|
[[nodiscard]] QString searchQueryCurrent() const;
|
||||||
|
void searchClear();
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<> forwardSelectionRequest() const {
|
[[nodiscard]] rpl::producer<> forwardSelectionRequest() const {
|
||||||
return _forwardSelection.events();
|
return _forwardSelection.events();
|
||||||
}
|
}
|
||||||
|
@ -104,7 +117,7 @@ private:
|
||||||
void refreshLang();
|
void refreshLang();
|
||||||
void updateSearchVisibility();
|
void updateSearchVisibility();
|
||||||
void updateControlsGeometry();
|
void updateControlsGeometry();
|
||||||
void selectedShowCallback();
|
void slideAnimationCallback();
|
||||||
void updateInfoToggleActive();
|
void updateInfoToggleActive();
|
||||||
|
|
||||||
void call();
|
void call();
|
||||||
|
@ -169,11 +182,22 @@ private:
|
||||||
bool _canDelete = false;
|
bool _canDelete = false;
|
||||||
bool _canForward = false;
|
bool _canForward = false;
|
||||||
bool _canSendNow = false;
|
bool _canSendNow = false;
|
||||||
|
bool _searchMode = false;
|
||||||
|
|
||||||
Ui::Animations::Simple _selectedShown;
|
Ui::Animations::Simple _selectedShown;
|
||||||
|
Ui::Animations::Simple _searchShown;
|
||||||
|
|
||||||
object_ptr<Ui::RoundButton> _clear;
|
object_ptr<Ui::RoundButton> _clear;
|
||||||
object_ptr<Ui::RoundButton> _forward, _sendNow, _delete;
|
object_ptr<Ui::RoundButton> _forward, _sendNow, _delete;
|
||||||
|
object_ptr<Ui::InputField> _searchField = { nullptr };
|
||||||
|
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _chooseFromUser
|
||||||
|
= { nullptr };
|
||||||
|
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _jumpToDate
|
||||||
|
= { nullptr };
|
||||||
|
object_ptr<Ui::CrossButton> _searchCancel = { nullptr };
|
||||||
|
rpl::variable<QString> _searchQuery;
|
||||||
|
rpl::event_stream<> _searchCancelled;
|
||||||
|
rpl::event_stream<> _searchSubmitted;
|
||||||
|
|
||||||
object_ptr<Ui::IconButton> _back;
|
object_ptr<Ui::IconButton> _back;
|
||||||
object_ptr<Ui::IconButton> _cancelChoose;
|
object_ptr<Ui::IconButton> _cancelChoose;
|
||||||
|
|
|
@ -83,7 +83,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kTopicsSearchMinCount = 10;
|
constexpr auto kTopicsSearchMinCount = 1;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -1005,8 +1005,14 @@ void Filler::addViewAsMessages() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Filler::addSearchTopics() {
|
void Filler::addSearchTopics() {
|
||||||
|
const auto forum = _peer ? _peer->forum() : nullptr;
|
||||||
|
if (!forum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto history = forum->history();
|
||||||
|
const auto controller = _controller;
|
||||||
_addAction(tr::lng_dlg_filter(tr::now), [=] {
|
_addAction(tr::lng_dlg_filter(tr::now), [=] {
|
||||||
|
controller->content()->searchInChat(history);
|
||||||
}, &st::menuIconSearch);
|
}, &st::menuIconSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue