mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 15:17:07 +02:00
Implement pinned topics reordering.
This commit is contained in:
parent
c7741cb62a
commit
8a288476b8
17 changed files with 221 additions and 105 deletions
Telegram/SourceFiles
api
apiwrap.cppapiwrap.hboxes
data
data_chat_filters.cppdata_folder.cppdata_forum.cppdata_forum_topic.cppdata_session.cppdata_session.h
dialogs
platform/mac/touchbar/items
window
|
@ -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(
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue