Added initial implementation of bot management box.

This commit is contained in:
23rd 2023-04-09 21:40:08 +03:00 committed by John Preston
parent cfc8820bad
commit 30a7893afe
1 changed files with 191 additions and 7 deletions

View File

@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_requests_box.h"
#include "boxes/peers/edit_peer_reactions.h"
#include "boxes/stickers_box.h"
#include "boxes/username_box.h"
#include "ui/boxes/single_choice_box.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "core/application.h"
@ -67,6 +68,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace {
constexpr auto kBotManagerUsername = "BotFather"_cs;
[[nodiscard]] auto ToPositiveNumberString() {
return rpl::map([](int count) {
return count ? QString::number(count) : QString();
@ -306,6 +309,11 @@ private:
void fillManageSection();
void fillPendingRequestsButton();
void fillBotUsernamesButton();
void fillBotEditIntroButton();
void fillBotEditCommandsButton();
void fillBotEditSettingsButton();
void submitTitle();
void submitDescription();
void deleteWithConfirmation();
@ -341,6 +349,8 @@ private:
void continueSave();
void cancelSave();
void toggleBotManager(const QString &command);
void togglePreHistoryHidden(
not_null<ChannelData*> channel,
bool hidden,
@ -363,6 +373,7 @@ private:
not_null<PeerData*> _peer;
MTP::Sender _api;
const bool _isGroup = false;
const bool _isBot = false;
base::unique_qptr<Ui::VerticalLayout> _wrap;
Controls _controls;
@ -386,8 +397,11 @@ Controller::Controller(
, _box(box)
, _peer(peer)
, _api(&_peer->session().mtp())
, _isGroup(_peer->isChat() || _peer->isMegagroup()) {
_box->setTitle(_isGroup
, _isGroup(_peer->isChat() || _peer->isMegagroup())
, _isBot(_peer->isUser() && _peer->asUser()->botInfo) {
_box->setTitle(_isBot
? tr::lng_edit_bot_title()
: _isGroup
? tr::lng_edit_group()
: tr::lng_edit_channel_title());
_box->addButton(tr::lng_settings_save(), [=] {
@ -491,7 +505,9 @@ object_ptr<Ui::RpWidget> Controller::createTitleEdit() {
object_ptr<Ui::InputField>(
_wrap,
st::defaultInputField,
(_isGroup
(_isBot
? tr::lng_dlg_new_bot_name
: _isGroup
? tr::lng_dlg_new_group_name
: tr::lng_dlg_new_channel_name)(),
_peer->name()),
@ -603,7 +619,9 @@ object_ptr<Ui::RpWidget> Controller::createStickersEdit() {
}
bool Controller::canEditInformation() const {
if (const auto channel = _peer->asChannel()) {
if (_isBot) {
return _peer->asUser()->botInfo->canEditInformation;
} else if (const auto channel = _peer->asChannel()) {
return channel->canEditInformation();
} else if (const auto chat = _peer->asChat()) {
return chat->canEditInformation();
@ -985,12 +1003,41 @@ void Controller::fillHistoryVisibilityButton() {
void Controller::fillManageSection() {
Expects(_controls.buttonsLayout != nullptr);
using namespace rpl::mappers;
if (_isBot) {
const auto &container = _controls.buttonsLayout;
AddSkip(
container,
st::editPeerTopButtonsLayoutSkipCustomTop);
fillBotUsernamesButton();
fillBotEditIntroButton();
fillBotEditCommandsButton();
fillBotEditSettingsButton();
Settings::AddSkip(
container,
st::editPeerTopButtonsLayoutSkipCustomBottom);
container->add(object_ptr<Ui::DividerLabel>(
container,
object_ptr<Ui::FlatLabel>(
container,
tr::lng_manage_peer_bot_about(
lt_bot,
rpl::single(Ui::Text::Link(
'@' + kBotManagerUsername.utf16(),
_peer->session().createInternalLinkFull(
kBotManagerUsername.utf16()))),
Ui::Text::RichLangValue),
st::boxDividerLabel),
st::settingsDividerLabelPadding));
return;
}
const auto chat = _peer->asChat();
const auto channel = _peer->asChannel();
const auto isChannel = (!chat);
if (!chat && !channel) return;
if (!chat && !channel) {
return;
}
const auto canEditType = [&] {
return isChannel
@ -1043,7 +1090,6 @@ void Controller::fillManageSection() {
}();
const auto canEditStickers = [&] {
// return true;
return isChannel
? channel->canEditStickers()
: false;
@ -1308,6 +1354,98 @@ void Controller::fillPendingRequestsButton() {
}, wrap->lifetime());
}
void Controller::fillBotUsernamesButton() {
Expects(_isBot);
const auto user = _peer->asUser();
auto localUsernames = rpl::single(
user->usernames()
) | rpl::map([](const std::vector<QString> &usernames) {
return ranges::views::all(
usernames
) | ranges::views::transform([](const QString &u) {
return Data::Username{ u };
}) | ranges::to_vector;
});
auto usernamesValue = std::move(
localUsernames
) | rpl::then(
_peer->session().api().usernames().loadUsernames(_peer)
);
auto rightLabel = rpl::duplicate(
usernamesValue
) | rpl::map([=](const Data::Usernames &usernames) {
if (usernames.size() <= 1) {
return user->session().createInternalLink(user->username());
} else {
const auto active = ranges::count_if(
usernames,
[](const Data::Username &u) { return u.active; });
return u"%1/%2"_q.arg(active).arg(usernames.size());
}
});
auto leftLabel = std::move(
usernamesValue
) | rpl::map([=](const Data::Usernames &usernames) {
return (usernames.size() <= 1)
? tr::lng_manage_peer_bot_public_link()
: tr::lng_manage_peer_bot_public_links();
}) | rpl::flatten_latest();
const auto wrap = _controls.buttonsLayout->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_controls.buttonsLayout,
object_ptr<Ui::VerticalLayout>(
_controls.buttonsLayout)));
AddButtonWithCount(
_controls.buttonsLayout,
std::move(leftLabel),
std::move(rightLabel),
[=] {
Window::Show(_navigation).showBox(
Box(UsernamesBox, user),
Ui::LayerOption::KeepOther);
},
{ &st::infoRoundedIconInviteLinks, Settings::kIconLightOrange });
}
void Controller::fillBotEditIntroButton() {
Expects(_isBot);
const auto user = _peer->asUser();
AddButtonWithCount(
_controls.buttonsLayout,
tr::lng_manage_peer_bot_edit_intro(),
rpl::never<QString>(),
[=] { toggleBotManager(u"%1-intro"_q.arg(user->username())); },
{ &st::settingsIconChat, Settings::kIconLightBlue });
}
void Controller::fillBotEditCommandsButton() {
Expects(_isBot);
const auto user = _peer->asUser();
AddButtonWithCount(
_controls.buttonsLayout,
tr::lng_manage_peer_bot_edit_commands(),
rpl::never<QString>(),
[=] { toggleBotManager(u"%1-commands"_q.arg(user->username())); },
{ &st::settingsIconChat, Settings::kIconLightBlue });
}
void Controller::fillBotEditSettingsButton() {
Expects(_isBot);
const auto user = _peer->asUser();
AddButtonWithCount(
_controls.buttonsLayout,
tr::lng_manage_peer_bot_edit_settings(),
rpl::never<QString>(),
[=] { toggleBotManager(user->username()); },
{ &st::settingsIconChat, Settings::kIconLightBlue });
}
void Controller::submitTitle() {
Expects(_controls.title != nullptr);
@ -1670,6 +1808,19 @@ void Controller::saveTitle() {
)).done(std::move(onDone)
).fail(std::move(onFail)
).send();
} else if (_isBot) {
using Flag = MTPbots_SetBotInfo::Flag;
_api.request(MTPbots_SetBotInfo(
MTP_flags(Flag::f_bot | Flag::f_name),
_peer->asUser()->inputUser,
MTPstring(), // Lang code.
MTP_string(*_savingData.title), // Name.
MTPstring(), // About.
MTPstring() // Description.
)).done([=] {
continueSave();
}).fail(std::move(onFail)
).send();
} else {
continueSave();
}
@ -1684,6 +1835,23 @@ void Controller::saveDescription() {
_peer->setAbout(*_savingData.description);
continueSave();
};
if (_isBot) {
using Flag = MTPbots_SetBotInfo::Flag;
_api.request(MTPbots_SetBotInfo(
MTP_flags(Flag::f_bot | Flag::f_about),
_peer->asUser()->inputUser,
MTPstring(), // Lang code.
MTPstring(), // Name.
MTP_string(*_savingData.description), // About.
MTPstring() // Description.
)).done([=] {
successCallback();
}).fail([=] {
_controls.description->showError();
cancelSave();
}).send();
return;
}
_api.request(MTPmessages_EditChatAbout(
_peer->input,
MTP_string(*_savingData.description)
@ -1726,6 +1894,22 @@ void Controller::saveHistoryVisibility() {
[=] { cancelSave(); });
}
void Controller::toggleBotManager(const QString &command) {
const auto controller = _navigation->parentController();
_api.request(MTPcontacts_ResolveUsername(
MTP_string(kBotManagerUsername.utf16())
)).done([=](const MTPcontacts_ResolvedPeer &result) {
_peer->owner().processUsers(result.data().vusers());
_peer->owner().processChats(result.data().vchats());
const auto botPeer = _peer->owner().peerLoaded(
peerFromMTP(result.data().vpeer()));
if (const auto bot = botPeer ? botPeer->asUser() : nullptr) {
_peer->session().api().sendBotStart(bot, bot, command);
controller->showPeerHistory(bot);
}
}).send();
}
void Controller::togglePreHistoryHidden(
not_null<ChannelData*> channel,
bool hidden,