diff --git a/Telegram/Resources/icons/chat/filled_forge.svg b/Telegram/Resources/icons/chat/filled_forge.svg
new file mode 100644
index 0000000000..02b46ac481
--- /dev/null
+++ b/Telegram/Resources/icons/chat/filled_forge.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/Telegram/SourceFiles/boxes/star_gift_craft_box.cpp b/Telegram/SourceFiles/boxes/star_gift_craft_box.cpp
index 2df5955893..b57df215a1 100644
--- a/Telegram/SourceFiles/boxes/star_gift_craft_box.cpp
+++ b/Telegram/SourceFiles/boxes/star_gift_craft_box.cpp
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_credits.h"
#include "api/api_premium.h"
#include "boxes/star_gift_box.h"
+#include "core/ui_integration.h"
#include "data/stickers/data_custom_emoji.h"
#include "data/data_document.h"
#include "data/data_session.h"
@@ -37,6 +38,189 @@ namespace {
using namespace Info::PeerGifts;
+[[nodiscard]] std::array CraftBackdrops() {
+ struct Colors {
+ int center = 0;
+ int edge = 0;
+ int pattern = 0;
+ };
+ const auto hardcoded = [](Colors colors) {
+ auto result = Data::UniqueGiftBackdrop();
+ const auto color = [](int value) {
+ return QColor(
+ (uint32(value) >> 16) & 0xFF,
+ (uint32(value) >> 8) & 0xFF,
+ (uint32(value)) & 0xFF);
+ };
+ result.centerColor = color(colors.center);
+ result.edgeColor = color(colors.edge);
+ result.patternColor = color(colors.pattern);
+ return result;
+ };
+ return {
+ hardcoded({ 0x1b2d39, 0x141d2e, 0x121823 }),
+ hardcoded({ 0x562f12, 0x2a160d, 0x1f130e }),
+ hardcoded({ 0x1f363e, 0x121929, 0x10141c }),
+ hardcoded({ 0x1b4140, 0x192e37, 0x183237 }),
+ };
+}
+
+struct GiftForCraft {
+ std::shared_ptr unique;
+ Data::SavedStarGiftId manageId;
+
+ explicit operator bool() const {
+ return unique != nullptr;
+ }
+ friend inline bool operator==(
+ const GiftForCraft &,
+ const GiftForCraft &) = default;
+};
+
+struct CraftingView {
+ object_ptr widget;
+ rpl::producer editRequests;
+ rpl::producer removeRequests;
+};
+
+[[nodiscard]] CraftingView MakeCraftingView(
+ not_null parent,
+ not_null session,
+ rpl::producer> chosen) {
+ const auto width = st::boxWidth;
+
+ const auto buttonPadding = st::craftPreviewPadding;
+ const auto buttonSize = st::giftBoxGiftTiny;
+ const auto height = 2
+ * (buttonPadding.top() + buttonSize + buttonPadding.bottom());
+
+ auto widget = object_ptr(parent, height);
+ const auto raw = widget.data();
+
+ struct Entry {
+ GiftForCraft gift;
+ GiftButton *button = nullptr;
+ AbstractButton *add = nullptr;
+ AbstractButton *percent = nullptr;
+ AbstractButton *remove = nullptr;
+ };
+ struct State {
+ explicit State(not_null session)
+ : delegate(session, GiftButtonMode::CraftPreview) {
+ }
+
+ Delegate delegate;
+ std::array entries;
+ Fn refreshButton;
+ rpl::event_stream editRequests;
+ rpl::event_stream removeRequests;
+ };
+ const auto state = raw->lifetime().make_state(session);
+
+ state->refreshButton = [=](int index) {
+ Expects(index >= 0 && index < state->entries.size());
+
+ auto &entry = state->entries[index];
+ const auto single = state->delegate.buttonSize();
+ const auto geometry = QRect(
+ ((index % 2)
+ ? (width - buttonPadding.left() - single.width())
+ : buttonPadding.left()),
+ ((index < 2)
+ ? buttonPadding.top()
+ : (height - buttonPadding.top() - single.height())),
+ single.width(),
+ single.height());
+ delete base::take(entry.add);
+ delete base::take(entry.button);
+ delete base::take(entry.percent);
+ delete base::take(entry.remove);
+
+ if (entry.gift) {
+ entry.button = CreateChild(raw, &state->delegate);
+ entry.button->setDescriptor(GiftTypeStars{
+ .info = {
+ .id = entry.gift.unique->initialGiftId,
+ .unique = entry.gift.unique,
+ .document = entry.gift.unique->model.document,
+ },
+ }, GiftButton::Mode::CraftPreview);
+ entry.button->show();
+ if (index > 0) {
+ entry.button->setClickedCallback([=] {
+ state->editRequests.fire_copy(index);
+ });
+ } else {
+ entry.button->setAttribute(Qt::WA_TransparentForMouseEvents);
+ }
+ entry.button->setGeometry(
+ geometry,
+ state->delegate.buttonExtend());
+ } else {
+ entry.add = CreateChild(raw);
+ entry.add->show();
+ entry.add->paintOn([=](QPainter &p) {
+ auto hq = PainterHighQualityEnabler(p);
+ const auto radius = st::boxRadius;
+ p.setPen(Qt::NoPen);
+ p.setBrush(QColor(255, 255, 255, 32));
+
+ const auto rect = QRect(QPoint(), geometry.size());
+ p.drawRoundedRect(rect, radius, radius);
+
+ const auto &icon = st::craftAddIcon;
+ icon.paintInCenter(p, rect, st::white->c);
+ });
+ entry.add->setClickedCallback([=] {
+ state->editRequests.fire_copy(index);
+ });
+ entry.add->setGeometry(geometry);
+ }
+ };
+
+ std::move(
+ chosen
+ ) | rpl::on_next([=](const std::vector &gifts) {
+ for (auto i = 0; i != 4; ++i) {
+ auto &entry = state->entries[i];
+ const auto gift = (i < gifts.size()) ? gifts[i] : GiftForCraft();
+ if (entry.gift == gift && (entry.button || entry.add)) {
+ continue;
+ }
+ entry.gift = gift;
+ state->refreshButton(i);
+ }
+ }, raw->lifetime());
+
+ raw->paintOn([=](QPainter &p) {
+ auto hq = PainterHighQualityEnabler(p);
+
+ const auto radius = st::boxRadius;
+ const auto buttonPadding = st::craftPreviewPadding;
+ const auto buttonSize = st::giftBoxGiftTiny;
+ const auto one = buttonPadding.left()
+ + buttonSize
+ + buttonPadding.right();
+ const auto center = (width - 2 * one);
+ const auto top = (height - center) / 2;
+
+ p.setPen(Qt::NoPen);
+ p.setBrush(QColor(255, 255, 255, 32));
+
+ const auto rect = QRect(one, top, center, center);
+ p.drawRoundedRect(rect, radius, radius);
+
+ st::craftForge.paintInCenter(p, rect, st::white->c);
+ });
+
+ return {
+ .widget = std::move(widget),
+ .editRequests = state->editRequests.events(),
+ .removeRequests = state->removeRequests.events(),
+ };
+}
+
+
[[nodiscard]] QImage CreateBgGradient(
QSize size,
const Data::UniqueGiftBackdrop &backdrop) {
@@ -65,10 +249,9 @@ using namespace Info::PeerGifts;
void ShowSelectGiftBox(
not_null controller,
std::vector list,
- Fn)> chosen,
- bool exists) {
+ Fn chosen) {
controller->show(Box([=](not_null box) {
- box->setTitle(rpl::single(u"Choose Gift"_q));
+ box->setTitle(tr::lng_gift_craft_select_title());
box->setWidth(st::boxWideWidth);
struct Entry {
@@ -77,7 +260,7 @@ void ShowSelectGiftBox(
};
struct State {
explicit State(not_null session)
- : delegate(session, GiftButtonMode::Minimal) {
+ : delegate(session, GiftButtonMode::Minimal) {
}
Delegate delegate;
@@ -111,7 +294,7 @@ void ShowSelectGiftBox(
});
const auto button = state->entries.back().button;
button->setClickedCallback([=] {
- chosen(gift);
+ chosen({ gift.info.unique, gift.manageId });
box->closeBox();
});
button->show();
@@ -121,7 +304,7 @@ void ShowSelectGiftBox(
.unique = gift.info.unique,
.document = gift.info.unique->model.document,
},
- }, GiftButton::Mode::Minimal);
+ }, GiftButton::Mode::CraftPreview);
const auto width = (st::boxWideWidth - 2 * skip - st::boxRowPadding.left() - st::boxRowPadding.right()) / 3;
const auto left = st::boxRowPadding.left() + (width + skip) * col;
button->setGeometry(QRect(left, extend.top(), width, single.height()), extend);
@@ -133,52 +316,60 @@ void ShowSelectGiftBox(
box->addButton(tr::lng_box_ok(), [=] {
box->closeBox();
});
- if (exists) {
- box->addLeftButton(rpl::single(u"Remove"_q), [=] {
- chosen(std::nullopt);
- box->closeBox();
- });
- }
box->setMaxHeight(st::boxWideWidth);
}));
}
-[[nodiscard]] object_ptr MakeCraftContent(
+void Craft(
+ not_null controller,
+ std::vector gifts) {
+#if 0
+ auto inputs = QVector();
+ for (const auto &gift : gifts) {
+ inputs.push_back(
+ Api::InputSavedStarGiftId(gift.manageId, gift.unique));
+ }
+ const auto weak = base::make_weak(controller);
+ const auto session = &controller->session();
+ session->api().request(MTPpayments_CraftStarGift(
+ MTP_vector(inputs)
+ )).done([=](const MTPUpdates &result) {
+ session->api().applyUpdates(result);
+ if (const auto strong = weak.get()) {
+ strong->showPeerHistory(strong->session().user()->id);
+ }
+ }).send();
+#endif
+}
+
+void MakeCraftContent(
not_null box,
not_null controller,
- std::shared_ptr gift,
- Data::SavedStarGiftId savedId) {
- auto result = object_ptr(box->verticalLayout());
- const auto raw = result.data();
-
- const auto width = st::boxWidth;
- const auto height = st::boxWideWidth;
-
+ GiftForCraft gift) {
struct BackdropView {
Data::UniqueGiftBackdrop colors;
QImage gradient;
};
struct PatternView {
- DocumentData *document = nullptr;
std::unique_ptr emoji;
base::flat_map> emojis;
};
- struct Entry {
- Data::SavedStarGiftId id;
- std::shared_ptr gift;
- GiftButton *button = nullptr;
- AbstractButton *add = nullptr;
+ struct Cover {
+ BackdropView backdrop;
+ PatternView pattern;
+ Ui::Animations::Simple shownAnimation;
+ bool shown = false;
};
struct State {
explicit State(not_null session)
- : delegate(session, GiftButtonMode::Minimal) {
+ : delegate(session, GiftButtonMode::CraftPreview) {
}
Delegate delegate;
- BackdropView backdrop;
- PatternView pattern;
- std::vector entries;
- rpl::event_stream<> changes;
+ std::array covers;
+
+ rpl::variable> chosen;
+ rpl::variable name;
rpl::variable successPercentPermille;
rpl::variable successPercentText;
@@ -186,20 +377,30 @@ void ShowSelectGiftBox(
bool crafting = false;
};
const auto session = &controller->session();
- const auto state = raw->lifetime().make_state(session);
- state->backdrop.colors.centerColor = QColor(42, 61, 82, 255);
- state->backdrop.colors.edgeColor = QColor(35, 45, 63, 255);
- state->entries.push_back(Entry{ savedId, gift });
- for (auto i = 0; i != 3; ++i) {
- state->entries.emplace_back();
+ const auto state = box->lifetime().make_state(session);
+
+ {
+ auto backdrops = CraftBackdrops();
+ const auto emoji = Text::IconEmoji(&st::craftPattern);
+ const auto data = emoji.entities.front().data();
+ for (auto i = 0; i != backdrops.size(); ++i) {
+ state->covers[i].backdrop.colors = backdrops[i];
+ state->covers[i].pattern.emoji = Text::TryMakeSimpleEmoji(data);
+ }
}
- state->successPercentPermille = state->changes.events_starting_with_copy(
- rpl::empty
- ) | rpl::map([=] {
+ state->chosen = std::vector{ gift };
+ state->covers[0].shown = true;
+
+ state->name = state->chosen.value(
+ ) | rpl::map([=](const std::vector &gifts) {
+ return Data::UniqueGiftName(*gifts.front().unique);
+ });
+ state->successPercentPermille = state->chosen.value(
+ ) | rpl::map([=](const std::vector &gifts) {
auto result = 0;
- for (const auto &entry : state->entries) {
- if (const auto gift = entry.gift.get()) {
+ for (const auto &entry : gifts) {
+ if (const auto gift = entry.unique.get()) {
result += gift->craftChancePermille;
}
}
@@ -210,7 +411,30 @@ void ShowSelectGiftBox(
return QString::number(permille / 10.) + '%';
});
- const auto editEntry = [=](int index) {
+ const auto raw = box->verticalLayout();
+
+ const auto title = raw->add(
+ object_ptr(
+ box,
+ tr::lng_gift_craft_title(),
+ st::uniqueGiftTitle),
+ st::craftTitleMargin,
+ style::al_top);
+ title->setTextColorOverride(QColor(255, 255, 255));
+
+ auto crafting = MakeCraftingView(raw, session, state->chosen.value());
+ raw->add(std::move(crafting.widget));
+ std::move(crafting.removeRequests) | rpl::on_next([=](int index) {
+ auto chosen = state->chosen.current();
+ if (index < chosen.size()) {
+ chosen.erase(begin(chosen) + index);
+ state->chosen = std::move(chosen);
+ }
+ }, raw->lifetime());
+
+ std::move(
+ crafting.editRequests
+ ) | rpl::on_next([=](int index) {
const auto guard = base::make_weak(raw);
if (state->requestingIndex) {
state->requestingIndex = index;
@@ -218,7 +442,7 @@ void ShowSelectGiftBox(
}
state->requestingIndex = index;
session->api().request(MTPpayments_GetCraftStarGifts(
- MTP_long(gift->initialGiftId),
+ MTP_long(gift.unique->initialGiftId),
MTP_string(),
MTP_int(30)
)).done([=](const MTPpayments_SavedStarGifts &result) {
@@ -240,103 +464,57 @@ void ShowSelectGiftBox(
}
const auto index = base::take(state->requestingIndex);
- ShowSelectGiftBox(controller, list, [=](std::optional chosen) {
- if (chosen) {
- state->entries[index].gift = chosen->info.unique;
- state->entries[index].id = chosen->manageId;
+ ShowSelectGiftBox(controller, list, [=](GiftForCraft chosen) {
+ auto copy = state->chosen.current();
+ if (index < copy.size()) {
+ copy[index] = chosen;
} else {
- state->entries[index].gift = nullptr;
- state->entries[index].id = Data::SavedStarGiftId();
+ copy.push_back(chosen);
}
- state->changes.fire({});
- }, (state->entries[index].gift != nullptr));
+ const auto count = int(copy.size());
+ state->chosen = std::move(copy);
+
+ for (auto i = 4; i != 0;) {
+ auto &cover = state->covers[--i];
+ const auto shown = (i < count);
+ if (cover.shown != shown) {
+ cover.shown = shown;
+ const auto from = shown ? 0. : 1.;
+ const auto to = shown ? 1. : 0.;
+ cover.shownAnimation.start([=] {
+ raw->update();
+ }, from, to, st::fadeWrapDuration);
+ }
+ }
+ });
}).send();
- };
- const auto refreshButton = [=](int index) {
- Expects(index >= 0 && index < state->entries.size());
-
- auto &entry = state->entries[index];
- const auto single = state->delegate.buttonSize();
- const auto skip = st::boxTitleClose.width;
- const auto geometry = QRect(
- (index % 2) ? (width - skip - single.width()) : skip,
- (index < 2) ? skip : (height - st::giftBox.buttonPadding.bottom() - st::giftBox.buttonHeight - st::giftBox.buttonPadding.top() - single.height()),
- single.width(),
- single.height());
- delete base::take(entry.add);
- delete base::take(entry.button);
- if (entry.gift) {
- entry.button = CreateChild(raw, &state->delegate);
- entry.button->setDescriptor(GiftTypeStars{
- .info = {
- .id = entry.gift->initialGiftId,
- .unique = entry.gift,
- .document = entry.gift->model.document,
- },
- }, GiftButton::Mode::Minimal);
- entry.button->show();
- if (index > 0) {
- entry.button->setClickedCallback([=] {
- editEntry(index);
- });
- } else {
- entry.button->setAttribute(Qt::WA_TransparentForMouseEvents);
- }
- entry.button->setGeometry(
- geometry,
- state->delegate.buttonExtend());
- } else {
- entry.add = CreateChild(raw);
- entry.add->show();
- entry.add->paintOn([=](QPainter &p) {
- auto hq = PainterHighQualityEnabler(p);
- const auto radius = st::boxRadius;
- p.setPen(Qt::NoPen);
- p.setBrush(QColor(57, 77, 99));
- p.drawRoundedRect(
- QRect(QPoint(), geometry.size()),
- radius,
- radius);
- const auto addSize = geometry.width() / 3;
- p.setBrush(QColor(255, 255, 255));
- p.drawEllipse(addSize, (geometry.height() - addSize) / 2, addSize, addSize);
-
- const auto plusSize = geometry.width() / 6;
- p.setPen(QPen(QBrush(QColor(57, 77, 99)), plusSize / 5));
- p.setBrush(Qt::NoBrush);
- p.drawLine((geometry.width() - plusSize) / 2, geometry.height() / 2, (geometry.width() - plusSize) / 2 + plusSize, geometry.height() / 2);
- p.drawLine(geometry.width() / 2, (geometry.height() - plusSize) / 2, geometry.width() / 2, (geometry.height() - plusSize) / 2 + plusSize);
- });
- entry.add->setClickedCallback([=] {
- editEntry(index);
- });
- entry.add->setGeometry(geometry);
- }
- };
- state->changes.events_starting_with_copy(rpl::empty) | rpl::on_next([=] {
- for (auto i = 0; i != 4; ++i) {
- refreshButton(i);
- }
}, raw->lifetime());
- const auto setupPattern = [=](
- PatternView &to,
- const Data::UniqueGiftPattern &pattern) {
- const auto document = pattern.document;
- const auto callback = [=] {
- if (state->pattern.document == document) {
- raw->update();
- }
- };
- to.document = document;
- to.emoji = document->owner().customEmojiManager().create(
- document,
- callback,
- Data::CustomEmojiSizeTag::Large);
- [[maybe_unused]] const auto preload = to.emoji->ready();
- };
+ auto fullName = state->chosen.value(
+ ) | rpl::map([=](const std::vector &list) {
+ const auto unique = list.front().unique.get();
+ return Data::SingleCustomEmoji(
+ unique->model.document
+ ).append(' ').append(Data::UniqueGiftName(*unique));
+ });
+ auto aboutText = rpl::combine(
+ tr::lng_gift_craft_about1(lt_gift, fullName, tr::rich),
+ tr::lng_gift_craft_about2(tr::rich)
+ ) | rpl::map([=](TextWithEntities &&a, TextWithEntities &&b) {
+ return a.append('\n').append('\n').append(b);
+ });
+ const auto about = raw->add(
+ object_ptr(
+ raw,
+ std::move(aboutText),
+ st::craftAbout,
+ st::defaultPopupMenu,
+ Core::TextContext({ .session = session })),
+ st::craftAboutMargin,
+ style::al_top);
+ about->setTextColorOverride(st::white->c);
+ about->setTryMakeSimilarLines(true);
- setupPattern(state->pattern, gift->pattern);
raw->paintOn([=](QPainter &p) {
const auto width = raw->width();
const auto getBackdrop = [&](BackdropView &backdrop) {
@@ -349,10 +527,10 @@ void ShowSelectGiftBox(
return gradient;
};
const auto paintPattern = [&](
- QPainter &p,
- PatternView &pattern,
- const BackdropView &backdrop,
- float64 shown) {
+ QPainter &p,
+ PatternView &pattern,
+ const BackdropView &backdrop,
+ float64 shown) {
const auto color = backdrop.colors.patternColor;
const auto key = (color.red() << 16)
| (color.green() << 8)
@@ -366,52 +544,47 @@ void ShowSelectGiftBox(
QRect(0, 0, width, st::uniqueGiftSubtitleTop),
shown);
};
- p.drawImage(0, 0, getBackdrop(state->backdrop));
- paintPattern(p, state->pattern, state->backdrop, 1.);
+ for (auto i = 0; i != 4; ++i) {
+ auto &cover = state->covers[i];
+ const auto finalValue = cover.shown ? 1. : 0.;
+ const auto shown = cover.shownAnimation.value(finalValue);
+ if (shown <= 0.) {
+ break;
+ } else if (shown == 1.) {
+ const auto next = i + 1;
+ if (next < 4
+ && state->covers[next].shown
+ && !state->covers[next].shownAnimation.animating()) {
+ continue;
+ }
+ }
+ p.setOpacity(shown);
+ p.drawImage(0, 0, getBackdrop(cover.backdrop));
+ paintPattern(p, cover.pattern, cover.backdrop, 1.);
+ }
});
- raw->resize(width, height);
+ const auto button = raw->add(
+ object_ptr(
+ raw,
+ rpl::single(QString()),
+ st::giftBox.button),
+ st::giftBox.buttonPadding);
+ button->setFullRadius(true);
- const auto button = CreateChild(
- raw,
- rpl::single(QString()),
- st::giftBox.button);
button->setClickedCallback([=] {
if (state->crafting) {
return;
}
state->crafting = true;
- auto inputs = QVector();
- for (const auto &entry : state->entries) {
- if (entry.gift) {
- inputs.push_back(
- Api::InputSavedStarGiftId(entry.id, entry.gift));
- }
- }
- const auto weak = base::make_weak(controller);
- session->api().request(MTPpayments_CraftStarGift(
- MTP_vector(inputs)
- )).done([=](const MTPUpdates &result) {
- session->api().applyUpdates(result);
- if (const auto strong = weak.get()) {
- strong->showPeerHistory(strong->session().user()->id);
- }
- }).send();
+ Craft(controller, state->chosen.current());
});
- raw->sizeValue() | rpl::on_next([=](QSize size) {
- const auto width = size.width();
- const auto height = size.height();
- const auto padding = st::giftBox.buttonPadding;
- button->setFullWidth(width - padding.left() - padding.right());
- button->moveToLeft(
- padding.left(),
- height - padding.bottom() - button->height());
- }, raw->lifetime());
+
SetButtonTwoLabels(
button,
tr::lng_gift_craft_button(
lt_gift,
- rpl::single(tr::marked(Data::UniqueGiftName(*gift))),
+ state->name.value() | rpl::map(tr::marked),
tr::marked),
tr::lng_gift_craft_button_chance(
lt_percent,
@@ -420,7 +593,10 @@ void ShowSelectGiftBox(
st::resaleButtonTitle,
st::resaleButtonSubtitle);
- return result;
+ raw->widthValue() | rpl::on_next([=](int width) {
+ const auto padding = st::giftBox.buttonPadding;
+ button->setFullWidth(width - padding.left() - padding.right());
+ }, raw->lifetime());
}
void ShowGiftCraftBox(
@@ -431,8 +607,7 @@ void ShowGiftCraftBox(
box->setStyle(st::giftCraftBox);
box->setWidth(st::boxWidth);
box->setNoContentMargin(true);
- box->addRow(
- MakeCraftContent(box, controller, gift, savedId), QMargins());
+ MakeCraftContent(box, controller, GiftForCraft{ gift, savedId });
AddUniqueCloseButton(box);
}));
}
@@ -463,7 +638,7 @@ void ShowGiftCraftInfoBox(
const auto features = std::vector{
{
- st::menuIconUnique,
+ st::menuIconNftWear,
tr::lng_gift_craft_combine_title(tr::now),
tr::lng_gift_craft_combine_about(tr::now, tr::rich),
},
@@ -473,7 +648,7 @@ void ShowGiftCraftInfoBox(
tr::lng_gift_craft_input_about(tr::now, tr::marked),
},
{
- st::menuIconNftWear,
+ st::menuIconUnique,
tr::lng_gift_craft_exclusive_title(tr::now),
tr::lng_gift_craft_exclusive_about(tr::now, tr::marked),
},
diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp
index cd0ea6fc25..ab31eff006 100644
--- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp
+++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp
@@ -403,18 +403,18 @@ void GiftButton::setDocument(not_null document) {
ChatHelpers::LottiePlayerFromDocument(
media.get(),
ChatHelpers::StickerLottieSize::InlineResults,
- st::giftBoxStickerSize,
+ stickerSize(),
Lottie::Quality::High));
} else if (sticker->isWebm()) {
result = std::make_unique(
media->owner()->location(),
media->bytes(),
- st::giftBoxStickerSize);
+ stickerSize());
} else {
result = std::make_unique(
media->owner()->location(),
media->bytes(),
- st::giftBoxStickerSize);
+ stickerSize());
}
result->setRepaintCallback([=] { update(); });
_playerDocument = media->owner();
@@ -736,7 +736,7 @@ void GiftButton::paintEvent(QPaintEvent *e) {
if (_player && _player->ready()) {
const auto paused = !isOver();
auto info = _player->frame(
- st::giftBoxStickerSize,
+ stickerSize(),
QColor(0, 0, 0, 0),
false,
crl::now(),
@@ -763,7 +763,7 @@ void GiftButton::paintEvent(QPaintEvent *e) {
}
if (hidden) {
const auto topleft = QPoint(
- (width - st::giftBoxStickerSize.width()) / 2,
+ (width - stickerSize().width()) / 2,
(small()
? st::giftBoxSmallStickerTop
: _text.isEmpty()
@@ -776,7 +776,7 @@ void GiftButton::paintEvent(QPaintEvent *e) {
frame,
_hiddenBgCache,
topleft,
- st::giftBoxStickerSize,
+ stickerSize(),
width);
}
@@ -999,6 +999,12 @@ void GiftButton::paintEvent(QPaintEvent *e) {
}
}
+QSize GiftButton::stickerSize() const {
+ return (_mode == GiftButtonMode::CraftPreview)
+ ? st::giftBoxStickerTiny
+ : st::giftBoxStickerSize;
+}
+
Delegate::Delegate(not_null session, GiftButtonMode mode)
: _session(session)
, _hiddenMark(std::make_unique(
@@ -1046,9 +1052,14 @@ QSize Delegate::buttonSize() {
const auto singlew = (available - 2 * st::giftBoxGiftSkip.x())
/ kGiftsPerRow;
const auto minimal = (_mode != GiftButtonMode::Full);
+ const auto tiny = (_mode == GiftButtonMode::CraftPreview);
_single = QSize(
- singlew,
- minimal ? st::giftBoxGiftSmall : st::giftBoxGiftHeight);
+ tiny ? st::giftBoxGiftTiny : singlew,
+ (tiny
+ ? st::giftBoxGiftTiny
+ : minimal
+ ? st::giftBoxGiftSmall
+ : st::giftBoxGiftHeight));
return _single;
}
diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h
index 9986e81912..0f3776f7d3 100644
--- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h
+++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h
@@ -140,6 +140,7 @@ enum class GiftButtonMode : uint8 {
Full,
Minimal,
Selection,
+ CraftPreview,
};
enum class GiftSelectionMode : uint8 {
@@ -203,6 +204,7 @@ private:
void refreshLocked();
void setDocument(not_null document);
+ [[nodiscard]] QSize stickerSize() const;
[[nodiscard]] QMargins currentExtend() const;
[[nodiscard]] bool small() const;
diff --git a/Telegram/SourceFiles/ui/effects/credits.style b/Telegram/SourceFiles/ui/effects/credits.style
index 2daab159e8..e143cd3634 100644
--- a/Telegram/SourceFiles/ui/effects/credits.style
+++ b/Telegram/SourceFiles/ui/effects/credits.style
@@ -196,6 +196,7 @@ giftBoxPadding: margins(11px, 4px, 11px, 24px);
giftBoxGiftSkip: point(10px, 8px);
giftBoxGiftHeight: 164px;
giftBoxGiftSmall: 108px;
+giftBoxGiftTiny: 72px;
giftBoxGiftRadius: 12px;
giftBoxGiftBadgeFont: font(10px semibold);
giftBoxByStarsStyle: TextStyle(defaultTextStyle) {
@@ -221,6 +222,7 @@ giftBoxStickerStarTop: 24px;
giftBoxSmallStickerTop: 16px;
giftBoxStickerTopByStars: -4px;
giftBoxStickerSize: size(80px, 80px);
+giftBoxStickerTiny: size(48px, 48px);
giftBoxSelectSkip: 5px;
giftBoxUserpicSize: 24px;
giftBoxUserpicSkip: 2px;
@@ -584,3 +586,19 @@ auctionListRaise: RoundButton(defaultActiveButton) {
width: 0px;
}
auctionListRaisePadding: margins(0px, 8px, 0px, 0px);
+
+craftTitleMargin: margins(64px, 16px, 64px, 4px);
+craftAbout: FlatLabel(defaultFlatLabel) {
+ align: align(top);
+ minWidth: 128px;
+}
+craftAboutMargin: margins(24px, 16px, 24px, 4px);
+craftPattern: IconEmoji {
+ icon: icon{{ "chat/filled_forge-36x36", windowFg }};
+ padding: margins(0px, 0px, 0px, 0px);
+}
+craftAddIcon: icon {{ "settings/plus", windowFgActive }};
+craftPreviewPadding: margins(24px, 12px, 18px, 8px);
+craftForge: icon{{ "chat/filled_forge-48x48", windowFg }};
+craftForgePadding: 12px;
+craftForgeTextBottom: 12px;