mirror of https://github.com/procxx/kepka.git
Parse and apply cloud filters.
This commit is contained in:
parent
ed715fb810
commit
11d31ffc84
|
@ -87,6 +87,12 @@ void ChannelData::setName(const QString &newName, const QString &newUsername) {
|
|||
updateNameDelayed(newName.isEmpty() ? name : newName, QString(), newUsername);
|
||||
}
|
||||
|
||||
void ChannelData::setAccessHash(uint64 accessHash) {
|
||||
access = accessHash;
|
||||
input = MTP_inputPeerChannel(MTP_int(bareId()), MTP_long(accessHash));
|
||||
inputChannel = MTP_inputChannel(MTP_int(bareId()), MTP_long(accessHash));
|
||||
}
|
||||
|
||||
void ChannelData::setInviteLink(const QString &newInviteLink) {
|
||||
if (newInviteLink != _inviteLink) {
|
||||
_inviteLink = newInviteLink;
|
||||
|
|
|
@ -127,6 +127,7 @@ public:
|
|||
void setPhoto(PhotoId photoId, const MTPChatPhoto &photo);
|
||||
|
||||
void setName(const QString &name, const QString &username);
|
||||
void setAccessHash(uint64 accessHash);
|
||||
|
||||
void setFlags(MTPDchannel::Flags which) {
|
||||
_flags.set(which);
|
||||
|
|
|
@ -12,71 +12,348 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_user.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_session.h"
|
||||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
namespace Data {
|
||||
|
||||
ChatFilter::ChatFilter(
|
||||
FilterId id,
|
||||
const QString &title,
|
||||
Flags flags,
|
||||
base::flat_set<not_null<History*>> always)
|
||||
: _title(title)
|
||||
base::flat_set<not_null<History*>> always,
|
||||
base::flat_set<not_null<History*>> never)
|
||||
: _id(id)
|
||||
, _title(title)
|
||||
, _always(std::move(always))
|
||||
, _never(std::move(never))
|
||||
, _flags(flags) {
|
||||
}
|
||||
|
||||
ChatFilter ChatFilter::FromTL(
|
||||
const MTPDialogFilter &data,
|
||||
not_null<Session*> owner) {
|
||||
return data.match([&](const MTPDdialogFilter &data) {
|
||||
const auto flags = (data.is_contacts() ? Flag::Contacts : Flag(0))
|
||||
| (data.is_non_contacts() ? Flag::NonContacts : Flag(0))
|
||||
| (data.is_groups() ? Flag::Groups : Flag(0))
|
||||
| (data.is_broadcasts() ? Flag::Broadcasts : Flag(0))
|
||||
| (data.is_bots() ? Flag::Bots : Flag(0))
|
||||
| (data.is_exclude_muted() ? Flag::NoMuted : Flag(0))
|
||||
| (data.is_exclude_read() ? Flag::NoRead : Flag(0))
|
||||
| (data.is_exclude_archived() ? Flag::NoArchive : Flag(0));
|
||||
auto &&to_histories = ranges::view::transform([&](
|
||||
const MTPInputPeer &data) {
|
||||
const auto peer = data.match([&](const MTPDinputPeerUser &data) {
|
||||
const auto user = owner->user(data.vuser_id().v);
|
||||
user->setAccessHash(data.vaccess_hash().v);
|
||||
return (PeerData*)user;
|
||||
}, [&](const MTPDinputPeerChat &data) {
|
||||
return (PeerData*)owner->chat(data.vchat_id().v);
|
||||
}, [&](const MTPDinputPeerChannel &data) {
|
||||
const auto channel = owner->channel(data.vchannel_id().v);
|
||||
channel->setAccessHash(data.vaccess_hash().v);
|
||||
return (PeerData*)channel;
|
||||
}, [&](const auto &data) {
|
||||
return (PeerData*)nullptr;
|
||||
});
|
||||
return peer ? owner->history(peer).get() : nullptr;
|
||||
}) | ranges::view::filter([](History *history) {
|
||||
return history != nullptr;
|
||||
}) | ranges::view::transform([](History *history) {
|
||||
return not_null<History*>(history);
|
||||
});
|
||||
auto &&always = ranges::view::all(
|
||||
data.vinclude_peers().v
|
||||
) | to_histories;
|
||||
auto &&never = ranges::view::all(
|
||||
data.vexclude_peers().v
|
||||
) | to_histories;
|
||||
return ChatFilter(
|
||||
data.vid().v,
|
||||
qs(data.vtitle()),
|
||||
flags,
|
||||
{ always.begin(), always.end() },
|
||||
{ never.begin(), never.end() });
|
||||
});
|
||||
}
|
||||
|
||||
MTPDialogFilter ChatFilter::tl() const {
|
||||
using TLFlag = MTPDdialogFilter::Flag;
|
||||
const auto flags = TLFlag(0)
|
||||
| ((_flags & Flag::Contacts) ? TLFlag::f_contacts : TLFlag(0))
|
||||
| ((_flags & Flag::NonContacts) ? TLFlag::f_non_contacts : TLFlag(0))
|
||||
| ((_flags & Flag::Groups) ? TLFlag::f_groups : TLFlag(0))
|
||||
| ((_flags & Flag::Broadcasts) ? TLFlag::f_broadcasts : TLFlag(0))
|
||||
| ((_flags & Flag::Bots) ? TLFlag::f_bots : TLFlag(0))
|
||||
| ((_flags & Flag::NoMuted) ? TLFlag::f_exclude_muted : TLFlag(0))
|
||||
| ((_flags & Flag::NoRead) ? TLFlag::f_exclude_read : TLFlag(0))
|
||||
| ((_flags & Flag::NoArchive)
|
||||
? TLFlag::f_exclude_archived
|
||||
: TLFlag(0));
|
||||
auto always = QVector<MTPInputPeer>();
|
||||
always.reserve(_always.size());
|
||||
for (const auto history : _always) {
|
||||
always.push_back(history->peer->input);
|
||||
}
|
||||
auto never = QVector<MTPInputPeer>();
|
||||
never.reserve(_never.size());
|
||||
for (const auto history : _never) {
|
||||
never.push_back(history->peer->input);
|
||||
}
|
||||
return MTP_dialogFilter(
|
||||
MTP_flags(flags),
|
||||
MTP_int(_id),
|
||||
MTP_string(_title),
|
||||
MTPstring(), // emoticon
|
||||
MTP_vector<MTPInputPeer>(),
|
||||
MTP_vector<MTPInputPeer>(always),
|
||||
MTP_vector<MTPInputPeer>(never));
|
||||
}
|
||||
|
||||
FilterId ChatFilter::id() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
QString ChatFilter::title() const {
|
||||
return _title;
|
||||
}
|
||||
|
||||
ChatFilter::Flags ChatFilter::flags() const {
|
||||
return _flags;
|
||||
}
|
||||
|
||||
const base::flat_set<not_null<History*>> &ChatFilter::always() const {
|
||||
return _always;
|
||||
}
|
||||
|
||||
const base::flat_set<not_null<History*>> &ChatFilter::never() const {
|
||||
return _never;
|
||||
}
|
||||
|
||||
bool ChatFilter::contains(not_null<History*> history) const {
|
||||
const auto flag = [&] {
|
||||
const auto peer = history->peer;
|
||||
if (const auto user = peer->asUser()) {
|
||||
return user->isBot() ? Flag::Bots : Flag::Users;
|
||||
return user->isBot()
|
||||
? Flag::Bots
|
||||
: user->isContact()
|
||||
? Flag::Contacts
|
||||
: Flag::NonContacts;
|
||||
} else if (const auto chat = peer->asChat()) {
|
||||
return Flag::PrivateGroups;
|
||||
return Flag::Groups;
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
if (channel->isBroadcast()) {
|
||||
return Flag::Broadcasts;
|
||||
} else if (channel->isPublic()) {
|
||||
return Flag::PublicGroups;
|
||||
} else {
|
||||
return Flag::PrivateGroups;
|
||||
return Flag::Groups;
|
||||
}
|
||||
} else {
|
||||
Unexpected("Peer type in ChatFilter::contains.");
|
||||
}
|
||||
}();
|
||||
if (history->folder()) {
|
||||
if (_never.contains(history)) {
|
||||
return false;
|
||||
}
|
||||
return false
|
||||
|| ((_flags & flag)
|
||||
&& (!(_flags & Flag::NoMuted) || !history->mute())
|
||||
&& (!(_flags & Flag::NoRead) || history->unreadCountForBadge()))
|
||||
&& (!(_flags & Flag::NoRead) || history->unreadCountForBadge())
|
||||
&& (!(_flags & Flag::NoArchive)
|
||||
|| (history->folderKnown() && !history->folder())))
|
||||
|| _always.contains(history);
|
||||
}
|
||||
|
||||
ChatFilters::ChatFilters(not_null<Session*> owner) : _owner(owner) {
|
||||
using Flag = ChatFilter::Flag;
|
||||
const auto all = Flag::Users
|
||||
| Flag::SecretChats
|
||||
| Flag::PrivateGroups
|
||||
| Flag::PublicGroups
|
||||
const auto all = Flag::Contacts
|
||||
| Flag::NonContacts
|
||||
| Flag::Groups
|
||||
| Flag::Broadcasts
|
||||
| Flag::Bots;
|
||||
_list.emplace(
|
||||
1,
|
||||
ChatFilter("Unmuted Chats", all | ChatFilter::Flag::NoMuted, {}));
|
||||
_list.emplace(
|
||||
2,
|
||||
ChatFilter("Unread Chats", all | ChatFilter::Flag::NoRead, {}));
|
||||
| Flag::Bots
|
||||
| Flag::NoArchive;
|
||||
_list.push_back(
|
||||
ChatFilter(1, "Unmuted", all | Flag::NoMuted, {}, {}));
|
||||
_list.push_back(
|
||||
ChatFilter(2, "Unread", all | Flag::NoRead, {}, {}));
|
||||
}
|
||||
|
||||
const base::flat_map<FilterId, ChatFilter> &ChatFilters::list() const {
|
||||
void ChatFilters::load() {
|
||||
load(false);
|
||||
}
|
||||
|
||||
void ChatFilters::load(bool force) {
|
||||
if (_loadRequestId && !force) {
|
||||
return;
|
||||
}
|
||||
auto &api = _owner->session().api();
|
||||
api.request(_loadRequestId).cancel();
|
||||
_loadRequestId = api.request(MTPmessages_GetDialogFilters(
|
||||
)).done([=](const MTPVector<MTPDialogFilter> &result) {
|
||||
auto position = 0;
|
||||
auto changed = false;
|
||||
for (const auto &filter : result.v) {
|
||||
auto parsed = ChatFilter::FromTL(filter, _owner);
|
||||
const auto b = begin(_list) + position, e = end(_list);
|
||||
const auto i = ranges::find(b, e, parsed.id(), &ChatFilter::id);
|
||||
if (i == e) {
|
||||
applyInsert(std::move(parsed), position);
|
||||
changed = true;
|
||||
} else if (i == b) {
|
||||
if (applyChange(*b, std::move(parsed))) {
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
std::swap(*i, *b);
|
||||
applyChange(*b, std::move(parsed));
|
||||
changed = true;
|
||||
}
|
||||
++position;
|
||||
}
|
||||
while (position < _list.size()) {
|
||||
applyRemove(position);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
_listChanged.fire({});
|
||||
}
|
||||
_loadRequestId = 0;
|
||||
}).fail([=](const RPCError &error) {
|
||||
_loadRequestId = 0;
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ChatFilters::apply(const MTPUpdate &update) {
|
||||
update.match([&](const MTPDupdateDialogFilter &data) {
|
||||
if (const auto filter = data.vfilter()) {
|
||||
set(ChatFilter::FromTL(*filter, _owner));
|
||||
} else {
|
||||
remove(data.vid().v);
|
||||
}
|
||||
}, [&](const MTPDupdateDialogFilters &data) {
|
||||
load(true);
|
||||
}, [&](const MTPDupdateDialogFilterOrder &data) {
|
||||
if (applyOrder(data.vorder().v)) {
|
||||
_listChanged.fire({});
|
||||
} else {
|
||||
load(true);
|
||||
}
|
||||
}, [](auto&&) {
|
||||
Unexpected("Update in ChatFilters::apply.");
|
||||
});
|
||||
}
|
||||
|
||||
void ChatFilters::set(ChatFilter filter) {
|
||||
if (!filter.id()) {
|
||||
return;
|
||||
}
|
||||
const auto i = ranges::find(_list, filter.id(), &ChatFilter::id);
|
||||
if (i == end(_list)) {
|
||||
applyInsert(std::move(filter), _list.size());
|
||||
_listChanged.fire({});
|
||||
} else if (applyChange(*i, std::move(filter))) {
|
||||
_listChanged.fire({});
|
||||
}
|
||||
}
|
||||
|
||||
void ChatFilters::applyInsert(ChatFilter filter, int position) {
|
||||
Expects(position >= 0 && position <= _list.size());
|
||||
|
||||
_list.insert(
|
||||
begin(_list) + position,
|
||||
ChatFilter(filter.id(), {}, {}, {}, {}));
|
||||
applyChange(*(begin(_list) + position), std::move(filter));
|
||||
}
|
||||
|
||||
void ChatFilters::remove(FilterId id) {
|
||||
const auto i = ranges::find(_list, id, &ChatFilter::id);
|
||||
if (i == end(_list)) {
|
||||
return;
|
||||
}
|
||||
applyRemove(i - begin(_list));
|
||||
_listChanged.fire({});
|
||||
}
|
||||
|
||||
void ChatFilters::applyRemove(int position) {
|
||||
Expects(position >= 0 && position < _list.size());
|
||||
|
||||
const auto i = begin(_list) + position;
|
||||
applyChange(*i, ChatFilter(i->id(), {}, {}, {}, {}));
|
||||
_list.erase(i);
|
||||
}
|
||||
|
||||
bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
||||
const auto rulesChanged = (filter.flags() != updated.flags())
|
||||
|| (filter.always() != updated.always());
|
||||
if (rulesChanged) {
|
||||
const auto list = _owner->chatsList()->indexed();
|
||||
for (const auto &entry : *list) {
|
||||
if (const auto history = entry->history()) {
|
||||
const auto now = updated.contains(history);
|
||||
const auto was = filter.contains(history);
|
||||
if (now != was) {
|
||||
if (now) {
|
||||
history->addToChatList(filter.id());
|
||||
} else {
|
||||
history->removeFromChatList(filter.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (filter.title() == updated.title()) {
|
||||
return false;
|
||||
}
|
||||
filter = std::move(updated);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatFilters::applyOrder(const QVector<MTPint> &order) {
|
||||
if (order.size() != _list.size()) {
|
||||
return false;
|
||||
} else if (_list.empty()) {
|
||||
return true;
|
||||
}
|
||||
auto indices = ranges::view::all(
|
||||
_list
|
||||
) | ranges::view::transform(
|
||||
&ChatFilter::id
|
||||
) | ranges::to_vector;
|
||||
auto b = indices.begin(), e = indices.end();
|
||||
for (const auto id : order) {
|
||||
const auto i = ranges::find(b, e, id.v);
|
||||
if (i == e) {
|
||||
return false;
|
||||
} else if (i != b) {
|
||||
std::swap(*i, *b);
|
||||
}
|
||||
++b;
|
||||
}
|
||||
auto changed = false;
|
||||
auto begin = _list.begin(), end = _list.end();
|
||||
for (const auto id : order) {
|
||||
const auto i = ranges::find(begin, end, id.v, &ChatFilter::id);
|
||||
Assert(i != end);
|
||||
if (i != begin) {
|
||||
changed = true;
|
||||
std::swap(*i, *begin);
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
if (changed) {
|
||||
_listChanged.fire({});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<ChatFilter> &ChatFilters::list() const {
|
||||
return _list;
|
||||
}
|
||||
|
||||
rpl::producer<> ChatFilters::changed() const {
|
||||
return _listChanged.events();
|
||||
}
|
||||
|
||||
void ChatFilters::refreshHistory(not_null<History*> history) {
|
||||
_refreshHistoryRequests.fire_copy(history);
|
||||
}
|
||||
|
|
|
@ -18,31 +18,44 @@ class Session;
|
|||
class ChatFilter final {
|
||||
public:
|
||||
enum class Flag : uchar {
|
||||
Users = 0x01,
|
||||
SecretChats = 0x02,
|
||||
PrivateGroups = 0x04,
|
||||
PublicGroups = 0x08,
|
||||
Broadcasts = 0x10,
|
||||
Bots = 0x20,
|
||||
NoMuted = 0x40,
|
||||
NoRead = 0x80,
|
||||
Contacts = 0x01,
|
||||
NonContacts = 0x02,
|
||||
Groups = 0x04,
|
||||
Broadcasts = 0x08,
|
||||
Bots = 0x10,
|
||||
NoMuted = 0x20,
|
||||
NoRead = 0x40,
|
||||
NoArchive = 0x80,
|
||||
};
|
||||
friend constexpr inline bool is_flag_type(Flag) { return true; };
|
||||
using Flags = base::flags<Flag>;
|
||||
|
||||
ChatFilter() = default;
|
||||
ChatFilter(
|
||||
FilterId id,
|
||||
const QString &title,
|
||||
Flags flags,
|
||||
base::flat_set<not_null<History*>> always);
|
||||
base::flat_set<not_null<History*>> always,
|
||||
base::flat_set<not_null<History*>> never);
|
||||
|
||||
[[nodiscard]] static ChatFilter FromTL(
|
||||
const MTPDialogFilter &data,
|
||||
not_null<Session*> owner);
|
||||
[[nodiscard]] MTPDialogFilter tl() const;
|
||||
|
||||
[[nodiscard]] FilterId id() const;
|
||||
[[nodiscard]] QString title() const;
|
||||
[[nodiscard]] Flags flags() const;
|
||||
[[nodiscard]] const base::flat_set<not_null<History*>> &always() const;
|
||||
[[nodiscard]] const base::flat_set<not_null<History*>> &never() const;
|
||||
|
||||
[[nodiscard]] bool contains(not_null<History*> history) const;
|
||||
|
||||
private:
|
||||
FilterId _id = 0;
|
||||
QString _title;
|
||||
base::flat_set<not_null<History*>> _always;
|
||||
base::flat_set<not_null<History*>> _never;
|
||||
Flags _flags;
|
||||
|
||||
};
|
||||
|
@ -51,17 +64,30 @@ class ChatFilters final {
|
|||
public:
|
||||
explicit ChatFilters(not_null<Session*> owner);
|
||||
|
||||
[[nodiscard]] const base::flat_map<FilterId, ChatFilter> &list() const;
|
||||
void load();
|
||||
void apply(const MTPUpdate &update);
|
||||
void set(ChatFilter filter);
|
||||
void remove(FilterId id);
|
||||
[[nodiscard]] const std::vector<ChatFilter> &list() const;
|
||||
[[nodiscard]] rpl::producer<> changed() const;
|
||||
|
||||
void refreshHistory(not_null<History*> history);
|
||||
[[nodiscard]] auto refreshHistoryRequests() const
|
||||
-> rpl::producer<not_null<History*>>;
|
||||
|
||||
private:
|
||||
void load(bool force);
|
||||
bool applyOrder(const QVector<MTPint> &order);
|
||||
bool applyChange(ChatFilter &filter, ChatFilter &&updated);
|
||||
void applyInsert(ChatFilter filter, int position);
|
||||
void applyRemove(int position);
|
||||
|
||||
const not_null<Session*> _owner;
|
||||
|
||||
base::flat_map<FilterId, ChatFilter> _list;
|
||||
std::vector<ChatFilter> _list;
|
||||
rpl::event_stream<> _listChanged;
|
||||
rpl::event_stream<not_null<History*>> _refreshHistoryRequests;
|
||||
mtpRequestId _loadRequestId = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_web_page.h"
|
||||
#include "data/data_game.h"
|
||||
#include "data/data_poll.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_cloud_themes.h"
|
||||
#include "data/data_streaming.h"
|
||||
|
@ -184,7 +185,6 @@ Session::Session(not_null<Main::Session*> session)
|
|||
Local::cacheBigFilePath(),
|
||||
Local::cacheBigFileSettings()))
|
||||
, _chatsList(PinnedDialogsCountMaxValue(session))
|
||||
, _chatsFilters(this)
|
||||
, _contactsList(Dialogs::SortMode::Name)
|
||||
, _contactsNoChatsList(Dialogs::SortMode::Name)
|
||||
, _selfDestructTimer([=] { checkSelfDestructItems(); })
|
||||
|
@ -193,6 +193,7 @@ Session::Session(not_null<Main::Session*> session)
|
|||
})
|
||||
, _unmuteByFinishedTimer([=] { unmuteByFinished(); })
|
||||
, _groups(this)
|
||||
, _chatsFilters(std::make_unique<ChatFilters>(this))
|
||||
, _scheduledMessages(std::make_unique<ScheduledMessages>(this))
|
||||
, _cloudThemes(std::make_unique<CloudThemes>(session))
|
||||
, _streaming(std::make_unique<Streaming>(this))
|
||||
|
@ -520,11 +521,7 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
|||
const auto channel = this->channel(input.vchannel_id().v);
|
||||
channel->addFlags(MTPDchannel::Flag::f_megagroup);
|
||||
if (!channel->access) {
|
||||
channel->input = MTP_inputPeerChannel(
|
||||
input.vchannel_id(),
|
||||
input.vaccess_hash());
|
||||
channel->inputChannel = *migratedTo;
|
||||
channel->access = input.vaccess_hash().v;
|
||||
channel->setAccessHash(input.vaccess_hash().v);
|
||||
}
|
||||
ApplyMigration(chat, channel);
|
||||
}, [](const MTPDinputChannelFromMessage &) {
|
||||
|
@ -567,10 +564,6 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
|||
if (result->loadedStatus != PeerData::FullLoaded) {
|
||||
LOG(("API Warning: not loaded minimal channel applied."));
|
||||
}
|
||||
} else {
|
||||
channel->input = MTP_inputPeerChannel(
|
||||
data.vid(),
|
||||
MTP_long(data.vaccess_hash().value_or_empty()));
|
||||
}
|
||||
|
||||
const auto wasInChannel = channel->amIn();
|
||||
|
@ -606,11 +599,8 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
|||
channel->setRestrictions(
|
||||
MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
|
||||
}
|
||||
const auto hash = data.vaccess_hash().value_or(channel->access);
|
||||
channel->inputChannel = MTP_inputChannel(
|
||||
data.vid(),
|
||||
MTP_long(hash));
|
||||
channel->access = hash;
|
||||
channel->setAccessHash(
|
||||
data.vaccess_hash().value_or(channel->access));
|
||||
channel->date = data.vdate().v;
|
||||
if (channel->version() < data.vversion().v) {
|
||||
channel->setVersion(data.vversion().v);
|
||||
|
@ -645,15 +635,12 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
|||
}
|
||||
}, [&](const MTPDchannelForbidden &data) {
|
||||
const auto channel = result->asChannel();
|
||||
channel->input = MTP_inputPeerChannel(data.vid(), data.vaccess_hash());
|
||||
|
||||
auto wasInChannel = channel->amIn();
|
||||
auto canViewAdmins = channel->canViewAdmins();
|
||||
auto canViewMembers = channel->canViewMembers();
|
||||
auto canAddMembers = channel->canAddMembers();
|
||||
|
||||
channel->inputChannel = MTP_inputChannel(data.vid(), data.vaccess_hash());
|
||||
|
||||
auto mask = mtpCastFlags(MTPDchannelForbidden::Flag::f_broadcast | MTPDchannelForbidden::Flag::f_megagroup);
|
||||
channel->setFlags((channel->flags() & ~mask) | (mtpCastFlags(data.vflags()) & mask) | MTPDchannel_ClientFlag::f_forbidden);
|
||||
|
||||
|
@ -666,7 +653,7 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
|||
|
||||
channel->setName(qs(data.vtitle()), QString());
|
||||
|
||||
channel->access = data.vaccess_hash().v;
|
||||
channel->setAccessHash(data.vaccess_hash().v);
|
||||
channel->setPhoto(MTP_chatPhotoEmpty());
|
||||
channel->date = 0;
|
||||
channel->setMembersCount(0);
|
||||
|
@ -3348,14 +3335,6 @@ not_null<const Dialogs::MainList*> Session::chatsList(
|
|||
return folder ? folder->chatsList() : &_chatsList;
|
||||
}
|
||||
|
||||
not_null<ChatFilters*> Session::chatsFilters() {
|
||||
return &_chatsFilters;
|
||||
}
|
||||
|
||||
not_null<const ChatFilters*> Session::chatsFilters() const {
|
||||
return &_chatsFilters;
|
||||
}
|
||||
|
||||
not_null<Dialogs::IndexedList*> Session::contactsList() {
|
||||
return &_contactsList;
|
||||
}
|
||||
|
@ -3383,20 +3362,21 @@ auto Session::refreshChatListEntry(
|
|||
auto result = filterIdForResult
|
||||
? RefreshChatListEntryResult()
|
||||
: mainListResult;
|
||||
for (const auto &[filterId, filter] : _chatsFilters.list()) {
|
||||
for (const auto &filter : _chatsFilters->list()) {
|
||||
const auto id = filter.id();
|
||||
auto filterResult = RefreshChatListEntryResult();
|
||||
if (history && filter.contains(history)) {
|
||||
filterResult.changed = !entry->inChatList(filterId);
|
||||
filterResult.changed = !entry->inChatList(id);
|
||||
if (filterResult.changed) {
|
||||
entry->addToChatList(filterId);
|
||||
entry->addToChatList(id);
|
||||
} else {
|
||||
filterResult.moved = entry->adjustByPosInChatList(filterId);
|
||||
filterResult.moved = entry->adjustByPosInChatList(id);
|
||||
}
|
||||
} else if (entry->inChatList(filterId)) {
|
||||
entry->removeFromChatList(filterId);
|
||||
} else if (entry->inChatList(id)) {
|
||||
entry->removeFromChatList(id);
|
||||
filterResult.changed = true;
|
||||
}
|
||||
if (filterId == filterIdForResult) {
|
||||
if (id == filterIdForResult) {
|
||||
result = filterResult;
|
||||
}
|
||||
}
|
||||
|
@ -3408,8 +3388,8 @@ void Session::removeChatListEntry(Dialogs::Key key) {
|
|||
|
||||
const auto entry = key.entry();
|
||||
entry->removeFromChatList(0);
|
||||
for (const auto &[filterId, filter] : _chatsFilters.list()) {
|
||||
entry->removeFromChatList(filterId);
|
||||
for (const auto &filter : _chatsFilters->list()) {
|
||||
entry->removeFromChatList(filter.id());
|
||||
}
|
||||
if (_contactsList.contains(key)) {
|
||||
if (!_contactsNoChatsList.contains(key)) {
|
||||
|
|
|
@ -14,7 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "dialogs/dialogs_main_list.h"
|
||||
#include "data/data_groups.h"
|
||||
#include "data/data_notify_settings.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "history/history_location_manager.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/flags.h"
|
||||
|
@ -59,6 +58,7 @@ class Folder;
|
|||
class LocationPoint;
|
||||
class WallPaper;
|
||||
class ScheduledMessages;
|
||||
class ChatFilters;
|
||||
class CloudThemes;
|
||||
class Streaming;
|
||||
class MediaRotation;
|
||||
|
@ -86,6 +86,9 @@ public:
|
|||
[[nodiscard]] const Groups &groups() const {
|
||||
return _groups;
|
||||
}
|
||||
[[nodiscard]] ChatFilters &chatsFilters() const {
|
||||
return *_chatsFilters;
|
||||
}
|
||||
[[nodiscard]] ScheduledMessages &scheduledMessages() const {
|
||||
return *_scheduledMessages;
|
||||
}
|
||||
|
@ -626,8 +629,6 @@ public:
|
|||
Data::Folder *folder = nullptr);
|
||||
[[nodiscard]] not_null<const Dialogs::MainList*> chatsList(
|
||||
Data::Folder *folder = nullptr) const;
|
||||
[[nodiscard]] not_null<ChatFilters*> chatsFilters();
|
||||
[[nodiscard]] not_null<const ChatFilters*> chatsFilters() const;
|
||||
[[nodiscard]] not_null<Dialogs::IndexedList*> contactsList();
|
||||
[[nodiscard]] not_null<Dialogs::IndexedList*> contactsNoChatsList();
|
||||
|
||||
|
@ -874,7 +875,6 @@ private:
|
|||
Stickers::SavedGifs _savedGifs;
|
||||
|
||||
Dialogs::MainList _chatsList;
|
||||
ChatFilters _chatsFilters;
|
||||
Dialogs::IndexedList _contactsList;
|
||||
Dialogs::IndexedList _contactsNoChatsList;
|
||||
|
||||
|
@ -980,6 +980,7 @@ private:
|
|||
int32 _wallpapersHash = 0;
|
||||
|
||||
Groups _groups;
|
||||
std::unique_ptr<ChatFilters> _chatsFilters;
|
||||
std::unique_ptr<ScheduledMessages> _scheduledMessages;
|
||||
std::unique_ptr<CloudThemes> _cloudThemes;
|
||||
std::unique_ptr<Streaming> _streaming;
|
||||
|
|
|
@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_user.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
|
@ -194,7 +195,10 @@ InnerWidget::InnerWidget(
|
|||
refresh();
|
||||
}, lifetime());
|
||||
|
||||
session().settings().archiveCollapsedChanges(
|
||||
rpl::merge(
|
||||
session().settings().archiveCollapsedChanges(
|
||||
) | rpl::map([] { return rpl::empty_value(); }),
|
||||
session().data().chatsFilters().changed()
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshWithCollapsedRows();
|
||||
}, lifetime());
|
||||
|
@ -204,10 +208,10 @@ InnerWidget::InnerWidget(
|
|||
refresh();
|
||||
}, lifetime());
|
||||
|
||||
session().data().chatsFilters()->refreshHistoryRequests(
|
||||
session().data().chatsFilters().refreshHistoryRequests(
|
||||
) | rpl::start_with_next([=](not_null<History*> history) {
|
||||
if (history->inChatList()
|
||||
&& !session().data().chatsFilters()->list().empty()) {
|
||||
&& !session().data().chatsFilters().list().empty()) {
|
||||
refreshDialog(history);
|
||||
}
|
||||
}, lifetime());
|
||||
|
@ -291,11 +295,17 @@ void InnerWidget::refreshWithCollapsedRows(bool toTop) {
|
|||
|
||||
_collapsedRows.clear();
|
||||
if (!_openedFolder && Global::DialogsFiltersEnabled()) {
|
||||
const auto &list = session().data().chatsFilters().list();
|
||||
if (_filterId
|
||||
&& ranges::find(list, _filterId, &Data::ChatFilter::id) == end(list)) {
|
||||
switchToFilter(0);
|
||||
}
|
||||
if (_filterId) {
|
||||
_collapsedRows.push_back(std::make_unique<CollapsedRow>(nullptr, 0));
|
||||
} else {
|
||||
for (const auto &[filterId, filter] : session().data().chatsFilters()->list()) {
|
||||
_collapsedRows.push_back(std::make_unique<CollapsedRow>(nullptr, filterId));
|
||||
for (const auto &filter : session().data().chatsFilters().list()) {
|
||||
_collapsedRows.push_back(
|
||||
std::make_unique<CollapsedRow>(nullptr, filter.id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -704,8 +714,10 @@ void InnerWidget::paintCollapsedRow(
|
|||
? row->folder->chatListName()
|
||||
: _filterId
|
||||
? (narrow ? "Show" : tr::lng_dialogs_show_all_chats(tr::now))
|
||||
: session().data().chatsFilters()->list().find(
|
||||
row->filterId)->second.title();
|
||||
: ranges::find(
|
||||
session().data().chatsFilters().list(),
|
||||
row->filterId,
|
||||
&Data::ChatFilter::id)->title();
|
||||
const auto unread = row->folder
|
||||
? row->folder->chatListUnreadCount()
|
||||
: _filterId
|
||||
|
@ -1705,6 +1717,16 @@ void InnerWidget::dragLeft() {
|
|||
clearSelection();
|
||||
}
|
||||
|
||||
FilterId InnerWidget::filterId() const {
|
||||
return _filterId;
|
||||
}
|
||||
|
||||
void InnerWidget::closeFilter() {
|
||||
if (_filterId) {
|
||||
switchToFilter(0);
|
||||
}
|
||||
}
|
||||
|
||||
void InnerWidget::clearSelection() {
|
||||
_mouseSelection = false;
|
||||
_lastMousePosition = std::nullopt;
|
||||
|
@ -2540,7 +2562,10 @@ bool InnerWidget::chooseCollapsedRow() {
|
|||
void InnerWidget::switchToFilter(FilterId filterId) {
|
||||
clearSelection();
|
||||
if (!Global::DialogsFiltersEnabled()
|
||||
|| !session().data().chatsFilters()->list().contains(filterId)) {
|
||||
|| !ranges::contains(
|
||||
session().data().chatsFilters().list(),
|
||||
filterId,
|
||||
&Data::ChatFilter::id)) {
|
||||
filterId = 0;
|
||||
}
|
||||
Global::SetDialogsFilterId(filterId);
|
||||
|
|
|
@ -80,6 +80,9 @@ public:
|
|||
const QVector<MTPPeer> &my,
|
||||
const QVector<MTPPeer> &result);
|
||||
|
||||
[[nodiscard]] FilterId filterId() const;
|
||||
void closeFilter();
|
||||
|
||||
void clearSelection();
|
||||
|
||||
void changeOpenedFolder(Data::Folder *folder);
|
||||
|
|
|
@ -1574,6 +1574,8 @@ void Widget::keyPressEvent(QKeyEvent *e) {
|
|||
if (e->key() == Qt::Key_Escape) {
|
||||
if (_openedFolder) {
|
||||
controller()->closeFolder();
|
||||
} else if (_inner->filterId()) {
|
||||
_inner->closeFilter();
|
||||
} else {
|
||||
e->ignore();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_channel_admins.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_photo.h"
|
||||
|
@ -839,7 +840,7 @@ void History::setUnreadMentionsCount(int count) {
|
|||
_unreadMentionsCount = count;
|
||||
const auto has = (count > 0);
|
||||
if (has != had) {
|
||||
owner().chatsFilters()->refreshHistory(this);
|
||||
owner().chatsFilters().refreshHistory(this);
|
||||
updateChatListEntry();
|
||||
}
|
||||
}
|
||||
|
@ -1785,7 +1786,7 @@ void History::setUnreadCount(int newUnreadCount) {
|
|||
const auto wasForBadge = (unreadCountForBadge() > 0);
|
||||
_unreadCount = newUnreadCount;
|
||||
if (wasForBadge != (unreadCountForBadge() > 0)) {
|
||||
owner().chatsFilters()->refreshHistory(this);
|
||||
owner().chatsFilters().refreshHistory(this);
|
||||
}
|
||||
|
||||
if (newUnreadCount == 1) {
|
||||
|
@ -1823,7 +1824,7 @@ void History::setUnreadMark(bool unread) {
|
|||
_unreadMark = unread;
|
||||
|
||||
if (inChatList() && noUnreadMessages) {
|
||||
owner().chatsFilters()->refreshHistory(this);
|
||||
owner().chatsFilters().refreshHistory(this);
|
||||
updateChatListEntry();
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
|
@ -1849,7 +1850,7 @@ bool History::changeMute(bool newMute) {
|
|||
_mute = newMute;
|
||||
|
||||
if (inChatList()) {
|
||||
owner().chatsFilters()->refreshHistory(this);
|
||||
owner().chatsFilters().refreshHistory(this);
|
||||
updateChatListEntry();
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
|
@ -1927,8 +1928,8 @@ void History::setFolderPointer(Data::Folder *folder) {
|
|||
const auto wasInList = inChatList();
|
||||
if (wasInList) {
|
||||
removeFromChatList(0);
|
||||
for (const auto &[filterId, _] : owner().chatsFilters()->list()) {
|
||||
removeFromChatList(filterId);
|
||||
for (const auto &filter : owner().chatsFilters().list()) {
|
||||
removeFromChatList(filter.id());
|
||||
}
|
||||
}
|
||||
const auto was = _folder.value_or(nullptr);
|
||||
|
@ -1938,9 +1939,9 @@ void History::setFolderPointer(Data::Folder *folder) {
|
|||
}
|
||||
if (wasInList) {
|
||||
addToChatList(0);
|
||||
for (const auto &[filterId, filter] : owner().chatsFilters()->list()) {
|
||||
for (const auto &filter : owner().chatsFilters().list()) {
|
||||
if (filter.contains(this)) {
|
||||
addToChatList(filterId);
|
||||
addToChatList(filter.id());
|
||||
}
|
||||
}
|
||||
owner().chatsListChanged(was);
|
||||
|
|
|
@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_histories.h"
|
||||
|
@ -1454,7 +1455,7 @@ bool HistoryWidget::notify_switchInlineBotButtonReceived(const QString &query, U
|
|||
|
||||
void HistoryWidget::notify_userIsBotChanged(UserData *user) {
|
||||
if (const auto history = session().data().history(user)) {
|
||||
session().data().chatsFilters()->refreshHistory(history);
|
||||
session().data().chatsFilters().refreshHistory(history);
|
||||
}
|
||||
if (_peer && _peer == user) {
|
||||
_list->notifyIsBotChanged();
|
||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_histories.h"
|
||||
|
@ -4051,6 +4052,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
ptsUpdateAndApply(data.vpts().v, data.vpts_count().v, update);
|
||||
} break;
|
||||
|
||||
case mtpc_updateDialogFilter:
|
||||
case mtpc_updateDialogFilterOrder:
|
||||
case mtpc_updateDialogFilters: {
|
||||
session().data().chatsFilters().apply(update);
|
||||
} break;
|
||||
|
||||
// Deleted messages.
|
||||
case mtpc_updateDeleteMessages: {
|
||||
auto &d = update.c_updateDeleteMessages();
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1720a5b4eebc794ff05d7223d79d42e00e39062e
|
||||
Subproject commit 62d4145ba04d8b6205fe0413318bc5a0f19f9410
|
Loading…
Reference in New Issue