Allow creating group / channel for the bot.

This commit is contained in:
John Preston 2023-01-13 17:59:15 +04:00
parent 809610817e
commit de5bbf2cb9
5 changed files with 273 additions and 112 deletions

View File

@ -424,7 +424,11 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
peer->session().api().applyUpdates(result); peer->session().api().applyUpdates(result);
}).send(); }).send();
}; };
ShowChoosePeerBox(controller, chosen, query); if (const auto bot = item->getMessageBot()) {
ShowChoosePeerBox(controller, bot, query, chosen);
} else {
LOG(("API Error: Bot not found for RequestPeer button."));
}
} break; } break;
case ButtonType::SwitchInlineSame: case ButtonType::SwitchInlineSame:

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/add_contact_box.h" #include "boxes/add_contact_box.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "base/call_delayed.h"
#include "base/random.h" #include "base/random.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
@ -20,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/core_settings.h" #include "core/core_settings.h"
#include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_suggestions_widget.h"
#include "countries/countries_instance.h" // Countries::ExtractPhoneCode. #include "countries/countries_instance.h" // Countries::ExtractPhoneCode.
#include "history/history_item_reply_markup.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "menu/menu_ttl.h" #include "menu/menu_ttl.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
@ -72,7 +74,8 @@ void ChatCreateDone(
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
QImage image, QImage image,
TimeId ttlPeriod, TimeId ttlPeriod,
const MTPUpdates &updates) { const MTPUpdates &updates,
Fn<void(not_null<PeerData*>)> done) {
navigation->session().api().applyUpdates(updates); navigation->session().api().applyUpdates(updates);
const auto success = base::make_optional(&updates) const auto success = base::make_optional(&updates)
@ -106,7 +109,11 @@ void ChatCreateDone(
if (ttlPeriod) { if (ttlPeriod) {
chat->setMessagesTTL(ttlPeriod); chat->setMessagesTTL(ttlPeriod);
} }
navigation->showPeerHistory(chat); if (done) {
done(chat);
} else {
navigation->showPeerHistory(chat);
}
}; };
if (!success) { if (!success) {
LOG(("API Error: chat not found in updates " LOG(("API Error: chat not found in updates "
@ -114,6 +121,25 @@ void ChatCreateDone(
} }
} }
void MustBePublicDestroy(not_null<ChannelData*> channel) {
const auto session = &channel->session();
session->api().request(MTPchannels_DeleteChannel(
channel->inputChannel
)).done([=](const MTPUpdates &result) {
session->api().applyUpdates(result);
}).send();
}
void MustBePublicFailed(
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel) {
const auto text = channel->isMegagroup()
? "Can't create a public group :("
: "Can't create a public channel :(";
Ui::Toast::Show(Window::Show(navigation).toastParent(), text);
MustBePublicDestroy(channel);
}
} // namespace } // namespace
TextWithEntities PeerFloodErrorText( TextWithEntities PeerFloodErrorText(
@ -456,7 +482,33 @@ GroupInfoBox::GroupInfoBox(
, _api(&_navigation->session().mtp()) , _api(&_navigation->session().mtp())
, _type(type) , _type(type)
, _initialTitle(title) , _initialTitle(title)
, _channelDone(std::move(channelDone)) { , _done([channelDone = std::move(channelDone)](not_null<PeerData*> peer) {
if (const auto channel = peer->asChannel()) {
if (const auto onstack = channelDone) {
onstack(channel);
}
}
}) {
}
GroupInfoBox::GroupInfoBox(
QWidget*,
not_null<Window::SessionNavigation*> navigation,
not_null<UserData*> bot,
RequestPeerQuery query,
Fn<void(not_null<PeerData*>)> done)
: _navigation(navigation)
, _api(&_navigation->session().mtp())
, _type((query.type == RequestPeerQuery::Type::Broadcast)
? Type::Channel
: (query.groupIsForum == RequestPeerQuery::Restriction::Yes)
? Type::Forum
: (query.hasUsername == RequestPeerQuery::Restriction::Yes)
? Type::Megagroup
: Type::Group)
, _mustBePublic(query.hasUsername == RequestPeerQuery::Restriction::Yes)
, _canAddBot(query.isBotParticipant ? bot.get() : nullptr)
, _done(std::move(done)) {
} }
void GroupInfoBox::prepare() { void GroupInfoBox::prepare() {
@ -466,7 +518,8 @@ void GroupInfoBox::prepare() {
this, this,
&_navigation->parentController()->window(), &_navigation->parentController()->window(),
Ui::UserpicButton::Role::ChoosePhoto, Ui::UserpicButton::Role::ChoosePhoto,
st::defaultUserpicButton); st::defaultUserpicButton,
(_type == Type::Forum));
_photo->showCustomOnChosen(); _photo->showCustomOnChosen();
_title.create( _title.create(
this, this,
@ -517,7 +570,7 @@ void GroupInfoBox::prepare() {
connect(_title, &Ui::InputField::submitted, [=] { submitName(); }); connect(_title, &Ui::InputField::submitted, [=] { submitName(); });
addButton( addButton(
(_type != Type::Group ((_type != Type::Group || _canAddBot)
? tr::lng_create_group_create() ? tr::lng_create_group_create()
: tr::lng_create_group_next()), : tr::lng_create_group_next()),
[=] { submit(); }); [=] { submit(); });
@ -613,7 +666,7 @@ void GroupInfoBox::submitName() {
} }
void GroupInfoBox::createGroup( void GroupInfoBox::createGroup(
not_null<PeerListBox*> selectUsersBox, QPointer<Ui::BoxContent> selectUsersBox,
const QString &title, const QString &title,
const std::vector<not_null<PeerData*>> &users) { const std::vector<not_null<PeerData*>> &users) {
if (_creationRequestId) { if (_creationRequestId) {
@ -643,16 +696,19 @@ void GroupInfoBox::createGroup(
auto image = _photo->takeResultImage(); auto image = _photo->takeResultImage();
const auto period = _ttlPeriod; const auto period = _ttlPeriod;
const auto navigation = _navigation; const auto navigation = _navigation;
const auto done = _done;
getDelegate()->hideLayer(); // Destroys 'this'. getDelegate()->hideLayer(); // Destroys 'this'.
ChatCreateDone(navigation, std::move(image), period, result); ChatCreateDone(navigation, std::move(image), period, result, done);
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
const auto &type = error.type(); const auto &type = error.type();
_creationRequestId = 0; _creationRequestId = 0;
const auto controller = _navigation->parentController(); const auto controller = _navigation->parentController();
if (type == u"NO_CHAT_TITLE"_q) { if (type == u"NO_CHAT_TITLE"_q) {
const auto weak = Ui::MakeWeak(this); const auto weak = Ui::MakeWeak(this);
selectUsersBox->closeBox(); if (const auto strong = selectUsersBox.data()) {
strong->closeBox();
}
if (weak) { if (weak) {
_title->showError(); _title->showError();
} }
@ -693,14 +749,19 @@ void GroupInfoBox::submit() {
} }
if (_type != Type::Group) { if (_type != Type::Group) {
createChannel(title, description); createChannel(title, description);
} else if (_canAddBot) {
createGroup(nullptr, title, { not_null<PeerData*>(_canAddBot) });
} else { } else {
auto initBox = [title, weak = Ui::MakeWeak(this)]( auto initBox = [title, weak = Ui::MakeWeak(this)](
not_null<PeerListBox*> box) { not_null<PeerListBox*> box) {
auto create = [box, title, weak] { auto create = [box, title, weak] {
if (weak) { if (const auto strong = weak.data()) {
auto rows = box->collectSelectedRows(); auto rows = box->collectSelectedRows();
if (!rows.empty()) { if (!rows.empty()) {
weak->createGroup(box, title, rows); strong->createGroup(
box.get(),
title,
std::move(rows));
} }
} }
}; };
@ -721,10 +782,13 @@ void GroupInfoBox::createChannel(
const QString &description) { const QString &description) {
Expects(!_creationRequestId); Expects(!_creationRequestId);
const auto flags = ((_type == Type::Megagroup) using Flag = MTPchannels_CreateChannel::Flag;
? MTPchannels_CreateChannel::Flag::f_megagroup const auto flags = Flag()
: MTPchannels_CreateChannel::Flag::f_broadcast) | ((_type == Type::Megagroup || _type == Type::Forum)
| (_ttlPeriod ? Flag::f_megagroup
: Flag::f_broadcast)
| ((_type == Type::Forum) ? Flag::f_forum : Flag())
| ((_type == Type::Megagroup && _ttlPeriod)
? MTPchannels_CreateChannel::Flag::f_ttl_period ? MTPchannels_CreateChannel::Flag::f_ttl_period
: MTPchannels_CreateChannel::Flags(0)); : MTPchannels_CreateChannel::Flags(0));
_creationRequestId = _api.request(MTPchannels_CreateChannel( _creationRequestId = _api.request(MTPchannels_CreateChannel(
@ -818,14 +882,18 @@ void GroupInfoBox::checkInviteLink() {
} }
void GroupInfoBox::channelReady() { void GroupInfoBox::channelReady() {
if (_channelDone) { if (_done && !_mustBePublic) {
const auto callback = _channelDone; const auto callback = _done;
const auto argument = _createdChannel; const auto argument = _createdChannel;
closeBox(); closeBox();
callback(argument); callback(argument);
} else { } else {
_navigation->parentController()->show( _navigation->parentController()->show(
Box<SetupChannelBox>(_navigation, _createdChannel), Box<SetupChannelBox>(
_navigation,
_createdChannel,
_mustBePublic,
_done),
Ui::LayerOption::CloseOther); Ui::LayerOption::CloseOther);
} }
} }
@ -853,11 +921,13 @@ SetupChannelBox::SetupChannelBox(
QWidget*, QWidget*,
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
bool existing) bool mustBePublic,
Fn<void(not_null<PeerData*>)> done)
: _navigation(navigation) : _navigation(navigation)
, _channel(channel) , _channel(channel)
, _api(&_channel->session().mtp()) , _api(&_channel->session().mtp())
, _existing(existing) , _mustBePublic(mustBePublic)
, _done(std::move(done))
, _privacyGroup( , _privacyGroup(
std::make_shared<Ui::RadioenumGroup<Privacy>>(Privacy::Public)) std::make_shared<Ui::RadioenumGroup<Privacy>>(Privacy::Public))
, _public( , _public(
@ -903,6 +973,10 @@ SetupChannelBox::SetupChannelBox(
channel->username(), channel->username(),
channel->session().createInternalLink(QString())) channel->session().createInternalLink(QString()))
, _checkTimer([=] { check(); }) { , _checkTimer([=] { check(); }) {
if (_mustBePublic) {
_public.destroy();
_private.destroy();
}
} }
void SetupChannelBox::prepare() { void SetupChannelBox::prepare() {
@ -923,9 +997,16 @@ void SetupChannelBox::prepare() {
}).send(); }).send();
addButton(tr::lng_settings_save(), [=] { save(); }); addButton(tr::lng_settings_save(), [=] { save(); });
const auto cancel = [=] {
if (_mustBePublic) {
MustBePublicDestroy(_channel);
}
closeBox();
};
addButton( addButton(
_existing ? tr::lng_cancel() : tr::lng_create_group_skip(), _mustBePublic ? tr::lng_cancel() : tr::lng_create_group_skip(),
[=] { closeBox(); }); cancel);
connect(_link, &Ui::MaskedInputField::changed, [=] { handleChange(); }); connect(_link, &Ui::MaskedInputField::changed, [=] { handleChange(); });
_link->setVisible(_privacyGroup->value() == Privacy::Public); _link->setVisible(_privacyGroup->value() == Privacy::Public);
@ -942,7 +1023,7 @@ void SetupChannelBox::prepare() {
}, lifetime()); }, lifetime());
boxClosing() | rpl::start_with_next([=] { boxClosing() | rpl::start_with_next([=] {
if (!_existing) { if (!_mustBePublic) {
AddParticipantsBoxController::Start(_navigation, _channel); AddParticipantsBoxController::Start(_navigation, _channel);
} }
}, lifetime()); }, lifetime());
@ -961,12 +1042,16 @@ void SetupChannelBox::setInnerFocus() {
void SetupChannelBox::updateMaxHeight() { void SetupChannelBox::updateMaxHeight() {
auto newHeight = st::boxPadding.top() auto newHeight = st::boxPadding.top()
+ st::newGroupPadding.top() + st::newGroupPadding.top()
+ _public->heightNoMargins() + (_public
+ _aboutPublicHeight ? (_public->heightNoMargins()
+ st::newGroupSkip + _aboutPublicHeight
+ _private->heightNoMargins() + st::newGroupSkip)
+ _aboutPrivate.countHeight(_aboutPublicWidth) : 0)
+ st::newGroupSkip + (_private
? (_private->heightNoMargins()
+ _aboutPrivate.countHeight(_aboutPublicWidth)
+ st::newGroupSkip)
: 0)
+ st::newGroupPadding.bottom(); + st::newGroupPadding.bottom();
if (!_channel->isMegagroup() if (!_channel->isMegagroup()
|| _privacyGroup->value() == Privacy::Public) { || _privacyGroup->value() == Privacy::Public) {
@ -998,36 +1083,38 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
p.fillRect(e->rect(), st::boxBg); p.fillRect(e->rect(), st::boxBg);
p.setPen(st::newGroupAboutFg); p.setPen(st::newGroupAboutFg);
const auto aboutPublic = QRect( if (_public) {
st::boxPadding.left() const auto aboutPublic = QRect(
+ st::newGroupPadding.left() st::boxPadding.left()
+ st::defaultRadio.diameter + st::newGroupPadding.left()
+ st::defaultBoxCheckbox.textPosition.x(), + st::defaultRadio.diameter
_public->bottomNoMargins(), + st::defaultBoxCheckbox.textPosition.x(),
_aboutPublicWidth, _public->bottomNoMargins(),
_aboutPublicHeight); _aboutPublicWidth,
_aboutPublic.drawLeft( _aboutPublicHeight);
p, _aboutPublic.drawLeft(
aboutPublic.x(), p,
aboutPublic.y(), aboutPublic.x(),
aboutPublic.width(), aboutPublic.y(),
width()); aboutPublic.width(),
width());
const auto aboutPrivate = QRect( }
st::boxPadding.left() if (_private) {
+ st::newGroupPadding.left() const auto aboutPrivate = QRect(
+ st::defaultRadio.diameter st::boxPadding.left()
+ st::defaultBoxCheckbox.textPosition.x(), + st::newGroupPadding.left()
_private->bottomNoMargins(), + st::defaultRadio.diameter
_aboutPublicWidth, + st::defaultBoxCheckbox.textPosition.x(),
_aboutPublicHeight); _private->bottomNoMargins(),
_aboutPrivate.drawLeft( _aboutPublicWidth,
p, _aboutPublicHeight);
aboutPrivate.x(), _aboutPrivate.drawLeft(
aboutPrivate.y(), p,
aboutPrivate.width(), aboutPrivate.x(),
width()); aboutPrivate.y(),
aboutPrivate.width(),
width());
}
if (!_channel->isMegagroup() || !_link->isHidden()) { if (!_channel->isMegagroup() || !_link->isHidden()) {
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
p.setFont(st::newGroupLinkFont); p.setFont(st::newGroupLinkFont);
@ -1077,13 +1164,14 @@ void SetupChannelBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e); BoxContent::resizeEvent(e);
const auto left = st::boxPadding.left() + st::newGroupPadding.left(); const auto left = st::boxPadding.left() + st::newGroupPadding.left();
_public->moveToLeft( if (_public && _private) {
left, _public->moveToLeft(
st::boxPadding.top() + st::newGroupPadding.top()); left,
_private->moveToLeft( st::boxPadding.top() + st::newGroupPadding.top());
left, _private->moveToLeft(
_public->bottomNoMargins() + _aboutPublicHeight + st::newGroupSkip); left,
_public->bottomNoMargins() + _aboutPublicHeight + st::newGroupSkip);
}
_link->resize( _link->resize(
width() width()
- st::boxPadding.left() - st::boxPadding.left()
@ -1092,11 +1180,20 @@ void SetupChannelBox::resizeEvent(QResizeEvent *e) {
_link->height()); _link->height());
_link->moveToLeft( _link->moveToLeft(
st::boxPadding.left() + st::newGroupLinkPadding.left(), st::boxPadding.left() + st::newGroupLinkPadding.left(),
_private->bottomNoMargins() (st::boxPadding.top()
+ _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupPadding.top()
+ st::newGroupSkip + (_public
? (_public->heightNoMargins()
+ _aboutPublicHeight
+ st::newGroupSkip)
: 0)
+ (_private
? (_private->heightNoMargins()
+ _aboutPrivate.countHeight(_aboutPublicWidth)
+ st::newGroupSkip)
: 0)
+ st::newGroupPadding.bottom() + st::newGroupPadding.bottom()
+ st::newGroupLinkPadding.top()); + st::newGroupLinkPadding.top()));
_invitationLink = QRect( _invitationLink = QRect(
_link->x(), _link->x(),
_link->y() + (_link->height() / 2) - st::boxTextFont->height, _link->y() + (_link->height() / 2) - st::boxTextFont->height,
@ -1144,10 +1241,15 @@ void SetupChannelBox::save() {
_channel->inputChannel, _channel->inputChannel,
MTP_string(_sentUsername) MTP_string(_sentUsername)
)).done([=] { )).done([=] {
const auto done = _done;
const auto channel = _channel;
_channel->setName( _channel->setName(
TextUtilities::SingleLine(_channel->name()), TextUtilities::SingleLine(_channel->name()),
_sentUsername); _sentUsername);
closeBox(); closeBox(); // Deletes `this`.
if (done) {
done(channel);
}
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
_saveRequestId = 0; _saveRequestId = 0;
updateFail(parseError(error.type())); updateFail(parseError(error.type()));
@ -1156,11 +1258,7 @@ void SetupChannelBox::save() {
if (_saveRequestId) { if (_saveRequestId) {
return; return;
} else if (_privacyGroup->value() == Privacy::Private) { } else if (_privacyGroup->value() == Privacy::Private) {
if (_existing) { closeBox();
saveUsername(QString());
} else {
closeBox();
}
} else { } else {
const auto link = _link->text().trimmed(); const auto link = _link->text().trimmed();
if (link.isEmpty()) { if (link.isEmpty()) {
@ -1315,9 +1413,12 @@ void SetupChannelBox::updateFail(UsernameResult result) {
void SetupChannelBox::checkFail(UsernameResult result) { void SetupChannelBox::checkFail(UsernameResult result) {
if (result == UsernameResult::NA) { if (result == UsernameResult::NA) {
if (_mustBePublic) {
mustBePublicFailed();
}
getDelegate()->hideLayer(); getDelegate()->hideLayer();
} else if (result == UsernameResult::ChatsTooMuch) { } else if (result == UsernameResult::ChatsTooMuch) {
if (_existing) { if (_mustBePublic) {
showRevokePublicLinkBoxForEdit(); showRevokePublicLinkBoxForEdit();
} else { } else {
_tooMuchUsernames = true; _tooMuchUsernames = true;
@ -1338,24 +1439,44 @@ void SetupChannelBox::checkFail(UsernameResult result) {
void SetupChannelBox::showRevokePublicLinkBoxForEdit() { void SetupChannelBox::showRevokePublicLinkBoxForEdit() {
const auto channel = _channel; const auto channel = _channel;
const auto existing = _existing; const auto mustBePublic = _mustBePublic;
const auto done = _done;
const auto navigation = _navigation; const auto navigation = _navigation;
const auto revoked = std::make_shared<bool>(false);
const auto callback = [=] { const auto callback = [=] {
Ui::show( *revoked = true;
Box<SetupChannelBox>(navigation, channel, existing), navigation->parentController()->show(
Box<SetupChannelBox>(navigation, channel, mustBePublic, done),
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
}; };
closeBox(); const auto revoker = navigation->parentController()->show(
Ui::show(
Box(PublicLinksLimitBox, navigation, callback), Box(PublicLinksLimitBox, navigation, callback),
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
const auto session = &navigation->session();
revoker->boxClosing(
) | rpl::start_with_next(crl::guard(session, [=] {
base::call_delayed(200, session, [=] {
if (*revoked) {
return;
}
MustBePublicDestroy(channel);
});
}), revoker->lifetime());
closeBox();
}
void SetupChannelBox::mustBePublicFailed() {
MustBePublicFailed(_navigation, _channel);
} }
void SetupChannelBox::firstCheckFail(UsernameResult result) { void SetupChannelBox::firstCheckFail(UsernameResult result) {
if (result == UsernameResult::NA) { if (result == UsernameResult::NA) {
if (_mustBePublic) {
mustBePublicFailed();
}
getDelegate()->hideLayer(); getDelegate()->hideLayer();
} else if (result == UsernameResult::ChatsTooMuch) { } else if (result == UsernameResult::ChatsTooMuch) {
if (_existing) { if (_mustBePublic) {
showRevokePublicLinkBoxForEdit(); showRevokePublicLinkBoxForEdit();
} else { } else {
_tooMuchUsernames = true; _tooMuchUsernames = true;

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/sender.h" #include "mtproto/sender.h"
class PeerListBox; class PeerListBox;
struct RequestPeerQuery;
namespace Window { namespace Window {
class SessionNavigation; class SessionNavigation;
@ -103,6 +104,12 @@ public:
Type type, Type type,
const QString &title = QString(), const QString &title = QString(),
Fn<void(not_null<ChannelData*>)> channelDone = nullptr); Fn<void(not_null<ChannelData*>)> channelDone = nullptr);
GroupInfoBox(
QWidget*,
not_null<Window::SessionNavigation*> navigation,
not_null<UserData*> bot,
RequestPeerQuery query,
Fn<void(not_null<PeerData*>)> done);
protected: protected:
void prepare() override; void prepare() override;
@ -113,7 +120,7 @@ protected:
private: private:
void createChannel(const QString &title, const QString &description); void createChannel(const QString &title, const QString &description);
void createGroup( void createGroup(
not_null<PeerListBox*> selectUsersBox, QPointer<Ui::BoxContent> selectUsersBox,
const QString &title, const QString &title,
const std::vector<not_null<PeerData*>> &users); const std::vector<not_null<PeerData*>> &users);
void submitName(); void submitName();
@ -129,7 +136,9 @@ private:
Type _type = Type::Group; Type _type = Type::Group;
QString _initialTitle; QString _initialTitle;
Fn<void(not_null<ChannelData*>)> _channelDone; bool _mustBePublic = false;
UserData *_canAddBot = nullptr;
Fn<void(not_null<PeerData*>)> _done;
object_ptr<Ui::UserpicButton> _photo = { nullptr }; object_ptr<Ui::UserpicButton> _photo = { nullptr };
object_ptr<Ui::InputField> _title = { nullptr }; object_ptr<Ui::InputField> _title = { nullptr };
@ -149,7 +158,8 @@ public:
QWidget*, QWidget*,
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
bool existing = false); bool mustBePublic,
Fn<void(not_null<PeerData*>)> done);
void setInnerFocus() override; void setInnerFocus() override;
@ -186,6 +196,7 @@ private:
void updateFail(UsernameResult result); void updateFail(UsernameResult result);
void mustBePublicFailed();
void checkFail(UsernameResult result); void checkFail(UsernameResult result);
void firstCheckFail(UsernameResult result); void firstCheckFail(UsernameResult result);
@ -197,8 +208,9 @@ private:
const not_null<ChannelData*> _channel; const not_null<ChannelData*> _channel;
MTP::Sender _api; MTP::Sender _api;
bool _existing = false;
bool _creatingInviteLink = false; bool _creatingInviteLink = false;
bool _mustBePublic = false;
Fn<void(not_null<PeerData*>)> _done;
std::shared_ptr<Ui::RadioenumGroup<Privacy>> _privacyGroup; std::shared_ptr<Ui::RadioenumGroup<Privacy>> _privacyGroup;
object_ptr<Ui::Radioenum<Privacy>> _public; object_ptr<Ui::Radioenum<Privacy>> _public;

View File

@ -7,7 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "boxes/peers/choose_peer_box.h" #include "boxes/peers/choose_peer_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 "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_peer.h" #include "data/data_peer.h"
@ -30,9 +32,10 @@ class ChoosePeerBoxController final
, public base::has_weak_ptr { , public base::has_weak_ptr {
public: public:
ChoosePeerBoxController( ChoosePeerBoxController(
not_null<Main::Session*> session, not_null<Window::SessionNavigation*> navigation,
Fn<void(not_null<PeerData*>)> callback, not_null<UserData*> bot,
RequestPeerQuery query); RequestPeerQuery query,
Fn<void(not_null<PeerData*>)> callback);
Main::Session &session() const override; Main::Session &session() const override;
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
@ -48,9 +51,10 @@ private:
void prepareRestrictions(); void prepareRestrictions();
const not_null<Main::Session*> _session; const not_null<Window::SessionNavigation*> _navigation;
Fn<void(not_null<PeerData*>)> _callback; not_null<UserData*> _bot;
RequestPeerQuery _query; RequestPeerQuery _query;
Fn<void(not_null<PeerData*>)> _callback;
}; };
@ -166,9 +170,24 @@ private:
} }
object_ptr<Ui::BoxContent> CreatePeerByQueryBox( object_ptr<Ui::BoxContent> CreatePeerByQueryBox(
not_null<Main::Session*> session, not_null<Window::SessionNavigation*> navigation,
RequestPeerQuery query) { not_null<UserData*> bot,
return object_ptr<Ui::BoxContent>(nullptr); RequestPeerQuery query,
Fn<void(not_null<PeerData*>)> done) {
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
auto callback = [=](not_null<PeerData*> peer) {
done(peer);
if (const auto strong = weak->data()) {
strong->closeBox();
}
};
auto result = Box<GroupInfoBox>(
navigation,
bot,
query,
std::move(callback));
*weak = result.data();
return result;
} }
[[nodiscard]] bool FilterPeerByQuery( [[nodiscard]] bool FilterPeerByQuery(
@ -223,17 +242,19 @@ object_ptr<Ui::BoxContent> CreatePeerByQueryBox(
} }
ChoosePeerBoxController::ChoosePeerBoxController( ChoosePeerBoxController::ChoosePeerBoxController(
not_null<Main::Session*> session, not_null<Window::SessionNavigation*> navigation,
Fn<void(not_null<PeerData*>)> callback, not_null<UserData*> bot,
RequestPeerQuery query) RequestPeerQuery query,
: ChatsListBoxController(session) Fn<void(not_null<PeerData*>)> callback)
, _session(session) : ChatsListBoxController(&navigation->session())
, _callback(std::move(callback)) , _navigation(navigation)
, _query(query) { , _bot(bot)
, _query(query)
, _callback(std::move(callback)) {
} }
Main::Session &ChoosePeerBoxController::session() const { Main::Session &ChoosePeerBoxController::session() const {
return *_session; return _navigation->session();
} }
void ChoosePeerBoxController::prepareRestrictions() { void ChoosePeerBoxController::prepareRestrictions() {
@ -273,8 +294,8 @@ void ChoosePeerBoxController::prepareRestrictions() {
}, icon->lifetime()); }, icon->lifetime());
button->setClickedCallback([=] { button->setClickedCallback([=] {
delegate()->peerListShowBox( _navigation->parentController()->show(
CreatePeerByQueryBox(&session(), _query)); CreatePeerByQueryBox(_navigation, _bot, _query, _callback));
}); });
button->events( button->events(
@ -351,8 +372,9 @@ QString ChoosePeerBoxController::emptyBoxText() const {
QPointer<Ui::BoxContent> ShowChoosePeerBox( QPointer<Ui::BoxContent> ShowChoosePeerBox(
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
Fn<void(not_null<PeerData*>)> &&chosen, not_null<UserData*> bot,
RequestPeerQuery query) { RequestPeerQuery query,
Fn<void(not_null<PeerData*>)> &&chosen) {
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] {
@ -367,9 +389,10 @@ QPointer<Ui::BoxContent> ShowChoosePeerBox(
}; };
*weak = navigation->parentController()->show(Box<PeerListBox>( *weak = navigation->parentController()->show(Box<PeerListBox>(
std::make_unique<ChoosePeerBoxController>( std::make_unique<ChoosePeerBoxController>(
&navigation->session(), navigation,
std::move(callback), bot,
query), query,
std::move(callback)),
std::move(initBox)), Ui::LayerOption::KeepOther); std::move(initBox)), Ui::LayerOption::KeepOther);
return weak->data(); return weak->data();
} }

View File

@ -19,5 +19,6 @@ class SessionNavigation;
QPointer<Ui::BoxContent> ShowChoosePeerBox( QPointer<Ui::BoxContent> ShowChoosePeerBox(
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
Fn<void(not_null<PeerData*>)> &&chosen, not_null<UserData*> bot,
RequestPeerQuery query); RequestPeerQuery query,
Fn<void(not_null<PeerData*>)> &&chosen);