Implement pinned topics reordering.

This commit is contained in:
John Preston 2022-11-08 17:57:54 +04:00
parent c7741cb62a
commit 8a288476b8
17 changed files with 221 additions and 105 deletions

View file

@ -17,9 +17,7 @@ namespace Api {
void SaveNewFilterPinned(
not_null<Main::Session*> 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(

View file

@ -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.

View file

@ -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<Data::Forum*> 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<MTPint>();
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*> history,
bool archived,

View file

@ -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<Data::Forum*> forum);
void toggleHistoryArchived(
not_null<History*> history,
bool archived,

View file

@ -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)

View file

@ -236,12 +236,12 @@ not_null<Dialogs::MainList*> 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<Dialogs::MainList>(
&_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<not_null<History*>>();
pinned.reserve(dialogs.size());

View file

@ -41,7 +41,7 @@ Folder::Folder(not_null<Data::Session*> owner, FolderId id)
, _chatsList(
&owner->session(),
FilterId(),
owner->maxPinnedChatsLimitValue(this, FilterId()))
owner->maxPinnedChatsLimitValue(this))
, _name(tr::lng_archived_name(tr::now)) {
indexNameParts();

View file

@ -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(history)
, _topicsList(&session(), FilterId(0), rpl::single(kPinnedLimit)) {
, _topicsList(&session(), {}, owner().maxPinnedChatsLimitValue(this)) {
Expects(_history->peer->isChannel());
if (_history->inChatList()) {

View file

@ -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()) {

View file

@ -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<Main::Session*> 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<Data::Forum*> forum,
const QVector<MTPint> &list) {
forum->topicsList()->pinned()->applyList(forum, list);
notifyPinnedDialogsOrderUpdated();
}
void Session::applyDialogs(
Data::Folder *requestFolder,
const QVector<MTPMessage> &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<Data::Thread*> 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*> 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<Data::Forum*> forum) const {
return kTopicsPinLimit;
}
rpl::producer<int> 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<int> 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<int> 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<int> Session::maxPinnedChatsLimitValue(
not_null<Data::Forum*> forum) const {
return rpl::single(pinnedChatsLimit(forum));
}
const std::vector<Dialogs::Key> &Session::pinnedChatsOrder(
Data::Folder *folder) const {
return chatsList(folder)->pinned()->order();
}
const std::vector<Dialogs::Key> &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<Dialogs::Key> &Session::pinnedChatsOrder(
not_null<Data::Forum*> 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);

View file

@ -230,16 +230,16 @@ public:
[[nodiscard]] rpl::variable<bool> &contactsLoaded() {
return _contactsLoaded;
}
[[nodiscard]] rpl::producer<Data::Folder*> chatsListChanges() const {
[[nodiscard]] rpl::producer<Folder*> chatsListChanges() const {
return _chatsListChanged.events();
}
[[nodiscard]] bool chatsListLoaded(Data::Folder *folder = nullptr);
[[nodiscard]] rpl::producer<Data::Folder*> chatsListLoadedEvents() const {
[[nodiscard]] bool chatsListLoaded(Folder *folder = nullptr);
[[nodiscard]] rpl::producer<Folder*> 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<UserData*> user);
[[nodiscard]] rpl::producer<not_null<UserData*>> userIsBotChanges() const;
@ -339,32 +339,42 @@ public:
void applyUpdate(const MTPDupdateChatDefaultBannedRights &update);
void applyDialogs(
Data::Folder *requestFolder,
Folder *requestFolder,
const QVector<MTPMessage> &messages,
const QVector<MTPDialog> &dialogs,
std::optional<int> count = std::nullopt);
int pinnedCanPin(
Data::Folder *folder,
[[nodiscard]] bool pinnedCanPin(not_null<Thread*> thread) const;
[[nodiscard]] bool pinnedCanPin(
FilterId filterId,
not_null<History*> 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*> forum) const;
[[nodiscard]] rpl::producer<int> maxPinnedChatsLimitValue(
Folder *folder) const;
[[nodiscard]] rpl::producer<int> maxPinnedChatsLimitValue(
FilterId filterId) const;
rpl::producer<int> maxPinnedChatsLimitValue(
Data::Folder *folder,
FilterId filterId) const;
const std::vector<Dialogs::Key> &pinnedChatsOrder(
Data::Folder *folder,
[[nodiscard]] rpl::producer<int> maxPinnedChatsLimitValue(
not_null<Forum*> forum) const;
[[nodiscard]] const std::vector<Dialogs::Key> &pinnedChatsOrder(
Folder *folder) const;
[[nodiscard]] const std::vector<Dialogs::Key> &pinnedChatsOrder(
not_null<Forum*> forum) const;
[[nodiscard]] const std::vector<Dialogs::Key> &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<MTPDialogPeer> &list);
void applyPinnedTopics(
not_null<Data::Forum*> forum,
const QVector<MTPint> &list);
void reorderTwoPinnedChats(
FilterId filterId,
const Dialogs::Key &key1,
@ -572,7 +582,7 @@ public:
not_null<PollData*> processPoll(const MTPPoll &data);
not_null<PollData*> processPoll(const MTPDmessageMediaPoll &data);
[[nodiscard]] not_null<Data::CloudImage*> location(
[[nodiscard]] not_null<CloudImage*> location(
const LocationPoint &point);
void registerPhotoItem(
@ -655,9 +665,9 @@ public:
[[nodiscard]] not_null<Dialogs::MainList*> chatsListFor(
not_null<Dialogs::Entry*> entry);
[[nodiscard]] not_null<Dialogs::MainList*> chatsList(
Data::Folder *folder = nullptr);
Folder *folder = nullptr);
[[nodiscard]] not_null<const Dialogs::MainList*> chatsList(
Data::Folder *folder = nullptr) const;
Folder *folder = nullptr) const;
[[nodiscard]] not_null<Dialogs::IndexedList*> contactsList();
[[nodiscard]] not_null<Dialogs::IndexedList*> 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 <typename Method>
void enumerateItemViews(
not_null<const HistoryItem*> item,
@ -843,8 +851,8 @@ private:
QPointer<Ui::BoxContent> _exportSuggestion;
rpl::variable<bool> _contactsLoaded = false;
rpl::event_stream<Data::Folder*> _chatsListLoadedEvents;
rpl::event_stream<Data::Folder*> _chatsListChanged;
rpl::event_stream<Folder*> _chatsListLoadedEvents;
rpl::event_stream<Folder*> _chatsListChanged;
rpl::event_stream<not_null<UserData*>> _userIsBotChanges;
rpl::event_stream<not_null<PeerData*>> _botCommandsChanges;
rpl::event_stream<ItemVisibilityQuery> _itemVisibilityQueries;
@ -916,7 +924,7 @@ private:
base::flat_set<not_null<ViewElement*>>> _webpageViews;
std::unordered_map<
LocationPoint,
std::unique_ptr<Data::CloudImage>> _locations;
std::unique_ptr<CloudImage>> _locations;
std::unordered_map<
PollId,
std::unique_ptr<PollData>> _polls;

View file

@ -1255,6 +1255,13 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
mousePressReleased(e->globalPos(), e->button(), e->modifiers());
}
}
const std::vector<Key> &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<Key>{
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);

View file

@ -346,6 +346,7 @@ private:
[[nodiscard]] not_null<IndexedList*> shownDialogs() const;
[[nodiscard]] const std::vector<Key> &pinnedChatsOrder() const;
void checkReorderPinnedStart(QPoint localPosition);
int updateReorderIndexGetCount();
bool updateReorderPinned(QPoint localPosition);

View file

@ -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<Data::Forum*> forum,
const QVector<MTPint> &list) {
clear();
for (const auto &topicId : list) {
addPinned(forum->topicFor(topicId.v));
}
}
void PinnedList::applyList(const std::vector<not_null<History*>> &list) {
Expects(_filterId != 0);

View file

@ -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<Data::Session*> owner,
const QVector<MTPDialogPeer> &list);
void applyList(
not_null<Data::Forum*> forum,
const QVector<MTPint> &list);
void applyList(const std::vector<not_null<History*>> &list);
void reorder(const Key &key1, const Key &key2);

View file

@ -386,9 +386,7 @@ TimeId CalculateOnlineTill(not_null<PeerData*> 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<PeerData*> 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;

View file

@ -315,7 +315,7 @@ private:
};
History *FindWastedPin(not_null<Data::Session*> 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<Window::SessionController*> controller,
not_null<History*> 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<Data::Thread*> 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<Window::SessionController*> controller,
not_null<History*> 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<Window::SessionController*> controller,
not_null<Data::Thread*> thread) {