[Improvement] Admin ranks
This commit is contained in:
parent
dec9de947c
commit
51808da2be
14 changed files with 276 additions and 43 deletions
|
|
@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
|
||||||
#include <rpl/range.h>
|
#include <rpl/range.h>
|
||||||
|
|
||||||
|
|
@ -633,9 +634,37 @@ void PeerListRow::invalidatePixmapsCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PeerListRow::nameIconWidth() const {
|
int PeerListRow::nameIconWidth() const {
|
||||||
return (special() || !_peer->isVerified())
|
if (special()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto hasCreatorRights = false;
|
||||||
|
auto hasAdminRights = false;
|
||||||
|
if (const auto chat = _peer->asChat()) {
|
||||||
|
if (chat->amCreator()) {
|
||||||
|
hasCreatorRights = true;
|
||||||
|
hasAdminRights = true;
|
||||||
|
} else if (chat->hasAdminRights()) {
|
||||||
|
hasAdminRights = true;
|
||||||
|
}
|
||||||
|
} else if (const auto channel = _peer->asChannel()) {
|
||||||
|
if (channel->amCreator()) {
|
||||||
|
hasCreatorRights = true;
|
||||||
|
hasAdminRights = true;
|
||||||
|
} else if (channel->hasAdminRights()) {
|
||||||
|
hasAdminRights = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return special()
|
||||||
? 0
|
? 0
|
||||||
: st::dialogsVerifiedIcon.width();
|
: (_peer->isVerified()
|
||||||
|
? st::dialogsVerifiedIcon.width()
|
||||||
|
: 0)
|
||||||
|
+ (hasCreatorRights
|
||||||
|
? st::infoMembersCreatorIcon.width()
|
||||||
|
: hasAdminRights
|
||||||
|
? st::infoMembersAdminIcon.width()
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerListRow::paintNameIcon(
|
void PeerListRow::paintNameIcon(
|
||||||
|
|
@ -644,7 +673,43 @@ void PeerListRow::paintNameIcon(
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
bool selected) {
|
bool selected) {
|
||||||
st::dialogsVerifiedIcon.paint(p, x, y, outerWidth);
|
if (special()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto hasCreatorRights = false;
|
||||||
|
auto hasAdminRights = false;
|
||||||
|
if (const auto chat = _peer->asChat()) {
|
||||||
|
if (chat->amCreator()) {
|
||||||
|
hasCreatorRights = true;
|
||||||
|
hasAdminRights = true;
|
||||||
|
} else if (chat->hasAdminRights()) {
|
||||||
|
hasAdminRights = true;
|
||||||
|
}
|
||||||
|
} else if (const auto channel = _peer->asChannel()) {
|
||||||
|
if (channel->amCreator()) {
|
||||||
|
hasCreatorRights = true;
|
||||||
|
hasAdminRights = true;
|
||||||
|
} else if (channel->hasAdminRights()) {
|
||||||
|
hasAdminRights = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto icon = [&] {
|
||||||
|
return hasCreatorRights
|
||||||
|
? (selected
|
||||||
|
? &st::infoMembersCreatorIconOver
|
||||||
|
: &st::infoMembersCreatorIcon)
|
||||||
|
: (selected
|
||||||
|
? &st::infoMembersAdminIconOver
|
||||||
|
: &st::infoMembersAdminIcon);
|
||||||
|
}();
|
||||||
|
if (_peer->isVerified()) {
|
||||||
|
st::dialogsVerifiedIcon.paint(p, x, y, outerWidth);
|
||||||
|
}
|
||||||
|
if (hasAdminRights) {
|
||||||
|
icon->paint(p, x + (_peer->isVerified() ? st::dialogsVerifiedIcon.width() : 0 ), y, outerWidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerListRow::paintStatusText(
|
void PeerListRow::paintStatusText(
|
||||||
|
|
@ -662,6 +727,10 @@ void PeerListRow::paintStatusText(
|
||||||
_status.drawLeftElided(p, x, y, availableWidth, outerWidth);
|
_status.drawLeftElided(p, x, y, availableWidth, outerWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PeerListRow::hasAction() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename MaskGenerator, typename UpdateCallback>
|
template <typename MaskGenerator, typename UpdateCallback>
|
||||||
void PeerListRow::addRipple(const style::PeerListItem &st, MaskGenerator &&maskGenerator, QPoint point, UpdateCallback &&updateCallback) {
|
void PeerListRow::addRipple(const style::PeerListItem &st, MaskGenerator &&maskGenerator, QPoint point, UpdateCallback &&updateCallback) {
|
||||||
if (!_ripple) {
|
if (!_ripple) {
|
||||||
|
|
@ -674,6 +743,18 @@ void PeerListRow::addRipple(const style::PeerListItem &st, MaskGenerator &&maskG
|
||||||
_ripple->add(point);
|
_ripple->add(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PeerListRow::adminRankWidth() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerListRow::paintAdminRank(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected) {
|
||||||
|
}
|
||||||
|
|
||||||
void PeerListRow::stopLastRipple() {
|
void PeerListRow::stopLastRipple() {
|
||||||
if (_ripple) {
|
if (_ripple) {
|
||||||
_ripple->lastStop();
|
_ripple->lastStop();
|
||||||
|
|
@ -1538,20 +1619,22 @@ crl::time PeerListContent::paintRow(
|
||||||
p.setPen(st::contactsNameFg);
|
p.setPen(st::contactsNameFg);
|
||||||
|
|
||||||
auto skipRight = _st.item.photoPosition.x();
|
auto skipRight = _st.item.photoPosition.x();
|
||||||
auto rightActionSize = row->rightActionSize();
|
auto rightActionSize = !row->rightActionSize().isEmpty()
|
||||||
auto rightActionMargins = rightActionSize.isEmpty()
|
&& (row->placeholderSize().isEmpty()
|
||||||
? QMargins()
|
|| selected)
|
||||||
: row->rightActionMargins();
|
? row->rightActionSize()
|
||||||
|
: row->placeholderSize();
|
||||||
|
auto rightActionMargins = rightActionSize.isEmpty() ? QMargins() : row->rightActionMargins();
|
||||||
auto &name = row->name();
|
auto &name = row->name();
|
||||||
auto namex = _st.item.namePosition.x();
|
auto namex = _st.item.namePosition.x();
|
||||||
auto namew = outerWidth - namex - skipRight;
|
auto namew = outerWidth - namex - skipRight;
|
||||||
|
auto statusw = namew;
|
||||||
if (!rightActionSize.isEmpty()) {
|
if (!rightActionSize.isEmpty()) {
|
||||||
namew -= rightActionMargins.left()
|
statusw -= rightActionMargins.left()
|
||||||
+ rightActionSize.width()
|
+ rightActionSize.width()
|
||||||
+ rightActionMargins.right()
|
+ rightActionMargins.right()
|
||||||
- skipRight;
|
- skipRight;
|
||||||
}
|
}
|
||||||
auto statusw = namew;
|
|
||||||
if (auto iconWidth = row->nameIconWidth()) {
|
if (auto iconWidth = row->nameIconWidth()) {
|
||||||
namew -= iconWidth;
|
namew -= iconWidth;
|
||||||
row->paintNameIcon(
|
row->paintNameIcon(
|
||||||
|
|
@ -1561,6 +1644,17 @@ crl::time PeerListContent::paintRow(
|
||||||
width(),
|
width(),
|
||||||
selected);
|
selected);
|
||||||
}
|
}
|
||||||
|
if (auto adminRankWidth = row->adminRankWidth()) {
|
||||||
|
namew -= adminRankWidth + skipRight;
|
||||||
|
auto rankx = width() - adminRankWidth - skipRight;
|
||||||
|
p.setFont(st::normalFont);
|
||||||
|
row->paintAdminRank(
|
||||||
|
p,
|
||||||
|
rankx,
|
||||||
|
_st.item.namePosition.y(),
|
||||||
|
width(),
|
||||||
|
selected);
|
||||||
|
}
|
||||||
auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
|
auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
|
||||||
p.setPen(anim::pen(_st.item.nameFg, _st.item.nameFgChecked, nameCheckedRatio));
|
p.setPen(anim::pen(_st.item.nameFg, _st.item.nameFgChecked, nameCheckedRatio));
|
||||||
name.drawLeftElided(p, namex, _st.item.namePosition.y(), namew, width());
|
name.drawLeftElided(p, namex, _st.item.namePosition.y(), namew, width());
|
||||||
|
|
|
||||||
|
|
@ -101,10 +101,20 @@ public:
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
bool selected);
|
bool selected);
|
||||||
|
virtual int adminRankWidth() const;
|
||||||
|
virtual void paintAdminRank(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected);
|
||||||
|
|
||||||
virtual QSize rightActionSize() const {
|
virtual QSize rightActionSize() const {
|
||||||
return QSize();
|
return QSize();
|
||||||
}
|
}
|
||||||
|
virtual QSize placeholderSize() const {
|
||||||
|
return QSize();
|
||||||
|
}
|
||||||
virtual QMargins rightActionMargins() const {
|
virtual QMargins rightActionMargins() const {
|
||||||
return QMargins();
|
return QMargins();
|
||||||
}
|
}
|
||||||
|
|
@ -231,6 +241,8 @@ public:
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
bool selected);
|
bool selected);
|
||||||
|
|
||||||
|
virtual bool hasAction();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool isInitialized() const {
|
bool isInitialized() const {
|
||||||
return _initialized;
|
return _initialized;
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,16 @@ void PeerListRowWithLink::setActionLink(const QString &action) {
|
||||||
refreshActionLink();
|
refreshActionLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PeerListRowWithLink::setActionPlaceholder(const QString &placeholder, bool active) {
|
||||||
|
_actionPlaceholder = placeholder;
|
||||||
|
_actionPlaceholderActive = active;
|
||||||
|
refreshActionLink();
|
||||||
|
}
|
||||||
|
|
||||||
void PeerListRowWithLink::refreshActionLink() {
|
void PeerListRowWithLink::refreshActionLink() {
|
||||||
if (!isInitialized()) return;
|
if (!isInitialized()) return;
|
||||||
_actionWidth = _action.isEmpty() ? 0 : st::normalFont->width(_action);
|
_actionWidth = _action.isEmpty() ? 0 : st::normalFont->width(_action);
|
||||||
|
_actionPlaceholderWidth = _actionPlaceholder.isEmpty() ? 0 : st::normalFont->width(_actionPlaceholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerListRowWithLink::lazyInitialize(const style::PeerListItem &st) {
|
void PeerListRowWithLink::lazyInitialize(const style::PeerListItem &st) {
|
||||||
|
|
@ -156,10 +163,18 @@ void PeerListRowWithLink::lazyInitialize(const style::PeerListItem &st) {
|
||||||
refreshActionLink();
|
refreshActionLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PeerListRowWithLink::hasAction() {
|
||||||
|
return !_action.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
QSize PeerListRowWithLink::rightActionSize() const {
|
QSize PeerListRowWithLink::rightActionSize() const {
|
||||||
return QSize(_actionWidth, st::normalFont->height);
|
return QSize(_actionWidth, st::normalFont->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize PeerListRowWithLink::placeholderSize() const {
|
||||||
|
return QSize(_actionPlaceholderWidth, st::normalFont->height);
|
||||||
|
}
|
||||||
|
|
||||||
QMargins PeerListRowWithLink::rightActionMargins() const {
|
QMargins PeerListRowWithLink::rightActionMargins() const {
|
||||||
return QMargins(
|
return QMargins(
|
||||||
st::contactsCheckPosition.x(),
|
st::contactsCheckPosition.x(),
|
||||||
|
|
@ -175,9 +190,45 @@ void PeerListRowWithLink::rightActionPaint(
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
bool selected,
|
bool selected,
|
||||||
bool actionSelected) {
|
bool actionSelected) {
|
||||||
p.setFont(actionSelected ? st::linkOverFont : st::linkFont);
|
if (!_action.isEmpty() && ((_actionPlaceholder.isEmpty() && _adminRank.isEmpty()) || selected)) {
|
||||||
p.setPen(actionSelected ? st::defaultLinkButton.overColor : st::defaultLinkButton.color);
|
p.setFont(actionSelected ? st::linkOverFont : st::linkFont);
|
||||||
p.drawTextLeft(x, y, outerWidth, _action, _actionWidth);
|
p.setPen(actionSelected ? st::defaultLinkButton.overColor : st::defaultLinkButton.color);
|
||||||
|
p.drawTextLeft(x, y, outerWidth, _action, _actionWidth);
|
||||||
|
} else {
|
||||||
|
p.setFont(st::linkFont);
|
||||||
|
p.setPen(_actionPlaceholderActive
|
||||||
|
? st::defaultPeerListItem.statusFgActive
|
||||||
|
: selected
|
||||||
|
? st::defaultPeerListItem.statusFgOver
|
||||||
|
: st::defaultPeerListItem.statusFg);
|
||||||
|
p.drawTextLeft(x, y, outerWidth, _actionPlaceholder, _actionPlaceholderWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerListRowWithLink::setAdminRank(const QString &rank, bool isCreator) {
|
||||||
|
_adminRank = rank;
|
||||||
|
_isCreator = isCreator;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PeerListRowWithLink::adminRankWidth() const {
|
||||||
|
return st::normalFont->width(_adminRank);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerListRowWithLink::paintAdminRank(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected) {
|
||||||
|
if (hasAction() && selected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p.setPen(_isCreator
|
||||||
|
? st::defaultPeerListItem.statusFgActive
|
||||||
|
: selected
|
||||||
|
? st::defaultPeerListItem.statusFgOver
|
||||||
|
: st::defaultPeerListItem.statusFg);
|
||||||
|
p.drawTextLeft(x, y, outerWidth, _adminRank, adminRankWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerListGlobalSearchController::PeerListGlobalSearchController(
|
PeerListGlobalSearchController::PeerListGlobalSearchController(
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,24 @@ public:
|
||||||
using PeerListRow::PeerListRow;
|
using PeerListRow::PeerListRow;
|
||||||
|
|
||||||
void setActionLink(const QString &action);
|
void setActionLink(const QString &action);
|
||||||
|
void setActionPlaceholder(const QString &placeholder, bool active = false);
|
||||||
|
|
||||||
void lazyInitialize(const style::PeerListItem &st) override;
|
void lazyInitialize(const style::PeerListItem &st) override;
|
||||||
|
bool hasAction() override;
|
||||||
|
|
||||||
|
void setAdminRank(const QString &rank, bool isCreator = false);
|
||||||
|
int adminRankWidth() const override;
|
||||||
|
void paintAdminRank(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refreshActionLink();
|
void refreshActionLink();
|
||||||
QSize rightActionSize() const override;
|
QSize rightActionSize() const override;
|
||||||
|
QSize placeholderSize() const override;
|
||||||
QMargins rightActionMargins() const override;
|
QMargins rightActionMargins() const override;
|
||||||
void rightActionPaint(
|
void rightActionPaint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
|
@ -59,8 +71,13 @@ private:
|
||||||
bool actionSelected) override;
|
bool actionSelected) override;
|
||||||
|
|
||||||
QString _action;
|
QString _action;
|
||||||
|
QString _actionPlaceholder;
|
||||||
|
bool _actionPlaceholderActive = false;
|
||||||
int _actionWidth = 0;
|
int _actionWidth = 0;
|
||||||
|
int _actionPlaceholderWidth = 0;
|
||||||
|
|
||||||
|
QString _adminRank;
|
||||||
|
bool _isCreator = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PeerListGlobalSearchController : public PeerListSearchController {
|
class PeerListGlobalSearchController : public PeerListSearchController {
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public:
|
||||||
|
|
||||||
template <typename Widget>
|
template <typename Widget>
|
||||||
Widget *addControl(object_ptr<Widget> widget, QMargins margin);
|
Widget *addControl(object_ptr<Widget> widget, QMargins margin);
|
||||||
|
void setCustomStatus(const QString &status);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int resizeGetHeight(int newWidth) override;
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
@ -72,6 +73,7 @@ private:
|
||||||
Ui::Text::String _userName;
|
Ui::Text::String _userName;
|
||||||
bool _hasAdminRights = false;
|
bool _hasAdminRights = false;
|
||||||
object_ptr<Ui::VerticalLayout> _rows;
|
object_ptr<Ui::VerticalLayout> _rows;
|
||||||
|
QString _customStatus;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -109,6 +111,10 @@ Widget *EditParticipantBox::Inner::addControl(
|
||||||
return _rows->add(std::move(widget), margin);
|
return _rows->add(std::move(widget), margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditParticipantBox::Inner::setCustomStatus(const QString &status) {
|
||||||
|
_customStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
int EditParticipantBox::Inner::resizeGetHeight(int newWidth) {
|
int EditParticipantBox::Inner::resizeGetHeight(int newWidth) {
|
||||||
_userPhoto->moveToLeft(
|
_userPhoto->moveToLeft(
|
||||||
st::rightsPhotoMargin.left(),
|
st::rightsPhotoMargin.left(),
|
||||||
|
|
@ -138,6 +144,10 @@ void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) {
|
||||||
namew,
|
namew,
|
||||||
width());
|
width());
|
||||||
const auto statusText = [&] {
|
const auto statusText = [&] {
|
||||||
|
if (!_customStatus.isEmpty()) {
|
||||||
|
return _customStatus;
|
||||||
|
}
|
||||||
|
|
||||||
if (_user->isBot()) {
|
if (_user->isBot()) {
|
||||||
const auto seesAllMessages = _user->botInfo->readsAllHistory
|
const auto seesAllMessages = _user->botInfo->readsAllHistory
|
||||||
|| _hasAdminRights;
|
|| _hasAdminRights;
|
||||||
|
|
@ -166,6 +176,13 @@ EditParticipantBox::EditParticipantBox(
|
||||||
, _hasAdminRights(hasAdminRights) {
|
, _hasAdminRights(hasAdminRights) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditParticipantBox::setCustomStatus(const QString &status) {
|
||||||
|
_customStatus = status;
|
||||||
|
if (_inner) {
|
||||||
|
_inner->setCustomStatus(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditParticipantBox::prepare() {
|
void EditParticipantBox::prepare() {
|
||||||
_inner = setInnerWidget(object_ptr<Inner>(
|
_inner = setInnerWidget(object_ptr<Inner>(
|
||||||
this,
|
this,
|
||||||
|
|
@ -173,6 +190,7 @@ void EditParticipantBox::prepare() {
|
||||||
_user,
|
_user,
|
||||||
hasAdminRights()));
|
hasAdminRights()));
|
||||||
setDimensionsToContent(st::boxWideWidth, _inner);
|
setDimensionsToContent(st::boxWideWidth, _inner);
|
||||||
|
_inner->setCustomStatus(_customStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Widget>
|
template <typename Widget>
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public:
|
||||||
not_null<UserData*> user,
|
not_null<UserData*> user,
|
||||||
bool hasAdminRights);
|
bool hasAdminRights);
|
||||||
|
|
||||||
|
void setCustomStatus(const QString &status);
|
||||||
protected:
|
protected:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
|
||||||
|
|
@ -61,6 +62,7 @@ private:
|
||||||
|
|
||||||
class Inner;
|
class Inner;
|
||||||
QPointer<Inner> _inner;
|
QPointer<Inner> _inner;
|
||||||
|
QString _customStatus;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1912,10 +1912,17 @@ std::unique_ptr<PeerListRow> ParticipantsBoxController::createRow(
|
||||||
refreshCustomStatus(row.get());
|
refreshCustomStatus(row.get());
|
||||||
if (_role == Role::Admins
|
if (_role == Role::Admins
|
||||||
&& user
|
&& user
|
||||||
&& !_additional.isCreator(user)
|
&& (_additional.adminRights(user).has_value()
|
||||||
&& _additional.adminRights(user).has_value()
|
|| _additional.isCreator(user))) {
|
||||||
&& _additional.canEditAdmin(user)) {
|
if (_additional.canEditAdmin(user) && !_additional.isCreator(user)) {
|
||||||
row->setActionLink(tr::lng_profile_kick(tr::now));
|
row->setActionLink(tr::lng_profile_kick(tr::now));
|
||||||
|
}
|
||||||
|
row->setAdminRank(channel
|
||||||
|
? channel->adminRank(user)
|
||||||
|
: (chat && _additional.isCreator(user))
|
||||||
|
? tr::lng_owner_badge(tr::now)
|
||||||
|
: QString(),
|
||||||
|
_additional.isCreator(user));
|
||||||
} else if (_role == Role::Kicked || _role == Role::Restricted) {
|
} else if (_role == Role::Kicked || _role == Role::Restricted) {
|
||||||
if (_additional.canRestrictParticipant(participant)) {
|
if (_additional.canRestrictParticipant(participant)) {
|
||||||
row->setActionLink(tr::lng_profile_delete_removed(tr::now));
|
row->setActionLink(tr::lng_profile_delete_removed(tr::now));
|
||||||
|
|
@ -1948,6 +1955,11 @@ auto ParticipantsBoxController::computeType(
|
||||||
? Rights::Admin
|
? Rights::Admin
|
||||||
: Rights::Normal;
|
: Rights::Normal;
|
||||||
result.canRemove = _additional.canRemoveParticipant(participant);
|
result.canRemove = _additional.canRemoveParticipant(participant);
|
||||||
|
if (user) {
|
||||||
|
if (const auto channel = _peer->asChannel()) {
|
||||||
|
result.adminRank = channel->adminRank(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_histories.h"
|
#include "data/data_histories.h"
|
||||||
#include "data/data_group_call.h"
|
#include "data/data_group_call.h"
|
||||||
#include "data/data_message_reactions.h"
|
#include "data/data_message_reactions.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "main/session/send_as_peers.h"
|
#include "main/session/send_as_peers.h"
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
|
|
@ -403,6 +404,26 @@ bool ChannelData::lastParticipantsRequestNeeded() const {
|
||||||
& MegagroupInfo::LastParticipantsCountOutdated);
|
& MegagroupInfo::LastParticipantsCountOutdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ChannelData::adminRank(not_null<UserData*> user) const {
|
||||||
|
if (!isGroupAdmin(user)) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
const auto info = mgInfo.get();
|
||||||
|
const auto i = mgInfo->admins.find(peerToUser(user->id));
|
||||||
|
const auto custom = (i != mgInfo->admins.end())
|
||||||
|
? i->second
|
||||||
|
: (info->creator == user)
|
||||||
|
? info->creatorRank
|
||||||
|
: QString();
|
||||||
|
return !custom.isEmpty()
|
||||||
|
? custom
|
||||||
|
: (info->creator == user)
|
||||||
|
? tr::lng_owner_badge(tr::now)
|
||||||
|
: (i != mgInfo->admins.end())
|
||||||
|
? tr::lng_admin_badge(tr::now)
|
||||||
|
: QString();
|
||||||
|
}
|
||||||
|
|
||||||
auto ChannelData::unavailableReasons() const
|
auto ChannelData::unavailableReasons() const
|
||||||
-> const std::vector<Data::UnavailableReason> & {
|
-> const std::vector<Data::UnavailableReason> & {
|
||||||
return _unavailableReasons;
|
return _unavailableReasons;
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ public:
|
||||||
void markForbidden();
|
void markForbidden();
|
||||||
|
|
||||||
[[nodiscard]] bool isGroupAdmin(not_null<UserData*> user) const;
|
[[nodiscard]] bool isGroupAdmin(not_null<UserData*> user) const;
|
||||||
|
[[nodiscard]] QString adminRank(not_null<UserData*> user) const;
|
||||||
[[nodiscard]] bool lastParticipantsRequestNeeded() const;
|
[[nodiscard]] bool lastParticipantsRequestNeeded() const;
|
||||||
[[nodiscard]] bool isMegagroup() const {
|
[[nodiscard]] bool isMegagroup() const {
|
||||||
return flags() & Flag::Megagroup;
|
return flags() & Flag::Megagroup;
|
||||||
|
|
|
||||||
|
|
@ -62,34 +62,29 @@ void MemberListRow::rightActionPaint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MemberListRow::nameIconWidth() const {
|
int MemberListRow::adminRankWidth() const {
|
||||||
return (_type.rights == Rights::Admin)
|
return st::normalFont->width(_type.adminRank);
|
||||||
? st::infoMembersAdminIcon.width()
|
|
||||||
: (_type.rights == Rights::Creator)
|
|
||||||
? st::infoMembersCreatorIcon.width()
|
|
||||||
: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<UserData*> MemberListRow::user() const {
|
not_null<UserData*> MemberListRow::user() const {
|
||||||
return peer()->asUser();
|
return peer()->asUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemberListRow::paintNameIcon(
|
void MemberListRow::paintAdminRank(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
bool selected) {
|
bool selected) {
|
||||||
auto icon = [&] {
|
if (_type.canRemove && selected) {
|
||||||
return (_type.rights == Rights::Admin)
|
return;
|
||||||
? (selected
|
}
|
||||||
? &st::infoMembersAdminIconOver
|
p.setPen(_type.rights == Rights::Creator
|
||||||
: &st::infoMembersAdminIcon)
|
? st::defaultPeerListItem.statusFgActive
|
||||||
: (selected
|
: selected
|
||||||
? &st::infoMembersCreatorIconOver
|
? st::defaultPeerListItem.statusFgOver
|
||||||
: &st::infoMembersCreatorIcon);
|
: st::defaultPeerListItem.statusFg);
|
||||||
}();
|
p.drawTextLeft(x, y, outerWidth, _type.adminRank, adminRankWidth());
|
||||||
icon->paint(p, x, y, outerWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemberListRow::refreshStatus() {
|
void MemberListRow::refreshStatus() {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ public:
|
||||||
struct Type {
|
struct Type {
|
||||||
Rights rights;
|
Rights rights;
|
||||||
bool canRemove = false;
|
bool canRemove = false;
|
||||||
|
QString adminRank;
|
||||||
};
|
};
|
||||||
|
|
||||||
MemberListRow(not_null<UserData*> user, Type type);
|
MemberListRow(not_null<UserData*> user, Type type);
|
||||||
|
|
@ -39,8 +40,8 @@ public:
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
bool selected,
|
bool selected,
|
||||||
bool actionSelected) override;
|
bool actionSelected) override;
|
||||||
int nameIconWidth() const override;
|
int adminRankWidth() const override;
|
||||||
void paintNameIcon(
|
void paintAdminRank(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,10 @@ void GroupMembersWidget::setItemFlags(
|
||||||
? AdminState::Admin
|
? AdminState::Admin
|
||||||
: AdminState::None;
|
: AdminState::None;
|
||||||
item->adminState = adminState;
|
item->adminState = adminState;
|
||||||
|
if (isCreator) {
|
||||||
|
item->adminRank = tr::lng_owner_badge(tr::now);
|
||||||
|
item->adminRankWidth = st::normalFont->width(item->adminRank);
|
||||||
|
}
|
||||||
if (item->peer->id == chat->session().userPeerId()) {
|
if (item->peer->id == chat->session().userPeerId()) {
|
||||||
item->hasRemoveLink = false;
|
item->hasRemoveLink = false;
|
||||||
} else if (chat->amCreator()
|
} else if (chat->amCreator()
|
||||||
|
|
@ -410,6 +414,8 @@ void GroupMembersWidget::setItemFlags(
|
||||||
updateItemStatusText(item);
|
updateItemStatusText(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
item->adminRank = megagroup->adminRank(item->peer->asUser());
|
||||||
|
item->adminRankWidth = st::normalFont->width(item->adminRank);
|
||||||
if (item->peer->isSelf()) {
|
if (item->peer->isSelf()) {
|
||||||
item->hasRemoveLink = false;
|
item->hasRemoveLink = false;
|
||||||
} else if (megagroup->amCreator() || (megagroup->canBanMembers() && ((adminState == AdminState::None) || adminCanEdit))) {
|
} else if (megagroup->amCreator() || (megagroup->canBanMembers() && ((adminState == AdminState::None) || adminCanEdit))) {
|
||||||
|
|
|
||||||
|
|
@ -110,14 +110,15 @@ void PeerListWidget::paintItem(Painter &p, int x, int y, Item *item, bool select
|
||||||
p.setPen(st::windowActiveTextFg);
|
p.setPen(st::windowActiveTextFg);
|
||||||
p.drawTextLeft(nameLeft + nameWidth - _removeWidth, nameTop, width(), _removeText, _removeWidth);
|
p.drawTextLeft(nameLeft + nameWidth - _removeWidth, nameTop, width(), _removeText, _removeWidth);
|
||||||
nameWidth -= _removeWidth + skip;
|
nameWidth -= _removeWidth + skip;
|
||||||
}
|
} else if (item->adminState != Item::AdminState::None) {
|
||||||
if (item->adminState != Item::AdminState::None) {
|
p.setFont(st::normalFont);
|
||||||
nameWidth -= st::profileMemberAdminIcon.width();
|
p.setPen(item->adminState == Item::AdminState::Creator
|
||||||
auto iconLeft = nameLeft + qMin(nameWidth, item->name.maxWidth());
|
? _st.statusFgActive
|
||||||
auto &icon = (item->adminState == Item::AdminState::Creator)
|
: selected
|
||||||
? (selected ? st::profileMemberCreatorIconOver : st::profileMemberCreatorIcon)
|
? _st.statusFgOver
|
||||||
: (selected ? st::profileMemberAdminIconOver : st::profileMemberAdminIcon);
|
: _st.statusFg);
|
||||||
icon.paint(p, QPoint(iconLeft, nameTop), width());
|
p.drawTextLeft(nameLeft + nameWidth - item->adminRankWidth, nameTop, width(), item->adminRank, item->adminRankWidth);
|
||||||
|
nameWidth -= item->adminRankWidth + skip;
|
||||||
}
|
}
|
||||||
p.setPen(st::profileMemberNameFg);
|
p.setPen(st::profileMemberNameFg);
|
||||||
item->name.drawLeftElided(p, nameLeft, nameTop, nameWidth, width());
|
item->name.drawLeftElided(p, nameLeft, nameTop, nameWidth, width());
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ public:
|
||||||
Creator,
|
Creator,
|
||||||
};
|
};
|
||||||
AdminState adminState = AdminState::None;
|
AdminState adminState = AdminState::None;
|
||||||
|
QString adminRank;
|
||||||
|
int adminRankWidth = 0;
|
||||||
bool hasRemoveLink = false;
|
bool hasRemoveLink = false;
|
||||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue