diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h index 9ff9333ae..c4075abc1 100644 --- a/Telegram/SourceFiles/data/data_changes.h +++ b/Telegram/SourceFiles/data/data_changes.h @@ -197,8 +197,9 @@ struct EntryUpdate { HasPinnedMessages = (1U << 1), ForwardDraft = (1U << 2), LocalDraftSet = (1U << 3), + Height = (1U << 4), - LastUsedBit = (1U << 3), + LastUsedBit = (1U << 4), }; using Flags = base::flags; friend inline constexpr auto is_flag_type(Flag) { return true; } diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index bb2b6e9e8..661214b66 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -183,6 +183,12 @@ void ChannelData::setFlags(ChannelDataFlags which) { } if (diff & Flag::Forum) { Core::App().notifications().clearFromHistory(history); + history->updateChatListEntryHeight(); + if (history->inChatList()) { + if (const auto forum = this->forum()) { + forum->preloadTopics(); + } + } } } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index 830012a3f..8d580abf4 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -379,4 +379,15 @@ void Entry::updateChatListEntryPostponed() { }); } +void Entry::updateChatListEntryHeight() { + auto &filters = _owner->chatsFilters(); + for (auto &[filterId, rows] : _chatListLinks) { + const auto list = filterId + ? filters.chatsList(filterId) + : _owner->chatsList(folder()); + list->updateEntryHeight(rows); + } + session().changes().entryUpdated(this, Data::EntryUpdate::Flag::Height); +} + } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.h b/Telegram/SourceFiles/dialogs/dialogs_entry.h index e8709ea53..a8940d2ae 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.h +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.h @@ -192,6 +192,7 @@ public: not_null row); void updateChatListEntry(); void updateChatListEntryPostponed(); + void updateChatListEntryHeight(); [[nodiscard]] bool isPinnedDialog(FilterId filterId) const { return lookupPinnedIndex(filterId) != 0; } diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp index a733b1c1f..7d480946e 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp @@ -61,6 +61,15 @@ void IndexedList::adjustByDate(const RowsByLetter &links) { } } +void IndexedList::updateHeight(const RowsByLetter &links) { + _list.updateHeight(links.main); + for (const auto &[ch, row] : links.letters) { + if (auto it = _index.find(ch); it != _index.cend()) { + it->second.updateHeight(row); + } + } +} + void IndexedList::moveToTop(Key key) { if (_list.moveToTop(key)) { for (const auto &ch : key.entry()->chatListFirstLetters()) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h index 6e570ab6e..ae8040271 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h @@ -22,6 +22,7 @@ public: Row *addByName(Key key); void adjustByDate(const RowsByLetter &links); void moveToTop(Key key); + void updateHeight(const RowsByLetter &links); // row must belong to this indexed list all(). void movePinned(Row *row, int deltaSign); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index b70cbcebf..9a4dd7fe6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -285,8 +285,14 @@ InnerWidget::InnerWidget( session().changes().entryUpdates( Data::EntryUpdate::Flag::Repaint + | Data::EntryUpdate::Flag::Height ) | rpl::start_with_next([=](const Data::EntryUpdate &update) { const auto entry = update.entry; + if (update.flags & Data::EntryUpdate::Flag::Height) { + updateFilteredEntryHeight(entry); + refresh(); + return; + } const auto repaintId = (_state == WidgetState::Default) ? _filterId : 0; @@ -320,6 +326,24 @@ InnerWidget::InnerWidget( setupShortcuts(); } +void InnerWidget::updateFilteredEntryHeight(not_null entry) { + auto changing = false; + auto top = 0; + for (auto &result : _filterResults) { + if (changing) { + result.top = top; + } + if (result.row->key().entry() == entry) { + result.row->recountHeight(); + changing = true; + top = result.top; + } + if (changing) { + top += result.row->height(); + } + } +} + Main::Session &InnerWidget::session() const { return _controller->session(); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 7ed2917a9..8265b3101 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -230,6 +230,7 @@ private: void repaintDialogRow(FilterId filterId, not_null row); void repaintDialogRow(RowDescriptor row); void refreshDialogRow(RowDescriptor row); + void updateFilteredEntryHeight(not_null entry); void clearMouseSelection(bool clearSelection = false); void mousePressReleased( diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_list.cpp index c985d7007..b8242b8da 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_list.cpp @@ -103,6 +103,17 @@ void List::adjustByDate(not_null row) { } } +void List::updateHeight(not_null row) { + row->recountHeight(); + + const auto index = row->index(); + auto top = row->top(); + for (auto i = _rows.begin() + index, e = _rows.end(); i != e; ++i) { + (*i)->_top = top; + top += (*i)->height(); + } +} + bool List::moveToTop(Key key) { const auto i = _rowByKey.find(key); if (i == _rowByKey.cend()) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.h b/Telegram/SourceFiles/dialogs/dialogs_list.h index 30388b89f..998fce5ad 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_list.h @@ -48,6 +48,7 @@ public: not_null addByName(Key key); bool moveToTop(Key key); void adjustByDate(not_null row); + void updateHeight(not_null row); bool remove(Key key, Row *replacedBy = nullptr); using const_iterator = std::vector>::const_iterator; diff --git a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp index d0197d391..d6c24f18b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp @@ -107,6 +107,10 @@ void MainList::removeEntry(Key key) { recomputeFullListSize(); } +void MainList::updateEntryHeight(const RowsByLetter &links) { + _all.updateHeight(links); +} + void MainList::recomputeFullListSize() { _fullListSize = std::max(_all.size(), loaded() ? 0 : _cloudListSize); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_main_list.h b/Telegram/SourceFiles/dialogs/dialogs_main_list.h index 157e48e31..27ec539a9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_main_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_main_list.h @@ -35,6 +35,7 @@ public: RowsByLetter addEntry(Key key); void removeEntry(Key key); + void updateEntryHeight(const RowsByLetter &links); void unreadStateChanged( const UnreadState &wasState, diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.cpp b/Telegram/SourceFiles/dialogs/dialogs_row.cpp index 4e38845e0..b757252dc 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_row.cpp @@ -100,10 +100,16 @@ void BasicRow::paintUserpic( Row::Row(Key key, int index, int top) : _id(key), _top(top), _index(index) { if (const auto history = key.history()) { updateCornerBadgeShown(history->peer); + } + recountHeight(); +} + +void Row::recountHeight() { + if (const auto history = _id.history()) { _height = history->peer->isForum() ? st::forumDialogRow.height : st::defaultDialogRow.height; - } else if (key.folder()) { + } else if (_id.folder()) { _height = st::defaultDialogRow.height; } else { _height = st::forumTopicRow.height; diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.h b/Telegram/SourceFiles/dialogs/dialogs_row.h index 4df2fd36f..1a1e8d5d9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.h +++ b/Telegram/SourceFiles/dialogs/dialogs_row.h @@ -91,6 +91,7 @@ public: [[nodiscard]] int height() const { return _height; } + void recountHeight(); void updateCornerBadgeShown( not_null peer,