Improve phrases in adding a bot as an admin.

This commit is contained in:
John Preston 2022-03-23 18:22:09 +04:00
parent a35888a07b
commit 649f2908e8
13 changed files with 596 additions and 312 deletions

View File

@ -163,6 +163,8 @@ PRIVATE
boxes/filters/edit_filter_box.h
boxes/filters/edit_filter_chats_list.cpp
boxes/filters/edit_filter_chats_list.h
boxes/peers/add_bot_to_chat_box.cpp
boxes/peers/add_bot_to_chat_box.h
boxes/peers/add_participants_box.cpp
boxes/peers/add_participants_box.h
boxes/peers/edit_contact_box.cpp

View File

@ -1714,6 +1714,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_bot_channels_manage" = "Channels I manage";
"lng_bot_groups" = "Groups";
"lng_bot_add_title" = "Add Bot";
"lng_bot_as_admin_check" = "Admin rights";
"lng_bot_add_as_admin" = "Add Bot as Admin";
"lng_bot_add_as_member" = "Add Bot as Member";
"lng_bot_sure_add_title" = "Add bot as admin";

View File

@ -89,35 +89,6 @@ private:
};
[[nodiscard]] object_ptr<Ui::RpWidget> CreateSectionSubtitle(
not_null<QWidget*> parent,
rpl::producer<QString> text) {
auto result = object_ptr<Ui::FixedHeightWidget>(
parent,
st::searchedBarHeight);
const auto raw = result.data();
raw->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = QPainter(raw);
p.fillRect(clip, st::searchedBarBg);
}, raw->lifetime());
const auto label = Ui::CreateChild<Ui::FlatLabel>(
raw,
std::move(text),
st::windowFilterChatsSectionSubtitle);
raw->widthValue(
) | rpl::start_with_next([=](int width) {
const auto padding = st::windowFilterChatsSectionSubtitlePadding;
const auto available = width - padding.left() - padding.right();
label->resizeToNaturalWidth(available);
label->moveToLeft(padding.left(), padding.top(), width);
}, label->lifetime());
return result;
}
[[nodiscard]] uint64 TypeId(Flag flag) {
return PeerId(FakeChatId(static_cast<BareId>(flag))).value;
}
@ -291,6 +262,35 @@ void PaintFilterChatsTypeIcon(
icon.paintInCenter(p, rect);
}
object_ptr<Ui::RpWidget> CreatePeerListSectionSubtitle(
not_null<QWidget*> parent,
rpl::producer<QString> text) {
auto result = object_ptr<Ui::FixedHeightWidget>(
parent,
st::searchedBarHeight);
const auto raw = result.data();
raw->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = QPainter(raw);
p.fillRect(clip, st::searchedBarBg);
}, raw->lifetime());
const auto label = Ui::CreateChild<Ui::FlatLabel>(
raw,
std::move(text),
st::windowFilterChatsSectionSubtitle);
raw->widthValue(
) | rpl::start_with_next([=](int width) {
const auto padding = st::windowFilterChatsSectionSubtitlePadding;
const auto available = width - padding.left() - padding.right();
label->resizeToNaturalWidth(available);
label->moveToLeft(padding.left(), padding.top(), width);
}, label->lifetime());
return result;
}
EditFilterChatsListController::EditFilterChatsListController(
not_null<Main::Session*> session,
rpl::producer<QString> title,
@ -357,7 +357,7 @@ void EditFilterChatsListController::prepareViewHook() {
object_ptr<Ui::RpWidget> EditFilterChatsListController::prepareTypesList() {
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
const auto container = result.data();
container->add(CreateSectionSubtitle(
container->add(CreatePeerListSectionSubtitle(
container,
tr::lng_filters_edit_types()));
container->add(object_ptr<Ui::FixedHeightWidget>(
@ -390,7 +390,7 @@ object_ptr<Ui::RpWidget> EditFilterChatsListController::prepareTypesList() {
container->add(object_ptr<Ui::FixedHeightWidget>(
container,
st::membersMarginBottom));
container->add(CreateSectionSubtitle(
container->add(CreatePeerListSectionSubtitle(
container,
tr::lng_filters_edit_chats()));

View File

@ -35,6 +35,10 @@ void PaintFilterChatsTypeIcon(
int outerWidth,
int size);
[[nodiscard]] object_ptr<Ui::RpWidget> CreatePeerListSectionSubtitle(
not_null<QWidget*> parent,
rpl::producer<QString> text);
class EditFilterChatsListController final : public ChatsListBoxController {
public:
using Flag = Data::ChatFilter::Flag;

View File

@ -25,8 +25,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h"
#include "lang/lang_keys.h"
#include "history/history.h"
#include "boxes/peers/edit_participant_box.h"
#include "boxes/peers/edit_participants_box.h"
#include "dialogs/dialogs_main_list.h"
#include "window/window_session_controller.h" // showAddContact()
#include "base/unixtime.h"
@ -38,52 +36,6 @@ namespace {
constexpr auto kSortByOnlineThrottle = 3 * crl::time(1000);
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = chat->owner().history(chat);
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::Send;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
const auto randomId = base::RandomValue<uint64>();
const auto api = &chat->session().api();
history->sendRequestId = api->request(MTPmessages_SendMedia(
MTP_flags(0),
chat->input,
MTP_int(0),
MTP_inputMediaGame(
MTP_inputGameShortName(
bot->inputUser,
MTP_string(bot->botInfo->shareGameShortName))),
MTP_string(),
MTP_long(randomId),
MTPReplyMarkup(),
MTPVector<MTPMessageEntity>(),
MTP_int(0), // schedule_date
MTPInputPeer() // send_as
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result, randomId);
finish();
}).fail([=](const MTP::Error &error) {
api->sendMessageFail(error, chat);
finish();
}).afterRequest(
history->sendRequestId
).send();
return history->sendRequestId;
});
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}
void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
if (bot->isBot() && !bot->botInfo->startGroupToken.isEmpty()) {
chat->session().api().sendBotStart(bot, chat);
} else {
chat->session().api().chatParticipants().add(chat, { 1, bot });
}
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}
} // namespace
// Not used for now.
@ -526,168 +478,6 @@ std::unique_ptr<PeerListRow> ContactsBoxController::createRow(
return std::make_unique<PeerListRow>(user);
}
void AddBotToGroupBoxController::Start(not_null<UserData*> bot) {
auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(tr::lng_cancel(), [box] { box->closeBox(); });
};
Ui::show(Box<PeerListBox>(
std::make_unique<AddBotToGroupBoxController>(bot),
std::move(initBox)));
}
AddBotToGroupBoxController::AddBotToGroupBoxController(
not_null<UserData*> bot)
: ChatsListBoxController(SharingBotGame(bot)
? std::make_unique<PeerListGlobalSearchController>(&bot->session())
: nullptr)
, _bot(bot) {
}
Main::Session &AddBotToGroupBoxController::session() const {
return _bot->session();
}
void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow*> row) {
if (sharingBotGame()) {
shareBotGame(row->peer());
} else {
addBotToGroup(row->peer());
}
}
void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
auto send = crl::guard(this, [bot = _bot, chat] {
ShareBotGame(bot, chat);
});
auto confirmText = [chat] {
if (chat->isUser()) {
return tr::lng_bot_sure_share_game(tr::now, lt_user, chat->name);
}
return tr::lng_bot_sure_share_game_group(tr::now, lt_group, chat->name);
}();
Ui::show(
Ui::MakeConfirmBox({
.text = confirmText,
.confirmed = std::move(send),
}),
Ui::LayerOption::KeepOther);
}
void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
if (const auto megagroup = chat->asMegagroup()) {
if (!megagroup->canAddMembers()) {
Ui::show(
Ui::MakeInformBox(tr::lng_error_cant_add_member()),
Ui::LayerOption::KeepOther);
return;
}
}
const auto bot = _bot;
const auto close = [=](auto&&...) {
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
};
const auto saveCallback = SaveAdminCallback(
chat,
bot,
close,
close);
auto box = object_ptr<EditAdminBox>(nullptr);
if (chat->isBroadcast()) {
if (bot->botInfo->channelAdminRights) {
box = Box<EditAdminBox>(
chat,
bot,
ChatAdminRightsInfo(bot->botInfo->channelAdminRights),
QString());
}
} else if (bot->botInfo->groupAdminRights) {
box = Box<EditAdminBox>(
chat,
bot,
ChatAdminRightsInfo(bot->botInfo->groupAdminRights),
QString());
}
if (box) {
box->setSaveCallback(saveCallback);
Ui::show(std::move(box));
return;
}
Ui::show(
Ui::MakeConfirmBox({
tr::lng_bot_sure_invite(tr::now, lt_group, chat->name),
crl::guard(this, [=] { AddBotToGroup(bot, chat); }),
}),
Ui::LayerOption::KeepOther);
}
auto AddBotToGroupBoxController::createRow(not_null<History*> history)
-> std::unique_ptr<ChatsListBoxController::Row> {
if (!needToCreateRow(history->peer)) {
return nullptr;
}
return std::make_unique<Row>(history);
}
bool AddBotToGroupBoxController::needToCreateRow(
not_null<PeerData*> peer) const {
if (sharingBotGame()) {
if (!peer->canWrite()
|| peer->amRestricted(ChatRestriction::SendGames)) {
return false;
}
return true;
}
if (const auto chat = peer->asChat()) {
return chat->canAddMembers();
} else if (const auto group = peer->asMegagroup()) {
return group->canAddMembers();
}
return false;
}
bool AddBotToGroupBoxController::SharingBotGame(not_null<UserData*> bot) {
const auto &info = bot->botInfo;
return (info && !info->shareGameShortName.isEmpty());
}
bool AddBotToGroupBoxController::sharingBotGame() const {
return SharingBotGame(_bot);
}
QString AddBotToGroupBoxController::emptyBoxText() const {
return !session().data().chatsListLoaded()
? tr::lng_contacts_loading(tr::now)
: sharingBotGame()
? tr::lng_bot_no_chats(tr::now)
: tr::lng_bot_no_groups(tr::now);
}
QString AddBotToGroupBoxController::noResultsText() const {
return !session().data().chatsListLoaded()
? tr::lng_contacts_loading(tr::now)
: sharingBotGame()
? tr::lng_bot_chats_not_found(tr::now)
: tr::lng_bot_groups_not_found(tr::now);
}
void AddBotToGroupBoxController::updateLabels() {
setSearchNoResultsText(noResultsText());
}
void AddBotToGroupBoxController::prepareViewHook() {
delegate()->peerListSetTitle(sharingBotGame()
? tr::lng_bot_choose_chat()
: tr::lng_bot_choose_group());
updateLabels();
session().data().chatsListLoadedEvents(
) | rpl::filter([=](Data::Folder *folder) {
return !folder;
}) | rpl::start_with_next([=] {
updateLabels();
}, lifetime());
}
ChooseRecipientBoxController::ChooseRecipientBoxController(
not_null<Main::Session*> session,
FnMut<void(not_null<PeerData*>)> callback)

View File

@ -165,38 +165,6 @@ private:
};
class AddBotToGroupBoxController
: public ChatsListBoxController
, public base::has_weak_ptr {
public:
static void Start(not_null<UserData*> bot);
explicit AddBotToGroupBoxController(not_null<UserData*> bot);
Main::Session &session() const override;
void rowClicked(not_null<PeerListRow*> row) override;
protected:
std::unique_ptr<Row> createRow(not_null<History*> history) override;
void prepareViewHook() override;
QString emptyBoxText() const override;
private:
static bool SharingBotGame(not_null<UserData*> bot);
bool needToCreateRow(not_null<PeerData*> peer) const;
bool sharingBotGame() const;
QString noResultsText() const;
QString descriptionText() const;
void updateLabels();
void shareBotGame(not_null<PeerData*> chat);
void addBotToGroup(not_null<PeerData*> chat);
const not_null<UserData*> _bot;
};
class ChooseRecipientBoxController
: public ChatsListBoxController
, public base::has_weak_ptr {

View File

@ -0,0 +1,381 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/peers/add_bot_to_chat_box.h"
#include "lang/lang_keys.h"
#include "data/data_user.h"
#include "data/data_chat.h"
#include "data/data_channel.h"
#include "data/data_session.h"
#include "data/data_histories.h"
#include "history/history.h"
#include "main/main_session.h"
#include "boxes/peers/edit_participant_box.h"
#include "boxes/peers/edit_participants_box.h"
#include "boxes/filters/edit_filter_chats_list.h"
#include "ui/boxes/confirm_box.h"
#include "base/random.h"
#include "base/weak_ptr.h"
#include "api/api_chat_participants.h"
#include "apiwrap.h"
#include "facades.h"
#include "styles/style_boxes.h"
namespace {
class Controller final
: public PeerListController
, public base::has_weak_ptr {
public:
Controller(
not_null<Main::Session*> session,
rpl::producer<not_null<PeerData*>> add,
Fn<void(not_null<PeerData*> chat)> callback);
Main::Session &session() const override;
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
private:
void addRow(not_null<PeerData*> peer);
const not_null<Main::Session*> _session;
Fn<void(not_null<PeerData*> chat)> _callback;
std::vector<not_null<PeerData*>> _list;
bool _prepared = false;
bool _refreshing = false;
rpl::lifetime _lifetime;
};
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = chat->owner().history(chat);
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::Send;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
const auto randomId = base::RandomValue<uint64>();
const auto api = &chat->session().api();
history->sendRequestId = api->request(MTPmessages_SendMedia(
MTP_flags(0),
chat->input,
MTP_int(0),
MTP_inputMediaGame(
MTP_inputGameShortName(
bot->inputUser,
MTP_string(bot->botInfo->shareGameShortName))),
MTP_string(),
MTP_long(randomId),
MTPReplyMarkup(),
MTPVector<MTPMessageEntity>(),
MTP_int(0), // schedule_date
MTPInputPeer() // send_as
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result, randomId);
finish();
}).fail([=](const MTP::Error &error) {
api->sendMessageFail(error, chat);
finish();
}).afterRequest(
history->sendRequestId
).send();
return history->sendRequestId;
});
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}
Controller::Controller(
not_null<Main::Session*> session,
rpl::producer<not_null<PeerData*>> add,
Fn<void(not_null<PeerData*> chat)> callback)
: _session(session)
, _callback(std::move(callback)) {
std::move(
add
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
if (_prepared) {
addRow(peer);
} else {
_list.push_back(peer);
}
}, _lifetime);
}
Main::Session &Controller::session() const {
return *_session;
}
void Controller::prepare() {
_prepared = true;
for (const auto &peer : _list) {
addRow(peer);
}
}
void Controller::rowClicked(not_null<PeerListRow*> row) {
_callback(row->peer());
}
void Controller::addRow(not_null<PeerData*> peer) {
if (delegate()->peerListFindRow(peer->id.value)) {
return;
}
delegate()->peerListAppendRow(std::make_unique<PeerListRow>(peer));
if (!_refreshing) {
_refreshing = true;
Ui::PostponeCall(this, [=] {
_refreshing = false;
delegate()->peerListRefreshRows();
});
}
}
} // namespace
void AddBotToGroupBoxController::Start(not_null<UserData*> bot) {
auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(tr::lng_cancel(), [box] { box->closeBox(); });
};
Ui::show(Box<PeerListBox>(
std::make_unique<AddBotToGroupBoxController>(bot),
std::move(initBox)));
}
AddBotToGroupBoxController::AddBotToGroupBoxController(
not_null<UserData*> bot)
: ChatsListBoxController(SharingBotGame(bot)
? std::make_unique<PeerListGlobalSearchController>(&bot->session())
: nullptr)
, _bot(bot)
, _adminToGroup(_bot->botInfo->groupAdminRights != 0)
, _adminToChannel(_bot->botInfo->channelAdminRights != 0) {
}
Main::Session &AddBotToGroupBoxController::session() const {
return _bot->session();
}
void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow*> row) {
if (sharingBotGame()) {
shareBotGame(row->peer());
} else {
addBotToGroup(row->peer());
}
}
void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
auto send = crl::guard(this, [bot = _bot, chat] {
ShareBotGame(bot, chat);
});
auto confirmText = [chat] {
if (chat->isUser()) {
return tr::lng_bot_sure_share_game(tr::now, lt_user, chat->name);
}
return tr::lng_bot_sure_share_game_group(tr::now, lt_group, chat->name);
}();
Ui::show(
Ui::MakeConfirmBox({
.text = confirmText,
.confirmed = std::move(send),
}),
Ui::LayerOption::KeepOther);
}
void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
if (const auto megagroup = chat->asMegagroup()) {
if (!megagroup->canAddMembers()) {
Ui::show(
Ui::MakeInformBox(tr::lng_error_cant_add_member()),
Ui::LayerOption::KeepOther);
return;
}
}
const auto bot = _bot;
const auto close = [=](auto&&...) {
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
};
const auto rights = (chat->isBroadcast()
&& chat->asBroadcast()->canAddAdmins())
? bot->botInfo->channelAdminRights
: ((chat->isMegagroup() && chat->asMegagroup()->canAddAdmins())
|| (chat->isChat() && chat->asChat()->canAddAdmins()))
? bot->botInfo->groupAdminRights
: ChatAdminRights();
if (rights) {
const auto saveCallback = SaveAdminCallback(
chat,
bot,
close,
close);
auto box = object_ptr<EditAdminBox>(nullptr);
box = Box<EditAdminBox>(
chat,
bot,
ChatAdminRightsInfo(rights),
QString(),
true);
box->setSaveCallback(saveCallback);
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
} else {
Ui::show(
Ui::MakeConfirmBox({
tr::lng_bot_sure_invite(tr::now, lt_group, chat->name),
crl::guard(this, [=] { AddBotToGroup(bot, chat); }),
}),
Ui::LayerOption::KeepOther);
}
}
auto AddBotToGroupBoxController::createRow(not_null<History*> history)
-> std::unique_ptr<ChatsListBoxController::Row> {
if (!needToCreateRow(history->peer)) {
return nullptr;
}
return std::make_unique<Row>(history);
}
bool AddBotToGroupBoxController::needToCreateRow(
not_null<PeerData*> peer) const {
if (sharingBotGame()) {
if (!peer->canWrite()
|| peer->amRestricted(ChatRestriction::SendGames)) {
return false;
}
return true;
}
if (const auto chat = peer->asChat()) {
if (_adminToGroup && chat->canAddAdmins()) {
_groups.fire_copy(peer);
} else {
return chat->canAddMembers();
}
} else if (const auto group = peer->asMegagroup()) {
if (_adminToGroup && group->canAddAdmins()) {
_groups.fire_copy(peer);
} else {
return group->canAddMembers();
}
} else if (const auto channel = peer->asBroadcast()) {
if (_adminToChannel && channel->canAddAdmins()) {
_channels.fire_copy(peer);
}
}
return false;
}
bool AddBotToGroupBoxController::SharingBotGame(not_null<UserData*> bot) {
const auto &info = bot->botInfo;
return (info && !info->shareGameShortName.isEmpty());
}
bool AddBotToGroupBoxController::sharingBotGame() const {
return SharingBotGame(_bot);
}
QString AddBotToGroupBoxController::emptyBoxText() const {
return !session().data().chatsListLoaded()
? tr::lng_contacts_loading(tr::now)
: (sharingBotGame() || _adminToChannel)
? tr::lng_bot_no_chats(tr::now)
: tr::lng_bot_no_groups(tr::now);
}
QString AddBotToGroupBoxController::noResultsText() const {
return !session().data().chatsListLoaded()
? tr::lng_contacts_loading(tr::now)
: (sharingBotGame() || _adminToChannel)
? tr::lng_bot_chats_not_found(tr::now)
: tr::lng_bot_groups_not_found(tr::now);
}
void AddBotToGroupBoxController::updateLabels() {
setSearchNoResultsText(noResultsText());
}
object_ptr<Ui::RpWidget> AddBotToGroupBoxController::prepareAdminnedChats() {
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
const auto container = result.data();
const auto callback = [=](not_null<PeerData*> chat) {
addBotToGroup(chat);
};
const auto addList = [&](
tr::phrase<> subtitle,
rpl::event_stream<not_null<PeerData*>> &items) {
container->add(CreatePeerListSectionSubtitle(
container,
subtitle()));
container->add(object_ptr<Ui::FixedHeightWidget>(
container,
st::membersMarginTop));
const auto delegate = container->lifetime().make_state<
PeerListContentDelegateSimple
>();
const auto controller = container->lifetime().make_state<Controller>(
&session(),
items.events(),
callback);
const auto content = result->add(object_ptr<PeerListContent>(
container,
controller));
delegate->setContent(content);
controller->setDelegate(delegate);
container->add(object_ptr<Ui::FixedHeightWidget>(
container,
st::membersMarginBottom));
};
if (_adminToChannel) {
addList(tr::lng_bot_channels_manage, _channels);
}
if (_adminToGroup) {
addList(tr::lng_bot_groups_manage, _groups);
}
rpl::merge(
_groups.events(),
_channels.events()
) | rpl::take(1) | rpl::start_with_next([=] {
container->add(CreatePeerListSectionSubtitle(
container,
tr::lng_bot_groups()));
}, container->lifetime());
return result;
}
void AddBotToGroupBoxController::prepareViewHook() {
delegate()->peerListSetTitle((sharingBotGame() || _adminToChannel)
? tr::lng_bot_choose_chat()
: tr::lng_bot_choose_group());
if (_adminToGroup || _adminToChannel) {
delegate()->peerListSetAboveWidget(prepareAdminnedChats());
}
updateLabels();
session().data().chatsListLoadedEvents(
) | rpl::filter([=](Data::Folder *folder) {
return !folder;
}) | rpl::start_with_next([=] {
updateLabels();
}, lifetime());
}
void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
if (bot->isBot() && !bot->botInfo->startGroupToken.isEmpty()) {
chat->session().api().sendBotStart(bot, chat);
} else {
chat->session().api().chatParticipants().add(chat, { 1, bot });
}
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}

View File

@ -0,0 +1,49 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/peer_list_controllers.h"
class AddBotToGroupBoxController
: public ChatsListBoxController
, public base::has_weak_ptr {
public:
static void Start(not_null<UserData*> bot);
explicit AddBotToGroupBoxController(not_null<UserData*> bot);
Main::Session &session() const override;
void rowClicked(not_null<PeerListRow*> row) override;
protected:
std::unique_ptr<Row> createRow(not_null<History*> history) override;
void prepareViewHook() override;
QString emptyBoxText() const override;
private:
static bool SharingBotGame(not_null<UserData*> bot);
object_ptr<Ui::RpWidget> prepareAdminnedChats();
bool needToCreateRow(not_null<PeerData*> peer) const;
bool sharingBotGame() const;
QString noResultsText() const;
void updateLabels();
void shareBotGame(not_null<PeerData*> chat);
void addBotToGroup(not_null<PeerData*> chat);
const not_null<UserData*> _bot;
rpl::event_stream<not_null<PeerData*>> _groups;
rpl::event_stream<not_null<PeerData*>> _channels;
bool _adminToGroup = false;
bool _adminToChannel = false;
};
void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat);

View File

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_privacy_security.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/passcode_box.h"
#include "boxes/peers/add_bot_to_chat_box.h"
#include "boxes/peers/edit_peer_permissions_box.h"
#include "boxes/peers/edit_peer_info_box.h"
#include "data/data_peer_values.h"
@ -198,7 +199,8 @@ EditAdminBox::EditAdminBox(
not_null<PeerData*> peer,
not_null<UserData*> user,
ChatAdminRightsInfo rights,
const QString &rank)
const QString &rank,
bool addingBot)
: EditParticipantBox(
nullptr,
peer,
@ -206,7 +208,8 @@ EditAdminBox::EditAdminBox(
(rights.flags != 0))
, _show(this)
, _oldRights(rights)
, _oldRank(rank) {
, _oldRank(rank)
, _addingBot(addingBot) {
}
ChatAdminRightsInfo EditAdminBox::defaultRights() const {
@ -236,12 +239,40 @@ void EditAdminBox::prepare() {
EditParticipantBox::prepare();
setTitle(_oldRights.flags
setTitle(_addingBot
? tr::lng_bot_add_title()
: _oldRights.flags
? tr::lng_rights_edit_admin()
: tr::lng_channel_add_admin());
addControl(
object_ptr<Ui::BoxContentDivider>(this),
if (_addingBot && !peer()->isBroadcast() && _saveCallback) {
addControl(
object_ptr<Ui::BoxContentDivider>(this),
st::rightsDividerMargin / 2);
_addAsAdmin = addControl(
object_ptr<Ui::Checkbox>(
this,
tr::lng_bot_as_admin_check(tr::now),
st::rightsCheckbox,
std::make_unique<Ui::ToggleView>(
st::rightsToggle,
true)),
st::rightsToggleMargin + (st::rightsDividerMargin / 2));
_addAsAdmin->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
_adminControlsWrap->toggle(checked, anim::type::normal);
refreshButtons();
}, _addAsAdmin->lifetime());
}
_adminControlsWrap = addControl(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
this,
object_ptr<Ui::VerticalLayout>(this)));
const auto inner = _adminControlsWrap->entity();
inner->add(
object_ptr<Ui::BoxContentDivider>(inner),
st::rightsDividerMargin);
const auto chat = peer()->asChat();
@ -290,21 +321,21 @@ void EditAdminBox::prepare() {
? chat->anyoneCanAddMembers()
: channel->anyoneCanAddMembers();
auto [checkboxes, getChecked, changes] = CreateEditAdminRights(
this,
inner,
tr::lng_rights_edit_admin_header(),
prepareFlags,
disabledMessages,
isGroup,
anyoneCanAddMembers);
addControl(std::move(checkboxes), QMargins());
inner->add(std::move(checkboxes), QMargins());
auto selectedFlags = rpl::single(
getChecked()
) | rpl::then(std::move(
changes
));
_aboutAddAdmins = addControl(
object_ptr<Ui::FlatLabel>(this, st::boxDividerLabel),
_aboutAddAdmins = inner->add(
object_ptr<Ui::FlatLabel>(inner, st::boxDividerLabel),
st::rightsAboutMargin);
rpl::duplicate(
selectedFlags
@ -318,6 +349,7 @@ void EditAdminBox::prepare() {
if (canTransferOwnership()) {
const auto allFlags = AdminRightsForOwnershipTransfer(isGroup);
setupTransferButton(
inner,
isGroup
)->toggleOn(rpl::duplicate(
selectedFlags
@ -327,37 +359,76 @@ void EditAdminBox::prepare() {
}
if (canSave()) {
const auto rank = (chat || channel->isMegagroup())
? addRankInput().get()
_rank = (chat || channel->isMegagroup())
? addRankInput(inner).get()
: nullptr;
addButton(tr::lng_settings_save(), [=, value = getChecked] {
if (!_saveCallback) {
return;
}
_finishSave = [=, value = getChecked] {
const auto newFlags = (value() | ChatAdminRight::Other)
& ((!channel || channel->amCreator())
? ~Flags(0)
: channel->adminRights());
_saveCallback(
_oldRights,
_addingBot ? ChatAdminRightsInfo() : _oldRights,
ChatAdminRightsInfo(newFlags),
rank ? rank->getLastText().trimmed() : QString());
});
_rank ? _rank->getLastText().trimmed() : QString());
};
_save = [=] {
if (!_saveCallback) {
return;
} else if (_addAsAdmin && !_addAsAdmin->checked()) {
AddBotToGroup(user(), peer());
return;
} else if (_addingBot) {
const auto phrase = peer()->isBroadcast()
? tr::lng_bot_sure_add_text_channel
: tr::lng_bot_sure_add_text_group;
_confirmBox = getDelegate()->show(Ui::MakeConfirmBox({
phrase(
tr::now,
lt_group,
Ui::Text::Bold(peer()->name),
Ui::Text::WithEntities),
crl::guard(this, [=] { finishAddAdmin(); })
}), Ui::LayerOption::KeepOther);
} else {
_finishSave();
}
};
}
refreshButtons();
}
void EditAdminBox::finishAddAdmin() {
_finishSave();
if (_confirmBox) {
_confirmBox->closeBox();
}
}
void EditAdminBox::refreshButtons() {
clearButtons();
if (canSave()) {
addButton(!_addingBot
? tr::lng_settings_save()
: _adminControlsWrap->toggled()
? tr::lng_bot_add_as_admin()
: tr::lng_bot_add_as_member(), _save);
addButton(tr::lng_cancel(), [=] { closeBox(); });
} else {
addButton(tr::lng_box_ok(), [=] { closeBox(); });
}
}
not_null<Ui::InputField*> EditAdminBox::addRankInput() {
addControl(
object_ptr<Ui::BoxContentDivider>(this),
not_null<Ui::InputField*> EditAdminBox::addRankInput(
not_null<Ui::VerticalLayout*> container) {
container->add(
object_ptr<Ui::BoxContentDivider>(container),
st::rightsRankMargin);
addControl(
container->add(
object_ptr<Ui::FlatLabel>(
this,
container,
tr::lng_rights_edit_admin_rank_name(),
st::rightsHeaderLabel),
st::rightsHeaderMargin);
@ -372,9 +443,9 @@ not_null<Ui::InputField*> EditAdminBox::addRankInput() {
}
Unexpected("Peer type in EditAdminBox::addRankInput.");
}();
const auto result = addControl(
const auto result = container->add(
object_ptr<Ui::InputField>(
this,
container,
st::customBadgeField,
(isOwner ? tr::lng_owner_badge : tr::lng_admin_badge)(),
TextUtilities::RemoveEmoji(_oldRank)),
@ -389,9 +460,9 @@ not_null<Ui::InputField*> EditAdminBox::addRankInput() {
}
});
addControl(
container->add(
object_ptr<Ui::FlatLabel>(
this,
container,
tr::lng_rights_edit_admin_rank_about(
lt_title,
(isOwner ? tr::lng_owner_badge : tr::lng_admin_badge)()),
@ -413,19 +484,20 @@ bool EditAdminBox::canTransferOwnership() const {
}
not_null<Ui::SlideWrap<Ui::RpWidget>*> EditAdminBox::setupTransferButton(
not_null<Ui::VerticalLayout*> container,
bool isGroup) {
const auto wrap = addControl(
const auto wrap = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
this,
object_ptr<Ui::VerticalLayout>(this)));
container,
object_ptr<Ui::VerticalLayout>(container)));
const auto container = wrap->entity();
const auto inner = wrap->entity();
container->add(
object_ptr<Ui::BoxContentDivider>(container),
inner->add(
object_ptr<Ui::BoxContentDivider>(inner),
{ 0, st::infoProfileSkip, 0, st::infoProfileSkip });
container->add(EditPeerInfoBox::CreateButton(
this,
inner->add(EditPeerInfoBox::CreateButton(
inner,
(isGroup
? tr::lng_rights_transfer_group
: tr::lng_rights_transfer_channel)(),

View File

@ -18,6 +18,7 @@ class Checkbox;
class Radiobutton;
class RadiobuttonGroup;
class CalendarBox;
class VerticalLayout;
template <typename Widget>
class SlideWrap;
} // namespace Ui
@ -71,7 +72,8 @@ public:
not_null<PeerData*> peer,
not_null<UserData*> user,
ChatAdminRightsInfo rights,
const QString &rank);
const QString &rank,
bool addingBot = false);
void setSaveCallback(
Fn<void(
@ -87,7 +89,8 @@ protected:
private:
[[nodiscard]] ChatAdminRightsInfo defaultRights() const;
not_null<Ui::InputField*> addRankInput();
not_null<Ui::InputField*> addRankInput(
not_null<Ui::VerticalLayout*> container);
void transferOwnership();
void transferOwnershipChecked();
bool handleTransferPasswordError(const QString &error);
@ -99,9 +102,13 @@ private:
bool canSave() const {
return _saveCallback != nullptr;
}
void finishAddAdmin();
void refreshButtons();
void refreshAboutAddAdminsText(bool canAddAdmins);
bool canTransferOwnership() const;
not_null<Ui::SlideWrap<Ui::RpWidget>*> setupTransferButton(bool isGroup);
not_null<Ui::SlideWrap<Ui::RpWidget>*> setupTransferButton(
not_null<Ui::VerticalLayout*> container,
bool isGroup);
const Ui::BoxShow _show;
const ChatAdminRightsInfo _oldRights;
@ -111,9 +118,16 @@ private:
ChatAdminRightsInfo,
const QString &rank)> _saveCallback;
QPointer<Ui::BoxContent> _confirmBox;
Ui::Checkbox *_addAsAdmin = nullptr;
Ui::SlideWrap<Ui::VerticalLayout> *_adminControlsWrap = nullptr;
Ui::InputField *_rank = nullptr;
QPointer<Ui::FlatLabel> _aboutAddAdmins;
mtpRequestId _checkTransferRequestId = 0;
mtpRequestId _transferRequestId = 0;
Fn<void()> _save, _finishSave;
bool _addingBot = false;
};

View File

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/add_contact_box.h"
#include "boxes/peers/add_bot_to_chat_box.h"
#include "boxes/peers/edit_contact_box.h"
#include "lang/lang_keys.h"
#include "info/info_controller.h"

View File

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/add_contact_box.h"
#include "boxes/create_poll_box.h"
#include "boxes/pin_messages_box.h"
#include "boxes/peers/add_bot_to_chat_box.h"
#include "boxes/peers/add_participants_box.h"
#include "boxes/peers/edit_contact_box.h"
#include "ui/boxes/report_box.h"

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "boxes/add_contact_box.h"
#include "boxes/peers/add_bot_to_chat_box.h"
#include "boxes/peers/edit_peer_info_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/delete_messages_box.h"