diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp
index 9254dad2b..d043049de 100644
--- a/Telegram/SourceFiles/boxes/peer_list_box.cpp
+++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp
@@ -379,6 +379,18 @@ void PeerListRow::invalidatePixmapsCache() {
 	}
 }
 
+int PeerListRow::nameIconWidth() const {
+	return _peer->isVerified() ? st::dialogsVerifiedIcon.width() : 0;
+}
+
+void PeerListRow::paintNameIcon(
+		Painter &p,
+		int x,
+		int y,
+		int outerWidth) {
+	st::dialogsVerifiedIcon.paint(p, x, y, outerWidth);
+}
+
 void PeerListRow::paintStatusText(
 		Painter &p,
 		const style::PeerListItem &st,
@@ -997,7 +1009,7 @@ TimeMs PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) {
 	auto row = getRow(index);
 	Assert(row != nullptr);
 	row->lazyInitialize(_st.item);
-	
+
 	auto refreshStatusAt = row->refreshStatusTime();
 	if (refreshStatusAt >= 0 && ms >= refreshStatusAt) {
 		row->refreshStatus();
@@ -1029,28 +1041,44 @@ TimeMs PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) {
 
 	p.setPen(st::contactsNameFg);
 
+	auto skipRight = _st.item.photoPosition.x();
 	auto actionSize = row->actionSize();
 	auto actionMargins = actionSize.isEmpty() ? QMargins() : row->actionMargins();
 	auto &name = row->name();
 	auto namex = _st.item.namePosition.x();
-	auto namew = width() - namex - _st.item.photoPosition.x();
+	auto namew = width() - namex - skipRight;
 	if (!actionSize.isEmpty()) {
-		namew -= actionMargins.left() + actionSize.width() + actionMargins.right();
+		namew -= actionMargins.left()
+			+ actionSize.width()
+			+ actionMargins.right()
+			- skipRight;
 	}
 	auto statusw = namew;
-	if (row->needsVerifiedIcon()) {
-		auto icon = &st::dialogsVerifiedIcon;
-		namew -= icon->width();
-		icon->paint(p, namex + qMin(name.maxWidth(), namew), _st.item.namePosition.y(), width());
+	if (auto iconWidth = row->nameIconWidth()) {
+		namew -= iconWidth;
+		row->paintNameIcon(
+			p,
+			namex + qMin(name.maxWidth(), namew),
+			_st.item.namePosition.y(),
+			width());
 	}
 	auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
 	p.setPen(anim::pen(st::contactsNameFg, st::contactsNameCheckedFg, nameCheckedRatio));
 	name.drawLeftElided(p, namex, _st.item.namePosition.y(), namew, width());
 
 	if (!actionSize.isEmpty()) {
-		auto actionLeft = width() - _st.item.photoPosition.x() - actionMargins.right() - actionSize.width();
+		auto actionLeft = width()
+			- actionMargins.right()
+			- actionSize.width();
 		auto actionTop = actionMargins.top();
-		row->paintAction(p, ms, actionLeft, actionTop, width(), actionSelected);
+		row->paintAction(
+			p,
+			ms,
+			actionLeft,
+			actionTop,
+			width(),
+			selected,
+			actionSelected);
 	}
 
 	p.setFont(st::contactsStatusFont);
@@ -1377,7 +1405,7 @@ QRect PeerListContent::getActionRect(not_null<PeerListRow*> row, RowIndex index)
 		return QRect();
 	}
 	auto actionMargins = row->actionMargins();
-	auto actionRight = _st.item.photoPosition.x() + actionMargins.right();
+	auto actionRight = actionMargins.right();
 	auto actionTop = actionMargins.top();
 	auto actionLeft = width() - actionRight - actionSize.width();
 	auto rowTop = getRowTop(index);
diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h
index a60e9ba7a..19c128acd 100644
--- a/Telegram/SourceFiles/boxes/peer_list_box.h
+++ b/Telegram/SourceFiles/boxes/peer_list_box.h
@@ -86,9 +86,12 @@ public:
 	virtual ~PeerListRow();
 
 	// Box interface.
-	virtual bool needsVerifiedIcon() const {
-		return _peer->isVerified();
-	}
+	virtual int nameIconWidth() const;
+	virtual void paintNameIcon(
+		Painter &p,
+		int x,
+		int y,
+		int outerWidth);
 	virtual QSize actionSize() const {
 		return QSize();
 	}
@@ -99,7 +102,14 @@ public:
 	}
 	virtual void stopLastActionRipple() {
 	}
-	virtual void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
+	virtual void paintAction(
+		Painter &p,
+		TimeMs ms,
+		int x,
+		int y,
+		int outerWidth,
+		bool selected,
+		bool actionSelected) {
 	}
 
 	void refreshName(const style::PeerListItem &st);
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
index 3f662d5b1..0581419f9 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
@@ -128,10 +128,21 @@ QSize PeerListRowWithLink::actionSize() const {
 }
 
 QMargins PeerListRowWithLink::actionMargins() const {
-	return QMargins(st::contactsCheckPosition.x(), (st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom() - st::normalFont->height) / 2, st::contactsCheckPosition.x(), 0);
+	return QMargins(
+		st::contactsCheckPosition.x(),
+		(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom() - st::normalFont->height) / 2,
+		st::defaultPeerListItem.photoPosition.x() + st::contactsCheckPosition.x(),
+		0);
 }
 
-void PeerListRowWithLink::paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
+void PeerListRowWithLink::paintAction(
+		Painter &p,
+		TimeMs ms,
+		int x,
+		int y,
+		int outerWidth,
+		bool selected,
+		bool actionSelected) {
 	p.setFont(actionSelected ? st::linkOverFont : st::linkFont);
 	p.setPen(actionSelected ? st::defaultLinkButton.overColor : st::defaultLinkButton.color);
 	p.drawTextLeft(x, y, outerWidth, _action, _actionWidth);
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h
index 9fa705d82..55be1dbd1 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.h
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h
@@ -53,7 +53,14 @@ private:
 	void refreshActionLink();
 	QSize actionSize() const override;
 	QMargins actionMargins() const override;
-	void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) override;
+	void paintAction(
+		Painter &p,
+		TimeMs ms,
+		int x,
+		int y,
+		int outerWidth,
+		bool selected,
+		bool actionSelected) override;
 
 	QString _action;
 	int _actionWidth = 0;
diff --git a/Telegram/SourceFiles/calls/calls_box_controller.cpp b/Telegram/SourceFiles/calls/calls_box_controller.cpp
index 1f7255cb4..f2ff9e4fb 100644
--- a/Telegram/SourceFiles/calls/calls_box_controller.cpp
+++ b/Telegram/SourceFiles/calls/calls_box_controller.cpp
@@ -90,16 +90,27 @@ public:
 	void addActionRipple(QPoint point, base::lambda<void()> updateCallback) override;
 	void stopLastActionRipple() override;
 
-	bool needsVerifiedIcon() const override {
-		return false;
+	int nameIconWidth() const override {
+		return 0;
 	}
 	QSize actionSize() const override {
 		return peer()->isUser() ? QSize(st::callReDial.width, st::callReDial.height) : QSize();
 	}
 	QMargins actionMargins() const override {
-		return QMargins(0, 0, 0, 0);
+		return QMargins(
+			0,
+			0,
+			st::defaultPeerListItem.photoPosition.x(),
+			0);
 	}
-	void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) override;
+	void paintAction(
+		Painter &p,
+		TimeMs ms,
+		int x,
+		int y,
+		int outerWidth,
+		bool selected,
+		bool actionSelected) override;
 
 private:
 	void refreshStatus();
@@ -138,7 +149,14 @@ void BoxController::Row::paintStatusText(Painter &p, const style::PeerListItem &
 	PeerListRow::paintStatusText(p, st, x, y, availableWidth, outerWidth, selected);
 }
 
-void BoxController::Row::paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
+void BoxController::Row::paintAction(
+		Painter &p,
+		TimeMs ms,
+		int x,
+		int y,
+		int outerWidth,
+		bool selected,
+		bool actionSelected) {
 	auto size = actionSize();
 	if (_actionRipple) {
 		_actionRipple->paint(p, x + st::callReDial.rippleAreaPosition.x(), y + st::callReDial.rippleAreaPosition.y(), outerWidth, ms);
diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp
index 5d4777df2..281c2bea6 100644
--- a/Telegram/SourceFiles/data/data_peer.cpp
+++ b/Telegram/SourceFiles/data/data_peer.cpp
@@ -928,7 +928,8 @@ void ChannelData::setRestrictionReason(const QString &text) {
 	}
 }
 
-bool ChannelData::canNotEditLastAdmin(not_null<UserData*> user) const {
+bool ChannelData::canEditLastAdmin(not_null<UserData*> user) const {
+	// Duplicated in ParticipantsBoxController::canEditAdmin :(
 	if (mgInfo) {
 		auto i = mgInfo->lastAdmins.constFind(user);
 		if (i != mgInfo->lastAdmins.cend()) {
@@ -940,22 +941,24 @@ bool ChannelData::canNotEditLastAdmin(not_null<UserData*> user) const {
 }
 
 bool ChannelData::canEditAdmin(not_null<UserData*> user) const {
+	// Duplicated in ParticipantsBoxController::canEditAdmin :(
 	if (user->isSelf()) {
 		return false;
 	} else if (amCreator()) {
 		return true;
-	} else if (canNotEditLastAdmin(user)) {
+	} else if (!canEditLastAdmin(user)) {
 		return false;
 	}
 	return adminRights() & AdminRight::f_add_admins;
 }
 
 bool ChannelData::canRestrictUser(not_null<UserData*> user) const {
+	// Duplicated in ParticipantsBoxController::canRestrictUser :(
 	if (user->isSelf()) {
 		return false;
 	} else if (amCreator()) {
 		return true;
-	} else if (canNotEditLastAdmin(user)) {
+	} else if (!canEditLastAdmin(user)) {
 		return false;
 	}
 	return adminRights() & AdminRight::f_ban_users;
diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h
index 4d3fffa24..8fbd168b5 100644
--- a/Telegram/SourceFiles/data/data_peer.h
+++ b/Telegram/SourceFiles/data/data_peer.h
@@ -1096,7 +1096,7 @@ private:
 	void flagsUpdated(MTPDchannel::Flags diff);
 	void fullFlagsUpdated(MTPDchannelFull::Flags diff);
 
-	bool canNotEditLastAdmin(not_null<UserData*> user) const;
+	bool canEditLastAdmin(not_null<UserData*> user) const;
 
 	Flags _flags = Flags(MTPDchannel_ClientFlag::f_forbidden | 0);
 	FullFlags _fullFlags;
diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style
index 518fb3237..fe494253c 100644
--- a/Telegram/SourceFiles/info/info.style
+++ b/Telegram/SourceFiles/info/info.style
@@ -478,6 +478,27 @@ infoMembersCancelSearch: CrossButton {
 }
 infoMembersSearchTop: 15px;
 
+infoMembersCreatorIcon: icon {{
+	"profile_admin_star",
+	profileAdminStartFg,
+	point(4px, 3px)
+}};
+infoMembersAdminIcon: icon {{
+	"profile_admin_star",
+	profileOtherAdminStarFg,
+	point(4px, 3px)
+}};
+infoMembersRemoveIcon: icon {{
+	"simple_close",
+	menuIconFg
+}};
+infoMembersRemoveIconOver: icon {{
+	"simple_close",
+	menuIconFgOver
+}};
+infoMembersAdminIconMarigns: margins(10px, 18px, 10px, 10px);
+infoMembersRemoveIconMargins: margins(10px, 12px, 12px, 10px);
+
 infoMediaHeaderStyle: TextStyle(semiboldTextStyle) {
 }
 infoMediaHeaderHeight: 28px;
diff --git a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp
index 95b5edfd4..0a4b562a3 100644
--- a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp
+++ b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp
@@ -31,6 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "observer_peer.h"
 #include "boxes/confirm_box.h"
 #include "window/window_controller.h"
+#include "styles/style_info.h"
 
 namespace Info {
 namespace Profile {
@@ -49,6 +50,7 @@ public:
 
 	void prepare() override;
 	void rowClicked(not_null<PeerListRow*> row) override;
+	void rowActionClicked(not_null<PeerListRow*> row) override;
 	Ui::PopupMenu *rowContextMenu(
 		not_null<PeerListRow*> row) override;
 
@@ -63,15 +65,20 @@ public:
 	void restoreState(std::unique_ptr<PeerListState> state) override;
 
 private:
+	using Rights = MemberListRow::Rights;
+	using Type = MemberListRow::Type;
 	struct SavedState : SavedStateBase {
 		rpl::lifetime lifetime;
 	};
 	void rebuildRows();
+	void rebuildRowTypes();
 	void refreshOnlineCount();
-	std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
+	std::unique_ptr<PeerListRow> createRow(
+		not_null<UserData*> user);
 	void sortByOnline();
 	void sortByOnlineDelayed();
 	void removeMember(not_null<UserData*> user);
+	Type computeType(not_null<UserData*> user);
 
 	not_null<Window::Controller*> _window;
 	not_null<ChatData*> _chat;
@@ -101,12 +108,18 @@ void ChatMembersController::prepare() {
 	}
 	using UpdateFlag = Notify::PeerUpdate::Flag;
 	subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
-		UpdateFlag::MembersChanged | UpdateFlag::UserOnlineChanged,
+		UpdateFlag::MembersChanged
+		| UpdateFlag::UserOnlineChanged
+		| UpdateFlag::AdminsChanged,
 		[this](const Notify::PeerUpdate &update) {
 			if (update.flags & UpdateFlag::MembersChanged) {
 				if (update.peer == _chat) {
 					rebuildRows();
 				}
+			} else if (update.flags & UpdateFlag::AdminsChanged) {
+				if (update.peer == _chat) {
+					rebuildRowTypes();
+				}
 			} else if (update.flags & UpdateFlag::UserOnlineChanged) {
 				if (auto row = delegate()->peerListFindRow(
 					update.peer->id)) {
@@ -187,6 +200,16 @@ void ChatMembersController::rebuildRows() {
 	delegate()->peerListRefreshRows();
 }
 
+void ChatMembersController::rebuildRowTypes() {
+	auto count = delegate()->peerListFullRowsCount();
+	for (auto i = 0; i != count; ++i) {
+		auto row = static_cast<MemberListRow*>(
+			delegate()->peerListRowAt(i).get());
+		row->setType(computeType(row->user()));
+	}
+	delegate()->peerListRefreshRows();
+}
+
 void ChatMembersController::refreshOnlineCount() {
 	auto now = unixtime();
 	auto left = 0, right = delegate()->peerListFullRowsCount();
@@ -212,29 +235,53 @@ std::unique_ptr<PeerListRow> ChatMembersController::createRestoredRow(
 
 std::unique_ptr<PeerListRow> ChatMembersController::createRow(
 		not_null<UserData*> user) {
-	return std::make_unique<PeerListRow>(user);
+	return std::make_unique<MemberListRow>(user, computeType(user));
+}
+
+auto ChatMembersController::computeType(
+		not_null<UserData*> user) -> Type {
+	auto isCreator = (peerFromUser(_chat->creator) == user->id);
+	auto isAdmin = _chat->adminsEnabled()
+		&& _chat->admins.contains(user);
+	auto canRemove = [&] {
+		if (user->isSelf()) {
+			return false;
+		} else if (_chat->amCreator()) {
+			return true;
+		} else if (isAdmin || isCreator) {
+			return false;
+		} else if (_chat->amAdmin()) {
+			return true;
+		} else if (_chat->invitedByMe.contains(user)) {
+			return true;
+		}
+		return false;
+	}();
+
+	auto result = Type();
+	result.rights = isCreator
+		? Rights::Creator
+		: isAdmin
+		? Rights::Admin
+		: Rights::Normal;
+	result.canRemove = canRemove;
+	return result;
 }
 
 void ChatMembersController::rowClicked(not_null<PeerListRow*> row) {
 	_window->showPeerInfo(row->peer());
 }
 
+void ChatMembersController::rowActionClicked(
+		not_null<PeerListRow*> row) {
+	removeMember(row->peer()->asUser());
+}
+
 Ui::PopupMenu *ChatMembersController::rowContextMenu(
 		not_null<PeerListRow*> row) {
-	Expects(row->peer()->isUser());
-
-	auto user = row->peer()->asUser();
-	auto isCreator = (peerFromUser(_chat->creator) == user->id);
-	auto isAdmin = _chat->adminsEnabled() && _chat->admins.contains(user);
-	auto canRemoveMember = (user->id == Auth().userPeerId())
-		? false
-		: _chat->amCreator()
-		? true
-		: (_chat->amAdmin() && !isCreator && !isAdmin)
-		? true
-		: (_chat->invitedByMe.contains(user) && !isCreator && !isAdmin)
-		? true
-		: false;
+	auto my = static_cast<MemberListRow*>(row.get());
+	auto user = my->user();
+	auto canRemoveMember = my->canRemove();
 
 	auto result = new Ui::PopupMenu(nullptr);
 	result->addAction(
@@ -267,6 +314,64 @@ void ChatMembersController::removeMember(not_null<UserData*> user) {
 
 } // namespace
 
+MemberListRow::MemberListRow(
+	not_null<UserData*> user,
+	Type type)
+: PeerListRow(user)
+, _type(type) {
+}
+
+void MemberListRow::setType(Type type) {
+	_type = type;
+}
+
+QSize MemberListRow::actionSize() const {
+	return canRemove()
+		? QRect(
+			QPoint(),
+			st::infoMembersRemoveIcon.size()).marginsAdded(
+				st::infoMembersRemoveIconMargins).size()
+		: QSize();
+}
+
+void MemberListRow::paintAction(
+		Painter &p,
+		TimeMs ms,
+		int x,
+		int y,
+		int outerWidth,
+		bool selected,
+		bool actionSelected) {
+	if (_type.canRemove && selected) {
+		x += st::infoMembersRemoveIconMargins.left();
+		y += st::infoMembersRemoveIconMargins.top();
+		(actionSelected
+			? st::infoMembersRemoveIconOver
+			: st::infoMembersRemoveIcon).paint(p, x, y, outerWidth);
+	}
+}
+
+int MemberListRow::nameIconWidth() const {
+	return (_type.rights == Rights::Admin)
+		? st::infoMembersAdminIcon.width()
+		: (_type.rights == Rights::Creator)
+		? st::infoMembersCreatorIcon.width()
+		: 0;
+}
+
+void MemberListRow::paintNameIcon(
+		Painter &p,
+		int x,
+		int y,
+		int outerWidth) {
+	auto icon = [&] {
+		return (_type.rights == Rights::Admin)
+			? &st::infoMembersAdminIcon
+			: &st::infoMembersCreatorIcon;
+	}();
+	icon->paint(p, x, y, outerWidth);
+}
+
 std::unique_ptr<PeerListController> CreateMembersController(
 		not_null<Window::Controller*> window,
 		not_null<PeerData*> peer) {
diff --git a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h
index 6998bca01..56762d9fe 100644
--- a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h
+++ b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-class PeerListController;
+#include "boxes/peer_list_box.h"
 
 namespace Window {
 class Controller;
@@ -29,6 +29,49 @@ class Controller;
 namespace Info {
 namespace Profile {
 
+class MemberListRow final : public PeerListRow {
+public:
+	enum class Rights {
+		Normal,
+		Admin,
+		Creator,
+	};
+	struct Type {
+		Rights rights;
+		bool canRemove = false;
+	};
+
+	MemberListRow(not_null<UserData*> user, Type type);
+
+	void setType(Type type);
+	QSize actionSize() const override;
+	void paintAction(
+		Painter &p,
+		TimeMs ms,
+		int x,
+		int y,
+		int outerWidth,
+		bool selected,
+		bool actionSelected) override;
+	int nameIconWidth() const override;
+	void paintNameIcon(
+		Painter &p,
+		int x,
+		int y,
+		int outerWidth) override;
+
+	not_null<UserData*> user() const {
+		return peer()->asUser();
+	}
+	bool canRemove() const {
+		return _type.canRemove;
+	}
+
+private:
+	Type _type;
+
+};
+
 std::unique_ptr<PeerListController> CreateMembersController(
 	not_null<Window::Controller*> window,
 	not_null<PeerData*> peer);
diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
index 986481a76..fe08972d5 100644
--- a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
+++ b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
@@ -545,6 +545,38 @@ void ParticipantsBoxController::rowActionClicked(not_null<PeerListRow*> row) {
 	}
 }
 
+bool ParticipantsBoxController::canEditAdminByRights(
+		not_null<UserData*> user) const {
+	if (_additional.adminCanEdit.find(user) != _additional.adminCanEdit.cend()) {
+		return true;
+	}
+	return (user != _additional.creator);
+}
+
+bool ParticipantsBoxController::canEditAdmin(
+		not_null<UserData*> user) const {
+	if (user->isSelf()) {
+		return false;
+	} else if (_channel->amCreator()) {
+		return true;
+	} else if (!canEditAdminByRights(user)) {
+		return false;
+	}
+	return _channel->adminRights() & ChannelAdminRight::f_add_admins;
+}
+
+bool ParticipantsBoxController::canRestrictUser(
+		not_null<UserData*> user) const {
+	if (user->isSelf()) {
+		return false;
+	} else if (_channel->amCreator()) {
+		return true;
+	} else if (!canEditAdminByRights(user)) {
+		return false;
+	}
+	return _channel->adminRights() & ChannelAdminRight::f_ban_users;
+}
+
 Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
 		not_null<PeerListRow*> row) {
 	Expects(row->peer()->isUser());
@@ -558,7 +590,7 @@ Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
 				weak->_window->showPeerInfo(user);
 			}
 		});
-	if (_channel->canEditAdmin(user)) {
+	if (canEditAdmin(user)) {
 		auto it = _additional.adminRights.find(user);
 		auto isCreator = (user == _additional.creator);
 		auto notAdmin = !isCreator && (it == _additional.adminRights.cend());
@@ -573,7 +605,7 @@ Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
 				}
 			});
 	}
-	if (_channel->canRestrictUser(user)) {
+	if (canRestrictUser(user)) {
 		result->addAction(
 			lang(lng_context_restrict_user),
 			[weak = base::make_weak_unique(this), user]{
@@ -617,7 +649,9 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
 	_editBox = Ui::show(std::move(box), LayerOption::KeepOther);
 }
 
-void ParticipantsBoxController::editAdminDone(not_null<UserData*> user, const MTPChannelAdminRights &rights) {
+void ParticipantsBoxController::editAdminDone(
+		not_null<UserData*> user,
+		const MTPChannelAdminRights &rights) {
 	if (_editBox) {
 		_editBox->closeBox();
 	}
@@ -646,6 +680,7 @@ void ParticipantsBoxController::editAdminDone(not_null<UserData*> user, const MT
 			removeRow(user);
 		}
 	}
+	recomputeTypeFor(user);
 	delegate()->peerListRefreshRows();
 }
 
@@ -714,6 +749,7 @@ void ParticipantsBoxController::editRestrictedDone(not_null<UserData*> user, con
 			}
 		}
 	}
+	recomputeTypeFor(user);
 	delegate()->peerListRefreshRows();
 }
 
@@ -750,6 +786,7 @@ void ParticipantsBoxController::removeKicked(not_null<PeerListRow*> row, not_nul
 
 bool ParticipantsBoxController::appendRow(not_null<UserData*> user) {
 	if (delegate()->peerListFindRow(user->id)) {
+		recomputeTypeFor(user);
 		return false;
 	}
 	delegate()->peerListAppendRow(createRow(user));
@@ -761,6 +798,7 @@ bool ParticipantsBoxController::appendRow(not_null<UserData*> user) {
 
 bool ParticipantsBoxController::prependRow(not_null<UserData*> user) {
 	if (auto row = delegate()->peerListFindRow(user->id)) {
+		recomputeTypeFor(user);
 		refreshCustomStatus(row);
 		if (_role == Role::Admins) {
 			// Perhaps we've added a new admin from search.
@@ -792,7 +830,11 @@ bool ParticipantsBoxController::removeRow(not_null<UserData*> user) {
 	return false;
 }
 
-std::unique_ptr<PeerListRow> ParticipantsBoxController::createRow(not_null<UserData*> user) const {
+std::unique_ptr<PeerListRow> ParticipantsBoxController::createRow(
+		not_null<UserData*> user) const {
+	if (_role == Role::Profile) {
+		return std::make_unique<Row>(user, computeType(user));
+	}
 	auto row = std::make_unique<PeerListRowWithLink>(user);
 	refreshCustomStatus(row.get());
 	if (_role == Role::Restricted || (_role == Role::Admins && _additional.adminCanEdit.find(user) != _additional.adminCanEdit.cend())) {
@@ -809,6 +851,31 @@ std::unique_ptr<PeerListRow> ParticipantsBoxController::createRow(not_null<UserD
 	return std::move(row);
 }
 
+auto ParticipantsBoxController::computeType(
+		not_null<UserData*> user) const -> Type {
+	auto isCreator = (user == _additional.creator);
+	auto isAdmin = (_additional.adminRights.find(user) != _additional.adminRights.cend());
+
+	auto result = Type();
+	result.rights = isCreator
+		? Rights::Creator
+		: isAdmin
+		? Rights::Admin
+		: Rights::Normal;
+	result.canRemove = canRestrictUser(user);
+	return result;
+}
+
+void ParticipantsBoxController::recomputeTypeFor(
+		not_null<UserData*> user) {
+	if (_role != Role::Profile) {
+		return;
+	}
+	if (auto row = delegate()->peerListFindRow(user->id)) {
+		static_cast<Row*>(row)->setType(computeType(user));
+	}
+}
+
 void ParticipantsBoxController::refreshCustomStatus(not_null<PeerListRow*> row) const {
 	auto user = row->peer()->asUser();
 	if (_role == Role::Admins) {
@@ -1209,7 +1276,9 @@ void AddParticipantBoxController::showAdmin(not_null<UserData*> user, bool sure)
 	_editBox = Ui::show(std::move(box), LayerOption::KeepOther);
 }
 
-void AddParticipantBoxController::editAdminDone(not_null<UserData*> user, const MTPChannelAdminRights &rights) {
+void AddParticipantBoxController::editAdminDone(
+		not_null<UserData*> user,
+		const MTPChannelAdminRights &rights) {
 	if (_editBox) _editBox->closeBox();
 	_additional.restrictedRights.erase(user);
 	_additional.restrictedBy.erase(user);
@@ -1291,7 +1360,9 @@ void AddParticipantBoxController::restrictUserSure(not_null<UserData*> user, con
 	}));
 }
 
-void AddParticipantBoxController::editRestrictedDone(not_null<UserData*> user, const MTPChannelBannedRights &rights) {
+void AddParticipantBoxController::editRestrictedDone(
+		not_null<UserData*> user,
+		const MTPChannelBannedRights &rights) {
 	if (_editBox) _editBox->closeBox();
 	_additional.adminRights.erase(user);
 	_additional.adminCanEdit.erase(user);
@@ -1380,7 +1451,10 @@ std::unique_ptr<PeerListRow> AddParticipantBoxController::createRow(not_null<Use
 }
 
 template <typename Callback>
-void AddParticipantBoxController::HandleParticipant(const MTPChannelParticipant &participant, not_null<Additional*> additional, Callback callback) {
+void AddParticipantBoxController::HandleParticipant(
+		const MTPChannelParticipant &participant,
+		not_null<Additional*> additional,
+		Callback callback) {
 	switch (participant.type()) {
 	case mtpc_channelParticipantAdmin: {
 		auto &admin = participant.c_channelParticipantAdmin();
diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.h b/Telegram/SourceFiles/profile/profile_channel_controllers.h
index 174eb51b1..0c986f49f 100644
--- a/Telegram/SourceFiles/profile/profile_channel_controllers.h
+++ b/Telegram/SourceFiles/profile/profile_channel_controllers.h
@@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "mtproto/sender.h"
 #include "base/timer.h"
 #include "base/weak_unique_ptr.h"
+#include "info/profile/info_profile_members_controllers.h"
 
 namespace Window {
 class Controller;
@@ -102,6 +103,9 @@ protected:
 	virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const;
 
 private:
+	using Row = Info::Profile::MemberListRow;
+	using Type = Row::Type;
+	using Rights = Row::Rights;
 	struct SavedState : SavedStateBase {
 		std::unique_ptr<PeerListSearchController::SavedStateBase> searchState;
 		int offset = 0;
@@ -110,7 +114,7 @@ private:
 		Additional additional;
 		rpl::lifetime lifetime;
 	};
-	
+
 	static std::unique_ptr<PeerListSearchController> CreateSearchController(
 		not_null<ChannelData*> channel,
 		Role role,
@@ -133,6 +137,11 @@ private:
 	void refreshCustomStatus(not_null<PeerListRow*> row) const;
 	bool feedMegagroupLastParticipants();
 	void refreshOnlineCount();
+	Type computeType(not_null<UserData*> user) const;
+	void recomputeTypeFor(not_null<UserData*> user);
+	bool canEditAdmin(not_null<UserData*> user) const;
+	bool canRestrictUser(not_null<UserData*> user) const;
+	bool canEditAdminByRights(not_null<UserData*> user) const;
 
 	not_null<Window::Controller*> _window;
 	not_null<ChannelData*> _channel;