mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Mostly ready emoji stake edit box.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2477,7 +2477,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_stake_game_beta" = "Beta";
|
||||
"lng_stake_game_about" = "A limited play-test of the upcoming emoji mini-game platform for a small group of users.";
|
||||
"lng_stake_game_results" = "Results and Returns";
|
||||
"lng_stake_game_resets" = "A streak resets after 3 sixes or a stake change.";
|
||||
"lng_stake_game_resets" = "A streak resets after 3 {emoji} or a stake change.";
|
||||
"lng_stake_game_your" = "Your stake";
|
||||
"lng_stake_game_save_and_roll" = "Save and Roll";
|
||||
|
||||
|
||||
@@ -67,6 +67,13 @@
|
||||
<file alias="slot_pull.tgs">../../animations/dice/slot_pull.tgs</file>
|
||||
<file alias="winners.tgs">../../animations/dice/winners.tgs</file>
|
||||
|
||||
<file alias="dice_1.tgs">../../animations/dice/dice_1.tgs</file>
|
||||
<file alias="dice_2.tgs">../../animations/dice/dice_2.tgs</file>
|
||||
<file alias="dice_3.tgs">../../animations/dice/dice_3.tgs</file>
|
||||
<file alias="dice_4.tgs">../../animations/dice/dice_4.tgs</file>
|
||||
<file alias="dice_5.tgs">../../animations/dice/dice_5.tgs</file>
|
||||
<file alias="dice_6.tgs">../../animations/dice/dice_6.tgs</file>
|
||||
|
||||
<file alias="star_reaction_appear.tgs">../../animations/star_reaction/appear.tgs</file>
|
||||
<file alias="star_reaction_center.tgs">../../animations/star_reaction/center.tgs</file>
|
||||
<file alias="star_reaction_select.tgs">../../animations/star_reaction/select.tgs</file>
|
||||
|
||||
@@ -47,6 +47,7 @@ Dice::Dice(not_null<Element*> parent, not_null<Data::MediaDice*> dice)
|
||||
|
||||
if (const auto outcome = _dice->outcome()) {
|
||||
_outcomeSet = true;
|
||||
_outcomeValue = _dice->value();
|
||||
_outcomeNanoTon = outcome.nanoTon;
|
||||
updateOutcomeMessage();
|
||||
}
|
||||
@@ -75,7 +76,7 @@ void Dice::updateOutcomeMessage() {
|
||||
lt_amount,
|
||||
amount,
|
||||
tr::marked))
|
||||
: !_dice->value()
|
||||
: !_outcomeValue
|
||||
? tr::lng_action_stake_game_loading(tr::now, tr::marked)
|
||||
: (out
|
||||
? tr::lng_action_stake_game_nothing_you(tr::now, tr::marked)
|
||||
@@ -103,11 +104,15 @@ bool Dice::updateItemData() {
|
||||
const auto outcome = _dice->outcome();
|
||||
const auto outcomeSet = !!outcome;
|
||||
const auto outcomeNanoTon = outcomeSet ? outcome.nanoTon : 0;
|
||||
if (_outcomeSet == outcomeSet && _outcomeNanoTon == outcomeNanoTon) {
|
||||
const auto outcomeValue = _dice->value();
|
||||
if (_outcomeSet == outcomeSet
|
||||
&& _outcomeNanoTon == outcomeNanoTon
|
||||
&& _outcomeValue == outcomeValue) {
|
||||
return false;
|
||||
}
|
||||
_outcomeSet = outcomeSet;
|
||||
_outcomeNanoTon = outcomeNanoTon;
|
||||
_outcomeValue = outcomeValue;
|
||||
updateOutcomeMessage();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ private:
|
||||
std::optional<Sticker> _start;
|
||||
std::optional<Sticker> _end;
|
||||
int64 _outcomeNanoTon = false;
|
||||
int _outcomeValue = 0;
|
||||
mutable bool _showLastFrame = false;
|
||||
mutable bool _drawingEnd = false;
|
||||
bool _outcomeSet = false;
|
||||
|
||||
@@ -8,7 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/boxes/emoji_stake_box.h"
|
||||
|
||||
#include "base/object_ptr.h"
|
||||
#include "chat_helpers/stickers_lottie.h"
|
||||
#include "data/components/credits.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_session.h"
|
||||
#include "info/channel_statistics/earn/earn_icons.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "lottie/lottie_icon.h"
|
||||
@@ -18,12 +22,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/controls/ton_common.h"
|
||||
#include "ui/text/custom_emoji_helper.h"
|
||||
#include "ui/text/custom_emoji_text_badge.h"
|
||||
#include "ui/text/text_lottie_custom_emoji.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/fields/number_input.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "styles/style_calls.h" // confcallJoinBox
|
||||
#include "styles/style_chat.h"
|
||||
@@ -53,15 +59,140 @@ namespace {
|
||||
const auto &size = st::settingsCloudPasswordIconSize;
|
||||
auto icon = Settings::CreateLottieIcon(
|
||||
box->verticalLayout(),
|
||||
{ .name = u"dice_idle"_q, .sizeOverride = { size, size } },
|
||||
{ .name = u"dice_6"_q, .sizeOverride = { size, size } },
|
||||
st::settingLocalPasscodeIconPadding);
|
||||
const auto animate = std::move(icon.animate);
|
||||
box->showFinishes() | rpl::take(1) | rpl::on_next([=] {
|
||||
animate(anim::repeat::loop);
|
||||
animate(anim::repeat::once);
|
||||
}, box->lifetime());
|
||||
return std::move(icon.widget);
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<RpWidget> MakeTable(
|
||||
not_null<RpWidget*> parent,
|
||||
const EmojiGameStakeArgs &args) {
|
||||
auto result = object_ptr<RpWidget>(parent);
|
||||
const auto raw = result.data();
|
||||
|
||||
struct State {
|
||||
std::array<std::unique_ptr<Text::CustomEmoji>, 6> dices;
|
||||
std::array<Text::String, 7> multiplicators;
|
||||
};
|
||||
const auto state = raw->lifetime().make_state<State>();
|
||||
const auto serialize = [&](int milliReward) {
|
||||
return QString(QChar(0xD7)) + QString::number(milliReward / 1000.);
|
||||
};
|
||||
const auto esize = st::largeEmojiSize;
|
||||
for (auto i = 0; i != 6; ++i) {
|
||||
state->dices[i] = Lottie::MakeEmoji({
|
||||
.name = u"dice_%1"_q.arg(i + 1),
|
||||
.sizeOverride = QSize(esize, esize),
|
||||
}, [=] { raw->update(); });
|
||||
const auto value = (i < args.milliRewards.size())
|
||||
? args.milliRewards[i]
|
||||
: 0;
|
||||
state->multiplicators[i].setText(
|
||||
st::semiboldTextStyle,
|
||||
serialize(value));
|
||||
}
|
||||
state->multiplicators[6].setText(
|
||||
st::semiboldTextStyle,
|
||||
serialize(args.jackpotMilliReward));
|
||||
|
||||
raw->paintOn([=](QPainter &p) {
|
||||
auto path = QPainterPath();
|
||||
const auto &st = st::defaultTable;
|
||||
const auto border = st.border;
|
||||
const auto half = border / 2.;
|
||||
const auto add = QMargins(border, border, border, border);
|
||||
const auto inner = raw->rect().marginsRemoved(add);
|
||||
path.addRoundedRect(inner, st.radius, st.radius);
|
||||
{
|
||||
const auto y = border + inner.height() / 2.;
|
||||
path.moveTo(border + half, y);
|
||||
path.lineTo(border + inner.width() - half, y);
|
||||
}
|
||||
{
|
||||
const auto x = border + inner.width() / 2.;
|
||||
path.moveTo(x, border + half);
|
||||
path.lineTo(x, border + inner.height() - half);
|
||||
}
|
||||
{
|
||||
const auto x = border + (inner.width() - border) / 4.;
|
||||
path.moveTo(x, border + half);
|
||||
path.lineTo(x, border + inner.height() - half);
|
||||
}
|
||||
{
|
||||
const auto x = border
|
||||
+ (inner.width() / 2.)
|
||||
+ (inner.width() - border) / 4.;
|
||||
path.moveTo(x, border + half);
|
||||
path.lineTo(x, border + (inner.height() / 2.) - half);
|
||||
}
|
||||
auto pen = st.borderFg->p;
|
||||
pen.setWidth(st.border);
|
||||
p.setPen(pen);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.drawPath(path);
|
||||
|
||||
const auto etop = -style::ConvertScale(10);
|
||||
const auto ttop = etop + esize;
|
||||
{
|
||||
auto left = border + half;
|
||||
const auto width = (inner.width() - 3 * border) / 4.;
|
||||
auto top = border + half;
|
||||
const auto now = crl::now();
|
||||
for (auto i = 0; i != 7; ++i, left += width + border) {
|
||||
if (i == 4) {
|
||||
left -= 4 * (width + border);
|
||||
top += border + half + inner.height() / 2.;
|
||||
}
|
||||
const auto x = int(base::SafeRound(left));
|
||||
const auto y = int(base::SafeRound(top));
|
||||
const auto right = (i < 6)
|
||||
? int(base::SafeRound(left + width))
|
||||
: int(base::SafeRound(left + 2 * width + border));
|
||||
const auto w = (right - x);
|
||||
|
||||
if (i < 6) {
|
||||
state->dices[i]->paint(p, {
|
||||
.textColor = st::windowBoldFg->c,
|
||||
.now = now,
|
||||
.position = QPoint(x + (w - esize) / 2, y + etop),
|
||||
.paused = true,
|
||||
.internal = { .forceLastFrame = true }
|
||||
});
|
||||
} else {
|
||||
const auto e = state->dices.back().get();
|
||||
for (auto j = 0; j != 3; ++j) {
|
||||
e->paint(p, {
|
||||
.textColor = st::windowBoldFg->c,
|
||||
.now = now,
|
||||
.position = QPoint(
|
||||
x + (w - 3 * esize) / 2 + (esize * j),
|
||||
y + etop),
|
||||
.paused = true,
|
||||
.internal = { .forceLastFrame = true }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
p.setPen(st::windowBoldFg);
|
||||
const auto &mul = state->multiplicators[i];
|
||||
mul.draw(p, {
|
||||
.position = { x + (w - mul.maxWidth()) / 2, y + ttop },
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
raw->widthValue() | rpl::on_next([=](int width) {
|
||||
raw->resize(width, width / 3);
|
||||
}, raw->lifetime());
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
not_null<NumberInput*> AddStarsInputField(
|
||||
@@ -124,10 +255,12 @@ void EmojiGameStakeBox(
|
||||
box->setStyle(st::confcallJoinBox);
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->setNoContentMargin(true);
|
||||
const auto container = box->verticalLayout();
|
||||
|
||||
const auto skip = st::confcallLinkHeaderIconPadding.bottom();
|
||||
box->addRow(
|
||||
MakeLogo(box),
|
||||
st::boxRowPadding + st::confcallLinkHeaderIconPadding,
|
||||
st::boxRowPadding + QMargins(0, 0, 0, skip),
|
||||
style::al_top);
|
||||
|
||||
auto helper = Text::CustomEmojiHelper();
|
||||
@@ -154,13 +287,91 @@ void EmojiGameStakeBox(
|
||||
box,
|
||||
tr::lng_stake_game_about(tr::rich),
|
||||
st::confcallLinkCenteredText),
|
||||
st::boxRowPadding,
|
||||
st::boxRowPadding + QMargins(0, 0, 0, skip),
|
||||
style::al_top
|
||||
)->setTryMakeSimilarLines(true);
|
||||
|
||||
const auto container = box->verticalLayout();
|
||||
const auto sub = st::boxRowPadding - st::defaultSubsectionTitlePadding;
|
||||
const auto subtitlePadding = QMargins(sub.left(), 0, sub.right(), 0);
|
||||
AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_stake_game_results(),
|
||||
subtitlePadding);
|
||||
|
||||
AddSubsectionTitle(container, tr::lng_stake_game_results());
|
||||
const auto half = (st::defaultTable.border + 1) / 2;
|
||||
box->addRow(
|
||||
MakeTable(box, args),
|
||||
st::boxRowPadding + QMargins(-half, 0, -half, skip / 2),
|
||||
style::al_top);
|
||||
|
||||
const auto six = Lottie::IconDescriptor{
|
||||
.name = u"dice_6"_q,
|
||||
.sizeOverride = { st::emojiSize, st::emojiSize },
|
||||
};
|
||||
const auto sixText = Text::LottieEmoji(six);
|
||||
const auto sixContext = Text::LottieEmojiContext(six);
|
||||
const auto factory = [=](
|
||||
QStringView data,
|
||||
const Text::MarkedContext &context) {
|
||||
if (auto result = sixContext.customEmojiFactory(data, context)) {
|
||||
return std::make_unique<Text::LimitedLoopsEmoji>(
|
||||
std::move(result),
|
||||
0,
|
||||
true);
|
||||
}
|
||||
return std::unique_ptr<Text::LimitedLoopsEmoji>();
|
||||
};
|
||||
const auto context = Text::MarkedContext{
|
||||
.customEmojiFactory = factory,
|
||||
};
|
||||
const auto resets = box->addRow(
|
||||
object_ptr<FlatLabel>(
|
||||
box,
|
||||
tr::lng_stake_game_resets(
|
||||
lt_emoji,
|
||||
rpl::single(sixText),
|
||||
tr::rich),
|
||||
st::confcallLinkFooterOr,
|
||||
st::defaultPopupMenu,
|
||||
context),
|
||||
st::boxRowPadding,
|
||||
style::al_top);
|
||||
resets->setTryMakeSimilarLines(true);
|
||||
resets->setAnimationsPausedCallback([=] {
|
||||
return FlatLabel::WhichAnimationsPaused::All;
|
||||
});
|
||||
|
||||
AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_stake_game_your(),
|
||||
subtitlePadding + QMargins(0, skip, 0, sub.bottom()));
|
||||
const auto field = AddTonInputField(container, {
|
||||
.value = args.currentStake,
|
||||
});
|
||||
box->setFocusCallback([=] {
|
||||
field->setFocusFast();
|
||||
});
|
||||
|
||||
const auto submit = args.submit;
|
||||
const auto callback = [=] {
|
||||
const auto text = field->getLastText();
|
||||
const auto now = Ui::ParseTonAmountString(text);
|
||||
if (!now) {
|
||||
field->showError();
|
||||
} else {
|
||||
box->closeBox();
|
||||
submit(*now);
|
||||
}
|
||||
};
|
||||
field->submits() | rpl::on_next(callback, field->lifetime());
|
||||
const auto button = box->addButton(rpl::single(QString()), callback);
|
||||
|
||||
button->setText(tr::lng_stake_game_save_and_roll(
|
||||
) | rpl::map([=](QString text) {
|
||||
return tr::marked(
|
||||
QString::fromUtf8("\xf0\x9f\x8e\xb2")
|
||||
).append(' ').append(text);
|
||||
}));
|
||||
|
||||
const auto close = CreateChild<IconButton>(
|
||||
container,
|
||||
@@ -186,39 +397,6 @@ void EmojiGameStakeBox(
|
||||
st::creditsHistoryRightSkip);
|
||||
balance->update();
|
||||
}, balance->lifetime());
|
||||
|
||||
box->addRow(
|
||||
object_ptr<FlatLabel>(
|
||||
box,
|
||||
tr::lng_stake_game_resets(tr::rich),
|
||||
st::confcallLinkCenteredText),
|
||||
st::boxRowPadding,
|
||||
style::al_top
|
||||
)->setTryMakeSimilarLines(true);
|
||||
|
||||
AddSubsectionTitle(container, tr::lng_stake_game_your());
|
||||
const auto field = AddTonInputField(container, {
|
||||
.value = args.currentStake,
|
||||
});
|
||||
|
||||
const auto submit = args.submit;
|
||||
const auto button = box->addButton(rpl::single(QString()), [=] {
|
||||
const auto text = field->getLastText();
|
||||
const auto now = Ui::ParseTonAmountString(text);
|
||||
if (!now) {
|
||||
field->showError();
|
||||
} else {
|
||||
box->closeBox();
|
||||
submit(*now);
|
||||
}
|
||||
});
|
||||
|
||||
button->setText(tr::lng_stake_game_save_and_roll(
|
||||
) | rpl::map([=](QString text) {
|
||||
return tr::marked(
|
||||
QString::fromUtf8("\xf0\x9f\x8e\xb2")
|
||||
).append(' ').append(text);
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
||||
Reference in New Issue
Block a user