Hashtag search results as dialogs (support).

This commit is contained in:
John Preston 2018-10-09 18:36:06 +03:00
parent 81a9554caa
commit 631e51a493
6 changed files with 264 additions and 89 deletions

View file

@ -641,6 +641,43 @@ void ApiWrap::requestDialogEntry(
}).send();
}
void ApiWrap::requestDialogEntries(
std::vector<not_null<History*>> histories) {
const auto already = [&](not_null<History*> history) {
const auto [i, ok] = _dialogRequests.try_emplace(history);
return !ok;
};
histories.erase(ranges::remove_if(histories, already), end(histories));
if (histories.empty()) {
return;
}
auto peers = QVector<MTPInputDialogPeer>();
peers.reserve(histories.size());
for (const auto history : histories) {
peers.push_back(MTP_inputDialogPeer(history->peer->input));
}
const auto finalize = [=](std::vector<not_null<History*>> histories) {
for (const auto history : histories) {
if (const auto callbacks = _dialogRequests.take(history)) {
for (const auto callback : *callbacks) {
callback();
}
}
}
};
request(MTPmessages_GetPeerDialogs(
MTP_vector(std::move(peers))
)).done([=](const MTPmessages_PeerDialogs &result) {
applyPeerDialogs(result);
for (const auto history : histories) {
historyDialogEntryApplied(history);
}
finalize(histories);
}).fail([=](const RPCError &error) {
finalize(histories);
}).send();
}
void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) {
Expects(dialogs.type() == mtpc_messages_peerDialogs);

View file

@ -87,6 +87,7 @@ public:
void requestDialogEntry(
not_null<History*> history,
Fn<void()> callback = nullptr);
void requestDialogEntries(std::vector<not_null<History*>> histories);
//void applyFeedSources(const MTPDchannels_feedSources &data); // #feed
//void setFeedChannels(
// not_null<Data::Feed*> feed,

View file

@ -451,9 +451,12 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
}
}
const auto showUnreadInSearchResults = uniqueSearchResults();
if (!_waitingForSearch || !_searchResults.empty()) {
const auto text = _searchResults.empty()
? lang(lng_search_no_results)
: showUnreadInSearchResults
? qsl("Search results")
: lng_search_found_results(
lt_count,
_searchedMigratedCount + _searchedCount);
@ -489,7 +492,8 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
active,
selected,
paintingOther,
ms);
ms,
showUnreadInSearchResults);
p.translate(0, st::dialogsRowHeight);
}
}
@ -674,7 +678,6 @@ void DialogsInner::paintSearchInFeed(
paintSearchInFilter(p, paintUserpic, top, fullWidth, icon, text);
}
void DialogsInner::activate() {
}
@ -1840,28 +1843,53 @@ void DialogsInner::addAllSavedPeers() {
addSavedPeersAfter(QDateTime());
}
bool DialogsInner::uniqueSearchResults() const {
return Auth().supportMode()
&& _filter.startsWith('#')
&& !_searchInChat;
}
bool DialogsInner::hasHistoryInSearchResults(not_null<History*> history) const {
using Result = std::unique_ptr<Dialogs::FakeRow>;
return ranges::find(
_searchResults,
history,
[](const Result &result) { return result->item()->history(); }
) != end(_searchResults);
}
bool DialogsInner::searchReceived(
const QVector<MTPMessage> &messages,
DialogsSearchRequestType type,
int fullCount) {
const auto uniquePeers = uniqueSearchResults();
if (type == DialogsSearchFromStart || type == DialogsSearchPeerFromStart) {
clearSearchResults(false);
}
auto isGlobalSearch = (type == DialogsSearchFromStart || type == DialogsSearchFromOffset);
auto isMigratedSearch = (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset);
auto unknownUnreadCounts = std::vector<not_null<History*>>();
TimeId lastDateFound = 0;
for_const (auto message, messages) {
auto msgId = idFromMessage(message);
auto peerId = peerFromMessage(message);
auto lastDate = dateFromMessage(message);
if (auto peer = App::peerLoaded(peerId)) {
if (const auto peer = App::peerLoaded(peerId)) {
if (lastDate) {
auto item = App::histories().addNewMessage(message, NewMessageExisting);
_searchResults.push_back(
std::make_unique<Dialogs::FakeRow>(
_searchInChat,
item));
const auto item = App::histories().addNewMessage(
message,
NewMessageExisting);
const auto history = item->history();
if (!uniquePeers || !hasHistoryInSearchResults(history)) {
_searchResults.push_back(
std::make_unique<Dialogs::FakeRow>(
_searchInChat,
item));
if (uniquePeers && !history->unreadCountKnown()) {
unknownUnreadCounts.push_back(history);
}
}
lastDateFound = lastDate;
if (isGlobalSearch) {
_lastSearchDate = lastDateFound;
@ -1891,7 +1919,12 @@ bool DialogsInner::searchReceived(
|| type == DialogsSearchMigratedFromOffset)) {
_waitingForSearch = false;
}
refresh();
if (!unknownUnreadCounts.empty()) {
Auth().api().requestDialogEntries(std::move(unknownUnreadCounts));
}
return lastDateFound != 0;
}
@ -2476,7 +2509,9 @@ bool DialogsInner::chooseRow() {
if (const auto history = chosen.key.history()) {
App::main()->choosePeer(
history->peer->id,
chosen.message.fullId.msg);
(uniqueSearchResults()
? ShowAtUnreadMsgId
: chosen.message.fullId.msg));
} else if (const auto feed = chosen.key.feed()) {
_controller->showSection(
HistoryFeed::Memento(feed, chosen.message),

View file

@ -189,6 +189,8 @@ private:
void handlePeerNameChange(
not_null<PeerData*> peer,
const base::flat_set<QChar> &oldLetters);
bool uniqueSearchResults() const;
bool hasHistoryInSearchResults(not_null<History*> history) const;
void applyDialog(const MTPDdialog &dialog);
// void applyFeedDialog(const MTPDdialogFeed &dialog); // #feed

View file

@ -52,6 +52,102 @@ void paintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, b
paintRowTopRight(p, dt, rectForName, active, selected);
}
void PaintNarrowCounter(
Painter &p,
bool displayUnreadCounter,
bool displayUnreadMark,
bool displayMentionBadge,
int unreadCount,
bool active,
bool unreadMuted) {
auto skipBeforeMention = 0;
if (displayUnreadCounter || displayUnreadMark) {
auto counter = (unreadCount > 0)
? QString::number(unreadCount)
: QString();
const auto allowDigits = displayMentionBadge ? 1 : 3;
if (counter.size() > allowDigits + 1) {
counter = qsl("..") + counter.mid(counter.size() - allowDigits);
}
auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize;
auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = unreadMuted;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
skipBeforeMention += unreadWidth + st.padding;
}
if (displayMentionBadge) {
auto counter = qsl("@");
auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize - skipBeforeMention;
auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = false;
st.padding = 0;
st.textTop = 0;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
}
}
int PaintWideCounter(
Painter &p,
int texttop,
int availableWidth,
int fullWidth,
bool displayUnreadCounter,
bool displayUnreadMark,
bool displayMentionBadge,
bool displayPinnedIcon,
int unreadCount,
bool active,
bool selected,
bool unreadMuted) {
const auto initial = availableWidth;
auto hadOneBadge = false;
if (displayUnreadCounter || displayUnreadMark) {
auto counter = (unreadCount > 0)
? QString::number(unreadCount)
: QString();
auto unreadRight = fullWidth - st::dialogsPadding.x();
auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = unreadMuted;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
availableWidth -= unreadWidth + st.padding;
hadOneBadge = true;
} else if (displayPinnedIcon) {
auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon));
icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth);
availableWidth -= icon.width() + st::dialogsUnreadPadding;
hadOneBadge = true;
}
if (displayMentionBadge) {
auto counter = qsl("@");
auto unreadRight = fullWidth - st::dialogsPadding.x() - (initial - availableWidth);
auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = false;
st.padding = 0;
st.textTop = 0;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
availableWidth -= unreadWidth + st.padding + (hadOneBadge ? st::dialogsUnreadPadding : 0);
}
return availableWidth;
}
enum class Flag {
Active = 0x01,
Selected = 0x02,
@ -370,7 +466,13 @@ UnreadBadgeStyle::UnreadBadgeStyle()
, font(st::dialogsUnreadFont) {
}
void paintUnreadCount(Painter &p, const QString &text, int x, int y, const UnreadBadgeStyle &st, int *outUnreadWidth) {
void paintUnreadCount(
Painter &p,
const QString &text,
int x,
int y,
const UnreadBadgeStyle &st,
int *outUnreadWidth) {
int unreadWidth = st.font->width(text);
int unreadRectWidth = unreadWidth + 2 * st.padding;
int unreadRectHeight = st.size;
@ -464,45 +566,22 @@ void RowPainter::paint(
| (onlyBackground ? Flag::OnlyBackground : Flag(0))
| (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0));
const auto paintItemCallback = [&](int nameleft, int namewidth) {
auto availableWidth = namewidth;
auto texttop = st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip;
auto hadOneBadge = false;
if (displayUnreadCounter || displayUnreadMark) {
auto counter = (unreadCount > 0)
? QString::number(unreadCount)
: QString();
auto unreadRight = fullWidth - st::dialogsPadding.x();
auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = unreadMuted;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
availableWidth -= unreadWidth + st.padding;
hadOneBadge = true;
} else if (displayPinnedIcon) {
auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon));
icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth);
availableWidth -= icon.width() + st::dialogsUnreadPadding;
hadOneBadge = true;
}
if (displayMentionBadge) {
auto counter = qsl("@");
auto unreadRight = fullWidth - st::dialogsPadding.x() - (namewidth - availableWidth);
auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = false;
st.padding = 0;
st.textTop = 0;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
availableWidth -= unreadWidth + st.padding + (hadOneBadge ? st::dialogsUnreadPadding : 0);
}
const auto texttop = st::dialogsPadding.y()
+ st::msgNameFont->height
+ st::dialogsSkip;
const auto availableWidth = PaintWideCounter(
p,
texttop,
namewidth,
fullWidth,
displayUnreadCounter,
displayUnreadMark,
displayMentionBadge,
displayPinnedIcon,
unreadCount,
active,
selected,
unreadMuted);
const auto &color = active
? st::dialogsTextFgServiceActive
: (selected
@ -517,7 +596,7 @@ void RowPainter::paint(
color,
ms) : false;
if (!actionWasPainted) {
auto itemRect = QRect(
const auto itemRect = QRect(
nameleft,
texttop,
availableWidth,
@ -533,39 +612,14 @@ void RowPainter::paint(
}
};
const auto paintCounterCallback = [&] {
auto hadOneBadge = false;
auto skipBeforeMention = 0;
if (displayUnreadCounter || displayUnreadMark) {
auto counter = (unreadCount > 0)
? QString::number(unreadCount)
: QString();
const auto allowDigits = displayMentionBadge ? 1 : 3;
if (counter.size() > allowDigits + 1) {
counter = qsl("..") + counter.mid(counter.size() - allowDigits);
}
auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize;
auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = unreadMuted;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
skipBeforeMention += unreadWidth + st.padding;
}
if (displayMentionBadge) {
auto counter = qsl("@");
auto unreadRight = st::dialogsPadding.x() + st::dialogsPhotoSize - skipBeforeMention;
auto unreadTop = st::dialogsPadding.y() + st::dialogsPhotoSize - st::dialogsUnreadHeight;
auto unreadWidth = 0;
UnreadBadgeStyle st;
st.active = active;
st.muted = false;
st.padding = 0;
st.textTop = 0;
paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth);
}
PaintNarrowCounter(
p,
displayUnreadCounter,
displayUnreadMark,
displayMentionBadge,
unreadCount,
active,
unreadMuted);
};
paintRow(
p,
@ -590,7 +644,8 @@ void RowPainter::paint(
bool active,
bool selected,
bool onlyBackground,
TimeMs ms) {
TimeMs ms,
bool displayUnreadInfo) {
auto item = row->item();
auto history = item->history();
auto cloudDraft = nullptr;
@ -618,19 +673,63 @@ void RowPainter::paint(
}
return HistoryItem::DrawInDialog::Normal;
}();
const auto unreadCount = displayUnreadInfo
? history->chatListUnreadCount()
: 0;
const auto unreadMark = displayUnreadInfo
&& history->chatListUnreadMark();
const auto unreadMuted = history->chatListMutedBadge();
const auto displayMentionBadge = displayUnreadInfo
&& history->hasUnreadMentions();
const auto displayUnreadCounter = (unreadCount > 0);
const auto displayUnreadMark = !displayUnreadCounter
&& !displayMentionBadge
&& unreadMark;
const auto displayPinnedIcon = false;
const auto paintItemCallback = [&](int nameleft, int namewidth) {
auto lastWidth = namewidth;
auto texttop = st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip;
const auto texttop = st::dialogsPadding.y()
+ st::msgNameFont->height
+ st::dialogsSkip;
const auto availableWidth = PaintWideCounter(
p,
texttop,
namewidth,
fullWidth,
displayUnreadCounter,
displayUnreadMark,
displayMentionBadge,
displayPinnedIcon,
unreadCount,
active,
selected,
unreadMuted);
const auto itemRect = QRect(
nameleft,
texttop,
availableWidth,
st::dialogsTextFont->height);
item->drawInDialog(
p,
QRect(nameleft, texttop, lastWidth, st::dialogsTextFont->height),
itemRect,
active,
selected,
drawInDialogWay,
row->_cacheFor,
row->_cache);
};
const auto paintCounterCallback = [] {};
const auto paintCounterCallback = [&] {
PaintNarrowCounter(
p,
displayUnreadCounter,
displayUnreadMark,
displayMentionBadge,
unreadCount,
active,
unreadMuted);
};
const auto showSavedMessages = history->peer->isSelf()
&& !row->searchInChat();
const auto flags = (active ? Flag::Active : Flag(0))

View file

@ -44,7 +44,8 @@ public:
bool active,
bool selected,
bool onlyBackground,
TimeMs ms);
TimeMs ms,
bool displayUnreadInfo);
static QRect sendActionAnimationRect(
int animationWidth,
int animationHeight,