diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp index b72de130f..24293ecf4 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp @@ -57,6 +57,59 @@ int SlowmodeDelayByIndex(int index) { Unexpected("Index in SlowmodeDelayByIndex."); } +template +void ApplyDependencies( + const CheckboxesMap &checkboxes, + const DependenciesMap &dependencies, + QPointer changed) { + const auto checkAndApply = [&]( + auto &¤t, + auto dependency, + bool isChecked) { + for (auto &&checkbox : checkboxes) { + if ((checkbox.first & dependency) + && (checkbox.second->checked() == isChecked)) { + current->setChecked(isChecked); + return true; + } + } + return false; + }; + const auto applySomeDependency = [&] { + auto result = false; + for (auto &&entry : checkboxes) { + if (entry.second == changed) { + continue; + } + auto isChecked = entry.second->checked(); + for (auto &&dependency : dependencies) { + const auto check = isChecked + ? dependency.first + : dependency.second; + if (entry.first & check) { + if (checkAndApply( + entry.second, + (isChecked + ? dependency.second + : dependency.first), + !isChecked)) { + result = true; + break; + } + } + } + } + return result; + }; + + const auto maxFixesCount = int(checkboxes.size()); + for (auto i = 0; i != maxFixesCount; ++i) { + if (!applySomeDependency()) { + break; + } + }; +} + auto Dependencies(ChatRestrictions) -> std::vector> { using Flag = ChatRestriction; @@ -524,6 +577,103 @@ template < }; } +template < + typename Flags, + typename DisabledMessagePairs, + typename FlagLabelPairs> +[[nodiscard]] EditFlagsControl CreateEditAdminFlags( + QWidget *parent, + rpl::producer header, + Flags checked, + const DisabledMessagePairs &disabledMessagePairs, + const FlagLabelPairs &flagLabelPairs) { + auto widget = object_ptr(parent); + const auto container = widget.data(); + + const auto checkboxes = container->lifetime( + ).make_state>>(); + + const auto value = [=] { + auto result = Flags(0); + for (const auto &[flags, checkbox] : *checkboxes) { + if (checkbox->checked()) { + result |= flags; + } else { + result &= ~flags; + } + } + return result; + }; + + const auto changes = container->lifetime( + ).make_state>(); + + const auto applyDependencies = [=](Ui::Checkbox *control) { + static const auto dependencies = Dependencies(Flags()); + ApplyDependencies(*checkboxes, dependencies, control); + }; + + container->add( + object_ptr( + container, + std::move(header), + st::rightsHeaderLabel), + 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( + st::rightsToggle, + toggled); + toggle->setLocked(locked.has_value()); + const auto control = container->add( + object_ptr( + container, + text, + st::rightsCheckbox, + std::move(toggle)), + st::rightsToggleMargin); + control->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { + if (locked.has_value()) { + if (checked != toggled) { + Ui::ShowMultilineToast({ + .parentOverride = parent, + .text = { *locked }, + }); + control->setChecked(toggled); + } + } else { + InvokeQueued(control, [=] { + applyDependencies(control); + changes->fire({}); + }); + } + }, control->lifetime()); + checkboxes->emplace(flags, control); + }; + for (const auto &[flags, label] : flagLabelPairs) { + addCheckbox(flags, label); + } + + applyDependencies(nullptr); + for (const auto &[flags, checkbox] : *checkboxes) { + checkbox->finishAnimating(); + } + + return { + std::move(widget), + value, + changes->events() | rpl::map(value) + }; +} + void AddSlowmodeLabels( not_null container) { const auto labels = container->add( @@ -1044,25 +1194,12 @@ EditFlagsControl CreateEditAdminRights( ChatAdminRights rights, std::map disabledMessages, Data::AdminRightsSetOptions options) { - auto widget = object_ptr(parent); - const auto checkboxFactory = [&]( - not_null container, - ChatAdminRights flags, - const QString &text, - bool toggled, - std::optional, - auto&&) { - return AddDefaultCheckbox(container, text, toggled); - }; - auto result = CreateEditFlags( - widget.data(), + return CreateEditAdminFlags( + parent, header, rights, disabledMessages, - AdminRightLabels(options), - checkboxFactory); - result.widget = std::move(widget); - return result; + AdminRightLabels(options)); } ChatAdminRights DisabledByDefaultRestrictions(not_null peer) {