mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added support of universal list of nested permission flags.
This commit is contained in:
parent
db7a251ceb
commit
d823db32fc
1 changed files with 129 additions and 94 deletions
|
@ -42,6 +42,54 @@ namespace {
|
||||||
constexpr auto kSlowmodeValues = 7;
|
constexpr auto kSlowmodeValues = 7;
|
||||||
constexpr auto kSuggestGigagroupThreshold = 199000;
|
constexpr auto kSuggestGigagroupThreshold = 199000;
|
||||||
|
|
||||||
|
struct NestedRestrictionLabels {
|
||||||
|
std::optional<rpl::producer<QString>> nestedLabel;
|
||||||
|
std::vector<RestrictionLabel> restrictionLabels;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] auto NestedRestrictionLabelsList(
|
||||||
|
Data::RestrictionsSetOptions options) {
|
||||||
|
using Flag = ChatRestriction;
|
||||||
|
|
||||||
|
auto first = std::vector<RestrictionLabel>{
|
||||||
|
{ Flag::SendOther, tr::lng_rights_chat_send_text(tr::now) },
|
||||||
|
// { Flag::SendMedia, tr::lng_rights_chat_send_media(tr::now) },
|
||||||
|
};
|
||||||
|
auto inner = std::vector<RestrictionLabel>{
|
||||||
|
{ Flag::SendPhotos, tr::lng_rights_chat_photos(tr::now) },
|
||||||
|
{ Flag::SendVideos, tr::lng_rights_chat_videos(tr::now) },
|
||||||
|
{ Flag::SendVideoMessages, tr::lng_rights_chat_video_messages(tr::now) },
|
||||||
|
{ Flag::SendMusic, tr::lng_rights_chat_music(tr::now) },
|
||||||
|
{ Flag::SendVoiceMessages, tr::lng_rights_chat_voice_messages(tr::now) },
|
||||||
|
{ Flag::SendFiles, tr::lng_rights_chat_files(tr::now) },
|
||||||
|
{ Flag::SendStickers
|
||||||
|
| Flag::SendGifs
|
||||||
|
| Flag::SendGames
|
||||||
|
| Flag::SendInline, tr::lng_rights_chat_stickers(tr::now) },
|
||||||
|
{ Flag::EmbedLinks, tr::lng_rights_chat_send_links(tr::now) },
|
||||||
|
{ Flag::SendPolls, tr::lng_rights_chat_send_polls(tr::now) },
|
||||||
|
};
|
||||||
|
auto second = std::vector<RestrictionLabel>{
|
||||||
|
{ Flag::AddParticipants, tr::lng_rights_chat_add_members(tr::now) },
|
||||||
|
{ Flag::CreateTopics, tr::lng_rights_group_add_topics(tr::now) },
|
||||||
|
{ Flag::PinMessages, tr::lng_rights_group_pin(tr::now) },
|
||||||
|
{ Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) },
|
||||||
|
};
|
||||||
|
if (!options.isForum) {
|
||||||
|
second.erase(
|
||||||
|
ranges::remove(
|
||||||
|
second,
|
||||||
|
Flag::CreateTopics,
|
||||||
|
&RestrictionLabel::flags),
|
||||||
|
end(second));
|
||||||
|
}
|
||||||
|
return std::vector<NestedRestrictionLabels>{
|
||||||
|
{ std::nullopt, std::move(first) },
|
||||||
|
{ tr::lng_rights_chat_send_media(), std::move(inner) },
|
||||||
|
{ std::nullopt, std::move(second) },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
int SlowmodeDelayByIndex(int index) {
|
int SlowmodeDelayByIndex(int index) {
|
||||||
Expects(index >= 0 && index < kSlowmodeValues);
|
Expects(index >= 0 && index < kSlowmodeValues);
|
||||||
|
|
||||||
|
@ -229,12 +277,11 @@ ChatRestrictions DisabledByAdminRights(not_null<PeerData*> peer) {
|
||||||
: Flag::ChangeInfo);
|
: Flag::ChangeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<Ui::RpWidget*> SendMediaToggle(
|
not_null<Ui::RpWidget*> AddInnerToggle(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
rpl::producer<int> checkedValue,
|
std::vector<not_null<Ui::AbstractCheckView*>> innerCheckViews,
|
||||||
int total,
|
|
||||||
not_null<Ui::SlideWrap<>*> wrap,
|
not_null<Ui::SlideWrap<>*> wrap,
|
||||||
Fn<void(bool)> toggleMedia,
|
rpl::producer<QString> buttonLabel,
|
||||||
std::optional<QString> locked) {
|
std::optional<QString> locked) {
|
||||||
const auto &stButton = st::rightsButton;
|
const auto &stButton = st::rightsButton;
|
||||||
const auto button = container->add(object_ptr<Ui::SettingsButton>(
|
const auto button = container->add(object_ptr<Ui::SettingsButton>(
|
||||||
|
@ -252,10 +299,24 @@ not_null<Ui::RpWidget*> SendMediaToggle(
|
||||||
}
|
}
|
||||||
Ui::ToggleView checkView;
|
Ui::ToggleView checkView;
|
||||||
Ui::Animations::Simple animation;
|
Ui::Animations::Simple animation;
|
||||||
|
rpl::event_stream<> anyChanges;
|
||||||
|
std::vector<not_null<Ui::AbstractCheckView*>> innerChecks;
|
||||||
};
|
};
|
||||||
const auto state = button->lifetime().make_state<State>(
|
const auto state = button->lifetime().make_state<State>(
|
||||||
stButton.toggle,
|
stButton.toggle,
|
||||||
[=] { toggleButton->update(); });
|
[=] { toggleButton->update(); });
|
||||||
|
state->innerChecks = std::move(innerCheckViews);
|
||||||
|
const auto countChecked = [=] {
|
||||||
|
return ranges::count_if(
|
||||||
|
state->innerChecks,
|
||||||
|
[](const auto &v) { return v->checked(); });
|
||||||
|
};
|
||||||
|
for (const auto &innerCheck : state->innerChecks) {
|
||||||
|
innerCheck->checkedChanges(
|
||||||
|
) | rpl::to_empty | rpl::start_to_stream(
|
||||||
|
state->anyChanges,
|
||||||
|
button->lifetime());
|
||||||
|
}
|
||||||
const auto checkView = &state->checkView;
|
const auto checkView = &state->checkView;
|
||||||
{
|
{
|
||||||
const auto separator = Ui::CreateChild<Ui::RpWidget>(container.get());
|
const auto separator = Ui::CreateChild<Ui::RpWidget>(container.get());
|
||||||
|
@ -296,23 +357,27 @@ not_null<Ui::RpWidget*> SendMediaToggle(
|
||||||
(s.height() - checkWidget->height()) / 2);
|
(s.height() - checkWidget->height()) / 2);
|
||||||
}, toggleButton->lifetime());
|
}, toggleButton->lifetime());
|
||||||
}
|
}
|
||||||
rpl::duplicate(
|
state->anyChanges.events_starting_with(
|
||||||
checkedValue
|
rpl::empty_value()
|
||||||
) | rpl::start_with_next([=](int count) {
|
) | rpl::map(countChecked) | rpl::start_with_next([=](int count) {
|
||||||
checkView->setChecked(count > 0, anim::type::normal);
|
checkView->setChecked(count > 0, anim::type::normal);
|
||||||
}, toggleButton->lifetime());
|
}, toggleButton->lifetime());
|
||||||
checkView->setLocked(locked.has_value());
|
checkView->setLocked(locked.has_value());
|
||||||
checkView->finishAnimating();
|
checkView->finishAnimating();
|
||||||
|
|
||||||
|
const auto totalInnerChecks = state->innerChecks.size();
|
||||||
const auto label = Ui::CreateChild<Ui::FlatLabel>(
|
const auto label = Ui::CreateChild<Ui::FlatLabel>(
|
||||||
button,
|
button,
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
tr::lng_rights_chat_send_media(),
|
std::move(buttonLabel),
|
||||||
rpl::duplicate(checkedValue)
|
state->anyChanges.events_starting_with(
|
||||||
) | rpl::map([total](const QString &t, int checked) {
|
rpl::empty_value()
|
||||||
|
) | rpl::map(countChecked)
|
||||||
|
) | rpl::map([=](const QString &t, int checked) {
|
||||||
auto count = Ui::Text::Bold(" "
|
auto count = Ui::Text::Bold(" "
|
||||||
+ QString::number(checked)
|
+ QString::number(checked)
|
||||||
+ '/'
|
+ '/'
|
||||||
+ QString::number(total));
|
+ QString::number(totalInnerChecks));
|
||||||
return TextWithEntities::Simple(t).append(std::move(count));
|
return TextWithEntities::Simple(t).append(std::move(count));
|
||||||
}));
|
}));
|
||||||
label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
@ -383,7 +448,10 @@ not_null<Ui::RpWidget*> SendMediaToggle(
|
||||||
toggleButton->clicks(
|
toggleButton->clicks(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
if (!handleLocked()) {
|
if (!handleLocked()) {
|
||||||
toggleMedia(!checkView->checked());
|
const auto checked = !checkView->checked();
|
||||||
|
for (const auto &innerCheck : state->innerChecks) {
|
||||||
|
innerCheck->setChecked(checked, anim::type::normal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, toggleButton->lifetime());
|
}, toggleButton->lifetime());
|
||||||
|
|
||||||
|
@ -399,15 +467,12 @@ template <
|
||||||
rpl::producer<QString> header,
|
rpl::producer<QString> header,
|
||||||
Flags checked,
|
Flags checked,
|
||||||
const DisabledMessagePairs &disabledMessagePairs,
|
const DisabledMessagePairs &disabledMessagePairs,
|
||||||
const FlagLabelPairs &flagLabelPairs) {
|
const FlagLabelPairs &flagLabelPairsNested) {
|
||||||
struct State final {
|
struct State final {
|
||||||
std::map<Flags, not_null<Ui::AbstractCheckView*>> checkViews;
|
std::map<Flags, not_null<Ui::AbstractCheckView*>> checkViews;
|
||||||
std::vector<not_null<Ui::AbstractCheckView*>> mediaChecks;
|
|
||||||
rpl::event_stream<> anyChanges;
|
rpl::event_stream<> anyChanges;
|
||||||
};
|
};
|
||||||
const auto state = container->lifetime().make_state<State>();
|
const auto state = container->lifetime().make_state<State>();
|
||||||
const auto mediaRestrictions = MediaRestrictions();
|
|
||||||
auto inner = (Ui::VerticalLayout*)(nullptr);
|
|
||||||
|
|
||||||
const auto value = [=] {
|
const auto value = [=] {
|
||||||
auto result = Flags(0);
|
auto result = Flags(0);
|
||||||
|
@ -424,12 +489,6 @@ template <
|
||||||
static const auto dependencies = Dependencies(Flags());
|
static const auto dependencies = Dependencies(Flags());
|
||||||
ApplyDependencies(state->checkViews, dependencies, view);
|
ApplyDependencies(state->checkViews, dependencies, view);
|
||||||
};
|
};
|
||||||
const auto toggleAllMedia = [=](bool toggled) {
|
|
||||||
for (const auto &checkView : state->mediaChecks) {
|
|
||||||
checkView->setChecked(toggled, anim::type::normal);
|
|
||||||
}
|
|
||||||
applyDependencies(nullptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
container->add(
|
container->add(
|
||||||
object_ptr<Ui::FlatLabel>(
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
@ -438,7 +497,11 @@ template <
|
||||||
st::rightsHeaderLabel),
|
st::rightsHeaderLabel),
|
||||||
st::rightsHeaderMargin);
|
st::rightsHeaderMargin);
|
||||||
|
|
||||||
auto addCheckbox = [&](Flags flags, const QString &text) {
|
const auto addCheckbox = [&](
|
||||||
|
not_null<Ui::VerticalLayout*> verticalLayout,
|
||||||
|
bool isInner,
|
||||||
|
Flags flags,
|
||||||
|
const QString &text) {
|
||||||
const auto lockedIt = ranges::find_if(
|
const auto lockedIt = ranges::find_if(
|
||||||
disabledMessagePairs,
|
disabledMessagePairs,
|
||||||
[&](const auto &pair) { return (pair.first & flags) != 0; });
|
[&](const auto &pair) { return (pair.first & flags) != 0; });
|
||||||
|
@ -446,52 +509,22 @@ template <
|
||||||
? std::make_optional(lockedIt->second)
|
? std::make_optional(lockedIt->second)
|
||||||
: std::nullopt;
|
: std::nullopt;
|
||||||
const auto toggled = ((checked & flags) != 0);
|
const auto toggled = ((checked & flags) != 0);
|
||||||
const auto isMedia = ranges::any_of(
|
|
||||||
mediaRestrictions,
|
|
||||||
[&](auto f) { return (flags & f); });
|
|
||||||
|
|
||||||
const auto checkView = [&]() -> not_null<Ui::AbstractCheckView*> {
|
const auto checkView = [&]() -> not_null<Ui::AbstractCheckView*> {
|
||||||
if (isMedia) {
|
if (isInner) {
|
||||||
if (!inner) {
|
const auto checkbox = verticalLayout->add(
|
||||||
auto wrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
|
||||||
container,
|
|
||||||
object_ptr<Ui::VerticalLayout>(container));
|
|
||||||
const auto raw = wrap.data();
|
|
||||||
raw->hide(anim::type::instant);
|
|
||||||
inner = raw->entity();
|
|
||||||
SendMediaToggle(
|
|
||||||
container,
|
|
||||||
rpl::single(
|
|
||||||
0
|
|
||||||
) | rpl::then(state->anyChanges.events(
|
|
||||||
) | rpl::map([=]() -> int {
|
|
||||||
return ranges::count_if(
|
|
||||||
state->mediaChecks,
|
|
||||||
[](const auto &v) { return v->checked(); });
|
|
||||||
})),
|
|
||||||
mediaRestrictions.size(),
|
|
||||||
raw,
|
|
||||||
toggleAllMedia,
|
|
||||||
locked);
|
|
||||||
container->add(std::move(wrap));
|
|
||||||
container->widthValue(
|
|
||||||
) | rpl::start_with_next([=](int w) {
|
|
||||||
raw->resizeToWidth(w);
|
|
||||||
}, raw->lifetime());
|
|
||||||
}
|
|
||||||
const auto checkbox = inner->add(
|
|
||||||
object_ptr<Ui::Checkbox>(
|
object_ptr<Ui::Checkbox>(
|
||||||
inner,
|
verticalLayout,
|
||||||
text,
|
text,
|
||||||
toggled,
|
toggled,
|
||||||
st::settingsCheckbox),
|
st::settingsCheckbox),
|
||||||
st::rightsButton.padding);
|
st::rightsButton.padding);
|
||||||
const auto button = Ui::CreateChild<Ui::RippleButton>(
|
const auto button = Ui::CreateChild<Ui::RippleButton>(
|
||||||
inner,
|
verticalLayout.get(),
|
||||||
st::defaultRippleAnimation);
|
st::defaultRippleAnimation);
|
||||||
button->stackUnder(checkbox);
|
button->stackUnder(checkbox);
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
inner->widthValue(),
|
verticalLayout->widthValue(),
|
||||||
checkbox->geometryValue()
|
checkbox->geometryValue()
|
||||||
) | rpl::start_with_next([=](int w, const QRect &r) {
|
) | rpl::start_with_next([=](int w, const QRect &r) {
|
||||||
button->setGeometry(0, r.y(), w, r.height());
|
button->setGeometry(0, r.y(), w, r.height());
|
||||||
|
@ -504,12 +537,10 @@ template <
|
||||||
anim::type::normal);
|
anim::type::normal);
|
||||||
});
|
});
|
||||||
|
|
||||||
state->mediaChecks.push_back(checkView);
|
|
||||||
|
|
||||||
return checkView;
|
return checkView;
|
||||||
} else {
|
} else {
|
||||||
const auto button = Settings::AddButton(
|
const auto button = Settings::AddButton(
|
||||||
container,
|
verticalLayout,
|
||||||
rpl::single(text),
|
rpl::single(text),
|
||||||
st::rightsButton);
|
st::rightsButton);
|
||||||
const auto toggle = Ui::CreateChild<Ui::RpWidget>(
|
const auto toggle = Ui::CreateChild<Ui::RpWidget>(
|
||||||
|
@ -557,10 +588,40 @@ template <
|
||||||
state->anyChanges.fire({});
|
state->anyChanges.fire({});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, container->lifetime());
|
}, verticalLayout->lifetime());
|
||||||
|
|
||||||
|
return checkView;
|
||||||
};
|
};
|
||||||
for (const auto &[flags, label] : flagLabelPairs) {
|
for (const auto &[nestedLabel, flagLabelPairs] : flagLabelPairsNested) {
|
||||||
addCheckbox(flags, label);
|
const auto isInner = nestedLabel.has_value();
|
||||||
|
auto wrap = isInner
|
||||||
|
? object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
container,
|
||||||
|
object_ptr<Ui::VerticalLayout>(container))
|
||||||
|
: object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>{ nullptr };
|
||||||
|
const auto verticalLayout = wrap ? wrap->entity() : container.get();
|
||||||
|
auto innerChecks = std::vector<not_null<Ui::AbstractCheckView*>>();
|
||||||
|
for (const auto &[flags, label] : flagLabelPairs) {
|
||||||
|
const auto c = addCheckbox(verticalLayout, isInner, flags, label);
|
||||||
|
if (isInner) {
|
||||||
|
innerChecks.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wrap) {
|
||||||
|
const auto raw = wrap.data();
|
||||||
|
raw->hide(anim::type::instant);
|
||||||
|
AddInnerToggle(
|
||||||
|
container,
|
||||||
|
innerChecks,
|
||||||
|
raw,
|
||||||
|
*nestedLabel,
|
||||||
|
std::nullopt);
|
||||||
|
container->add(std::move(wrap));
|
||||||
|
container->widthValue(
|
||||||
|
) | rpl::start_with_next([=](int w) {
|
||||||
|
raw->resizeToWidth(w);
|
||||||
|
}, raw->lifetime());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyDependencies(nullptr);
|
applyDependencies(nullptr);
|
||||||
|
@ -1026,35 +1087,9 @@ Fn<void()> AboutGigagroupCallback(
|
||||||
|
|
||||||
std::vector<RestrictionLabel> RestrictionLabels(
|
std::vector<RestrictionLabel> RestrictionLabels(
|
||||||
Data::RestrictionsSetOptions options) {
|
Data::RestrictionsSetOptions options) {
|
||||||
using Flag = ChatRestriction;
|
auto result = std::vector<RestrictionLabel>();
|
||||||
|
for (const auto &[_, r] : NestedRestrictionLabelsList(options)) {
|
||||||
auto result = std::vector<RestrictionLabel>{
|
result.insert(result.end(), r.begin(), r.end());
|
||||||
{ Flag::SendOther, tr::lng_rights_chat_send_text(tr::now) },
|
|
||||||
// { Flag::SendMedia, tr::lng_rights_chat_send_media(tr::now) },
|
|
||||||
{ Flag::SendPhotos, tr::lng_rights_chat_photos(tr::now) },
|
|
||||||
{ Flag::SendVideos, tr::lng_rights_chat_videos(tr::now) },
|
|
||||||
{ Flag::SendVideoMessages, tr::lng_rights_chat_video_messages(tr::now) },
|
|
||||||
{ Flag::SendMusic, tr::lng_rights_chat_music(tr::now) },
|
|
||||||
{ Flag::SendVoiceMessages, tr::lng_rights_chat_voice_messages(tr::now) },
|
|
||||||
{ Flag::SendFiles, tr::lng_rights_chat_files(tr::now) },
|
|
||||||
{ Flag::SendStickers
|
|
||||||
| Flag::SendGifs
|
|
||||||
| Flag::SendGames
|
|
||||||
| Flag::SendInline, tr::lng_rights_chat_stickers(tr::now) },
|
|
||||||
{ Flag::EmbedLinks, tr::lng_rights_chat_send_links(tr::now) },
|
|
||||||
{ Flag::SendPolls, tr::lng_rights_chat_send_polls(tr::now) },
|
|
||||||
{ Flag::AddParticipants, tr::lng_rights_chat_add_members(tr::now) },
|
|
||||||
{ Flag::CreateTopics, tr::lng_rights_group_add_topics(tr::now) },
|
|
||||||
{ Flag::PinMessages, tr::lng_rights_group_pin(tr::now) },
|
|
||||||
{ Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) },
|
|
||||||
};
|
|
||||||
if (!options.isForum) {
|
|
||||||
result.erase(
|
|
||||||
ranges::remove(
|
|
||||||
result,
|
|
||||||
Flag::CreateTopics,
|
|
||||||
&RestrictionLabel::flags),
|
|
||||||
end(result));
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1111,7 +1146,7 @@ EditFlagsControl<ChatRestrictions, Ui::RpWidget> CreateEditRestrictions(
|
||||||
header,
|
header,
|
||||||
NegateRestrictions(restrictions),
|
NegateRestrictions(restrictions),
|
||||||
disabledMessages,
|
disabledMessages,
|
||||||
RestrictionLabels(options));
|
NestedRestrictionLabelsList(options));
|
||||||
result.widget = std::move(widget);
|
result.widget = std::move(widget);
|
||||||
result.value = [original = std::move(result.value)]{
|
result.value = [original = std::move(result.value)]{
|
||||||
return NegateRestrictions(original());
|
return NegateRestrictions(original());
|
||||||
|
|
Loading…
Add table
Reference in a new issue