mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Check if bot is in group or if can be added.
This commit is contained in:
parent
17ce93fd5e
commit
4234f0b797
4 changed files with 208 additions and 67 deletions
|
@ -4089,6 +4089,50 @@ void ApiWrap::saveContactSignupSilent(bool silent) {
|
||||||
_contactSignupSilentRequestId = requestId;
|
_contactSignupSilentRequestId = requestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto ApiWrap::botCommonGroups(not_null<UserData*> bot) const
|
||||||
|
-> std::optional<std::vector<not_null<PeerData*>>> {
|
||||||
|
const auto i = _botCommonGroups.find(bot);
|
||||||
|
return (i != end(_botCommonGroups))
|
||||||
|
? i->second
|
||||||
|
: std::optional<std::vector<not_null<PeerData*>>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiWrap::requestBotCommonGroups(
|
||||||
|
not_null<UserData*> bot,
|
||||||
|
Fn<void()> done) {
|
||||||
|
if (_botCommonGroupsRequests.contains(bot)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_botCommonGroupsRequests.emplace(bot, done);
|
||||||
|
const auto finish = [=](std::vector<not_null<PeerData*>> list) {
|
||||||
|
_botCommonGroups.emplace(bot, std::move(list));
|
||||||
|
if (const auto callback = _botCommonGroupsRequests.take(bot)) {
|
||||||
|
(*callback)();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto limit = 100;
|
||||||
|
request(MTPmessages_GetCommonChats(
|
||||||
|
bot->inputUser,
|
||||||
|
MTP_long(0), // max_id
|
||||||
|
MTP_int(limit)
|
||||||
|
)).done([=](const MTPmessages_Chats &result) {
|
||||||
|
const auto chats = result.match([](const auto &data) {
|
||||||
|
return &data.vchats().v;
|
||||||
|
});
|
||||||
|
auto &owner = session().data();
|
||||||
|
auto list = std::vector<not_null<PeerData*>>();
|
||||||
|
list.reserve(chats->size());
|
||||||
|
for (const auto &chat : *chats) {
|
||||||
|
if (const auto peer = owner.processChat(chat)) {
|
||||||
|
list.push_back(peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish(std::move(list));
|
||||||
|
}).fail([=] {
|
||||||
|
finish({});
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
void ApiWrap::saveSelfBio(const QString &text) {
|
void ApiWrap::saveSelfBio(const QString &text) {
|
||||||
if (_bio.requestId) {
|
if (_bio.requestId) {
|
||||||
if (text != _bio.requestedText) {
|
if (text != _bio.requestedText) {
|
||||||
|
|
|
@ -352,6 +352,10 @@ public:
|
||||||
std::optional<bool> contactSignupSilentCurrent() const;
|
std::optional<bool> contactSignupSilentCurrent() const;
|
||||||
void saveContactSignupSilent(bool silent);
|
void saveContactSignupSilent(bool silent);
|
||||||
|
|
||||||
|
[[nodiscard]] auto botCommonGroups(not_null<UserData*> bot) const
|
||||||
|
-> std::optional<std::vector<not_null<PeerData*>>>;
|
||||||
|
void requestBotCommonGroups(not_null<UserData*> bot, Fn<void()> done);
|
||||||
|
|
||||||
void saveSelfBio(const QString &text);
|
void saveSelfBio(const QString &text);
|
||||||
|
|
||||||
[[nodiscard]] Api::Authorizations &authorizations();
|
[[nodiscard]] Api::Authorizations &authorizations();
|
||||||
|
@ -692,6 +696,11 @@ private:
|
||||||
std::optional<bool> _contactSignupSilent;
|
std::optional<bool> _contactSignupSilent;
|
||||||
rpl::event_stream<bool> _contactSignupSilentChanges;
|
rpl::event_stream<bool> _contactSignupSilentChanges;
|
||||||
|
|
||||||
|
base::flat_map<
|
||||||
|
not_null<UserData*>,
|
||||||
|
std::vector<not_null<PeerData*>>> _botCommonGroups;
|
||||||
|
base::flat_map<not_null<UserData*>, Fn<void()>> _botCommonGroupsRequests;
|
||||||
|
|
||||||
base::flat_map<FullMsgId, QString> _unlikelyMessageLinks;
|
base::flat_map<FullMsgId, QString> _unlikelyMessageLinks;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "boxes/peers/choose_peer_box.h"
|
#include "boxes/peers/choose_peer_box.h"
|
||||||
|
|
||||||
|
#include "apiwrap.h" // ApiWrap::botCommonGroups / requestBotCommonGroups.
|
||||||
#include "boxes/add_contact_box.h"
|
#include "boxes/add_contact_box.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "boxes/premium_limits_box.h"
|
#include "boxes/premium_limits_box.h"
|
||||||
|
@ -18,8 +19,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history_item_reply_markup.h"
|
#include "history/history_item_reply_markup.h"
|
||||||
#include "info/profile/info_profile_icon.h"
|
#include "info/profile/info_profile_icon.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h" // Session::api().
|
||||||
#include "settings/settings_common.h"
|
#include "settings/settings_common.h"
|
||||||
#include "ui/boxes/confirm_box.h"
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
@ -55,10 +58,87 @@ private:
|
||||||
const not_null<Window::SessionNavigation*> _navigation;
|
const not_null<Window::SessionNavigation*> _navigation;
|
||||||
not_null<UserData*> _bot;
|
not_null<UserData*> _bot;
|
||||||
RequestPeerQuery _query;
|
RequestPeerQuery _query;
|
||||||
|
base::flat_set<not_null<PeerData*>> _commonGroups;
|
||||||
Fn<void(not_null<PeerData*>)> _callback;
|
Fn<void(not_null<PeerData*>)> _callback;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using RightsMap = std::vector<std::pair<ChatAdminRight, tr::phrase<>>>;
|
||||||
|
|
||||||
|
[[nodiscard]] RightsMap GroupRights() {
|
||||||
|
using Flag = ChatAdminRight;
|
||||||
|
return {
|
||||||
|
{ Flag::ChangeInfo, tr::lng_request_group_change_info },
|
||||||
|
{
|
||||||
|
Flag::DeleteMessages,
|
||||||
|
tr::lng_request_group_delete_messages },
|
||||||
|
{ Flag::BanUsers, tr::lng_request_group_ban_users },
|
||||||
|
{ Flag::InviteByLinkOrAdd, tr::lng_request_group_invite },
|
||||||
|
{ Flag::PinMessages, tr::lng_request_group_pin_messages },
|
||||||
|
{ Flag::ManageTopics, tr::lng_request_group_manage_topics },
|
||||||
|
{
|
||||||
|
Flag::ManageCall,
|
||||||
|
tr::lng_request_group_manage_video_chats },
|
||||||
|
{ Flag::Anonymous, tr::lng_request_group_anonymous },
|
||||||
|
{ Flag::AddAdmins, tr::lng_request_group_add_admins },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] RightsMap BroadcastRights() {
|
||||||
|
using Flag = ChatAdminRight;
|
||||||
|
return {
|
||||||
|
{ Flag::ChangeInfo, tr::lng_request_channel_change_info },
|
||||||
|
{
|
||||||
|
Flag::PostMessages,
|
||||||
|
tr::lng_request_channel_post_messages },
|
||||||
|
{
|
||||||
|
Flag::EditMessages,
|
||||||
|
tr::lng_request_channel_edit_messages },
|
||||||
|
{
|
||||||
|
Flag::DeleteMessages,
|
||||||
|
tr::lng_request_channel_delete_messages },
|
||||||
|
{
|
||||||
|
Flag::InviteByLinkOrAdd,
|
||||||
|
tr::lng_request_channel_add_subscribers },
|
||||||
|
{
|
||||||
|
Flag::ManageCall,
|
||||||
|
tr::lng_request_channel_manage_livestreams },
|
||||||
|
{ Flag::AddAdmins, tr::lng_request_channel_add_admins },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QString RightsText(
|
||||||
|
ChatAdminRights rights,
|
||||||
|
const RightsMap &phrases) {
|
||||||
|
auto list = QStringList();
|
||||||
|
for (const auto &[flag, phrase] : phrases) {
|
||||||
|
if (rights & flag) {
|
||||||
|
list.push_back(phrase(tr::now));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto count = list.size();
|
||||||
|
if (!count) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
const auto last = list.back();
|
||||||
|
return (count > 1)
|
||||||
|
? tr::lng_request_peer_rights_and(
|
||||||
|
tr::now,
|
||||||
|
lt_rights,
|
||||||
|
list.mid(0, count - 1).join(", "),
|
||||||
|
lt_last,
|
||||||
|
last)
|
||||||
|
: last;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QString GroupRightsText(ChatAdminRights rights) {
|
||||||
|
return RightsText(rights, GroupRights());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QString BroadcastRightsText(ChatAdminRights rights) {
|
||||||
|
return RightsText(rights, BroadcastRights());
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] QStringList RestrictionsList(RequestPeerQuery query) {
|
[[nodiscard]] QStringList RestrictionsList(RequestPeerQuery query) {
|
||||||
using Flag = ChatAdminRight;
|
using Flag = ChatAdminRight;
|
||||||
using Type = RequestPeerQuery::Type;
|
using Type = RequestPeerQuery::Type;
|
||||||
|
@ -74,30 +154,11 @@ private:
|
||||||
result.push_back(no(tr::now));
|
result.push_back(no(tr::now));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto addRights = [&](
|
const auto addRights = [&](const QString &rights) {
|
||||||
ChatAdminRights rights,
|
if (!rights.isEmpty()) {
|
||||||
std::vector<std::pair<Flag, tr::phrase<>>> phrases) {
|
result.push_back(
|
||||||
auto list = QStringList();
|
tr::lng_request_peer_rights(tr::now, lt_rights, rights));
|
||||||
for (const auto &[flag, phrase] : phrases) {
|
|
||||||
if (rights & flag) {
|
|
||||||
list.push_back(phrase(tr::now));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const auto count = list.size();
|
|
||||||
if (!count) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto last = list.back();
|
|
||||||
const auto full = (count > 1)
|
|
||||||
? tr::lng_request_peer_rights_and(
|
|
||||||
tr::now,
|
|
||||||
lt_rights,
|
|
||||||
list.mid(0, count - 1).join(", "),
|
|
||||||
lt_last,
|
|
||||||
last)
|
|
||||||
: last;
|
|
||||||
result.push_back(
|
|
||||||
tr::lng_request_peer_rights(tr::now, lt_rights, full));
|
|
||||||
};
|
};
|
||||||
switch (query.type) {
|
switch (query.type) {
|
||||||
case Type::User:
|
case Type::User:
|
||||||
|
@ -120,21 +181,7 @@ private:
|
||||||
if (query.amCreator) {
|
if (query.amCreator) {
|
||||||
result.push_back(tr::lng_request_group_am_owner(tr::now));
|
result.push_back(tr::lng_request_group_am_owner(tr::now));
|
||||||
} else {
|
} else {
|
||||||
addRights(query.myRights, {
|
addRights(GroupRightsText(query.myRights));
|
||||||
{ Flag::ChangeInfo, tr::lng_request_group_change_info },
|
|
||||||
{
|
|
||||||
Flag::DeleteMessages,
|
|
||||||
tr::lng_request_group_delete_messages },
|
|
||||||
{ Flag::BanUsers, tr::lng_request_group_ban_users },
|
|
||||||
{ Flag::InviteByLinkOrAdd, tr::lng_request_group_invite },
|
|
||||||
{ Flag::PinMessages, tr::lng_request_group_pin_messages },
|
|
||||||
{ Flag::ManageTopics, tr::lng_request_group_manage_topics },
|
|
||||||
{
|
|
||||||
Flag::ManageCall,
|
|
||||||
tr::lng_request_group_manage_video_chats },
|
|
||||||
{ Flag::Anonymous, tr::lng_request_group_anonymous },
|
|
||||||
{ Flag::AddAdmins, tr::lng_request_group_add_admins },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::Broadcast:
|
case Type::Broadcast:
|
||||||
|
@ -145,25 +192,7 @@ private:
|
||||||
if (query.amCreator) {
|
if (query.amCreator) {
|
||||||
result.push_back(tr::lng_request_channel_am_owner(tr::now));
|
result.push_back(tr::lng_request_channel_am_owner(tr::now));
|
||||||
} else {
|
} else {
|
||||||
addRights(query.myRights, {
|
addRights(BroadcastRightsText(query.myRights));
|
||||||
{ Flag::ChangeInfo, tr::lng_request_channel_change_info },
|
|
||||||
{
|
|
||||||
Flag::PostMessages,
|
|
||||||
tr::lng_request_channel_post_messages },
|
|
||||||
{
|
|
||||||
Flag::EditMessages,
|
|
||||||
tr::lng_request_channel_edit_messages },
|
|
||||||
{
|
|
||||||
Flag::DeleteMessages,
|
|
||||||
tr::lng_request_channel_delete_messages },
|
|
||||||
{
|
|
||||||
Flag::InviteByLinkOrAdd,
|
|
||||||
tr::lng_request_channel_add_subscribers },
|
|
||||||
{
|
|
||||||
Flag::ManageCall,
|
|
||||||
tr::lng_request_channel_manage_livestreams },
|
|
||||||
{ Flag::AddAdmins, tr::lng_request_channel_add_admins },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -175,10 +204,48 @@ object_ptr<Ui::BoxContent> MakeConfirmBox(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
RequestPeerQuery query,
|
RequestPeerQuery query,
|
||||||
Fn<void()> confirmed) {
|
Fn<void()> confirmed) {
|
||||||
auto text = TextWithEntities{ "Sure?.." };
|
const auto user = peer->asUser();
|
||||||
|
const auto name = user ? user->firstName : peer->name();
|
||||||
|
const auto botName = bot->name();
|
||||||
|
auto text = tr::lng_request_peer_confirm(
|
||||||
|
tr::now,
|
||||||
|
lt_chat,
|
||||||
|
Ui::Text::Bold(name),
|
||||||
|
lt_bot,
|
||||||
|
Ui::Text::Bold(botName),
|
||||||
|
Ui::Text::WithEntities);
|
||||||
|
if (!user) {
|
||||||
|
const auto rights = peer->isBroadcast()
|
||||||
|
? BroadcastRightsText(query.botRights)
|
||||||
|
: GroupRightsText(query.botRights);
|
||||||
|
if (!rights.isEmpty()) {
|
||||||
|
text.append('\n').append('\n').append(
|
||||||
|
tr::lng_request_peer_confirm_rights(
|
||||||
|
tr::now,
|
||||||
|
lt_bot,
|
||||||
|
Ui::Text::Bold(botName),
|
||||||
|
lt_chat,
|
||||||
|
Ui::Text::Bold(name),
|
||||||
|
lt_rights,
|
||||||
|
TextWithEntities{ rights },
|
||||||
|
Ui::Text::WithEntities));
|
||||||
|
} else if (!peer->isBroadcast() && query.isBotParticipant) {
|
||||||
|
const auto common = bot->session().api().botCommonGroups(bot);
|
||||||
|
if (!common || !ranges::contains(*common, peer)) {
|
||||||
|
text.append('\n').append('\n').append(
|
||||||
|
tr::lng_request_peer_confirm_add(
|
||||||
|
tr::now,
|
||||||
|
lt_bot,
|
||||||
|
Ui::Text::Bold(botName),
|
||||||
|
lt_chat,
|
||||||
|
Ui::Text::Bold(name),
|
||||||
|
Ui::Text::WithEntities));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return Ui::MakeConfirmBox({
|
return Ui::MakeConfirmBox({
|
||||||
.text = std::move(text),
|
.text = std::move(text),
|
||||||
.confirmed = std::move(confirmed),
|
.confirmed = [=](Fn<void()> close) { confirmed(); close(); },
|
||||||
.confirmText = tr::lng_request_peer_confirm_send(tr::now),
|
.confirmText = tr::lng_request_peer_confirm_send(tr::now),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -206,7 +273,8 @@ object_ptr<Ui::BoxContent> CreatePeerByQueryBox(
|
||||||
|
|
||||||
[[nodiscard]] bool FilterPeerByQuery(
|
[[nodiscard]] bool FilterPeerByQuery(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
RequestPeerQuery query) {
|
RequestPeerQuery query,
|
||||||
|
const base::flat_set<not_null<PeerData*>> &commonGroups) {
|
||||||
using Type = RequestPeerQuery::Type;
|
using Type = RequestPeerQuery::Type;
|
||||||
using Restriction = RequestPeerQuery::Restriction;
|
using Restriction = RequestPeerQuery::Restriction;
|
||||||
const auto checkRestriction = [](Restriction restriction, bool value) {
|
const auto checkRestriction = [](Restriction restriction, bool value) {
|
||||||
|
@ -239,7 +307,13 @@ object_ptr<Ui::BoxContent> CreatePeerByQueryBox(
|
||||||
&& checkRights(
|
&& checkRights(
|
||||||
query.myRights,
|
query.myRights,
|
||||||
chat ? chat->amCreator() : megagroup->amCreator(),
|
chat ? chat->amCreator() : megagroup->amCreator(),
|
||||||
chat ? chat->adminRights() : megagroup->adminRights());
|
chat ? chat->adminRights() : megagroup->adminRights())
|
||||||
|
&& (!query.isBotParticipant
|
||||||
|
|| query.myRights
|
||||||
|
|| commonGroups.contains(peer)
|
||||||
|
|| (chat
|
||||||
|
? chat->canAddMembers()
|
||||||
|
: megagroup->canAddMembers()));
|
||||||
}
|
}
|
||||||
case Type::Broadcast: {
|
case Type::Broadcast: {
|
||||||
const auto broadcast = peer->asBroadcast();
|
const auto broadcast = peer->asBroadcast();
|
||||||
|
@ -265,6 +339,9 @@ ChoosePeerBoxController::ChoosePeerBoxController(
|
||||||
, _bot(bot)
|
, _bot(bot)
|
||||||
, _query(query)
|
, _query(query)
|
||||||
, _callback(std::move(callback)) {
|
, _callback(std::move(callback)) {
|
||||||
|
if (const auto list = _bot->session().api().botCommonGroups(_bot)) {
|
||||||
|
_commonGroups = { begin(*list), end(*list) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Main::Session &ChoosePeerBoxController::session() const {
|
Main::Session &ChoosePeerBoxController::session() const {
|
||||||
|
@ -358,7 +435,7 @@ void ChoosePeerBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
|
||||||
auto ChoosePeerBoxController::createRow(not_null<History*> history)
|
auto ChoosePeerBoxController::createRow(not_null<History*> history)
|
||||||
-> std::unique_ptr<Row> {
|
-> std::unique_ptr<Row> {
|
||||||
return FilterPeerByQuery(history->peer, _query)
|
return FilterPeerByQuery(history->peer, _query, _commonGroups)
|
||||||
? std::make_unique<Row>(history)
|
? std::make_unique<Row>(history)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
@ -388,11 +465,23 @@ QString ChoosePeerBoxController::emptyBoxText() const {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
QPointer<Ui::BoxContent> ShowChoosePeerBox(
|
void ShowChoosePeerBox(
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
RequestPeerQuery query,
|
RequestPeerQuery query,
|
||||||
Fn<void(not_null<PeerData*>)> &&chosen) {
|
Fn<void(not_null<PeerData*>)> chosen) {
|
||||||
|
const auto needCommonGroups = query.isBotParticipant
|
||||||
|
&& (query.type == RequestPeerQuery::Type::Group)
|
||||||
|
&& !query.myRights;
|
||||||
|
if (needCommonGroups && !bot->session().api().botCommonGroups(bot)) {
|
||||||
|
const auto weak = base::make_weak(navigation);
|
||||||
|
bot->session().api().requestBotCommonGroups(bot, [=] {
|
||||||
|
if (const auto strong = weak.get()) {
|
||||||
|
ShowChoosePeerBox(strong, bot, query, chosen);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
|
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||||
auto initBox = [=](not_null<PeerListBox*> box) {
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
box->addButton(tr::lng_cancel(), [box] {
|
box->addButton(tr::lng_cancel(), [box] {
|
||||||
|
@ -412,5 +501,4 @@ QPointer<Ui::BoxContent> ShowChoosePeerBox(
|
||||||
query,
|
query,
|
||||||
std::move(callback)),
|
std::move(callback)),
|
||||||
std::move(initBox)), Ui::LayerOption::KeepOther);
|
std::move(initBox)), Ui::LayerOption::KeepOther);
|
||||||
return weak->data();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ namespace Window {
|
||||||
class SessionNavigation;
|
class SessionNavigation;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
QPointer<Ui::BoxContent> ShowChoosePeerBox(
|
void ShowChoosePeerBox(
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
RequestPeerQuery query,
|
RequestPeerQuery query,
|
||||||
Fn<void(not_null<PeerData*>)> &&chosen);
|
Fn<void(not_null<PeerData*>)> chosen);
|
||||||
|
|
Loading…
Add table
Reference in a new issue