Allow saving "Autotranslation of Messages" in channels.

This commit is contained in:
John Preston 2025-04-24 13:54:07 +04:00
parent 8d734f5cc4
commit eb81c33308
13 changed files with 174 additions and 5 deletions

View file

@ -3155,6 +3155,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boost_group_ask" = "Ask your **Premium** members to boost your group with this link:"; "lng_boost_group_ask" = "Ask your **Premium** members to boost your group with this link:";
//"lng_boost_group_gifting" = "Boost your group by gifting your members Telegram Premium. {link}"; //"lng_boost_group_gifting" = "Boost your group by gifting your members Telegram Premium. {link}";
"lng_boost_channel_title_autotranslate" = "Autotranslation of Messages";
"lng_boost_channel_needs_level_autotranslate#one" = "Your channel needs to reach **Level {count}** to enable autotranslation of messages.";
"lng_boost_channel_needs_level_autotranslate#other" = "Your channel needs to reach **Level {count}** to enable autotranslation of messages.";
"lng_feature_stories#one" = "**{count}** Story Per Day"; "lng_feature_stories#one" = "**{count}** Story Per Day";
"lng_feature_stories#other" = "**{count}** Stories Per Day"; "lng_feature_stories#other" = "**{count}** Stories Per Day";
"lng_feature_reactions#one" = "**{count}** Custom Reaction"; "lng_feature_reactions#one" = "**{count}** Custom Reaction";
@ -3173,6 +3177,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_feature_custom_background_group" = "Custom Group Background"; "lng_feature_custom_background_group" = "Custom Group Background";
"lng_feature_custom_emoji_pack" = "Custom Emoji Pack"; "lng_feature_custom_emoji_pack" = "Custom Emoji Pack";
"lng_feature_transcribe" = "Voice-to-Text Conversion"; "lng_feature_transcribe" = "Voice-to-Text Conversion";
"lng_feature_autotranslate" = "Autotranslation of Messages";
"lng_giveaway_new_title" = "Boosts via Gifts"; "lng_giveaway_new_title" = "Boosts via Gifts";
"lng_giveaway_new_about" = "Get more boosts for your channel by gifting Premium to your subscribers."; "lng_giveaway_new_about" = "Get more boosts for your channel by gifting Premium to your subscribers.";
@ -4392,6 +4397,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_contact_title" = "Edit contact"; "lng_edit_contact_title" = "Edit contact";
"lng_edit_channel_title" = "Edit channel"; "lng_edit_channel_title" = "Edit channel";
"lng_edit_bot_title" = "Edit bot"; "lng_edit_bot_title" = "Edit bot";
"lng_edit_autotranslate" = "Auto-translate messages";
"lng_edit_sign_messages" = "Sign messages"; "lng_edit_sign_messages" = "Sign messages";
"lng_edit_sign_messages_about" = "Add names of admins to the messages they post."; "lng_edit_sign_messages_about" = "Add names of admins to the messages they post.";
"lng_edit_sign_profiles" = "Show authors' profiles"; "lng_edit_sign_profiles" = "Show authors' profiles";
@ -5372,6 +5378,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_participant_volume_channel" = "{from} changed live stream volume for {user} to {percent}"; "lng_admin_log_participant_volume_channel" = "{from} changed live stream volume for {user} to {percent}";
"lng_admin_log_antispam_enabled" = "{from} enabled aggressive anti-spam"; "lng_admin_log_antispam_enabled" = "{from} enabled aggressive anti-spam";
"lng_admin_log_antispam_disabled" = "{from} disabled aggressive anti-spam"; "lng_admin_log_antispam_disabled" = "{from} disabled aggressive anti-spam";
"lng_admin_log_autotranslate_enabled" = "{from} enabled automatic translation";
"lng_admin_log_autotranslate_disabled" = "{from} disabled automatic translation";
"lng_admin_log_change_color" = "{from} changed channel color from {previous} to {color}"; "lng_admin_log_change_color" = "{from} changed channel color from {previous} to {color}";
"lng_admin_log_set_background_emoji" = "{from} set channel background emoji to {emoji}"; "lng_admin_log_set_background_emoji" = "{from} set channel background emoji to {emoji}";
"lng_admin_log_change_background_emoji" = "{from} changed channel background emoji from {previous} to {emoji}"; "lng_admin_log_change_background_emoji" = "{from} changed channel background emoji from {previous} to {emoji}";

View file

@ -1482,7 +1482,11 @@ void CheckBoostLevel(
show->show(Box(Ui::AskBoostBox, Ui::AskBoostBoxData{ show->show(Box(Ui::AskBoostBox, Ui::AskBoostBoxData{
.link = qs(data.vboost_url()), .link = qs(data.vboost_url()),
.boost = counters, .boost = counters,
.features = (peer->isChannel()
? LookupBoostFeatures(peer->asChannel())
: Ui::BoostFeatures()),
.reason = *reason, .reason = *reason,
.group = !peer->isBroadcast(),
}, openStatistics, nullptr)); }, openStatistics, nullptr));
cancel(); cancel();
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {

View file

@ -358,6 +358,7 @@ private:
std::optional<QString> description; std::optional<QString> description;
std::optional<bool> hiddenPreHistory; std::optional<bool> hiddenPreHistory;
std::optional<bool> forum; std::optional<bool> forum;
std::optional<bool> autotranslate;
std::optional<bool> signatures; std::optional<bool> signatures;
std::optional<bool> signatureProfiles; std::optional<bool> signatureProfiles;
std::optional<bool> noForwards; std::optional<bool> noForwards;
@ -385,6 +386,7 @@ private:
//void fillInviteLinkButton(); //void fillInviteLinkButton();
void fillForumButton(); void fillForumButton();
void fillColorIndexButton(); void fillColorIndexButton();
void fillAutoTranslateButton();
void fillSignaturesButton(); void fillSignaturesButton();
void fillHistoryVisibilityButton(); void fillHistoryVisibilityButton();
void fillManageSection(); void fillManageSection();
@ -413,6 +415,7 @@ private:
[[nodiscard]] bool validateDescription(Saving &to) const; [[nodiscard]] bool validateDescription(Saving &to) const;
[[nodiscard]] bool validateHistoryVisibility(Saving &to) const; [[nodiscard]] bool validateHistoryVisibility(Saving &to) const;
[[nodiscard]] bool validateForum(Saving &to) const; [[nodiscard]] bool validateForum(Saving &to) const;
[[nodiscard]] bool validateAutotranslate(Saving &to) const;
[[nodiscard]] bool validateSignatures(Saving &to) const; [[nodiscard]] bool validateSignatures(Saving &to) const;
[[nodiscard]] bool validateForwards(Saving &to) const; [[nodiscard]] bool validateForwards(Saving &to) const;
[[nodiscard]] bool validateJoinToWrite(Saving &to) const; [[nodiscard]] bool validateJoinToWrite(Saving &to) const;
@ -426,6 +429,7 @@ private:
void saveDescription(); void saveDescription();
void saveHistoryVisibility(); void saveHistoryVisibility();
void saveForum(); void saveForum();
void saveAutotranslate();
void saveSignatures(); void saveSignatures();
void saveForwards(); void saveForwards();
void saveJoinToWrite(); void saveJoinToWrite();
@ -452,6 +456,7 @@ private:
std::optional<HistoryVisibility> _historyVisibilitySavedValue; std::optional<HistoryVisibility> _historyVisibilitySavedValue;
std::optional<EditPeerTypeData> _typeDataSavedValue; std::optional<EditPeerTypeData> _typeDataSavedValue;
std::optional<bool> _forumSavedValue; std::optional<bool> _forumSavedValue;
std::optional<bool> _autotranslateSavedValue;
std::optional<bool> _signaturesSavedValue; std::optional<bool> _signaturesSavedValue;
std::optional<bool> _signatureProfilesSavedValue; std::optional<bool> _signatureProfilesSavedValue;
@ -1093,6 +1098,61 @@ void Controller::fillColorIndexButton() {
st::managePeerColorsButton); st::managePeerColorsButton);
} }
void Controller::fillAutoTranslateButton() {
Expects(_controls.buttonsLayout != nullptr);
const auto channel = _peer->asBroadcast();
if (!channel) {
return;
}
const auto requiredLevel = Data::LevelLimits(&channel->session())
.channelAutoTranslateLevelMin();
const auto autotranslate = _controls.buttonsLayout->add(
EditPeerInfoBox::CreateButton(
_controls.buttonsLayout,
tr::lng_edit_autotranslate(),
rpl::single(QString()),
[] {},
st::manageGroupTopicsButton,
{ &st::menuIconTranslate }));
const auto toggled = autotranslate->lifetime().make_state<
rpl::event_stream<bool>
>();
autotranslate->toggleOn(rpl::single(
channel->autoTranslation()
) | rpl::then(toggled->events()));
const auto isLocked = channel->levelHint() < requiredLevel;
const auto reason = Ui::AskBoostReason{
.data = Ui::AskBoostAutotranslate{ .requiredLevel = requiredLevel },
};
autotranslate->setToggleLocked(isLocked);
autotranslate->toggledChanges(
) | rpl::start_with_next([=](bool value) {
if (!isLocked) {
_autotranslateSavedValue = toggled;
} else if (value) {
toggled->fire(false);
CheckBoostLevel(
_navigation->uiShow(),
_peer,
[=](int level) {
return (level < requiredLevel)
? std::make_optional(reason)
: std::nullopt;
},
[] {});
}
}, autotranslate->lifetime());
autotranslate->toggledValue(
) | rpl::start_with_next([=](bool toggled) {
_autotranslateSavedValue = toggled;
}, _controls.buttonsLayout->lifetime());
}
void Controller::fillSignaturesButton() { void Controller::fillSignaturesButton() {
Expects(_controls.buttonsLayout != nullptr); Expects(_controls.buttonsLayout != nullptr);
@ -1255,6 +1315,8 @@ void Controller::fillManageSection() {
const auto canEditSignatures = isChannel const auto canEditSignatures = isChannel
&& channel->canEditSignatures() && channel->canEditSignatures()
&& !channel->isMegagroup(); && !channel->isMegagroup();
const auto canEditAutoTranslate = isChannel
&& channel->canEditAutoTranslate();
const auto canEditPreHistoryHidden = isChannel const auto canEditPreHistoryHidden = isChannel
? channel->canEditPreHistoryHidden() ? channel->canEditPreHistoryHidden()
: chat->canEditPreHistoryHidden(); : chat->canEditPreHistoryHidden();
@ -1308,6 +1370,9 @@ void Controller::fillManageSection() {
if (canEditColorIndex) { if (canEditColorIndex) {
fillColorIndexButton(); fillColorIndexButton();
} }
if (canEditAutoTranslate) {
fillAutoTranslateButton();
}
if (canEditSignatures) { if (canEditSignatures) {
fillSignaturesButton(); fillSignaturesButton();
} else if (canEditPreHistoryHidden } else if (canEditPreHistoryHidden
@ -1543,7 +1608,11 @@ void Controller::editReactions() {
strong->show(Box(Ui::AskBoostBox, Ui::AskBoostBoxData{ strong->show(Box(Ui::AskBoostBox, Ui::AskBoostBoxData{
.link = link, .link = link,
.boost = counters, .boost = counters,
.features = (_peer->isChannel()
? LookupBoostFeatures(_peer->asChannel())
: Ui::BoostFeatures()),
.reason = { Ui::AskBoostCustomReactions{ required } }, .reason = { Ui::AskBoostCustomReactions{ required } },
.group = !_peer->isBroadcast(),
}, openStatistics, nullptr)); }, openStatistics, nullptr));
} }
}; };
@ -1897,6 +1966,7 @@ std::optional<Controller::Saving> Controller::validate() const {
&& validateDescription(result) && validateDescription(result)
&& validateHistoryVisibility(result) && validateHistoryVisibility(result)
&& validateForum(result) && validateForum(result)
&& validateAutotranslate(result)
&& validateSignatures(result) && validateSignatures(result)
&& validateForwards(result) && validateForwards(result)
&& validateJoinToWrite(result) && validateJoinToWrite(result)
@ -1984,6 +2054,14 @@ bool Controller::validateForum(Saving &to) const {
return true; return true;
} }
bool Controller::validateAutotranslate(Saving &to) const {
if (!_autotranslateSavedValue.has_value()) {
return true;
}
to.autotranslate = _autotranslateSavedValue;
return true;
}
bool Controller::validateSignatures(Saving &to) const { bool Controller::validateSignatures(Saving &to) const {
Expects(_signaturesSavedValue.has_value() Expects(_signaturesSavedValue.has_value()
== _signatureProfilesSavedValue.has_value()); == _signatureProfilesSavedValue.has_value());
@ -2035,6 +2113,7 @@ void Controller::save() {
pushSaveStage([=] { saveDescription(); }); pushSaveStage([=] { saveDescription(); });
pushSaveStage([=] { saveHistoryVisibility(); }); pushSaveStage([=] { saveHistoryVisibility(); });
pushSaveStage([=] { saveForum(); }); pushSaveStage([=] { saveForum(); });
pushSaveStage([=] { saveAutotranslate(); });
pushSaveStage([=] { saveSignatures(); }); pushSaveStage([=] { saveSignatures(); });
pushSaveStage([=] { saveForwards(); }); pushSaveStage([=] { saveForwards(); });
pushSaveStage([=] { saveJoinToWrite(); }); pushSaveStage([=] { saveJoinToWrite(); });
@ -2181,7 +2260,8 @@ void Controller::saveLinkedChat() {
)).done([=] { )).done([=] {
channel->setLinkedChat(*_savingData.linkedChat); channel->setLinkedChat(*_savingData.linkedChat);
continueSave(); continueSave();
}).fail([=] { }).fail([=](const MTP::Error &error) {
_navigation->showToast(error.type());
cancelSave(); cancelSave();
}).send(); }).send();
} }
@ -2421,6 +2501,30 @@ void Controller::saveForum() {
if (error.type() == u"CHAT_NOT_MODIFIED"_q) { if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
continueSave(); continueSave();
} else { } else {
_navigation->showToast(error.type());
cancelSave();
}
}).send();
}
void Controller::saveAutotranslate() {
const auto channel = _peer->asBroadcast();
if (!_savingData.autotranslate
|| !channel
|| (*_savingData.autotranslate == channel->autoTranslation())) {
return continueSave();
}
_api.request(MTPchannels_ToggleAutotranslation(
channel->inputChannel,
MTP_bool(*_savingData.autotranslate)
)).done([=](const MTPUpdates &result) {
channel->session().api().applyUpdates(result);
continueSave();
}).fail([=](const MTP::Error &error) {
if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
continueSave();
} else {
_navigation->showToast(error.type());
cancelSave(); cancelSave();
} }
}).send(); }).send();
@ -2455,6 +2559,7 @@ void Controller::saveSignatures() {
if (error.type() == u"CHAT_NOT_MODIFIED"_q) { if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
continueSave(); continueSave();
} else { } else {
_navigation->showToast(error.type());
cancelSave(); cancelSave();
} }
}).send(); }).send();
@ -2475,6 +2580,7 @@ void Controller::saveForwards() {
if (error.type() == u"CHAT_NOT_MODIFIED"_q) { if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
continueSave(); continueSave();
} else { } else {
_navigation->showToast(error.type());
cancelSave(); cancelSave();
} }
}).send(); }).send();
@ -2497,6 +2603,7 @@ void Controller::saveJoinToWrite() {
if (error.type() == u"CHAT_NOT_MODIFIED"_q) { if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
continueSave(); continueSave();
} else { } else {
_navigation->showToast(error.type());
cancelSave(); cancelSave();
} }
}).send(); }).send();
@ -2519,6 +2626,7 @@ void Controller::saveRequestToJoin() {
if (error.type() == u"CHAT_NOT_MODIFIED"_q) { if (error.type() == u"CHAT_NOT_MODIFIED"_q) {
continueSave(); continueSave();
} else { } else {
_navigation->showToast(error.type());
cancelSave(); cancelSave();
} }
}).send(); }).send();

View file

@ -449,6 +449,7 @@ Ui::BoostFeatures LookupBoostFeatures(not_null<ChannelData*> channel) {
.nameColorsByLevel = std::move(nameColorsByLevel), .nameColorsByLevel = std::move(nameColorsByLevel),
.linkStylesByLevel = std::move(linkStylesByLevel), .linkStylesByLevel = std::move(linkStylesByLevel),
.linkLogoLevel = group ? 0 : levelLimits.channelBgIconLevelMin(), .linkLogoLevel = group ? 0 : levelLimits.channelBgIconLevelMin(),
.autotranslateLevel = group ? 0 : levelLimits.channelAutoTranslateLevelMin(),
.transcribeLevel = group ? levelLimits.groupTranscribeLevelMin() : 0, .transcribeLevel = group ? levelLimits.groupTranscribeLevelMin() : 0,
.emojiPackLevel = group ? levelLimits.groupEmojiStickersLevelMin() : 0, .emojiPackLevel = group ? levelLimits.groupEmojiStickersLevelMin() : 0,
.emojiStatusLevel = group .emojiStatusLevel = group

View file

@ -649,7 +649,11 @@ bool ChannelData::canEditPermissions() const {
} }
bool ChannelData::canEditSignatures() const { bool ChannelData::canEditSignatures() const {
return isChannel() && canEditInformation(); return isBroadcast() && canEditInformation();
}
bool ChannelData::canEditAutoTranslate() const {
return isBroadcast() && canEditInformation();
} }
bool ChannelData::canEditPreHistoryHidden() const { bool ChannelData::canEditPreHistoryHidden() const {

View file

@ -73,6 +73,7 @@ enum class ChannelDataFlag : uint64 {
SignatureProfiles = (1ULL << 35), SignatureProfiles = (1ULL << 35),
StargiftsAvailable = (1ULL << 36), StargiftsAvailable = (1ULL << 36),
PaidMessagesAvailable = (1ULL << 37), PaidMessagesAvailable = (1ULL << 37),
AutoTranslation = (1ULL << 38),
}; };
inline constexpr bool is_flag_type(ChannelDataFlag) { return true; }; inline constexpr bool is_flag_type(ChannelDataFlag) { return true; };
using ChannelDataFlags = base::flags<ChannelDataFlag>; using ChannelDataFlags = base::flags<ChannelDataFlag>;
@ -321,6 +322,9 @@ public:
[[nodiscard]] bool antiSpamMode() const { [[nodiscard]] bool antiSpamMode() const {
return flags() & Flag::AntiSpam; return flags() & Flag::AntiSpam;
} }
[[nodiscard]] bool autoTranslation() const {
return flags() & Flag::AutoTranslation;
}
[[nodiscard]] auto adminRights() const { [[nodiscard]] auto adminRights() const {
return _adminRights.current(); return _adminRights.current();
@ -382,6 +386,7 @@ public:
[[nodiscard]] bool canViewAdmins() const; [[nodiscard]] bool canViewAdmins() const;
[[nodiscard]] bool canViewBanned() const; [[nodiscard]] bool canViewBanned() const;
[[nodiscard]] bool canEditSignatures() const; [[nodiscard]] bool canEditSignatures() const;
[[nodiscard]] bool canEditAutoTranslate() const;
[[nodiscard]] bool canEditStickers() const; [[nodiscard]] bool canEditStickers() const;
[[nodiscard]] bool canEditEmoji() const; [[nodiscard]] bool canEditEmoji() const;
[[nodiscard]] bool canDelete() const; [[nodiscard]] bool canDelete() const;

View file

@ -262,6 +262,12 @@ int LevelLimits::channelRestrictSponsoredLevelMin() const {
20); 20);
} }
int LevelLimits::channelAutoTranslateLevelMin() const {
return _session->appConfig().get<int>(
u"channel_autotranslation_level_min"_q,
3);
}
int LevelLimits::groupTranscribeLevelMin() const { int LevelLimits::groupTranscribeLevelMin() const {
return _session->appConfig().get<int>( return _session->appConfig().get<int>(
u"group_transcribe_level_min"_q, u"group_transcribe_level_min"_q,

View file

@ -102,6 +102,7 @@ public:
[[nodiscard]] int channelWallpaperLevelMin() const; [[nodiscard]] int channelWallpaperLevelMin() const;
[[nodiscard]] int channelCustomWallpaperLevelMin() const; [[nodiscard]] int channelCustomWallpaperLevelMin() const;
[[nodiscard]] int channelRestrictSponsoredLevelMin() const; [[nodiscard]] int channelRestrictSponsoredLevelMin() const;
[[nodiscard]] int channelAutoTranslateLevelMin() const;
[[nodiscard]] int groupTranscribeLevelMin() const; [[nodiscard]] int groupTranscribeLevelMin() const;
[[nodiscard]] int groupEmojiStickersLevelMin() const; [[nodiscard]] int groupEmojiStickersLevelMin() const;
[[nodiscard]] int groupProfileBgIconLevelMin() const; [[nodiscard]] int groupProfileBgIconLevelMin() const;

View file

@ -967,7 +967,8 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
| Flag::Forum | Flag::Forum
| ((!minimal && !data.is_stories_hidden_min()) | ((!minimal && !data.is_stories_hidden_min())
? Flag::StoriesHidden ? Flag::StoriesHidden
: Flag()); : Flag())
| Flag::AutoTranslation;
const auto storiesState = minimal const auto storiesState = minimal
? std::optional<Data::Stories::PeerSourceState>() ? std::optional<Data::Stories::PeerSourceState>()
: data.is_stories_unavailable() : data.is_stories_unavailable()
@ -1006,7 +1007,8 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
&& !data.is_stories_hidden_min() && !data.is_stories_hidden_min()
&& data.is_stories_hidden()) && data.is_stories_hidden())
? Flag::StoriesHidden ? Flag::StoriesHidden
: Flag()); : Flag())
| (data.is_autotranslation() ? Flag::AutoTranslation : Flag());
channel->setFlags((channel->flags() & ~flagsMask) | flagsSet); channel->setFlags((channel->flags() & ~flagsMask) | flagsSet);
channel->setBotVerifyDetailsIcon( channel->setBotVerifyDetailsIcon(
data.vbot_verification_icon().value_or_empty()); data.vbot_verification_icon().value_or_empty());

View file

@ -31,7 +31,7 @@ settingsButtonLight: SettingsButton(settingsButton) {
} }
settingsButtonLightNoIcon: SettingsButton(settingsButtonLight, settingsButtonNoIcon) { settingsButtonLightNoIcon: SettingsButton(settingsButtonLight, settingsButtonNoIcon) {
} }
settingsButtonNoIconLocked : SettingsButton(settingsButtonNoIcon) { settingsButtonNoIconLocked: SettingsButton(settingsButtonNoIcon) {
toggle: Toggle(infoProfileToggle) { toggle: Toggle(infoProfileToggle) {
lockIcon: icon {{ "info/info_rights_lock", menuIconFg }}; lockIcon: icon {{ "info/info_rights_lock", menuIconFg }};
} }

View file

@ -143,6 +143,7 @@ void AddFeaturesList(
const auto proj = &Ui::Text::RichLangValue; const auto proj = &Ui::Text::RichLangValue;
const auto lowMax = std::max({ const auto lowMax = std::max({
features.linkLogoLevel, features.linkLogoLevel,
features.autotranslateLevel,
features.transcribeLevel, features.transcribeLevel,
features.emojiPackLevel, features.emojiPackLevel,
features.emojiStatusLevel, features.emojiStatusLevel,
@ -208,6 +209,11 @@ void AddFeaturesList(
st::boostFeatureCustomEmoji); st::boostFeatureCustomEmoji);
} }
if (!group) { if (!group) {
if (i >= features.autotranslateLevel) {
add(
tr::lng_feature_autotranslate(proj),
st::boostFeatureAutoTranslate);
}
if (const auto j = features.linkStylesByLevel.find(i) if (const auto j = features.linkStylesByLevel.find(i)
; j != end(features.linkStylesByLevel)) { ; j != end(features.linkStylesByLevel)) {
linkStyles += j->second; linkStyles += j->second;
@ -665,6 +671,8 @@ void AskBoostBox(
Fn<void()> startGiveaway) { Fn<void()> startGiveaway) {
box->setWidth(st::boxWideWidth); box->setWidth(st::boxWideWidth);
box->setStyle(st::boostBox); box->setStyle(st::boostBox);
box->setNoContentMargin(true);
box->addSkip(st::boxRowPadding.left());
FillBoostLimit( FillBoostLimit(
BoxShowFinishes(box), BoxShowFinishes(box),
@ -676,6 +684,8 @@ void AskBoostBox(
auto title = v::match(data.reason.data, [](AskBoostChannelColor) { auto title = v::match(data.reason.data, [](AskBoostChannelColor) {
return tr::lng_boost_channel_title_color(); return tr::lng_boost_channel_title_color();
}, [](AskBoostAutotranslate) {
return tr::lng_boost_channel_title_autotranslate();
}, [](AskBoostWallpaper) { }, [](AskBoostWallpaper) {
return tr::lng_boost_channel_title_wallpaper(); return tr::lng_boost_channel_title_wallpaper();
}, [](AskBoostEmojiStatus) { }, [](AskBoostEmojiStatus) {
@ -696,6 +706,11 @@ void AskBoostBox(
lt_count, lt_count,
rpl::single(float64(data.requiredLevel)), rpl::single(float64(data.requiredLevel)),
Ui::Text::RichLangValue); Ui::Text::RichLangValue);
}, [&](AskBoostAutotranslate data) {
return tr::lng_boost_channel_needs_level_autotranslate(
lt_count,
rpl::single(float64(data.requiredLevel)),
Ui::Text::RichLangValue);
}, [&](AskBoostWallpaper data) { }, [&](AskBoostWallpaper data) {
isGroup = data.group; isGroup = data.group;
return (data.group return (data.group
@ -766,6 +781,12 @@ void AskBoostBox(
box->uiShow(), box->uiShow(),
std::move(stats))); std::move(stats)));
AddFeaturesList(
box->verticalLayout(),
data.features,
data.boost.level + (data.boost.nextLevelBoosts ? 1 : 0),
data.group);
auto submit = tr::lng_boost_channel_ask_button(); auto submit = tr::lng_boost_channel_ask_button();
const auto button = box->addButton(rpl::duplicate(submit), [=] { const auto button = box->addButton(rpl::duplicate(submit), [=] {
QGuiApplication::clipboard()->setText(data.link); QGuiApplication::clipboard()->setText(data.link);

View file

@ -35,6 +35,7 @@ struct BoostFeatures {
base::flat_map<int, int> nameColorsByLevel; base::flat_map<int, int> nameColorsByLevel;
base::flat_map<int, int> linkStylesByLevel; base::flat_map<int, int> linkStylesByLevel;
int linkLogoLevel = 0; int linkLogoLevel = 0;
int autotranslateLevel = 0;
int transcribeLevel = 0; int transcribeLevel = 0;
int emojiPackLevel = 0; int emojiPackLevel = 0;
int emojiStatusLevel = 0; int emojiStatusLevel = 0;
@ -74,6 +75,10 @@ struct AskBoostChannelColor {
int requiredLevel = 0; int requiredLevel = 0;
}; };
struct AskBoostAutotranslate {
int requiredLevel = 0;
};
struct AskBoostWallpaper { struct AskBoostWallpaper {
int requiredLevel = 0; int requiredLevel = 0;
bool group = false; bool group = false;
@ -103,6 +108,7 @@ struct AskBoostWearCollectible {
struct AskBoostReason { struct AskBoostReason {
std::variant< std::variant<
AskBoostChannelColor, AskBoostChannelColor,
AskBoostAutotranslate,
AskBoostWallpaper, AskBoostWallpaper,
AskBoostEmojiStatus, AskBoostEmojiStatus,
AskBoostEmojiPack, AskBoostEmojiPack,
@ -114,7 +120,9 @@ struct AskBoostReason {
struct AskBoostBoxData { struct AskBoostBoxData {
QString link; QString link;
BoostCounters boost; BoostCounters boost;
BoostFeatures features;
AskBoostReason reason; AskBoostReason reason;
bool group = false;
}; };
void AskBoostBox( void AskBoostBox(

View file

@ -371,6 +371,7 @@ boostFeatureLink: icon{{ "settings/premium/features/feature_links", windowBgActi
boostFeatureName: icon{{ "settings/premium/features/feature_color_names", windowBgActive }}; boostFeatureName: icon{{ "settings/premium/features/feature_color_names", windowBgActive }};
boostFeatureStories: icon{{ "settings/premium/features/feature_stories", windowBgActive }}; boostFeatureStories: icon{{ "settings/premium/features/feature_stories", windowBgActive }};
boostFeatureTranscribe: icon{{ "settings/premium/features/feature_voice", windowBgActive }}; boostFeatureTranscribe: icon{{ "settings/premium/features/feature_voice", windowBgActive }};
boostFeatureAutoTranslate: icon{{ "menu/translate", windowBgActive }};
boostFeatureOffSponsored: icon{{ "settings/premium/features/feature_off_sponsored", windowBgActive }}; boostFeatureOffSponsored: icon{{ "settings/premium/features/feature_off_sponsored", windowBgActive }};
paidReactBox: Box(boostBox) { paidReactBox: Box(boostBox) {