From 9e8ae54821fdec4fb5feb2f4be15e8ce3f18ba68 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 26 Aug 2025 18:03:15 +0400 Subject: [PATCH] Update API scheme to layer 214. Start themes. --- Telegram/Resources/langs/lang.strings | 2 + Telegram/SourceFiles/boxes/background_box.cpp | 6 +- .../boxes/background_preview_box.cpp | 2 +- .../SourceFiles/core/local_url_handlers.cpp | 5 +- Telegram/SourceFiles/data/data_changes.h | 2 +- Telegram/SourceFiles/data/data_channel.cpp | 2 +- Telegram/SourceFiles/data/data_chat.cpp | 2 +- .../SourceFiles/data/data_cloud_themes.cpp | 170 +++++++++++++++++- Telegram/SourceFiles/data/data_cloud_themes.h | 27 ++- Telegram/SourceFiles/data/data_peer.cpp | 24 ++- Telegram/SourceFiles/data/data_peer.h | 6 +- Telegram/SourceFiles/data/data_user.cpp | 12 +- .../export/data/export_data_types.cpp | 10 +- Telegram/SourceFiles/history/history.cpp | 8 +- Telegram/SourceFiles/history/history_item.cpp | 85 +++++---- .../SourceFiles/history/history_widget.cpp | 8 +- .../channel_statistics/earn/earn_format.cpp | 11 +- .../earn/info_channel_earn_list.cpp | 1 - Telegram/SourceFiles/mtproto/scheme/api.tl | 21 ++- .../statistics/view/chart_rulers_view.cpp | 2 + .../ui/chat/choose_theme_controller.cpp | 109 +++++++++-- .../SourceFiles/window/section_widget.cpp | 14 +- 22 files changed, 426 insertions(+), 103 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 7fc646fa0a..e178713532 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2191,6 +2191,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_action_you_proximity_reached" = "You are now within {distance} from {user}"; "lng_action_you_theme_changed" = "You changed the chat theme to {emoji}"; "lng_action_theme_changed" = "{from} changed the chat theme to {emoji}"; +"lng_action_you_gift_theme_changed" = "You set {name} as a new theme for this chat."; +"lng_action_gift_theme_changed" = "{from} set {name} as a new theme for this chat."; "lng_action_you_theme_disabled" = "You disabled the chat theme"; "lng_action_theme_disabled" = "{from} disabled the chat theme"; "lng_action_proximity_distance_m#one" = "{count} meter"; diff --git a/Telegram/SourceFiles/boxes/background_box.cpp b/Telegram/SourceFiles/boxes/background_box.cpp index f2e2f647b3..8723572da2 100644 --- a/Telegram/SourceFiles/boxes/background_box.cpp +++ b/Telegram/SourceFiles/boxes/background_box.cpp @@ -451,12 +451,12 @@ auto BackgroundBox::Inner::resolveResetCustomPaper() const return {}; } const auto nonCustom = Window::Theme::Background()->paper(); - const auto themeEmoji = _forPeer->themeEmoji(); - if (forChannel() || themeEmoji.isEmpty()) { + const auto themeToken = _forPeer->themeToken(); + if (forChannel() || themeToken.isEmpty()) { return nonCustom; } const auto &themes = _forPeer->owner().cloudThemes(); - const auto theme = themes.themeForEmoji(themeEmoji); + const auto theme = themes.themeForToken(themeToken); if (!theme) { return nonCustom; } diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index 0fc02e2efc..24d4fd1835 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -161,7 +161,7 @@ constexpr auto kMaxWallPaperSlugLength = 255; return paper; } const auto &themes = session->data().cloudThemes(); - if (const auto theme = themes.themeForEmoji(paper.emojiId())) { + if (const auto theme = themes.themeForToken(paper.emojiId())) { using Type = Data::CloudThemeType; const auto type = dark ? Type::Dark : Type::Light; const auto i = theme->settings.find(type); diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 65d423a245..7e313dab5a 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -1320,8 +1320,9 @@ bool ResolveTestChatTheme( qthelp::UrlParamNameTransform::ToLower); if (const auto history = controller->activeChatCurrent().history()) { controller->clearCachedChatThemes(); - const auto theme = history->owner().cloudThemes().updateThemeFromLink( - history->peer->themeEmoji(), + const auto owner = &history->owner(); + const auto theme = owner->cloudThemes().updateThemeFromLink( + history->peer->themeToken(), params); if (theme) { if (!params["export"].isEmpty()) { diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h index 86dc7f2bf4..443d242cb9 100644 --- a/Telegram/SourceFiles/data/data_changes.h +++ b/Telegram/SourceFiles/data/data_changes.h @@ -66,7 +66,7 @@ struct PeerUpdate { Notifications = (1ULL << 4), Migration = (1ULL << 5), UnavailableReason = (1ULL << 6), - ChatThemeEmoji = (1ULL << 7), + ChatThemeToken = (1ULL << 7), ChatWallPaper = (1ULL << 8), IsBlocked = (1ULL << 9), MessagesTTL = (1ULL << 10), diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index d9016fb7ed..08321386f9 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -1406,7 +1406,7 @@ void ApplyChannelUpdate( update.vboosts_applied().value_or_empty(), update.vboosts_unrestrict().value_or_empty()); } - channel->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty())); + channel->setThemeToken(qs(update.vtheme_emoticon().value_or_empty())); channel->setTranslationDisabled(update.is_translations_disabled()); const auto reactionsLimit = update.vreactions_limit().value_or_empty(); diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp index fc33c01708..288e0807c9 100644 --- a/Telegram/SourceFiles/data/data_chat.cpp +++ b/Telegram/SourceFiles/data/data_chat.cpp @@ -486,7 +486,7 @@ void ApplyChatUpdate(not_null chat, const MTPDchatFull &update) { SetTopPinnedMessageId(chat, pinned->v); } chat->checkFolder(update.vfolder_id().value_or_empty()); - chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty())); + chat->setThemeToken(qs(update.vtheme_emoticon().value_or_empty())); chat->setTranslationDisabled(update.is_translations_disabled()); const auto reactionsLimit = update.vreactions_limit().value_or_empty(); if (const auto allowed = update.vavailable_reactions()) { diff --git a/Telegram/SourceFiles/data/data_cloud_themes.cpp b/Telegram/SourceFiles/data/data_cloud_themes.cpp index 56c7647dac..929bca7247 100644 --- a/Telegram/SourceFiles/data/data_cloud_themes.cpp +++ b/Telegram/SourceFiles/data/data_cloud_themes.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "data/data_cloud_themes.h" +#include "api/api_premium.h" #include "window/themes/window_theme.h" #include "window/themes/window_theme_preview.h" #include "window/themes/window_theme_editor_box.h" @@ -26,6 +27,7 @@ namespace { constexpr auto kFirstReloadTimeout = 10 * crl::time(1000); constexpr auto kReloadTimeout = 3600 * crl::time(1000); +constexpr auto kGiftThemesLimit = 24; bool IsTestingColors/* = false*/; @@ -111,6 +113,77 @@ CloudTheme CloudTheme::Parse( }; } +CloudTheme CloudTheme::Parse( + not_null session, + const MTPDchatThemeUniqueGift &data, + bool parseSettings) { + const auto gift = Api::FromTL(session, data.vgift()); + if (!gift || !gift->unique) { + return {}; + } + const auto paper = [&](const MTPThemeSettings &settings) { + return settings.match([&](const MTPDthemeSettings &data) { + return data.vwallpaper() + ? WallPaper::Create(session, *data.vwallpaper()) + : std::nullopt; + }); + }; + const auto outgoingMessagesColors = [&]( + const MTPThemeSettings &settings) { + auto result = std::vector(); + settings.match([&](const MTPDthemeSettings &data) { + if (const auto colors = data.vmessage_colors()) { + for (const auto &color : colors->v) { + result.push_back(Ui::ColorFromSerialized(color)); + } + } + }); + return result; + }; + const auto accentColor = [&](const MTPThemeSettings &settings) { + return settings.match([&](const MTPDthemeSettings &data) { + return Ui::ColorFromSerialized(data.vaccent_color()); + }); + }; + const auto outgoingAccentColor = [&](const MTPThemeSettings &settings) { + return settings.match([&](const MTPDthemeSettings &data) { + return Ui::MaybeColorFromSerialized(data.voutbox_accent_color()); + }); + }; + const auto basedOnDark = [&](const MTPThemeSettings &settings) { + return settings.match([&](const MTPDthemeSettings &data) { + return data.vbase_theme().match([]( + const MTPDbaseThemeNight &) { + return true; + }, [](const MTPDbaseThemeTinted &) { + return true; + }, [](const auto &) { + return false; + }); + }); + }; + const auto settings = [&] { + auto result = base::flat_map(); + for (const auto &fields : data.vtheme_settings().v) { + const auto type = basedOnDark(fields) ? Type::Dark : Type::Light; + result.emplace(type, Settings{ + .paper = paper(fields), + .accentColor = accentColor(fields), + .outgoingAccentColor = outgoingAccentColor(fields), + .outgoingMessagesColors = outgoingMessagesColors(fields), + }); + } + return result; + }; + return { + .id = gift->unique->id, + .unique = gift->unique, + .settings = (parseSettings + ? settings() + : base::flat_map()), + }; +} + CloudTheme CloudTheme::Parse( not_null session, const MTPTheme &data, @@ -382,9 +455,16 @@ rpl::producer<> CloudThemes::chatThemesUpdated() const { return _chatThemesUpdates.events(); } -std::optional CloudThemes::themeForEmoji( - const QString &emoticon) const { - const auto emoji = Ui::Emoji::Find(emoticon); +std::optional CloudThemes::themeForToken( + const QString &token) const { + if (token.startsWith(u"gift:"_q)) { + const auto id = QStringView(token).mid(5).toULongLong(); + const auto i = _giftThemes.find(id); + return (i != end(_giftThemes)) + ? i->second + : std::optional(); + } + const auto emoji = Ui::Emoji::Find(token); if (!emoji) { return {}; } @@ -394,18 +474,21 @@ std::optional CloudThemes::themeForEmoji( return (i != end(_chatThemes)) ? std::make_optional(*i) : std::nullopt; } -rpl::producer> CloudThemes::themeForEmojiValue( - const QString &emoticon) { +rpl::producer> CloudThemes::themeForTokenValue( + const QString &token) { + if (token.startsWith(u"gift:"_q)) { + return rpl::single(themeForToken(token)); + } const auto testing = TestingColors(); - if (!Ui::Emoji::Find(emoticon)) { + if (!Ui::Emoji::Find(token)) { return rpl::single>(std::nullopt); - } else if (auto result = themeForEmoji(emoticon)) { + } else if (auto result = themeForToken(token)) { if (testing) { return rpl::single( std::move(result) ) | rpl::then(chatThemesUpdated( ) | rpl::map([=] { - return themeForEmoji(emoticon); + return themeForToken(token); }) | rpl::filter([](const std::optional &theme) { return theme.has_value(); })); @@ -418,12 +501,81 @@ rpl::producer> CloudThemes::themeForEmojiValue( std::nullopt ) | rpl::then(chatThemesUpdated( ) | rpl::map([=] { - return themeForEmoji(emoticon); + return themeForToken(token); }) | rpl::filter([](const std::optional &theme) { return theme.has_value(); }) | rpl::take(limit)); } +void CloudThemes::myGiftThemesLoadMore(bool reload) { + if (reload && !_myGiftThemesTokens.empty()) { + _session->api().request(base::take(_myGiftThemesRequestId)).cancel(); + } + if (_myGiftThemesRequestId || (!reload && _myGiftThemesLoaded)) { + return; + } + _myGiftThemesRequestId = _session->api().request( + MTPaccount_GetUniqueGiftChatThemes( + MTP_int(reload ? 0 : _myGiftThemesTokens.size()), + MTP_int(kGiftThemesLimit), + MTP_long(_myGiftThemesHash)) + ).done([=](const MTPaccount_ChatThemes &result) { + _myGiftThemesRequestId = 0; + result.match([&](const MTPDaccount_chatThemes &data) { + if (reload || _myGiftThemesTokens.empty()) { + _myGiftThemesHash = data.vhash().v; + _myGiftThemesTokens.clear(); + _myGiftThemesLoaded = false; + } + const auto &list = data.vthemes().v; + const auto got = int(list.size()); + _myGiftThemesTokens.reserve(_myGiftThemesTokens.size() + got); + for (const auto &theme : list) { + theme.match([](const MTPDchatTheme &) { + }, [&](const MTPDchatThemeUniqueGift &data) { + _myGiftThemesTokens.push_back( + processGiftThemeGetToken(data)); + }); + } + _myGiftThemesLoaded = (got < kGiftThemesLimit); + _chatThemesUpdates.fire({}); + }, [&](const MTPDaccount_chatThemesNotModified &) { + if (!reload) { + _myGiftThemesLoaded = true; + } + }); + }).fail([=] { + _myGiftThemesRequestId = 0; + _myGiftThemesLoaded = true; + }).send(); +} + +const std::vector &CloudThemes::myGiftThemesTokens() const { + return _myGiftThemesTokens; +} + +rpl::producer<> CloudThemes::myGiftThemesUpdated() const { + return _myGiftThemesUpdates.events(); +} + +QString CloudThemes::processGiftThemeGetToken( + const MTPDchatThemeUniqueGift &data) { + auto parsed = CloudTheme::Parse(_session, data, true); + if (parsed.unique) { + const auto id = parsed.unique->id; + _giftThemes[id] = std::move(parsed); + return u"gift:%1"_q.arg(id); + } + return QString(); +} + +void CloudThemes::refreshChatThemesFor(const QString &token) { + if (token.startsWith(u"gift:"_q)) { + return; + } + refreshChatThemes(); +} + bool CloudThemes::TestingColors() { return IsTestingColors; } diff --git a/Telegram/SourceFiles/data/data_cloud_themes.h b/Telegram/SourceFiles/data/data_cloud_themes.h index 1ac4ceff19..4ccbf0a0b9 100644 --- a/Telegram/SourceFiles/data/data_cloud_themes.h +++ b/Telegram/SourceFiles/data/data_cloud_themes.h @@ -22,6 +22,7 @@ class Controller; namespace Data { +struct UniqueGift; class DocumentMedia; enum class CloudThemeType { @@ -38,6 +39,7 @@ struct CloudTheme { UserId createdBy = 0; int usersCount = 0; QString emoticon; + std::shared_ptr unique; using Type = CloudThemeType; struct Settings { @@ -52,6 +54,10 @@ struct CloudTheme { not_null session, const MTPDtheme &data, bool parseSettings = false); + static CloudTheme Parse( + not_null session, + const MTPDchatThemeUniqueGift &data, + bool parseSettings = false); static CloudTheme Parse( not_null session, const MTPTheme &data, @@ -73,9 +79,17 @@ public: void refreshChatThemes(); [[nodiscard]] const std::vector &chatThemes() const; [[nodiscard]] rpl::producer<> chatThemesUpdated() const; - [[nodiscard]] std::optional themeForEmoji( - const QString &emoticon) const; - [[nodiscard]] auto themeForEmojiValue(const QString &emoticon) + + void myGiftThemesLoadMore(bool reload = false); + [[nodiscard]] const std::vector &myGiftThemesTokens() const; + [[nodiscard]] rpl::producer<> myGiftThemesUpdated() const; + [[nodiscard]] QString processGiftThemeGetToken( + const MTPDchatThemeUniqueGift &data); + + void refreshChatThemesFor(const QString &token); + [[nodiscard]] std::optional themeForToken( + const QString &token) const; + [[nodiscard]] auto themeForTokenValue(const QString &token) -> rpl::producer>; [[nodiscard]] static bool TestingColors(); @@ -140,6 +154,13 @@ private: std::vector _chatThemes; rpl::event_stream<> _chatThemesUpdates; + mtpRequestId _myGiftThemesRequestId = 0; + base::flat_map _giftThemes; + std::vector _myGiftThemesTokens; + rpl::event_stream<> _myGiftThemesUpdates; + uint64 _myGiftThemesHash = 0; + bool _myGiftThemesLoaded = false; + base::Timer _reloadCurrentTimer; LoadingDocument _updatingFrom; LoadingDocument _previewFrom; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 1c70a3b6a8..d762a6cf68 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1736,24 +1736,22 @@ PeerId PeerData::groupCallDefaultJoinAs() const { return 0; } -void PeerData::setThemeEmoji(const QString &emoticon) { - if (_themeEmoticon == emoticon) { +void PeerData::setThemeToken(const QString &token) { + if (_themeToken == token) { + return; + } else if (Ui::Emoji::Find(_themeToken) == Ui::Emoji::Find(token)) { + _themeToken = token; return; } - if (Ui::Emoji::Find(_themeEmoticon) == Ui::Emoji::Find(emoticon)) { - _themeEmoticon = emoticon; - return; + _themeToken = token; + if (!token.isEmpty() && !owner().cloudThemes().themeForToken(token)) { + owner().cloudThemes().refreshChatThemesFor(token); } - _themeEmoticon = emoticon; - if (!emoticon.isEmpty() - && !owner().cloudThemes().themeForEmoji(emoticon)) { - owner().cloudThemes().refreshChatThemes(); - } - session().changes().peerUpdated(this, UpdateFlag::ChatThemeEmoji); + session().changes().peerUpdated(this, UpdateFlag::ChatThemeToken); } -const QString &PeerData::themeEmoji() const { - return _themeEmoticon; +const QString &PeerData::themeToken() const { + return _themeToken; } void PeerData::setWallPaper( diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index c27b25834a..ad8a1e70a3 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -530,8 +530,8 @@ public: [[nodiscard]] Data::GroupCall *groupCall() const; [[nodiscard]] PeerId groupCallDefaultJoinAs() const; - void setThemeEmoji(const QString &emoticon); - [[nodiscard]] const QString &themeEmoji() const; + void setThemeToken(const QString &token); + [[nodiscard]] const QString &themeToken() const; void setWallPaper( std::optional paper, @@ -615,7 +615,7 @@ private: uint8 _userpicHasVideo : 1 = 0; QString _about; - QString _themeEmoticon; + QString _themeToken; std::unique_ptr _wallPaper; }; diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index e0b00b1963..638aa1ff7c 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/business/data_business_common.h" #include "data/business/data_business_info.h" #include "data/components/credits.h" +#include "data/data_cloud_themes.h" #include "data/data_saved_music.h" #include "data/data_session.h" #include "data/data_changes.h" @@ -789,7 +790,16 @@ void ApplyUserUpdate(not_null user, const MTPDuserFull &update) { user->setCommonChatsCount(update.vcommon_chats_count().v); user->setPeerGiftsCount(update.vstargifts_count().value_or_empty()); user->checkFolder(update.vfolder_id().value_or_empty()); - user->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty())); + if (const auto theme = update.vtheme()) { + theme->match([&](const MTPDchatTheme &data) { + user->setThemeToken(qs(data.vemoticon())); + }, [&](const MTPDchatThemeUniqueGift &data) { + user->setThemeToken( + user->owner().cloudThemes().processGiftThemeGetToken(data)); + }); + } else { + user->setThemeToken(QString()); + } user->setTranslationDisabled(update.is_translations_disabled()); user->setPrivateForwardName( update.vprivate_forward_name().value_or_empty()); diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index 68e8d37cbe..bd16f6d86f 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -1608,9 +1608,13 @@ ServiceAction ParseServiceAction( .date = data.vschedule_date().v, }; }, [&](const MTPDmessageActionSetChatTheme &data) { - result.content = ActionSetChatTheme{ - .emoji = qs(data.vemoticon()), - }; + data.vtheme().match([&](const MTPDchatTheme &data) { + result.content = ActionSetChatTheme{ + .emoji = qs(data.vemoticon()), + }; + }, [&](const MTPDchatThemeUniqueGift &data) { + result.content = ActionSetChatTheme{}; + }); }, [&](const MTPDmessageActionChatJoinedByRequest &data) { result.content = ActionChatJoinedByRequest(); }, [&](const MTPDmessageActionWebViewDataSentMe &data) { diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 69e0ed7600..be7089d41b 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/components/top_peers.h" #include "data/notify/data_notify_settings.h" #include "data/stickers/data_stickers.h" +#include "data/data_cloud_themes.h" #include "data/data_drafts.h" #include "data/data_saved_messages.h" #include "data/data_saved_sublist.h" @@ -1303,7 +1304,12 @@ void History::applyServiceChanges( } } }, [&](const MTPDmessageActionSetChatTheme &data) { - peer->setThemeEmoji(qs(data.vemoticon())); + data.vtheme().match([&](const MTPDchatTheme &data) { + peer->setThemeToken(qs(data.vemoticon())); + }, [&](const MTPDchatThemeUniqueGift &data) { + peer->setThemeToken( + owner().cloudThemes().processGiftThemeGetToken(data)); + }); }, [&](const MTPDmessageActionSetChatWallPaper &data) { if (item->out() || data.is_for_both()) { peer->setWallPaper( diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 5207443627..66d6317374 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -5350,38 +5350,63 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) { auto prepareSetChatTheme = [this](const MTPDmessageActionSetChatTheme &action) { auto result = PreparedServiceText(); - const auto text = qs(action.vemoticon()); - if (!text.isEmpty()) { - if (_from->isSelf()) { - result.text = tr::lng_action_you_theme_changed( - tr::now, - lt_emoji, - { .text = text }, - Ui::Text::WithEntities); + action.vtheme().match([&](const MTPDchatTheme &data) { + const auto text = qs(data.vemoticon()); + if (!text.isEmpty()) { + if (_from->isSelf()) { + result.text = tr::lng_action_you_theme_changed( + tr::now, + lt_emoji, + { .text = text }, + Ui::Text::WithEntities); + } else { + result.links.push_back(fromLink()); + result.text = tr::lng_action_theme_changed( + tr::now, + lt_from, + fromLinkText(), // Link 1. + lt_emoji, + { .text = text }, + Ui::Text::WithEntities); + } } else { - result.links.push_back(fromLink()); - result.text = tr::lng_action_theme_changed( - tr::now, - lt_from, - fromLinkText(), // Link 1. - lt_emoji, - { .text = text }, - Ui::Text::WithEntities); + if (_from->isSelf()) { + result.text = tr::lng_action_you_theme_disabled( + tr::now, + Ui::Text::WithEntities); + } else { + result.links.push_back(fromLink()); + result.text = tr::lng_action_theme_disabled( + tr::now, + lt_from, + fromLinkText(), // Link 1. + Ui::Text::WithEntities); + } } - } else { - if (_from->isSelf()) { - result.text = tr::lng_action_you_theme_disabled( - tr::now, - Ui::Text::WithEntities); - } else { - result.links.push_back(fromLink()); - result.text = tr::lng_action_theme_disabled( - tr::now, - lt_from, - fromLinkText(), // Link 1. - Ui::Text::WithEntities); - } - } + }, [&](const MTPDchatThemeUniqueGift &data) { + data.vgift().match([&](const MTPDstarGiftUnique &data) { + const auto giftName = Ui::Text::Bold(qs(data.vtitle()) + + u" #"_q + + QString::number(data.vnum().v)); + if (_from->isSelf()) { + result.text = tr::lng_action_you_gift_theme_changed( + tr::now, + lt_name, + giftName, + Ui::Text::WithEntities); + } else { + result.links.push_back(fromLink()); + result.text = tr::lng_action_gift_theme_changed( + tr::now, + lt_from, + fromLinkText(), + lt_name, + giftName, + Ui::Text::WithEntities); + } + }, [](const MTPDstarGift &) { + }); + }); return result; }; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index a0cdec1702..1fa75f6852 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -814,7 +814,7 @@ HistoryWidget::HistoryWidget( | PeerUpdateFlag::Slowmode | PeerUpdateFlag::BotStartToken | PeerUpdateFlag::MessagesTTL - | PeerUpdateFlag::ChatThemeEmoji + | PeerUpdateFlag::ChatThemeToken | PeerUpdateFlag::FullInfo | PeerUpdateFlag::StarsPerMessage | PeerUpdateFlag::GiftSettings @@ -888,10 +888,10 @@ HistoryWidget::HistoryWidget( if (flags & PeerUpdateFlag::MessagesTTL) { checkMessagesTTL(); } - if ((flags & PeerUpdateFlag::ChatThemeEmoji) && _list) { - const auto emoji = _peer->themeEmoji(); + if ((flags & PeerUpdateFlag::ChatThemeToken) && _list) { + const auto emoji = _peer->themeToken(); if (Data::CloudThemes::TestingColors() && !emoji.isEmpty()) { - _peer->owner().cloudThemes().themeForEmojiValue( + _peer->owner().cloudThemes().themeForTokenValue( emoji ) | rpl::filter_optional( ) | rpl::take( diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp index 99ca5dcb62..69ece36f32 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/earn_format.cpp @@ -7,14 +7,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/channel_statistics/earn/earn_format.h" -namespace Info::ChannelEarn { +#include -using EarnInt = Data::EarnInt; +namespace Info::ChannelEarn { +namespace { constexpr auto kMinorPartLength = 9; constexpr auto kMaxChoppedZero = kMinorPartLength - 2; constexpr auto kZero = QChar('0'); -static const auto DecimalPoint = QLocale().decimalPoint(); +const auto DecimalPoint = QString() + QLocale().decimalPoint(); + +using EarnInt = Data::EarnInt; + +} // namespace QString MajorPart(EarnInt value) { const auto string = QString::number(value); diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp index ae4349346d..cbc837690d 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp @@ -1312,7 +1312,6 @@ void InnerWidget::fill() { = lifetime().make_state(_peer); state->token = firstSlice.token; state->showed = firstSlice.list.size(); - const auto max = firstSlice.total; const auto wrap = tabCurrencyList->entity()->add( object_ptr>( tabCurrencyList->entity(), diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index cdb5dfd39b..c7e6dc08db 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -167,7 +167,7 @@ messageActionGroupCall#7a0d7f42 flags:# call:InputGroupCall duration:flags.0?int messageActionInviteToGroupCall#502f92f7 call:InputGroupCall users:Vector = MessageAction; messageActionSetMessagesTTL#3c134d7b flags:# period:int auto_setting_from:flags.0?long = MessageAction; messageActionGroupCallScheduled#b3a07661 call:InputGroupCall schedule_date:int = MessageAction; -messageActionSetChatTheme#aa786345 emoticon:string = MessageAction; +messageActionSetChatTheme#b91bbd3a theme:ChatTheme = MessageAction; messageActionChatJoinedByRequest#ebbca3cb = MessageAction; messageActionWebViewDataSentMe#47dd8079 text:string data:string = MessageAction; messageActionWebViewDataSent#b4c38cb5 text:string = MessageAction; @@ -215,7 +215,7 @@ geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radiu auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode; auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode; -auth.sentCodePaymentRequired#d7cef980 store_product:string phone_code_hash:string = auth.SentCode; +auth.sentCodePaymentRequired#d7a2fcf9 store_product:string phone_code_hash:string support_email_address:string support_email_subject:string = auth.SentCode; auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization; auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization; @@ -248,7 +248,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason; inputReportReasonIllegalDrugs#a8eb2be = ReportReason; inputReportReasonPersonalDetails#9ec7863d = ReportReason; -userFull#3fd81e28 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings stars_rating:flags2.17?StarsRating stars_my_pending_rating:flags2.18?StarsRating stars_my_pending_rating_date:flags2.18?int main_tab:flags2.20?ProfileTab saved_music:flags2.21?Document = UserFull; +userFull#c577b5ad flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme:flags.15?ChatTheme private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings stars_rating:flags2.17?StarsRating stars_my_pending_rating:flags2.18?StarsRating stars_my_pending_rating_date:flags2.18?int main_tab:flags2.20?ProfileTab saved_music:flags2.21?Document = UserFull; contact#145ade0b user_id:long mutual:Bool = Contact; @@ -1417,6 +1417,12 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult; account.resetPasswordOk#e926d63e = account.ResetPasswordResult; +chatTheme#c3dffc04 emoticon:string = ChatTheme; +chatThemeUniqueGift#3458f9c8 gift:StarGift theme_settings:Vector = ChatTheme; + +account.chatThemesNotModified#e011e1c4 = account.ChatThemes; +account.chatThemes#4bcef97b flags:# hash:long themes:Vector next_offset:flags.0?int = account.ChatThemes; + sponsoredMessage#7dbf8673 flags:# recommended:flags.5?true can_report:flags.12?true random_id:bytes url:string title:string message:string entities:flags.1?Vector photo:flags.6?Photo media:flags.14?MessageMedia color:flags.13?PeerColor button_text:string sponsor_info:flags.7?string additional_info:flags.8?string min_display_duration:flags.15?int max_display_duration:flags.15?int = SponsoredMessage; messages.sponsoredMessages#ffda656d flags:# posts_between:flags.0?int start_delay:flags.1?int between_delay:flags.2?int messages:Vector chats:Vector users:Vector = messages.SponsoredMessages; @@ -2025,6 +2031,10 @@ account.savedMusicIds#998d6636 ids:Vector = account.SavedMusicIds; payments.checkCanSendGiftResultOk#374fa7ad = payments.CheckCanSendGiftResult; payments.checkCanSendGiftResultFail#d5e58274 reason:TextWithEntities = payments.CheckCanSendGiftResult; +inputChatThemeEmpty#83268483 = InputChatTheme; +inputChatTheme#c93de95c emoticon:string = InputChatTheme; +inputChatThemeUniqueGift#87e5dfe4 slug:string = InputChatTheme; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -2181,6 +2191,7 @@ account.toggleNoPaidMessagesException#fe2eda76 flags:# refund_charged:flags.0?tr account.setMainProfileTab#5dee78b0 tab:ProfileTab = Bool; account.saveMusic#b26732a9 flags:# unsave:flags.0?true id:InputDocument after_id:flags.1?InputDocument = Bool; account.getSavedMusicIds#e09d5faf hash:long = account.SavedMusicIds; +account.getUniqueGiftChatThemes#fe74ef9f offset:int limit:int hash:long = account.ChatThemes; users.getUsers#d91a548 id:Vector = Vector; users.getFullUser#b60f5918 id:InputUser = users.UserFull; @@ -2357,7 +2368,7 @@ messages.getAdminsWithInvites#3920e6ef peer:InputPeer = messages.ChatAdminsWithI messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true subscription_expired:flags.3?true peer:InputPeer link:flags.1?string q:flags.2?string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters; messages.setHistoryTTL#b80e5fe4 peer:InputPeer period:int = Updates; messages.checkHistoryImportPeer#5dc60f03 peer:InputPeer = messages.CheckedHistoryImportPeer; -messages.setChatTheme#e63be13f peer:InputPeer emoticon:string = Updates; +messages.setChatTheme#81202c9 peer:InputPeer theme:InputChatTheme = Updates; messages.getMessageReadParticipants#31c1c44f peer:InputPeer msg_id:int = Vector; messages.getSearchResultsCalendar#6aa3f6bd flags:# peer:InputPeer saved_peer_id:flags.2?InputPeer filter:MessagesFilter offset_id:int offset_date:int = messages.SearchResultsCalendar; messages.getSearchResultsPositions#9c7f2f10 flags:# peer:InputPeer saved_peer_id:flags.2?InputPeer filter:MessagesFilter offset_id:int limit:int = messages.SearchResultsPositions; @@ -2776,4 +2787,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool; fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo; -// LAYER 213 +// LAYER 214 diff --git a/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp b/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp index 5093766b17..9034ed1d26 100644 --- a/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp +++ b/Telegram/SourceFiles/statistics/view/chart_rulers_view.cpp @@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_basic.h" #include "styles/style_statistics.h" +#include + namespace Statistic { namespace { diff --git a/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp b/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp index 4314f48f20..940254a851 100644 --- a/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp +++ b/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp @@ -149,8 +149,9 @@ struct ChooseThemeController::Entry { Ui::ChatThemeKey key; std::shared_ptr theme; std::shared_ptr media; - QImage preview; + std::shared_ptr gift; EmojiPtr emoji = nullptr; + QImage preview; QRect geometry; bool chosen = false; }; @@ -178,6 +179,10 @@ void ChooseThemeController::init(rpl::producer outer) { using namespace rpl::mappers; const auto themes = &_controller->session().data().cloudThemes(); + if (themes->myGiftThemesTokens().empty()) { + themes->myGiftThemesLoadMore(); + } + const auto &list = themes->chatThemes(); if (!list.empty()) { fill(list); @@ -269,7 +274,7 @@ void ChooseThemeController::initButtons() { int applyWidth, int chooseWidth, QString chosen) { - const auto was = _peer->themeEmoji(); + const auto was = _peer->themeToken(); const auto now = (chosen == kDisableElement()) ? QString() : chosen; const auto changed = (now != was); apply->setVisible(changed); @@ -283,10 +288,14 @@ void ChooseThemeController::initButtons() { apply->setClickedCallback([=] { if (const auto chosen = findChosen()) { - const auto was = _peer->themeEmoji(); + const auto was = _peer->themeToken(); const auto now = chosen->key ? _chosen.current() : QString(); if (was != now) { - _peer->setThemeEmoji(now); + const auto giftTheme = now.startsWith(u"gift:"_q) + ? _peer->owner().cloudThemes().themeForToken(now) + : std::optional(); + + _peer->setThemeToken(now); const auto dropWallPaper = (_peer->wallPaper() != nullptr); if (dropWallPaper) { _peer->setWallPaper({}); @@ -297,6 +306,7 @@ void ChooseThemeController::initButtons() { _controller->pushLastUsedChatTheme(chosen->theme); } const auto api = &_peer->session().api(); + api->request(MTPmessages_SetChatWallPaper( MTP_flags(0), _peer->input, @@ -306,9 +316,13 @@ void ChooseThemeController::initButtons() { )).afterDelay(10).done([=](const MTPUpdates &result) { api->applyUpdates(result); }).send(); + api->request(MTPmessages_SetChatTheme( _peer->input, - MTP_string(now) + ((giftTheme && giftTheme->unique) + ? MTP_inputChatThemeUniqueGift( + MTP_string(giftTheme->unique->slug)) + : MTP_inputChatTheme(MTP_string(now))) )).done([=](const MTPUpdates &result) { api->applyUpdates(result); }).send(); @@ -333,7 +347,9 @@ void ChooseThemeController::paintEntry(QPainter &p, const Entry &entry) { + geometry.height() - (size / factor) - st::chatThemeEmojiBottom; - Ui::Emoji::Draw(p, entry.emoji, size, emojiLeft, emojiTop); + if (const auto emoji = entry.emoji) { + Ui::Emoji::Draw(p, emoji, size, emojiLeft, emojiTop); + } if (entry.chosen) { auto hq = PainterHighQualityEnabler(p); @@ -492,7 +508,7 @@ void ChooseThemeController::updateInnerLeft(int now) { void ChooseThemeController::close() { if (const auto chosen = findChosen()) { - if (Ui::Emoji::Find(_peer->themeEmoji()) != chosen->emoji) { + if (Ui::Emoji::Find(_peer->themeToken()) != chosen->emoji) { clearCurrentBackgroundState(); } } @@ -543,13 +559,18 @@ void ChooseThemeController::fill( full, margin.top() + single.height() + margin.bottom()); - const auto initial = Ui::Emoji::Find(_peer->themeEmoji()); + const auto initial = Ui::Emoji::Find(_peer->themeToken()); if (!initial) { _chosen = kDisableElement(); } - _dark.value( - ) | rpl::start_with_next([=](bool dark) { + const auto cloudThemes = &_controller->session().data().cloudThemes(); + rpl::combine( + _dark.value(), + rpl::single( + rpl::empty + ) | rpl::then(cloudThemes->myGiftThemesUpdated()) + ) | rpl::start_with_next([=](bool dark, auto) { clearCurrentBackgroundState(); if (_chosen.current().isEmpty() && initial) { _chosen = initial->text(); @@ -559,8 +580,8 @@ void ChooseThemeController::fill( const auto old = base::take(_entries); auto x = margin.left(); _entries.push_back({ - .preview = GenerateEmptyPreview(), .emoji = _disabledEmoji, + .preview = GenerateEmptyPreview(), .geometry = QRect(QPoint(x, margin.top()), single), .chosen = (_chosen.current() == kDisableElement()), }); @@ -640,6 +661,72 @@ void ChooseThemeController::fill( }, _cachingLifetime); x += single.width() + skip; } + for (const auto &token : cloudThemes->myGiftThemesTokens()) { + const auto found = cloudThemes->themeForToken(token); + if (!found || found->settings.contains(type)) { + continue; + } + const auto &theme = *found; + const auto key = ChatThemeKey{ theme.id, dark }; + const auto isChosen = (_chosen.current() == token); + _entries.push_back({ + .key = key, + .gift = found->unique, + .geometry = QRect(QPoint(x, skip), single), + .chosen = isChosen, + }); + _controller->cachedChatThemeValue( + theme, + Data::WallPaper(0), + type + ) | rpl::filter([=](const std::shared_ptr &data) { + return data && (data->key() == key); + }) | rpl::take( + 1 + ) | rpl::start_with_next([=](std::shared_ptr &&data) { + const auto key = data->key(); + const auto i = ranges::find(_entries, key, &Entry::key); + if (i == end(_entries)) { + return; + } + const auto theme = data.get(); + i->theme = std::move(data); + i->preview = GeneratePreview(theme); + if (_chosen.current() == i->emoji->text()) { + _controller->overridePeerTheme( + _peer, + i->theme, + i->emoji); + } + _inner->update(); + + if (!theme->background().isPattern + || !theme->background().prepared.isNull()) { + return; + } + // Subscribe to pattern loading if needed. + theme->repaintBackgroundRequests( + ) | rpl::filter([=] { + const auto i = ranges::find( + _entries, + key, + &Entry::key); + return (i == end(_entries)) + || !i->theme->background().prepared.isNull(); + }) | rpl::take(1) | rpl::start_with_next([=] { + const auto i = ranges::find( + _entries, + key, + &Entry::key); + if (i == end(_entries)) { + return; + } + i->preview = GeneratePreview(theme); + _inner->update(); + }, _cachingLifetime); + }, _cachingLifetime); + x += single.width() + skip; + } if (!_initialInnerLeftApplied && _content->width() > 0) { applyInitialInnerLeft(); diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index 29da7f47ad..42112e3be6 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -36,13 +36,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Window { namespace { -[[nodiscard]] rpl::producer PeerThemeEmojiValue( +[[nodiscard]] rpl::producer PeerThemeTokenValue( not_null peer) { return peer->session().changes().peerFlagsValue( peer, - Data::PeerUpdate::Flag::ChatThemeEmoji + Data::PeerUpdate::Flag::ChatThemeToken ) | rpl::map([=] { - return peer->themeEmoji(); + return peer->themeToken(); }); } @@ -96,11 +96,11 @@ struct ResolvedPaper { [[nodiscard]] auto MaybeChatThemeDataValueFromPeer( not_null peer) -> rpl::producer> { - return PeerThemeEmojiValue( + return PeerThemeTokenValue( peer - ) | rpl::map([=](const QString &emoji) + ) | rpl::map([=](const QString &token) -> rpl::producer> { - return peer->owner().cloudThemes().themeForEmojiValue(emoji); + return peer->owner().cloudThemes().themeForTokenValue(token); }) | rpl::flatten_latest(); } @@ -507,7 +507,7 @@ auto ChatThemeValueFromPeer( std::shared_ptr &&cloud, PeerThemeOverride &&overriden) { return (overriden.peer == peer.get() - && Ui::Emoji::Find(peer->themeEmoji()) != overriden.emoji) + && Ui::Emoji::Find(peer->themeToken()) != overriden.emoji) ? std::move(overriden.theme) : std::move(cloud); });