diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index bd6100058..ea98e618d 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2133,6 +2133,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_boost_channel_needs_level_color#one" = "Your channel needs to reach **Level {count}** to change channel color."; "lng_boost_channel_needs_level_color#other" = "Your channel needs to reach **Level {count}** to change channel color."; +"lng_boost_channel_title_wallpaper" = "Enable wallpapers"; +"lng_boost_channel_needs_level_wallpaper#one" = "Your channel needs to reach **Level {count}** to change channel wallpaper."; +"lng_boost_channel_needs_level_wallpaper#other" = "Your channel needs to reach **Level {count}** to change channel wallpaper."; + +"lng_boost_channel_title_status" = "Enable emoji status"; +"lng_boost_channel_needs_level_status#one" = "Your channel needs to reach **Level {count}** to set emoji status."; +"lng_boost_channel_needs_level_status#other" = "Your channel needs to reach **Level {count}** to set emoji status."; + "lng_boost_channel_title_reactions" = "Custom reactions"; "lng_boost_channel_needs_level_reactions#one" = "Your channel needs to reach **Level {count}** to add **{same_count}** custom emoji as a reaction."; "lng_boost_channel_needs_level_reactions#other" = "Your channel needs to reach **Level {count}** to add **{same_count}** custom emoji as reactions."; @@ -2847,6 +2855,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_edit_sign_messages" = "Sign messages"; "lng_edit_group" = "Edit group"; "lng_edit_channel_color" = "Change name color"; +"lng_edit_channel_level_min" = "Level 1+"; +"lng_edit_channel_wallpaper" = "Channel wallpaper"; +"lng_edit_channel_wallpaper_about" = "Set a wallpaper that will be visible for everyone reading your channel."; +"lng_edit_channel_status" = "Channel emoji status"; +"lng_edit_channel_status_about" = "Choose a status that will be shown next to the channel's name."; "lng_edit_self_title" = "Edit your name"; "lng_confirm_contact_data" = "New Contact"; "lng_add_contact" = "Create"; diff --git a/Telegram/SourceFiles/api/api_peer_colors.cpp b/Telegram/SourceFiles/api/api_peer_colors.cpp index 85d60d814..50c2382fd 100644 --- a/Telegram/SourceFiles/api/api_peer_colors.cpp +++ b/Telegram/SourceFiles/api/api_peer_colors.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_peer_colors.h" #include "apiwrap.h" +#include "data/data_peer.h" #include "ui/chat/chat_style.h" namespace Api { @@ -62,6 +63,16 @@ auto PeerColors::indicesValue() const })); } +int PeerColors::requiredLevelFor(PeerId channel, uint8 index) const { + if (Data::DecideColorIndex(channel) == index) { + return 0; + } else if (const auto i = _requiredLevels.find(index) + ; i != end(_requiredLevels)) { + return i->second; + } + return 1; +} + void PeerColors::apply(const MTPDhelp_peerColors &data) { auto suggested = std::vector(); auto colors = std::make_shared< @@ -89,6 +100,7 @@ void PeerColors::apply(const MTPDhelp_peerColors &data) { }; const auto &list = data.vcolors().v; + _requiredLevels.clear(); suggested.reserve(list.size()); for (const auto &color : list) { const auto &data = color.data(); @@ -98,6 +110,9 @@ void PeerColors::apply(const MTPDhelp_peerColors &data) { continue; } const auto colorIndex = uint8(colorIndexBare); + if (const auto min = data.vchannel_min_level()) { + _requiredLevels[colorIndex] = min->v; + } if (!data.is_hidden()) { suggested.push_back(colorIndex); } diff --git a/Telegram/SourceFiles/api/api_peer_colors.h b/Telegram/SourceFiles/api/api_peer_colors.h index de06d4221..0ad1a63c7 100644 --- a/Telegram/SourceFiles/api/api_peer_colors.h +++ b/Telegram/SourceFiles/api/api_peer_colors.h @@ -28,6 +28,10 @@ public: [[nodiscard]] auto indicesValue() const -> rpl::producer; + [[nodiscard]] int requiredLevelFor( + PeerId channel, + uint8 index) const; + private: void request(); void apply(const MTPDhelp_peerColors &data); @@ -38,6 +42,7 @@ private: mtpRequestId _requestId = 0; base::Timer _timer; rpl::variable> _suggested; + base::flat_map _requiredLevels; rpl::event_stream<> _colorIndicesChanged; std::unique_ptr _colorIndicesCurrent; diff --git a/Telegram/SourceFiles/api/api_statistics.cpp b/Telegram/SourceFiles/api/api_statistics.cpp index 16d27b34d..f24e156d0 100644 --- a/Telegram/SourceFiles/api/api_statistics.cpp +++ b/Telegram/SourceFiles/api/api_statistics.cpp @@ -612,6 +612,7 @@ rpl::producer Boosts::request() { _peer->input )).done([=](const MTPpremium_BoostsStatus &result) { const auto &data = result.data(); + channel->updateLevelHint(data.vlevel().v); const auto hasPremium = !!data.vpremium_audience(); const auto premiumMemberCount = hasPremium ? std::max(0, int(data.vpremium_audience()->data().vpart().v)) diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp index fd3458c1d..f686c06cf 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp @@ -452,8 +452,11 @@ void Set( : tr::lng_settings_color_changed_channel(tr::now)); }; const auto fail = [=](const MTP::Error &error) { - setLocal(wasIndex, wasEmojiId); - show->showToast(error.type()); + const auto type = error.type(); + if (type != u"CHAT_NOT_MODIFIED"_q) { + setLocal(wasIndex, wasEmojiId); + show->showToast(type); + } }; const auto send = [&](auto &&request) { peer->session().api().request( @@ -469,7 +472,7 @@ void Set( } else if (const auto channel = peer->asChannel()) { using Flag = MTPchannels_UpdateColor::Flag; send(MTPchannels_UpdateColor( - MTP_flags(Flag::f_background_emoji_id), + MTP_flags(Flag::f_color | Flag::f_background_emoji_id), channel->inputChannel, MTP_int(colorIndex), MTP_long(backgroundEmojiId))); @@ -509,9 +512,19 @@ void Apply( peer->input )).done([=](const MTPpremium_BoostsStatus &result) { const auto &data = result.data(); - const auto required = session->account().appConfig().get( - "channel_color_level_min", - 5); + if (const auto channel = peer->asChannel()) { + channel->updateLevelHint(data.vlevel().v); + } + const auto peerColors = &peer->session().api().peerColors(); + const auto colorRequired = peerColors->requiredLevelFor( + peer->id, + colorIndex); + const auto iconRequired = backgroundEmojiId + ? session->account().appConfig().get( + "channel_bg_icon_level_min", + 5) + : 0; + const auto required = std::max(colorRequired, iconRequired); if (data.vlevel().v >= required) { Set(show, peer, colorIndex, backgroundEmojiId); close(); @@ -842,11 +855,12 @@ void AddPeerColorButton( not_null container, std::shared_ptr show, not_null peer) { + auto label = peer->isSelf() + ? tr::lng_settings_theme_name_color() + : tr::lng_edit_channel_color(); const auto button = AddButtonWithIcon( container, - (peer->isSelf() - ? tr::lng_settings_theme_name_color() - : tr::lng_edit_channel_color()), + rpl::duplicate(label), st::settingsColorButton, { &st::menuIconChangeColors }); @@ -873,7 +887,7 @@ void AddPeerColorButton( rpl::combine( button->widthValue(), - tr::lng_settings_theme_name_color(), + rpl::duplicate(label), rpl::duplicate(colorIndexValue) ) | rpl::start_with_next([=]( int width, diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 7b1010272..fba0c7303 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -1294,6 +1294,9 @@ void Controller::editReactions() { _peer->input )).done([=](const MTPpremium_BoostsStatus &result) { _controls.levelRequested = false; + if (const auto channel = _peer->asChannel()) { + channel->updateLevelHint(result.data().vlevel().v); + } const auto link = qs(result.data().vboost_url()); const auto weak = base::make_weak(_navigation->parentController()); auto counters = ParseBoostCounters(result); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index ca1bd81b2..fecbe6287 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -949,6 +949,14 @@ void ChannelData::processTopics(const MTPVector &topics) { } } +int ChannelData::levelHint() const { + return _levelHint; +} + +void ChannelData::updateLevelHint(int levelHint) { + _levelHint = levelHint; +} + namespace Data { void ApplyMigration( diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 0d1faf269..d55e8a4e6 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -463,6 +463,9 @@ public: void processTopics(const MTPVector &topics); + [[nodiscard]] int levelHint() const; + void updateLevelHint(int levelHint); + // Still public data members. uint64 access = 0; @@ -497,6 +500,7 @@ private: int _restrictedCount = 0; int _kickedCount = 0; int _pendingRequestsCount = 0; + int _levelHint = 0; std::vector _recentRequesters; MsgId _availableMinId = 0; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index eaea5ba61..c385a8c3d 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -845,6 +845,7 @@ not_null Session::processChat(const MTPChat &data) { const auto wasCallNotEmpty = Data::ChannelHasActiveCall(channel); + channel->updateLevelHint(data.vlevel().value_or_empty()); if (const auto count = data.vparticipants_count()) { channel->setMembersCount(count->v); } diff --git a/Telegram/SourceFiles/ui/boxes/boost_box.cpp b/Telegram/SourceFiles/ui/boxes/boost_box.cpp index 592436a13..5a226eea4 100644 --- a/Telegram/SourceFiles/ui/boxes/boost_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/boost_box.cpp @@ -467,15 +467,32 @@ void AskBoostBox( box->addTopButton(st::boxTitleClose, [=] { box->closeBox(); }); - auto title = v::is(data.reason.data) - ? tr::lng_boost_channel_title_color() - : tr::lng_boost_channel_title_reactions(); + auto title = v::match(data.reason.data, [&]( + AskBoostChannelColor data) { + return tr::lng_boost_channel_title_color(); + }, [&](AskBoostWallpaper data) { + return tr::lng_boost_channel_title_wallpaper(); + }, [&](AskBoostEmojiStatus data) { + return tr::lng_boost_channel_title_status(); + }, [&](AskBoostCustomReactions data) { + return tr::lng_boost_channel_title_reactions(); + }); auto reasonText = v::match(data.reason.data, [&]( AskBoostChannelColor data) { return tr::lng_boost_channel_needs_level_color( lt_count, rpl::single(float64(data.requiredLevel)), Ui::Text::RichLangValue); + }, [&](AskBoostWallpaper data) { + return tr::lng_boost_channel_needs_level_wallpaper( + lt_count, + rpl::single(float64(data.requiredLevel)), + Ui::Text::RichLangValue); + }, [&](AskBoostEmojiStatus data) { + return tr::lng_boost_channel_needs_level_status( + lt_count, + rpl::single(float64(data.requiredLevel)), + Ui::Text::RichLangValue); }, [&](AskBoostCustomReactions data) { return tr::lng_boost_channel_needs_level_reactions( lt_count, diff --git a/Telegram/SourceFiles/ui/boxes/boost_box.h b/Telegram/SourceFiles/ui/boxes/boost_box.h index 84d0b65b3..68ff1d771 100644 --- a/Telegram/SourceFiles/ui/boxes/boost_box.h +++ b/Telegram/SourceFiles/ui/boxes/boost_box.h @@ -54,6 +54,14 @@ struct AskBoostChannelColor { int requiredLevel = 0; }; +struct AskBoostWallpaper { + int requiredLevel = 0; +}; + +struct AskBoostEmojiStatus { + int requiredLevel = 0; +}; + struct AskBoostCustomReactions { int count = 0; }; @@ -61,6 +69,8 @@ struct AskBoostCustomReactions { struct AskBoostReason { std::variant< AskBoostChannelColor, + AskBoostWallpaper, + AskBoostEmojiStatus, AskBoostCustomReactions> data; }; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 7e12d1945..3a348ade3 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -623,6 +623,7 @@ void SessionNavigation::resolveBoostState(not_null channel) { channel->input )).done([=](const MTPpremium_BoostsStatus &result) { _boostStateResolving = nullptr; + channel->updateLevelHint(result.data().vlevel().v); const auto submit = [=](Fn done) { applyBoost(channel, done); }; @@ -730,6 +731,7 @@ void SessionNavigation::applyBoostsChecked( _api.request(MTPpremium_GetBoostsStatus( channel->input )).done([=](const MTPpremium_BoostsStatus &result) { + channel->updateLevelHint(result.data().vlevel().v); done(ParseBoostCounters(result)); }).fail([=](const MTP::Error &error) { showToast(u"Error: "_q + error.type());