From 7d172a6427f9f353bcc998bc5f9c4235ca51978d Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 4 Feb 2026 14:28:15 +0400 Subject: [PATCH] Allow to toggle between regular and crafted models. --- Telegram/Resources/langs/lang.strings | 2 + .../boxes/star_gift_preview_box.cpp | 120 ++++++++++++++++-- Telegram/SourceFiles/ui/effects/credits.style | 4 + 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 578a935bc7..a808dc5d34 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4279,6 +4279,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_auction_preview_models_button" = "Models"; "lng_auction_preview_crafted#one" = "This collectible features **{count}** crafted model."; "lng_auction_preview_crafted#other" = "This collectible features **{count}** crafted models."; +"lng_auction_preview_view_craftable" = "View craftable models {arrow}"; +"lng_auction_preview_view_primary" = "View primary models {arrow}"; "lng_auction_preview_backdrop" = "backdrop"; "lng_auction_preview_backdrops#one" = "This collectible features **{count}** unique backdrop."; "lng_auction_preview_backdrops#other" = "This collectible features **{count}** unique backdrops."; diff --git a/Telegram/SourceFiles/boxes/star_gift_preview_box.cpp b/Telegram/SourceFiles/boxes/star_gift_preview_box.cpp index d096700a47..1c35a778e9 100644 --- a/Telegram/SourceFiles/boxes/star_gift_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_preview_box.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/top_background_gradient.h" #include "settings/settings_credits_graphics.h" +#include "styles/style_chat.h" #include "styles/style_credits.h" #include "styles/style_layers.h" @@ -200,10 +201,13 @@ public: QWidget *parent, not_null delegate, not_null attributes, + std::vector otherModels, rpl::producer tab, Selection initialSelection); [[nodiscard]] rpl::producer selected() const; + [[nodiscard]] auto modelsToggled() const + -> rpl::producer>; private: struct Entry { @@ -231,6 +235,7 @@ private: int resizeGetHeight(int width) override; void clicked(int index); + void toggleModels(); const not_null _delegate; const not_null _attributes; @@ -257,6 +262,10 @@ private: int _visibleTill = 0; bool _craftedModels = false; + std::vector _activeModels; + std::vector _otherModels; + std::unique_ptr _toggleLink; + rpl::event_stream> _modelsToggled; }; @@ -970,6 +979,7 @@ AttributesList::AttributesList( QWidget *parent, not_null delegate, not_null attributes, + std::vector otherModels, rpl::producer tab, Selection initialSelection) : BoxContentDivider(parent) @@ -980,9 +990,13 @@ AttributesList::AttributesList( , _entries(&_models) , _list(&_entries->list) { _singleMin = _delegate->buttonSize(); + _activeModels.assign( + attributes->models.begin(), + attributes->models.end()); + _otherModels = std::move(otherModels); - _craftedModels = !attributes->models.empty() - && (attributes->models.front().rarityType() + _craftedModels = !_activeModels.empty() + && (_activeModels.front().rarityType() != Data::UniqueGiftRarity::Default); fill(); @@ -998,8 +1012,8 @@ AttributesList::AttributesList( Unexpected("Tab in AttributesList."); }(); _list = &_entries->list; - refreshButtons(); refreshAbout(); + refreshButtons(); }, lifetime()); _selected.value() | rpl::combine_previous() | rpl::on_next([=]( @@ -1034,6 +1048,11 @@ auto AttributesList::selected() const -> rpl::producer { return _selected.value(); } +auto AttributesList::modelsToggled() const + -> rpl::producer> { + return _modelsToggled.events(); +} + void AttributesList::fill() { const auto addEntries = [&]( const auto &source, @@ -1047,7 +1066,7 @@ void AttributesList::fill() { target.list.emplace_back(Entry{ { item }, { value } }); } }; - addEntries(_attributes->models, _models, &Selection::model); + addEntries(_activeModels, _models, &Selection::model); addEntries(_attributes->patterns, _patterns, &Selection::pattern); addEntries(_attributes->backdrops, _backdrops, &Selection::backdrop); } @@ -1226,9 +1245,42 @@ void AttributesList::refreshAbout() { st::giftListAbout); about->show(); _about = std::move(about); + + if (_tab.current() == Tab::Model && !_otherModels.empty()) { + auto linkText = (_craftedModels + ? tr::lng_auction_preview_view_primary + : tr::lng_auction_preview_view_craftable)( + lt_arrow, + rpl::single(Ui::Text::IconEmoji(&st::textMoreIconEmoji)), + tr::link); + auto link = std::make_unique( + this, + std::move(linkText), + st::giftListAboutToggle); + link->overrideLinkClickHandler([=] { toggleModels(); }); + link->show(); + _toggleLink = std::move(link); + } else { + _toggleLink = nullptr; + } + resizeToWidth(width()); } +void AttributesList::toggleModels() { + std::swap(_activeModels, _otherModels); + _craftedModels = !_craftedModels; + fill(); + _entries = &_models; + _list = &_entries->list; + _modelsToggled.fire_copy(_activeModels); + auto sel = _selected.current(); + sel.model = -1; + _selected.force_assign(sel); + refreshAbout(); + refreshButtons(); +} + int AttributesList::resizeGetHeight(int width) { const auto padding = st::giftBoxPadding; const auto count = int(_list->size()); @@ -1243,9 +1295,25 @@ int AttributesList::resizeGetHeight(int width) { auto result = 0; const auto margin = st::giftListAboutMargin; - _about->resizeToWidth(width - margin.left() - margin.right()); - _about->moveToLeft(margin.left(), result + margin.top()); - result += margin.top() + _about->height() + margin.bottom(); + const auto contentWidth = width - margin.left() - margin.right(); + _about->resizeToWidth(contentWidth); + if (_toggleLink) { + _toggleLink->resizeToWidth(contentWidth); + } + const auto addedSpace = _toggleLink + ? (st::giftListAboutToggleSkip + _toggleLink->height()) + : 0; + const auto marginTop = margin.top() - addedSpace / 2; + const auto marginBottom = margin.bottom() + - (addedSpace - addedSpace / 2); + _about->moveToLeft(margin.left(), result + marginTop); + result += marginTop + _about->height(); + if (_toggleLink) { + result += st::giftListAboutToggleSkip; + _toggleLink->moveToLeft(margin.left(), result); + result += _toggleLink->height(); + } + result += marginBottom; const auto singlew = std::min( ((available + skipw) / _perRow) - skipw, @@ -1276,8 +1344,6 @@ void StarGiftPreviewBox( Expects(!attributes.patterns.empty()); Expects(!attributes.backdrops.empty()); - // If we have selected gift, remove all attributes not of the same type. - // If we don't have selected gift, remove non-default-type attributes. const auto filter = [&](auto &list, auto attribute) { const auto rarityProj = &Data::UniqueGiftAttribute::rarityType; const auto simple = Data::UniqueGiftRarity::Default; @@ -1297,10 +1363,38 @@ void StarGiftPreviewBox( } Assert(!list.empty()); }; - filter(attributes.models, &Data::UniqueGift::model); filter(attributes.patterns, &Data::UniqueGift::pattern); filter(attributes.backdrops, &Data::UniqueGift::backdrop); + auto otherModels = std::vector(); + { + const auto simple = Data::UniqueGiftRarity::Default; + const auto showCrafted = selected + && (selected->model.rarityType() != simple); + auto defaultModels = std::vector(); + auto craftedModels = std::vector(); + for (auto &model : attributes.models) { + if (model.rarityType() == simple) { + defaultModels.push_back(std::move(model)); + } else { + craftedModels.push_back(std::move(model)); + } + } + if (!defaultModels.empty() && !craftedModels.empty()) { + if (showCrafted) { + attributes.models = std::move(craftedModels); + otherModels = std::move(defaultModels); + } else { + attributes.models = std::move(defaultModels); + otherModels = std::move(craftedModels); + } + } else if (!defaultModels.empty()) { + attributes.models = std::move(defaultModels); + } else { + attributes.models = std::move(craftedModels); + } + } + box->setStyle(st::uniqueAttributesBox); box->setWidth(st::boxWideWidth); box->setNoContentMargin(true); @@ -1436,6 +1530,7 @@ void StarGiftPreviewBox( box, &state->delegate, &state->attributes, + std::move(otherModels), state->tab.value(), state->fixed)); state->list->selected( @@ -1446,6 +1541,11 @@ void StarGiftPreviewBox( || (value.backdrop >= 0); state->push(); }, box->lifetime()); + state->list->modelsToggled( + ) | rpl::on_next([=](std::vector models) { + state->attributes.models = std::move(models); + state->models.clear(); + }, box->lifetime()); const auto button = box->addButton(rpl::single(u""_q), [] {}); const auto buttonsParent = button->parentWidget(); diff --git a/Telegram/SourceFiles/ui/effects/credits.style b/Telegram/SourceFiles/ui/effects/credits.style index 294672caca..2c05692c25 100644 --- a/Telegram/SourceFiles/ui/effects/credits.style +++ b/Telegram/SourceFiles/ui/effects/credits.style @@ -255,6 +255,10 @@ giftListAbout: FlatLabel(defaultFlatLabel) { style: boxLabelStyle; } giftListAboutMargin: margins(12px, 24px, 12px, 24px); +giftListAboutToggle: FlatLabel(giftListAbout) { + style: semiboldTextStyle; +} +giftListAboutToggleSkip: 4px; giftBoxEmojiToggleTop: 7px; giftBoxLimitTop: 28px; giftBoxLock: IconEmoji {