Show forum messages search results with topics.

This commit is contained in:
John Preston 2022-10-26 16:33:58 +04:00
parent 88d1a502a5
commit d6ee5b3456
9 changed files with 235 additions and 177 deletions

View file

@ -712,9 +712,9 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
p.translate(0, st::searchedBarHeight);
auto skip = searchedOffset();
auto from = floorclamp(r.y() - skip, st::dialogsRowHeight, 0, _searchResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _searchResults.size());
p.translate(0, from * st::dialogsRowHeight);
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);
if (from < _searchResults.size()) {
for (; from < to; ++from) {
const auto &result = _searchResults[from];
@ -725,7 +725,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
? _searchedPressed
: _searchedSelected));
Ui::RowPainter::Paint(p, result.get(), {
.st = &st::defaultDialogRow,
.st = _st,
.folder = _openedFolder,
.forum = _openedForum,
.filter = _filterId,
@ -738,7 +738,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
.narrow = (fullWidth < st::columnMinimalWidthLeft),
.displayUnreadInfo = showUnreadInSearchResults,
});
p.translate(0, st::dialogsRowHeight);
p.translate(0, _st->height);
}
}
}
@ -1141,7 +1141,7 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
}
if (!_waitingForSearch && !_searchResults.empty()) {
auto skip = searchedOffset();
auto searchedSelected = (mouseY >= skip) ? ((mouseY - skip) / st::dialogsRowHeight) : -1;
auto searchedSelected = (mouseY >= skip) ? ((mouseY - skip) / _st->height) : -1;
if (searchedSelected < 0 || searchedSelected >= _searchResults.size()) {
searchedSelected = -1;
}
@ -1205,7 +1205,7 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
[this, peer = result->peer] { updateSearchResult(peer); });
} else if (base::in_range(_searchedPressed, 0, _searchResults.size())) {
auto &row = _searchResults[_searchedPressed];
row->addRipple(e->pos() - QPoint(0, searchedOffset() + _searchedPressed * st::dialogsRowHeight), QSize(width(), st::dialogsRowHeight), row->repaint());
row->addRipple(e->pos() - QPoint(0, searchedOffset() + _searchedPressed * _st->height), QSize(width(), _st->height), row->repaint());
}
if (anim::Disabled()
&& (!_pressed || !_pressed->entry()->isPinnedDialog(_filterId))) {
@ -1789,8 +1789,8 @@ void InnerWidget::updateDialogRow(
for (const auto &result : _searchResults) {
if (isSearchResultActive(result.get(), row)) {
updateRow(
add + index * st::dialogsRowHeight,
st::dialogsRowHeight);
add + index * _st->height,
_st->height);
break;
}
++index;
@ -1836,7 +1836,7 @@ void InnerWidget::updateSelectedRow(Key key) {
} else if (_peerSearchSelected >= 0) {
update(0, peerSearchOffset() + _peerSearchSelected * st::dialogsRowHeight, width(), st::dialogsRowHeight);
} else if (_searchedSelected >= 0) {
update(0, searchedOffset() + _searchedSelected * st::dialogsRowHeight, width(), st::dialogsRowHeight);
update(0, searchedOffset() + _searchedSelected * _st->height, width(), _st->height);
}
}
}
@ -2068,10 +2068,43 @@ InnerWidget::~InnerWidget() {
void InnerWidget::clearSearchResults(bool clearPeerSearchResults) {
if (clearPeerSearchResults) _peerSearchResults.clear();
_searchResults.clear();
_searchResultsLifetime.destroy();
_searchedCount = _searchedMigratedCount = 0;
_lastSearchDate = 0;
_lastSearchPeer = nullptr;
_lastSearchId = _lastSearchMigratedId = 0;
}
void InnerWidget::trackSearchResultsHistory(not_null<History*> history) {
const auto channel = history->peer->asChannel();
if (!channel || channel->isBroadcast()) {
return;
}
channel->flagsValue(
) | rpl::skip(
1
) | rpl::filter([=](const ChannelData::Flags::Change &change) {
return (change.diff & ChannelDataFlag::Forum);
}) | rpl::start_with_next([=] {
for (const auto &row : _searchResults) {
if (row->item()->history()->peer == channel) {
row->invalidateTopic();
}
}
update();
}, _searchResultsLifetime);
if (const auto forum = channel->forum()) {
forum->topicDestroyed(
) | rpl::start_with_next([=](not_null<Data::ForumTopic*> topic) {
const auto from = ranges::remove(
_searchResults,
topic.get(),
&FakeRow::topic);
if (from != end(_searchResults)) {
_searchResults.erase(from, end(_searchResults));
refresh(true);
clearMouseSelection(true);
}
}, _searchResultsLifetime);
}
}
PeerData *InnerWidget::updateFromParentDrag(QPoint globalPosition) {
@ -2210,8 +2243,8 @@ bool InnerWidget::hasHistoryInResults(not_null<History*> history) const {
return false;
}
bool InnerWidget::searchReceived(
const QVector<MTPMessage> &messages,
void InnerWidget::searchReceived(
std::vector<not_null<HistoryItem*>> messages,
HistoryItem *inject,
SearchRequestType type,
int fullCount) {
@ -2219,10 +2252,12 @@ bool InnerWidget::searchReceived(
if (type == SearchRequestType::FromStart || type == SearchRequestType::PeerFromStart) {
clearSearchResults(false);
}
auto isGlobalSearch = (type == SearchRequestType::FromStart || type == SearchRequestType::FromOffset);
auto isMigratedSearch = (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset);
const auto isMigratedSearch = (type == SearchRequestType::MigratedFromStart)
|| (type == SearchRequestType::MigratedFromOffset);
TimeId lastDateFound = 0;
const auto key = _openedForum
? Key(_openedForum->history())
: _searchInChat;
if (inject
&& (!_searchInChat
|| inject->history() == _searchInChat.history())) {
@ -2230,49 +2265,25 @@ bool InnerWidget::searchReceived(
const auto index = int(_searchResults.size());
_searchResults.push_back(
std::make_unique<FakeRow>(
_searchInChat,
key,
inject,
[=] { repaintSearchResult(index); }));
trackSearchResultsHistory(inject->history());
++fullCount;
}
for (const auto &message : messages) {
auto msgId = IdFromMessage(message);
auto peerId = PeerFromMessage(message);
auto lastDate = DateFromMessage(message);
if (const auto peer = session().data().peerLoaded(peerId)) {
if (lastDate) {
const auto item = session().data().addNewMessage(
message,
MessageFlags(),
NewMessageType::Existing);
const auto history = item->history();
if (!uniquePeers || !hasHistoryInResults(history)) {
const auto index = int(_searchResults.size());
_searchResults.push_back(
std::make_unique<FakeRow>(
_searchInChat,
item,
[=] { repaintSearchResult(index); }));
if (uniquePeers && !history->unreadCountKnown()) {
history->owner().histories().requestDialogEntry(history);
}
}
lastDateFound = lastDate;
if (isGlobalSearch) {
_lastSearchDate = lastDateFound;
}
for (const auto &item : messages) {
const auto history = item->history();
if (!uniquePeers || !hasHistoryInResults(history)) {
const auto index = int(_searchResults.size());
_searchResults.push_back(
std::make_unique<FakeRow>(
key,
item,
[=] { repaintSearchResult(index); }));
trackSearchResultsHistory(history);
if (uniquePeers && !history->unreadCountKnown()) {
history->owner().histories().requestDialogEntry(history);
}
if (isGlobalSearch) {
_lastSearchPeer = peer;
}
} else {
LOG(("API Error: a search results with not loaded peer %1"
).arg(peerId.value));
}
if (isMigratedSearch) {
_lastSearchMigratedId = msgId;
} else {
_lastSearchId = msgId;
}
}
if (isMigratedSearch) {
@ -2289,8 +2300,6 @@ bool InnerWidget::searchReceived(
}
refresh();
return lastDateFound != 0;
}
void InnerWidget::peerSearchReceived(
@ -2397,9 +2406,9 @@ void InnerWidget::refresh(bool toTop) {
}
} else if (_state == WidgetState::Filtered) {
if (_waitingForSearch) {
h = searchedOffset() + (_searchResults.size() * st::dialogsRowHeight) + ((_searchResults.empty() && !_searchInChat) ? -st::searchedBarHeight : 0);
h = searchedOffset() + (_searchResults.size() * _st->height) + ((_searchResults.empty() && !_searchInChat) ? -st::searchedBarHeight : 0);
} else {
h = searchedOffset() + (_searchResults.size() * st::dialogsRowHeight);
h = searchedOffset() + (_searchResults.size() * _st->height);
}
}
resize(width(), h);
@ -2585,9 +2594,9 @@ void InnerWidget::refreshSearchInChatLabel() {
void InnerWidget::repaintSearchResult(int index) {
rtlupdate(
0,
searchedOffset() + index * st::dialogsRowHeight,
searchedOffset() + index * _st->height,
width(),
st::dialogsRowHeight);
_st->height);
}
void InnerWidget::clearFilter() {
@ -2603,9 +2612,6 @@ void InnerWidget::clearFilter() {
_filterResultsGlobal.clear();
_peerSearchResults.clear();
_searchResults.clear();
_lastSearchDate = 0;
_lastSearchPeer = nullptr;
_lastSearchId = _lastSearchMigratedId = 0;
_filter = QString();
refresh(true);
}
@ -2718,10 +2724,10 @@ void InnerWidget::selectSkip(int32 direction) {
} else {
_mustScrollTo.fire({
searchedOffset()
+ _searchedSelected * st::dialogsRowHeight
+ _searchedSelected * _st->height
+ (_searchedSelected ? 0 : -st::searchedBarHeight),
searchedOffset()
+ (_searchedSelected + 1) * st::dialogsRowHeight,
+ (_searchedSelected + 1) * _st->height,
});
}
}
@ -2738,8 +2744,8 @@ void InnerWidget::scrollToEntry(const RowDescriptor &entry) {
} else if (_state == WidgetState::Filtered) {
for (int32 i = 0, c = _searchResults.size(); i < c; ++i) {
if (isSearchResultActive(_searchResults[i].get(), entry)) {
fromY = searchedOffset() + i * st::dialogsRowHeight;
rowHeight = st::dialogsRowHeight;
fromY = searchedOffset() + i * _st->height;
rowHeight = _st->height;
break;
}
}
@ -2936,9 +2942,11 @@ ChosenRow InnerWidget::computeChosenRow() const {
};
} else if (base::in_range(_searchedSelected, 0, _searchResults.size())) {
const auto result = _searchResults[_searchedSelected].get();
const auto topic = result->topic();
const auto item = result->item();
return {
result->item()->history(),
result->item()->position()
(topic ? (Entry*)topic : (Entry*)item->history()),
item->position()
};
}
}
@ -3168,22 +3176,6 @@ RowDescriptor InnerWidget::chatListEntryLast() const {
return RowDescriptor();
}
int32 InnerWidget::lastSearchDate() const {
return _lastSearchDate;
}
PeerData *InnerWidget::lastSearchPeer() const {
return _lastSearchPeer;
}
MsgId InnerWidget::lastSearchId() const {
return _lastSearchId;
}
MsgId InnerWidget::lastSearchMigratedId() const {
return _lastSearchMigratedId;
}
void InnerWidget::setupOnlineStatusCheck() {
session().changes().peerUpdates(
Data::PeerUpdate::Flag::OnlineStatus

View file

@ -85,8 +85,8 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller);
bool searchReceived(
const QVector<MTPMessage> &result,
void searchReceived(
std::vector<not_null<HistoryItem*>> result,
HistoryItem *inject,
SearchRequestType type,
int fullCount);
@ -117,10 +117,6 @@ public:
[[nodiscard]] Data::Folder *shownFolder() const;
[[nodiscard]] Data::Forum *shownForum() const;
[[nodiscard]] int32 lastSearchDate() const;
[[nodiscard]] PeerData *lastSearchPeer() const;
[[nodiscard]] MsgId lastSearchId() const;
[[nodiscard]] MsgId lastSearchMigratedId() const;
[[nodiscard]] WidgetState state() const;
[[nodiscard]] not_null<const style::DialogRow*> st() const {
@ -333,6 +329,8 @@ private:
void clearSearchResults(bool clearPeerSearchResults = true);
void updateSelectedRow(Key key = Key());
void trackSearchResultsHistory(not_null<History*> history);
void trackSearchResultsForum(Data::Forum *forum);
[[nodiscard]] not_null<IndexedList*> shownDialogs() const;
@ -406,16 +404,12 @@ private:
int _peerSearchPressed = -1;
std::vector<std::unique_ptr<FakeRow>> _searchResults;
rpl::lifetime _searchResultsLifetime;
int _searchedCount = 0;
int _searchedMigratedCount = 0;
int _searchedSelected = -1;
int _searchedPressed = -1;
int _lastSearchDate = 0;
PeerData *_lastSearchPeer = nullptr;
MsgId _lastSearchId = 0;
MsgId _lastSearchMigratedId = 0;
WidgetState _state = WidgetState::Default;
object_ptr<Ui::FlatLabel> _empty = { nullptr };

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "dialogs/ui/dialogs_video_userpic.h"
#include "dialogs/ui/dialogs_layout.h"
#include "data/data_folder.h"
#include "data/data_forum.h"
#include "data/data_session.h"
#include "data/data_peer_values.h"
#include "history/history.h"
@ -351,6 +352,25 @@ FakeRow::FakeRow(
: _searchInChat(searchInChat)
, _item(item)
, _repaint(std::move(repaint)) {
invalidateTopic();
}
void FakeRow::invalidateTopic() {
_topic = _item->topic();
if (_topic) {
return;
} else if (const auto rootId = _item->topicRootId()) {
if (const auto forum = _item->history()->peer->forum()) {
if (!forum->topicDeleted(rootId)) {
forum->requestTopic(rootId, crl::guard(this, [=] {
_topic = _item->topic();
if (_topic) {
_repaint();
}
}));
}
}
}
}
const Ui::Text::String &FakeRow::name() const {

View file

@ -147,7 +147,7 @@ private:
};
class FakeRow : public BasicRow {
class FakeRow final : public BasicRow, public base::has_weak_ptr {
public:
FakeRow(
Key searchInChat,
@ -157,6 +157,9 @@ public:
[[nodiscard]] Key searchInChat() const {
return _searchInChat;
}
[[nodiscard]] Data::ForumTopic *topic() const {
return _topic;
}
[[nodiscard]] not_null<HistoryItem*> item() const {
return _item;
}
@ -171,11 +174,14 @@ public:
}
[[nodiscard]] const Ui::Text::String &name() const;
void invalidateTopic();
private:
friend class Ui::RowPainter;
const Key _searchInChat;
const not_null<HistoryItem*> _item;
Data::ForumTopic *_topic = nullptr;
const Fn<void()> _repaint;
mutable Ui::MessageView _itemView;
mutable Ui::PeerBadge _badge;

View file

@ -344,7 +344,9 @@ Widget::Widget(
setupMainMenuToggle();
setupShortcuts();
_searchForNarrowFilters->setClickedCallback([=] { Ui::showChatsList(&session()); });
_searchForNarrowFilters->setClickedCallback([=] {
Ui::showChatsList(&session());
});
setAcceptDrops(true);
@ -446,7 +448,11 @@ void Widget::chosenRow(const ChosenRow &row) {
controller()->openFolder(folder);
}
if (openSearchResult && !session().supportMode()) {
escape();
if (_subsectionTopBar) {
_subsectionTopBar->toggleSearch(false, anim::type::instant);
} else {
escape();
}
}
}
@ -1336,15 +1342,13 @@ void Widget::searchMore() {
return;
}
if (!_searchFull) {
auto offsetPeer = _inner->lastSearchPeer();
auto offsetId = _inner->lastSearchId();
if (const auto peer = searchInPeer()) {
auto &histories = session().data().histories();
const auto topic = searchInTopic();
const auto type = Data::Histories::RequestType::History;
const auto history = session().data().history(peer);
_searchInHistoryRequest = histories.sendRequest(history, type, [=](Fn<void()> finish) {
const auto type = offsetId
const auto type = _lastSearchId
? SearchRequestType::PeerFromOffset
: SearchRequestType::PeerFromStart;
using Flag = MTPmessages_Search::Flag;
@ -1356,11 +1360,11 @@ void Widget::searchMore() {
(_searchQueryFrom
? _searchQueryFrom->input
: MTP_inputPeerEmpty()),
MTPint(), // top_msg_id
MTP_int(topic ? topic->rootId() : 0),
MTP_inputMessagesFilterEmpty(),
MTP_int(0), // min_date
MTP_int(0), // max_date
MTP_int(offsetId),
MTP_int(_lastSearchId),
MTP_int(0), // add_offset
MTP_int(kSearchPerPage),
MTP_int(0), // max_id
@ -1375,13 +1379,13 @@ void Widget::searchMore() {
_searchInHistoryRequest = 0;
finish();
}).send();
if (!offsetId) {
if (!_lastSearchId) {
_searchQueries.emplace(_searchRequest, _searchQuery);
}
return _searchRequest;
});
} else {
const auto type = offsetId
const auto type = _lastSearchId
? SearchRequestType::FromOffset
: SearchRequestType::FromStart;
const auto flags = session().settings().skipArchiveInSearch()
@ -1396,27 +1400,26 @@ void Widget::searchMore() {
MTP_int(0), // min_date
MTP_int(0), // max_date
MTP_int(_searchNextRate),
offsetPeer
? offsetPeer->input
: MTP_inputPeerEmpty(),
MTP_int(offsetId),
(_lastSearchPeer
? _lastSearchPeer->input
: MTP_inputPeerEmpty()),
MTP_int(_lastSearchId),
MTP_int(kSearchPerPage)
)).done([=](const MTPmessages_Messages &result) {
searchReceived(type, result, _searchRequest);
}).fail([=](const MTP::Error &error) {
searchFailed(type, error, _searchRequest);
}).send();
if (!offsetId) {
if (!_lastSearchId) {
_searchQueries.emplace(_searchRequest, _searchQuery);
}
}
} else if (_searchInMigrated && !_searchFullMigrated) {
auto offsetMigratedId = _inner->lastSearchMigratedId();
auto &histories = session().data().histories();
const auto type = Data::Histories::RequestType::History;
const auto history = _searchInMigrated;
_searchInHistoryRequest = histories.sendRequest(history, type, [=](Fn<void()> finish) {
const auto type = offsetMigratedId
const auto type = _lastSearchMigratedId
? SearchRequestType::MigratedFromOffset
: SearchRequestType::MigratedFromStart;
const auto flags = _searchQueryFrom
@ -1433,7 +1436,7 @@ void Widget::searchMore() {
MTP_inputMessagesFilterEmpty(),
MTP_int(0), // min_date
MTP_int(0), // max_date
MTP_int(offsetMigratedId),
MTP_int(_lastSearchMigratedId),
MTP_int(0), // add_offset
MTP_int(kSearchPerPage),
MTP_int(0), // max_id
@ -1475,37 +1478,69 @@ void Widget::searchReceived(
if (_searchRequest != requestId) {
return;
}
switch (result.type()) {
case mtpc_messages_messages: {
auto &d = result.c_messages_messages();
if (type == SearchRequestType::FromStart
|| type == SearchRequestType::PeerFromStart) {
_lastSearchPeer = nullptr;
_lastSearchId = _lastSearchMigratedId = 0;
}
const auto isGlobalSearch = (type == SearchRequestType::FromStart)
|| (type == SearchRequestType::FromOffset);
const auto isMigratedSearch = (type == SearchRequestType::MigratedFromStart)
|| (type == SearchRequestType::MigratedFromOffset);
const auto process = [&](const MTPVector<MTPMessage> &messages) {
auto result = std::vector<not_null<HistoryItem*>>();
for (const auto &message : messages.v) {
const auto msgId = IdFromMessage(message);
const auto peerId = PeerFromMessage(message);
const auto lastDate = DateFromMessage(message);
if (const auto peer = session().data().peerLoaded(peerId)) {
if (lastDate) {
const auto item = session().data().addNewMessage(
message,
MessageFlags(),
NewMessageType::Existing);
result.push_back(item);
}
_lastSearchPeer = peer;
} else {
LOG(("API Error: a search results with not loaded peer %1"
).arg(peerId.value));
}
if (isMigratedSearch) {
_lastSearchMigratedId = msgId;
} else {
_lastSearchId = msgId;
}
}
return result;
};
auto fullCount = 0;
auto messages = result.match([&](const MTPDmessages_messages &data) {
if (_searchRequest != 0) {
// Don't apply cached data!
session().data().processUsers(d.vusers());
session().data().processChats(d.vchats());
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
}
auto &msgs = d.vmessages().v;
_inner->searchReceived(msgs, inject, type, msgs.size());
if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) {
_searchFullMigrated = true;
} else {
_searchFull = true;
}
} break;
case mtpc_messages_messagesSlice: {
auto &d = result.c_messages_messagesSlice();
auto list = process(data.vmessages());
fullCount = list.size();
return list;
}, [&](const MTPDmessages_messagesSlice &data) {
if (_searchRequest != 0) {
// Don't apply cached data!
session().data().processUsers(d.vusers());
session().data().processChats(d.vchats());
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
}
auto &msgs = d.vmessages().v;
const auto someAdded = _inner->searchReceived(msgs, inject, type, d.vcount().v);
const auto nextRate = d.vnext_rate();
auto list = process(data.vmessages());
const auto nextRate = data.vnext_rate();
const auto rateUpdated = nextRate && (nextRate->v != _searchNextRate);
const auto finished = (type == SearchRequestType::FromStart || type == SearchRequestType::FromOffset)
? !rateUpdated
: !someAdded;
: list.empty();
if (rateUpdated) {
_searchNextRate = nextRate->v;
}
@ -1516,13 +1551,12 @@ void Widget::searchReceived(
_searchFull = true;
}
}
} break;
case mtpc_messages_channelMessages: {
auto &d = result.c_messages_channelMessages();
if (const auto peer = _openedForum ? _openedForum : _searchInChat.peer()) {
fullCount = data.vcount().v;
return list;
}, [&](const MTPDmessages_channelMessages &data) {
if (const auto peer = searchInPeer()) {
if (const auto channel = peer->asChannel()) {
channel->ptsReceived(d.vpts().v);
channel->ptsReceived(data.vpts().v);
} else {
LOG(("API Error: "
"received messages.channelMessages when no channel "
@ -1535,28 +1569,29 @@ void Widget::searchReceived(
}
if (_searchRequest != 0) {
// Don't apply cached data!
session().data().processUsers(d.vusers());
session().data().processChats(d.vchats());
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
}
auto &msgs = d.vmessages().v;
if (!_inner->searchReceived(msgs, inject, type, d.vcount().v)) {
auto list = process(data.vmessages());
if (list.empty()) {
if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) {
_searchFullMigrated = true;
} else {
_searchFull = true;
}
}
} break;
case mtpc_messages_messagesNotModified: {
fullCount = data.vcount().v;
return list;
}, [&](const MTPDmessages_messagesNotModified &) {
LOG(("API Error: received messages.messagesNotModified! (Widget::searchReceived)"));
if (type == SearchRequestType::MigratedFromStart || type == SearchRequestType::MigratedFromOffset) {
_searchFullMigrated = true;
} else {
_searchFull = true;
}
} break;
}
return std::vector<not_null<HistoryItem*>>();
});
_inner->searchReceived(messages, inject, type, fullCount);
_searchRequest = 0;
listScrollUpdated();
@ -1808,8 +1843,10 @@ void Widget::showCalendar() {
}
void Widget::showSearchFrom() {
if (const auto peer = _searchInChat.peer()) {
const auto chat = _searchInChat;
if (const auto peer = searchInPeer()) {
const auto chat = _openedForum
? Key(_openedForum->forum()->history())
: _searchInChat;
auto box = SearchFromBox(
peer,
crl::guard(this, [=](not_null<PeerData*> from) {
@ -1914,7 +1951,7 @@ void Widget::updateJumpToDateVisibility(bool fast) {
void Widget::updateSearchFromVisibility(bool fast) {
auto visible = [&] {
if (const auto peer = _searchInChat.peer()) {
if (const auto peer = searchInPeer()) {
if (peer->isChat() || peer->isMegagroup()) {
return !_searchFromAuthor;
}
@ -2197,6 +2234,8 @@ bool Widget::cancelSearch() {
setFocus();
return true;
}
_lastSearchPeer = nullptr;
_lastSearchId = _lastSearchMigratedId = 0;
_inner->clearFilter();
clearSearchField();
applyFilterUpdate();

View file

@ -252,6 +252,10 @@ private:
int _searchInHistoryRequest = 0; // Not real mtpRequestId.
mtpRequestId _searchRequest = 0;
PeerData *_lastSearchPeer = nullptr;
MsgId _lastSearchId = 0;
MsgId _lastSearchMigratedId = 0;
base::flat_map<QString, MTPmessages_Messages> _searchCache;
Api::SingleMessageSearch _singleMessageSearch;
base::flat_map<mtpRequestId, QString> _searchQueries;

View file

@ -243,7 +243,6 @@ void PaintRow(
Painter &p,
not_null<const BasicRow*> row,
not_null<Entry*> entry,
Dialogs::Key chat,
VideoUserpic *videoUserpic,
PeerData *from,
Ui::PeerBadge &fromBadge,
@ -274,8 +273,8 @@ void PaintRow(
p.fillRect(fullRect, bg);
row->paintRipple(p, 0, 0, context.width, &ripple->c);
const auto history = chat.history();
const auto thread = chat.thread();
const auto history = entry->asHistory();
const auto thread = entry->asThread();
if (flags & Flag::SavedMessages) {
EmptyUserpic::PaintSavedMessages(
@ -512,7 +511,7 @@ void PaintRow(
if (!thread) {
return nullptr;
} else if (const auto topic = thread->asTopic()
; topic && topic->closed()) {
; !context.search && topic && topic->closed()) {
return &(context.active
? st::dialogsLockIconActive
: context.selected
@ -927,11 +926,10 @@ void RowPainter::Paint(
p,
row,
entry,
row->key(),
videoUserpic,
from,
entry->chatListPeerBadge(),
[=] { history->updateChatListEntry(); },
[=] { entry->updateChatListEntry(); },
entry->chatListNameText(),
nullptr,
item,
@ -947,14 +945,17 @@ void RowPainter::Paint(
Painter &p,
not_null<const FakeRow*> row,
const PaintContext &context) {
auto item = row->item();
auto history = item->history();
const auto item = row->item();
const auto topic = context.forum ? row->topic() : nullptr;
const auto history = topic ? nullptr : item->history().get();
const auto entry = topic ? (Entry*)topic : (Entry*)history;
auto cloudDraft = nullptr;
const auto from = [&] {
if (row->searchInChat()) {
return item->displayFrom();
}
return history->peer->migrateTo()
return topic
? nullptr
: row->searchInChat()
? item->displayFrom()
: history->peer->migrateTo()
? history->peer->migrateTo()
: history->peer.get();
}();
@ -971,7 +972,9 @@ void RowPainter::Paint(
return nullptr;
}();
const auto previewOptions = [&]() -> HistoryView::ToPreviewOptions {
if (const auto searchChat = row->searchInChat()) {
if (topic) {
return {};
} else if (const auto searchChat = row->searchInChat()) {
if (const auto peer = searchChat.peer()) {
if (!peer->isChannel() || peer->isMegagroup()) {
return { .hideSender = true };
@ -982,7 +985,7 @@ void RowPainter::Paint(
}();
const auto badgesState = context.displayUnreadInfo
? history->chatListBadgesState()
? entry->chatListBadgesState()
: BadgesState();
const auto displayPinnedIcon = false;
@ -1007,17 +1010,18 @@ void RowPainter::Paint(
}
row->itemView().paint(p, itemRect, context);
};
const auto showSavedMessages = history->peer->isSelf()
const auto showSavedMessages = history
&& history->peer->isSelf()
&& !row->searchInChat();
const auto showRepliesMessages = history->peer->isRepliesChat()
const auto showRepliesMessages = history
&& history->peer->isRepliesChat()
&& !row->searchInChat();
const auto flags = (showSavedMessages ? Flag::SavedMessages : Flag(0))
| (showRepliesMessages ? Flag::RepliesMessages : Flag(0));
PaintRow(
p,
row,
history,
history,
entry,
nullptr,
from,
row->badge(),

View file

@ -334,8 +334,7 @@ HistoryMessage::HistoryMessage(
config.replyTo = data.is_reply_to_scheduled()
? history->owner().scheduledMessages().localMessageId(id)
: id;
config.replyToTop = data.vreply_to_top_id().value_or(
data.vreply_to_msg_id().v);
config.replyToTop = data.vreply_to_top_id().value_or(id);
config.replyIsTopicPost = data.is_forum_topic();
});
}
@ -385,9 +384,9 @@ HistoryMessage::HistoryMessage(
? peerFromMTP(*data.vreply_to_peer_id())
: history->peer->id;
if (!peer || peer == history->peer->id) {
config.replyTo = data.vreply_to_msg_id().v;
config.replyToTop = data.vreply_to_top_id().value_or(
data.vreply_to_msg_id().v);
const auto id = data.vreply_to_msg_id().v;
config.replyTo = id;
config.replyToTop = data.vreply_to_top_id().value_or(id);
}
});
}

View file

@ -1607,9 +1607,9 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
dependent->peerId = (peerId != history()->peer->id)
? peerId
: 0;
dependent->msgId = data.vreply_to_msg_id().v;
dependent->topId = data.vreply_to_top_id().value_or(
data.vreply_to_msg_id().v);
const auto id = data.vreply_to_msg_id().v;
dependent->msgId = id;
dependent->topId = data.vreply_to_top_id().value_or(id);
dependent->topicPost = data.is_forum_topic()
|| Has<HistoryServiceTopicInfo>();
if (!updateDependent()) {