diff --git a/Telegram/SourceFiles/api/api_chat_filters.cpp b/Telegram/SourceFiles/api/api_chat_filters.cpp index 5cb157b5c..7efcaf01a 100644 --- a/Telegram/SourceFiles/api/api_chat_filters.cpp +++ b/Telegram/SourceFiles/api/api_chat_filters.cpp @@ -17,9 +17,7 @@ namespace Api { void SaveNewFilterPinned( not_null session, FilterId filterId) { - const auto &order = session->data().pinnedChatsOrder( - nullptr, - filterId); + const auto &order = session->data().pinnedChatsOrder(filterId); auto &filters = session->data().chatsFilters(); const auto &filter = filters.applyUpdatedPinned(filterId, order); session->api().request(MTPmessages_UpdateDialogFilter( diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index b7ed8477e..54ef340e4 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -2308,6 +2308,29 @@ void Updates::feedUpdate(const MTPUpdate &update) { case mtpc_updateChannelPinnedTopics: { const auto &d = update.c_updateChannelPinnedTopics(); + const auto peerId = peerFromChannel(d.vchannel_id()); + if (const auto peer = session().data().peerLoaded(peerId)) { + if (const auto forum = peer->forum()) { + const auto done = [&] { + const auto list = d.vorder(); + if (!list) { + return false; + } + const auto &order = list->v; + const auto notLoaded = [&](const MTPint &topicId) { + return !forum->topicFor(topicId.v); + }; + if (!ranges::none_of(order, notLoaded)) { + return false; + } + session().data().applyPinnedTopics(forum, order); + return true; + }(); + if (!done) { + forum->reloadTopics(); + } + } + } } break; // Pinned message. diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index bfcb78975..e1ec8482c 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_web_page.h" #include "data/data_folder.h" #include "data/data_forum_topic.h" +#include "data/data_forum.h" #include "data/data_media_types.h" #include "data/data_sparse_ids.h" #include "data/data_search_controller.h" @@ -384,9 +385,7 @@ void ApiWrap::checkChatInvite( } void ApiWrap::savePinnedOrder(Data::Folder *folder) { - const auto &order = _session->data().pinnedChatsOrder( - folder, - FilterId()); + const auto &order = _session->data().pinnedChatsOrder(folder); const auto input = [](const Dialogs::Key &key) { if (const auto history = key.history()) { return MTP_inputDialogPeer(history->peer->input); @@ -408,6 +407,29 @@ void ApiWrap::savePinnedOrder(Data::Folder *folder) { )).send(); } +void ApiWrap::savePinnedOrder(not_null forum) { + const auto &order = _session->data().pinnedChatsOrder(forum); + const auto input = [](const Dialogs::Key &key) { + if (const auto topic = key.topic()) { + return MTP_int(topic->rootId().bare); + } + Unexpected("Key type in pinnedDialogsOrder()."); + }; + auto topics = QVector(); + topics.reserve(order.size()); + ranges::transform( + order, + ranges::back_inserter(topics), + input); + request(MTPchannels_ReorderPinnedForumTopics( + MTP_flags(MTPchannels_ReorderPinnedForumTopics::Flag::f_force), + forum->channel()->inputChannel, + MTP_vector(topics) + )).done([=](const MTPUpdates &result) { + applyUpdates(result); + }).send(); +} + void ApiWrap::toggleHistoryArchived( not_null history, bool archived, diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 5bbaabf02..349425338 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -32,6 +32,7 @@ class WallPaper; struct ResolvedForwardDraft; enum class DefaultNotify; enum class StickersType : uchar; +class Forum; class ForumTopic; class Thread; } // namespace Data @@ -149,6 +150,7 @@ public: void saveCurrentDraftToCloud(); void savePinnedOrder(Data::Folder *folder); + void savePinnedOrder(not_null forum); void toggleHistoryArchived( not_null history, bool archived, diff --git a/Telegram/SourceFiles/boxes/choose_filter_box.cpp b/Telegram/SourceFiles/boxes/choose_filter_box.cpp index a6b7d6ff4..e3452953d 100644 --- a/Telegram/SourceFiles/boxes/choose_filter_box.cpp +++ b/Telegram/SourceFiles/boxes/choose_filter_box.cpp @@ -127,7 +127,7 @@ ChooseFilterValidator::LimitData ChooseFilterValidator::limitReached( const auto list = _history->owner().chatsFilters().list(); const auto i = ranges::find(list, filterId, &Data::ChatFilter::id); - const auto limit = _history->owner().pinnedChatsLimit(nullptr, filterId); + const auto limit = _history->owner().pinnedChatsLimit(filterId); return { .reached = (i != end(list)) && !ranges::contains(i->always(), _history) diff --git a/Telegram/SourceFiles/data/data_chat_filters.cpp b/Telegram/SourceFiles/data/data_chat_filters.cpp index d7472837a..770e6855a 100644 --- a/Telegram/SourceFiles/data/data_chat_filters.cpp +++ b/Telegram/SourceFiles/data/data_chat_filters.cpp @@ -236,12 +236,12 @@ not_null ChatFilters::chatsList(FilterId filterId) { auto limit = rpl::single(rpl::empty_value()) | rpl::then( _owner->session().account().appConfig().refreshed() ) | rpl::map([=] { - return _owner->pinnedChatsLimit(nullptr, filterId); + return _owner->pinnedChatsLimit(filterId); }); pointer = std::make_unique( &_owner->session(), filterId, - _owner->maxPinnedChatsLimitValue(nullptr, filterId)); + _owner->maxPinnedChatsLimitValue(filterId)); } return pointer.get(); } @@ -476,7 +476,7 @@ const ChatFilter &ChatFilters::applyUpdatedPinned( const auto i = ranges::find(_list, id, &ChatFilter::id); Assert(i != end(_list)); - const auto limit = _owner->pinnedChatsLimit(nullptr, id); + const auto limit = _owner->pinnedChatsLimit(id); auto always = i->always(); auto pinned = std::vector>(); pinned.reserve(dialogs.size()); diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index 7c7e16a6d..99af91d01 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -41,7 +41,7 @@ Folder::Folder(not_null owner, FolderId id) , _chatsList( &owner->session(), FilterId(), - owner->maxPinnedChatsLimitValue(this, FilterId())) + owner->maxPinnedChatsLimitValue(this)) , _name(tr::lng_archived_name(tr::now)) { indexNameParts(); diff --git a/Telegram/SourceFiles/data/data_forum.cpp b/Telegram/SourceFiles/data/data_forum.cpp index 7035e0f71..6c0b835e4 100644 --- a/Telegram/SourceFiles/data/data_forum.cpp +++ b/Telegram/SourceFiles/data/data_forum.cpp @@ -37,14 +37,13 @@ constexpr auto kTopicsFirstLoad = 20; constexpr auto kLoadedTopicsMinCount = 20; constexpr auto kTopicsPerPage = 500; constexpr auto kStalePerRequest = 100; -constexpr auto kPinnedLimit = 5; // constexpr auto kGeneralColorId = 0xA9A9A9; } // namespace Forum::Forum(not_null history) : _history(history) -, _topicsList(&session(), FilterId(0), rpl::single(kPinnedLimit)) { +, _topicsList(&session(), {}, owner().maxPinnedChatsLimitValue(this)) { Expects(_history->peer->isChannel()); if (_history->inChatList()) { diff --git a/Telegram/SourceFiles/data/data_forum_topic.cpp b/Telegram/SourceFiles/data/data_forum_topic.cpp index c363ebb90..c97f57171 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.cpp +++ b/Telegram/SourceFiles/data/data_forum_topic.cpp @@ -42,7 +42,7 @@ namespace { using UpdateFlag = TopicUpdate::Flag; -constexpr auto kUserpicLoopsCount = 2; +constexpr auto kUserpicLoopsCount = 1; } // namespace @@ -315,12 +315,7 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) { if (min) { int a = 0; } else { - if (data.is_pinned()) { - owner().setChatPinned(this, 0, true); - } else { - _list->pinned()->setPinned(this, false); - } - + owner().setPinnedFromEntryList(this, data.is_pinned()); owner().notifySettings().apply(this, data.vnotify_settings()); if (const auto draft = data.vdraft()) { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 26180efa3..4c4d6a508 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -85,6 +85,8 @@ namespace { using ViewElement = HistoryView::Element; +constexpr auto kTopicsPinLimit = 5; + // s: box 100x100 // m: box 320x320 // x: box 800x800 @@ -241,7 +243,7 @@ Session::Session(not_null session) , _chatsList( session, FilterId(), - maxPinnedChatsLimitValue(nullptr, FilterId())) + maxPinnedChatsLimitValue(nullptr)) , _contactsList(Dialogs::SortMode::Name) , _contactsNoChatsList(Dialogs::SortMode::Name) , _ttlCheckTimer([=] { checkTTLs(); }) @@ -1925,10 +1927,10 @@ void Session::setChatPinned( notifyPinnedDialogsOrderUpdated(); } -void Session::setPinnedFromDialog(const Dialogs::Key &key, bool pinned) { +void Session::setPinnedFromEntryList(const Dialogs::Key &key, bool pinned) { Expects(key.entry()->folderKnown()); - const auto list = chatsList(key.entry()->folder())->pinned(); + const auto list = chatsListFor(key.entry())->pinned(); if (pinned) { list->addPinned(key); } else { @@ -1957,6 +1959,13 @@ void Session::applyPinnedChats( notifyPinnedDialogsOrderUpdated(); } +void Session::applyPinnedTopics( + not_null forum, + const QVector &list) { + forum->topicsList()->pinned()->applyList(forum, list); + notifyPinnedDialogsOrderUpdated(); +} + void Session::applyDialogs( Data::Folder *requestFolder, const QVector &messages, @@ -1983,7 +1992,7 @@ void Session::applyDialog( const auto history = this->history(peerId); history->applyDialog(requestFolder, data); - setPinnedFromDialog(history, data.is_pinned()); + setPinnedFromEntryList(history, data.is_pinned()); if (const auto from = history->peer->migrateFrom()) { if (const auto historyFrom = historyLoaded(from)) { @@ -2004,37 +2013,63 @@ void Session::applyDialog( } const auto folder = processFolder(data.vfolder()); folder->applyDialog(data); - setPinnedFromDialog(folder, data.is_pinned()); + setPinnedFromEntryList(folder, data.is_pinned()); } -int Session::pinnedCanPin( - Data::Folder *folder, +bool Session::pinnedCanPin(not_null thread) const { + if (const auto topic = thread->asTopic()) { + const auto forum = topic->forum(); + return pinnedChatsOrder(forum).size() < pinnedChatsLimit(forum); + } + const auto folder = thread->folder(); + return pinnedChatsOrder(folder).size() < pinnedChatsLimit(folder); +} + +bool Session::pinnedCanPin( FilterId filterId, not_null history) const { - if (!filterId) { - const auto limit = pinnedChatsLimit(folder, filterId); - return pinnedChatsOrder(folder, FilterId()).size() < limit; - } + Expects(filterId != 0); + const auto &list = chatsFilters().list(); const auto i = ranges::find(list, filterId, &Data::ChatFilter::id); return (i == end(list)) || (i->always().contains(history)) - || (i->always().size() < pinnedChatsLimit(folder, filterId)); + || (i->always().size() < pinnedChatsLimit(filterId)); } -int Session::pinnedChatsLimit( - Data::Folder *folder, - FilterId filterId) const { +int Session::pinnedChatsLimit(Data::Folder *folder) const { const auto limits = Data::PremiumLimits(_session); - return filterId - ? limits.dialogFiltersChatsCurrent() - : folder + return folder ? limits.dialogsFolderPinnedCurrent() : limits.dialogsPinnedCurrent(); } +int Session::pinnedChatsLimit(FilterId filterId) const { + const auto limits = Data::PremiumLimits(_session); + return limits.dialogFiltersChatsCurrent(); +} + +int Session::pinnedChatsLimit(not_null forum) const { + return kTopicsPinLimit; +} + +rpl::producer Session::maxPinnedChatsLimitValue( + Data::Folder *folder) const { + // Premium limit from appconfig. + // We always use premium limit in the MainList limit producer, + // because it slices the list to that limit. We don't want to slice + // premium-ly added chats from the pinned list because of sync issues. + return rpl::single(rpl::empty_value()) | rpl::then( + _session->account().appConfig().refreshed() + ) | rpl::map([=] { + const auto limits = Data::PremiumLimits(_session); + return folder + ? limits.dialogsFolderPinnedPremium() + : limits.dialogsPinnedPremium(); + }); +} + rpl::producer Session::maxPinnedChatsLimitValue( - Data::Folder *folder, FilterId filterId) const { // Premium limit from appconfig. // We always use premium limit in the MainList limit producer, @@ -2044,21 +2079,28 @@ rpl::producer Session::maxPinnedChatsLimitValue( _session->account().appConfig().refreshed() ) | rpl::map([=] { const auto limits = Data::PremiumLimits(_session); - return filterId - ? limits.dialogFiltersChatsPremium() - : folder - ? limits.dialogsFolderPinnedPremium() - : limits.dialogsPinnedPremium(); + return limits.dialogFiltersChatsPremium(); }); } +rpl::producer Session::maxPinnedChatsLimitValue( + not_null forum) const { + return rpl::single(pinnedChatsLimit(forum)); +} + +const std::vector &Session::pinnedChatsOrder( + Data::Folder *folder) const { + return chatsList(folder)->pinned()->order(); +} + const std::vector &Session::pinnedChatsOrder( - Data::Folder *folder, FilterId filterId) const { - const auto list = filterId - ? chatsFilters().chatsList(filterId) - : chatsList(folder); - return list->pinned()->order(); + return chatsFilters().chatsList(filterId)->pinned()->order(); +} + +const std::vector &Session::pinnedChatsOrder( + not_null forum) const { + return forum->topicsList()->pinned()->order(); } void Session::clearPinnedChats(Data::Folder *folder) { @@ -2072,7 +2114,10 @@ void Session::reorderTwoPinnedChats( Expects(key1.entry()->folderKnown() && key2.entry()->folderKnown()); Expects(filterId || (key1.entry()->folder() == key2.entry()->folder())); - const auto list = filterId + const auto topic = key1.topic(); + const auto list = topic + ? topic->forum()->topicsList() + : filterId ? chatsFilters().chatsList(filterId) : chatsList(key1.entry()->folder()); list->pinned()->reorder(key1, key2); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 7d8595a23..c3f908416 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -230,16 +230,16 @@ public: [[nodiscard]] rpl::variable &contactsLoaded() { return _contactsLoaded; } - [[nodiscard]] rpl::producer chatsListChanges() const { + [[nodiscard]] rpl::producer chatsListChanges() const { return _chatsListChanged.events(); } - [[nodiscard]] bool chatsListLoaded(Data::Folder *folder = nullptr); - [[nodiscard]] rpl::producer chatsListLoadedEvents() const { + [[nodiscard]] bool chatsListLoaded(Folder *folder = nullptr); + [[nodiscard]] rpl::producer chatsListLoadedEvents() const { return _chatsListLoadedEvents.events(); } void chatsListChanged(FolderId folderId); - void chatsListChanged(Data::Folder *folder); - void chatsListDone(Data::Folder *folder); + void chatsListChanged(Folder *folder); + void chatsListDone(Folder *folder); void userIsBotChanged(not_null user); [[nodiscard]] rpl::producer> userIsBotChanges() const; @@ -339,32 +339,42 @@ public: void applyUpdate(const MTPDupdateChatDefaultBannedRights &update); void applyDialogs( - Data::Folder *requestFolder, + Folder *requestFolder, const QVector &messages, const QVector &dialogs, std::optional count = std::nullopt); - int pinnedCanPin( - Data::Folder *folder, + [[nodiscard]] bool pinnedCanPin(not_null thread) const; + [[nodiscard]] bool pinnedCanPin( FilterId filterId, not_null history) const; - int pinnedChatsLimit( - Data::Folder *folder, + [[nodiscard]] int pinnedChatsLimit(Folder *folder) const; + [[nodiscard]] int pinnedChatsLimit(FilterId filterId) const; + [[nodiscard]] int pinnedChatsLimit(not_null forum) const; + [[nodiscard]] rpl::producer maxPinnedChatsLimitValue( + Folder *folder) const; + [[nodiscard]] rpl::producer maxPinnedChatsLimitValue( FilterId filterId) const; - rpl::producer maxPinnedChatsLimitValue( - Data::Folder *folder, - FilterId filterId) const; - const std::vector &pinnedChatsOrder( - Data::Folder *folder, + [[nodiscard]] rpl::producer maxPinnedChatsLimitValue( + not_null forum) const; + [[nodiscard]] const std::vector &pinnedChatsOrder( + Folder *folder) const; + [[nodiscard]] const std::vector &pinnedChatsOrder( + not_null forum) const; + [[nodiscard]] const std::vector &pinnedChatsOrder( FilterId filterId) const; void setChatPinned( const Dialogs::Key &key, FilterId filterId, bool pinned); - void clearPinnedChats(Data::Folder *folder); + void setPinnedFromEntryList(const Dialogs::Key &key, bool pinned); + void clearPinnedChats(Folder *folder); void applyPinnedChats( - Data::Folder *folder, + Folder *folder, const QVector &list); + void applyPinnedTopics( + not_null forum, + const QVector &list); void reorderTwoPinnedChats( FilterId filterId, const Dialogs::Key &key1, @@ -572,7 +582,7 @@ public: not_null processPoll(const MTPPoll &data); not_null processPoll(const MTPDmessageMediaPoll &data); - [[nodiscard]] not_null location( + [[nodiscard]] not_null location( const LocationPoint &point); void registerPhotoItem( @@ -655,9 +665,9 @@ public: [[nodiscard]] not_null chatsListFor( not_null entry); [[nodiscard]] not_null chatsList( - Data::Folder *folder = nullptr); + Folder *folder = nullptr); [[nodiscard]] not_null chatsList( - Data::Folder *folder = nullptr) const; + Folder *folder = nullptr) const; [[nodiscard]] not_null contactsList(); [[nodiscard]] not_null contactsNoChatsList(); @@ -727,9 +737,9 @@ private: int computeUnreadBadge(const Dialogs::UnreadState &state) const; bool computeUnreadBadgeMuted(const Dialogs::UnreadState &state) const; - void applyDialog(Data::Folder *requestFolder, const MTPDdialog &data); + void applyDialog(Folder *requestFolder, const MTPDdialog &data); void applyDialog( - Data::Folder *requestFolder, + Folder *requestFolder, const MTPDdialogFolder &data); const Messages *messagesList(PeerId peerId) const; @@ -818,8 +828,6 @@ private: PhotoData *photo, DocumentData *document); - void setPinnedFromDialog(const Dialogs::Key &key, bool pinned); - template void enumerateItemViews( not_null item, @@ -843,8 +851,8 @@ private: QPointer _exportSuggestion; rpl::variable _contactsLoaded = false; - rpl::event_stream _chatsListLoadedEvents; - rpl::event_stream _chatsListChanged; + rpl::event_stream _chatsListLoadedEvents; + rpl::event_stream _chatsListChanged; rpl::event_stream> _userIsBotChanges; rpl::event_stream> _botCommandsChanges; rpl::event_stream _itemVisibilityQueries; @@ -916,7 +924,7 @@ private: base::flat_set>> _webpageViews; std::unordered_map< LocationPoint, - std::unique_ptr> _locations; + std::unique_ptr> _locations; std::unordered_map< PollId, std::unique_ptr> _polls; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index ad2034417..04f64f21b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1255,6 +1255,13 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) { mousePressReleased(e->globalPos(), e->button(), e->modifiers()); } } +const std::vector &InnerWidget::pinnedChatsOrder() const { + return _openedForum + ? session().data().pinnedChatsOrder(_openedForum) + : _filterId + ? session().data().pinnedChatsOrder(_filterId) + : session().data().pinnedChatsOrder(_openedFolder); +} void InnerWidget::checkReorderPinnedStart(QPoint localPosition) { if (!_pressed || _dragging || _state != WidgetState::Default) { @@ -1262,16 +1269,12 @@ void InnerWidget::checkReorderPinnedStart(QPoint localPosition) { } else if (qAbs(localPosition.y() - _dragStart.y()) < style::ConvertScale(kStartReorderThreshold)) { return; - } else if (_openedForum) { - return; } _dragging = _pressed; if (updateReorderIndexGetCount() < 2) { _dragging = nullptr; } else { - const auto &order = session().data().pinnedChatsOrder( - _openedFolder, - _filterId); + const auto &order = pinnedChatsOrder(); _pinnedOnDragStart = base::flat_set{ order.begin(), order.end() @@ -1301,12 +1304,7 @@ int InnerWidget::countPinnedIndex(Row *ofRow) { } void InnerWidget::savePinnedOrder() { - if (_openedForum) { - return; - } - const auto &newOrder = session().data().pinnedChatsOrder( - _openedFolder, - _filterId); + const auto &newOrder = pinnedChatsOrder(); if (newOrder.size() != _pinnedOnDragStart.size()) { return; // Something has changed in the set of pinned chats. } @@ -1315,7 +1313,9 @@ void InnerWidget::savePinnedOrder() { return; // Something has changed in the set of pinned chats. } } - if (_filterId) { + if (_openedForum) { + session().api().savePinnedOrder(_openedForum); + } else if (_filterId) { Api::SaveNewFilterPinned(&session(), _filterId); } else { session().api().savePinnedOrder(_openedFolder); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index c20c789d1..5923e8869 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -346,6 +346,7 @@ private: [[nodiscard]] not_null shownDialogs() const; + [[nodiscard]] const std::vector &pinnedChatsOrder() const; void checkReorderPinnedStart(QPoint localPosition); int updateReorderIndexGetCount(); bool updateReorderPinned(QPoint localPosition); diff --git a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp index 94a05d302..c47ee9b3c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_entry.h" #include "history/history.h" #include "data/data_session.h" +#include "data/data_forum.h" namespace Dialogs { @@ -97,6 +98,15 @@ void PinnedList::applyList( } } +void PinnedList::applyList( + not_null forum, + const QVector &list) { + clear(); + for (const auto &topicId : list) { + addPinned(forum->topicFor(topicId.v)); + } +} + void PinnedList::applyList(const std::vector> &list) { Expects(_filterId != 0); diff --git a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h index cbdb0994b..238175b0f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h @@ -11,6 +11,7 @@ class History; namespace Data { class Session; +class Forum; } // namespace Data namespace Dialogs { @@ -35,6 +36,9 @@ public: void applyList( not_null owner, const QVector &list); + void applyList( + not_null forum, + const QVector &list); void applyList(const std::vector> &list); void reorder(const Key &key1, const Key &key2); diff --git a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm index 3f7180f44..028de0625 100644 --- a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm +++ b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm @@ -386,9 +386,7 @@ TimeId CalculateOnlineTill(not_null peer) { if (index == result) { return; } - const auto &order = _session->data().pinnedChatsOrder( - nullptr, - FilterId()); + const auto &order = _session->data().pinnedChatsOrder(nullptr); const auto d = (index < result) ? 1 : -1; // Direction. for (auto i = index; i != result; i += d) { _session->data().chatsList()->pinned()->reorder( @@ -634,7 +632,7 @@ TimeId CalculateOnlineTill(not_null peer) { const auto updatePinnedChats = [=] { _pins = ranges::views::zip( - _session->data().pinnedChatsOrder(nullptr, FilterId()), + _session->data().pinnedChatsOrder(nullptr), ranges::views::ints(0, ranges::unreachable) ) | ranges::views::transform([=](const auto &pair) { const auto index = pair.second; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 7762b7dd9..cd87cf586 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -315,7 +315,7 @@ private: }; History *FindWastedPin(not_null data, Data::Folder *folder) { - const auto &order = data->pinnedChatsOrder(folder, FilterId()); + const auto &order = data->pinnedChatsOrder(folder); for (const auto &pinned : order) { if (const auto history = pinned.history()) { if (history->peer->isChat() @@ -336,24 +336,22 @@ void AddChatMembers( bool PinnedLimitReached( not_null controller, - not_null history, - FilterId filterId) { - Expects(filterId != 0 || history->folderKnown()); - - const auto owner = &history->owner(); - const auto folder = history->folder(); - if (owner->pinnedCanPin(folder, filterId, history)) { + not_null thread) { + const auto owner = &thread->owner(); + if (owner->pinnedCanPin(thread)) { return false; } // Some old chat, that was converted, maybe is still pinned. - const auto wasted = filterId ? nullptr : FindWastedPin(owner, folder); + const auto history = thread->asHistory(); + if (!history) { + return true; + } + const auto folder = history->folder(); + const auto wasted = FindWastedPin(owner, folder); if (wasted) { owner->setChatPinned(wasted, FilterId(), false); owner->setChatPinned(history, FilterId(), true); history->session().api().savePinnedOrder(folder); - } else if (filterId) { - controller->show( - Box(FilterPinsLimitBox, &history->session(), filterId)); } else if (folder) { controller->show(Box(FolderPinsLimitBox, &history->session())); } else { @@ -362,6 +360,19 @@ bool PinnedLimitReached( return true; } +bool PinnedLimitReached( + not_null controller, + not_null history, + FilterId filterId) { + const auto owner = &history->owner(); + if (owner->pinnedCanPin(filterId, history)) { + return false; + } + controller->show( + Box(FilterPinsLimitBox, &history->session(), filterId)); + return true; +} + void TogglePinnedThread( not_null controller, not_null thread) {