From 9d2239291d9df61c7526e4e71bcd84ad9e5e62b3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 4 Jan 2018 22:54:35 +0300 Subject: [PATCH] Add support for pinned feeds management. --- Telegram/SourceFiles/apiwrap.cpp | 34 +++--- Telegram/SourceFiles/apiwrap.h | 2 +- .../chat_helpers/gifs_list_widget.cpp | 3 +- Telegram/SourceFiles/data/data_feed.cpp | 10 ++ Telegram/SourceFiles/data/data_feed.h | 10 ++ Telegram/SourceFiles/data/data_session.cpp | 108 ++++++++++++++++++ Telegram/SourceFiles/data/data_session.h | 14 +++ .../dialogs/dialogs_indexed_list.cpp | 15 +-- .../dialogs/dialogs_inner_widget.cpp | 22 ++-- .../dialogs/dialogs_inner_widget.h | 3 +- Telegram/SourceFiles/dialogs/dialogs_key.cpp | 66 +++++++++++ Telegram/SourceFiles/dialogs/dialogs_key.h | 85 ++++++++++++++ Telegram/SourceFiles/dialogs/dialogs_row.h | 79 +------------ .../SourceFiles/dialogs/dialogs_widget.cpp | 6 +- Telegram/SourceFiles/history/history.cpp | 84 +++----------- Telegram/SourceFiles/history/history.h | 13 +-- .../SourceFiles/history/history_widget.cpp | 2 +- .../inline_bots/inline_results_widget.cpp | 3 +- Telegram/SourceFiles/mainwidget.cpp | 43 ++++--- Telegram/SourceFiles/mainwindow.cpp | 4 +- .../SourceFiles/window/window_peer_menu.cpp | 26 +++-- Telegram/gyp/telegram_sources.txt | 2 + 22 files changed, 388 insertions(+), 246 deletions(-) create mode 100644 Telegram/SourceFiles/dialogs/dialogs_key.cpp create mode 100644 Telegram/SourceFiles/dialogs/dialogs_key.h diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 7109922c6..52dbee6e0 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_drafts.h" #include "data/data_photo.h" #include "data/data_web_page.h" +#include "data/data_feed.h" #include "core/tl_help.h" #include "base/overload.h" #include "observer_peer.h" @@ -147,27 +148,22 @@ void ApiWrap::applyUpdates( App::main()->feedUpdates(updates, sentMessageRandomId); } -void ApiWrap::applyDialogsPinned(const QVector &list) { - for (auto i = list.size(); i != 0;) { - const auto &dialog = list[--i]; - switch (dialog.type()) { - case mtpc_dialog: { - const auto &dialogData = dialog.c_dialog(); - if (const auto peer = peerFromMTP(dialogData.vpeer)) { - const auto history = App::history(peer); - history->setPinnedDialog(dialogData.is_pinned()); - } - } break; - - case mtpc_dialogFeed: { - const auto &feedData = dialog.c_dialogFeed(); - const auto feedId = feedData.vfeed_id.v; - // #TODO feeds - } break; - - default: Unexpected("Type in ApiWrap::applyDialogsPinned."); +void ApiWrap::savePinnedOrder() { + const auto &order = _session->data().pinnedDialogsOrder(); + auto peers = QVector(); + peers.reserve(order.size()); + for (const auto pinned : base::reversed(order)) { + if (const auto history = pinned.history()) { + peers.push_back(MTP_inputDialogPeer(history->peer->input)); + } else if (const auto feed = pinned.feed()) { + peers.push_back(MTP_inputDialogPeerFeed(MTP_int(feed->id()))); } } + auto flags = MTPmessages_ReorderPinnedDialogs::Flag::f_force; + request(MTPmessages_ReorderPinnedDialogs( + MTP_flags(flags), + MTP_vector(peers) + )).send(); } void ApiWrap::sendMessageFail(const RPCError &error) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 9c708f984..035cce204 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -45,7 +45,7 @@ public: void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0); - void applyDialogsPinned(const QVector &list); + void savePinnedOrder(); using RequestMessageDataCallback = base::lambda; void requestMessageData( diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 2e04f81dc..dd8ec4932 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -208,9 +208,10 @@ void GifsListWidget::inlineResultsDone(const MTPmessages_BotResults &result) { auto it = _inlineCache.find(_inlineQuery); auto adding = (it != _inlineCache.cend()); - // #TODO layer 72 feed users if (result.type() == mtpc_messages_botResults) { auto &d = result.c_messages_botResults(); + App::feedUsers(d.vusers); + auto &v = d.vresults.v; auto queryId = d.vquery_id.v; diff --git a/Telegram/SourceFiles/data/data_feed.cpp b/Telegram/SourceFiles/data/data_feed.cpp index 6ac8b3e01..e623bb33e 100644 --- a/Telegram/SourceFiles/data/data_feed.cpp +++ b/Telegram/SourceFiles/data/data_feed.cpp @@ -25,4 +25,14 @@ void Feed::setUnreadCounts(int unreadCount, int unreadMutedCount) { _unreadMutedCount = unreadMutedCount; } +void Feed::cachePinnedIndex(int index) { + _pinnedIndex = index; +} + +uint64 Feed::sortKeyInChatList() const { + return 0ULL;/* isPinnedDialog() + ? pinnedDialogPos(_pinnedIndex) + : dialogPosFromDate(chatListDate());*/ +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_feed.h b/Telegram/SourceFiles/data/data_feed.h index 78722c88d..f01a2e6f0 100644 --- a/Telegram/SourceFiles/data/data_feed.h +++ b/Telegram/SourceFiles/data/data_feed.h @@ -15,16 +15,26 @@ class Feed { public: Feed(FeedId id); + FeedId id() const { + return _id; + } void registerOne(not_null channel); void unregisterOne(not_null channel); void setUnreadCounts(int unreadCount, int unreadMutedCount); + bool isPinnedDialog() const { + return _pinnedIndex > 0; + } + void cachePinnedIndex(int index); + uint64 sortKeyInChatList() const; + private: FeedId _id = 0; base::flat_set> _channels; int _unreadCount = 0; int _unreadMutedCount = 0; + int _pinnedIndex = 0; bool _complete = false; }; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index cedeb541f..533280bbc 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -164,6 +164,114 @@ MessageIdsList Session::groupToIds( return result; } +void Session::setPinnedDialog(const Dialogs::Key &key, bool pinned) { + setIsPinned(key, pinned); +} + +void Session::applyPinnedDialogs(const QVector &list) { + clearPinnedDialogs(); + for (auto i = list.size(); i != 0;) { + const auto &dialog = list[--i]; + switch (dialog.type()) { + case mtpc_dialog: { + const auto &dialogData = dialog.c_dialog(); + if (const auto peer = peerFromMTP(dialogData.vpeer)) { + setPinnedDialog(App::history(peer), true); + } + } break; + + case mtpc_dialogFeed: { + const auto &feedData = dialog.c_dialogFeed(); + const auto feedId = feedData.vfeed_id.v; + setPinnedDialog(feed(feedId), true); + } break; + + default: Unexpected("Type in ApiWrap::applyDialogsPinned."); + } + } +} + +void Session::applyPinnedDialogs(const QVector &list) { + clearPinnedDialogs(); + for (auto i = list.size(); i != 0;) { + const auto &dialogPeer = list[--i]; + switch (dialogPeer.type()) { + case mtpc_dialogPeer: { + const auto &peerData = dialogPeer.c_dialogPeer(); + if (const auto peerId = peerFromMTP(peerData.vpeer)) { + setPinnedDialog(App::history(peerId), true); + } + } break; + case mtpc_dialogPeerFeed: { + const auto &feedData = dialogPeer.c_dialogPeerFeed(); + const auto feedId = feedData.vfeed_id.v; + setPinnedDialog(feed(feedId), true); + } break; + } + } +} + +int Session::pinnedDialogsCount() const { + return _pinnedDialogs.size(); +} + +const std::deque &Session::pinnedDialogsOrder() const { + return _pinnedDialogs; +} + +void Session::clearPinnedDialogs() { + while (!_pinnedDialogs.empty()) { + setPinnedDialog(_pinnedDialogs.back(), false); + } +} + +void Session::reorderTwoPinnedDialogs( + const Dialogs::Key &key1, + const Dialogs::Key &key2) { + const auto &order = pinnedDialogsOrder(); + const auto index1 = ranges::find(order, key1) - begin(order); + const auto index2 = ranges::find(order, key2) - begin(order); + Assert(index1 >= 0 && index1 < order.size()); + Assert(index2 >= 0 && index2 < order.size()); + Assert(index1 != index2); + std::swap(_pinnedDialogs[index1], _pinnedDialogs[index2]); + key1.cachePinnedIndex(index2 + 1); + key2.cachePinnedIndex(index1 + 1); +} + +void Session::setIsPinned(const Dialogs::Key &key, bool pinned) { + const auto already = ranges::find(_pinnedDialogs, key); + if (pinned) { + if (already != end(_pinnedDialogs)) { + auto saved = std::move(*already); + const auto alreadyIndex = already - end(_pinnedDialogs); + const auto count = int(size(_pinnedDialogs)); + Assert(alreadyIndex < count); + for (auto index = alreadyIndex + 1; index != count; ++index) { + _pinnedDialogs[index - 1] = std::move(_pinnedDialogs[index]); + _pinnedDialogs[index - 1].cachePinnedIndex(index); + } + _pinnedDialogs.back() = std::move(saved); + _pinnedDialogs.back().cachePinnedIndex(count); + } else { + _pinnedDialogs.push_back(key); + if (_pinnedDialogs.size() > Global::PinnedDialogsCountMax()) { + _pinnedDialogs.front().cachePinnedIndex(0); + _pinnedDialogs.pop_front(); + + auto index = 0; + for (const auto &pinned : _pinnedDialogs) { + pinned.cachePinnedIndex(++index); + } + } else { + key.cachePinnedIndex(_pinnedDialogs.size()); + } + } + } else if (!pinned && already != _pinnedDialogs.end()) { + _pinnedDialogs.erase(already); + } +} + not_null Session::feed(FeedId id) { if (const auto result = feedLoaded(id)) { return result; diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 80ace497a..3d27d4cc0 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "chat_helpers/stickers.h" +#include "dialogs/dialogs_key.h" namespace Data { @@ -142,6 +143,15 @@ public: MessageIdsList itemsToIds(const HistoryItemsList &items) const; MessageIdsList groupToIds(not_null group) const; + int pinnedDialogsCount() const; + const std::deque &pinnedDialogsOrder() const; + void setPinnedDialog(const Dialogs::Key &key, bool pinned); + void applyPinnedDialogs(const QVector &list); + void applyPinnedDialogs(const QVector &list); + void reorderTwoPinnedDialogs( + const Dialogs::Key &key1, + const Dialogs::Key &key2); + not_null feed(FeedId id); Data::Feed *feedLoaded(FeedId id); @@ -153,6 +163,9 @@ private: } void userIsContactUpdated(not_null user); + void clearPinnedDialogs(); + void setIsPinned(const Dialogs::Key &key, bool pinned); + base::Variable _contactsLoaded = { false }; base::Variable _allChatsLoaded = { false }; base::Observable _moreChatsLoaded; @@ -180,6 +193,7 @@ private: Stickers::Order _archivedStickerSetsOrder; Stickers::SavedGifs _savedGifs; + std::deque _pinnedDialogs; base::flat_map> _feeds; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp index 7fef3c0eb..9420ab4b6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp @@ -7,6 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "dialogs/dialogs_indexed_list.h" +#include "auth_session.h" +#include "data/data_session.h" + namespace Dialogs { IndexedList::IndexedList(SortMode sortMode) @@ -81,15 +84,9 @@ void IndexedList::movePinned(Row *row, int deltaSign) { Assert(swapPinnedIndexWith != cbegin()); --swapPinnedIndexWith; } - // #TODO feeds pinned - auto history1 = row->history(); - auto history2 = (*swapPinnedIndexWith)->history(); - Assert(history1->isPinnedDialog()); - Assert(history2->isPinnedDialog()); - auto index1 = history1->getPinnedIndex(); - auto index2 = history2->getPinnedIndex(); - history1->setPinnedIndex(index2); - history2->setPinnedIndex(index1); + Auth().data().reorderTwoPinnedDialogs( + row->key(), + (*swapPinnedIndexWith)->key()); } void IndexedList::peerNameChanged( diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index aca7c2928..a1bfd7a1d 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -736,7 +736,7 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { if (updateReorderIndexGetCount() < 2) { _dragging = nullptr; } else { - _pinnedOrder = App::histories().getPinnedOrder(); + _pinnedOrder = Auth().data().pinnedDialogsOrder(); _pinnedRows[_draggingIndex].yadd = anim::value(0, localPosition.y() - _dragStart.y()); _pinnedRows[_draggingIndex].animStartTime = getms(); _a_pinnedShifting.start(); @@ -748,8 +748,7 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { int DialogsInner::shownPinnedCount() const { auto result = 0; for_const (auto row, *shownDialogs()) { - // #TODO feeds pinned - if (!row->history()->isPinnedDialog()) { + if (!row->entry()->isPinnedDialog()) { break; } ++result; @@ -758,13 +757,12 @@ int DialogsInner::shownPinnedCount() const { } int DialogsInner::countPinnedIndex(Dialogs::Row *ofRow) { - // #TODO feeds pinned - if (!ofRow || !ofRow->history()->isPinnedDialog()) { + if (!ofRow || !ofRow->entry()->isPinnedDialog()) { return -1; } auto result = 0; for_const (auto row, *shownDialogs()) { - if (!row->history()->isPinnedDialog()) { + if (!row->entry()->isPinnedDialog()) { break; } else if (row == ofRow) { return result; @@ -775,16 +773,16 @@ int DialogsInner::countPinnedIndex(Dialogs::Row *ofRow) { } void DialogsInner::savePinnedOrder() { - auto newOrder = App::histories().getPinnedOrder(); + const auto &newOrder = Auth().data().pinnedDialogsOrder(); if (newOrder.size() != _pinnedOrder.size()) { return; // Something has changed in the set of pinned chats. } - for_const (auto history, newOrder) { - if (_pinnedOrder.indexOf(history) < 0) { + for (const auto &pinned : newOrder) { + if (!base::contains(_pinnedOrder, pinned)) { return; // Something has changed in the set of pinned chats. } } - App::histories().savePinnedToServer(); + Auth().api().savePinnedOrder(); } void DialogsInner::finishReorderPinned() { @@ -2246,7 +2244,7 @@ void DialogsInner::destroyData() { Dialogs::RowDescriptor DialogsInner::chatListEntryBefore( const Dialogs::RowDescriptor &which) const { - if (!which.key.value) { + if (!which.key) { return Dialogs::RowDescriptor(); } if (_state == DefaultState) { @@ -2323,7 +2321,7 @@ Dialogs::RowDescriptor DialogsInner::chatListEntryBefore( Dialogs::RowDescriptor DialogsInner::chatListEntryAfter( const Dialogs::RowDescriptor &which) const { - if (!which.key.value) { + if (!which.key) { return Dialogs::RowDescriptor(); } if (_state == DefaultState) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 0f1488bc9..1aec0554b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "dialogs/dialogs_widget.h" +#include "dialogs/dialogs_key.h" #include "base/flags.h" namespace Dialogs { @@ -276,7 +277,7 @@ private: }; std::vector _pinnedRows; BasicAnimation _a_pinnedShifting; - QList _pinnedOrder; + std::deque _pinnedOrder; // Remember the last currently dragged row top shift for updating area. int _aboveTopShift = -1; diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.cpp b/Telegram/SourceFiles/dialogs/dialogs_key.cpp new file mode 100644 index 000000000..260e1641b --- /dev/null +++ b/Telegram/SourceFiles/dialogs/dialogs_key.cpp @@ -0,0 +1,66 @@ +/* +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 "dialogs/dialogs_key.h" + +#include "data/data_feed.h" + +namespace Dialogs { + +const QString &Key::name() const { + if (const auto h = history()) { + return h->peer->name; + } + // #TODO feeds name + static const auto empty = QString(); + return empty; +} + +const PeerData::NameFirstChars &Key::nameFirstChars() const { + if (const auto h = history()) { + return h->peer->nameFirstChars(); + } + // #TODO feeds name + static const auto empty = PeerData::NameFirstChars(); + return empty; +} + +uint64 Key::sortKey() const { + if (const auto h = history()) { + return h->sortKeyInChatList(); + } else if (const auto f = feed()) { + return f->sortKeyInChatList(); + } else { + Unexpected("Key value in Key::sortKey"); + } +} + +void Key::cachePinnedIndex(int index) const { + if (const auto h = history()) { + h->cachePinnedIndex(index); + } else if (const auto f = feed()) { + f->cachePinnedIndex(index); + } else { + Unexpected("Key value in Key::setPinnedIndex"); + } +} + +History *Key::history() const { + if (const auto p = base::get_if>(&_value)) { + return *p; + } + return nullptr; +} + +Data::Feed *Key::feed() const { + if (const auto p = base::get_if>(&_value)) { + return *p; + } + return nullptr; +} + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.h b/Telegram/SourceFiles/dialogs/dialogs_key.h new file mode 100644 index 000000000..389ec7a13 --- /dev/null +++ b/Telegram/SourceFiles/dialogs/dialogs_key.h @@ -0,0 +1,85 @@ +/* +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 + +#include "base/value_ordering.h" + +namespace Data { +class Feed; +} // namespace Data + +namespace Dialogs { + +class Key { +public: + Key() = default; + Key(History *history) : _value(history) { + } + Key(not_null history) : _value(history) { + } + Key(Data::Feed *feed) : _value(feed) { + } + Key(not_null feed) : _value(feed) { + } + + explicit operator bool() const { + return !!_value; + } + History *history() const; + Data::Feed *feed() const; + + const QString &name() const; + const PeerData::NameFirstChars &nameFirstChars() const; + uint64 sortKey() const; + void cachePinnedIndex(int index) const; + + inline bool operator<(const Key &other) const { + return _value < other._value; + } + inline bool operator>(const Key &other) const { + return (other < *this); + } + inline bool operator<=(const Key &other) const { + return !(other < *this); + } + inline bool operator>=(const Key &other) const { + return !(*this < other); + } + inline bool operator==(const Key &other) const { + return _value == other._value; + } + inline bool operator!=(const Key &other) const { + return !(*this == other); + } + + base::optional_variant< + not_null, + not_null> raw() const { + return _value; + } + + // Not working :( + //friend inline auto value_ordering_helper(const Key &key) { + // return key.value; + //} + +private: + base::optional_variant, not_null> _value; + +}; + +struct RowDescriptor { + RowDescriptor() = default; + RowDescriptor(Key key, MsgId msgId) : key(key), msgId(msgId) { + } + + Key key; + MsgId msgId = 0; +}; + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.h b/Telegram/SourceFiles/dialogs/dialogs_row.h index f3dff3669..7831b3887 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.h +++ b/Telegram/SourceFiles/dialogs/dialogs_row.h @@ -8,15 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/text/text.h" -#include "base/value_ordering.h" +#include "dialogs/dialogs_key.h" class History; class HistoryItem; -namespace Data { -class Feed; -} // namespace Data - namespace Ui { class RippleAnimation; } // namespace Ui @@ -26,79 +22,6 @@ namespace Layout { class RowPainter; } // namespace Layout -struct Key { - Key() = default; - Key(History *history) : value(history) { - } - Key(not_null history) : value(history) { - } - Key(Data::Feed *feed) : value(feed) { - } - Key(not_null feed) : value(feed) { - } - const QString &name() const { - if (const auto p = base::get_if>(&value)) { - return (*p)->peer->name; - } - // #TODO feeds name - static const auto empty = QString(); - return empty; - } - const PeerData::NameFirstChars &nameFirstChars() const { - if (const auto p = base::get_if>(&value)) { - return (*p)->peer->nameFirstChars(); - } - // #TODO feeds name - static const auto empty = PeerData::NameFirstChars(); - return empty; - } - uint64 sortKey() const { - if (const auto p = base::get_if>(&value)) { - return (*p)->sortKeyInChatList(); - } - // #TODO feeds sort in chats list - return 0ULL; - } - History *history() const { - if (const auto p = base::get_if>(&value)) { - return *p; - } - return nullptr; - } - Data::Feed *feed() const { - if (const auto p = base::get_if>(&value)) { - return *p; - } - return nullptr; - } - - inline bool operator<(const Key &other) const { - return value < other.value; - } - inline bool operator==(const Key &other) const { - return value == other.value; - } - - // Not working :( - //friend inline auto value_ordering_helper(const Key &key) { - // return key.value; - //} - - base::optional_variant< - not_null, - not_null> value; - -}; - -struct RowDescriptor { - RowDescriptor() = default; - RowDescriptor(Key key, MsgId msgId) : key(key), msgId(msgId) { - } - - Key key; - MsgId msgId = 0; -}; - class RippleRow { public: RippleRow(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 9857e7082..1dcee945d 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_inner_widget.h" #include "dialogs/dialogs_search_from_controllers.h" -#include "dialogs/dialogs_row.h" +#include "dialogs/dialogs_key.h" #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" #include "ui/wrap/fade_wrap.h" @@ -400,12 +400,11 @@ void DialogsWidget::pinnedDialogsReceived( if (_pinnedDialogsRequestId != requestId) return; - App::histories().clearPinned(); - auto &data = result.c_messages_peerDialogs(); App::feedUsers(data.vusers); App::feedChats(data.vchats); + Auth().data().applyPinnedDialogs(data.vdialogs.v); applyReceivedDialogs(data.vdialogs.v, data.vmessages.v); _pinnedDialogsRequestId = 0; @@ -420,7 +419,6 @@ void DialogsWidget::pinnedDialogsReceived( void DialogsWidget::applyReceivedDialogs( const QVector &dialogs, const QVector &messages) { - Auth().api().applyDialogsPinned(dialogs); App::feedMsgs(messages, NewMessageLast); _inner->dialogsReceived(dialogs); onListScroll(); diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index d25dd2424..23aa030a5 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -47,8 +47,6 @@ constexpr auto kStatusShowClientsidePlayGame = 10000; constexpr auto kSetMyActionForMs = 10000; constexpr auto kNewBlockEachMessage = 50; -auto GlobalPinnedIndex = 0; - HistoryItem *createUnsupportedMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from) { auto text = TextWithEntities { lng_message_unsupported(lt_link, qsl("https://desktop.telegram.org")) }; TextUtilities::ParseEntities(text, Ui::ItemTextNoMonoOptions().flags); @@ -516,7 +514,8 @@ void ChannelHistory::checkMaxReadMessageDate() { if (!item->unread()) { _maxReadMessageDate = item->date; if (item->isGroupMigrate() && isMegagroup() && peer->migrateFrom()) { - _maxReadMessageDate = date(MTP_int(peer->asChannel()->date + 1)); // no report spam panel + // No report spam panel. + _maxReadMessageDate = date(MTP_int(peer->asChannel()->date + 1)); } return; } @@ -583,7 +582,6 @@ not_null Histories::findOrInsert(const PeerId &peerId, int32 unreadCou void Histories::clear() { App::historyClearMsgs(); - _pinnedDialogs.clear(); auto temp = base::take(map); for_const (auto history, temp) { delete history; @@ -677,63 +675,6 @@ bool Histories::unreadOnlyMuted() const { return Global::IncludeMuted() ? (_unreadMuted >= _unreadFull) : false; } -void Histories::setIsPinned(History *history, bool isPinned) { - if (isPinned) { - _pinnedDialogs.insert(history); - if (_pinnedDialogs.size() > Global::PinnedDialogsCountMax()) { - auto minIndex = GlobalPinnedIndex + 1; - auto minIndexHistory = (History*)nullptr; - for_const (auto pinned, _pinnedDialogs) { - if (pinned->getPinnedIndex() < minIndex) { - minIndex = pinned->getPinnedIndex(); - minIndexHistory = pinned; - } - } - Assert(minIndexHistory != nullptr); - minIndexHistory->setPinnedDialog(false); - } - } else { - _pinnedDialogs.remove(history); - } -} - -void Histories::clearPinned() { - for (auto pinned : base::take(_pinnedDialogs)) { - pinned->setPinnedDialog(false); - } -} - -int Histories::pinnedCount() const { - return _pinnedDialogs.size(); -} - -QList Histories::getPinnedOrder() const { - QMap sorter; - for_const (auto pinned, _pinnedDialogs) { - sorter.insert(pinned->getPinnedIndex(), pinned); - } - QList result; - for (auto i = sorter.cend(), e = sorter.cbegin(); i != e;) { - --i; - result.push_back(i.value()); - } - return result; -} - -void Histories::savePinnedToServer() const { - const auto order = getPinnedOrder(); - auto peers = QVector(); - peers.reserve(order.size()); - for (const auto history : order) { - peers.push_back(MTP_inputDialogPeer(history->peer->input)); - } - auto flags = MTPmessages_ReorderPinnedDialogs::Flag::f_force; - MTP::send( - MTPmessages_ReorderPinnedDialogs( - MTP_flags(flags), - MTP_vector(peers))); -} - void Histories::selfDestructIn(not_null item, TimeMs delay) { _selfDestructItems.push_back(item->fullId()); if (!_selfDestructTimer.isActive() || _selfDestructTimer.remainingTime() > delay) { @@ -2262,8 +2203,10 @@ void History::setNotLoadedAtBottom() { } namespace { - uint32 _dialogsPosToTopShift = 0x80000000UL; -} + +uint32 _dialogsPosToTopShift = 0x80000000UL; + +} // namespace inline uint64 dialogPosFromDate(const QDateTime &date) { if (date.isNull()) return 0; @@ -2316,7 +2259,9 @@ void History::updateChatListSortPosition() { return lastMsgDate; }; - _sortKeyInChatList = isPinnedDialog() ? pinnedDialogPos(_pinnedIndex) : dialogPosFromDate(chatListDate()); + _sortKeyInChatList = isPinnedDialog() + ? pinnedDialogPos(_pinnedIndex) + : dialogPosFromDate(chatListDate()); if (auto m = App::main()) { if (needUpdateInChatList()) { if (_sortKeyInChatList) { @@ -2602,20 +2547,17 @@ void History::updateChatListEntry() const { } } -void History::setPinnedDialog(bool isPinned) { - setPinnedIndex(isPinned ? (++GlobalPinnedIndex) : 0); -} - -void History::setPinnedIndex(int pinnedIndex) { +void History::cachePinnedIndex(int pinnedIndex) { if (_pinnedIndex != pinnedIndex) { auto wasPinned = isPinnedDialog(); _pinnedIndex = pinnedIndex; updateChatListSortPosition(); updateChatListEntry(); if (wasPinned != isPinnedDialog()) { - Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::PinnedChanged); + Notify::peerUpdatedDelayed( + peer, + Notify::PeerUpdate::Flag::PinnedChanged); } - App::histories().setIsPinned(this, isPinnedDialog()); } } diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 6878f643c..ac20eae05 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -75,12 +75,6 @@ public: } } - void setIsPinned(History *history, bool isPinned); - void clearPinned(); - int pinnedCount() const; - QList getPinnedOrder() const; - void savePinnedToServer() const; - struct SendActionAnimationUpdate { History *history; int width; @@ -98,7 +92,6 @@ private: int _unreadFull = 0; int _unreadMuted = 0; base::Observable _sendActionAnimationUpdated; - OrderedSet _pinnedDialogs; base::Timer _selfDestructTimer; std::vector _selfDestructItems; @@ -275,11 +268,7 @@ public: bool isPinnedDialog() const { return (_pinnedIndex > 0); } - void setPinnedDialog(bool isPinned); - void setPinnedIndex(int newPinnedIndex); - int getPinnedIndex() const { - return _pinnedIndex; - } + void cachePinnedIndex(int newPinnedIndex); MsgId minMsgId() const; MsgId maxMsgId() const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 46bea9634..58bb947f8 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -65,7 +65,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "inline_bots/inline_results_widget.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "core/crash_reports.h" -#include "dialogs/dialogs_row.h" +#include "dialogs/dialogs_key.h" #include "styles/style_history.h" #include "styles/style_dialogs.h" #include "styles/style_window.h" diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 4a2f2e0d1..41eeebe00 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -1008,9 +1008,10 @@ void Widget::inlineResultsDone(const MTPmessages_BotResults &result) { auto it = _inlineCache.find(_inlineQuery); auto adding = (it != _inlineCache.cend()); - // #TODO layer 72 feed users if (result.type() == mtpc_messages_botResults) { auto &d = result.c_messages_botResults(); + App::feedUsers(d.vusers); + auto &v = d.vresults.v; auto queryId = d.vquery_id.v; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 75fc425e1..092afec8c 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -34,7 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "observer_peer.h" #include "apiwrap.h" #include "dialogs/dialogs_widget.h" -#include "dialogs/dialogs_row.h" +#include "dialogs/dialogs_key.h" #include "history/history_widget.h" #include "history/history_message.h" #include "history/history_media.h" @@ -1100,7 +1100,7 @@ void MainWidget::deleteConversation(PeerData *peer, bool deleteHistory) { Ui::showChatsList(); } if (auto history = App::historyLoaded(peer->id)) { - history->setPinnedDialog(false); + Auth().data().setPinnedDialog(history, false); removeDialog(history); if (peer->isMegagroup() && peer->asChannel()->mgInfo->migrateFromPtr) { if (auto migrated = App::historyLoaded(peer->asChannel()->mgInfo->migrateFromPtr->id)) { @@ -5330,31 +5330,20 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_dialogPeerFeed: { const auto &feed = dialogPeer.c_dialogPeerFeed(); const auto feedId = feed.vfeed_id.v; - // #TODO feeds + if (!Auth().data().feedLoaded(feedId)) { + DEBUG_LOG(("API Error: " + "pinned feed not loaded for feedId %1" + ).arg(feedId + )); + return false; + } } break; } } return true; }(); if (allLoaded) { - App::histories().clearPinned(); - for (auto i = order.size(); i != 0;) { - const auto &dialogPeer = order[--i]; - switch (dialogPeer.type()) { - case mtpc_dialogPeer: { - const auto &peer = dialogPeer.c_dialogPeer(); - const auto peerId = peerFromMTP(peer.vpeer); - const auto history = App::historyLoaded(peerId); - Assert(history != nullptr); - history->setPinnedDialog(true); - } break; - case mtpc_dialogPeerFeed: { - const auto &feed = dialogPeer.c_dialogPeerFeed(); - const auto feedId = feed.vfeed_id.v; - // #TODO feeds - } break; - } - } + Auth().data().applyPinnedDialogs(order); } else { _dialogs->loadPinnedDialogs(); } @@ -5369,7 +5358,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_dialogPeer: { const auto peerId = peerFromMTP(d.vpeer.c_dialogPeer().vpeer); if (const auto history = App::historyLoaded(peerId)) { - history->setPinnedDialog(d.is_pinned()); + Auth().data().setPinnedDialog(history, d.is_pinned()); } else { DEBUG_LOG(("API Error: " "pinned chat not loaded for peer %1" @@ -5380,7 +5369,15 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { } break; case mtpc_dialogPeerFeed: { const auto feedId = d.vpeer.c_dialogPeerFeed().vfeed_id.v; - // #TODO feeds + if (const auto feed = Auth().data().feedLoaded(feedId)) { + Auth().data().setPinnedDialog(feed, d.is_pinned()); + } else { + DEBUG_LOG(("API Error: " + "pinned feed not loaded for feedId %1" + ).arg(feedId + )); + _dialogs->loadPinnedDialogs(); + } } break; } } break; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 7512ab06f..6da36d5da 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -222,7 +222,9 @@ void MainWindow::setupPasscode() { } void MainWindow::setupIntro() { - if (_intro && !_intro->isHidden() && !_main) return; + if (_intro && !_intro->isHidden() && !_main) { + return; + } Ui::hideSettingsAndLayer(anim::type::instant); diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index c78cede73..347de8a76 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -65,12 +65,14 @@ private: }; History *FindWastedPin() { - auto order = App::histories().getPinnedOrder(); - for_const (auto pinned, order) { - if (pinned->peer->isChat() - && pinned->peer->asChat()->isDeactivated() - && !pinned->inChatList(Dialogs::Mode::All)) { - return pinned; + const auto &order = Auth().data().pinnedDialogsOrder(); + for (const auto pinned : order) { + if (const auto history = pinned.history()) { + if (history->peer->isChat() + && history->peer->asChat()->isDeactivated() + && !history->inChatList(Dialogs::Mode::All)) { + return history; + } } } return nullptr; @@ -116,14 +118,14 @@ void Filler::addPinToggle() { auto pinToggle = [peer] { auto history = App::history(peer); auto isPinned = !history->isPinnedDialog(); - auto pinnedCount = App::histories().pinnedCount(); - auto pinnedMax = Global::PinnedDialogsCountMax(); + const auto pinnedCount = Auth().data().pinnedDialogsCount(); + const auto pinnedMax = Global::PinnedDialogsCountMax(); if (isPinned && pinnedCount >= pinnedMax) { // Some old chat, that was converted to supergroup, maybe is still pinned. if (auto wasted = FindWastedPin()) { - wasted->setPinnedDialog(false); - history->setPinnedDialog(isPinned); - App::histories().savePinnedToServer(); + Auth().data().setPinnedDialog(wasted, false); + Auth().data().setPinnedDialog(history, true); + Auth().api().savePinnedOrder(); } else { auto errorText = lng_error_pinned_max( lt_count, @@ -133,7 +135,7 @@ void Filler::addPinToggle() { return; } - history->setPinnedDialog(isPinned); + Auth().data().setPinnedDialog(history, isPinned); auto flags = MTPmessages_ToggleDialogPin::Flags(0); if (isPinned) { flags |= MTPmessages_ToggleDialogPin::Flag::f_pinned; diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index ff87a9e78..410429230 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -198,6 +198,8 @@ <(src_loc)/dialogs/dialogs_indexed_list.h <(src_loc)/dialogs/dialogs_inner_widget.cpp <(src_loc)/dialogs/dialogs_inner_widget.h +<(src_loc)/dialogs/dialogs_key.cpp +<(src_loc)/dialogs/dialogs_key.h <(src_loc)/dialogs/dialogs_layout.cpp <(src_loc)/dialogs/dialogs_layout.h <(src_loc)/dialogs/dialogs_list.cpp