diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 2fde605adc..4a70bd8e5c 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3787,6 +3787,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_transfer_sure_for" = "Do you want to transfer ownership of {name} to {recipient} for {price}?"; "lng_gift_transfer_button" = "Transfer"; "lng_gift_transfer_button_for" = "Transfer for {price}"; +"lng_gift_transfer_set_theme" = "Set as Theme in..."; +"lng_gift_transfer_choose" = "Choose Chat"; "lng_gift_transfer_wear" = "Wear"; "lng_gift_transfer_take_off" = "Take Off"; "lng_gift_transfer_sell" = "Sell"; diff --git a/Telegram/SourceFiles/boxes/transfer_gift_box.cpp b/Telegram/SourceFiles/boxes/transfer_gift_box.cpp index 598c2a4744..6ee2a4977d 100644 --- a/Telegram/SourceFiles/boxes/transfer_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/transfer_gift_box.cpp @@ -12,8 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_cloud_password.h" #include "base/unixtime.h" #include "boxes/passcode_box.h" +#include "data/data_cloud_themes.h" #include "data/data_session.h" #include "data/data_star_gift.h" +#include "data/data_thread.h" #include "data/data_user.h" #include "boxes/filters/edit_filter_chats_list.h" // CreatePe...tionSubtitle. #include "boxes/peer_list_box.h" @@ -673,6 +675,107 @@ void ShowTransferGiftBox( Ui::LayerOption::KeepOther); } +void SetThemeFromUniqueGift( + not_null window, + std::shared_ptr unique) { + class Controller final : public ChooseRecipientBoxController { + public: + Controller( + not_null window, + std::shared_ptr unique) + : ChooseRecipientBoxController({ + .session = &window->session(), + .callback = [=](not_null thread) { + const auto weak = base::make_weak(window); + const auto peer = thread->peer(); + SendPeerThemeChangeRequest(window, peer, QString(), unique); + if (weak) window->showPeerHistory(peer); + if (weak) window->hideLayer(anim::type::normal); + }, + .filter = [=](not_null thread) { + return thread->peer()->isUser(); + }, + .moneyRestrictionError = WriteMoneyRestrictionError, + }) { + } + + private: + void prepareViewHook() override { + ChooseRecipientBoxController::prepareViewHook(); + delegate()->peerListSetTitle(tr::lng_gift_transfer_choose()); + } + + }; + + window->show( + Box( + std::make_unique(window, std::move(unique)), + [](not_null box) { + box->addButton(tr::lng_cancel(), [=] { + box->closeBox(); + }); + })); +} + +void SendPeerThemeChangeRequest( + not_null controller, + not_null peer, + const QString &token, + const std::shared_ptr &unique, + bool locallySet) { + const auto api = &peer->session().api(); + + api->request(MTPmessages_SetChatWallPaper( + MTP_flags(0), + peer->input, + MTPInputWallPaper(), + MTPWallPaperSettings(), + MTPint() + )).afterDelay(10).done([=](const MTPUpdates &result) { + api->applyUpdates(result); + }).send(); + + api->request(MTPmessages_SetChatTheme( + peer->input, + (unique + ? MTP_inputChatThemeUniqueGift(MTP_string(unique->slug)) + : MTP_inputChatTheme(MTP_string(token))) + )).done([=](const MTPUpdates &result) { + api->applyUpdates(result); + if (!locallySet) { + peer->updateFullForced(); + } + }).send(); +} + +void SetPeerTheme( + not_null controller, + not_null peer, + const QString &token, + const std::shared_ptr &theme) { + const auto giftTheme = token.startsWith(u"gift:"_q) + ? peer->owner().cloudThemes().themeForToken(token) + : std::optional(); + + peer->setThemeToken(token); + const auto dropWallPaper = (peer->wallPaper() != nullptr); + if (dropWallPaper) { + peer->setWallPaper({}); + } + + if (theme) { + // Remember while changes propagate through event loop. + controller->pushLastUsedChatTheme(theme); + } + + SendPeerThemeChangeRequest( + controller, + peer, + token, + giftTheme ? giftTheme->unique : nullptr, + true); +} + void ShowBuyResaleGiftBox( std::shared_ptr show, std::shared_ptr gift, diff --git a/Telegram/SourceFiles/boxes/transfer_gift_box.h b/Telegram/SourceFiles/boxes/transfer_gift_box.h index cab7aee2b4..285c2149fb 100644 --- a/Telegram/SourceFiles/boxes/transfer_gift_box.h +++ b/Telegram/SourceFiles/boxes/transfer_gift_box.h @@ -20,6 +20,10 @@ struct UniqueGift; class SavedStarGiftId; } // namespace Data +namespace Ui { +class ChatTheme; +} // namespace Ui + void ShowTransferToBox( not_null controller, not_null peer, @@ -45,3 +49,18 @@ bool ShowResaleGiftLater( bool ShowTransferGiftLater( std::shared_ptr show, std::shared_ptr gift); + +void SetThemeFromUniqueGift( + not_null window, + std::shared_ptr unique); +void SendPeerThemeChangeRequest( + not_null controller, + not_null peer, + const QString &token, + const std::shared_ptr &unique, + bool locallySet = false); +void SetPeerTheme( + not_null controller, + not_null peer, + const QString &token, + const std::shared_ptr &theme); diff --git a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style index 6a2472a955..956c16c2cc 100644 --- a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style +++ b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style @@ -214,6 +214,7 @@ darkGiftCodeBox: Box(giveawayGiftCodeBox) { } darkGiftLink: icon {{ "menu/copy", groupCallMembersFg }}; darkGiftShare: icon {{ "menu/share", groupCallMembersFg }}; +darkGiftTheme: icon {{ "menu/colors", groupCallMembersFg }}; darkGiftTransfer: icon {{ "chat/input_replace", groupCallMembersFg }}; darkGiftNftWear: icon {{ "menu/nft_wear", groupCallMembersFg }}; darkGiftNftTakeOff: icon {{ "menu/nft_takeoff", groupCallMembersFg }}; diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index 873ac0bd34..ad337fc840 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -1094,6 +1094,13 @@ void FillUniqueGiftMenu( if (!unique) { return; } + if (unique->canBeTheme) { + menu->addAction(tr::lng_gift_transfer_set_theme(tr::now), [=] { + if (const auto window = show->resolveWindow()) { + SetThemeFromUniqueGift(window, unique); + } + }, st.theme ? st.theme : &st::menuIconChangeColors); + } const auto transfer = savedId && (savedId.isUser() ? e.in : savedId.chat()->canTransferGifts()) && (unique->starsForTransfer >= 0); @@ -1176,6 +1183,7 @@ CreditsEntryBoxStyleOverrides DarkCreditsEntryBoxStyle() { .tableValueMessage = &st::darkGiftTableMessage, .link = &st::darkGiftLink, .share = &st::darkGiftShare, + .theme = &st::darkGiftTheme, .transfer = &st::darkGiftTransfer, .wear = &st::darkGiftNftWear, .takeoff = &st::darkGiftNftTakeOff, diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.h b/Telegram/SourceFiles/settings/settings_credits_graphics.h index db7cdbe066..d4af6f0977 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.h +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.h @@ -115,6 +115,7 @@ struct CreditsEntryBoxStyleOverrides { const style::FlatLabel *tableValueMessage = nullptr; const style::icon *link = nullptr; const style::icon *share = nullptr; + const style::icon *theme = nullptr; const style::icon *transfer = nullptr; const style::icon *wear = nullptr; const style::icon *takeoff = nullptr; diff --git a/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp b/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp index cfe31e3e8d..ad42cb8dc6 100644 --- a/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp +++ b/Telegram/SourceFiles/ui/chat/choose_theme_controller.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/choose_theme_controller.h" #include "boxes/background_box.h" +#include "boxes/transfer_gift_box.h" #include "ui/dynamic_image.h" #include "ui/dynamic_thumbnails.h" #include "ui/rp_widget.h" @@ -327,42 +328,7 @@ void ChooseThemeController::initButtons() { const auto setTheme = crl::guard(apply, [=]( const QString &token, const std::shared_ptr &theme) { - const auto giftTheme = token.startsWith(u"gift:"_q) - ? _peer->owner().cloudThemes().themeForToken(token) - : std::optional(); - - _peer->setThemeToken(token); - const auto dropWallPaper = (_peer->wallPaper() != nullptr); - if (dropWallPaper) { - _peer->setWallPaper({}); - } - - if (theme) { - // Remember while changes propagate through event loop. - _controller->pushLastUsedChatTheme(theme); - } - const auto api = &_peer->session().api(); - - api->request(MTPmessages_SetChatWallPaper( - MTP_flags(0), - _peer->input, - MTPInputWallPaper(), - MTPWallPaperSettings(), - MTPint() - )).afterDelay(10).done([=](const MTPUpdates &result) { - api->applyUpdates(result); - }).send(); - - api->request(MTPmessages_SetChatTheme( - _peer->input, - ((giftTheme && giftTheme->unique) - ? MTP_inputChatThemeUniqueGift( - MTP_string(giftTheme->unique->slug)) - : MTP_inputChatTheme(MTP_string(token))) - )).done([=](const MTPUpdates &result) { - api->applyUpdates(result); - }).send(); - + SetPeerTheme(_controller, _peer, token, theme); _controller->toggleChooseChatTheme(_peer); }); const auto confirmTakeGiftTheme = crl::guard(apply, [=](