Support locked gifts.

This commit is contained in:
John Preston
2025-08-22 16:16:58 +04:00
parent 0e43fd4d00
commit 1e2531f0b1
8 changed files with 100 additions and 16 deletions
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Mini / mini_gift_lock</title>
<g id="Mini-/-mini_gift_lock" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M34.6666667,26.3333333 C40.1895142,26.3333333 44.6666667,30.8104858 44.6666667,36.3333333 C44.6666667,41.8561808 40.1895142,46.3333333 34.6666667,46.3333333 C29.1438192,46.3333333 24.6666667,41.8561808 24.6666667,36.3333333 C24.6666667,30.8104858 29.1438192,26.3333333 34.6666667,26.3333333 Z M22,3.06666667 C27.8542183,3.06666667 32.6,7.81244832 32.6,13.6666667 L32.5999548,19.4672746 C34.7232323,19.9235567 36.4292218,21.5034006 37.0650949,23.5539779 C36.287246,23.4090943 35.4858038,23.3333333 34.6666667,23.3333333 C27.4869649,23.3333333 21.6666667,29.1536316 21.6666667,36.3333333 C21.6666667,38.3649522 22.1326999,40.2877232 22.9636948,42.0005746 L12.6666667,42 C9.35295817,42 6.66666667,39.3137085 6.66666667,36 L6.66666667,25.3333333 C6.66666667,22.454169 8.69461762,20.048658 11.4000452,19.4672746 L11.4,13.6666667 C11.4,7.81244832 16.1457817,3.06666667 22,3.06666667 Z M34.6666667,29.3061633 C33.7052821,29.3061633 32.9259259,30.0855195 32.9259259,31.0469041 L32.9259259,36.9308449 C32.9259259,37.7182476 33.2996271,38.4589206 33.9329602,38.9267797 L37.3333333,41.3922119 C38.1066056,41.9634476 39.1965447,41.7996646 39.7677804,41.0263923 L39.8381314,40.9238035 C40.323622,40.1593232 40.1416125,39.1383445 39.4019608,38.5919452 L36.4074074,36.4264726 L36.4074074,31.0469041 C36.4074074,30.0855195 35.6280512,29.3061633 34.6666667,29.3061633 Z M22,7.6 C18.6494725,7.6 15.9333333,10.3161392 15.9333333,13.6666667 L15.9326667,19.3326667 L28.0666667,19.3326667 L28.0666667,13.6666667 C28.0666667,10.3161392 25.3505275,7.6 22,7.6 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+1
View File
@@ -3867,6 +3867,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_collection_delete_sure" = "Are you sure you want to delete this collection?";
"lng_gift_collection_delete_button" = "Delete";
"lng_gift_collection_add_to" = "Add to Collection";
"lng_gift_locked_title" = "Gift Locked";
"lng_accounts_limit_title" = "Limit Reached";
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";
+1
View File
@@ -863,6 +863,7 @@ std::optional<Data::StarGift> FromTL(
.perUserRemains = data.vper_user_remains().value_or_empty(),
.firstSaleDate = data.vfirst_sale_date().value_or_empty(),
.lastSaleDate = data.vlast_sale_date().value_or_empty(),
.lockedUntilDate = data.vlocked_until_date().value_or_empty(),
.requirePremium = data.is_require_premium(),
.upgradable = data.vupgrade_stars().has_value(),
.birthday = data.is_birthday(),
+53 -15
View File
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_credits.h"
#include "api/api_global_privacy.h"
#include "api/api_premium.h"
#include "api/api_text_entities.h"
#include "base/event_filter.h"
#include "base/qt_signal_producer.h"
#include "base/random.h"
@@ -70,6 +71,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_credits_graphics.h"
#include "settings/settings_premium.h"
#include "ui/boxes/boost_box.h"
#include "ui/boxes/confirm_box.h"
#include "ui/chat/chat_style.h"
#include "ui/chat/chat_theme.h"
#include "ui/controls/emoji_button.h"
@@ -2365,6 +2367,27 @@ void AddSoldLeftSlider(
}, slider->lifetime());
}
void CheckMaybeGiftLocked(
not_null<Window::SessionController*> window,
uint64 giftId,
Fn<void()> send) {
const auto session = &window->session();
session->api().request(MTPpayments_CheckCanSendGift(
MTP_long(giftId)
)).done(crl::guard(window, [=](
const MTPpayments_CheckCanSendGiftResult &result) {
result.match([&](const MTPDpayments_checkCanSendGiftResultOk &) {
send();
}, [&](const MTPDpayments_checkCanSendGiftResultFail &data) {
window->show(Ui::MakeInformBox({
.text = Api::ParseTextWithEntities(session, data.vreason()),
.title = tr::lng_gift_locked_title(),
}));
});
})).fail(crl::guard(window, [=] {
})).send();
}
void SendGiftBox(
not_null<GenericBox*> box,
not_null<Window::SessionController*> window,
@@ -2828,21 +2851,41 @@ void SendGiftBox(
raw,
&state->delegate);
}
const auto raw = button.get();
if (validated[index]) {
return;
}
button->show();
raw->show();
validated[index] = true;
const auto &descriptor = state->list[state->order[index]];
button->setDescriptor(descriptor, GiftButton::Mode::Full);
button->setClickedCallback([=] {
raw->setDescriptor(descriptor, GiftButton::Mode::Full);
raw->setClickedCallback([=] {
const auto star = std::get_if<GiftTypeStars>(&descriptor);
const auto send = crl::guard(raw, [=] {
window->show(Box(
SendGiftBox,
window,
peer,
state->api,
descriptor));
});
const auto unique = star ? star->info.unique : nullptr;
if (star
&& star->info.requirePremium
&& !peer->session().premium()) {
const auto premiumNeeded = star && star->info.requirePremium;
if (premiumNeeded && !peer->session().premium()) {
Settings::ShowPremiumGiftPremium(window, star->info);
return;
} else if (star
&& star->info.lockedUntilDate
&& star->info.lockedUntilDate > base::unixtime::now()) {
const auto ready = crl::guard(raw, [=] {
if (premiumNeeded && !peer->session().premium()) {
Settings::ShowPremiumGiftPremium(
window,
v::get<GiftTypeStars>(descriptor).info);
} else {
send();
}
});
CheckMaybeGiftLocked(window, star->info.id, ready);
} else if (unique && star->mine && !peer->isSelf()) {
if (ShowTransferGiftLater(window->uiShow(), unique)) {
return;
@@ -2886,7 +2929,7 @@ void SendGiftBox(
Api::InputSavedStarGiftId(savedId, unique),
peer->input),
formReady);
} else if (star && star->info.unique && star->resale) {
} else if (unique && star->resale) {
window->show(Box(
Settings::GlobalStarGiftBox,
window->uiShow(),
@@ -2911,15 +2954,10 @@ void SendGiftBox(
} else if (star && IsSoldOut(star->info)) {
window->show(Box(SoldOutBox, window, *star));
} else {
window->show(Box(
SendGiftBox,
window,
peer,
state->api,
descriptor));
send();
}
});
button->setGeometry(QRect(QPoint(x, y), single), extend);
raw->setGeometry(QRect(QPoint(x, y), single), extend);
};
y += rowFrom * singleh;
for (auto row = rowFrom; row != rowTill; ++row) {
@@ -104,6 +104,7 @@ struct StarGift {
int perUserRemains = 0;
TimeId firstSaleDate = 0;
TimeId lastSaleDate = 0;
TimeId lockedUntilDate = 0;
bool resellTonOnly : 1 = false;
bool requirePremium : 1 = false;
bool upgradable : 1 = false;
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "info/peer_gifts/info_peer_gifts_common.h"
#include "base/unixtime.h"
#include "boxes/send_credits_box.h" // SetButtonMarkedLabel
#include "boxes/star_gift_box.h"
#include "boxes/sticker_set_box.h"
@@ -73,7 +74,8 @@ GiftButton::GiftButton(
QWidget *parent,
not_null<GiftButtonDelegate*> delegate)
: AbstractButton(parent)
, _delegate(delegate) {
, _delegate(delegate)
, _lockedTimer([=] { refreshLocked(); }) {
}
GiftButton::~GiftButton() {
@@ -166,6 +168,7 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
{ 0., anim::with_alpha(st::windowActiveTextFg->c, .3) },
{ 1., st::windowActiveTextFg->c },
});
_lockedUntilDate = 0;
}, [&](const GiftTypeStars &data) {
const auto soldOut = data.info.limitedCount
&& !data.userpic
@@ -219,8 +222,11 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
_stars->setColorOverride(
Ui::Premium::CreditsIconGradientStops());
}
_lockedUntilDate = data.info.lockedUntilDate;
});
refreshLocked();
_resolvedDocument = nullptr;
_documentLifetime = _delegate->sticker(
descriptor
@@ -263,6 +269,22 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
}
}
void GiftButton::refreshLocked() {
_lockedTimer.cancel();
const auto lockedFor = _lockedUntilDate
? std::max(_lockedUntilDate - base::unixtime::now(), TimeId())
: TimeId();
const auto locked = (lockedFor > 0);
if (locked) {
_lockedTimer.callOnce(std::min(lockedFor, 86'400) * crl::time(1000));
}
if (_locked != locked) {
_locked = locked;
update();
}
}
void GiftButton::setDocument(not_null<DocumentData*> document) {
_resolvedDocument = document;
if (_playerDocument == document) {
@@ -510,6 +532,12 @@ void GiftButton::paintEvent(QPaintEvent *e) {
const auto radius = st::giftBoxGiftRadius;
p.drawRoundedRect(outer.marginsRemoved(extend), radius, radius);
}
if (_locked) {
st::giftBoxLockIcon.paint(
p,
position + st::giftBoxLockIconPosition,
width);
}
if (_userpic) {
if (!_subscribed) {
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/qt/qt_compare.h"
#include "base/timer.h"
#include "data/data_star_gift.h"
#include "ui/abstract_button.h"
#include "ui/effects/premium_stars_colored.h"
@@ -176,6 +177,7 @@ private:
int width,
int height);
void refreshLocked();
void setDocument(not_null<DocumentData*> document);
[[nodiscard]] QMargins currentExtend() const;
[[nodiscard]] bool small() const;
@@ -203,6 +205,10 @@ private:
bool _subscribed = false;
bool _patterned = false;
bool _selected = false;
bool _locked = false;
base::Timer _lockedTimer;
TimeId _lockedUntilDate = 0;
QRect _button;
QMargins _extend;
@@ -246,6 +246,8 @@ giftBoxLock: IconEmoji {
padding: margins(-2px, 1px, 0px, 0px);
}
giftBoxPinIcon: icon {{ "dialogs/dialogs_pinned", premiumButtonFg }};
giftBoxLockIcon: icon{{ "limits/mini_gift_lock-18x18", attentionButtonFg }};
giftBoxLockIconPosition: point(4px, 4px);
creditsHistoryEntriesList: PeerList(defaultPeerList) {
padding: margins(0px, 7px, 0px, 7px);