mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Add 'X' and admin star in group info members.
This commit is contained in:
parent
5f0ba48309
commit
1871425b2d
12 changed files with 381 additions and 52 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue