mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Fixed stale pinned Saved Messages sublists on clear that subsection.
This commit is contained in:
@@ -239,6 +239,17 @@ void SavedMessages::requestSublist(
|
||||
}
|
||||
}
|
||||
|
||||
void SavedMessages::refreshPinned() {
|
||||
if (parentChat()) {
|
||||
return;
|
||||
}
|
||||
if (_pinnedRequestId) {
|
||||
_refreshPinnedAfterRequest = true;
|
||||
return;
|
||||
}
|
||||
loadPinned();
|
||||
}
|
||||
|
||||
rpl::producer<> SavedMessages::chatsListChanges() const {
|
||||
return _chatsListChanges.events();
|
||||
}
|
||||
@@ -266,11 +277,15 @@ void SavedMessages::clearAllUnreadReactions() {
|
||||
}
|
||||
|
||||
void SavedMessages::sendLoadMore() {
|
||||
if (_loadMoreRequestId || _chatsList.loaded()) {
|
||||
if (_loadMoreRequestId) {
|
||||
return;
|
||||
} else if (!_pinnedLoaded) {
|
||||
}
|
||||
if (!_pinnedLoaded) {
|
||||
loadPinned();
|
||||
}
|
||||
if (_chatsList.loaded()) {
|
||||
return;
|
||||
}
|
||||
using Flag = MTPmessages_GetSavedDialogs::Flag;
|
||||
_loadMoreRequestId = _owner->session().api().request(
|
||||
MTPmessages_GetSavedDialogs(
|
||||
@@ -319,6 +334,10 @@ void SavedMessages::loadPinned() {
|
||||
_pinnedLoaded = true;
|
||||
applyReceivedSublists(result, true);
|
||||
_chatsListChanges.fire({});
|
||||
if (_refreshPinnedAfterRequest) {
|
||||
_refreshPinnedAfterRequest = false;
|
||||
loadPinned();
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) {
|
||||
markUnsupported();
|
||||
@@ -326,6 +345,10 @@ void SavedMessages::loadPinned() {
|
||||
_pinnedLoaded = true;
|
||||
}
|
||||
_pinnedRequestId = 0;
|
||||
if (_refreshPinnedAfterRequest) {
|
||||
_refreshPinnedAfterRequest = false;
|
||||
loadPinned();
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
@@ -348,20 +371,32 @@ SavedMessages::ApplyResult SavedMessages::applyReceivedSublists(
|
||||
}
|
||||
auto lastValid = false;
|
||||
auto result = ApplyResult();
|
||||
auto serverPinnedPeers = base::flat_set<not_null<PeerData*>>();
|
||||
const auto parentPeerId = _parentChat
|
||||
? _parentChat->id
|
||||
: _owner->session().userPeerId();
|
||||
for (const auto &dialog : *list) {
|
||||
dialog.match([&](const MTPDsavedDialog &data) {
|
||||
const auto peer = _owner->peer(peerFromMTP(data.vpeer()));
|
||||
const auto entryPinned = pinned || data.is_pinned();
|
||||
const auto topId = MsgId(data.vtop_message().v);
|
||||
if (const auto item = _owner->message(parentPeerId, topId)) {
|
||||
if (entryPinned) {
|
||||
serverPinnedPeers.emplace(peer);
|
||||
}
|
||||
if (entryPinned) {
|
||||
if (const auto loaded = sublistLoaded(peer)) {
|
||||
_owner->setPinnedFromEntryList(loaded, true);
|
||||
}
|
||||
}
|
||||
if (const auto item = _owner->message(parentPeerId, topId);
|
||||
item
|
||||
&& item->isRegular()
|
||||
&& !item->isService()) {
|
||||
result.offset.peer = peer;
|
||||
result.offset.date = item->date();
|
||||
result.offset.id = topId;
|
||||
lastValid = true;
|
||||
const auto entry = sublist(peer);
|
||||
const auto entryPinned = pinned || data.is_pinned();
|
||||
entry->applyMaybeLast(item);
|
||||
_owner->setPinnedFromEntryList(entry, entryPinned);
|
||||
} else {
|
||||
@@ -369,8 +404,14 @@ SavedMessages::ApplyResult SavedMessages::applyReceivedSublists(
|
||||
}
|
||||
}, [&](const MTPDmonoForumDialog &data) {
|
||||
const auto peer = _owner->peer(peerFromMTP(data.vpeer()));
|
||||
if (pinned) {
|
||||
serverPinnedPeers.emplace(peer);
|
||||
}
|
||||
const auto topId = MsgId(data.vtop_message().v);
|
||||
if (const auto item = _owner->message(parentPeerId, topId)) {
|
||||
if (const auto item = _owner->message(parentPeerId, topId);
|
||||
item
|
||||
&& item->isRegular()
|
||||
&& !item->isService()) {
|
||||
result.offset.peer = peer;
|
||||
result.offset.date = item->date();
|
||||
result.offset.id = topId;
|
||||
@@ -382,6 +423,17 @@ SavedMessages::ApplyResult SavedMessages::applyReceivedSublists(
|
||||
});
|
||||
}
|
||||
if (pinned) {
|
||||
for (const auto &[peer, holder] : _sublists) {
|
||||
const auto entry = holder.get();
|
||||
if (entry->isPinnedDialog(FilterId())
|
||||
&& !serverPinnedPeers.contains(peer)) {
|
||||
if (!entry->parentChat() && !entry->chatListMessage()) {
|
||||
entry->setRestorePinnedWhenNonEmpty(true);
|
||||
}
|
||||
_owner->setChatPinned(entry, FilterId(), false);
|
||||
}
|
||||
entry->updateChatListExistence();
|
||||
}
|
||||
} else if (!lastValid) {
|
||||
LOG(("API Error: Unknown message in the end of a slice."));
|
||||
result.allLoaded = true;
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
[[nodiscard]] not_null<SavedSublist*> sublist(not_null<PeerData*> peer);
|
||||
[[nodiscard]] SavedSublist *sublistLoaded(not_null<PeerData*> peer);
|
||||
void requestSublist(not_null<PeerData*> peer, Fn<void()> done = nullptr);
|
||||
void refreshPinned();
|
||||
|
||||
[[nodiscard]] rpl::producer<> chatsListChanges() const;
|
||||
[[nodiscard]] rpl::producer<> chatsListLoadedEvents() const;
|
||||
@@ -127,6 +128,7 @@ private:
|
||||
|
||||
mtpRequestId _loadMoreRequestId = 0;
|
||||
mtpRequestId _pinnedRequestId = 0;
|
||||
bool _refreshPinnedAfterRequest = false;
|
||||
|
||||
SavedMessagesOffsets _offset;
|
||||
|
||||
|
||||
@@ -97,6 +97,12 @@ bool SavedSublist::removeOne(not_null<HistoryItem*> item) {
|
||||
const auto i = ranges::lower_bound(_list, id, std::greater<>());
|
||||
changeUnreadCountByMessage(id, -1);
|
||||
if (i == end(_list) || *i != id) {
|
||||
if (const auto known = _fullCount.current()) {
|
||||
if (*known > 0) {
|
||||
_fullCount = (*known - 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
_list.erase(i);
|
||||
@@ -188,6 +194,9 @@ rpl::producer<> SavedSublist::destroyed() const {
|
||||
}
|
||||
|
||||
void SavedSublist::applyMaybeLast(not_null<HistoryItem*> item) {
|
||||
if (!item->isRegular() || item->isService()) {
|
||||
return;
|
||||
}
|
||||
if (!_lastServerMessage.value_or(nullptr)
|
||||
|| (*_lastServerMessage)->id < item->id) {
|
||||
setLastServerMessage(item);
|
||||
@@ -198,11 +207,23 @@ void SavedSublist::applyMaybeLast(not_null<HistoryItem*> item) {
|
||||
}
|
||||
|
||||
void SavedSublist::applyItemAdded(not_null<HistoryItem*> item) {
|
||||
if (item->isService()) {
|
||||
return;
|
||||
}
|
||||
const auto wasInChatList = shouldBeInChatList();
|
||||
if (item->isRegular()) {
|
||||
setLastServerMessage(item);
|
||||
} else {
|
||||
setLastMessage(item);
|
||||
}
|
||||
if (!_parent->parentChat() && !isPinnedDialog(FilterId())) {
|
||||
if (_restorePinnedWhenNonEmpty) {
|
||||
owner().setChatPinned(this, FilterId(), true);
|
||||
_restorePinnedWhenNonEmpty = false;
|
||||
} else if (!wasInChatList && shouldBeInChatList()) {
|
||||
_parent->refreshPinned();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SavedSublist::applyItemRemoved(MsgId id) {
|
||||
@@ -220,16 +241,22 @@ void SavedSublist::applyItemRemoved(MsgId id) {
|
||||
if (chatListItem->id == id) {
|
||||
_chatListMessage = std::nullopt;
|
||||
crl::on_main(this, [=] {
|
||||
// We didn't yet update _list here.
|
||||
if (_chatListMessage.has_value()) {
|
||||
const auto locallyKnownEmpty = _list.empty()
|
||||
&& (_fullCount.current() == 0);
|
||||
if (_chatListMessage.value_or(nullptr)) {
|
||||
return;
|
||||
} else if (_skippedAfter == 0) {
|
||||
} else if ((_skippedAfter == 0) || locallyKnownEmpty) {
|
||||
if (!_list.empty()) {
|
||||
applyMaybeLast(owner().message(
|
||||
owningHistory()->peer,
|
||||
_list.front()));
|
||||
return;
|
||||
} else if (_skippedBefore == 0) {
|
||||
} else if ((_skippedBefore == 0) || locallyKnownEmpty) {
|
||||
if (!_parent->parentChat()
|
||||
&& isPinnedDialog(FilterId())) {
|
||||
_restorePinnedWhenNonEmpty = true;
|
||||
owner().setChatPinned(this, FilterId(), false);
|
||||
}
|
||||
setLastServerMessage(nullptr);
|
||||
updateChatListExistence();
|
||||
return;
|
||||
@@ -251,6 +278,10 @@ void SavedSublist::requestChatListMessage() {
|
||||
}
|
||||
}
|
||||
|
||||
void SavedSublist::setRestorePinnedWhenNonEmpty(bool restore) {
|
||||
_restorePinnedWhenNonEmpty = restore;
|
||||
}
|
||||
|
||||
void SavedSublist::readTillEnd() {
|
||||
readTill(_lastKnownServerMessageId);
|
||||
}
|
||||
@@ -329,6 +360,7 @@ bool SavedSublist::applyUpdate(const MessageUpdate &update) {
|
||||
|
||||
if (update.item->history() != owningHistory()
|
||||
|| !update.item->isRegular()
|
||||
|| update.item->isService()
|
||||
|| update.item->sublistPeerId() != sublistPeer()->id) {
|
||||
return false;
|
||||
} else if (update.flags & Flag::Destroyed) {
|
||||
@@ -405,7 +437,9 @@ bool SavedSublist::processMessagesIsEmpty(
|
||||
auto skipped = 0;
|
||||
for (const auto &message : list) {
|
||||
if (const auto item = owner().addNewMessage(message, localFlags, type)) {
|
||||
if (item->sublistPeerId() == sublistPeer()->id) {
|
||||
if (item->sublistPeerId() == sublistPeer()->id
|
||||
&& item->isRegular()
|
||||
&& !item->isService()) {
|
||||
if (toFront && item->id > _list.front()) {
|
||||
refreshed.push_back(item->id);
|
||||
} else if (_list.empty() || item->id < _list.back()) {
|
||||
@@ -871,14 +905,18 @@ int SavedSublist::fixedOnTopIndex() const {
|
||||
}
|
||||
|
||||
bool SavedSublist::shouldBeInChatList() const {
|
||||
if (const auto monoforum = _parent->parentChat()) {
|
||||
if (monoforum == sublistPeer()) {
|
||||
return false;
|
||||
}
|
||||
const auto monoforum = _parent->parentChat();
|
||||
if (monoforum && (monoforum == sublistPeer())) {
|
||||
return false;
|
||||
}
|
||||
const auto last = lastMessage();
|
||||
const auto hasDisplayableLast = last && !last->isService();
|
||||
if (!monoforum) {
|
||||
return hasDisplayableLast;
|
||||
}
|
||||
return isPinnedDialog(FilterId())
|
||||
|| !lastMessageKnown()
|
||||
|| (lastMessage() != nullptr);
|
||||
|| hasDisplayableLast;
|
||||
}
|
||||
|
||||
HistoryItem *SavedSublist::lastMessage() const {
|
||||
@@ -1066,9 +1104,10 @@ void SavedSublist::setChatListMessage(HistoryItem *item) {
|
||||
}
|
||||
_chatListMessage = item;
|
||||
setChatListTimeId(item->date());
|
||||
updateChatListExistence();
|
||||
} else if (!_chatListMessage || *_chatListMessage) {
|
||||
_chatListMessage = nullptr;
|
||||
updateChatListEntry();
|
||||
updateChatListExistence();
|
||||
}
|
||||
_parent->listMessageChanged(was, item);
|
||||
}
|
||||
@@ -1102,8 +1141,10 @@ Histories &SavedSublist::histories() {
|
||||
|
||||
void SavedSublist::loadAround(MsgId id) {
|
||||
if (_loadingAround && *_loadingAround == id) {
|
||||
_loadingAroundRetry = id;
|
||||
return;
|
||||
}
|
||||
_loadingAroundRetry = std::nullopt;
|
||||
histories().cancelRequest(base::take(_beforeId));
|
||||
histories().cancelRequest(base::take(_afterId));
|
||||
|
||||
@@ -1135,7 +1176,12 @@ void SavedSublist::loadAround(MsgId id) {
|
||||
_list.clear();
|
||||
if (processMessagesIsEmpty(result)) {
|
||||
_fullCount = _skippedBefore = _skippedAfter = 0;
|
||||
if (!_parent->parentChat() && !_chatListMessage) {
|
||||
if (!_parent->parentChat()
|
||||
&& !_chatListMessage.value_or(nullptr)) {
|
||||
if (isPinnedDialog(FilterId())) {
|
||||
_restorePinnedWhenNonEmpty = true;
|
||||
owner().setChatPinned(this, FilterId(), false);
|
||||
}
|
||||
setLastServerMessage(nullptr);
|
||||
updateChatListExistence();
|
||||
}
|
||||
@@ -1146,13 +1192,17 @@ void SavedSublist::loadAround(MsgId id) {
|
||||
} else if (_list.back() >= id) {
|
||||
_skippedBefore = 0;
|
||||
}
|
||||
} else if (!_parent->parentChat() && !_chatListMessage) {
|
||||
} else if (!_parent->parentChat()
|
||||
&& !_chatListMessage.value_or(nullptr)) {
|
||||
Assert(!_list.empty());
|
||||
applyMaybeLast(owner().message(
|
||||
owningHistory()->peer,
|
||||
_list.front()));
|
||||
}
|
||||
checkReadTillEnd();
|
||||
if (const auto retry = base::take(_loadingAroundRetry)) {
|
||||
loadAround(*retry);
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) {
|
||||
_parent->markUnsupported();
|
||||
@@ -1160,6 +1210,9 @@ void SavedSublist::loadAround(MsgId id) {
|
||||
_beforeId = 0;
|
||||
_loadingAround = std::nullopt;
|
||||
finish();
|
||||
if (const auto retry = base::take(_loadingAroundRetry)) {
|
||||
loadAround(*retry);
|
||||
}
|
||||
}).send();
|
||||
};
|
||||
_loadingAround = id;
|
||||
|
||||
@@ -72,6 +72,7 @@ public:
|
||||
not_null<HistoryItem*> topItem);
|
||||
void readTillEnd();
|
||||
void requestChatListMessage();
|
||||
void setRestorePinnedWhenNonEmpty(bool restore);
|
||||
|
||||
TimeId adjustedChatListTimeId() const override;
|
||||
|
||||
@@ -173,6 +174,7 @@ private:
|
||||
rpl::event_stream<> _listChanges;
|
||||
rpl::event_stream<> _instantChanges;
|
||||
std::optional<MsgId> _loadingAround;
|
||||
std::optional<MsgId> _loadingAroundRetry;
|
||||
rpl::variable<std::optional<int>> _unreadCount;
|
||||
MsgId _inboxReadTillId = 0;
|
||||
MsgId _outboxReadTillId = 0;
|
||||
@@ -189,6 +191,8 @@ private:
|
||||
mtpRequestId _readRequestId = 0;
|
||||
MsgId _sentReadTill = 0;
|
||||
|
||||
bool _restorePinnedWhenNonEmpty = false;
|
||||
|
||||
mtpRequestId _reloadUnreadCountRequestId = 0;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
Reference in New Issue
Block a user