Preload complex last message on demand.

This commit is contained in:
John Preston 2023-02-09 09:56:47 +04:00
parent 369862a3a7
commit f2ed77649e
11 changed files with 101 additions and 55 deletions

View file

@ -854,7 +854,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
if (((*i)->index() * _rowHeight) >= yTo) {
break;
}
(*i)->entry()->loadUserpic();
(*i)->entry()->chatListPreloadData();
}
}
} else if (!_filtered.empty()) {
@ -865,7 +865,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
if (to > _filtered.size()) to = _filtered.size();
for (; from < to; ++from) {
_filtered[from]->entry()->loadUserpic();
_filtered[from]->entry()->chatListPreloadData();
}
}
}

View file

@ -211,7 +211,7 @@ not_null<Dialogs::MainList*> Folder::chatsList() {
return &_chatsList;
}
void Folder::loadUserpic() {
void Folder::chatListPreloadData() {
}
void Folder::paintUserpic(

View file

@ -54,7 +54,7 @@ public:
const base::flat_set<QString> &chatListNameWords() const override;
const base::flat_set<QChar> &chatListFirstLetters() const override;
void loadUserpic() override;
void chatListPreloadData() override;
void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,

View file

@ -471,17 +471,7 @@ void ForumTopic::applyTopicTopMessage(MsgId topMessageId) {
const auto itemId = FullMsgId(channel()->id, topMessageId);
if (const auto item = owner().message(itemId)) {
setLastServerMessage(item);
// If we set a single album part, request the full album.
if (item->groupId() != MessageGroupId()) {
if (owner().groups().isGroupOfOne(item)
&& !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty()
&& _requestedGroups.emplace(item->fullId()).second) {
owner().histories().requestGroupAround(item);
}
}
resolveChatListMessageGroup();
} else {
setLastServerMessage(nullptr);
}
@ -490,6 +480,23 @@ void ForumTopic::applyTopicTopMessage(MsgId topMessageId) {
}
}
void ForumTopic::resolveChatListMessageGroup() {
if (!(_flags & Flag::ResolveChatListMessage)) {
return;
}
// If we set a single album part, request the full album.
const auto item = _lastServerMessage.value_or(nullptr);
if (item && item->groupId() != MessageGroupId()) {
if (owner().groups().isGroupOfOne(item)
&& !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty()
&& _requestedGroups.emplace(item->fullId()).second) {
owner().histories().requestGroupAround(item);
}
}
}
void ForumTopic::growLastKnownServerMessageId(MsgId id) {
_lastKnownServerMessageId = std::max(_lastKnownServerMessageId, id);
}
@ -548,10 +555,11 @@ void ForumTopic::setChatListMessage(HistoryItem *item) {
_forum->listMessageChanged(was, item);
}
void ForumTopic::loadUserpic() {
void ForumTopic::chatListPreloadData() {
if (_icon) {
[[maybe_unused]] const auto preload = _icon->ready();
}
allowChatListMessageResolve();
}
void ForumTopic::paintUserpic(
@ -840,6 +848,14 @@ Dialogs::UnreadState ForumTopic::unreadStateFor(
return result;
}
void ForumTopic::allowChatListMessageResolve() {
if (_flags & Flag::ResolveChatListMessage) {
return;
}
_flags |= Flag::ResolveChatListMessage;
resolveChatListMessageGroup();
}
HistoryItem *ForumTopic::chatListMessage() const {
return _lastMessage.value_or(nullptr);
}

View file

@ -146,7 +146,7 @@ public:
return _notify;
}
void loadUserpic() override;
void chatListPreloadData() override;
void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,
@ -169,6 +169,7 @@ private:
HasPinnedMessages = (1 << 3),
GeneralIconActive = (1 << 4),
GeneralIconSelected = (1 << 5),
ResolveChatListMessage = (1 << 6),
};
friend inline constexpr bool is_flag_type(Flag) { return true; }
using Flags = base::flags<Flag>;
@ -183,6 +184,8 @@ private:
void setLastMessage(HistoryItem *item);
void setLastServerMessage(HistoryItem *item);
void setChatListMessage(HistoryItem *item);
void allowChatListMessageResolve();
void resolveChatListMessageGroup();
int chatListNameVersion() const override;

View file

@ -230,7 +230,7 @@ public:
return nullptr;
}
virtual void loadUserpic() = 0;
virtual void chatListPreloadData() = 0;
virtual void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,

View file

@ -2506,7 +2506,7 @@ void InnerWidget::visibleTopBottomUpdated(
int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadPeerPhotos();
preloadRowsData();
const auto loadTill = _visibleTop
+ PreloadHeightsCount * (_visibleBottom - _visibleTop);
if (_state == WidgetState::Filtered && loadTill >= peerSearchOffset()) {
@ -2726,7 +2726,7 @@ void InnerWidget::refresh(bool toTop) {
if (toTop) {
stopReorderPinned();
_mustScrollTo.fire({ 0, 0 });
loadPeerPhotos();
preloadRowsData();
}
_controller->setDialogsListDisplayForced(
_searchInChat || !_filter.isEmpty());
@ -3115,8 +3115,10 @@ void InnerWidget::scrollToDefaultSelected() {
}
}
void InnerWidget::loadPeerPhotos() {
if (!parentWidget()) return;
void InnerWidget::preloadRowsData() {
if (!parentWidget()) {
return;
}
auto yFrom = _visibleTop;
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
@ -3129,7 +3131,7 @@ void InnerWidget::loadPeerPhotos() {
if (((*i)->index() * _st->height) >= yTo) {
break;
}
(*i)->entry()->loadUserpic();
(*i)->entry()->chatListPreloadData();
}
yFrom = 0;
} else {
@ -3144,7 +3146,7 @@ void InnerWidget::loadPeerPhotos() {
if (to > _filterResults.size()) to = _filterResults.size();
for (; from < to; ++from) {
_filterResults[from].key().entry()->loadUserpic();
_filterResults[from].key().entry()->chatListPreloadData();
}
}

View file

@ -243,7 +243,7 @@ private:
Qt::KeyboardModifiers modifiers);
void clearIrrelevantState();
void selectByMouse(QPoint globalPosition);
void loadPeerPhotos();
void preloadRowsData();
void scrollToItem(int top, int height);
void scrollToDefaultSelected();
void setCollapsedPressed(int pressed);

View file

@ -743,6 +743,7 @@ void RowPainter::Paint(
const auto thread = row->thread();
const auto peer = history ? history->peer.get() : nullptr;
const auto badgesState = entry->chatListBadgesState();
entry->chatListPreloadData(); // Allow chat list message resolve.
const auto item = entry->chatListMessage();
const auto cloudDraft = [&]() -> const Data::Draft*{
if (!thread) {

View file

@ -607,16 +607,6 @@ not_null<HistoryItem*> History::addNewItem(
} else {
addNewToBack(item, unread);
checkForLoadedAtTop(item);
if (!unread) {
// When we add just one last item, like we do while loading dialogs,
// we want to remove a single added grouped media, otherwise it will
// jump once we open the message history (first we show only that
// media, then we load the rest of the group and show the group).
//
// That way when we open the message history we show nothing until a
// whole history part is loaded, it certainly will contain the group.
removeOrphanMediaGroupPart();
}
}
return item;
}
@ -2241,6 +2231,44 @@ Dialogs::UnreadState History::computeUnreadState() const {
return result;
}
void History::allowChatListMessageResolve() {
if (_flags & Flag::ResolveChatListMessage) {
return;
}
_flags |= Flag::ResolveChatListMessage;
if (!chatListMessageKnown()) {
requestChatListMessage();
} else {
resolveChatListMessageGroup();
}
}
void History::resolveChatListMessageGroup() {
const auto item = _chatListMessage.value_or(nullptr);
if (!(_flags & Flag::ResolveChatListMessage)
|| !item
|| !hasOrphanMediaGroupPart()) {
return;
}
// If we set a single album part, request the full album.
const auto withImages = !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty();
if (withImages) {
owner().histories().requestGroupAround(item);
}
if (unreadCountKnown() && !unreadCount()) {
// When we add just one last item, like we do while loading dialogs,
// we want to remove a single added grouped media, otherwise it will
// jump once we open the message history (first we show only that
// media, then we load the rest of the group and show the group).
//
// That way when we open the message history we show nothing until a
// whole history part is loaded, it certainly will contain the group.
clear(ClearType::Unload);
}
}
HistoryItem *History::chatListMessage() const {
return _chatListMessage.value_or(nullptr);
}
@ -2269,8 +2297,9 @@ const base::flat_set<QChar> &History::chatListFirstLetters() const {
return peer->nameFirstLetters();
}
void History::loadUserpic() {
void History::chatListPreloadData() {
peer->loadUserpic();
allowChatListMessageResolve();
}
void History::paintUserpic(
@ -2452,14 +2481,7 @@ void History::setChatListMessage(HistoryItem *item) {
}
_chatListMessage = item;
setChatListTimeId(item->date());
// If we have a single message from a group, request the full album.
if (hasOrphanMediaGroupPart()
&& !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty()) {
owner().histories().requestGroupAround(item);
}
resolveChatListMessageGroup();
} else if (!_chatListMessage || *_chatListMessage) {
_chatListMessage = nullptr;
updateChatListEntry();
@ -2560,13 +2582,21 @@ void History::requestChatListMessage() {
}
void History::setFakeChatListMessage() {
if (const auto chat = peer->asChat()) {
if (!(_flags & Flag::ResolveChatListMessage)) {
if (!chatListTimeId()) {
if (const auto last = lastMessage()) {
setChatListTimeId(last->date());
}
}
return;
} else if (const auto chat = peer->asChat()) {
// In chats we try to take the item before the 'last', which
// is the empty-displayed migration message.
owner().histories().requestFakeChatListMessage(this);
} else if (const auto from = migrateFrom()) {
// In megagroups we just try to use
// the message from the original group.
from->allowChatListMessageResolve();
from->requestChatListMessage();
}
}
@ -3309,14 +3339,6 @@ bool History::hasOrphanMediaGroupPart() const {
return last->groupId() != MessageGroupId();
}
bool History::removeOrphanMediaGroupPart() {
if (hasOrphanMediaGroupPart()) {
clear(ClearType::Unload);
return true;
}
return false;
}
std::vector<MsgId> History::collectMessagesFromParticipantToDelete(
not_null<PeerData*> participant) const {
auto result = std::vector<MsgId>();

View file

@ -111,7 +111,6 @@ public:
Element *findLastNonEmpty() const;
Element *findLastDisplayed() const;
bool hasOrphanMediaGroupPart() const;
bool removeOrphanMediaGroupPart();
[[nodiscard]] std::vector<MsgId> collectMessagesFromParticipantToDelete(
not_null<PeerData*> participant) const;
@ -387,7 +386,7 @@ public:
const QString &chatListNameSortKey() const override;
const base::flat_set<QString> &chatListNameWords() const override;
const base::flat_set<QChar> &chatListFirstLetters() const override;
void loadUserpic() override;
void chatListPreloadData() override;
void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,
@ -467,6 +466,7 @@ private:
IsForum = (1 << 3),
FakeUnreadWhileOpened = (1 << 4),
HasPinnedMessages = (1 << 5),
ResolveChatListMessage = (1 << 6),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) {
@ -553,6 +553,8 @@ private:
void setChatListMessageFromLast();
void setChatListMessageUnknown();
void setFakeChatListMessage();
void allowChatListMessageResolve();
void resolveChatListMessageGroup();
// Add all items to the unread mentions if we were not loaded at bottom and now are.
void checkAddAllToUnreadMentions();