diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index b8c24968df..ace72d47d0 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -134,6 +134,8 @@ nice_target_sources(Telegram ${src_loc} PRIVATE ${style_files} + api/api_chat_filters.cpp + api/api_chat_filters.h api/api_common.h api/api_hash.h api/api_self_destruct.cpp diff --git a/Telegram/SourceFiles/api/api_chat_filters.cpp b/Telegram/SourceFiles/api/api_chat_filters.cpp new file mode 100644 index 0000000000..68b0dbebe0 --- /dev/null +++ b/Telegram/SourceFiles/api/api_chat_filters.cpp @@ -0,0 +1,35 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "api/api_chat_filters.h" + +#include "data/data_session.h" +#include "data/data_chat_filters.h" +#include "main/main_session.h" +#include "apiwrap.h" + +namespace Api { + +void SaveNewFilterPinned( + not_null session, + FilterId filterId) { + const auto &order = session->data().pinnedChatsOrder( + nullptr, + filterId); + auto &filters = session->data().chatsFilters(); + const auto &filter = filters.applyUpdatedPinned( + filterId, + order); + session->api().request(MTPmessages_UpdateDialogFilter( + MTP_flags(MTPmessages_UpdateDialogFilter::Flag::f_filter), + MTP_int(filterId), + filter.tl() + )).send(); + +} + +} // namespace Api diff --git a/Telegram/SourceFiles/api/api_chat_filters.h b/Telegram/SourceFiles/api/api_chat_filters.h new file mode 100644 index 0000000000..286ca2945b --- /dev/null +++ b/Telegram/SourceFiles/api/api_chat_filters.h @@ -0,0 +1,18 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +namespace Main { +class Session; +} // namespace Main + +namespace Api { + +void SaveNewFilterPinned(not_null session, FilterId filterId); + +} // namespace Api diff --git a/Telegram/SourceFiles/data/data_chat_filters.cpp b/Telegram/SourceFiles/data/data_chat_filters.cpp index d5e1c6aada..048543feaa 100644 --- a/Telegram/SourceFiles/data/data_chat_filters.cpp +++ b/Telegram/SourceFiles/data/data_chat_filters.cpp @@ -343,9 +343,6 @@ bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) { const auto feedHistory = [&](not_null history) { const auto now = updated.contains(history); const auto was = filter.contains(history); - if (now) { - history->applyFilterPinnedIndex(id, updated); - } if (now != was) { if (now) { history->addToChatList(id, filterList); @@ -365,7 +362,8 @@ bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) { if (const auto folder = _owner->folderLoaded(Data::Folder::kId)) { feedList(folder->chatsList()); } - } else if (pinnedChanged) { + } + if (pinnedChanged) { const auto id = filter.id(); const auto filterList = _owner->chatsFilters().chatsList(id); filterList->pinned()->applyList(updated.pinned()); @@ -412,6 +410,35 @@ bool ChatFilters::applyOrder(const QVector &order) { return true; } +const ChatFilter &ChatFilters::applyUpdatedPinned( + FilterId id, + const std::vector &dialogs) { + const auto i = ranges::find(_list, id, &ChatFilter::id); + Assert(i != end(_list)); + + auto always = i->always(); + auto pinned = std::vector>(); + pinned.reserve(dialogs.size()); + for (const auto &row : dialogs) { + if (const auto history = row.history()) { + if (always.contains(history)) { + pinned.push_back(history); + } else if (always.size() < ChatFilter::kPinnedLimit) { + always.insert(history); + pinned.push_back(history); + } + } + } + set(ChatFilter( + id, + i->title(), + i->flags(), + std::move(always), + std::move(pinned), + i->never())); + return *i; +} + const std::vector &ChatFilters::list() const { return _list; } diff --git a/Telegram/SourceFiles/data/data_chat_filters.h b/Telegram/SourceFiles/data/data_chat_filters.h index b5a6efbc28..ec7f19fbb3 100644 --- a/Telegram/SourceFiles/data/data_chat_filters.h +++ b/Telegram/SourceFiles/data/data_chat_filters.h @@ -13,6 +13,7 @@ class History; namespace Dialogs { class MainList; +class Key; } // namespace Dialogs namespace Data { @@ -34,7 +35,7 @@ public: friend constexpr inline bool is_flag_type(Flag) { return true; }; using Flags = base::flags; - static constexpr int kPinnedLimit = 100; + static constexpr int kPinnedLimit = 10; ChatFilter() = default; ChatFilter( @@ -98,6 +99,10 @@ public: [[nodiscard]] not_null chatsList(FilterId filterId); + const ChatFilter &applyUpdatedPinned( + FilterId id, + const std::vector &dialogs); + private: void load(bool force); bool applyOrder(const QVector &order); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 20e9df1351..3720ac5f16 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1570,11 +1570,16 @@ int Session::pinnedChatsCount( int Session::pinnedChatsLimit( Data::Folder *folder, FilterId filterId) const { - return filterId - ? Data::ChatFilter::kPinnedLimit - : folder - ? Global::PinnedDialogsInFolderMax() - : Global::PinnedDialogsCountMax(); + if (!filterId) { + return folder + ? Global::PinnedDialogsInFolderMax() + : Global::PinnedDialogsCountMax(); + } + const auto &list = chatsFilters().list(); + const auto i = ranges::find(list, filterId, &Data::ChatFilter::id); + const auto pinned = (i != end(list)) ? i->pinned().size() : 0; + const auto already = (i != end(list)) ? i->always().size() : 0; + return Data::ChatFilter::kPinnedLimit + pinned - already; } const std::vector &Session::pinnedChatsOrder( @@ -3375,7 +3380,6 @@ auto Session::refreshChatListEntry( const auto filterList = chatsFilters().chatsList(id); auto filterResult = RefreshChatListEntryResult(); if (filter.contains(history)) { - history->applyFilterPinnedIndex(id, filter); filterResult.changed = !entry->inChatList(id); if (filterResult.changed) { entry->addToChatList(id, filterList); diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index ecf99794be..fa0919e67b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -235,9 +235,6 @@ void Entry::removeFromChatList( return; } _chatListLinks.erase(i); - if (isPinnedDialog(filterId)) { - owner().setChatPinned(_key, filterId, false); - } list->removeEntry(_key); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index f3bea90834..602793c6bf 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/multi_select.h" #include "ui/empty_userpic.h" #include "ui/unread_badge.h" +#include "api/api_chat_filters.h" #include "facades.h" #include "styles/style_dialogs.h" #include "styles/style_chat_helpers.h" @@ -1137,7 +1138,7 @@ void InnerWidget::savePinnedOrder() { } } if (_filterId) { - // #TODO pinned reorder data and to server + Api::SaveNewFilterPinned(&session(), _filterId); } else { session().api().savePinnedOrder(_openedFolder); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp index 5b79fa9b8d..969bfa64c6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.cpp @@ -70,21 +70,6 @@ void PinnedList::setPinned(const Key &key, bool pinned) { } } -void PinnedList::applyFilterPinned( - FilterId filterId, - not_null history, - int index) { - Expects(index > 0); - - history->cachePinnedIndex(filterId, index); - - const auto key = Key{ history }; - if (ranges::find(_data, key) == end(_data)) { - _data.push_back(key); - // #TODO pinned - } -} - void PinnedList::applyLimit(int limit) { Expects(limit >= 0); @@ -120,10 +105,8 @@ void PinnedList::applyList(const std::vector> &list) { _data.reserve(count); for (auto i = 0; i != count; ++i) { const auto history = list[i]; - if (history->inChatList()) { - _data.emplace_back(history); - history->cachePinnedIndex(_filterId, i + 1); - } + _data.emplace_back(history); + history->cachePinnedIndex(_filterId, i + 1); } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h index 9e064da1a2..cbdb0994ba 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_pinned_list.h @@ -30,11 +30,6 @@ public: // if (pinned) places on the first place in the list. void setPinned(const Key &key, bool pinned); - void applyFilterPinned( - FilterId filterId, - not_null history, - int index); - void clear(); void applyList( diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index b6cf3ed745..a908dfbb6a 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -1921,6 +1921,9 @@ void History::setFolderPointer(Data::Folder *folder) { if (_folder == folder) { return; } + if (isPinnedDialog(FilterId())) { + owner().setChatPinned(this, FilterId(), false); + } auto &filters = owner().chatsFilters(); const auto wasKnown = folderKnown(); const auto wasInList = inChatList(); @@ -1943,7 +1946,6 @@ void History::setFolderPointer(Data::Folder *folder) { for (const auto &filter : filters.list()) { if (filter.contains(this)) { const auto id = filter.id(); - applyFilterPinnedIndex(id, filter); addToChatList(id, filters.chatsList(id)); } } @@ -1957,24 +1959,6 @@ void History::setFolderPointer(Data::Folder *folder) { } } -void History::applyFilterPinnedIndex( - FilterId filterId, - const Data::ChatFilter &filter) { - const auto &pinned = filter.pinned(); - const auto i = ranges::find(pinned, this); - if (i == end(pinned)) { - return; - } - const auto index = (i - begin(pinned)) + 1; - if (index == lookupPinnedIndex(filterId)) { - return; - } - owner().chatsFilters().chatsList(filterId)->pinned()->applyFilterPinned( - filterId, - this, - index); -} - void History::applyPinnedUpdate(const MTPDupdateDialogPinned &data) { const auto folderId = data.vfolder_id().value_or_empty(); if (!folderKnown()) { diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 2e6a06e40a..dc05ae9713 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -369,10 +369,6 @@ public: HistoryItem *folderDialogItem = nullptr); void clearFolder(); - void applyFilterPinnedIndex( - FilterId filterId, - const Data::ChatFilter &filter); - // Interface for Data::Histories. void setInboxReadTill(MsgId upTo); std::optional countStillUnreadLocal(MsgId readTillId) const; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index c268daa6d5..3bf0f97bed 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "observer_peer.h" #include "api/api_common.h" +#include "api/api_chat_filters.h" #include "history/history.h" #include "history/history_item.h" #include "history/history_message.h" // GetErrorTextForSending. @@ -45,6 +46,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_scheduled_messages.h" #include "data/data_histories.h" +#include "data/data_chat_filters.h" #include "dialogs/dialogs_key.h" #include "boxes/peers/edit_peer_info_box.h" #include "facades.h" @@ -208,23 +210,7 @@ void TogglePinnedDialog(Dialogs::Key key, FilterId filterId) { } owner->setChatPinned(key, filterId, isPinned); - // #TODO pinned save data and to server - //const auto flags = isPinned - // ? MTPmessages_ToggleDialogPin::Flag::f_pinned - // : MTPmessages_ToggleDialogPin::Flag(0); - //if (const auto history = key.history()) { - // history->session().api().request(MTPmessages_ToggleDialogPin( - // MTP_flags(flags), - // MTP_inputDialogPeer(key.history()->peer->input) - // )).done([=](const MTPBool &result) { - // owner->notifyPinnedDialogsOrderUpdated(); - // }).send(); - //} else if (const auto folder = key.folder()) { - // folder->session().api().request(MTPmessages_ToggleDialogPin( - // MTP_flags(flags), - // MTP_inputDialogPeerFolder(MTP_int(folder->id())) - // )).send(); - //} + Api::SaveNewFilterPinned(&owner->session(), filterId); if (isPinned) { if (const auto main = App::main()) { main->dialogsToUp();