Add EditPeerPermissionsBox.

This commit is contained in:
John Preston 2019-01-08 14:54:18 +04:00
parent f4d52b82b4
commit eff90395b6
20 changed files with 469 additions and 142 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -789,6 +789,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_manage_peer_administrators" = "Administrators";
"lng_manage_peer_banned_users" = "Banned users";
"lng_manage_peer_restricted_users" = "Restricted users";
"lng_manage_peer_exceptions" = "Exceptions";
"lng_manage_peer_removed_users" = "Removed users";
"lng_manage_peer_permissions" = "Permissions";
"lng_manage_history_visibility_title" = "Chat history for new members";
"lng_manage_history_visibility_shown" = "Visible";
"lng_manage_history_visibility_shown_about" = "New members will see messages that were sent before they joined.";
@ -1472,7 +1475,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"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_user_restrictions" = "User restrictions";
"lng_rights_user_restrictions_header" = "What can this user do?";
"lng_rights_user_restrictions_header" = "What can this member do?";
"lng_rights_default_restrictions_header" = "What can members of this group do?";
"lng_rights_channel_info" = "Change channel info";
"lng_rights_channel_post" = "Post messages";
@ -1490,6 +1494,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_rights_chat_send_media" = "Send media";
"lng_rights_chat_send_stickers" = "Send stickers & GIFs";
"lng_rights_chat_send_links" = "Embed links";
"lng_rights_chat_send_polls" = "Send polls";
"lng_rights_chat_add_members" = "Add members";
"lng_rights_chat_banned_until_header" = "Restricted until";
"lng_rights_chat_banned_forever" = "Forever";
"lng_rights_chat_banned_day#one" = "For {count} day";
@ -1586,7 +1592,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_admin_edit_messages" = "Edit messages";
"lng_admin_log_admin_delete_messages" = "Delete messages";
"lng_admin_log_admin_ban_users" = "Ban users";
"lng_admin_log_admin_invite_users" = "Add users";
"lng_admin_log_admin_invite_users" = "Add members";
"lng_admin_log_admin_invite_link" = "Invite users via link";
"lng_admin_log_admin_pin_messages" = "Pin messages";
"lng_admin_log_admin_add_admins" = "Add new admins";

View File

@ -1636,6 +1636,39 @@ void ApiWrap::unblockParticipant(
_kickRequests.emplace(kick, requestId);
}
void ApiWrap::saveDefaultRestrictions(
not_null<PeerData*> peer,
const MTPChatBannedRights &rights,
Fn<void(bool)> callback) {
if (_defaultRestrictionsRequests.contains(peer)) {
return;
}
const auto requestId = request(MTPmessages_EditChatDefaultBannedRights(
peer->input,
rights
)).done([=](const MTPUpdates &result) {
_defaultRestrictionsRequests.erase(peer);
applyUpdates(result);
if (callback) {
callback(true);
}
}).fail([=](const RPCError &error) {
_defaultRestrictionsRequests.erase(peer);
if (error.type() == qstr("CHAT_NOT_MODIFIED")) {
if (const auto chat = peer->asChat()) {
chat->setDefaultRestrictions(rights);
if (callback) {
callback(true);
}
return;
}
}
if (callback) {
callback(false);
}
}).send();
}
void ApiWrap::deleteAllFromUser(
not_null<ChannelData*> channel,
not_null<UserData*> from) {

View File

@ -156,6 +156,10 @@ public:
void deleteAllFromUser(
not_null<ChannelData*> channel,
not_null<UserData*> from);
void saveDefaultRestrictions(
not_null<PeerData*> peer,
const MTPChatBannedRights &rights,
Fn<void(bool)> callback = nullptr);
void requestWebPageDelayed(WebPageData *page);
void clearWebPageRequest(WebPageData *page);
@ -610,6 +614,10 @@ private:
not_null<UserData*>>;
base::flat_map<KickRequest, mtpRequestId> _kickRequests;
base::flat_map<
not_null<PeerData*>,
mtpRequestId> _defaultRestrictionsRequests;
QMap<ChannelData*, mtpRequestId> _selfParticipantRequests;
base::flat_map<

View File

@ -103,11 +103,14 @@ public:
void clearButtons() {
getDelegate()->clearButtons();
}
QPointer<Ui::RoundButton> addButton(Fn<QString()> textFactory, Fn<void()> clickCallback);
QPointer<Ui::RoundButton> addLeftButton(Fn<QString()> textFactory, Fn<void()> clickCallback);
QPointer<Ui::IconButton> addTopButton(const style::IconButton &st, Fn<void()> clickCallback) {
QPointer<Ui::RoundButton> addButton(Fn<QString()> textFactory, Fn<void()> clickCallback = nullptr);
QPointer<Ui::RoundButton> addLeftButton(Fn<QString()> textFactory, Fn<void()> clickCallback = nullptr);
QPointer<Ui::IconButton> addTopButton(const style::IconButton &st, Fn<void()> clickCallback = nullptr) {
return getDelegate()->addTopButton(st, std::move(clickCallback));
}
QPointer<Ui::RoundButton> addButton(Fn<QString()> textFactory, const style::RoundButton &st) {
return getDelegate()->addButton(std::move(textFactory), nullptr, st);
}
QPointer<Ui::RoundButton> addButton(Fn<QString()> textFactory, Fn<void()> clickCallback, const style::RoundButton &st) {
return getDelegate()->addButton(std::move(textFactory), std::move(clickCallback), st);
}

View File

@ -699,7 +699,8 @@ rightsToggle: Toggle(defaultToggle) {
duration: 120;
}
rightsDividerHeight: 10px;
rightsHeaderMargin: margins(23px, 20px, 23px, 8px);
rightsDividerMargin: margins(0px, 0px, 0px, 20px);
rightsHeaderMargin: margins(23px, 0px, 23px, 8px);
rightsToggleMargin: margins(23px, 8px, 23px, 8px);
rightsAboutMargin: margins(23px, 8px, 23px, 8px);
rightsPhotoButton: UserpicButton(defaultUserpicButton) {
@ -722,7 +723,7 @@ rightsHeaderLabel: FlatLabel(boxLabel) {
}
textFg: windowActiveTextFg;
}
rightsUntilMargin: margins(0px, 8px, 0px, 0px);
rightsUntilMargin: margins(0px, 8px, 0px, 20px);
mutePhotoButton: UserpicButton(defaultUserpicButton) {
size: size(40px, 40px);

View File

@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_participant_box.h"
#include "lang/lang_keys.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
@ -28,7 +30,7 @@ constexpr auto kSecondsInWeek = 7 * kSecondsInDay;
} // namespace
class EditParticipantBox::Inner : public TWidget {
class EditParticipantBox::Inner : public Ui::RpWidget {
public:
Inner(
QWidget *parent,
@ -37,27 +39,19 @@ public:
bool hasAdminRights);
template <typename Widget>
QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin);
void removeControl(QPointer<TWidget> widget);
Widget *addControl(object_ptr<Widget> widget, QMargins margin);
protected:
int resizeGetHeight(int newWidth) override;
void paintEvent(QPaintEvent *e) override;
private:
void doAddControl(object_ptr<TWidget> widget, QMargins margin);
not_null<ChannelData*> _channel;
not_null<UserData*> _user;
object_ptr<Ui::UserpicButton> _userPhoto;
Text _userName;
bool _hasAdminRights = false;
struct Control {
object_ptr<TWidget> widget;
QMargins margin;
};
std::vector<Control> _rows;
object_ptr<Ui::VerticalLayout> _rows;
};
@ -66,7 +60,7 @@ EditParticipantBox::Inner::Inner(
not_null<ChannelData*> channel,
not_null<UserData*> user,
bool hasAdminRights)
: TWidget(parent)
: RpWidget(parent)
, _channel(channel)
, _user(user)
, _userPhoto(
@ -74,7 +68,13 @@ EditParticipantBox::Inner::Inner(
_user,
Ui::UserpicButton::Role::Custom,
st::rightsPhotoButton)
, _hasAdminRights(hasAdminRights) {
, _hasAdminRights(hasAdminRights)
, _rows(this) {
_rows->heightValue(
) | rpl::start_with_next([=] {
resizeToWidth(width());
}, lifetime());
_userPhoto->setPointerCursor(false);
_userName.setText(
st::rightsNameStyle,
@ -82,44 +82,23 @@ EditParticipantBox::Inner::Inner(
Ui::NameTextOptions());
}
void EditParticipantBox::Inner::removeControl(QPointer<TWidget> widget) {
auto row = ranges::find(_rows, widget, &Control::widget);
Assert(row != _rows.end());
row->widget.destroy();
_rows.erase(row);
}
template <typename Widget>
QPointer<Widget> EditParticipantBox::Inner::addControl(
Widget *EditParticipantBox::Inner::addControl(
object_ptr<Widget> widget,
QMargins margin) {
doAddControl(std::move(widget), margin);
return static_cast<Widget*>(_rows.back().widget.data());
}
void EditParticipantBox::Inner::doAddControl(
object_ptr<TWidget> widget,
QMargins margin) {
widget->setParent(this);
_rows.push_back({ std::move(widget), margin });
_rows.back().widget->show();
return _rows->add(std::move(widget), margin);
}
int EditParticipantBox::Inner::resizeGetHeight(int newWidth) {
_userPhoto->moveToLeft(
st::rightsPhotoMargin.left(),
st::rightsPhotoMargin.top());
auto newHeight = st::rightsPhotoMargin.top()
const auto rowsTop = st::rightsPhotoMargin.top()
+ st::rightsPhotoButton.size.height()
+ st::rightsPhotoMargin.bottom();
for (auto &&row : _rows) {
auto rowWidth = newWidth - row.margin.left() - row.margin.right();
newHeight += row.margin.top();
row.widget->resizeToNaturalWidth(rowWidth);
row.widget->moveToLeft(row.margin.left(), newHeight);
newHeight += row.widget->heightNoMargins() + row.margin.bottom();
}
return newHeight;
_rows->resizeToWidth(newWidth);
_rows->moveToLeft(0, rowsTop, newWidth);
return rowsTop + _rows->heightNoMargins();
}
void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) {
@ -173,10 +152,11 @@ void EditParticipantBox::prepare() {
_channel,
_user,
hasAdminRights()));
setDimensionsToContent(st::boxWideWidth, _inner);
}
template <typename Widget>
QPointer<Widget> EditParticipantBox::addControl(
Widget *EditParticipantBox::addControl(
object_ptr<Widget> widget,
QMargins margin) {
Expects(_inner != nullptr);
@ -184,19 +164,6 @@ QPointer<Widget> EditParticipantBox::addControl(
return _inner->addControl(std::move(widget), margin);
}
void EditParticipantBox::removeControl(QPointer<TWidget> widget) {
Expects(_inner != nullptr);
return _inner->removeControl(widget);
}
void EditParticipantBox::resizeToContent() {
_inner->resizeToWidth(st::boxWideWidth);
setDimensions(
_inner->width(),
qMin(_inner->height(), st::boxMaxListHeight));
}
EditAdminBox::EditAdminBox(
QWidget*,
not_null<ChannelData*> channel,
@ -235,7 +202,9 @@ void EditAdminBox::prepare() {
? lng_rights_edit_admin
: lng_channel_add_admin));
addControl(object_ptr<BoxContentDivider>(this), QMargins());
addControl(
object_ptr<BoxContentDivider>(this),
st::rightsDividerMargin);
const auto prepareRights = hadRights ? _oldRights : Defaults(channel());
const auto filterByMyRights = canSave()
@ -290,8 +259,6 @@ void EditAdminBox::prepare() {
} else {
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
}
resizeToContent();
}
void EditAdminBox::refreshAboutAddAdminsText(bool canAddAdmins) {
@ -303,7 +270,6 @@ void EditAdminBox::refreshAboutAddAdminsText(bool canAddAdmins) {
}
return lang(lng_rights_about_add_admins_no);
}());
resizeToContent();
}
EditRestrictedBox::EditRestrictedBox(
@ -321,14 +287,21 @@ void EditRestrictedBox::prepare() {
setTitle(langFactory(lng_rights_user_restrictions));
addControl(object_ptr<BoxContentDivider>(this), QMargins());
addControl(
object_ptr<BoxContentDivider>(this),
st::rightsDividerMargin);
const auto prepareRights = _oldRights.c_chatBannedRights().vflags.v
? _oldRights
: Defaults(channel());
const auto disabledFlags = canSave() ? Flags(0) : ~Flags(0);
const auto disabledFlags = canSave()
? (channel()->defaultRestrictions()
/*| (channel()->isPublic()
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0))*/) // #TODO groups
: ~Flags(0);
auto [checkboxes, getChecked, changes] = CreateEditRestrictions(
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
this,
lng_rights_user_restrictions_header,
prepareRights.c_chatBannedRights().vflags.v,
@ -353,7 +326,7 @@ void EditRestrictedBox::prepare() {
// st::boxLinkButton));
if (canSave()) {
addButton(langFactory(lng_settings_save), [=, value = getChecked] {
const auto save = [=, value = getRestrictions] {
if (!_saveCallback) {
return;
}
@ -362,13 +335,12 @@ void EditRestrictedBox::prepare() {
MTP_chatBannedRights(
MTP_flags(value()),
MTP_int(getRealUntilValue())));
});
};
addButton(langFactory(lng_settings_save), save);
addButton(langFactory(lng_cancel), [=] { closeBox(); });
} else {
addButton(langFactory(lng_box_ok), [=] { closeBox(); });
}
resizeToContent();
}
MTPChatBannedRights EditRestrictedBox::Defaults(
@ -411,22 +383,15 @@ void EditRestrictedBox::setRestrictUntil(TimeId until) {
if (_restrictUntilBox) {
_restrictUntilBox->closeBox();
}
clearVariants();
_untilVariants.clear();
createUntilGroup();
createUntilVariants();
resizeToContent();
}
bool EditRestrictedBox::isUntilForever() const {
return ChannelData::IsRestrictedForever(_until);
}
void EditRestrictedBox::clearVariants() {
for (auto &&widget : base::take(_untilVariants)) {
removeControl(widget.data());
}
}
void EditRestrictedBox::createUntilGroup() {
_untilGroup = std::make_shared<Ui::RadiobuttonGroup>(
isUntilForever() ? 0 : _until);
@ -445,14 +410,15 @@ void EditRestrictedBox::createUntilVariants() {
if (!canSave() && _untilGroup->value() != value) {
return;
}
_untilVariants.push_back(addControl(
object_ptr<Ui::Radiobutton>(
this,
_untilGroup,
value,
text,
st::defaultBoxCheckbox),
st::rightsToggleMargin));
_untilVariants.push_back(base::unique_qptr<Ui::Radiobutton>(
addControl(
object_ptr<Ui::Radiobutton>(
this,
_untilGroup,
value,
text,
st::defaultBoxCheckbox),
st::rightsToggleMargin)));
if (!canSave()) {
_untilVariants.back()->setDisabled(true);
}

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "boxes/abstract_box.h"
#include "base/unique_qptr.h"
namespace Ui {
class FlatLabel;
@ -30,8 +31,6 @@ public:
protected:
void prepare() override;
void resizeToContent();
not_null<UserData*> user() const {
return _user;
}
@ -40,9 +39,7 @@ protected:
}
template <typename Widget>
QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin);
void removeControl(QPointer<TWidget> widget);
Widget *addControl(object_ptr<Widget> widget, QMargins margin = {});
bool hasAdminRights() const {
return _hasAdminRights;
@ -134,7 +131,7 @@ private:
Fn<void(MTPChatBannedRights, MTPChatBannedRights)> _saveCallback;
std::shared_ptr<Ui::RadiobuttonGroup> _untilGroup;
QVector<QPointer<Ui::Radiobutton>> _untilVariants;
std::vector<base::unique_qptr<Ui::Radiobutton>> _untilVariants;
QPointer<CalendarBox> _restrictUntilBox;
static constexpr auto kUntilOneDay = -1;

View File

@ -8,10 +8,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_permissions_box.h"
#include "lang/lang_keys.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/checkbox.h"
#include "info/profile/info_profile_button.h"
#include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_values.h"
#include "profile/profile_channel_controllers.h"
#include "boxes/peers/manage_peer_box.h"
#include "window/window_controller.h"
#include "mainwindow.h"
#include "styles/style_boxes.h"
#include "styles/style_info.h"
namespace {
@ -71,7 +81,6 @@ std::vector<std::pair<ChatRestrictions, LangKey>> RestrictionLabels() {
using Flag = ChatRestriction;
return {
{ Flag::f_view_messages, lng_rights_chat_read },
{ Flag::f_send_messages, lng_rights_chat_send_text },
{ Flag::f_send_media, lng_rights_chat_send_media },
{ Flag::f_send_stickers
@ -79,6 +88,10 @@ std::vector<std::pair<ChatRestrictions, LangKey>> RestrictionLabels() {
| Flag::f_send_games
| Flag::f_send_inline, lng_rights_chat_send_stickers },
{ Flag::f_embed_links, lng_rights_chat_send_links },
{ Flag::f_send_polls, lng_rights_chat_send_polls },
{ Flag::f_invite_users, lng_rights_chat_add_members },
{ Flag::f_pin_messages, lng_rights_group_pin },
{ Flag::f_change_info, lng_rights_group_info },
};
}
@ -133,9 +146,12 @@ auto Dependencies(ChatRestrictions)
// embed_links -> send_media
{ Flag::f_embed_links, Flag::f_send_media },
// send_media- > send_messages
// send_media -> send_messages
{ Flag::f_send_media, Flag::f_send_messages },
// send_polls -> send_messages
{ Flag::f_send_polls, Flag::f_send_messages },
// send_messages -> view_messages
{ Flag::f_send_messages, Flag::f_view_messages },
};
@ -145,6 +161,8 @@ ChatRestrictions NegateRestrictions(ChatRestrictions value) {
using Flag = ChatRestriction;
return (~value) & (Flag(0)
// view_messages is always allowed, so it is never in restrictions.
//| Flag::f_view_messages
| Flag::f_change_info
| Flag::f_embed_links
| Flag::f_invite_users
@ -155,8 +173,7 @@ ChatRestrictions NegateRestrictions(ChatRestrictions value) {
| Flag::f_send_media
| Flag::f_send_messages
| Flag::f_send_polls
| Flag::f_send_stickers
| Flag::f_view_messages);
| Flag::f_send_stickers);
}
auto Dependencies(ChatAdminRights)
@ -164,8 +181,146 @@ auto Dependencies(ChatAdminRights)
return {};
}
auto ToPositiveNumberString() {
return rpl::map([](int count) {
return count ? QString::number(count) : QString();
});
}
ChatRestrictions DisabledByAdminRights(not_null<PeerData*> peer) {
using Flag = ChatRestriction;
using Flags = ChatRestrictions;
using Admin = ChatAdminRight;
using Admins = ChatAdminRights;
const auto adminRights = [&] {
const auto full = ~Admins(0);
if (const auto chat = peer->asChat()) {
return chat->amCreator() ? full : chat->adminRights();
} else if (const auto channel = peer->asChannel()) {
return channel->amCreator() ? full : channel->adminRights();
}
Unexpected("User in DisabledByAdminRights.");
}();
return Flag(0)
| ((adminRights & Admin::f_pin_messages)
? Flag(0)
: Flag::f_pin_messages)
| ((adminRights & Admin::f_invite_users)
? Flag(0)
: Flag::f_invite_users)
| ((adminRights & Admin::f_change_info)
? Flag(0)
: Flag::f_change_info);
}
} // namespace
EditPeerPermissionsBox::EditPeerPermissionsBox(
QWidget*,
not_null<PeerData*> peer)
: _peer(peer) {
}
auto EditPeerPermissionsBox::saveEvents() const
-> rpl::producer<MTPDchatBannedRights::Flags> {
Expects(_save != nullptr);
return _save->clicks() | rpl::map(_value);
}
void EditPeerPermissionsBox::prepare() {
setTitle(langFactory(lng_manage_peer_permissions));
const auto inner = setInnerWidget(object_ptr<Ui::VerticalLayout>(this));
using Flag = ChatRestriction;
using Flags = ChatRestrictions;
const auto disabledByAdminRights = DisabledByAdminRights(_peer);
const auto restrictions = [&] {
if (const auto chat = _peer->asChat()) {
return chat->defaultRestrictions()
/*| disabledByAdminRights*/; // #TODO groups
} else if (const auto channel = _peer->asChannel()) {
return (channel->defaultRestrictions()
/*| (channel->isPublic()
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0))
| disabledByAdminRights*/); // #TODO groups
}
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;
}
Unexpected("User in EditPeerPermissionsBox.");
}();
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
this,
lng_rights_default_restrictions_header,
restrictions,
disabledFlags);
inner->add(std::move(checkboxes));
if (const auto channel = _peer->asChannel()) {
addBannedButtons(inner, channel);
}
_value = getRestrictions;
_save = addButton(langFactory(lng_settings_save));
addButton(langFactory(lng_cancel), [=] { closeBox(); });
setDimensionsToContent(st::boxWidth, inner);
}
void EditPeerPermissionsBox::addBannedButtons(
not_null<Ui::VerticalLayout*> container,
not_null<ChannelData*> channel) {
using Profile::ParticipantsBoxController;
container->add(
object_ptr<BoxContentDivider>(container),
{ 0, st::infoProfileSkip, 0, st::infoProfileSkip });
const auto navigation = App::wnd()->controller();
ManagePeerBox::CreateButton(
container,
Lang::Viewer(lng_manage_peer_exceptions),
Info::Profile::RestrictedCountValue(channel)
| ToPositiveNumberString(),
[=] {
ParticipantsBoxController::Start(
navigation,
channel,
ParticipantsBoxController::Role::Restricted);
},
st::peerPermissionsButton,
st::infoIconRestrictedUsers);
ManagePeerBox::CreateButton(
container,
Lang::Viewer(lng_manage_peer_removed_users),
Info::Profile::KickedCountValue(channel)
| ToPositiveNumberString(),
[=] {
ParticipantsBoxController::Start(
navigation,
channel,
ParticipantsBoxController::Role::Kicked);
},
st::peerPermissionsButton,
st::infoIconBlacklist);
}
template <typename Flags, typename FlagLabelPairs>
EditFlagsControl<Flags> CreateEditFlags(
QWidget *parent,

View File

@ -10,8 +10,33 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
#include "data/data_peer.h"
namespace Ui {
class RoundButton;
class VerticalLayout;
} // namespace Ui
enum LangKey : int;
class EditPeerPermissionsBox : public BoxContent {
public:
EditPeerPermissionsBox(QWidget*, not_null<PeerData*> peer);
rpl::producer<MTPDchatBannedRights::Flags> saveEvents() const;
protected:
void prepare() override;
private:
void addBannedButtons(
not_null<Ui::VerticalLayout*> container,
not_null<ChannelData*> channel);
not_null<PeerData*> _peer;
Ui::RoundButton *_save = nullptr;
Fn<MTPDchatBannedRights::Flags()> _value;
};
template <typename Flags>
struct EditFlagsControl {
object_ptr<Ui::RpWidget> widget;

View File

@ -15,13 +15,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/labels.h"
#include "history/admin_log/history_admin_log_section.h"
#include "window/window_controller.h"
#include "mainwindow.h"
#include "profile/profile_channel_controllers.h"
#include "info/profile/info_profile_button.h"
#include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_values.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "mainwindow.h"
#include "auth_session.h"
#include "apiwrap.h"
#include "styles/style_boxes.h"
#include "styles/style_info.h"
@ -39,51 +41,33 @@ auto ToPositiveNumberString() {
});
}
template <typename Callback>
Info::Profile::Button *AddButton(
not_null<Ui::VerticalLayout*> parent,
rpl::producer<QString> &&text,
Callback callback,
Fn<void()> callback,
const style::icon &icon) {
auto button = parent->add(
object_ptr<Info::Profile::Button>(
parent,
std::move(text),
st::managePeerButton));
button->addClickHandler(std::forward<Callback>(callback));
Ui::CreateChild<Info::Profile::FloatingIcon>(
button,
icon,
st::managePeerButtonIconPosition);
return button;
return ManagePeerBox::CreateButton(
parent,
std::move(text),
rpl::single(QString()),
std::move(callback),
st::managePeerButton,
icon);
}
template <typename Callback>
void AddButtonWithCount(
not_null<Ui::VerticalLayout*> parent,
rpl::producer<QString> &&text,
rpl::producer<QString> &&count,
Callback callback,
Fn<void()> callback,
const style::icon &icon) {
auto button = AddButton(
ManagePeerBox::CreateButton(
parent,
std::move(text),
std::forward<Callback>(callback),
icon);
auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
std::move(count),
st::managePeerButtonLabel);
label->setAttribute(Qt::WA_TransparentForMouseEvents);
rpl::combine(
button->widthValue(),
label->widthValue()
) | rpl::start_with_next([label](int outerWidth, int width) {
label->moveToRight(
st::managePeerButtonLabelPosition.x(),
st::managePeerButtonLabelPosition.y(),
outerWidth);
}, label->lifetime());
std::move(callback),
st::managePeerButton,
icon);
}
bool HasRecentActions(not_null<ChannelData*> channel) {
@ -112,6 +96,24 @@ bool HasEditInfoBox(not_null<PeerData*> peer) {
return false;
}
void ShowEditPermissions(not_null<PeerData*> peer) {
const auto box = Ui::show(
Box<EditPeerPermissionsBox>(peer),
LayerOption::KeepOther);
box->saveEvents(
) | rpl::start_with_next([=](MTPDchatBannedRights::Flags restrictions) {
const auto callback = crl::guard(box, [=](bool success) {
if (success) {
box->closeBox();
}
});
Auth().api().saveDefaultRestrictions(
peer,
MTP_chatBannedRights(MTP_flags(restrictions), MTP_int(0)),
callback);
}, box->lifetime());
}
void FillManageChatBox(
not_null<Window::Navigation*> navigation,
not_null<ChatData*> chat,
@ -123,6 +125,13 @@ void FillManageChatBox(
[=] { Ui::show(Box<EditPeerInfoBox>(chat)); },
st::infoIconInformation);
}
if (chat->canEditPermissions()) {
AddButton(
content,
Lang::Viewer(lng_manage_peer_permissions),
[=] { ShowEditPermissions(chat); },
st::infoIconPermissions);
}
if (chat->amIn()) {
AddButtonWithCount(
content,
@ -174,6 +183,13 @@ void FillManageChannelBox(
[=] { ShowRecentActions(navigation, channel); },
st::infoIconRecentActions);
}
if (channel->canEditPermissions()) {
AddButton(
content,
Lang::Viewer(lng_manage_peer_permissions),
[=] { ShowEditPermissions(channel); },
st::infoIconPermissions);
}
if (channel->canViewAdmins()) {
AddButtonWithCount(
content,
@ -202,6 +218,20 @@ void FillManageChannelBox(
},
st::infoIconMembers);
}
if (!channel->isMegagroup()) {
AddButtonWithCount(
content,
Lang::Viewer(lng_manage_peer_removed_users),
Info::Profile::KickedCountValue(channel)
| ToPositiveNumberString(),
[=] {
ParticipantsBoxController::Start(
navigation,
channel,
ParticipantsBoxController::Role::Kicked);
},
st::infoIconBlacklist);
}
}
} // namespace
@ -236,6 +266,42 @@ bool ManagePeerBox::Available(not_null<PeerData*> peer) {
}
}
Info::Profile::Button *ManagePeerBox::CreateButton(
not_null<Ui::VerticalLayout*> parent,
rpl::producer<QString> &&text,
rpl::producer<QString> &&count,
Fn<void()> callback,
const style::InfoProfileCountButton &st,
const style::icon &icon) {
const auto button = parent->add(
object_ptr<Info::Profile::Button>(
parent,
std::move(text),
st.button));
button->addClickHandler(callback);
Ui::CreateChild<Info::Profile::FloatingIcon>(
button,
icon,
st.iconPosition);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
std::move(count),
st.label);
label->setAttribute(Qt::WA_TransparentForMouseEvents);
rpl::combine(
button->widthValue(),
label->widthValue()
) | rpl::start_with_next([=, &st](int outerWidth, int width) {
label->moveToRight(
st.labelPosition.x(),
st.labelPosition.y(),
outerWidth);
}, label->lifetime());
return button;
}
void ManagePeerBox::prepare() {
_peer->updateFull();

View File

@ -9,12 +9,34 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
namespace style {
struct InfoProfileCountButton;
} // namespace style
namespace Ui {
class VerticalLayout;
} // namespace Ui
namespace Info {
namespace Profile {
class Button;
} // namespace Profile
} // namespace Info
class ManagePeerBox : public BoxContent {
public:
ManagePeerBox(QWidget*, not_null<PeerData*> peer);
static bool Available(not_null<PeerData*> peer);
static Info::Profile::Button *CreateButton(
not_null<Ui::VerticalLayout*> parent,
rpl::producer<QString> &&text,
rpl::producer<QString> &&count,
Fn<void()> callback,
const style::InfoProfileCountButton &st,
const style::icon &icon);
protected:
void prepare() override;

View File

@ -357,7 +357,7 @@ bool ChannelData::canEditInformation() const {
}
bool ChannelData::canEditPermissions() const {
return (hasAdminRights() || amCreator());
return isMegagroup() && (hasAdminRights() || amCreator());
}
bool ChannelData::canEditSignatures() const {

View File

@ -446,7 +446,8 @@ not_null<PeerData*> Session::chat(const MTPChat &data) {
: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0))));
chat->setDefaultRestrictions(data.has_default_banned_rights()
? data.vdefault_banned_rights
: MTPChatBannedRights(MTP_chatBannedRights(MTP_flags(0), MTP_int(0))));
: MTPChatBannedRights(
MTP_chatBannedRights(MTP_flags(0), MTP_int(0))));
const auto &migratedTo = data.has_migrated_to()
? data.vmigrated_to
@ -535,6 +536,10 @@ not_null<PeerData*> Session::chat(const MTPChat &data) {
if (data.has_participants_count()) {
channel->setMembersCount(data.vparticipants_count.v);
}
channel->setDefaultRestrictions(data.has_default_banned_rights()
? data.vdefault_banned_rights
: MTPChatBannedRights(
MTP_chatBannedRights(MTP_flags(0), MTP_int(0))));
if (minimal) {
auto mask = 0
| MTPDchannel::Flag::f_broadcast

View File

@ -362,6 +362,7 @@ infoIconRecentActions: icon {{ "info_recent_actions", infoIconFg }};
infoIconAdministrators: icon {{ "info_administrators", infoIconFg }};
infoIconBlacklist: icon {{ "info_blacklist", infoIconFg }};
infoIconRestrictedUsers: icon {{ "info_restricted_users", infoIconFg }};
infoIconPermissions: icon {{ "info_permissions", infoIconFg }};
infoInformationIconPosition: point(25px, 12px);
infoNotificationsIconPosition: point(20px, 5px);
infoSharedMediaIconPosition: point(20px, 24px);
@ -578,15 +579,23 @@ infoChannelsList: PeerList(infoCommonGroupsList) {
}
}
managePeerButton: InfoProfileButton(infoProfileButton) {
padding: margins(76px, 12px, 76px, 10px);
managePeerButton: InfoProfileCountButton {
button: InfoProfileButton(infoProfileButton) {
padding: margins(76px, 12px, 76px, 10px);
}
iconPosition: point(20px, 5px);
label: FlatLabel(defaultFlatLabel) {
textFg: windowActiveTextFg;
style: semiboldTextStyle;
}
labelPosition: point(25px, 12px);
}
managePeerButtonIconPosition: point(20px, 5px);
managePeerButtonLabel: FlatLabel(defaultFlatLabel) {
textFg: windowActiveTextFg;
style: semiboldTextStyle;
peerPermissionsButton: InfoProfileCountButton(managePeerButton) {
button: InfoProfileButton(infoProfileButton) {
padding: margins(67px, 12px, 67px, 10px);
}
iconPosition: point(24px, 5px);
}
managePeerButtonLabelPosition: point(25px, 11px);
terminateSessionsButton: InfoProfileButton(infoBlockButton) {
padding: margins(23px, 12px, 23px, 10px);

View File

@ -4226,7 +4226,28 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
App::feedParticipantDelete(update.c_updateChatParticipantDelete());
} break;
// #TODO groups new update
case mtpc_updateChatDefaultBannedRights: {
const auto &data = update.c_updateChatDefaultBannedRights();
const auto peerId = peerFromMTP(data.vpeer);
if (const auto peer = Auth().data().peerLoaded(peerId)) {
if (const auto chat = peer->asChat()) {
if (data.vversion.v == chat->version + 1) {
chat->setDefaultRestrictions(
data.vdefault_banned_rights);
} else {
chat->version = data.vversion.v;
chat->invalidateParticipants();
Auth().api().requestPeer(chat);
}
} else if (const auto channel = peer->asChannel()) {
channel->setDefaultRestrictions(
data.vdefault_banned_rights);
} else {
LOG(("API Error: "
"User received in updateChatDefaultBannedRights."));
}
}
} break;
case mtpc_updateChatParticipantAdmin: {
App::feedParticipantAdmin(update.c_updateChatParticipantAdmin());

View File

@ -527,6 +527,14 @@ InfoProfileButton {
ripple: RippleAnimation;
}
InfoProfileCountButton {
button: InfoProfileButton;
icon: icon;
iconPosition: point;
label: FlatLabel;
labelPosition: point;
}
PassportScanRow {
padding: margins;
size: pixels;

View File

@ -36,11 +36,13 @@ QMargins VerticalLayout::getMargins() const {
int VerticalLayout::naturalWidth() const {
auto result = 0;
for (auto &row : _rows) {
auto natural = row.widget->naturalWidth();
const auto natural = row.widget->naturalWidth();
if (natural < 0) {
return natural;
}
accumulate_max(result, natural);
accumulate_max(
result,
row.margin.left() + natural + row.margin.right());
}
return result;
}