Improve unacessible permissions design.

This commit is contained in:
John Preston 2019-01-21 14:22:18 +04:00
parent 6066265717
commit 6d706fd222
12 changed files with 133 additions and 63 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

View file

@ -1489,7 +1489,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_rights_edit_admin_header" = "What can this admin do?";
"lng_rights_about_add_admins_yes" = "This admin will be able to add new admins with the same (or more limited) permissions.";
"lng_rights_about_add_admins_no" = "This admin will not be able to add new admins.";
"lng_rights_about_admin_cant_edit" = "You cannot edit rights of this admin.";
"lng_rights_about_admin_cant_edit" = "You are not allowed to edit the rights of this admin.";
"lng_rights_about_restriction_cant_edit" = "You cannot change the restrictions for this user.";
"lng_rights_restriction_for_all" = "This option is disabled for all members in Group Permissions. You can either enable the permission for everyone or make this user an admin.";
"lng_rights_permission_for_all" = "This option is enabled for all members in Group Permissions.";
"lng_rights_permission_unavailable" = "This permission is not available in public groups.";
"lng_rights_permission_cant_edit" = "You cannot edit this permission.";
"lng_rights_user_restrictions" = "User restrictions";
"lng_rights_user_restrictions_header" = "What can this member do?";
"lng_rights_default_restrictions_header" = "What can members of this group do?";

View file

@ -692,6 +692,7 @@ rightsCheckbox: Checkbox(defaultBoxCheckbox) {
rightsToggle: Toggle(defaultToggle) {
toggledFg: windowBgActive;
untoggledFg: attentionButtonFg;
lockIcon: icon {{ "info_rights_lock", windowBgActive }};
xsize: 8px;
vsize: 5px;
vshift: 1px;

View file

@ -221,12 +221,26 @@ void EditAdminBox::prepare() {
| (prepareRights.c_chatAdminRights().vflags.v
& (filterByMyRights ? channel->adminRights() : ~Flag(0)));
const auto disabledFlags = canSave()
? (disabledByDefaults
| ((!channel || channel->amCreator())
? Flags(0)
: ~channel->adminRights()))
: ~Flags(0);
const auto disabledMessages = [&] {
auto result = std::map<Flags, QString>();
if (!canSave()) {
result.emplace(
~Flags(0),
lang(lng_rights_about_admin_cant_edit));
} else {
result.emplace(
disabledByDefaults,
lang(lng_rights_permission_for_all));
if (const auto channel = peer()->asChannel()) {
if (!channel->amCreator()) {
result.emplace(
~channel->adminRights(),
lang(lng_rights_permission_cant_edit));
}
}
}
return result;
}();
const auto anyoneCanAddMembers = chat
? chat->anyoneCanAddMembers()
@ -235,7 +249,7 @@ void EditAdminBox::prepare() {
this,
lng_rights_edit_admin_header,
prepareFlags,
disabledFlags,
disabledMessages,
peer()->isChat() || peer()->isMegagroup(),
anyoneCanAddMembers);
addControl(std::move(checkboxes), QMargins());
@ -316,18 +330,29 @@ void EditRestrictedBox::prepare() {
| ((channel && channel->isPublic())
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0));
const auto disabledFlags = canSave()
? (defaultRestrictions
| ((channel && channel->isPublic())
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0)))
: ~Flags(0);
const auto disabledMessages = [&] {
auto result = std::map<Flags, QString>();
if (!canSave()) {
result.emplace(
~Flags(0),
lang(lng_rights_about_restriction_cant_edit));
} else {
const auto disabled = defaultRestrictions
| ((channel && channel->isPublic())
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0));
result.emplace(
disabled,
lang(lng_rights_restriction_for_all));
}
return result;
}();
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
this,
lng_rights_user_restrictions_header,
prepareFlags,
disabledFlags);
disabledMessages);
addControl(std::move(checkboxes), QMargins());
_until = prepareRights.c_chatBannedRights().vuntil_date.v;
@ -424,7 +449,7 @@ void EditRestrictedBox::createUntilVariants() {
if (!canSave() && _untilGroup->value() != value) {
return;
}
_untilVariants.push_back(base::unique_qptr<Ui::Radiobutton>(
_untilVariants.emplace_back(
addControl(
object_ptr<Ui::Radiobutton>(
this,
@ -432,7 +457,7 @@ void EditRestrictedBox::createUntilVariants() {
value,
text,
st::defaultBoxCheckbox),
st::rightsToggleMargin)));
st::rightsToggleMargin));
if (!canSave()) {
_untilVariants.back()->setDisabled(true);
}

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/checkbox.h"
#include "ui/toast/toast.h"
#include "info/profile/info_profile_button.h"
#include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_values.h"
@ -280,24 +281,26 @@ void EditPeerPermissionsBox::prepare() {
}
Unexpected("User in EditPeerPermissionsBox.");
}();
const auto disabledFlags = [&] {
if (const auto chat = _peer->asChat()) {
return Flags(0)
| disabledByAdminRights;
} else if (const auto channel = _peer->asChannel()) {
return (channel->isPublic()
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0))
| disabledByAdminRights;
const auto disabledMessages = [&] {
auto result = std::map<Flags, QString>();
result.emplace(
disabledByAdminRights,
lang(lng_rights_permission_cant_edit));
if (const auto channel = _peer->asChannel()) {
if (channel->isPublic()) {
result.emplace(
Flag::f_change_info | Flag::f_pin_messages,
lang(lng_rights_permission_unavailable));
}
}
Unexpected("User in EditPeerPermissionsBox.");
return result;
}();
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
this,
lng_rights_default_restrictions_header,
restrictions,
disabledFlags);
disabledMessages);
inner->add(std::move(checkboxes));
@ -353,12 +356,15 @@ void EditPeerPermissionsBox::addBannedButtons(
}
}
template <typename Flags, typename FlagLabelPairs>
template <
typename Flags,
typename DisabledMessagePairs,
typename FlagLabelPairs>
EditFlagsControl<Flags> CreateEditFlags(
QWidget *parent,
LangKey header,
Flags checked,
Flags disabled,
const DisabledMessagePairs &disabledMessagePairs,
const FlagLabelPairs &flagLabelPairs) {
auto widget = object_ptr<Ui::VerticalLayout>(parent);
const auto container = widget.data();
@ -394,24 +400,38 @@ EditFlagsControl<Flags> CreateEditFlags(
st::rightsHeaderMargin);
auto addCheckbox = [&](Flags flags, const QString &text) {
const auto lockedIt = ranges::find_if(
disabledMessagePairs,
[&](const auto &pair) { return (pair.first & flags) != 0; });
const auto locked = (lockedIt != end(disabledMessagePairs))
? std::make_optional(lockedIt->second)
: std::nullopt;
const auto toggled = ((checked & flags) != 0);
auto toggle = std::make_unique<Ui::ToggleView>(
st::rightsToggle,
toggled);
toggle->setLocked(locked.has_value());
const auto control = container->add(
object_ptr<Ui::Checkbox>(
container,
text,
(checked & flags) != 0,
st::rightsCheckbox,
st::rightsToggle),
std::move(toggle)),
st::rightsToggleMargin);
control->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
InvokeQueued(control, [=] {
applyDependencies(control);
changes->fire({});
});
if (locked.has_value()) {
if (checked != toggled) {
Ui::Toast::Show(*locked);
control->setChecked(toggled);
}
} else {
InvokeQueued(control, [=] {
applyDependencies(control);
changes->fire({});
});
}
}, control->lifetime());
if ((disabled & flags) != 0) {
control->setDisabled(true);
}
checkboxes->emplace(flags, control);
};
for (const auto &[flags, label] : flagLabelPairs) {
@ -434,12 +454,12 @@ EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
QWidget *parent,
LangKey header,
MTPDchatBannedRights::Flags restrictions,
MTPDchatBannedRights::Flags disabled) {
std::map<MTPDchatBannedRights::Flags, QString> disabledMessages) {
auto result = CreateEditFlags(
parent,
header,
NegateRestrictions(restrictions),
disabled,
disabledMessages,
RestrictionLabels());
result.value = [original = std::move(result.value)]{
return NegateRestrictions(original());
@ -455,13 +475,13 @@ EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
QWidget *parent,
LangKey header,
MTPDchatAdminRights::Flags rights,
MTPDchatAdminRights::Flags disabled,
std::map<MTPDchatAdminRights::Flags, QString> disabledMessages,
bool isGroup,
bool anyoneCanAddMembers) {
return CreateEditFlags(
parent,
header,
rights,
disabled,
disabledMessages,
AdminRightLabels(isGroup, anyoneCanAddMembers));
}

View file

@ -46,13 +46,13 @@ EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
QWidget *parent,
LangKey header,
MTPDchatBannedRights::Flags restrictions,
MTPDchatBannedRights::Flags disabled);
std::map<MTPDchatBannedRights::Flags, QString> disabledMessages);
EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
QWidget *parent,
LangKey header,
MTPDchatAdminRights::Flags rights,
MTPDchatAdminRights::Flags disabled,
std::map<MTPDchatAdminRights::Flags, QString> disabledMessages,
bool isGroup,
bool anyoneCanAddMembers);

View file

@ -22,7 +22,7 @@ bool ValidateFont(const QString &familyName, int flags = 0) {
checkFont.setStyleStrategy(QFont::PreferQuality);
auto realFamily = QFontInfo(checkFont).family();
if (realFamily.trimmed().compare(familyName, Qt::CaseInsensitive)) {
LOG(("Font Error: could not resolve '%1' font, got '%2' after feeding '%3'.").arg(familyName).arg(realFamily));
LOG(("Font Error: could not resolve '%1' font, got '%2'.").arg(familyName).arg(realFamily));
return false;
}

View file

@ -115,20 +115,28 @@ void ToggleView::paint(Painter &p, int left, int top, int outerWidth, TimeMs ms)
p.drawEllipse(fgRect);
if (_st->xsize > 0) {
paintXV(p, toggleLeft, top, outerWidth, toggled, fgBrush);
p.setPen(Qt::NoPen);
p.setBrush(fgBrush);
if (_locked) {
const auto color = anim::color(_st->untoggledFg, _st->toggledFg, toggled);
_st->lockIcon.paint(p, toggleLeft, top, outerWidth, color);
} else {
paintXV(p, toggleLeft, top, outerWidth, toggled, fgBrush);
}
}
}
void ToggleView::paintXV(Painter &p, int left, int top, int outerWidth, float64 toggled, const QBrush &brush) {
Assert(_st->vsize > 0);
Assert(_st->stroke > 0);
Expects(_st->vsize > 0);
Expects(_st->stroke > 0);
static const auto sqrt2 = sqrt(2.);
auto stroke = (0. + _st->stroke) / sqrt2;
const auto stroke = (0. + _st->stroke) / sqrt2;
if (toggled < 1) {
// Just X or X->V.
auto xSize = 0. + _st->xsize;
auto xLeft = left + (_st->diameter - xSize) / 2.;
auto xTop = top + (_st->diameter - xSize) / 2.;
const auto xSize = 0. + _st->xsize;
const auto xLeft = left + (_st->diameter - xSize) / 2.;
const auto xTop = top + (_st->diameter - xSize) / 2.;
QPointF pathX[] = {
{ xLeft, xTop + stroke },
{ xLeft + stroke, xTop },
@ -148,10 +156,10 @@ void ToggleView::paintXV(Painter &p, int left, int top, int outerWidth, float64
}
if (toggled > 0) {
// X->V.
auto vSize = 0. + _st->vsize;
auto fSize = (xSize + vSize - 2. * stroke);
auto vLeft = left + (_st->diameter - fSize) / 2.;
auto vTop = 0. + xTop + _st->vshift;
const auto vSize = 0. + _st->vsize;
const auto fSize = (xSize + vSize - 2. * stroke);
const auto vLeft = left + (_st->diameter - fSize) / 2.;
const auto vTop = 0. + xTop + _st->vshift;
QPointF pathV[] = {
{ vLeft, vTop + xSize - vSize + stroke },
{ vLeft + stroke, vTop + xSize - vSize },
@ -176,12 +184,12 @@ void ToggleView::paintXV(Painter &p, int left, int top, int outerWidth, float64
}
} else {
// Just V.
auto xSize = 0. + _st->xsize;
auto xTop = top + (_st->diameter - xSize) / 2.;
auto vSize = 0. + _st->vsize;
auto fSize = (xSize + vSize - 2. * stroke);
auto vLeft = left + (_st->diameter - (_st->xsize + _st->vsize - 2. * stroke)) / 2.;
auto vTop = 0. + xTop + _st->vshift;
const auto xSize = 0. + _st->xsize;
const auto xTop = top + (_st->diameter - xSize) / 2.;
const auto vSize = 0. + _st->vsize;
const auto fSize = (xSize + vSize - 2. * stroke);
const auto vLeft = left + (_st->diameter - (_st->xsize + _st->vsize - 2. * stroke)) / 2.;
const auto vTop = 0. + xTop + _st->vshift;
QPointF pathV[] = {
{ vLeft, vTop + xSize - vSize + stroke },
{ vLeft + stroke, vTop + xSize - vSize },
@ -214,6 +222,13 @@ bool ToggleView::checkRippleStartPosition(QPoint position) const {
return QRect(QPoint(0, 0), rippleSize()).contains(position);
}
void ToggleView::setLocked(bool locked) {
if (_locked != locked) {
_locked = locked;
update();
}
}
CheckView::CheckView(const style::Check &st, bool checked, Fn<void()> updateCallback) : AbstractCheckView(st.duration, checked, std::move(updateCallback))
, _st(&st) {
}

View file

@ -126,12 +126,14 @@ public:
void paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) override;
QImage prepareRippleMask() const override;
bool checkRippleStartPosition(QPoint position) const override;
void setLocked(bool locked);
private:
void paintXV(Painter &p, int left, int top, int outerWidth, float64 toggled, const QBrush &brush);
QSize rippleSize() const;
not_null<const style::Toggle*> _st;
bool _locked = false;
};

View file

@ -115,6 +115,7 @@ Toggle {
vsize: pixels;
vshift: pixels;
stroke: pixels;
lockIcon: icon;
rippleAreaPadding: pixels;
}