Preload complex last message on demand.
This commit is contained in:
parent
369862a3a7
commit
f2ed77649e
11 changed files with 101 additions and 55 deletions
|
@ -854,7 +854,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
|
||||||
if (((*i)->index() * _rowHeight) >= yTo) {
|
if (((*i)->index() * _rowHeight) >= yTo) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(*i)->entry()->loadUserpic();
|
(*i)->entry()->chatListPreloadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!_filtered.empty()) {
|
} else if (!_filtered.empty()) {
|
||||||
|
@ -865,7 +865,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
|
||||||
if (to > _filtered.size()) to = _filtered.size();
|
if (to > _filtered.size()) to = _filtered.size();
|
||||||
|
|
||||||
for (; from < to; ++from) {
|
for (; from < to; ++from) {
|
||||||
_filtered[from]->entry()->loadUserpic();
|
_filtered[from]->entry()->chatListPreloadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,7 +211,7 @@ not_null<Dialogs::MainList*> Folder::chatsList() {
|
||||||
return &_chatsList;
|
return &_chatsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Folder::loadUserpic() {
|
void Folder::chatListPreloadData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Folder::paintUserpic(
|
void Folder::paintUserpic(
|
||||||
|
|
|
@ -54,7 +54,7 @@ public:
|
||||||
const base::flat_set<QString> &chatListNameWords() const override;
|
const base::flat_set<QString> &chatListNameWords() const override;
|
||||||
const base::flat_set<QChar> &chatListFirstLetters() const override;
|
const base::flat_set<QChar> &chatListFirstLetters() const override;
|
||||||
|
|
||||||
void loadUserpic() override;
|
void chatListPreloadData() override;
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
Ui::PeerUserpicView &view,
|
Ui::PeerUserpicView &view,
|
||||||
|
|
|
@ -471,17 +471,7 @@ void ForumTopic::applyTopicTopMessage(MsgId topMessageId) {
|
||||||
const auto itemId = FullMsgId(channel()->id, topMessageId);
|
const auto itemId = FullMsgId(channel()->id, topMessageId);
|
||||||
if (const auto item = owner().message(itemId)) {
|
if (const auto item = owner().message(itemId)) {
|
||||||
setLastServerMessage(item);
|
setLastServerMessage(item);
|
||||||
|
resolveChatListMessageGroup();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setLastServerMessage(nullptr);
|
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) {
|
void ForumTopic::growLastKnownServerMessageId(MsgId id) {
|
||||||
_lastKnownServerMessageId = std::max(_lastKnownServerMessageId, id);
|
_lastKnownServerMessageId = std::max(_lastKnownServerMessageId, id);
|
||||||
}
|
}
|
||||||
|
@ -548,10 +555,11 @@ void ForumTopic::setChatListMessage(HistoryItem *item) {
|
||||||
_forum->listMessageChanged(was, item);
|
_forum->listMessageChanged(was, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForumTopic::loadUserpic() {
|
void ForumTopic::chatListPreloadData() {
|
||||||
if (_icon) {
|
if (_icon) {
|
||||||
[[maybe_unused]] const auto preload = _icon->ready();
|
[[maybe_unused]] const auto preload = _icon->ready();
|
||||||
}
|
}
|
||||||
|
allowChatListMessageResolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForumTopic::paintUserpic(
|
void ForumTopic::paintUserpic(
|
||||||
|
@ -840,6 +848,14 @@ Dialogs::UnreadState ForumTopic::unreadStateFor(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ForumTopic::allowChatListMessageResolve() {
|
||||||
|
if (_flags & Flag::ResolveChatListMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_flags |= Flag::ResolveChatListMessage;
|
||||||
|
resolveChatListMessageGroup();
|
||||||
|
}
|
||||||
|
|
||||||
HistoryItem *ForumTopic::chatListMessage() const {
|
HistoryItem *ForumTopic::chatListMessage() const {
|
||||||
return _lastMessage.value_or(nullptr);
|
return _lastMessage.value_or(nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ public:
|
||||||
return _notify;
|
return _notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadUserpic() override;
|
void chatListPreloadData() override;
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
Ui::PeerUserpicView &view,
|
Ui::PeerUserpicView &view,
|
||||||
|
@ -169,6 +169,7 @@ private:
|
||||||
HasPinnedMessages = (1 << 3),
|
HasPinnedMessages = (1 << 3),
|
||||||
GeneralIconActive = (1 << 4),
|
GeneralIconActive = (1 << 4),
|
||||||
GeneralIconSelected = (1 << 5),
|
GeneralIconSelected = (1 << 5),
|
||||||
|
ResolveChatListMessage = (1 << 6),
|
||||||
};
|
};
|
||||||
friend inline constexpr bool is_flag_type(Flag) { return true; }
|
friend inline constexpr bool is_flag_type(Flag) { return true; }
|
||||||
using Flags = base::flags<Flag>;
|
using Flags = base::flags<Flag>;
|
||||||
|
@ -183,6 +184,8 @@ private:
|
||||||
void setLastMessage(HistoryItem *item);
|
void setLastMessage(HistoryItem *item);
|
||||||
void setLastServerMessage(HistoryItem *item);
|
void setLastServerMessage(HistoryItem *item);
|
||||||
void setChatListMessage(HistoryItem *item);
|
void setChatListMessage(HistoryItem *item);
|
||||||
|
void allowChatListMessageResolve();
|
||||||
|
void resolveChatListMessageGroup();
|
||||||
|
|
||||||
int chatListNameVersion() const override;
|
int chatListNameVersion() const override;
|
||||||
|
|
||||||
|
|
|
@ -230,7 +230,7 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void loadUserpic() = 0;
|
virtual void chatListPreloadData() = 0;
|
||||||
virtual void paintUserpic(
|
virtual void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
Ui::PeerUserpicView &view,
|
Ui::PeerUserpicView &view,
|
||||||
|
|
|
@ -2506,7 +2506,7 @@ void InnerWidget::visibleTopBottomUpdated(
|
||||||
int visibleBottom) {
|
int visibleBottom) {
|
||||||
_visibleTop = visibleTop;
|
_visibleTop = visibleTop;
|
||||||
_visibleBottom = visibleBottom;
|
_visibleBottom = visibleBottom;
|
||||||
loadPeerPhotos();
|
preloadRowsData();
|
||||||
const auto loadTill = _visibleTop
|
const auto loadTill = _visibleTop
|
||||||
+ PreloadHeightsCount * (_visibleBottom - _visibleTop);
|
+ PreloadHeightsCount * (_visibleBottom - _visibleTop);
|
||||||
if (_state == WidgetState::Filtered && loadTill >= peerSearchOffset()) {
|
if (_state == WidgetState::Filtered && loadTill >= peerSearchOffset()) {
|
||||||
|
@ -2726,7 +2726,7 @@ void InnerWidget::refresh(bool toTop) {
|
||||||
if (toTop) {
|
if (toTop) {
|
||||||
stopReorderPinned();
|
stopReorderPinned();
|
||||||
_mustScrollTo.fire({ 0, 0 });
|
_mustScrollTo.fire({ 0, 0 });
|
||||||
loadPeerPhotos();
|
preloadRowsData();
|
||||||
}
|
}
|
||||||
_controller->setDialogsListDisplayForced(
|
_controller->setDialogsListDisplayForced(
|
||||||
_searchInChat || !_filter.isEmpty());
|
_searchInChat || !_filter.isEmpty());
|
||||||
|
@ -3115,8 +3115,10 @@ void InnerWidget::scrollToDefaultSelected() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::loadPeerPhotos() {
|
void InnerWidget::preloadRowsData() {
|
||||||
if (!parentWidget()) return;
|
if (!parentWidget()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto yFrom = _visibleTop;
|
auto yFrom = _visibleTop;
|
||||||
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
|
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
|
||||||
|
@ -3129,7 +3131,7 @@ void InnerWidget::loadPeerPhotos() {
|
||||||
if (((*i)->index() * _st->height) >= yTo) {
|
if (((*i)->index() * _st->height) >= yTo) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(*i)->entry()->loadUserpic();
|
(*i)->entry()->chatListPreloadData();
|
||||||
}
|
}
|
||||||
yFrom = 0;
|
yFrom = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3144,7 +3146,7 @@ void InnerWidget::loadPeerPhotos() {
|
||||||
if (to > _filterResults.size()) to = _filterResults.size();
|
if (to > _filterResults.size()) to = _filterResults.size();
|
||||||
|
|
||||||
for (; from < to; ++from) {
|
for (; from < to; ++from) {
|
||||||
_filterResults[from].key().entry()->loadUserpic();
|
_filterResults[from].key().entry()->chatListPreloadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ private:
|
||||||
Qt::KeyboardModifiers modifiers);
|
Qt::KeyboardModifiers modifiers);
|
||||||
void clearIrrelevantState();
|
void clearIrrelevantState();
|
||||||
void selectByMouse(QPoint globalPosition);
|
void selectByMouse(QPoint globalPosition);
|
||||||
void loadPeerPhotos();
|
void preloadRowsData();
|
||||||
void scrollToItem(int top, int height);
|
void scrollToItem(int top, int height);
|
||||||
void scrollToDefaultSelected();
|
void scrollToDefaultSelected();
|
||||||
void setCollapsedPressed(int pressed);
|
void setCollapsedPressed(int pressed);
|
||||||
|
|
|
@ -743,6 +743,7 @@ void RowPainter::Paint(
|
||||||
const auto thread = row->thread();
|
const auto thread = row->thread();
|
||||||
const auto peer = history ? history->peer.get() : nullptr;
|
const auto peer = history ? history->peer.get() : nullptr;
|
||||||
const auto badgesState = entry->chatListBadgesState();
|
const auto badgesState = entry->chatListBadgesState();
|
||||||
|
entry->chatListPreloadData(); // Allow chat list message resolve.
|
||||||
const auto item = entry->chatListMessage();
|
const auto item = entry->chatListMessage();
|
||||||
const auto cloudDraft = [&]() -> const Data::Draft*{
|
const auto cloudDraft = [&]() -> const Data::Draft*{
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
|
|
|
@ -607,16 +607,6 @@ not_null<HistoryItem*> History::addNewItem(
|
||||||
} else {
|
} else {
|
||||||
addNewToBack(item, unread);
|
addNewToBack(item, unread);
|
||||||
checkForLoadedAtTop(item);
|
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;
|
return item;
|
||||||
}
|
}
|
||||||
|
@ -2241,6 +2231,44 @@ Dialogs::UnreadState History::computeUnreadState() const {
|
||||||
return result;
|
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 {
|
HistoryItem *History::chatListMessage() const {
|
||||||
return _chatListMessage.value_or(nullptr);
|
return _chatListMessage.value_or(nullptr);
|
||||||
}
|
}
|
||||||
|
@ -2269,8 +2297,9 @@ const base::flat_set<QChar> &History::chatListFirstLetters() const {
|
||||||
return peer->nameFirstLetters();
|
return peer->nameFirstLetters();
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::loadUserpic() {
|
void History::chatListPreloadData() {
|
||||||
peer->loadUserpic();
|
peer->loadUserpic();
|
||||||
|
allowChatListMessageResolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::paintUserpic(
|
void History::paintUserpic(
|
||||||
|
@ -2452,14 +2481,7 @@ void History::setChatListMessage(HistoryItem *item) {
|
||||||
}
|
}
|
||||||
_chatListMessage = item;
|
_chatListMessage = item;
|
||||||
setChatListTimeId(item->date());
|
setChatListTimeId(item->date());
|
||||||
|
resolveChatListMessageGroup();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
} else if (!_chatListMessage || *_chatListMessage) {
|
} else if (!_chatListMessage || *_chatListMessage) {
|
||||||
_chatListMessage = nullptr;
|
_chatListMessage = nullptr;
|
||||||
updateChatListEntry();
|
updateChatListEntry();
|
||||||
|
@ -2560,13 +2582,21 @@ void History::requestChatListMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::setFakeChatListMessage() {
|
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
|
// In chats we try to take the item before the 'last', which
|
||||||
// is the empty-displayed migration message.
|
// is the empty-displayed migration message.
|
||||||
owner().histories().requestFakeChatListMessage(this);
|
owner().histories().requestFakeChatListMessage(this);
|
||||||
} else if (const auto from = migrateFrom()) {
|
} else if (const auto from = migrateFrom()) {
|
||||||
// In megagroups we just try to use
|
// In megagroups we just try to use
|
||||||
// the message from the original group.
|
// the message from the original group.
|
||||||
|
from->allowChatListMessageResolve();
|
||||||
from->requestChatListMessage();
|
from->requestChatListMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3309,14 +3339,6 @@ bool History::hasOrphanMediaGroupPart() const {
|
||||||
return last->groupId() != MessageGroupId();
|
return last->groupId() != MessageGroupId();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool History::removeOrphanMediaGroupPart() {
|
|
||||||
if (hasOrphanMediaGroupPart()) {
|
|
||||||
clear(ClearType::Unload);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<MsgId> History::collectMessagesFromParticipantToDelete(
|
std::vector<MsgId> History::collectMessagesFromParticipantToDelete(
|
||||||
not_null<PeerData*> participant) const {
|
not_null<PeerData*> participant) const {
|
||||||
auto result = std::vector<MsgId>();
|
auto result = std::vector<MsgId>();
|
||||||
|
|
|
@ -111,7 +111,6 @@ public:
|
||||||
Element *findLastNonEmpty() const;
|
Element *findLastNonEmpty() const;
|
||||||
Element *findLastDisplayed() const;
|
Element *findLastDisplayed() const;
|
||||||
bool hasOrphanMediaGroupPart() const;
|
bool hasOrphanMediaGroupPart() const;
|
||||||
bool removeOrphanMediaGroupPart();
|
|
||||||
[[nodiscard]] std::vector<MsgId> collectMessagesFromParticipantToDelete(
|
[[nodiscard]] std::vector<MsgId> collectMessagesFromParticipantToDelete(
|
||||||
not_null<PeerData*> participant) const;
|
not_null<PeerData*> participant) const;
|
||||||
|
|
||||||
|
@ -387,7 +386,7 @@ public:
|
||||||
const QString &chatListNameSortKey() const override;
|
const QString &chatListNameSortKey() const override;
|
||||||
const base::flat_set<QString> &chatListNameWords() const override;
|
const base::flat_set<QString> &chatListNameWords() const override;
|
||||||
const base::flat_set<QChar> &chatListFirstLetters() const override;
|
const base::flat_set<QChar> &chatListFirstLetters() const override;
|
||||||
void loadUserpic() override;
|
void chatListPreloadData() override;
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
Ui::PeerUserpicView &view,
|
Ui::PeerUserpicView &view,
|
||||||
|
@ -467,6 +466,7 @@ private:
|
||||||
IsForum = (1 << 3),
|
IsForum = (1 << 3),
|
||||||
FakeUnreadWhileOpened = (1 << 4),
|
FakeUnreadWhileOpened = (1 << 4),
|
||||||
HasPinnedMessages = (1 << 5),
|
HasPinnedMessages = (1 << 5),
|
||||||
|
ResolveChatListMessage = (1 << 6),
|
||||||
};
|
};
|
||||||
using Flags = base::flags<Flag>;
|
using Flags = base::flags<Flag>;
|
||||||
friend inline constexpr auto is_flag_type(Flag) {
|
friend inline constexpr auto is_flag_type(Flag) {
|
||||||
|
@ -553,6 +553,8 @@ private:
|
||||||
void setChatListMessageFromLast();
|
void setChatListMessageFromLast();
|
||||||
void setChatListMessageUnknown();
|
void setChatListMessageUnknown();
|
||||||
void setFakeChatListMessage();
|
void setFakeChatListMessage();
|
||||||
|
void allowChatListMessageResolve();
|
||||||
|
void resolveChatListMessageGroup();
|
||||||
|
|
||||||
// Add all items to the unread mentions if we were not loaded at bottom and now are.
|
// Add all items to the unread mentions if we were not loaded at bottom and now are.
|
||||||
void checkAddAllToUnreadMentions();
|
void checkAddAllToUnreadMentions();
|
||||||
|
|
Loading…
Reference in a new issue