diff --git a/Telegram/SourceFiles/data/data_community.cpp b/Telegram/SourceFiles/data/data_community.cpp index 37bff64c0d..41ff18fc93 100644 --- a/Telegram/SourceFiles/data/data_community.cpp +++ b/Telegram/SourceFiles/data/data_community.cpp @@ -129,7 +129,8 @@ CommunityInfo::CommunityInfo(not_null channel) &channel->session(), FilterId(), channel->owner().maxPinnedChatsLimitValue( - static_cast(nullptr))) { + static_cast(nullptr))) +, _collapsedInChatLists(channel->collapsedInDialogs()) { _channel->session().changes().peerUpdates( PeerUpdate::Flag::Name ) | rpl::filter([=](const PeerUpdate &update) { @@ -227,26 +228,40 @@ bool CommunityInfo::collapsedInDialogs() const { return _channel->collapsedInDialogs(); } -void CommunityInfo::moveHistory( - not_null history, - bool nowCollapsed) { - if (!history->inChatList()) { - history->updateChatListSortPosition(); - history->updateChatListExistence(); - return; - } - auto &owner = _channel->owner(); - const auto wasList = nowCollapsed - ? owner.chatsList(history->folder()) - : chatsList(); - history->removeFromChatList(0, wasList); - history->updateChatListSortPosition(); -} - void CommunityInfo::collapsedChanged() { + // The channel flag is already flipped when this runs, while rows and + // pinned state of the linked histories still live in the old lists. + // _collapsedInChatLists feeds Data::Session::chatsListFor(), so it + // must keep naming the old list until every linked history is removed + // from it (the unpin inside removeFromChatList and the pinned-index + // reindex of not-yet-moved siblings resolve lists through it), and + // flip exactly once before the histories are re-added to the new one. const auto nowCollapsed = collapsedInDialogs(); + auto &owner = _channel->owner(); + auto moved = base::flat_set>(); + const auto removeAll = [&]( + const base::flat_set> &from) { + for (const auto &history : from) { + if (history->inChatList()) { + const auto wasList = _collapsedInChatLists + ? chatsList() + : owner.chatsList(history->folder()); + history->removeFromChatList(0, wasList); + moved.emplace(history); + } + } + }; + removeAll(_histories); + removeAll(_otherHistories); + _collapsedInChatLists = nowCollapsed; + for (const auto &history : moved) { + history->updateChatListSortPosition(); + } for (const auto &history : _histories) { - moveHistory(history, nowCollapsed); + if (!moved.contains(history)) { + history->updateChatListSortPosition(); + history->updateChatListExistence(); + } } ensureRowInChatList(); repaintRow(); diff --git a/Telegram/SourceFiles/data/data_community.h b/Telegram/SourceFiles/data/data_community.h index 8fdb622b51..2bb303363b 100644 --- a/Telegram/SourceFiles/data/data_community.h +++ b/Telegram/SourceFiles/data/data_community.h @@ -49,6 +49,9 @@ public: [[nodiscard]] bool isHidden(not_null peer) const; [[nodiscard]] bool collapsedInDialogs() const; + [[nodiscard]] bool collapsedInChatLists() const { + return _collapsedInChatLists; + } void collapsedChanged(); void ensureRowInChatList(); @@ -84,7 +87,6 @@ private: void reorderLastHistories(); void updateRowSortPosition(); void repaintRow(); - void moveHistory(not_null history, bool nowCollapsed); const not_null _channel; std::vector _linkedPeers; @@ -105,6 +107,7 @@ private: int _chatListViewVersion = 0; TimeId _chatsListDate = 0; Dialogs::MainList _chatsList; + bool _collapsedInChatLists = false; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index d10ad72aef..abd1848f0b 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -5327,7 +5327,7 @@ not_null Session::chatsListFor( } else if (const auto history = entry->asHistory()) { if (const auto info = history->communityListInfo() ; info - && info->collapsedInDialogs() + && info->collapsedInChatLists() && info->channel() != history->peer) { return info->chatsList(); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index 5c93c8e501..ca7fa1f9d9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -472,7 +472,8 @@ void Entry::removeFromChatList( FilterId filterId, not_null list) { if (isPinnedDialog(filterId)) { - owner().setChatPinned(this, filterId, false); + list->pinned()->setPinned(this, false); + owner().notifyPinnedDialogsOrderUpdated(); } if (filterId) { const auto it = _tagColors.find(filterId); diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_list.cpp index 3d6515baba..e1606a5e76 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_list.cpp @@ -83,6 +83,7 @@ void List::adjustByName(not_null row) { void List::adjustByDate(not_null row) { Expects(_sortMode == SortMode::Date); + Expects(row->index() >= 0 && row->index() < _rows.size()); if (_frozen) { const auto canAdjustWhileFrozen = _pendingAdjust.empty() diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 1d209c5cc0..139d21f137 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -2475,7 +2475,7 @@ void History::updateCommunityRegistration() { const auto listFor = [&](Data::CommunityInfo *info) -> Dialogs::MainList* { if (info - && info->collapsedInDialogs() + && info->collapsedInChatLists() && info->channel() != peer) { return info->chatsList(); }