Fix blocking users in channel direct messages.

Fixes #29549.
This commit is contained in:
John Preston 2025-07-14 17:15:25 +04:00
parent 01e313e56b
commit e62881e08b

View file

@ -361,9 +361,14 @@ void CreateModerateMessagesBox(
}); });
} }
if (allCanBan) { if (allCanBan) {
auto ownedWrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>( const auto peer = items.front()->history()->peer;
inner, auto ownedWrap = peer->isMonoforum()
object_ptr<Ui::VerticalLayout>(inner)); ? nullptr
: object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
inner,
object_ptr<Ui::VerticalLayout>(inner));
auto computeRestrictions = Fn<ChatRestrictions()>();
const auto wrap = ownedWrap.data();
Ui::AddSkip(inner); Ui::AddSkip(inner);
Ui::AddSkip(inner); Ui::AddSkip(inner);
@ -371,7 +376,9 @@ void CreateModerateMessagesBox(
object_ptr<Ui::Checkbox>( object_ptr<Ui::Checkbox>(
box, box,
rpl::conditional( rpl::conditional(
ownedWrap->toggledValue(), (ownedWrap
? ownedWrap->toggledValue()
: rpl::single(false)),
tr::lng_restrict_user( tr::lng_restrict_user(
lt_count, lt_count,
rpl::single(participants.size()) | tr::to_count()), rpl::single(participants.size()) | tr::to_count()),
@ -390,136 +397,141 @@ void CreateModerateMessagesBox(
Ui::AddSkip(inner); Ui::AddSkip(inner);
Ui::AddSkip(inner); Ui::AddSkip(inner);
const auto wrap = inner->add(std::move(ownedWrap)); if (ownedWrap) {
const auto container = wrap->entity(); inner->add(std::move(ownedWrap));
wrap->toggle(false, anim::type::instant);
const auto session = &participants.front()->session(); const auto container = wrap->entity();
const auto emojiMargin = QMargins( wrap->toggle(false, anim::type::instant);
-st::moderateBoxExpandInnerSkip,
-st::moderateBoxExpandInnerSkip / 2,
0,
0);
const auto emojiUp = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIcon,
emojiMargin,
false));
const auto emojiDown = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIconDown,
emojiMargin,
false));
auto label = object_ptr<Ui::FlatLabel>( const auto session = &participants.front()->session();
inner, const auto emojiMargin = QMargins(
QString(), -st::moderateBoxExpandInnerSkip,
st::moderateBoxDividerLabel); -st::moderateBoxExpandInnerSkip / 2,
const auto raw = label.data(); 0,
0);
const auto emojiUp = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIcon,
emojiMargin,
false));
const auto emojiDown = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIconDown,
emojiMargin,
false));
auto &lifetime = wrap->lifetime(); auto label = object_ptr<Ui::FlatLabel>(
const auto scrollLifetime = lifetime.make_state<rpl::lifetime>(); inner,
label->setClickHandlerFilter([=]( QString(),
const ClickHandlerPtr &handler, st::moderateBoxDividerLabel);
Qt::MouseButton button) { const auto raw = label.data();
if (button != Qt::LeftButton) {
return false; auto &lifetime = wrap->lifetime();
} const auto scrollLifetime = lifetime.make_state<rpl::lifetime>();
wrap->toggle(!wrap->toggled(), anim::type::normal); label->setClickHandlerFilter([=](
{ const ClickHandlerPtr &handler,
inner->heightValue() | rpl::start_with_next([=] { Qt::MouseButton button) {
if (!wrap->animating()) { if (button != Qt::LeftButton) {
scrollLifetime->destroy(); return false;
Ui::PostponeCall(crl::guard(box, [=] { }
wrap->toggle(!wrap->toggled(), anim::type::normal);
{
inner->heightValue() | rpl::start_with_next([=] {
if (!wrap->animating()) {
scrollLifetime->destroy();
Ui::PostponeCall(crl::guard(box, [=] {
box->scrollToY(std::numeric_limits<int>::max());
}));
} else {
box->scrollToY(std::numeric_limits<int>::max()); box->scrollToY(std::numeric_limits<int>::max());
})); }
} else { }, *scrollLifetime);
box->scrollToY(std::numeric_limits<int>::max()); }
} return true;
}, *scrollLifetime); });
} wrap->toggledValue(
return true; ) | rpl::map([isSingle, emojiUp, emojiDown](bool toggled) {
}); return ((toggled && isSingle)
wrap->toggledValue( ? tr::lng_restrict_user_part
) | rpl::map([isSingle, emojiUp, emojiDown](bool toggled) { : (toggled && !isSingle)
return ((toggled && isSingle) ? tr::lng_restrict_users_part
? tr::lng_restrict_user_part : isSingle
: (toggled && !isSingle) ? tr::lng_restrict_user_full
? tr::lng_restrict_users_part : tr::lng_restrict_users_full)(
: isSingle lt_emoji,
? tr::lng_restrict_user_full rpl::single(toggled ? emojiUp : emojiDown),
: tr::lng_restrict_users_full)( Ui::Text::WithEntities);
lt_emoji, }) | rpl::flatten_latest(
rpl::single(toggled ? emojiUp : emojiDown), ) | rpl::start_with_next([=](const TextWithEntities &text) {
Ui::Text::WithEntities); raw->setMarkedText(
}) | rpl::flatten_latest( Ui::Text::Link(text, u"internal:"_q),
) | rpl::start_with_next([=](const TextWithEntities &text) { Core::TextContext({ .session = session }));
raw->setMarkedText( }, label->lifetime());
Ui::Text::Link(text, u"internal:"_q),
Core::TextContext({ .session = session }));
}, label->lifetime());
Ui::AddSkip(inner); Ui::AddSkip(inner);
inner->add(object_ptr<Ui::DividerLabel>( inner->add(object_ptr<Ui::DividerLabel>(
inner, inner,
std::move(label), std::move(label),
st::defaultBoxDividerLabelPadding, st::defaultBoxDividerLabelPadding,
RectPart::Top | RectPart::Bottom)); RectPart::Top | RectPart::Bottom));
using Flag = ChatRestriction; using Flag = ChatRestriction;
using Flags = ChatRestrictions; using Flags = ChatRestrictions;
const auto peer = items.front()->history()->peer; const auto chat = peer->asChat();
const auto chat = peer->asChat(); const auto channel = peer->asChannel();
const auto channel = peer->asChannel(); const auto defaultRestrictions = chat
const auto defaultRestrictions = chat ? chat->defaultRestrictions()
? chat->defaultRestrictions() : channel->defaultRestrictions();
: channel->defaultRestrictions(); const auto prepareFlags = FixDependentRestrictions(
const auto prepareFlags = FixDependentRestrictions( defaultRestrictions
defaultRestrictions | ((channel && channel->isPublic())
| ((channel && channel->isPublic()) ? (Flag::ChangeInfo | Flag::PinMessages)
? (Flag::ChangeInfo | Flag::PinMessages) : Flags(0)));
: Flags(0))); const auto disabledMessages = [&] {
const auto disabledMessages = [&] { auto result = base::flat_map<Flags, QString>();
auto result = base::flat_map<Flags, QString>(); {
{ const auto disabled = FixDependentRestrictions(
const auto disabled = FixDependentRestrictions( defaultRestrictions
defaultRestrictions | ((channel && channel->isPublic())
| ((channel && channel->isPublic()) ? (Flag::ChangeInfo | Flag::PinMessages)
? (Flag::ChangeInfo | Flag::PinMessages) : Flags(0)));
: Flags(0))); result.emplace(
result.emplace( disabled,
disabled, tr::lng_rights_restriction_for_all(tr::now));
tr::lng_rights_restriction_for_all(tr::now)); }
} return result;
return result; }();
}();
Ui::AddSubsectionTitle( Ui::AddSubsectionTitle(
inner, inner,
rpl::conditional( rpl::conditional(
rpl::single(isSingle), rpl::single(isSingle),
tr::lng_restrict_users_part_single_header(), tr::lng_restrict_users_part_single_header(),
tr::lng_restrict_users_part_header( tr::lng_restrict_users_part_header(
lt_count, lt_count,
rpl::single(participants.size()) | tr::to_count()))); rpl::single(participants.size()) | tr::to_count())));
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions( auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
box, box,
prepareFlags, prepareFlags,
disabledMessages, disabledMessages,
{ .isForum = peer->isForum() }); { .isForum = peer->isForum() });
std::move(changes) | rpl::start_with_next([=] { computeRestrictions = getRestrictions;
ban->setChecked(true); std::move(changes) | rpl::start_with_next([=] {
}, ban->lifetime()); ban->setChecked(true);
Ui::AddSkip(container); }, ban->lifetime());
Ui::AddDivider(container); Ui::AddSkip(container);
Ui::AddSkip(container); Ui::AddDivider(container);
container->add(std::move(checkboxes)); Ui::AddSkip(container);
container->add(std::move(checkboxes));
}
// Handle confirmation manually. // Handle confirmation manually.
confirms->events() | rpl::start_with_next([=] { confirms->events() | rpl::start_with_next([=] {
if (ban->checked() && controller->collectRequests) { if (ban->checked() && controller->collectRequests) {
const auto kick = !wrap->toggled(); const auto kick = !wrap || !wrap->toggled();
const auto restrictions = getRestrictions(); const auto restrictions = computeRestrictions
? computeRestrictions()
: ChatRestrictions();
const auto request = [=]( const auto request = [=](
not_null<PeerData*> peer, not_null<PeerData*> peer,
not_null<ChannelData*> channel) { not_null<ChannelData*> channel) {
@ -532,10 +544,15 @@ void CreateModerateMessagesBox(
nullptr, nullptr,
nullptr); nullptr);
} else { } else {
channel->session().api().chatParticipants().kick( const auto block = channel->isMonoforum()
channel, ? channel->monoforumBroadcast()
peer, : channel.get();
{ channel->restrictions(), 0 }); if (block) {
block->session().api().chatParticipants().kick(
block,
peer,
{ block->restrictions(), 0 });
}
} }
}; };
sequentiallyRequest(request, controller->collectRequests()); sequentiallyRequest(request, controller->collectRequests());