Update API scheme on layer 145.

This commit is contained in:
John Preston 2022-08-22 12:15:34 +03:00
parent 33b266175d
commit f72092a261
25 changed files with 165 additions and 114 deletions

View file

@ -128,8 +128,8 @@ chatForbidden#6592a1a7 id:long title:string = Chat;
channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat; channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat; channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#d18ee226 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?Vector<string> = ChatFull; chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions = ChatFull;
channelFull#ea68a619 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?Vector<string> = ChatFull; channelFull#f2355507 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant; chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant; chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -1417,6 +1417,10 @@ reactionEmpty#79f5d419 = Reaction;
reactionEmoji#1b2286b8 emoticon:string = Reaction; reactionEmoji#1b2286b8 emoticon:string = Reaction;
reactionCustomEmoji#8935fc73 document_id:long = Reaction; reactionCustomEmoji#8935fc73 document_id:long = Reaction;
chatReactionsNone#eafc32bc = ChatReactions;
chatReactionsAll#52928bca flags:# allow_custom:flags.0?true = ChatReactions;
chatReactionsSome#661d4037 reactions:Vector<Reaction> = ChatReactions;
emailVerifyPurposeLoginSetup#4345be73 phone_number:string phone_code_hash:string = EmailVerifyPurpose; emailVerifyPurposeLoginSetup#4345be73 phone_number:string phone_code_hash:string = EmailVerifyPurpose;
emailVerifyPurposeLoginChange#527d22eb = EmailVerifyPurpose; emailVerifyPurposeLoginChange#527d22eb = EmailVerifyPurpose;
emailVerifyPurposePassport#bbf51685 = EmailVerifyPurpose; emailVerifyPurposePassport#bbf51685 = EmailVerifyPurpose;
@ -1716,7 +1720,7 @@ messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
messages.sendReaction#d30d78d4 flags:# big:flags.1?true peer:InputPeer msg_id:int reaction:flags.0?Vector<Reaction> = Updates; messages.sendReaction#d30d78d4 flags:# big:flags.1?true peer:InputPeer msg_id:int reaction:flags.0?Vector<Reaction> = Updates;
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates; messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = messages.MessageReactionsList; messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = messages.MessageReactionsList;
messages.setChatAvailableReactions#14050ea6 peer:InputPeer available_reactions:Vector<string> = Updates; messages.setChatAvailableReactions#feb16771 peer:InputPeer available_reactions:ChatReactions = Updates;
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions; messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool; messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?int text:flags.1?string from_lang:flags.2?string to_lang:string = messages.TranslatedText; messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?int text:flags.1?string from_lang:flags.2?string to_lang:string = messages.TranslatedText;

View file

@ -1002,8 +1002,8 @@ void Controller::fillManageSection() {
? QString::number(allowed) + " / " + QString::number(total) ? QString::number(allowed) + " / " + QString::number(total)
: tr::lng_manage_peer_reactions_off(tr::now); : tr::lng_manage_peer_reactions_off(tr::now);
}); });
const auto done = [=](const std::vector<QString> &chosen) { const auto done = [=](const std::vector<QString> &chosen, bool all) {
SaveAllowedReactions(_peer, chosen); SaveAllowedReactions(_peer, chosen, all);
}; };
AddButtonWithCount( AddButtonWithCount(
_controls.buttonsLayout, _controls.buttonsLayout,
@ -1015,7 +1015,7 @@ void Controller::fillManageSection() {
!_peer->isBroadcast(), !_peer->isBroadcast(),
session->data().reactions().list( session->data().reactions().list(
Data::Reactions::Type::Active), Data::Reactions::Type::Active),
*Data::PeerReactionsFilter(_peer).allowed, Data::PeerAllowedReactions(_peer),
done)); done));
}, },
{ &st::infoRoundedIconReactions, Settings::kIconRed }); { &st::infoRoundedIconReactions, Settings::kIconRed });

View file

@ -26,8 +26,8 @@ void EditAllowedReactionsBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
bool isGroup, bool isGroup,
const std::vector<Data::Reaction> &list, const std::vector<Data::Reaction> &list,
const base::flat_set<QString> &selected, const Data::AllowedReactions &allowed,
Fn<void(const std::vector<QString> &)> callback) { Fn<void(const std::vector<QString> &, bool all)> callback) {
const auto iconHeight = st::editPeerReactionsPreview; const auto iconHeight = st::editPeerReactionsPreview;
box->setTitle(tr::lng_manage_peer_reactions()); box->setTitle(tr::lng_manage_peer_reactions());
@ -37,7 +37,7 @@ void EditAllowedReactionsBox(
rpl::event_stream<bool> forceToggleAll; rpl::event_stream<bool> forceToggleAll;
}; };
const auto state = box->lifetime().make_state<State>(State{ const auto state = box->lifetime().make_state<State>(State{
.anyToggled = !selected.empty(), .anyToggled = (allowed.type != Data::AllowedReactionsType::Some),
}); });
const auto collect = [=] { const auto collect = [=] {
@ -91,7 +91,7 @@ void EditAllowedReactionsBox(
tr::lng_manage_peer_reactions_available()); tr::lng_manage_peer_reactions_available());
const auto active = [&](const Data::Reaction &entry) { const auto active = [&](const Data::Reaction &entry) {
return selected.contains(entry.id.emoji()); return ranges::contains(allowed.some, entry.id);
}; };
const auto add = [&](const Data::Reaction &entry) { const auto add = [&](const Data::Reaction &entry) {
if (entry.id.emoji().isEmpty()) { if (entry.id.emoji().isEmpty()) {
@ -139,7 +139,7 @@ void EditAllowedReactionsBox(
box->addButton(tr::lng_settings_save(), [=] { box->addButton(tr::lng_settings_save(), [=] {
const auto ids = collect(); const auto ids = collect();
box->closeBox(); box->closeBox();
callback(ids); callback(ids, false);
}); });
box->addButton(tr::lng_cancel(), [=] { box->addButton(tr::lng_cancel(), [=] {
box->closeBox(); box->closeBox();
@ -148,20 +148,26 @@ void EditAllowedReactionsBox(
void SaveAllowedReactions( void SaveAllowedReactions(
not_null<PeerData*> peer, not_null<PeerData*> peer,
const std::vector<QString> &allowed) { const std::vector<QString> &allowed,
bool all) {
auto ids = allowed | ranges::views::transform([=](QString value) { auto ids = allowed | ranges::views::transform([=](QString value) {
return MTP_string(value); return MTP_reactionEmoji(MTP_string(value));
}) | ranges::to<QVector<MTPstring>>; }) | ranges::to<QVector<MTPReaction>>;
const auto updated = all
? MTP_chatReactionsAll(MTP_flags(peer->isBroadcast()
? MTPDchatReactionsAll::Flag(0)
: MTPDchatReactionsAll::Flag::f_allow_custom))
: MTP_chatReactionsSome(MTP_vector<MTPReaction>(ids));
peer->session().api().request(MTPmessages_SetChatAvailableReactions( peer->session().api().request(MTPmessages_SetChatAvailableReactions(
peer->input, peer->input,
MTP_vector<MTPstring>(ids) updated
)).done([=](const MTPUpdates &result) { )).done([=](const MTPUpdates &result) {
peer->session().api().applyUpdates(result); peer->session().api().applyUpdates(result);
if (const auto chat = peer->asChat()) { if (const auto chat = peer->asChat()) {
chat->setAllowedReactions({ begin(allowed), end(allowed) }); chat->setAllowedReactions(Data::Parse(updated));
} else if (const auto channel = peer->asChannel()) { } else if (const auto channel = peer->asChannel()) {
channel->setAllowedReactions({ begin(allowed), end(allowed) }); channel->setAllowedReactions(Data::Parse(updated));
} else { } else {
Unexpected("Invalid peer type in SaveAllowedReactions."); Unexpected("Invalid peer type in SaveAllowedReactions.");
} }

View file

@ -11,6 +11,7 @@ class PeerData;
namespace Data { namespace Data {
struct Reaction; struct Reaction;
struct AllowedReactions;
} // namespace Data } // namespace Data
namespace Ui { namespace Ui {
@ -21,9 +22,10 @@ void EditAllowedReactionsBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
bool isGroup, bool isGroup,
const std::vector<Data::Reaction> &list, const std::vector<Data::Reaction> &list,
const base::flat_set<QString> &selected, const Data::AllowedReactions &allowed,
Fn<void(const std::vector<QString> &)> callback); Fn<void(const std::vector<QString> &, bool all)> callback);
void SaveAllowedReactions( void SaveAllowedReactions(
not_null<PeerData*> peer, not_null<PeerData*> peer,
const std::vector<QString> &allowed); const std::vector<QString> &allowed,
bool all);

View file

@ -769,20 +769,23 @@ PeerId ChannelData::groupCallDefaultJoinAs() const {
return _callDefaultJoinAs; return _callDefaultJoinAs;
} }
void ChannelData::setAllowedReactions(base::flat_set<QString> list) { void ChannelData::setAllowedReactions(Data::AllowedReactions value) {
if (_allowedReactions != list) { if (_allowedReactions != value) {
const auto toggled = (_allowedReactions.empty() != list.empty()); const auto enabled = [](const Data::AllowedReactions &allowed) {
_allowedReactions = std::move(list); return (allowed.type != Data::AllowedReactionsType::Some)
if (toggled) { || !allowed.some.empty();
owner().reactions().updateAllInHistory( };
this, const auto was = enabled(_allowedReactions);
!_allowedReactions.empty()); _allowedReactions = std::move(value);
const auto now = enabled(_allowedReactions);
if (was != now) {
owner().reactions().updateAllInHistory(this, now);
} }
session().changes().peerUpdated(this, UpdateFlag::Reactions); session().changes().peerUpdated(this, UpdateFlag::Reactions);
} }
} }
const base::flat_set<QString> &ChannelData::allowedReactions() const { const Data::AllowedReactions &ChannelData::allowedReactions() const {
return _allowedReactions; return _allowedReactions;
} }
@ -935,8 +938,11 @@ void ApplyChannelUpdate(
} }
} }
channel->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty())); channel->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
channel->setAllowedReactions( if (const auto allowed = update.vavailable_reactions()) {
Data::Reactions::ParseAllowed(update.vavailable_reactions())); channel->setAllowedReactions(Data::Parse(*allowed));
} else {
channel->setAllowedReactions({});
}
channel->fullUpdated(); channel->fullUpdated();
channel->setPendingRequestsCount( channel->setPendingRequestsCount(
update.vrequests_pending().value_or_empty(), update.vrequests_pending().value_or_empty(),

View file

@ -417,8 +417,8 @@ public:
void setGroupCallDefaultJoinAs(PeerId peerId); void setGroupCallDefaultJoinAs(PeerId peerId);
[[nodiscard]] PeerId groupCallDefaultJoinAs() const; [[nodiscard]] PeerId groupCallDefaultJoinAs() const;
void setAllowedReactions(base::flat_set<QString> list); void setAllowedReactions(Data::AllowedReactions value);
[[nodiscard]] const base::flat_set<QString> &allowedReactions() const; [[nodiscard]] const Data::AllowedReactions &allowedReactions() const;
// Still public data members. // Still public data members.
uint64 access = 0; uint64 access = 0;
@ -467,7 +467,7 @@ private:
QString _inviteLink; QString _inviteLink;
std::optional<ChannelData*> _linkedChat; std::optional<ChannelData*> _linkedChat;
base::flat_set<QString> _allowedReactions; Data::AllowedReactions _allowedReactions;
std::unique_ptr<Data::GroupCall> _call; std::unique_ptr<Data::GroupCall> _call;
PeerId _callDefaultJoinAs = 0; PeerId _callDefaultJoinAs = 0;

View file

@ -284,20 +284,23 @@ void ChatData::setPendingRequestsCount(
} }
} }
void ChatData::setAllowedReactions(base::flat_set<QString> list) { void ChatData::setAllowedReactions(Data::AllowedReactions value) {
if (_allowedReactions != list) { if (_allowedReactions != value) {
const auto toggled = (_allowedReactions.empty() != list.empty()); const auto enabled = [](const Data::AllowedReactions &allowed) {
_allowedReactions = std::move(list); return (allowed.type != Data::AllowedReactionsType::Some)
if (toggled) { || !allowed.some.empty();
owner().reactions().updateAllInHistory( };
this, const auto was = enabled(_allowedReactions);
!_allowedReactions.empty()); _allowedReactions = std::move(value);
const auto now = enabled(_allowedReactions);
if (was != now) {
owner().reactions().updateAllInHistory(this, now);
} }
session().changes().peerUpdated(this, UpdateFlag::Reactions); session().changes().peerUpdated(this, UpdateFlag::Reactions);
} }
} }
const base::flat_set<QString> &ChatData::allowedReactions() const { const Data::AllowedReactions &ChatData::allowedReactions() const {
return _allowedReactions; return _allowedReactions;
} }
@ -475,8 +478,11 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
} }
chat->checkFolder(update.vfolder_id().value_or_empty()); chat->checkFolder(update.vfolder_id().value_or_empty());
chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty())); chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
chat->setAllowedReactions( if (const auto allowed = update.vavailable_reactions()) {
Data::Reactions::ParseAllowed(update.vavailable_reactions())); chat->setAllowedReactions(Data::Parse(*allowed));
} else {
chat->setAllowedReactions({});
}
chat->fullUpdated(); chat->fullUpdated();
chat->setAbout(qs(update.vabout())); chat->setAbout(qs(update.vabout()));
chat->setPendingRequestsCount( chat->setPendingRequestsCount(

View file

@ -167,8 +167,8 @@ public:
int count, int count,
std::vector<UserId> recentRequesters); std::vector<UserId> recentRequesters);
void setAllowedReactions(base::flat_set<QString> list); void setAllowedReactions(Data::AllowedReactions value);
[[nodiscard]] const base::flat_set<QString> &allowedReactions() const; [[nodiscard]] const Data::AllowedReactions &allowedReactions() const;
// Still public data members. // Still public data members.
const MTPlong inputChat; const MTPlong inputChat;
@ -194,7 +194,7 @@ private:
int _pendingRequestsCount = 0; int _pendingRequestsCount = 0;
std::vector<UserId> _recentRequesters; std::vector<UserId> _recentRequesters;
base::flat_set<QString> _allowedReactions; Data::AllowedReactions _allowedReactions;
std::unique_ptr<Data::GroupCall> _call; std::unique_ptr<Data::GroupCall> _call;
PeerId _callDefaultJoinAs = 0; PeerId _callDefaultJoinAs = 0;

View file

@ -37,13 +37,4 @@ inline bool operator==(const ReactionId &a, const ReactionId &b) {
[[nodiscard]] ReactionId ReactionFromMTP(const MTPReaction &reaction); [[nodiscard]] ReactionId ReactionFromMTP(const MTPReaction &reaction);
[[nodiscard]] MTPReaction ReactionToMTP(ReactionId id); [[nodiscard]] MTPReaction ReactionToMTP(ReactionId id);
struct ReactionsFilter {
std::optional<base::flat_set<QString>> allowed;
bool customAllowed = false;
friend inline auto operator<=>(
const ReactionsFilter &,
const ReactionsFilter &) = default;
};
} // namespace Data } // namespace Data

View file

@ -72,15 +72,14 @@ PossibleItemReactions LookupPossibleReactions(not_null<HistoryItem*> item) {
} }
} }
} else { } else {
const auto filter = PeerReactionsFilter(peer); const auto &allowed = PeerAllowedReactions(peer);
result.recent.reserve(filter.allowed result.recent.reserve((allowed.type == AllowedReactionsType::Some)
? filter.allowed->size() ? allowed.some.size()
: full.size()); : full.size());
for (const auto &reaction : full) { for (const auto &reaction : full) {
const auto id = reaction.id; const auto id = reaction.id;
const auto emoji = filter.allowed ? id.emoji() : QString(); if ((allowed.type == AllowedReactionsType::Some)
if (filter.allowed && !ranges::contains(allowed.some, id)) {
&& (emoji.isEmpty() || !filter.allowed->contains(emoji))) {
continue; continue;
} else if (reaction.premium } else if (reaction.premium
&& !session->premium() && !session->premium()
@ -93,7 +92,7 @@ PossibleItemReactions LookupPossibleReactions(not_null<HistoryItem*> item) {
result.recent.push_back(&reaction); result.recent.push_back(&reaction);
} }
} }
result.customAllowed = session->premium() && peer->isUser(); result.customAllowed = (allowed.type == AllowedReactionsType::All);
} }
const auto i = ranges::find( const auto i = ranges::find(
result.recent, result.recent,
@ -344,19 +343,6 @@ void Reactions::downloadTaskFinished() {
} }
} }
base::flat_set<QString> Reactions::ParseAllowed(
const MTPVector<MTPstring> *list) {
if (!list) {
return {};
}
const auto parsed = ranges::views::all(
list->v
) | ranges::views::transform([](const MTPstring &string) {
return qs(string);
}) | ranges::to_vector;
return { begin(parsed), end(parsed) };
}
void Reactions::request() { void Reactions::request() {
auto &api = _owner->session().api(); auto &api = _owner->session().api();
if (_requestId) { if (_requestId) {

View file

@ -61,9 +61,6 @@ public:
[[nodiscard]] ReactionId favorite() const; [[nodiscard]] ReactionId favorite() const;
void setFavorite(const ReactionId &emoji); void setFavorite(const ReactionId &emoji);
[[nodiscard]] static base::flat_set<QString> ParseAllowed(
const MTPVector<MTPstring> *list);
[[nodiscard]] rpl::producer<> updates() const; [[nodiscard]] rpl::producer<> updates() const;
enum class ImageSize { enum class ImageSize {

View file

@ -109,6 +109,39 @@ bool ApplyBotMenuButton(
return changed; return changed;
} }
bool operator<(
const AllowedReactions &a,
const AllowedReactions &b) {
return (a.type < b.type) || ((a.type == b.type) && (a.some < b.some));
}
bool operator==(
const AllowedReactions &a,
const AllowedReactions &b) {
return (a.type == b.type) && (a.some == b.some);
}
AllowedReactions Parse(const MTPChatReactions &value) {
return value.match([&](const MTPDchatReactionsNone &) {
return AllowedReactions();
}, [&](const MTPDchatReactionsAll &data) {
return AllowedReactions{
.type = (data.is_allow_custom()
? AllowedReactionsType::All
: AllowedReactionsType::Default),
};
}, [&](const MTPDchatReactionsSome &data) {
return AllowedReactions{
.some = ranges::views::all(
data.vreactions().v
) | ranges::views::transform(
ReactionFromMTP
) | ranges::to_vector,
.type = AllowedReactionsType::Some,
};
});
}
} // namespace Data } // namespace Data
PeerClickHandler::PeerClickHandler(not_null<PeerData*> peer) PeerClickHandler::PeerClickHandler(not_null<PeerData*> peer)

View file

@ -35,6 +35,7 @@ namespace Data {
class Session; class Session;
class GroupCall; class GroupCall;
class CloudImageView; class CloudImageView;
struct ReactionId;
int PeerColorIndex(PeerId peerId); int PeerColorIndex(PeerId peerId);
int PeerColorIndex(BareId bareId); int PeerColorIndex(BareId bareId);
@ -100,6 +101,22 @@ bool ApplyBotMenuButton(
not_null<BotInfo*> info, not_null<BotInfo*> info,
const MTPBotMenuButton *button); const MTPBotMenuButton *button);
enum class AllowedReactionsType {
All,
Default,
Some,
};
struct AllowedReactions {
std::vector<ReactionId> some;
AllowedReactionsType type = AllowedReactionsType::Some;
};
bool operator<(const AllowedReactions &a, const AllowedReactions &b);
bool operator==(const AllowedReactions &a, const AllowedReactions &b);
[[nodiscard]] AllowedReactions Parse(const MTPChatReactions &value);
} // namespace Data } // namespace Data
class PeerClickHandler : public ClickHandler { class PeerClickHandler : public ClickHandler {

View file

@ -513,23 +513,26 @@ rpl::producer<QImage> PeerUserpicImageValue(
}; };
} }
ReactionsFilter PeerReactionsFilter(not_null<PeerData*> peer) { const AllowedReactions &PeerAllowedReactions(not_null<PeerData*> peer) {
if (const auto chat = peer->asChat()) { if (const auto chat = peer->asChat()) {
return { .allowed = chat->allowedReactions() }; return chat->allowedReactions();
} else if (const auto channel = peer->asChannel()) { } else if (const auto channel = peer->asChannel()) {
return { .allowed = channel->allowedReactions() }; return channel->allowedReactions();
} else { } else {
return { .customAllowed = true }; static const auto result = AllowedReactions{
.type = AllowedReactionsType::All,
};
return result;
} }
} }
rpl::producer<ReactionsFilter> PeerReactionsFilterValue( rpl::producer<AllowedReactions> PeerAllowedReactionsValue(
not_null<PeerData*> peer) { not_null<PeerData*> peer) {
return peer->session().changes().peerFlagsValue( return peer->session().changes().peerFlagsValue(
peer, peer,
Data::PeerUpdate::Flag::Reactions Data::PeerUpdate::Flag::Reactions
) | rpl::map([=]{ ) | rpl::map([=]{
return PeerReactionsFilter(peer); return PeerAllowedReactions(peer);
}); });
} }

View file

@ -21,7 +21,6 @@ class Session;
namespace Data { namespace Data {
struct Reaction; struct Reaction;
struct ReactionsFilter;
template <typename ChangeType, typename Error, typename Generator> template <typename ChangeType, typename Error, typename Generator>
inline auto FlagsValueWithMask( inline auto FlagsValueWithMask(
@ -134,8 +133,9 @@ inline auto PeerFullFlagValue(
int size, int size,
ImageRoundRadius radius); ImageRoundRadius radius);
[[nodiscard]] ReactionsFilter PeerReactionsFilter(not_null<PeerData*> peer); [[nodiscard]] const AllowedReactions &PeerAllowedReactions(
[[nodiscard]] rpl::producer<ReactionsFilter> PeerReactionsFilterValue( not_null<PeerData*> peer);
[[nodiscard]] rpl::producer<AllowedReactions> PeerAllowedReactionsValue(
not_null<PeerData*> peer); not_null<PeerData*> peer);
[[nodiscard]] int UniqueReactionsLimit(not_null<PeerData*> peer); [[nodiscard]] int UniqueReactionsLimit(not_null<PeerData*> peer);

View file

@ -36,7 +36,7 @@ namespace Data {
struct Group; struct Group;
class CloudImageView; class CloudImageView;
struct Reaction; struct Reaction;
struct ReactionsFilter; struct AllowedReactions;
} // namespace Data } // namespace Data
namespace HistoryView::Reactions { namespace HistoryView::Reactions {
@ -120,7 +120,7 @@ public:
} }
virtual CopyRestrictionType listSelectRestrictionType() = 0; virtual CopyRestrictionType listSelectRestrictionType() = 0;
virtual auto listAllowedReactionsValue() virtual auto listAllowedReactionsValue()
-> rpl::producer<Data::ReactionsFilter> = 0; -> rpl::producer<Data::AllowedReactions> = 0;
virtual void listShowPremiumToast(not_null<DocumentData*> document) = 0; virtual void listShowPremiumToast(not_null<DocumentData*> document) = 0;
}; };

View file

@ -684,8 +684,8 @@ CopyRestrictionType PinnedWidget::listSelectRestrictionType() {
} }
auto PinnedWidget::listAllowedReactionsValue() auto PinnedWidget::listAllowedReactionsValue()
-> rpl::producer<Data::ReactionsFilter> { -> rpl::producer<Data::AllowedReactions> {
return Data::PeerReactionsFilterValue(_history->peer); return Data::PeerAllowedReactionsValue(_history->peer);
} }
void PinnedWidget::listShowPremiumToast(not_null<DocumentData*> document) { void PinnedWidget::listShowPremiumToast(not_null<DocumentData*> document) {

View file

@ -106,7 +106,7 @@ public:
CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override; CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override;
CopyRestrictionType listSelectRestrictionType() override; CopyRestrictionType listSelectRestrictionType() override;
auto listAllowedReactionsValue() auto listAllowedReactionsValue()
-> rpl::producer<Data::ReactionsFilter> override; -> rpl::producer<Data::AllowedReactions> override;
void listShowPremiumToast(not_null<DocumentData*> document) override; void listShowPremiumToast(not_null<DocumentData*> document) override;
protected: protected:

View file

@ -2043,8 +2043,8 @@ CopyRestrictionType RepliesWidget::listSelectRestrictionType() {
} }
auto RepliesWidget::listAllowedReactionsValue() auto RepliesWidget::listAllowedReactionsValue()
-> rpl::producer<Data::ReactionsFilter> { -> rpl::producer<Data::AllowedReactions> {
return Data::PeerReactionsFilterValue(_history->peer); return Data::PeerAllowedReactionsValue(_history->peer);
} }
void RepliesWidget::listShowPremiumToast(not_null<DocumentData*> document) { void RepliesWidget::listShowPremiumToast(not_null<DocumentData*> document) {

View file

@ -143,7 +143,7 @@ public:
CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override; CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override;
CopyRestrictionType listSelectRestrictionType() override; CopyRestrictionType listSelectRestrictionType() override;
auto listAllowedReactionsValue() auto listAllowedReactionsValue()
->rpl::producer<Data::ReactionsFilter> override; ->rpl::producer<Data::AllowedReactions> override;
void listShowPremiumToast(not_null<DocumentData*> document) override; void listShowPremiumToast(not_null<DocumentData*> document) override;
protected: protected:

View file

@ -1357,9 +1357,8 @@ CopyRestrictionType ScheduledWidget::listSelectRestrictionType() {
} }
auto ScheduledWidget::listAllowedReactionsValue() auto ScheduledWidget::listAllowedReactionsValue()
-> rpl::producer<Data::ReactionsFilter> { -> rpl::producer<Data::AllowedReactions> {
const auto empty = base::flat_set<QString>(); return rpl::single(Data::AllowedReactions());
return rpl::single(Data::ReactionsFilter{ .allowed = empty });
} }
void ScheduledWidget::listShowPremiumToast( void ScheduledWidget::listShowPremiumToast(

View file

@ -128,7 +128,7 @@ public:
CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override; CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override;
CopyRestrictionType listSelectRestrictionType() override; CopyRestrictionType listSelectRestrictionType() override;
auto listAllowedReactionsValue() auto listAllowedReactionsValue()
-> rpl::producer<Data::ReactionsFilter> override; -> rpl::producer<Data::AllowedReactions> override;
void listShowPremiumToast(not_null<DocumentData*> document) override; void listShowPremiumToast(not_null<DocumentData*> document) override;
protected: protected:

View file

@ -888,7 +888,7 @@ void SetupManagerList(
if (peerChanged) { if (peerChanged) {
state->peer = peer; state->peer = peer;
state->peerLifetime = rpl::combine( state->peerLifetime = rpl::combine(
Data::PeerReactionsFilterValue(peer), Data::PeerAllowedReactionsValue(peer),
Data::UniqueReactionsLimitValue(peer) Data::UniqueReactionsLimitValue(peer)
) | rpl::start_with_next(push); ) | rpl::start_with_next(push);
} else { } else {

View file

@ -459,16 +459,16 @@ rpl::producer<int> AllowedReactionsCountValue(not_null<PeerData*> peer) {
if (peer->isUser()) { if (peer->isUser()) {
return FullReactionsCountValue(&peer->session()); return FullReactionsCountValue(&peer->session());
} }
return peer->session().changes().peerFlagsValue( return rpl::combine(
peer, FullReactionsCountValue(&peer->session()),
UpdateFlag::Reactions peer->session().changes().peerFlagsValue(
) | rpl::map([=] { peer,
if (const auto chat = peer->asChat()) { UpdateFlag::Reactions)
return int(chat->allowedReactions().size()); ) | rpl::map([=](int full, const auto&) {
} else if (const auto channel = peer->asChannel()) { const auto &allowed = Data::PeerAllowedReactions(peer);
return int(channel->allowedReactions().size()); return (allowed.type == Data::AllowedReactionsType::Some)
} ? int(allowed.some.size())
Unexpected("Peer type in AllowedReactionsCountValue."); : full;
}); });
} }

View file

@ -351,10 +351,11 @@ bool ShowSendPremiumError(
const auto type = peer->isBroadcast() const auto type = peer->isBroadcast()
? ReactionDisableType::Channel ? ReactionDisableType::Channel
: ReactionDisableType::Group; : ReactionDisableType::Group;
if (const auto allowed = Data::PeerReactionsFilter(peer).allowed) { const auto &allowed = Data::PeerAllowedReactions(peer);
if (!allowed.some.empty()) {
for (const auto &reaction : list) { for (const auto &reaction : list) {
if (reaction.premium if (reaction.premium
&& !allowed->contains(reaction.id.emoji())) { && !ranges::contains(allowed.some, reaction.id)) {
result.emplace(reaction.id, type); result.emplace(reaction.id, type);
} }
} }