Set custom reactions hard limit to max level.

This commit is contained in:
John Preston 2023-11-29 18:25:27 +04:00
parent 514ced1d8e
commit 2611899448
6 changed files with 54 additions and 9 deletions

View file

@ -1357,6 +1357,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_manage_peer_reactions_level#other" = "Your channel needs to reach level **{count}** to use **{same_count}** custom reactions.";
"lng_manage_peer_reactions_boost" = "Boost your channel {link}.";
"lng_manage_peer_reactions_boost_link" = "here";
"lng_manage_peer_reactions_limit" = "Channels can't have more custom reactions.";
"lng_manage_peer_antispam" = "Aggressive Anti-Spam";
"lng_manage_peer_antispam_about" = "Telegram will filter more spam but may occasionally affect ordinary messages. You can report False Positives in Recent Actions.";

View file

@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h"
#include "data/data_message_reactions.h"
#include "data/data_peer_values.h"
#include "data/data_premium_limits.h"
#include "data/data_user.h"
#include "history/admin_log/history_admin_log_section.h"
#include "info/boosts/info_boosts_widget.h"
@ -1315,6 +1316,8 @@ void Controller::editReactions() {
EditAllowedReactionsArgs{
.navigation = _navigation,
.allowedCustomReactions = counters.level,
.customReactionsHardLimit = Data::PremiumLimits(
&_peer->session()).maxBoostLevel(),
.list = _navigation->session().data().reactions().list(
Data::Reactions::Type::Active),
.allowed = Data::PeerAllowedReactions(_peer),

View file

@ -42,6 +42,10 @@ constexpr auto kDisabledEmojiOpacity = 0.4;
struct UniqueCustomEmojiContext {
std::vector<DocumentId> ids;
Fn<bool(DocumentId)> applyHardLimit;
int hardLimit = 0;
int hardLimitChecked = 0;
bool hardLimitHit = false;
};
class MaybeDisabledEmoji final : public Ui::Text::CustomEmoji {
@ -153,6 +157,7 @@ bool MaybeDisabledEmoji::readyInDefaultState() {
not_null<QTextDocument*> document,
UniqueCustomEmojiContext &context) {
context.ids.clear();
context.hardLimitChecked = 0;
auto removeFrom = 0;
auto removeTill = 0;
auto block = document->begin();
@ -168,11 +173,20 @@ bool MaybeDisabledEmoji::readyInDefaultState() {
}
const auto id = format.property(Ui::InputField::kCustomEmojiId);
const auto documentId = id.toULongLong();
const auto applyHardLimit = context.applyHardLimit(documentId);
if (ranges::contains(context.ids, documentId)) {
removeTill += fragment.length();
break;
} else if (applyHardLimit
&& context.hardLimitChecked >= context.hardLimit) {
context.hardLimitHit = true;
removeTill += fragment.length();
break;
}
context.ids.push_back(documentId);
if (applyHardLimit) {
++context.hardLimitChecked;
}
}
while (removeTill == removeFrom) {
block = block.next();
@ -202,7 +216,9 @@ bool RemoveNonCustomEmoji(
void SetupOnlyCustomEmojiField(
not_null<Ui::InputField*> field,
Fn<void(std::vector<DocumentId>)> callback) {
Fn<void(std::vector<DocumentId>, bool)> callback,
Fn<bool(DocumentId)> applyHardLimit,
int customHardLimit) {
field->setTagMimeProcessor(AllowOnlyCustomEmojiProcessor);
field->setMimeDataHook(AllowOnlyCustomEmojiMimeDataHook);
@ -218,7 +234,10 @@ void SetupOnlyCustomEmojiField(
if (state->processing) {
return;
}
auto context = UniqueCustomEmojiContext();
auto context = UniqueCustomEmojiContext{
.applyHardLimit = applyHardLimit,
.hardLimit = customHardLimit,
};
auto changed = false;
state->processing = true;
while (state->pending) {
@ -235,7 +254,7 @@ void SetupOnlyCustomEmojiField(
document->setPageSize(pageSize);
}
}
callback(context.ids);
callback(context.ids, context.hardLimitHit);
if (changed) {
field->forceProcessContentsChanges();
}
@ -289,9 +308,10 @@ struct ReactionsSelectorArgs {
rpl::producer<QString> title;
std::vector<Data::Reaction> list;
std::vector<Data::ReactionId> selected;
Fn<void(std::vector<Data::ReactionId>)> callback;
Fn<void(std::vector<Data::ReactionId>, bool)> callback;
rpl::producer<ReactionsSelectorState> stateValue;
int customAllowed = 0;
int customHardLimit = 0;
bool all = false;
};
@ -344,7 +364,12 @@ object_ptr<Ui::RpWidget> AddReactionsSelector(
}, std::move(customEmojiPaused));
const auto callback = args.callback;
SetupOnlyCustomEmojiField(raw, [=](std::vector<DocumentId> ids) {
const auto isCustom = [=](DocumentId id) {
return state->unifiedFactoryOwner->lookupReactionId(id).custom();
};
SetupOnlyCustomEmojiField(raw, [=](
std::vector<DocumentId> ids,
bool hardLimitHit) {
auto allowed = base::flat_set<DocumentId>();
auto reactions = std::vector<Data::ReactionId>();
reactions.reserve(ids.size());
@ -361,8 +386,8 @@ object_ptr<Ui::RpWidget> AddReactionsSelector(
state->allowed = std::move(allowed);
raw->rawTextEdit()->update();
}
callback(std::move(reactions));
});
callback(std::move(reactions), hardLimitHit);
}, isCustom, args.customHardLimit);
raw->setTextWithTags(ComposeEmojiList(reactions, args.selected));
using SelectorState = ReactionsSelectorState;
@ -667,13 +692,19 @@ void EditAllowedReactionsBox(
| ranges::views::transform(&Data::Reaction::id)
| ranges::to_vector)
: allowed.some;
const auto changed = [=](std::vector<Data::ReactionId> chosen) {
const auto changed = [=](
std::vector<Data::ReactionId> chosen,
bool hardLimitHit) {
state->selected = std::move(chosen);
state->customCount = ranges::count_if(
state->selected,
&Data::ReactionId::custom);
if (hardLimitHit) {
box->uiShow()->showToast(
tr::lng_manage_peer_reactions_limit(tr::now));
}
};
changed(selected.empty() ? DefaultSelected() : std::move(selected));
changed(selected.empty() ? DefaultSelected() : std::move(selected), {});
reactions->add(AddReactionsSelector(reactions, {
.outer = box->getDelegate()->outerContainer(),
.controller = args.navigation->parentController(),
@ -685,6 +716,7 @@ void EditAllowedReactionsBox(
.callback = changed,
.stateValue = state->selectorState.value(),
.customAllowed = args.allowedCustomReactions,
.customHardLimit = args.customReactionsHardLimit,
.all = !args.isGroup,
}), st::boxRowPadding);

View file

@ -25,6 +25,7 @@ class SessionNavigation;
struct EditAllowedReactionsArgs {
not_null<Window::SessionNavigation*> navigation;
int allowedCustomReactions = 0;
int customReactionsHardLimit = 0;
bool isGroup = false;
std::vector<Data::Reaction> list;
Data::AllowedReactions allowed;

View file

@ -189,6 +189,12 @@ int PremiumLimits::aboutLengthCurrent() const {
: aboutLengthDefault();
}
int PremiumLimits::maxBoostLevel() const {
return appConfigLimit(
u"boosts_channel_level_max"_q,
_session->isTestMode() ? 9 : 99);
}
int PremiumLimits::appConfigLimit(
const QString &key,
int fallback) const {

View file

@ -75,6 +75,8 @@ public:
[[nodiscard]] int aboutLengthPremium() const;
[[nodiscard]] int aboutLengthCurrent() const;
[[nodiscard]] int maxBoostLevel() const;
private:
[[nodiscard]] int appConfigLimit(
const QString &key,