From 38daffdbfe565c0b38adac0ea97d867806009f54 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 18 May 2018 17:16:14 +0300
Subject: [PATCH] Handle the ADMINS_TOO_MUCH error for channels.

---
 Telegram/Resources/langs/lang.strings         |   2 +
 .../profile/profile_block_group_members.cpp   |  22 ++--
 .../profile/profile_channel_controllers.cpp   | 108 ++++++++++++------
 .../profile/profile_channel_controllers.h     |   8 ++
 4 files changed, 93 insertions(+), 47 deletions(-)

diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 07873018b..8dcde941c 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -123,6 +123,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_error_cant_add_admin_invite" = "Sorry, you can't add this user as an admin because they are not a member of this group and you are not allowed to invite them.";
 "lng_error_cant_add_admin_unban" = "Sorry, you can't add this user as an admin because they are in the blacklist and you can't unban them.";
 "lng_error_cant_ban_admin" = "Sorry, you can't ban this user because they are an admin in this group and you are not allowed to demote them.";
+"lng_error_admin_limit" = "Sorry, you've reached the maximum number of admins for this group.";
+"lng_error_admin_limit_channel" = "Sorry, you've reached the maximum number of admins for this channel.";
 "lng_sure_add_admin_invite" = "This user is not a member of this group. Add them to the group and promote them to admin?";
 "lng_sure_add_admin_invite_channel" = "This user is not a subscriber of this channel. Add them to the channel and promote them to admin?";
 "lng_sure_add_admin_unban" = "This user is currently restricted or banned. Are you sure you want to unban and promote them?";
diff --git a/Telegram/SourceFiles/profile/profile_block_group_members.cpp b/Telegram/SourceFiles/profile/profile_block_group_members.cpp
index 7be60b05b..84e192906 100644
--- a/Telegram/SourceFiles/profile/profile_block_group_members.cpp
+++ b/Telegram/SourceFiles/profile/profile_block_group_members.cpp
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "ui/widgets/labels.h"
 #include "boxes/confirm_box.h"
 #include "boxes/edit_participant_box.h"
+#include "profile/profile_channel_controllers.h"
 #include "ui/widgets/popup_menu.h"
 #include "data/data_peer_values.h"
 #include "mainwidget.h"
@@ -67,16 +68,19 @@ void GroupMembersWidget::editAdmin(not_null<UserData*> user) {
 	auto currentRightsIt = megagroup->mgInfo->lastAdmins.find(user);
 	auto hasAdminRights = (currentRightsIt != megagroup->mgInfo->lastAdmins.cend());
 	auto currentRights = hasAdminRights ? currentRightsIt->second.rights : MTP_channelAdminRights(MTP_flags(0));
-	auto weak = QPointer<GroupMembersWidget>(this);
+	auto weak = std::make_shared<QPointer<EditAdminBox>>(nullptr);
 	auto box = Box<EditAdminBox>(megagroup, user, currentRights);
-	box->setSaveCallback([weak, megagroup, user](const MTPChannelAdminRights &oldRights, const MTPChannelAdminRights &newRights) {
-		Ui::hideLayer();
-		MTP::send(MTPchannels_EditAdmin(megagroup->inputChannel, user->inputUser, newRights), rpcDone([weak, megagroup, user, oldRights, newRights](const MTPUpdates &result) {
-			if (App::main()) App::main()->sentUpdatesReceived(result);
-			megagroup->applyEditAdmin(user, oldRights, newRights);
-		}));
-	});
-	Ui::show(std::move(box));
+	box->setSaveCallback(SaveAdminCallback(megagroup, user, [=](
+			const MTPChannelAdminRights &newRights) {
+		if (*weak) {
+			(*weak)->closeBox();
+		}
+	}, [=] {
+		if (*weak) {
+			(*weak)->closeBox();
+		}
+	}));
+	*weak = Ui::show(std::move(box));
 }
 
 void GroupMembersWidget::restrictUser(not_null<UserData*> user) {
diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
index 4d30bf059..c559d54d8 100644
--- a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
+++ b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
@@ -53,6 +53,56 @@ void RemoveAdmin(
 
 } // namespace
 
+base::lambda<void(
+	const MTPChannelAdminRights &oldRights,
+	const MTPChannelAdminRights &newRights)> SaveAdminCallback(
+		not_null<ChannelData*> channel,
+		not_null<UserData*> user,
+		base::lambda<void(const MTPChannelAdminRights &newRights)> onDone,
+		base::lambda<void()> onFail) {
+	return [=](
+			const MTPChannelAdminRights &oldRights,
+			const MTPChannelAdminRights &newRights) {
+		auto done = [=](const MTPUpdates &result) {
+			Auth().api().applyUpdates(result);
+			channel->applyEditAdmin(user, oldRights, newRights);
+			onDone(newRights);
+		};
+		auto fail = [=](const RPCError &error) {
+			if (MTP::isDefaultHandledError(error)) {
+				return false;
+			}
+			if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) {
+				Ui::show(
+					Box<InformBox>(PeerFloodErrorText(
+						channel->isMegagroup()
+						? PeerFloodType::InviteGroup
+						: PeerFloodType::InviteChannel)),
+					LayerOption::KeepOther);
+			} else if (error.type() == qstr("BOT_GROUPS_BLOCKED")) {
+				Ui::show(
+					Box<InformBox>(lang(lng_error_cant_add_bot)),
+					LayerOption::KeepOther);
+			} else if (error.type() == qstr("ADMINS_TOO_MUCH")) {
+				Ui::show(
+					Box<InformBox>(lang(channel->isMegagroup()
+						? lng_error_admin_limit
+						: lng_error_admin_limit_channel)),
+					LayerOption::KeepOther);
+			}
+			onFail();
+			return true;
+		};
+		MTP::send(
+			MTPchannels_EditAdmin(
+				channel->inputChannel,
+				user->inputUser,
+				newRights),
+			rpcDone(std::move(done)),
+			rpcFail(std::move(fail)));
+	};
+}
+
 ParticipantsBoxController::ParticipantsBoxController(
 	not_null<Window::Navigation*> navigation,
 	not_null<ChannelData*> channel,
@@ -717,15 +767,16 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
 	auto canEdit = (_additional.adminCanEdit.find(user) != _additional.adminCanEdit.end());
 	auto canSave = notAdmin ? _channel->canAddAdmins() : canEdit;
 	if (canSave) {
-		box->setSaveCallback([channel = _channel.get(), user, weak](const MTPChannelAdminRights &oldRights, const MTPChannelAdminRights &newRights) {
-			MTP::send(MTPchannels_EditAdmin(channel->inputChannel, user->inputUser, newRights), rpcDone([channel, user, weak, oldRights, newRights](const MTPUpdates &result) {
-				Auth().api().applyUpdates(result);
-				channel->applyEditAdmin(user, oldRights, newRights);
-				if (weak) {
-					weak->editAdminDone(user, newRights);
-				}
-			}));
-		});
+		box->setSaveCallback(SaveAdminCallback(_channel, user, [=](
+				const MTPChannelAdminRights &newRights) {
+			if (weak) {
+				weak->editAdminDone(user, newRights);
+			}
+		}, [=] {
+			if (weak && weak->_editBox) {
+				weak->_editBox->closeBox();
+			}
+		}));
 	}
 	_editBox = Ui::show(std::move(box), LayerOption::KeepOther);
 }
@@ -1389,35 +1440,16 @@ void AddParticipantBoxController::showAdmin(not_null<UserData*> user, bool sure)
 			&& (_additional.adminCanEdit.find(user) == _additional.adminCanEdit.end()));
 	auto box = Box<EditAdminBox>(_channel, user, currentRights);
 	if (!canNotEdit) {
-		box->setSaveCallback([channel = _channel.get(), user, weak](const MTPChannelAdminRights &oldRights, const MTPChannelAdminRights &newRights) {
-			MTP::send(MTPchannels_EditAdmin(channel->inputChannel, user->inputUser, newRights), rpcDone([channel, user, weak, oldRights, newRights](const MTPUpdates &result) {
-				Auth().api().applyUpdates(result);
-				channel->applyEditAdmin(user, oldRights, newRights);
-				if (weak) {
-					weak->editAdminDone(user, newRights);
-				}
-			}), rpcFail([channel, weak](const RPCError &error) {
-				if (MTP::isDefaultHandledError(error)) {
-					return false;
-				}
-				if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) {
-					Ui::show(
-						Box<InformBox>(PeerFloodErrorText(
-							channel->isMegagroup()
-								? PeerFloodType::InviteGroup
-								: PeerFloodType::InviteChannel)),
-						LayerOption::KeepOther);
-				} else if (error.type() == qstr("BOT_GROUPS_BLOCKED")) {
-					Ui::show(
-						Box<InformBox>(lang(lng_error_cant_add_bot)),
-						LayerOption::KeepOther);
-				}
-				if (weak && weak->_editBox) {
-					weak->_editBox->closeBox();
-				}
-				return true;
-			}));
-		});
+		box->setSaveCallback(SaveAdminCallback(_channel, user, [=](
+				const MTPChannelAdminRights &newRights) {
+			if (weak) {
+				weak->editAdminDone(user, newRights);
+			}
+		}, [=] {
+			if (weak && weak->_editBox) {
+				weak->_editBox->closeBox();
+			}
+		}));
 	}
 	_editBox = Ui::show(std::move(box), LayerOption::KeepOther);
 }
diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.h b/Telegram/SourceFiles/profile/profile_channel_controllers.h
index dc729e56b..9aee0f44d 100644
--- a/Telegram/SourceFiles/profile/profile_channel_controllers.h
+++ b/Telegram/SourceFiles/profile/profile_channel_controllers.h
@@ -20,6 +20,14 @@ class Navigation;
 
 namespace Profile {
 
+base::lambda<void(
+	const MTPChannelAdminRights &oldRights,
+	const MTPChannelAdminRights &newRights)> SaveAdminCallback(
+		not_null<ChannelData*> channel,
+		not_null<UserData*> user,
+		base::lambda<void(const MTPChannelAdminRights &newRights)> onDone,
+		base::lambda<void()> onFail);
+
 // Viewing admins, banned or restricted users list with search.
 class ParticipantsBoxController
 	: public PeerListController