Replaced EditPeerPermissionsBox with generic box.
This commit is contained in:
parent
19e43cfd1d
commit
f21edd1d23
|
@ -200,46 +200,46 @@ void SaveSlowmodeSeconds(
|
||||||
void ShowEditPermissions(
|
void ShowEditPermissions(
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer) {
|
||||||
auto content = Box<EditPeerPermissionsBox>(navigation, peer);
|
auto createBox = [=](not_null<Ui::GenericBox*> box) {
|
||||||
const auto box = QPointer<EditPeerPermissionsBox>(content.data());
|
const auto saving = box->lifetime().make_state<int>(0);
|
||||||
navigation->parentController()->show(
|
const auto save = [=](
|
||||||
std::move(content),
|
not_null<PeerData*> peer,
|
||||||
Ui::LayerOption::KeepOther);
|
EditPeerPermissionsBoxResult result) {
|
||||||
const auto saving = box->lifetime().make_state<int>(0);
|
Expects(result.slowmodeSeconds == 0 || peer->isChannel());
|
||||||
const auto save = [=](
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
EditPeerPermissionsBox::Result result) {
|
|
||||||
Expects(result.slowmodeSeconds == 0 || peer->isChannel());
|
|
||||||
|
|
||||||
const auto close = crl::guard(box, [=] { box->closeBox(); });
|
const auto close = crl::guard(box, [=] { box->closeBox(); });
|
||||||
SaveDefaultRestrictions(
|
SaveDefaultRestrictions(
|
||||||
peer,
|
peer,
|
||||||
result.rights,
|
result.rights,
|
||||||
close);
|
close);
|
||||||
if (const auto channel = peer->asChannel()) {
|
if (const auto channel = peer->asChannel()) {
|
||||||
SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close);
|
SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
auto done = [=](EditPeerPermissionsBoxResult result) {
|
||||||
|
if (*saving) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*saving = true;
|
||||||
|
|
||||||
|
const auto saveFor = peer->migrateToOrMe();
|
||||||
|
const auto chat = saveFor->asChat();
|
||||||
|
if (!result.slowmodeSeconds || !chat) {
|
||||||
|
save(saveFor, result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto api = &peer->session().api();
|
||||||
|
api->migrateChat(chat, [=](not_null<ChannelData*> channel) {
|
||||||
|
save(channel, result);
|
||||||
|
}, [=](const QString &) {
|
||||||
|
*saving = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
ShowEditPeerPermissionsBox(box, navigation, peer, std::move(done));
|
||||||
};
|
};
|
||||||
box->saveEvents(
|
navigation->parentController()->show(
|
||||||
) | rpl::start_with_next([=](EditPeerPermissionsBox::Result result) {
|
Box(std::move(createBox)),
|
||||||
if (*saving) {
|
Ui::LayerOption::KeepOther);
|
||||||
return;
|
|
||||||
}
|
|
||||||
*saving = true;
|
|
||||||
|
|
||||||
const auto saveFor = peer->migrateToOrMe();
|
|
||||||
const auto chat = saveFor->asChat();
|
|
||||||
if (!result.slowmodeSeconds || !chat) {
|
|
||||||
save(saveFor, result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto api = &peer->session().api();
|
|
||||||
api->migrateChat(chat, [=](not_null<ChannelData*> channel) {
|
|
||||||
save(channel, result);
|
|
||||||
}, [=](const QString &) {
|
|
||||||
*saving = false;
|
|
||||||
});
|
|
||||||
}, box->lifetime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -26,7 +26,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "mainwindow.h"
|
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "settings/settings_common.h"
|
#include "settings/settings_common.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
|
@ -212,7 +211,7 @@ template <
|
||||||
typename Flags,
|
typename Flags,
|
||||||
typename DisabledMessagePairs,
|
typename DisabledMessagePairs,
|
||||||
typename FlagLabelPairs>
|
typename FlagLabelPairs>
|
||||||
[[nodiscard]] EditFlagsControl<Flags> CreateEditFlags(
|
[[nodiscard]] EditFlagsControl<Flags, Ui::RpWidget> CreateEditFlags(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
rpl::producer<QString> header,
|
rpl::producer<QString> header,
|
||||||
Flags checked,
|
Flags checked,
|
||||||
|
@ -305,73 +304,283 @@ template <
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddSlowmodeLabels(
|
||||||
|
not_null<Ui::VerticalLayout*> container) {
|
||||||
|
const auto labels = container->add(
|
||||||
|
object_ptr<Ui::FixedHeightWidget>(container, st::normalFont->height),
|
||||||
|
st::slowmodeLabelsMargin);
|
||||||
|
for (auto i = 0; i != kSlowmodeValues; ++i) {
|
||||||
|
const auto seconds = SlowmodeDelayByIndex(i);
|
||||||
|
const auto label = Ui::CreateChild<Ui::LabelSimple>(
|
||||||
|
labels,
|
||||||
|
st::slowmodeLabel,
|
||||||
|
(!seconds
|
||||||
|
? tr::lng_rights_slowmode_off(tr::now)
|
||||||
|
: (seconds < 60)
|
||||||
|
? tr::lng_seconds_tiny(tr::now, lt_count, seconds)
|
||||||
|
: (seconds < 3600)
|
||||||
|
? tr::lng_minutes_tiny(tr::now, lt_count, seconds / 60)
|
||||||
|
: tr::lng_hours_tiny(tr::now, lt_count,seconds / 3600)));
|
||||||
|
rpl::combine(
|
||||||
|
labels->widthValue(),
|
||||||
|
label->widthValue()
|
||||||
|
) | rpl::start_with_next([=](int outer, int inner) {
|
||||||
|
const auto skip = st::localStorageLimitMargin;
|
||||||
|
const auto size = st::localStorageLimitSlider.seekSize;
|
||||||
|
const auto available = outer
|
||||||
|
- skip.left()
|
||||||
|
- skip.right()
|
||||||
|
- size.width();
|
||||||
|
const auto shift = (i == 0)
|
||||||
|
? -(size.width() / 2)
|
||||||
|
: (i + 1 == kSlowmodeValues)
|
||||||
|
? (size.width() - (size.width() / 2) - inner)
|
||||||
|
: (-inner / 2);
|
||||||
|
const auto left = skip.left()
|
||||||
|
+ (size.width() / 2)
|
||||||
|
+ (i * available) / (kSlowmodeValues - 1)
|
||||||
|
+ shift;
|
||||||
|
label->moveToLeft(left, 0, outer);
|
||||||
|
}, label->lifetime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Fn<int()> AddSlowmodeSlider(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
not_null<PeerData*> peer) {
|
||||||
|
using namespace rpl::mappers;
|
||||||
|
|
||||||
|
if (const auto chat = peer->asChat()) {
|
||||||
|
if (!chat->amCreator()) {
|
||||||
|
return [] { return 0; };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto channel = peer->asChannel();
|
||||||
|
auto &lifetime = container->lifetime();
|
||||||
|
const auto secondsCount = lifetime.make_state<rpl::variable<int>>(
|
||||||
|
channel ? channel->slowmodeSeconds() : 0);
|
||||||
|
|
||||||
|
container->add(
|
||||||
|
object_ptr<Ui::BoxContentDivider>(container),
|
||||||
|
{ 0, st::infoProfileSkip, 0, st::infoProfileSkip });
|
||||||
|
|
||||||
|
container->add(
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
tr::lng_rights_slowmode_header(),
|
||||||
|
st::rightsHeaderLabel),
|
||||||
|
st::rightsHeaderMargin);
|
||||||
|
|
||||||
|
AddSlowmodeLabels(container);
|
||||||
|
|
||||||
|
const auto slider = container->add(
|
||||||
|
object_ptr<Ui::MediaSlider>(container, st::localStorageLimitSlider),
|
||||||
|
st::localStorageLimitMargin);
|
||||||
|
slider->resize(st::localStorageLimitSlider.seekSize);
|
||||||
|
slider->setPseudoDiscrete(
|
||||||
|
kSlowmodeValues,
|
||||||
|
SlowmodeDelayByIndex,
|
||||||
|
secondsCount->current(),
|
||||||
|
[=](int seconds) {
|
||||||
|
(*secondsCount) = seconds;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto hasSlowMode = secondsCount->value(
|
||||||
|
) | rpl::map(
|
||||||
|
_1 != 0
|
||||||
|
) | rpl::distinct_until_changed();
|
||||||
|
|
||||||
|
auto useSeconds = secondsCount->value(
|
||||||
|
) | rpl::map(
|
||||||
|
_1 < 60
|
||||||
|
) | rpl::distinct_until_changed();
|
||||||
|
|
||||||
|
auto interval = rpl::combine(
|
||||||
|
std::move(useSeconds),
|
||||||
|
tr::lng_rights_slowmode_interval_seconds(
|
||||||
|
lt_count,
|
||||||
|
secondsCount->value() | tr::to_count()),
|
||||||
|
tr::lng_rights_slowmode_interval_minutes(
|
||||||
|
lt_count,
|
||||||
|
secondsCount->value() | rpl::map(_1 / 60.))
|
||||||
|
) | rpl::map([](
|
||||||
|
bool use,
|
||||||
|
const QString &seconds,
|
||||||
|
const QString &minutes) {
|
||||||
|
return use ? seconds : minutes;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto aboutText = rpl::combine(
|
||||||
|
std::move(hasSlowMode),
|
||||||
|
tr::lng_rights_slowmode_about(),
|
||||||
|
tr::lng_rights_slowmode_about_interval(
|
||||||
|
lt_interval,
|
||||||
|
std::move(interval))
|
||||||
|
) | rpl::map([](
|
||||||
|
bool has,
|
||||||
|
const QString &about,
|
||||||
|
const QString &aboutInterval) {
|
||||||
|
return has ? aboutInterval : about;
|
||||||
|
});
|
||||||
|
|
||||||
|
container->add(
|
||||||
|
object_ptr<Ui::DividerLabel>(
|
||||||
|
container,
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
std::move(aboutText),
|
||||||
|
st::boxDividerLabel),
|
||||||
|
st::proxyAboutPadding),
|
||||||
|
style::margins(0, st::infoProfileSkip, 0, st::infoProfileSkip));
|
||||||
|
|
||||||
|
return [=] { return secondsCount->current(); };
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddSuggestGigagroup(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
Fn<void()> callback) {
|
||||||
|
container->add(
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
tr::lng_rights_gigagroup_title(),
|
||||||
|
st::rightsHeaderLabel),
|
||||||
|
st::rightsHeaderMargin);
|
||||||
|
container->add(EditPeerInfoBox::CreateButton(
|
||||||
|
container,
|
||||||
|
tr::lng_rights_gigagroup_convert(),
|
||||||
|
rpl::single(QString()),
|
||||||
|
std::move(callback),
|
||||||
|
st::peerPermissionsButton,
|
||||||
|
{}));
|
||||||
|
|
||||||
|
container->add(
|
||||||
|
object_ptr<Ui::DividerLabel>(
|
||||||
|
container,
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
tr::lng_rights_gigagroup_about(),
|
||||||
|
st::boxDividerLabel),
|
||||||
|
st::proxyAboutPadding),
|
||||||
|
style::margins(0, st::infoProfileSkip, 0, st::infoProfileSkip));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddBannedButtons(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
|
not_null<PeerData*> peer) {
|
||||||
|
if (const auto chat = peer->asChat()) {
|
||||||
|
if (!chat->amCreator()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto channel = peer->asChannel();
|
||||||
|
container->add(EditPeerInfoBox::CreateButton(
|
||||||
|
container,
|
||||||
|
tr::lng_manage_peer_exceptions(),
|
||||||
|
(channel
|
||||||
|
? Info::Profile::RestrictedCountValue(channel)
|
||||||
|
: rpl::single(0)) | ToPositiveNumberString(),
|
||||||
|
[=] {
|
||||||
|
ParticipantsBoxController::Start(
|
||||||
|
navigation,
|
||||||
|
peer,
|
||||||
|
ParticipantsBoxController::Role::Restricted);
|
||||||
|
},
|
||||||
|
st::peerPermissionsButton,
|
||||||
|
{}));
|
||||||
|
if (channel) {
|
||||||
|
container->add(EditPeerInfoBox::CreateButton(
|
||||||
|
container,
|
||||||
|
tr::lng_manage_peer_removed_users(),
|
||||||
|
Info::Profile::KickedCountValue(channel)
|
||||||
|
| ToPositiveNumberString(),
|
||||||
|
[=] {
|
||||||
|
ParticipantsBoxController::Start(
|
||||||
|
navigation,
|
||||||
|
peer,
|
||||||
|
ParticipantsBoxController::Role::Kicked);
|
||||||
|
},
|
||||||
|
st::peerPermissionsButton,
|
||||||
|
{}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ChatAdminRights DisabledByDefaultRestrictions(not_null<PeerData*> peer) {
|
void ShowEditPeerPermissionsBox(
|
||||||
using Flag = ChatAdminRight;
|
not_null<Ui::GenericBox*> box,
|
||||||
using Restriction = ChatRestriction;
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
|
not_null<PeerData*> channelOrGroup,
|
||||||
|
Fn<void(EditPeerPermissionsBoxResult)> done) {
|
||||||
|
const auto peer = channelOrGroup->migrateToOrMe();
|
||||||
|
|
||||||
|
box->setTitle(tr::lng_manage_peer_permissions());
|
||||||
|
|
||||||
|
const auto inner = box->verticalLayout();
|
||||||
|
|
||||||
|
using Flag = ChatRestriction;
|
||||||
|
using Flags = ChatRestrictions;
|
||||||
|
|
||||||
|
const auto disabledByAdminRights = DisabledByAdminRights(peer);
|
||||||
const auto restrictions = FixDependentRestrictions([&] {
|
const auto restrictions = FixDependentRestrictions([&] {
|
||||||
if (const auto chat = peer->asChat()) {
|
if (const auto chat = peer->asChat()) {
|
||||||
return chat->defaultRestrictions();
|
return chat->defaultRestrictions()
|
||||||
|
| disabledByAdminRights;
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
return channel->defaultRestrictions();
|
return channel->defaultRestrictions()
|
||||||
|
| (channel->isPublic()
|
||||||
|
? (Flag::ChangeInfo | Flag::PinMessages)
|
||||||
|
: Flags(0))
|
||||||
|
| disabledByAdminRights;
|
||||||
}
|
}
|
||||||
Unexpected("User in DisabledByDefaultRestrictions.");
|
Unexpected("User in EditPeerPermissionsBox.");
|
||||||
}());
|
}());
|
||||||
return Flag(0)
|
const auto disabledMessages = [&] {
|
||||||
| ((restrictions & Restriction::PinMessages)
|
auto result = std::map<Flags, QString>();
|
||||||
? Flag(0)
|
result.emplace(
|
||||||
: Flag::PinMessages)
|
disabledByAdminRights,
|
||||||
//
|
tr::lng_rights_permission_cant_edit(tr::now));
|
||||||
// We allow to edit 'invite_users' admin right no matter what
|
if (const auto channel = peer->asChannel()) {
|
||||||
// is chosen in default permissions for 'invite_users', because
|
if (channel->isPublic()
|
||||||
// if everyone can 'invite_users' it handles invite link for admins.
|
|| (channel->isMegagroup() && channel->linkedChat())) {
|
||||||
//
|
result.emplace(
|
||||||
//| ((restrictions & Restriction::AddParticipants)
|
Flag::ChangeInfo | Flag::PinMessages,
|
||||||
// ? Flag(0)
|
tr::lng_rights_permission_unavailable(tr::now));
|
||||||
// : Flag::InviteByLinkOrAdd)
|
|
||||||
//
|
|
||||||
| ((restrictions & Restriction::ChangeInfo)
|
|
||||||
? Flag(0)
|
|
||||||
: Flag::ChangeInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
|
|
||||||
const auto &dependencies = Dependencies(restrictions);
|
|
||||||
|
|
||||||
// Fix iOS bug of saving send_inline like embed_links.
|
|
||||||
// We copy send_stickers to send_inline.
|
|
||||||
if (restrictions & ChatRestriction::SendStickers) {
|
|
||||||
restrictions |= ChatRestriction::SendInline;
|
|
||||||
} else {
|
|
||||||
restrictions &= ~ChatRestriction::SendInline;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the strictest.
|
|
||||||
const auto fixOne = [&] {
|
|
||||||
for (const auto &[first, second] : dependencies) {
|
|
||||||
if ((restrictions & second) && !(restrictions & first)) {
|
|
||||||
restrictions |= first;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return result;
|
||||||
};
|
}();
|
||||||
while (fixOne()) {
|
|
||||||
}
|
|
||||||
return restrictions;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatAdminRights AdminRightsForOwnershipTransfer(
|
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
|
||||||
Data::AdminRightsSetOptions options) {
|
inner,
|
||||||
auto result = ChatAdminRights();
|
tr::lng_rights_default_restrictions_header(),
|
||||||
for (const auto &[flag, label] : AdminRightLabels(options)) {
|
restrictions,
|
||||||
if (!(flag & ChatAdminRight::Anonymous)) {
|
disabledMessages,
|
||||||
result |= flag;
|
{ .isForum = peer->isForum() });
|
||||||
|
|
||||||
|
inner->add(std::move(checkboxes));
|
||||||
|
|
||||||
|
const auto getSlowmodeSeconds = AddSlowmodeSlider(inner, peer);
|
||||||
|
|
||||||
|
if (const auto channel = peer->asChannel()) {
|
||||||
|
if (channel->amCreator()
|
||||||
|
&& channel->membersCount() >= kSuggestGigagroupThreshold) {
|
||||||
|
AddSuggestGigagroup(
|
||||||
|
inner,
|
||||||
|
AboutGigagroupCallback(
|
||||||
|
peer->asChannel(),
|
||||||
|
navigation->parentController()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
AddBannedButtons(inner, navigation, peer);
|
||||||
|
|
||||||
|
box->addButton(tr::lng_settings_save(), [=, rights = getRestrictions] {
|
||||||
|
done({ rights(), getSlowmodeSeconds() });
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
|
||||||
|
box->setWidth(st::boxWideWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fn<void()> AboutGigagroupCallback(
|
Fn<void()> AboutGigagroupCallback(
|
||||||
|
@ -447,286 +656,6 @@ Fn<void()> AboutGigagroupCallback(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
EditPeerPermissionsBox::EditPeerPermissionsBox(
|
|
||||||
QWidget*,
|
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
|
||||||
not_null<PeerData*> peer)
|
|
||||||
: _navigation(navigation)
|
|
||||||
, _peer(peer->migrateToOrMe()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
auto EditPeerPermissionsBox::saveEvents() const -> rpl::producer<Result> {
|
|
||||||
Expects(_save != nullptr);
|
|
||||||
|
|
||||||
return _save->clicks() | rpl::map(_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditPeerPermissionsBox::prepare() {
|
|
||||||
setTitle(tr::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 = FixDependentRestrictions([&] {
|
|
||||||
if (const auto chat = _peer->asChat()) {
|
|
||||||
return chat->defaultRestrictions()
|
|
||||||
| disabledByAdminRights;
|
|
||||||
} else if (const auto channel = _peer->asChannel()) {
|
|
||||||
return channel->defaultRestrictions()
|
|
||||||
| (channel->isPublic()
|
|
||||||
? (Flag::ChangeInfo | Flag::PinMessages)
|
|
||||||
: Flags(0))
|
|
||||||
| disabledByAdminRights;
|
|
||||||
}
|
|
||||||
Unexpected("User in EditPeerPermissionsBox.");
|
|
||||||
}());
|
|
||||||
const auto disabledMessages = [&] {
|
|
||||||
auto result = std::map<Flags, QString>();
|
|
||||||
result.emplace(
|
|
||||||
disabledByAdminRights,
|
|
||||||
tr::lng_rights_permission_cant_edit(tr::now));
|
|
||||||
if (const auto channel = _peer->asChannel()) {
|
|
||||||
if (channel->isPublic()
|
|
||||||
|| (channel->isMegagroup() && channel->linkedChat())) {
|
|
||||||
result.emplace(
|
|
||||||
Flag::ChangeInfo | Flag::PinMessages,
|
|
||||||
tr::lng_rights_permission_unavailable(tr::now));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}();
|
|
||||||
|
|
||||||
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
|
|
||||||
this,
|
|
||||||
tr::lng_rights_default_restrictions_header(),
|
|
||||||
restrictions,
|
|
||||||
disabledMessages,
|
|
||||||
{ .isForum = _peer->isForum() });
|
|
||||||
|
|
||||||
inner->add(std::move(checkboxes));
|
|
||||||
|
|
||||||
const auto getSlowmodeSeconds = addSlowmodeSlider(inner);
|
|
||||||
|
|
||||||
if (const auto channel = _peer->asChannel()) {
|
|
||||||
if (channel->amCreator()
|
|
||||||
&& channel->membersCount() >= kSuggestGigagroupThreshold) {
|
|
||||||
addSuggestGigagroup(inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addBannedButtons(inner);
|
|
||||||
|
|
||||||
_value = [=, rights = getRestrictions]() -> Result {
|
|
||||||
return { rights(), getSlowmodeSeconds() };
|
|
||||||
};
|
|
||||||
_save = addButton(tr::lng_settings_save());
|
|
||||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
|
||||||
|
|
||||||
setDimensionsToContent(st::boxWidth, inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fn<int()> EditPeerPermissionsBox::addSlowmodeSlider(
|
|
||||||
not_null<Ui::VerticalLayout*> container) {
|
|
||||||
using namespace rpl::mappers;
|
|
||||||
|
|
||||||
if (const auto chat = _peer->asChat()) {
|
|
||||||
if (!chat->amCreator()) {
|
|
||||||
return [] { return 0; };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto channel = _peer->asChannel();
|
|
||||||
auto &lifetime = container->lifetime();
|
|
||||||
const auto secondsCount = lifetime.make_state<rpl::variable<int>>(
|
|
||||||
channel ? channel->slowmodeSeconds() : 0);
|
|
||||||
|
|
||||||
container->add(
|
|
||||||
object_ptr<Ui::BoxContentDivider>(container),
|
|
||||||
{ 0, st::infoProfileSkip, 0, st::infoProfileSkip });
|
|
||||||
|
|
||||||
container->add(
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
container,
|
|
||||||
tr::lng_rights_slowmode_header(),
|
|
||||||
st::rightsHeaderLabel),
|
|
||||||
st::rightsHeaderMargin);
|
|
||||||
|
|
||||||
addSlowmodeLabels(container);
|
|
||||||
|
|
||||||
const auto slider = container->add(
|
|
||||||
object_ptr<Ui::MediaSlider>(container, st::localStorageLimitSlider),
|
|
||||||
st::localStorageLimitMargin);
|
|
||||||
slider->resize(st::localStorageLimitSlider.seekSize);
|
|
||||||
slider->setPseudoDiscrete(
|
|
||||||
kSlowmodeValues,
|
|
||||||
SlowmodeDelayByIndex,
|
|
||||||
secondsCount->current(),
|
|
||||||
[=](int seconds) {
|
|
||||||
(*secondsCount) = seconds;
|
|
||||||
});
|
|
||||||
|
|
||||||
auto hasSlowMode = secondsCount->value(
|
|
||||||
) | rpl::map(
|
|
||||||
_1 != 0
|
|
||||||
) | rpl::distinct_until_changed();
|
|
||||||
|
|
||||||
auto useSeconds = secondsCount->value(
|
|
||||||
) | rpl::map(
|
|
||||||
_1 < 60
|
|
||||||
) | rpl::distinct_until_changed();
|
|
||||||
|
|
||||||
auto interval = rpl::combine(
|
|
||||||
std::move(useSeconds),
|
|
||||||
tr::lng_rights_slowmode_interval_seconds(
|
|
||||||
lt_count,
|
|
||||||
secondsCount->value() | tr::to_count()),
|
|
||||||
tr::lng_rights_slowmode_interval_minutes(
|
|
||||||
lt_count,
|
|
||||||
secondsCount->value() | rpl::map(_1 / 60.))
|
|
||||||
) | rpl::map([](
|
|
||||||
bool use,
|
|
||||||
const QString &seconds,
|
|
||||||
const QString &minutes) {
|
|
||||||
return use ? seconds : minutes;
|
|
||||||
});
|
|
||||||
|
|
||||||
auto aboutText = rpl::combine(
|
|
||||||
std::move(hasSlowMode),
|
|
||||||
tr::lng_rights_slowmode_about(),
|
|
||||||
tr::lng_rights_slowmode_about_interval(
|
|
||||||
lt_interval,
|
|
||||||
std::move(interval))
|
|
||||||
) | rpl::map([](
|
|
||||||
bool has,
|
|
||||||
const QString &about,
|
|
||||||
const QString &aboutInterval) {
|
|
||||||
return has ? aboutInterval : about;
|
|
||||||
});
|
|
||||||
|
|
||||||
container->add(
|
|
||||||
object_ptr<Ui::DividerLabel>(
|
|
||||||
container,
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
container,
|
|
||||||
std::move(aboutText),
|
|
||||||
st::boxDividerLabel),
|
|
||||||
st::proxyAboutPadding),
|
|
||||||
style::margins(0, st::infoProfileSkip, 0, st::infoProfileSkip));
|
|
||||||
|
|
||||||
return [=] { return secondsCount->current(); };
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditPeerPermissionsBox::addSlowmodeLabels(
|
|
||||||
not_null<Ui::VerticalLayout*> container) {
|
|
||||||
const auto labels = container->add(
|
|
||||||
object_ptr<Ui::FixedHeightWidget>(container, st::normalFont->height),
|
|
||||||
st::slowmodeLabelsMargin);
|
|
||||||
for (auto i = 0; i != kSlowmodeValues; ++i) {
|
|
||||||
const auto seconds = SlowmodeDelayByIndex(i);
|
|
||||||
const auto label = Ui::CreateChild<Ui::LabelSimple>(
|
|
||||||
labels,
|
|
||||||
st::slowmodeLabel,
|
|
||||||
(!seconds
|
|
||||||
? tr::lng_rights_slowmode_off(tr::now)
|
|
||||||
: (seconds < 60)
|
|
||||||
? tr::lng_seconds_tiny(tr::now, lt_count, seconds)
|
|
||||||
: (seconds < 3600)
|
|
||||||
? tr::lng_minutes_tiny(tr::now, lt_count, seconds / 60)
|
|
||||||
: tr::lng_hours_tiny(tr::now, lt_count,seconds / 3600)));
|
|
||||||
rpl::combine(
|
|
||||||
labels->widthValue(),
|
|
||||||
label->widthValue()
|
|
||||||
) | rpl::start_with_next([=](int outer, int inner) {
|
|
||||||
const auto skip = st::localStorageLimitMargin;
|
|
||||||
const auto size = st::localStorageLimitSlider.seekSize;
|
|
||||||
const auto available = outer
|
|
||||||
- skip.left()
|
|
||||||
- skip.right()
|
|
||||||
- size.width();
|
|
||||||
const auto shift = (i == 0)
|
|
||||||
? -(size.width() / 2)
|
|
||||||
: (i + 1 == kSlowmodeValues)
|
|
||||||
? (size.width() - (size.width() / 2) - inner)
|
|
||||||
: (-inner / 2);
|
|
||||||
const auto left = skip.left()
|
|
||||||
+ (size.width() / 2)
|
|
||||||
+ (i * available) / (kSlowmodeValues - 1)
|
|
||||||
+ shift;
|
|
||||||
label->moveToLeft(left, 0, outer);
|
|
||||||
}, label->lifetime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditPeerPermissionsBox::addSuggestGigagroup(
|
|
||||||
not_null<Ui::VerticalLayout*> container) {
|
|
||||||
container->add(
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
container,
|
|
||||||
tr::lng_rights_gigagroup_title(),
|
|
||||||
st::rightsHeaderLabel),
|
|
||||||
st::rightsHeaderMargin);
|
|
||||||
container->add(EditPeerInfoBox::CreateButton(
|
|
||||||
container,
|
|
||||||
tr::lng_rights_gigagroup_convert(),
|
|
||||||
rpl::single(QString()),
|
|
||||||
AboutGigagroupCallback(
|
|
||||||
_peer->asChannel(),
|
|
||||||
_navigation->parentController()),
|
|
||||||
st::peerPermissionsButton,
|
|
||||||
{}));
|
|
||||||
|
|
||||||
container->add(
|
|
||||||
object_ptr<Ui::DividerLabel>(
|
|
||||||
container,
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
container,
|
|
||||||
tr::lng_rights_gigagroup_about(),
|
|
||||||
st::boxDividerLabel),
|
|
||||||
st::proxyAboutPadding),
|
|
||||||
style::margins(0, st::infoProfileSkip, 0, st::infoProfileSkip));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditPeerPermissionsBox::addBannedButtons(
|
|
||||||
not_null<Ui::VerticalLayout*> container) {
|
|
||||||
if (const auto chat = _peer->asChat()) {
|
|
||||||
if (!chat->amCreator()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto channel = _peer->asChannel();
|
|
||||||
container->add(EditPeerInfoBox::CreateButton(
|
|
||||||
container,
|
|
||||||
tr::lng_manage_peer_exceptions(),
|
|
||||||
(channel
|
|
||||||
? Info::Profile::RestrictedCountValue(channel)
|
|
||||||
: rpl::single(0)) | ToPositiveNumberString(),
|
|
||||||
[=] {
|
|
||||||
ParticipantsBoxController::Start(
|
|
||||||
_navigation,
|
|
||||||
_peer,
|
|
||||||
ParticipantsBoxController::Role::Restricted);
|
|
||||||
},
|
|
||||||
st::peerPermissionsButton,
|
|
||||||
{}));
|
|
||||||
if (channel) {
|
|
||||||
container->add(EditPeerInfoBox::CreateButton(
|
|
||||||
container,
|
|
||||||
tr::lng_manage_peer_removed_users(),
|
|
||||||
Info::Profile::KickedCountValue(channel)
|
|
||||||
| ToPositiveNumberString(),
|
|
||||||
[=] {
|
|
||||||
ParticipantsBoxController::Start(
|
|
||||||
_navigation,
|
|
||||||
_peer,
|
|
||||||
ParticipantsBoxController::Role::Kicked);
|
|
||||||
},
|
|
||||||
st::peerPermissionsButton,
|
|
||||||
{}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<RestrictionLabel> RestrictionLabels(
|
std::vector<RestrictionLabel> RestrictionLabels(
|
||||||
Data::RestrictionsSetOptions options) {
|
Data::RestrictionsSetOptions options) {
|
||||||
using Flag = ChatRestriction;
|
using Flag = ChatRestriction;
|
||||||
|
@ -802,7 +731,7 @@ std::vector<AdminRightLabel> AdminRightLabels(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
|
EditFlagsControl<ChatRestrictions, Ui::RpWidget> CreateEditRestrictions(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
rpl::producer<QString> header,
|
rpl::producer<QString> header,
|
||||||
ChatRestrictions restrictions,
|
ChatRestrictions restrictions,
|
||||||
|
@ -824,7 +753,7 @@ EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
|
EditFlagsControl<ChatAdminRights, Ui::RpWidget> CreateEditAdminRights(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
rpl::producer<QString> header,
|
rpl::producer<QString> header,
|
||||||
ChatAdminRights rights,
|
ChatAdminRights rights,
|
||||||
|
@ -837,3 +766,70 @@ EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
|
||||||
disabledMessages,
|
disabledMessages,
|
||||||
AdminRightLabels(options));
|
AdminRightLabels(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatAdminRights DisabledByDefaultRestrictions(not_null<PeerData*> peer) {
|
||||||
|
using Flag = ChatAdminRight;
|
||||||
|
using Restriction = ChatRestriction;
|
||||||
|
|
||||||
|
const auto restrictions = FixDependentRestrictions([&] {
|
||||||
|
if (const auto chat = peer->asChat()) {
|
||||||
|
return chat->defaultRestrictions();
|
||||||
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
|
return channel->defaultRestrictions();
|
||||||
|
}
|
||||||
|
Unexpected("User in DisabledByDefaultRestrictions.");
|
||||||
|
}());
|
||||||
|
return Flag(0)
|
||||||
|
| ((restrictions & Restriction::PinMessages)
|
||||||
|
? Flag(0)
|
||||||
|
: Flag::PinMessages)
|
||||||
|
//
|
||||||
|
// We allow to edit 'invite_users' admin right no matter what
|
||||||
|
// is chosen in default permissions for 'invite_users', because
|
||||||
|
// if everyone can 'invite_users' it handles invite link for admins.
|
||||||
|
//
|
||||||
|
//| ((restrictions & Restriction::AddParticipants)
|
||||||
|
// ? Flag(0)
|
||||||
|
// : Flag::InviteByLinkOrAdd)
|
||||||
|
//
|
||||||
|
| ((restrictions & Restriction::ChangeInfo)
|
||||||
|
? Flag(0)
|
||||||
|
: Flag::ChangeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
|
||||||
|
const auto &dependencies = Dependencies(restrictions);
|
||||||
|
|
||||||
|
// Fix iOS bug of saving send_inline like embed_links.
|
||||||
|
// We copy send_stickers to send_inline.
|
||||||
|
if (restrictions & ChatRestriction::SendStickers) {
|
||||||
|
restrictions |= ChatRestriction::SendInline;
|
||||||
|
} else {
|
||||||
|
restrictions &= ~ChatRestriction::SendInline;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the strictest.
|
||||||
|
const auto fixOne = [&] {
|
||||||
|
for (const auto &[first, second] : dependencies) {
|
||||||
|
if ((restrictions & second) && !(restrictions & first)) {
|
||||||
|
restrictions |= first;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
while (fixOne()) {
|
||||||
|
}
|
||||||
|
return restrictions;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatAdminRights AdminRightsForOwnershipTransfer(
|
||||||
|
Data::AdminRightsSetOptions options) {
|
||||||
|
auto result = ChatAdminRights();
|
||||||
|
for (const auto &[flag, label] : AdminRightLabels(options)) {
|
||||||
|
if (!(flag & ChatAdminRight::Anonymous)) {
|
||||||
|
result |= flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -7,49 +7,34 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "boxes/abstract_box.h"
|
|
||||||
#include "data/data_chat_participant_status.h"
|
#include "data/data_chat_participant_status.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
class GenericBox;
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
class RpWidget;
|
||||||
class VerticalLayout;
|
class VerticalLayout;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
|
template <typename Object>
|
||||||
|
class object_ptr;
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
class SessionController;
|
class SessionController;
|
||||||
class SessionNavigation;
|
class SessionNavigation;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
class EditPeerPermissionsBox : public Ui::BoxContent {
|
struct EditPeerPermissionsBoxResult final {
|
||||||
public:
|
ChatRestrictions rights;
|
||||||
EditPeerPermissionsBox(
|
int slowmodeSeconds = 0;
|
||||||
QWidget*,
|
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
|
||||||
not_null<PeerData*> peer);
|
|
||||||
|
|
||||||
struct Result {
|
|
||||||
ChatRestrictions rights;
|
|
||||||
int slowmodeSeconds = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
rpl::producer<Result> saveEvents() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void prepare() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Fn<int()> addSlowmodeSlider(not_null<Ui::VerticalLayout*> container);
|
|
||||||
void addSlowmodeLabels(not_null<Ui::VerticalLayout*> container);
|
|
||||||
void addSuggestGigagroup(not_null<Ui::VerticalLayout*> container);
|
|
||||||
void addBannedButtons(not_null<Ui::VerticalLayout*> container);
|
|
||||||
|
|
||||||
const not_null<Window::SessionNavigation*> _navigation;
|
|
||||||
const not_null<PeerData*> _peer;
|
|
||||||
Ui::RoundButton *_save = nullptr;
|
|
||||||
Fn<Result()> _value;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ShowEditPeerPermissionsBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
|
not_null<PeerData*> channelOrGroup,
|
||||||
|
Fn<void(EditPeerPermissionsBoxResult)> done);
|
||||||
|
|
||||||
[[nodiscard]] Fn<void()> AboutGigagroupCallback(
|
[[nodiscard]] Fn<void()> AboutGigagroupCallback(
|
||||||
not_null<ChannelData*> channel,
|
not_null<ChannelData*> channel,
|
||||||
not_null<Window::SessionController*> controller);
|
not_null<Window::SessionController*> controller);
|
||||||
|
@ -68,26 +53,28 @@ struct AdminRightLabel {
|
||||||
[[nodiscard]] std::vector<AdminRightLabel> AdminRightLabels(
|
[[nodiscard]] std::vector<AdminRightLabel> AdminRightLabels(
|
||||||
Data::AdminRightsSetOptions options);
|
Data::AdminRightsSetOptions options);
|
||||||
|
|
||||||
template <typename Flags>
|
template <typename Flags, typename Widget>
|
||||||
struct EditFlagsControl {
|
struct EditFlagsControl {
|
||||||
object_ptr<Ui::RpWidget> widget;
|
object_ptr<Widget> widget;
|
||||||
Fn<Flags()> value;
|
Fn<Flags()> value;
|
||||||
rpl::producer<Flags> changes;
|
rpl::producer<Flags> changes;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
|
[[nodiscard]] auto CreateEditRestrictions(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
rpl::producer<QString> header,
|
rpl::producer<QString> header,
|
||||||
ChatRestrictions restrictions,
|
ChatRestrictions restrictions,
|
||||||
std::map<ChatRestrictions, QString> disabledMessages,
|
std::map<ChatRestrictions, QString> disabledMessages,
|
||||||
Data::RestrictionsSetOptions options);
|
Data::RestrictionsSetOptions options)
|
||||||
|
-> EditFlagsControl<ChatRestrictions, Ui::RpWidget>;
|
||||||
|
|
||||||
[[nodiscard]] EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
|
[[nodiscard]] auto CreateEditAdminRights(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
rpl::producer<QString> header,
|
rpl::producer<QString> header,
|
||||||
ChatAdminRights rights,
|
ChatAdminRights rights,
|
||||||
std::map<ChatAdminRights, QString> disabledMessages,
|
std::map<ChatAdminRights, QString> disabledMessages,
|
||||||
Data::AdminRightsSetOptions options);
|
Data::AdminRightsSetOptions options)
|
||||||
|
-> EditFlagsControl<ChatAdminRights, Ui::RpWidget>;
|
||||||
|
|
||||||
[[nodiscard]] ChatAdminRights DisabledByDefaultRestrictions(
|
[[nodiscard]] ChatAdminRights DisabledByDefaultRestrictions(
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer);
|
||||||
|
|
Loading…
Reference in New Issue