Implement search inside a single topic.

This commit is contained in:
John Preston 2022-10-26 18:49:07 +04:00
parent 60aef7871a
commit ee8f997c14
8 changed files with 107 additions and 33 deletions

View file

@ -675,7 +675,12 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
} }
if (_searchInChat) { if (_searchInChat) {
paintSearchInChat(p); paintSearchInChat(p, {
.st = &st::forumTopicRow,
.now = ms,
.width = fullWidth,
.paused = videoPaused,
});
p.translate(0, searchInChatSkip()); p.translate(0, searchInChatSkip());
if (_waitingForSearch && _searchResults.empty()) { if (_waitingForSearch && _searchResults.empty()) {
p.fillRect( p.fillRect(
@ -926,7 +931,9 @@ void InnerWidget::paintPeerSearchResult(
result->name.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); result->name.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} }
void InnerWidget::paintSearchInChat(Painter &p) const { void InnerWidget::paintSearchInChat(
Painter &p,
const Ui::PaintContext &context) const {
auto height = searchInChatSkip(); auto height = searchInChatSkip();
auto top = st::searchedBarHeight; auto top = st::searchedBarHeight;
@ -942,7 +949,9 @@ void InnerWidget::paintSearchInChat(Painter &p) const {
} }
p.setPen(st::dialogsNameFg); p.setPen(st::dialogsNameFg);
if (const auto peer = _searchInChat.peer()) { if (const auto topic = _searchInChat.topic()) {
paintSearchInTopic(p, context, topic, _searchInChatUserpic, top, _searchInChatText);
} else if (const auto peer = _searchInChat.peer()) {
if (peer->isSelf()) { if (peer->isSelf()) {
paintSearchInSaved(p, top, _searchInChatText); paintSearchInSaved(p, top, _searchInChatText);
} else if (peer->isRepliesChat()) { } else if (peer->isRepliesChat()) {
@ -1035,6 +1044,21 @@ void InnerWidget::paintSearchInReplies(
paintSearchInFilter(p, paintUserpic, top, nullptr, text); paintSearchInFilter(p, paintUserpic, top, nullptr, text);
} }
void InnerWidget::paintSearchInTopic(
Painter &p,
const Ui::PaintContext &context,
not_null<Data::ForumTopic*> topic,
std::shared_ptr<Data::CloudImageView> &userpic,
int top,
const Ui::Text::String &text) const {
const auto paintUserpic = [&](Painter &p, int x, int y, int size) {
p.translate(x, y);
topic->paintUserpic(p, userpic, context);
p.translate(-x, -y);
};
paintSearchInFilter(p, paintUserpic, top, nullptr, text);
}
void InnerWidget::mouseMoveEvent(QMouseEvent *e) { void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
const auto globalPosition = e->globalPos(); const auto globalPosition = e->globalPos();
if (!_lastMousePosition) { if (!_lastMousePosition) {
@ -2313,9 +2337,9 @@ void InnerWidget::searchReceived(
const auto isMigratedSearch = (type == SearchRequestType::MigratedFromStart) const auto isMigratedSearch = (type == SearchRequestType::MigratedFromStart)
|| (type == SearchRequestType::MigratedFromOffset); || (type == SearchRequestType::MigratedFromOffset);
const auto key = _openedForum const auto key = (!_openedForum || _searchInChat.topic())
? Key(_openedForum->history()) ? _searchInChat
: _searchInChat; : Key(_openedForum->history());
if (inject if (inject
&& (!_searchInChat && (!_searchInChat
|| inject->history() == _searchInChat.history())) { || inject->history() == _searchInChat.history())) {
@ -2600,7 +2624,9 @@ void InnerWidget::searchInChat(Key key, PeerData *from) {
void InnerWidget::refreshSearchInChatLabel() { void InnerWidget::refreshSearchInChatLabel() {
const auto dialog = [&] { const auto dialog = [&] {
if (const auto peer = _searchInChat.peer()) { if (const auto topic = _searchInChat.topic()) {
return topic->title();
} else if (const auto peer = _searchInChat.peer()) {
if (peer->isSelf()) { if (peer->isSelf()) {
return tr::lng_saved_messages(tr::now); return tr::lng_saved_messages(tr::now);
} else if (peer->isRepliesChat()) { } else if (peer->isRepliesChat()) {

View file

@ -301,7 +301,9 @@ private:
Painter &p, Painter &p,
not_null<const PeerSearchResult*> result, not_null<const PeerSearchResult*> result,
const Ui::PaintContext &context); const Ui::PaintContext &context);
void paintSearchInChat(Painter &p) const; void paintSearchInChat(
Painter &p,
const Ui::PaintContext &context) const;
void paintSearchInPeer( void paintSearchInPeer(
Painter &p, Painter &p,
not_null<PeerData*> peer, not_null<PeerData*> peer,
@ -316,6 +318,13 @@ private:
Painter &p, Painter &p,
int top, int top,
const Ui::Text::String &text) const; const Ui::Text::String &text) const;
void paintSearchInTopic(
Painter &p,
const Ui::PaintContext &context,
not_null<Data::ForumTopic*> topic,
std::shared_ptr<Data::CloudImageView> &userpic,
int top,
const Ui::Text::String &text) const;
template <typename PaintUserpic> template <typename PaintUserpic>
void paintSearchInFilter( void paintSearchInFilter(
Painter &p, Painter &p,

View file

@ -1848,6 +1848,12 @@ void Widget::applyFilterUpdate(bool force) {
} }
void Widget::searchInChat(Key chat) { void Widget::searchInChat(Key chat) {
if (_openedFolder) {
controller()->closeFolder();
}
if (const auto topic = chat.topic()) {
controller()->openForum(topic->channel());
}
cancelSearch(); cancelSearch();
setSearchInChat(chat); setSearchInChat(chat);
applyFilterUpdate(true); applyFilterUpdate(true);
@ -1855,24 +1861,25 @@ void Widget::searchInChat(Key chat) {
void Widget::setSearchInChat(Key chat, PeerData *from) { void Widget::setSearchInChat(Key chat, PeerData *from) {
const auto peer = chat.peer(); const auto peer = chat.peer();
if (const auto forum = peer ? peer->forum() : nullptr) { const auto topic = chat.topic();
const auto forum = peer ? peer->forum() : nullptr;
if (forum) {
if (controller()->openedForum().current() == peer) { if (controller()->openedForum().current() == peer) {
_subsectionTopBar->toggleSearch(true, anim::type::normal); _subsectionTopBar->toggleSearch(true, anim::type::normal);
} else { } else {
_forumSearchRequested = true; _forumSearchRequested = true;
controller()->openForum(forum->channel()); controller()->openForum(forum->channel());
} }
return;
} }
if (chat.folder()) { if (chat.folder() || (forum && !topic)) {
chat = Key(); chat = Key();
} }
_searchInMigrated = nullptr; _searchInMigrated = nullptr;
if (const auto peer = chat.peer()) { if (peer) {
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()) {
if (!chat.topic()) { if (!topic) {
_searchInMigrated = peer->owner().history(migrateFrom); _searchInMigrated = peer->owner().history(migrateFrom);
} }
} }

View file

@ -955,9 +955,10 @@ void RowPainter::Paint(
const auto entry = topic ? (Entry*)topic : (Entry*)history; const auto entry = topic ? (Entry*)topic : (Entry*)history;
auto cloudDraft = nullptr; auto cloudDraft = nullptr;
const auto from = [&] { const auto from = [&] {
return topic const auto in = row->searchInChat();
return (topic && (in.topic() != topic))
? nullptr ? nullptr
: row->searchInChat() : in
? item->displayFrom() ? item->displayFrom()
: history->peer->migrateTo() : history->peer->migrateTo()
? history->peer->migrateTo() ? history->peer->migrateTo()

View file

@ -1825,25 +1825,24 @@ bool HistoryWidget::notify_switchInlineBotButtonReceived(const QString &query, U
void HistoryWidget::setupShortcuts() { void HistoryWidget::setupShortcuts() {
Shortcuts::Requests( Shortcuts::Requests(
) | rpl::filter([=] { ) | rpl::filter([=] {
return Ui::AppInFocus() return _history
&& Ui::AppInFocus()
&& Ui::InFocusChain(this) && Ui::InFocusChain(this)
&& !Ui::isLayerShown() && !Ui::isLayerShown()
&& (Core::App().activeWindow() == &controller()->window()); && (Core::App().activeWindow() == &controller()->window());
}) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) { }) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) {
using Command = Shortcuts::Command; using Command = Shortcuts::Command;
if (_history) { request->check(Command::Search, 1) && request->handle([=] {
request->check(Command::Search, 1) && request->handle([=] { searchInChat();
searchInChat(); return true;
});
if (session().supportMode()) {
request->check(
Command::SupportToggleMuted
) && request->handle([=] {
toggleMuteUnmute();
return true; return true;
}); });
if (session().supportMode()) {
request->check(
Command::SupportToggleMuted
) && request->handle([=] {
toggleMuteUnmute();
return true;
});
}
} }
}, lifetime()); }, lifetime());
} }
@ -4450,8 +4449,7 @@ bool HistoryWidget::updateCmdStartShown() {
void HistoryWidget::searchInChat() { void HistoryWidget::searchInChat() {
if (!_history) { if (!_history) {
return; return;
} } else if (controller()->isPrimary()) {
if (controller()->isPrimary()) {
controller()->content()->searchInChat(_history); controller()->content()->searchInChat(_history);
} else if (!_composeSearch) { } else if (!_composeSearch) {
const auto search = [=] { const auto search = [=] {

View file

@ -55,7 +55,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "base/qt/qt_key_modifiers.h" #include "base/qt/qt_key_modifiers.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "core/application.h"
#include "core/shortcuts.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mainwidget.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_chat.h" #include "data/data_chat.h"
@ -233,6 +236,7 @@ RepliesWidget::RepliesWidget(
setupRoot(); setupRoot();
setupRootView(); setupRootView();
setupShortcuts();
session().api().requestFullPeer(_history->peer); session().api().requestFullPeer(_history->peer);
@ -258,6 +262,10 @@ RepliesWidget::RepliesWidget(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
clearSelected(); clearSelected();
}, _topBar->lifetime()); }, _topBar->lifetime());
_topBar->searchRequest(
) | rpl::start_with_next([=] {
searchInTopic();
}, _topBar->lifetime());
if (_rootView) { if (_rootView) {
_rootView->raise(); _rootView->raise();
@ -2133,4 +2141,31 @@ void RepliesWidget::setupDragArea() {
areas.photo->setDroppedCallback(droppedCallback(true)); areas.photo->setDroppedCallback(droppedCallback(true));
} }
void RepliesWidget::setupShortcuts() {
Shortcuts::Requests(
) | rpl::filter([=] {
return _topic
&& Ui::AppInFocus()
&& Ui::InFocusChain(this)
&& !Ui::isLayerShown()
&& (Core::App().activeWindow() == &controller()->window());
}) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) {
using Command = Shortcuts::Command;
request->check(Command::Search, 1) && request->handle([=] {
searchInTopic();
return true;
});
}, lifetime());
}
void RepliesWidget::searchInTopic() {
if (!_topic) {
return;
} else if (controller()->isPrimary()) {
controller()->content()->searchInChat(_topic);
} else {
// #TODO forum window
}
}
} // namespace HistoryView } // namespace HistoryView

View file

@ -206,7 +206,9 @@ private:
void subscribeToTopic(); void subscribeToTopic();
void setTopic(Data::ForumTopic *topic); void setTopic(Data::ForumTopic *topic);
void setupDragArea(); void setupDragArea();
void setupShortcuts();
void searchInTopic();
void scrollDownAnimationFinish(); void scrollDownAnimationFinish();
void updatePinnedVisibility(); void updatePinnedVisibility();

View file

@ -2678,10 +2678,6 @@ void MainWidget::searchInChat(Dialogs::Key chat) {
if (!_dialogs) { if (!_dialogs) {
return; return;
} }
if (_controller->openedFolder().current()) {
_controller->closeFolder();
}
_dialogs->searchInChat(chat); _dialogs->searchInChat(chat);
if (isOneColumn()) { if (isOneColumn()) {
Ui::showChatsList(&session()); Ui::showChatsList(&session());