Improve archive chat list entry layout.

This commit is contained in:
John Preston 2019-04-23 16:29:23 +04:00
parent 2d1dcb36cb
commit 9ff02707bf
13 changed files with 291 additions and 50 deletions

View File

@ -304,7 +304,7 @@ historyPeer8NameFgSelected: historyPeer8NameFg; // orange group member name in a
historyPeer8UserpicBg: #faa774; // orange userpic background historyPeer8UserpicBg: #faa774; // orange userpic background
historyPeerUserpicFg: windowFgActive; // default userpic initials historyPeerUserpicFg: windowFgActive; // default userpic initials
historyPeerSavedMessagesBg: historyPeer4UserpicBg; // saved messages userpic background historyPeerSavedMessagesBg: historyPeer4UserpicBg; // saved messages userpic background
historyPeerArchiveUserpicBg: historyPeer2UserpicBg; // archive folder userpic background historyPeerArchiveUserpicBg: dialogsUnreadBgMuted; // archive folder userpic background
// Some values are marked as (adjusted), it means they're adjusted by // Some values are marked as (adjusted), it means they're adjusted by
// hue and saturation of the average background color if user chooses // hue and saturation of the average background color if user chooses

View File

@ -1195,11 +1195,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_saved_short" = "Save"; "lng_saved_short" = "Save";
"lng_saved_forward_here" = "Forward messages here for quick access"; "lng_saved_forward_here" = "Forward messages here for quick access";
"lng_archived_chats" = "Archived chats"; "lng_archived_name" = "Archived chats";
"lng_archived_add" = "Archive"; "lng_archived_add" = "Archive";
"lng_archived_remove" = "Unarchive"; "lng_archived_remove" = "Unarchive";
"lng_chat_archived" = "Chat archived.\nMuted chats will stay archived after new messages arrive."; "lng_archived_added" = "Chat archived.\nMuted chats will stay archived after new messages arrive.";
"lng_chat_unarchived" = "Chat restored from your archive."; "lng_archived_removed" = "Chat restored from your archive.";
"lng_archived_chats#one" = "{count} chat";
"lng_archived_chats#other" = "{count} chats";
"lng_archived_unread_two" = "{chat}, {second_chat}";
"lng_archived_unread#one" = "{chat}, {second_chat} and {count} more unread chat";
"lng_archived_unread#other" = "{chat}, {second_chat} and {count} more unread chats";
"lng_dialogs_text_with_from" = "{from_part} {message}"; "lng_dialogs_text_with_from" = "{from_part} {message}";
"lng_dialogs_text_from_wrapped" = "{from}:"; "lng_dialogs_text_from_wrapped" = "{from}:";

View File

@ -744,26 +744,33 @@ void ApiWrap::requestMoreDialogs(Data::Folder *folder) {
MTP_int(hash) MTP_int(hash)
)).done([=](const MTPmessages_Dialogs &result) { )).done([=](const MTPmessages_Dialogs &result) {
const auto state = dialogsLoadState(folder); const auto state = dialogsLoadState(folder);
const auto count = result.match([](
const MTPDmessages_dialogsNotModified &) {
LOG(("API Error: not-modified received for requested dialogs."));
return 0;
}, [&](const MTPDmessages_dialogs &data) {
if (state) {
state->listReceived = true;
dialogsLoadFinish(folder); // may kill 'state'.
}
return int(data.vdialogs.v.size());
}, [&](const MTPDmessages_dialogsSlice &data) {
updateDialogsOffset(
folder,
data.vdialogs.v,
data.vmessages.v);
return data.vcount.v;
});
result.match([](const MTPDmessages_dialogsNotModified & data) { result.match([](const MTPDmessages_dialogsNotModified & data) {
LOG(("API Error: not-modified received for requested dialogs.")); LOG(("API Error: not-modified received for requested dialogs."));
}, [&](const auto &data) { }, [&](const auto &data) {
if constexpr (data.Is<MTPDmessages_dialogs>()) {
if (state) {
state->listReceived = true;
dialogsLoadFinish(folder); // may kill 'state'.
}
} else {
updateDialogsOffset(
folder,
data.vdialogs.v,
data.vmessages.v);
}
_session->data().processUsers(data.vusers); _session->data().processUsers(data.vusers);
_session->data().processChats(data.vchats); _session->data().processChats(data.vchats);
_session->data().applyDialogs( _session->data().applyDialogs(
folder, folder,
data.vmessages.v, data.vmessages.v,
data.vdialogs.v); data.vdialogs.v,
count);
}); });
if (!folder) { if (!folder) {

View File

@ -25,6 +25,7 @@ namespace Data {
namespace { namespace {
constexpr auto kLoadedChatsMinCount = 20; constexpr auto kLoadedChatsMinCount = 20;
constexpr auto kShowChatNamesCount = 2;
rpl::producer<int> PinnedDialogsInFolderMaxValue() { rpl::producer<int> PinnedDialogsInFolderMaxValue() {
return rpl::single( return rpl::single(
@ -52,7 +53,7 @@ Folder::Folder(not_null<Data::Session*> owner, FolderId id)
: Entry(owner, this) : Entry(owner, this)
, _id(id) , _id(id)
, _chatsList(PinnedDialogsInFolderMaxValue()) , _chatsList(PinnedDialogsInFolderMaxValue())
, _name(lang(lng_archived_chats)) { , _name(lang(lng_archived_name)) {
indexNameParts(); indexNameParts();
} }
@ -89,6 +90,9 @@ void Folder::indexNameParts() {
void Folder::registerOne(not_null<History*> history) { void Folder::registerOne(not_null<History*> history) {
if (_chatsList.indexed()->size() == 1) { if (_chatsList.indexed()->size() == 1) {
updateChatListSortPosition(); updateChatListSortPosition();
} else {
++_chatListViewVersion;
updateChatListEntry();
} }
applyChatListMessage(history->chatListMessage()); applyChatListMessage(history->chatListMessage());
} }
@ -96,6 +100,9 @@ void Folder::registerOne(not_null<History*> history) {
void Folder::unregisterOne(not_null<History*> history) { void Folder::unregisterOne(not_null<History*> history) {
if (_chatsList.empty()) { if (_chatsList.empty()) {
updateChatListExistence(); updateChatListExistence();
} else {
++_chatListViewVersion;
updateChatListEntry();
} }
if (_chatListMessage && _chatListMessage->history() == history) { if (_chatListMessage && _chatListMessage->history() == history) {
computeChatListMessage(); computeChatListMessage();
@ -106,6 +113,12 @@ void Folder::oneListMessageChanged(HistoryItem *from, HistoryItem *to) {
if (!applyChatListMessage(to) && _chatListMessage == from) { if (!applyChatListMessage(to) && _chatListMessage == from) {
computeChatListMessage(); computeChatListMessage();
} }
if (from || to) {
const auto history = from ? from->history() : to->history();
if (!history->chatListUnreadState().empty()) {
reorderUnreadHistories();
}
}
} }
bool Folder::applyChatListMessage(HistoryItem *item) { bool Folder::applyChatListMessage(HistoryItem *item) {
@ -141,6 +154,55 @@ void Folder::computeChatListMessage() {
updateChatListEntry(); updateChatListEntry();
} }
void Folder::addUnreadHistory(not_null<History*> history) {
const auto i = ranges::find(_unreadHistories, history);
if (i == end(_unreadHistories)) {
_unreadHistories.push_back(history);
reorderUnreadHistories();
}
}
void Folder::removeUnreadHistory(not_null<History*> history) {
const auto i = ranges::find(_unreadHistories, history);
if (i != end(_unreadHistories)) {
_unreadHistories.erase(i);
reorderUnreadHistories();
}
}
void Folder::reorderUnreadHistories() {
// We want first kShowChatNamesCount histories, by last message date.
const auto predicate = [](not_null<History*> a, not_null<History*> b) {
const auto aItem = a->chatListMessage();
const auto bItem = b->chatListMessage();
const auto aDate = aItem ? aItem->date() : TimeId(0);
const auto bDate = bItem ? bItem->date() : TimeId(0);
return aDate > bDate;
};
if (size(_unreadHistories) <= kShowChatNamesCount) {
ranges::sort(_unreadHistories, predicate);
if (!ranges::equal(_unreadHistories, _unreadHistoriesLast)) {
_unreadHistoriesLast = _unreadHistories;
}
} else {
const auto till = begin(_unreadHistories) + kShowChatNamesCount - 1;
ranges::nth_element(_unreadHistories, till, predicate);
if constexpr (kShowChatNamesCount > 2) {
ranges::sort(begin(_unreadHistories), till, predicate);
}
auto &&head = ranges::view::all(
_unreadHistories
) | ranges::view::take_exactly(
kShowChatNamesCount
);
if (!ranges::equal(head, _unreadHistoriesLast)) {
_unreadHistoriesLast = head | ranges::to_vector;
}
}
++_chatListViewVersion;
updateChatListEntry();
}
not_null<Dialogs::MainList*> Folder::chatsList() { not_null<Dialogs::MainList*> Folder::chatsList() {
return &_chatsList; return &_chatsList;
} }
@ -194,6 +256,29 @@ void Folder::setChatsListLoaded(bool loaded) {
_chatsList.setLoaded(loaded); _chatsList.setLoaded(loaded);
} }
void Folder::setCloudChatsListSize(int size) {
_cloudChatsListSize = size;
updateChatListEntry();
}
int Folder::chatsListSize() const {
return std::max(
_chatsList.indexed()->size(),
_chatsList.loaded() ? 0 : _cloudChatsListSize);
}
int Folder::unreadHistoriesCount() const {
return _unreadHistories.size();
}
const std::vector<not_null<History*>> &Folder::lastUnreadHistories() const {
return _unreadHistoriesLast;
}
uint32 Folder::chatListViewVersion() const {
return _chatListViewVersion;
}
void Folder::requestChatListMessage() { void Folder::requestChatListMessage() {
if (!chatListMessageKnown()) { if (!chatListMessageKnown()) {
session().api().requestDialogEntry(this); session().api().requestDialogEntry(this);
@ -252,8 +337,17 @@ void Folder::applyPinnedUpdate(const MTPDupdateDialogPinned &data) {
} }
void Folder::unreadStateChanged( void Folder::unreadStateChanged(
const Dialogs::Key &key,
const Dialogs::UnreadState &wasState, const Dialogs::UnreadState &wasState,
const Dialogs::UnreadState &nowState) { const Dialogs::UnreadState &nowState) {
if (const auto history = key.history()) {
if (!wasState.empty() && nowState.empty()) {
removeUnreadHistory(history);
} else if (wasState.empty() && !nowState.empty()) {
addUnreadHistory(history);
}
}
const auto updateCloudUnread = _cloudUnread.messagesCount.has_value() const auto updateCloudUnread = _cloudUnread.messagesCount.has_value()
&& wasState.messagesCount.has_value(); && wasState.messagesCount.has_value();
const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notify = _chatsList.loaded() || updateCloudUnread;
@ -276,8 +370,19 @@ void Folder::unreadStateChanged(
} }
void Folder::unreadEntryChanged( void Folder::unreadEntryChanged(
const Dialogs::Key &key,
const Dialogs::UnreadState &state, const Dialogs::UnreadState &state,
bool added) { bool added) {
if (const auto history = key.history()) {
if (!state.empty()) {
if (added) {
addUnreadHistory(history);
} else {
removeUnreadHistory(history);
}
}
}
const auto updateCloudUnread = _cloudUnread.messagesCount.has_value() const auto updateCloudUnread = _cloudUnread.messagesCount.has_value()
&& state.messagesCount.has_value(); && state.messagesCount.has_value();
const auto notify = _chatsList.loaded() || updateCloudUnread; const auto notify = _chatsList.loaded() || updateCloudUnread;

View File

@ -44,9 +44,13 @@ public:
void updateCloudUnread(const MTPDdialogFolder &data); void updateCloudUnread(const MTPDdialogFolder &data);
void unreadStateChanged( void unreadStateChanged(
const Dialogs::Key &key,
const Dialogs::UnreadState &wasState, const Dialogs::UnreadState &wasState,
const Dialogs::UnreadState &nowState); const Dialogs::UnreadState &nowState);
void unreadEntryChanged(const Dialogs::UnreadState &state, bool added); void unreadEntryChanged(
const Dialogs::Key &key,
const Dialogs::UnreadState &state,
bool added);
TimeId adjustedChatListTimeId() const override; TimeId adjustedChatListTimeId() const override;
@ -73,12 +77,22 @@ public:
bool chatsListLoaded() const; bool chatsListLoaded() const;
void setChatsListLoaded(bool loaded = true); void setChatsListLoaded(bool loaded = true);
void setCloudChatsListSize(int size);
int chatsListSize() const;
int unreadHistoriesCount() const;
const std::vector<not_null<History*>> &lastUnreadHistories() const;
uint32 chatListViewVersion() const;
private: private:
void indexNameParts(); void indexNameParts();
bool applyChatListMessage(HistoryItem *item); bool applyChatListMessage(HistoryItem *item);
void computeChatListMessage(); void computeChatListMessage();
void addUnreadHistory(not_null<History*> history);
void removeUnreadHistory(not_null<History*> history);
void reorderUnreadHistories();
FolderId _id = 0; FolderId _id = 0;
Dialogs::MainList _chatsList; Dialogs::MainList _chatsList;
@ -87,7 +101,11 @@ private:
base::flat_set<QChar> _nameFirstLetters; base::flat_set<QChar> _nameFirstLetters;
Dialogs::UnreadState _cloudUnread; Dialogs::UnreadState _cloudUnread;
int _cloudChatsListSize = 0;
std::vector<not_null<History*>> _unreadHistories;
std::vector<not_null<History*>> _unreadHistoriesLast;
HistoryItem *_chatListMessage = nullptr; HistoryItem *_chatListMessage = nullptr;
uint32 _chatListViewVersion = 0;
//rpl::variable<MessagePosition> _unreadPosition; //rpl::variable<MessagePosition> _unreadPosition;
}; };

View File

@ -1375,13 +1375,17 @@ void Session::applyPinnedChats(
void Session::applyDialogs( void Session::applyDialogs(
Data::Folder *requestFolder, Data::Folder *requestFolder,
const QVector<MTPMessage> &messages, const QVector<MTPMessage> &messages,
const QVector<MTPDialog> &dialogs) { const QVector<MTPDialog> &dialogs,
std::optional<int> count) {
App::feedMsgs(messages, NewMessageLast); App::feedMsgs(messages, NewMessageLast);
for (const auto &dialog : dialogs) { for (const auto &dialog : dialogs) {
dialog.match([&](const auto &data) { dialog.match([&](const auto &data) {
applyDialog(requestFolder, data); applyDialog(requestFolder, data);
}); });
} }
if (requestFolder && count) {
requestFolder->setCloudChatsListSize(*count);
}
} }
void Session::applyDialog( void Session::applyDialog(
@ -1663,7 +1667,7 @@ void Session::unreadStateChanged(
const auto nowState = key.entry()->chatListUnreadState(); const auto nowState = key.entry()->chatListUnreadState();
if (const auto folder = key.entry()->folder()) { if (const auto folder = key.entry()->folder()) {
folder->unreadStateChanged(wasState, nowState); folder->unreadStateChanged(key, wasState, nowState);
} else { } else {
_chatsList.unreadStateChanged(wasState, nowState); _chatsList.unreadStateChanged(wasState, nowState);
} }
@ -1674,10 +1678,12 @@ void Session::unreadEntryChanged(const Dialogs::Key &key, bool added) {
Expects(key.entry()->folderKnown()); Expects(key.entry()->folderKnown());
const auto state = key.entry()->chatListUnreadState(); const auto state = key.entry()->chatListUnreadState();
if (const auto folder = key.entry()->folder()) { if (!state.empty()) {
folder->unreadEntryChanged(state, added); if (const auto folder = key.entry()->folder()) {
} else { folder->unreadEntryChanged(key, state, added);
_chatsList.unreadEntryChanged(state, added); } else {
_chatsList.unreadEntryChanged(state, added);
}
} }
} }

View File

@ -296,7 +296,8 @@ public:
void applyDialogs( void applyDialogs(
Data::Folder *requestFolder, Data::Folder *requestFolder,
const QVector<MTPMessage> &messages, const QVector<MTPMessage> &messages,
const QVector<MTPDialog> &dialogs); const QVector<MTPDialog> &dialogs,
std::optional<int> count = std::nullopt);
void addSavedPeersAfter(const QDateTime &date); void addSavedPeersAfter(const QDateTime &date);
void addAllSavedPeers(); void addAllSavedPeers();

View File

@ -47,6 +47,10 @@ struct UnreadState {
int chatsCountMuted = 0; int chatsCountMuted = 0;
bool mark = false; bool mark = false;
bool markMuted = false; bool markMuted = false;
bool empty() const {
return !messagesCount.value_or(0) && !chatsCount && !mark;
}
}; };
class Entry { class Entry {

View File

@ -34,7 +34,7 @@ bool ShowUserBotIcon(not_null<UserData*> user) {
return user->isBot() && !user->isSupport(); return user->isBot() && !user->isSupport();
} }
void paintRowTopRight(Painter &p, const QString &text, QRect &rectForName, bool active, bool selected) { void PaintRowTopRight(Painter &p, const QString &text, QRect &rectForName, bool active, bool selected) {
const auto width = st::dialogsDateFont->width(text); const auto width = st::dialogsDateFont->width(text);
rectForName.setWidth(rectForName.width() - width - st::dialogsDateSkip); rectForName.setWidth(rectForName.width() - width - st::dialogsDateSkip);
p.setFont(st::dialogsDateFont); p.setFont(st::dialogsDateFont);
@ -42,7 +42,7 @@ void paintRowTopRight(Painter &p, const QString &text, QRect &rectForName, bool
p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::msgNameFont->height - st::msgDateFont->descent, text); p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::msgNameFont->height - st::msgDateFont->descent, text);
} }
void paintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, bool selected) { void PaintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, bool selected) {
const auto now = QDateTime::currentDateTime(); const auto now = QDateTime::currentDateTime();
const auto &lastTime = date; const auto &lastTime = date;
const auto nowDate = now.date(); const auto nowDate = now.date();
@ -60,7 +60,7 @@ void paintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, b
return lastDate.toString(qsl("d.MM.yy")); return lastDate.toString(qsl("d.MM.yy"));
} }
}(); }();
paintRowTopRight(p, dt, rectForName, active, selected); PaintRowTopRight(p, dt, rectForName, active, selected);
} }
void PaintNarrowCounter( void PaintNarrowCounter(
@ -159,6 +159,38 @@ int PaintWideCounter(
return availableWidth; return availableWidth;
} }
void PaintListEntryText(
Painter &p,
QRect rect,
bool active,
bool selected,
not_null<const Row*> row) {
if (rect.isEmpty()) {
return;
}
row->validateListEntryCache();
const auto &palette = active
? st::dialogsTextPaletteActive
: selected
? st::dialogsTextPaletteOver
: st::dialogsTextPalette;
const auto &color = active
? st::dialogsTextFgActive
: selected
? st::dialogsTextFgOver
: st::dialogsTextFg;
p.setTextPalette(palette);
p.setFont(st::dialogsTextFont);
p.setPen(color);
row->listEntryCache().drawElided(
p,
rect.left(),
rect.top(),
rect.width(),
rect.height() / st::dialogsTextFont->height);
p.restoreTextPalette();
}
enum class Flag { enum class Flag {
Active = 0x01, Active = 0x01,
Selected = 0x02, Selected = 0x02,
@ -255,7 +287,7 @@ void paintRow(
&& !(flags & (Flag::SearchResult/* | Flag::FeedSearchResult*/)); // #feed && !(flags & (Flag::SearchResult/* | Flag::FeedSearchResult*/)); // #feed
if (promoted) { if (promoted) {
const auto text = lang(lng_proxy_sponsor); const auto text = lang(lng_proxy_sponsor);
paintRowTopRight(p, text, rectForName, active, selected); PaintRowTopRight(p, text, rectForName, active, selected);
} else if (from/* && !(flags & Flag::FeedSearchResult)*/) { // #feed } else if (from/* && !(flags & Flag::FeedSearchResult)*/) { // #feed
if (const auto chatTypeIcon = ChatTypeIcon(from, active, selected)) { if (const auto chatTypeIcon = ChatTypeIcon(from, active, selected)) {
chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth); chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth);
@ -274,7 +306,7 @@ void paintRow(
|| (supportMode || (supportMode
&& Auth().supportHelper().isOccupiedBySomeone(history))) { && Auth().supportHelper().isOccupiedBySomeone(history))) {
if (!promoted) { if (!promoted) {
paintRowDate(p, date, rectForName, active, selected); PaintRowDate(p, date, rectForName, active, selected);
} }
auto availableWidth = namewidth; auto availableWidth = namewidth;
@ -318,7 +350,7 @@ void paintRow(
} }
} else if (!item->isEmpty()) { } else if (!item->isEmpty()) {
if (!promoted) { if (!promoted) {
paintRowDate(p, date, rectForName, active, selected); PaintRowDate(p, date, rectForName, active, selected);
} }
paintItemCallback(nameleft, namewidth); paintItemCallback(nameleft, namewidth);
@ -560,7 +592,7 @@ void RowPainter::paint(
} }
return nullptr; return nullptr;
}(); }();
const auto displayDate = [item, cloudDraft] { const auto displayDate = [&] {
if (item) { if (item) {
if (cloudDraft) { if (cloudDraft) {
return (item->date() > cloudDraft->date) return (item->date() > cloudDraft->date)
@ -623,20 +655,22 @@ void RowPainter::paint(
: (selected : (selected
? st::dialogsTextFgServiceOver ? st::dialogsTextFgServiceOver
: st::dialogsTextFgService); : st::dialogsTextFgService);
const auto actionWasPainted = history ? history->paintSendAction( const auto itemRect = QRect(
p,
nameleft, nameleft,
texttop, texttop,
availableWidth, availableWidth,
st::dialogsTextFont->height);
const auto actionWasPainted = history ? history->paintSendAction(
p,
itemRect.x(),
itemRect.y(),
itemRect.width(),
fullWidth, fullWidth,
color, color,
ms) : false; ms) : false;
if (!actionWasPainted) { if (const auto folder = row->folder()) {
const auto itemRect = QRect( PaintListEntryText(p, itemRect, active, selected, row);
nameleft, } else if (!actionWasPainted) {
texttop,
availableWidth,
st::dialogsTextFont->height);
item->drawInDialog( item->drawInDialog(
p, p,
itemRect, itemRect,

View File

@ -7,12 +7,49 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "dialogs/dialogs_row.h" #include "dialogs/dialogs_row.h"
#include "styles/style_dialogs.h"
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "ui/text_options.h"
#include "dialogs/dialogs_entry.h" #include "dialogs/dialogs_entry.h"
#include "data/data_folder.h"
#include "history/history.h"
#include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "styles/style_dialogs.h"
namespace Dialogs { namespace Dialogs {
namespace {
QString ComposeFolderListEntryText(not_null<Data::Folder*> folder) {
const auto &list = folder->lastUnreadHistories();
if (list.empty()) {
const auto count = folder->chatsListSize();
if (!count) {
return QString();
}
return lng_archived_chats(lt_count, count);
}
const auto count = std::max(
int(list.size()),
folder->unreadHistoriesCount());
if (list.size() == 1) {
return App::peerName(list[0]->peer);
} else if (count == 2) {
return lng_archived_unread_two(
lt_chat,
App::peerName(list[0]->peer),
lt_second_chat,
App::peerName(list[1]->peer));
}
return lng_archived_unread(
lt_count,
count - 2,
lt_chat,
App::peerName(list[0]->peer),
lt_second_chat,
App::peerName(list[1]->peer));
}
} // namespace
RippleRow::RippleRow() = default; RippleRow::RippleRow() = default;
RippleRow::~RippleRow() = default; RippleRow::~RippleRow() = default;
@ -44,6 +81,22 @@ uint64 Row::sortKey() const {
return _id.entry()->sortKeyInChatList(); return _id.entry()->sortKeyInChatList();
} }
void Row::validateListEntryCache() const {
const auto folder = _id.folder();
if (!folder) {
return;
}
const auto version = folder->chatListViewVersion();
if (_listEntryCacheVersion == version) {
return;
}
_listEntryCacheVersion = version;
_listEntryCache.setText(
st::dialogsTextStyle,
ComposeFolderListEntryText(folder),
Ui::DialogTextOptions());
}
FakeRow::FakeRow(Key searchInChat, not_null<HistoryItem*> item) FakeRow::FakeRow(Key searchInChat, not_null<HistoryItem*> item)
: _searchInChat(searchInChat) : _searchInChat(searchInChat)
, _item(item) , _item(item)

View File

@ -62,6 +62,11 @@ public:
} }
uint64 sortKey() const; uint64 sortKey() const;
void validateListEntryCache() const;
const Text &listEntryCache() const {
return _listEntryCache;
}
// for any attached data, for example View in contacts list // for any attached data, for example View in contacts list
void *attached = nullptr; void *attached = nullptr;
@ -70,6 +75,8 @@ private:
Key _id; Key _id;
int _pos = 0; int _pos = 0;
mutable uint32 _listEntryCacheVersion = 0;
mutable Text _listEntryCache;
}; };

View File

@ -742,17 +742,18 @@ void HistoryItem::drawInDialog(
DrawInDialog way, DrawInDialog way,
const HistoryItem *&cacheFor, const HistoryItem *&cacheFor,
Text &cache) const { Text &cache) const {
if (r.isEmpty()) {
return;
}
if (cacheFor != this) { if (cacheFor != this) {
cacheFor = this; cacheFor = this;
cache.setText(st::dialogsTextStyle, inDialogsText(way), Ui::DialogTextOptions()); cache.setText(st::dialogsTextStyle, inDialogsText(way), Ui::DialogTextOptions());
} }
if (r.width()) { p.setTextPalette(active ? st::dialogsTextPaletteActive : (selected ? st::dialogsTextPaletteOver : st::dialogsTextPalette));
p.setTextPalette(active ? st::dialogsTextPaletteActive : (selected ? st::dialogsTextPaletteOver : st::dialogsTextPalette)); p.setFont(st::dialogsTextFont);
p.setFont(st::dialogsTextFont); p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg));
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg)); cache.drawElided(p, r.left(), r.top(), r.width(), r.height() / st::dialogsTextFont->height);
cache.drawElided(p, r.left(), r.top(), r.width(), r.height() / st::dialogsTextFont->height); p.restoreTextPalette();
p.restoreTextPalette();
}
} }
HistoryItem::~HistoryItem() { HistoryItem::~HistoryItem() {

View File

@ -796,8 +796,8 @@ void PeerMenuAddMuteAction(
void ToggleHistoryArchived(not_null<History*> history, bool archived) { void ToggleHistoryArchived(not_null<History*> history, bool archived) {
const auto callback = [=] { const auto callback = [=] {
Ui::Toast::Show(lang(archived Ui::Toast::Show(lang(archived
? lng_chat_archived ? lng_archived_added
: lng_chat_unarchived)); : lng_archived_removed));
}; };
history->session().api().toggleHistoryArchived( history->session().api().toggleHistoryArchived(
history, history,