mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Implement unique gift transfer.
This commit is contained in:
parent
7491337bfd
commit
083400d1c2
19 changed files with 622 additions and 65 deletions
|
@ -332,6 +332,8 @@ PRIVATE
|
||||||
boxes/sticker_set_box.h
|
boxes/sticker_set_box.h
|
||||||
boxes/stickers_box.cpp
|
boxes/stickers_box.cpp
|
||||||
boxes/stickers_box.h
|
boxes/stickers_box.h
|
||||||
|
boxes/transfer_gift_box.cpp
|
||||||
|
boxes/transfer_gift_box.h
|
||||||
boxes/translate_box.cpp
|
boxes/translate_box.cpp
|
||||||
boxes/translate_box.h
|
boxes/translate_box.h
|
||||||
boxes/url_auth_box.cpp
|
boxes/url_auth_box.cpp
|
||||||
|
|
|
@ -2025,6 +2025,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_action_gift_unique_sent" = "You sent a unique collectible item";
|
"lng_action_gift_unique_sent" = "You sent a unique collectible item";
|
||||||
"lng_action_gift_upgraded" = "{user} turned the gift from you to a unique collectible";
|
"lng_action_gift_upgraded" = "{user} turned the gift from you to a unique collectible";
|
||||||
"lng_action_gift_upgraded_mine" = "You turned the gift from {user} to a unique collectible";
|
"lng_action_gift_upgraded_mine" = "You turned the gift from {user} to a unique collectible";
|
||||||
|
"lng_action_gift_transferred" = "{user} transferred you a gift";
|
||||||
|
"lng_action_gift_transferred_mine" = "You transferred a gift to {user}";
|
||||||
"lng_action_gift_received_anonymous" = "Unknown user sent you a gift for {cost}";
|
"lng_action_gift_received_anonymous" = "Unknown user sent you a gift for {cost}";
|
||||||
"lng_action_gift_for_stars#one" = "{count} Star";
|
"lng_action_gift_for_stars#one" = "{count} Star";
|
||||||
"lng_action_gift_for_stars#other" = "{count} Stars";
|
"lng_action_gift_for_stars#other" = "{count} Stars";
|
||||||
|
@ -3239,6 +3241,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_gift_sent_about#other" = "You spent **{count}** Stars from your balance.";
|
"lng_gift_sent_about#other" = "You spent **{count}** Stars from your balance.";
|
||||||
"lng_gift_limited_of_one" = "unique";
|
"lng_gift_limited_of_one" = "unique";
|
||||||
"lng_gift_limited_of_count" = "1 of {amount}";
|
"lng_gift_limited_of_count" = "1 of {amount}";
|
||||||
|
"lng_gift_collectible_tag" = "gift";
|
||||||
"lng_gift_price_unique" = "Unique";
|
"lng_gift_price_unique" = "Unique";
|
||||||
"lng_gift_view_unpack" = "Unpack";
|
"lng_gift_view_unpack" = "Unpack";
|
||||||
"lng_gift_anonymous_hint" = "Only you can see the sender's name.";
|
"lng_gift_anonymous_hint" = "Only you can see the sender's name.";
|
||||||
|
|
|
@ -806,8 +806,8 @@ std::optional<Data::StarGift> FromTL(
|
||||||
.id = uint64(data.vid().v),
|
.id = uint64(data.vid().v),
|
||||||
.unique = std::make_shared<Data::UniqueGift>(Data::UniqueGift{
|
.unique = std::make_shared<Data::UniqueGift>(Data::UniqueGift{
|
||||||
.title = qs(data.vtitle()),
|
.title = qs(data.vtitle()),
|
||||||
.number = data.vnum().v,
|
|
||||||
.ownerId = peerFromUser(UserId(data.vowner_id().v)),
|
.ownerId = peerFromUser(UserId(data.vowner_id().v)),
|
||||||
|
.number = data.vnum().v,
|
||||||
.model = *model,
|
.model = *model,
|
||||||
.pattern = *pattern,
|
.pattern = *pattern,
|
||||||
}),
|
}),
|
||||||
|
@ -837,6 +837,9 @@ std::optional<Data::UserStarGift> FromTL(
|
||||||
auto parsed = FromTL(session, data.vgift());
|
auto parsed = FromTL(session, data.vgift());
|
||||||
if (!parsed) {
|
if (!parsed) {
|
||||||
return {};
|
return {};
|
||||||
|
} else if (const auto unique = parsed->unique.get()) {
|
||||||
|
unique->starsForTransfer = data.vtransfer_stars().value_or(-1);
|
||||||
|
unique->exportAt = data.vcan_export_at().value_or_empty();
|
||||||
}
|
}
|
||||||
return Data::UserStarGift{
|
return Data::UserStarGift{
|
||||||
.info = std::move(*parsed),
|
.info = std::move(*parsed),
|
||||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/peers/replace_boost_box.h" // BoostsForGift.
|
#include "boxes/peers/replace_boost_box.h" // BoostsForGift.
|
||||||
#include "boxes/premium_preview_box.h" // ShowPremiumPreviewBox.
|
#include "boxes/premium_preview_box.h" // ShowPremiumPreviewBox.
|
||||||
#include "boxes/star_gift_box.h" // ShowStarGiftBox.
|
#include "boxes/star_gift_box.h" // ShowStarGiftBox.
|
||||||
|
#include "boxes/transfer_gift_box.h" // ShowTransferGiftBox.
|
||||||
#include "data/data_boosts.h"
|
#include "data/data_boosts.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
|
@ -1204,8 +1205,16 @@ void AddStarGiftTable(
|
||||||
const auto unique = entry.uniqueGift.get();
|
const auto unique = entry.uniqueGift.get();
|
||||||
if (unique) {
|
if (unique) {
|
||||||
const auto ownerId = PeerId(entry.bareGiftOwnerId);
|
const auto ownerId = PeerId(entry.bareGiftOwnerId);
|
||||||
auto send = entry.in ? tr::lng_gift_unique_owner_change() : nullptr;
|
const auto transfer = entry.in
|
||||||
auto handler = entry.in ? Fn<void()>([=] {}) : nullptr;
|
&& entry.bareMsgId
|
||||||
|
&& (unique->starsForTransfer >= 0);
|
||||||
|
auto send = transfer ? tr::lng_gift_unique_owner_change() : nullptr;
|
||||||
|
auto handler = transfer ? Fn<void()>([=] {
|
||||||
|
ShowTransferGiftBox(
|
||||||
|
controller->parentController(),
|
||||||
|
entry.uniqueGift,
|
||||||
|
MsgId(entry.bareMsgId));
|
||||||
|
}) : nullptr;
|
||||||
AddTableRow(
|
AddTableRow(
|
||||||
table,
|
table,
|
||||||
tr::lng_gift_unique_owner(),
|
tr::lng_gift_unique_owner(),
|
||||||
|
|
|
@ -1129,11 +1129,10 @@ void ShowGiftUpgradedToast(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendUpgradeRequest(
|
void SendStarsFormRequest(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
Settings::SmallBalanceResult result,
|
Settings::SmallBalanceResult result,
|
||||||
uint64 formId,
|
uint64 formId,
|
||||||
int stars,
|
|
||||||
MTPInputInvoice invoice,
|
MTPInputInvoice invoice,
|
||||||
Fn<void(Payments::CheckoutResult)> done) {
|
Fn<void(Payments::CheckoutResult)> done) {
|
||||||
using BalanceResult = Settings::SmallBalanceResult;
|
using BalanceResult = Settings::SmallBalanceResult;
|
||||||
|
@ -1190,46 +1189,12 @@ void UpgradeGift(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using Flag = MTPDinputInvoiceStarGiftUpgrade::Flag;
|
using Flag = MTPDinputInvoiceStarGiftUpgrade::Flag;
|
||||||
const auto weak = base::make_weak(window);
|
RequestStarsFormAndSubmit(
|
||||||
const auto invoice = MTP_inputInvoiceStarGiftUpgrade(
|
window,
|
||||||
MTP_flags(keepDetails ? Flag::f_keep_original_details : Flag()),
|
MTP_inputInvoiceStarGiftUpgrade(
|
||||||
MTP_int(messageId.bare));
|
MTP_flags(keepDetails ? Flag::f_keep_original_details : Flag()),
|
||||||
session->api().request(MTPpayments_GetPaymentForm(
|
MTP_int(messageId.bare)),
|
||||||
MTP_flags(0),
|
std::move(done));
|
||||||
invoice,
|
|
||||||
MTPDataJSON() // theme_params
|
|
||||||
)).done([=](const MTPpayments_PaymentForm &result) {
|
|
||||||
result.match([&](const MTPDpayments_paymentFormStarGift &data) {
|
|
||||||
const auto formId = data.vform_id().v;
|
|
||||||
const auto prices = data.vinvoice().data().vprices().v;
|
|
||||||
const auto strong = weak.get();
|
|
||||||
if (!strong) {
|
|
||||||
done(Payments::CheckoutResult::Failed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto ready = [=](Settings::SmallBalanceResult result) {
|
|
||||||
SendUpgradeRequest(
|
|
||||||
strong,
|
|
||||||
result,
|
|
||||||
formId,
|
|
||||||
stars,
|
|
||||||
invoice,
|
|
||||||
done);
|
|
||||||
};
|
|
||||||
Settings::MaybeRequestBalanceIncrease(
|
|
||||||
Main::MakeSessionShow(strong->uiShow(), session),
|
|
||||||
prices.front().data().vamount().v,
|
|
||||||
Settings::SmallBalanceDeepLink{},
|
|
||||||
ready);
|
|
||||||
}, [&](const auto &) {
|
|
||||||
done(Payments::CheckoutResult::Failed);
|
|
||||||
});
|
|
||||||
}).fail([=](const MTP::Error &error) {
|
|
||||||
if (const auto strong = weak.get()) {
|
|
||||||
strong->showToast(error.type());
|
|
||||||
}
|
|
||||||
done(Payments::CheckoutResult::Failed);
|
|
||||||
}).send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoldOutBox(
|
void SoldOutBox(
|
||||||
|
@ -2327,4 +2292,41 @@ void AddUniqueCloseButton(not_null<GenericBox*> box) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RequestStarsFormAndSubmit(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
MTPInputInvoice invoice,
|
||||||
|
Fn<void(Payments::CheckoutResult)> done) {
|
||||||
|
const auto weak = base::make_weak(window);
|
||||||
|
window->session().api().request(MTPpayments_GetPaymentForm(
|
||||||
|
MTP_flags(0),
|
||||||
|
invoice,
|
||||||
|
MTPDataJSON() // theme_params
|
||||||
|
)).done([=](const MTPpayments_PaymentForm &result) {
|
||||||
|
result.match([&](const MTPDpayments_paymentFormStarGift &data) {
|
||||||
|
const auto formId = data.vform_id().v;
|
||||||
|
const auto prices = data.vinvoice().data().vprices().v;
|
||||||
|
const auto strong = weak.get();
|
||||||
|
if (!strong) {
|
||||||
|
done(Payments::CheckoutResult::Failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto ready = [=](Settings::SmallBalanceResult result) {
|
||||||
|
SendStarsFormRequest(strong, result, formId, invoice, done);
|
||||||
|
};
|
||||||
|
Settings::MaybeRequestBalanceIncrease(
|
||||||
|
strong->uiShow(),
|
||||||
|
prices.front().data().vamount().v,
|
||||||
|
Settings::SmallBalanceDeepLink{},
|
||||||
|
ready);
|
||||||
|
}, [&](const auto &) {
|
||||||
|
done(Payments::CheckoutResult::Failed);
|
||||||
|
});
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
if (const auto strong = weak.get()) {
|
||||||
|
strong->showToast(error.type());
|
||||||
|
}
|
||||||
|
done(Payments::CheckoutResult::Failed);
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -13,6 +13,10 @@ struct GiftCode;
|
||||||
struct CreditsHistoryEntry;
|
struct CreditsHistoryEntry;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
namespace Payments {
|
||||||
|
enum class CheckoutResult;
|
||||||
|
} // namespace Payments
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
class SessionController;
|
class SessionController;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
@ -60,4 +64,9 @@ void ShowStarGiftUpgradeBox(StarGiftUpgradeArgs &&args);
|
||||||
|
|
||||||
void AddUniqueCloseButton(not_null<GenericBox*> box);
|
void AddUniqueCloseButton(not_null<GenericBox*> box);
|
||||||
|
|
||||||
|
void RequestStarsFormAndSubmit(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
MTPInputInvoice invoice,
|
||||||
|
Fn<void(Payments::CheckoutResult)> done);
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
407
Telegram/SourceFiles/boxes/transfer_gift_box.cpp
Normal file
407
Telegram/SourceFiles/boxes/transfer_gift_box.cpp
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "boxes/transfer_gift_box.h"
|
||||||
|
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
|
#include "data/data_star_gift.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "boxes/filters/edit_filter_chats_list.h" // CreatePe...tionSubtitle.
|
||||||
|
#include "boxes/peer_list_box.h"
|
||||||
|
#include "boxes/peer_list_controllers.h"
|
||||||
|
#include "boxes/star_gift_box.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "payments/payments_checkout_process.h"
|
||||||
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "ui/layers/generic_box.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
|
#include "ui/empty_userpic.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
|
#include "ui/vertical_list.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
#include "styles/style_boxes.h" // peerListSingleRow.
|
||||||
|
#include "styles/style_dialogs.h" // recentPeersSpecialName.
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct ExportOption {
|
||||||
|
object_ptr<Ui::RpWidget> content = { nullptr };
|
||||||
|
Fn<bool(int, int, int)> overrideKey;
|
||||||
|
Fn<void()> activate;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Controller final : public ContactsBoxController {
|
||||||
|
public:
|
||||||
|
Controller(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
Fn<void(not_null<PeerData*>)> choose);
|
||||||
|
|
||||||
|
void noSearchSubmit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void prepareViewHook() override;
|
||||||
|
void setupExportOption();
|
||||||
|
|
||||||
|
bool overrideKeyboardNavigation(
|
||||||
|
int direction,
|
||||||
|
int fromIndex,
|
||||||
|
int toIndex) override;
|
||||||
|
|
||||||
|
std::unique_ptr<PeerListRow> createRow(
|
||||||
|
not_null<UserData*> user) override;
|
||||||
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
|
||||||
|
const std::shared_ptr<Data::UniqueGift> _gift;
|
||||||
|
const Fn<void(not_null<PeerData*>)> _choose;
|
||||||
|
ExportOption _exportOption;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] ExportOption MakeExportOption(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
TimeId when) {
|
||||||
|
const auto activate = [=] {
|
||||||
|
const auto now = base::unixtime::now();
|
||||||
|
const auto left = (when > now) ? (when - now) : 0;
|
||||||
|
const auto hours = left ? std::max((left + 1800) / 3600, 1) : 0;
|
||||||
|
window->show(Ui::MakeInformBox({
|
||||||
|
.text = (!hours
|
||||||
|
? tr::lng_gift_transfer_unlocks_update_about()
|
||||||
|
: tr::lng_gift_transfer_unlocks_about(
|
||||||
|
lt_when,
|
||||||
|
((hours >= 24)
|
||||||
|
? tr::lng_gift_transfer_unlocks_when_days(
|
||||||
|
lt_count,
|
||||||
|
rpl::single((hours / 24) * 1.))
|
||||||
|
: tr::lng_gift_transfer_unlocks_when_hours(
|
||||||
|
lt_count,
|
||||||
|
rpl::single(hours * 1.))))),
|
||||||
|
.title = (!hours
|
||||||
|
? tr::lng_gift_transfer_unlocks_update_title()
|
||||||
|
: tr::lng_gift_transfer_unlocks_title()),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExportRow final : public PeerListRow {
|
||||||
|
public:
|
||||||
|
explicit ExportRow(TimeId when)
|
||||||
|
: PeerListRow(Data::FakePeerIdForJustName("ton-export").value) {
|
||||||
|
const auto now = base::unixtime::now();
|
||||||
|
_available = (when <= now);
|
||||||
|
if (const auto left = when - now; left > 0) {
|
||||||
|
const auto hours = std::max((left + 1800) / 3600, 1);
|
||||||
|
const auto days = hours / 24;
|
||||||
|
setCustomStatus(days
|
||||||
|
? tr::lng_gift_transfer_unlocks_days(
|
||||||
|
tr::now,
|
||||||
|
lt_count,
|
||||||
|
days)
|
||||||
|
: tr::lng_gift_transfer_unlocks_hours(
|
||||||
|
tr::now,
|
||||||
|
lt_count,
|
||||||
|
hours));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString generateName() override {
|
||||||
|
return tr::lng_gift_transfer_via_blockchain(tr::now);
|
||||||
|
}
|
||||||
|
QString generateShortName() override {
|
||||||
|
return generateName();
|
||||||
|
}
|
||||||
|
auto generatePaintUserpicCallback(bool forceRound)
|
||||||
|
-> PaintRoundImageCallback override {
|
||||||
|
return [=](
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
int size) mutable {
|
||||||
|
Ui::EmptyUserpic::PaintCurrency(p, x, y, outerWidth, size);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const style::PeerListItem &computeSt(
|
||||||
|
const style::PeerListItem &st) const {
|
||||||
|
return _available ? st::recentPeersSpecialName : st;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _available = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExportController final : public PeerListController {
|
||||||
|
public:
|
||||||
|
ExportController(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
TimeId when,
|
||||||
|
Fn<void()> activate)
|
||||||
|
: _session(session)
|
||||||
|
, _when(when)
|
||||||
|
, _activate(std::move(activate)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare() override {
|
||||||
|
delegate()->peerListAppendRow(
|
||||||
|
std::make_unique<ExportRow>(_when));
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
|
}
|
||||||
|
void loadMoreRows() override {
|
||||||
|
}
|
||||||
|
void rowClicked(not_null<PeerListRow*> row) override {
|
||||||
|
_activate();
|
||||||
|
}
|
||||||
|
Main::Session &session() const override {
|
||||||
|
return *_session;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const not_null<Main::Session*> _session;
|
||||||
|
TimeId _when = 0;
|
||||||
|
Fn<void()> _activate;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
|
||||||
|
const auto container = result.data();
|
||||||
|
|
||||||
|
Ui::AddSkip(container);
|
||||||
|
|
||||||
|
const auto delegate = container->lifetime().make_state<
|
||||||
|
PeerListContentDelegateSimple
|
||||||
|
>();
|
||||||
|
const auto controller = container->lifetime().make_state<
|
||||||
|
ExportController
|
||||||
|
>(&window->session(), when, activate);
|
||||||
|
controller->setStyleOverrides(&st::peerListSingleRow);
|
||||||
|
const auto content = container->add(object_ptr<PeerListContent>(
|
||||||
|
container,
|
||||||
|
controller));
|
||||||
|
delegate->setContent(content);
|
||||||
|
controller->setDelegate(delegate);
|
||||||
|
|
||||||
|
Ui::AddSkip(container);
|
||||||
|
container->add(CreatePeerListSectionSubtitle(
|
||||||
|
container,
|
||||||
|
tr::lng_contacts_header()));
|
||||||
|
|
||||||
|
const auto overrideKey = [=](int direction, int from, int to) {
|
||||||
|
if (!content->isVisible()) {
|
||||||
|
return false;
|
||||||
|
} else if (direction > 0 && from < 0 && to >= 0) {
|
||||||
|
if (content->hasSelection()) {
|
||||||
|
const auto was = content->selectedIndex();
|
||||||
|
const auto now = content->selectSkip(1).reallyMovedTo;
|
||||||
|
if (was != now) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
content->clearSelection();
|
||||||
|
} else {
|
||||||
|
content->selectSkip(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (direction < 0 && to < 0) {
|
||||||
|
if (!content->hasSelection()) {
|
||||||
|
content->selectLast();
|
||||||
|
} else if (from >= 0 || content->hasSelection()) {
|
||||||
|
content->selectSkip(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
.content = std::move(result),
|
||||||
|
.overrideKey = overrideKey,
|
||||||
|
.activate = activate,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller::Controller(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
Fn<void(not_null<PeerData*>)> choose)
|
||||||
|
: ContactsBoxController(&window->session())
|
||||||
|
, _gift(std::move(gift))
|
||||||
|
, _choose(std::move(choose)) {
|
||||||
|
if (const auto when = _gift->exportAt) {
|
||||||
|
_exportOption = MakeExportOption(window, when);
|
||||||
|
}
|
||||||
|
if (_exportOption.content) {
|
||||||
|
setStyleOverrides(&st::peerListSmallSkips);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::noSearchSubmit() {
|
||||||
|
if (const auto onstack = _exportOption.activate) {
|
||||||
|
onstack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::overrideKeyboardNavigation(
|
||||||
|
int direction,
|
||||||
|
int fromIndex,
|
||||||
|
int toIndex) {
|
||||||
|
return _exportOption.overrideKey
|
||||||
|
&& _exportOption.overrideKey(direction, fromIndex, toIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::prepareViewHook() {
|
||||||
|
delegate()->peerListSetTitle(tr::lng_gift_transfer_title(
|
||||||
|
lt_name,
|
||||||
|
rpl::single(UniqueGiftName(*_gift))));
|
||||||
|
setupExportOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::setupExportOption() {
|
||||||
|
delegate()->peerListSetAboveWidget(std::move(_exportOption.content));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<PeerListRow> Controller::createRow(
|
||||||
|
not_null<UserData*> user) {
|
||||||
|
if (user->isSelf()
|
||||||
|
|| user->isBot()
|
||||||
|
|| user->isServiceUser()
|
||||||
|
|| user->isInaccessible()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return ContactsBoxController::createRow(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
_choose(row->peer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferGift(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
not_null<PeerData*> to,
|
||||||
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
MsgId messageId,
|
||||||
|
Fn<void(Payments::CheckoutResult)> done) {
|
||||||
|
Expects(to->isUser());
|
||||||
|
|
||||||
|
const auto session = &window->session();
|
||||||
|
const auto weak = base::make_weak(window);
|
||||||
|
if (gift->starsForTransfer <= 0) {
|
||||||
|
session->api().request(MTPpayments_TransferStarGift(
|
||||||
|
MTP_int(messageId.bare),
|
||||||
|
to->asUser()->inputUser
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
session->api().applyUpdates(result);
|
||||||
|
done(Payments::CheckoutResult::Paid);
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
if (const auto strong = weak.get()) {
|
||||||
|
strong->showToast(error.type());
|
||||||
|
}
|
||||||
|
done(Payments::CheckoutResult::Failed);
|
||||||
|
}).send();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ui::RequestStarsFormAndSubmit(
|
||||||
|
window,
|
||||||
|
MTP_inputInvoiceStarGiftTransfer(
|
||||||
|
MTP_int(messageId.bare),
|
||||||
|
to->asUser()->inputUser),
|
||||||
|
std::move(done));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowTransferToBox(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
MsgId msgId) {
|
||||||
|
const auto stars = gift->starsForTransfer;
|
||||||
|
controller->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||||
|
box->setTitle(tr::lng_gift_transfer_title(
|
||||||
|
lt_name,
|
||||||
|
rpl::single(UniqueGiftName(*gift))));
|
||||||
|
|
||||||
|
auto transfer = (stars > 0)
|
||||||
|
? tr::lng_gift_transfer_button_for(
|
||||||
|
lt_price,
|
||||||
|
tr::lng_action_gift_for_stars(
|
||||||
|
lt_count,
|
||||||
|
rpl::single(stars * 1.)))
|
||||||
|
: tr::lng_gift_transfer_button();
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
bool sent = false;
|
||||||
|
};
|
||||||
|
const auto state = std::make_shared<State>();
|
||||||
|
auto callback = [=] {
|
||||||
|
if (state->sent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state->sent = true;
|
||||||
|
const auto weak = Ui::MakeWeak(box);
|
||||||
|
const auto done = [=](Payments::CheckoutResult result) {
|
||||||
|
if (result != Payments::CheckoutResult::Paid) {
|
||||||
|
state->sent = false;
|
||||||
|
} else {
|
||||||
|
controller->showPeerHistory(peer);
|
||||||
|
if (const auto strong = weak.data()) {
|
||||||
|
strong->closeBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TransferGift(controller, peer, gift, msgId, done);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ui::ConfirmBox(box, {
|
||||||
|
.text = (stars > 0)
|
||||||
|
? tr::lng_gift_transfer_sure_for(
|
||||||
|
lt_name,
|
||||||
|
rpl::single(Ui::Text::Bold(UniqueGiftName(*gift))),
|
||||||
|
lt_recipient,
|
||||||
|
rpl::single(Ui::Text::Bold(peer->shortName())),
|
||||||
|
lt_price,
|
||||||
|
tr::lng_action_gift_for_stars(
|
||||||
|
lt_count,
|
||||||
|
rpl::single(stars * 1.),
|
||||||
|
Ui::Text::Bold),
|
||||||
|
Ui::Text::WithEntities)
|
||||||
|
: tr::lng_gift_transfer_sure(
|
||||||
|
lt_name,
|
||||||
|
rpl::single(Ui::Text::Bold(UniqueGiftName(*gift))),
|
||||||
|
lt_recipient,
|
||||||
|
rpl::single(Ui::Text::Bold(peer->shortName())),
|
||||||
|
Ui::Text::WithEntities),
|
||||||
|
.confirmed = std::move(callback),
|
||||||
|
.confirmText = std::move(transfer),
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void ShowTransferGiftBox(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
MsgId msgId) {
|
||||||
|
auto controller = std::make_unique<Controller>(
|
||||||
|
window,
|
||||||
|
gift,
|
||||||
|
[=](not_null<PeerData*> peer) {
|
||||||
|
ShowTransferToBox(window, peer, gift, msgId);
|
||||||
|
});
|
||||||
|
const auto controllerRaw = controller.get();
|
||||||
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
|
||||||
|
|
||||||
|
box->noSearchSubmits() | rpl::start_with_next([=] {
|
||||||
|
controllerRaw->noSearchSubmit();
|
||||||
|
}, box->lifetime());
|
||||||
|
};
|
||||||
|
window->show(
|
||||||
|
Box<PeerListBox>(std::move(controller), std::move(initBox)),
|
||||||
|
Ui::LayerOption::KeepOther);
|
||||||
|
}
|
21
Telegram/SourceFiles/boxes/transfer_gift_box.h
Normal file
21
Telegram/SourceFiles/boxes/transfer_gift_box.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
class SessionController;
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
struct UniqueGift;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
|
void ShowTransferGiftBox(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
MsgId msgId);
|
|
@ -84,6 +84,7 @@ struct CreditsHistoryEntry final {
|
||||||
bool converted : 1 = false;
|
bool converted : 1 = false;
|
||||||
bool anonymous : 1 = false;
|
bool anonymous : 1 = false;
|
||||||
bool stargift : 1 = false;
|
bool stargift : 1 = false;
|
||||||
|
bool giftTransferred : 1 = false;
|
||||||
bool savedToProfile : 1 = false;
|
bool savedToProfile : 1 = false;
|
||||||
bool fromGiftsList : 1 = false;
|
bool fromGiftsList : 1 = false;
|
||||||
bool soldOutInfo : 1 = false;
|
bool soldOutInfo : 1 = false;
|
||||||
|
|
|
@ -132,7 +132,6 @@ enum class GiftType : uchar {
|
||||||
Premium, // count - months
|
Premium, // count - months
|
||||||
Credits, // count - credits
|
Credits, // count - credits
|
||||||
StarGift, // count - stars
|
StarGift, // count - stars
|
||||||
StarGiftUpgrade,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GiftCode {
|
struct GiftCode {
|
||||||
|
@ -151,11 +150,14 @@ struct GiftCode {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
GiftType type = GiftType::Premium;
|
GiftType type = GiftType::Premium;
|
||||||
bool viaGiveaway : 1 = false;
|
bool viaGiveaway : 1 = false;
|
||||||
|
bool transferred : 1 = false;
|
||||||
bool upgradable : 1 = false;
|
bool upgradable : 1 = false;
|
||||||
bool unclaimed : 1 = false;
|
bool unclaimed : 1 = false;
|
||||||
bool anonymous : 1 = false;
|
bool anonymous : 1 = false;
|
||||||
bool converted : 1 = false;
|
bool converted : 1 = false;
|
||||||
bool upgraded : 1 = false;
|
bool upgraded : 1 = false;
|
||||||
|
bool refunded : 1 = false;
|
||||||
|
bool upgrade : 1 = false;
|
||||||
bool saved : 1 = false;
|
bool saved : 1 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,10 @@ struct UniqueGiftOriginalDetails {
|
||||||
|
|
||||||
struct UniqueGift {
|
struct UniqueGift {
|
||||||
QString title;
|
QString title;
|
||||||
int number = 0;
|
|
||||||
PeerId ownerId = 0;
|
PeerId ownerId = 0;
|
||||||
|
int number = 0;
|
||||||
|
int starsForTransfer = -1;
|
||||||
|
TimeId exportAt = 0;
|
||||||
UniqueGiftModel model;
|
UniqueGiftModel model;
|
||||||
UniqueGiftPattern pattern;
|
UniqueGiftPattern pattern;
|
||||||
UniqueGiftBackdrop backdrop;
|
UniqueGiftBackdrop backdrop;
|
||||||
|
|
|
@ -5463,13 +5463,17 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
||||||
const auto isSelf = _from->isSelf();
|
const auto isSelf = _from->isSelf();
|
||||||
const auto peer = isSelf ? _history->peer : _from;
|
const auto peer = isSelf ? _history->peer : _from;
|
||||||
result.links.push_back(peer->createOpenLink());
|
result.links.push_back(peer->createOpenLink());
|
||||||
result.text = (isSelf
|
result.text = (action.is_upgrade()
|
||||||
? tr::lng_action_gift_upgraded_mine
|
? (isSelf
|
||||||
: tr::lng_action_gift_upgraded)(
|
? tr::lng_action_gift_upgraded_mine
|
||||||
tr::now,
|
: tr::lng_action_gift_upgraded)
|
||||||
lt_user,
|
: (isSelf
|
||||||
Ui::Text::Link(peer->shortName(), 1), // Link 1.
|
? tr::lng_action_gift_transferred_mine
|
||||||
Ui::Text::WithEntities);
|
: tr::lng_action_gift_transferred))(
|
||||||
|
tr::now,
|
||||||
|
lt_user,
|
||||||
|
Ui::Text::Link(peer->shortName(), 1), // Link 1.
|
||||||
|
Ui::Text::WithEntities);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5683,7 +5687,10 @@ void HistoryItem::applyAction(const MTPMessageAction &action) {
|
||||||
}, [&](const MTPDmessageActionStarGiftUnique &data) {
|
}, [&](const MTPDmessageActionStarGiftUnique &data) {
|
||||||
using Fields = Data::GiftCode;
|
using Fields = Data::GiftCode;
|
||||||
auto fields = Fields{
|
auto fields = Fields{
|
||||||
.type = Data::GiftType::StarGiftUpgrade,
|
.type = Data::GiftType::StarGift,
|
||||||
|
.transferred = data.is_transferred(),
|
||||||
|
.refunded = data.is_refunded(),
|
||||||
|
.upgrade = data.is_upgrade(),
|
||||||
.saved = data.is_saved(),
|
.saved = data.is_saved(),
|
||||||
};
|
};
|
||||||
if (auto gift = Api::FromTL(&history()->session(), data.vgift())) {
|
if (auto gift = Api::FromTL(&history()->session(), data.vgift())) {
|
||||||
|
@ -5692,7 +5699,12 @@ void HistoryItem::applyAction(const MTPMessageAction &action) {
|
||||||
fields.limitedCount = gift->limitedCount;
|
fields.limitedCount = gift->limitedCount;
|
||||||
fields.limitedLeft = gift->limitedLeft;
|
fields.limitedLeft = gift->limitedLeft;
|
||||||
fields.count = gift->stars;
|
fields.count = gift->stars;
|
||||||
fields.unique = gift->unique;
|
fields.unique = std::move(gift->unique);
|
||||||
|
if (const auto unique = fields.unique.get()) {
|
||||||
|
unique->starsForTransfer
|
||||||
|
= data.vtransfer_stars().value_or(-1);
|
||||||
|
unique->exportAt = data.vcan_export_at().value_or_empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_media = std::make_unique<Data::MediaGiftBox>(
|
_media = std::make_unique<Data::MediaGiftBox>(
|
||||||
this,
|
this,
|
||||||
|
|
|
@ -235,7 +235,7 @@ void PremiumGift::draw(
|
||||||
|
|
||||||
QString PremiumGift::cornerTagText() {
|
QString PremiumGift::cornerTagText() {
|
||||||
if (_data.unique) {
|
if (_data.unique) {
|
||||||
return tr::lng_gift_limited_of_one(tr::now);
|
return tr::lng_gift_collectible_tag(tr::now);
|
||||||
} else if (const auto count = _data.limitedCount) {
|
} else if (const auto count = _data.limitedCount) {
|
||||||
return (count == 1)
|
return (count == 1)
|
||||||
? tr::lng_gift_limited_of_one(tr::now)
|
? tr::lng_gift_limited_of_one(tr::now)
|
||||||
|
@ -292,12 +292,11 @@ bool PremiumGift::gift() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PremiumGift::starGift() const {
|
bool PremiumGift::starGift() const {
|
||||||
return (_data.type == Data::GiftType::StarGift)
|
return (_data.type == Data::GiftType::StarGift);
|
||||||
|| (_data.type == Data::GiftType::StarGiftUpgrade);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PremiumGift::starGiftUpgrade() const {
|
bool PremiumGift::starGiftUpgrade() const {
|
||||||
return (_data.type == Data::GiftType::StarGiftUpgrade);
|
return (_data.type == Data::GiftType::StarGift) && _data.upgrade;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PremiumGift::creditsPrize() const {
|
bool PremiumGift::creditsPrize() const {
|
||||||
|
|
|
@ -400,6 +400,12 @@ auto GenerateUniqueGiftMedia(
|
||||||
st));
|
st));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const auto item = parent->data();
|
||||||
|
const auto media = item->media();
|
||||||
|
const auto fields = media ? media->gift() : nullptr;
|
||||||
|
const auto upgrade = fields && fields->upgrade;
|
||||||
|
const auto outgoing = upgrade ? !item->out() : item->out();
|
||||||
|
|
||||||
const auto white = QColor(255, 255, 255);
|
const auto white = QColor(255, 255, 255);
|
||||||
const auto sticker = [=] {
|
const auto sticker = [=] {
|
||||||
using Tag = ChatHelpers::StickerLottieSize;
|
using Tag = ChatHelpers::StickerLottieSize;
|
||||||
|
@ -415,7 +421,7 @@ auto GenerateUniqueGiftMedia(
|
||||||
sticker,
|
sticker,
|
||||||
st::chatUniqueStickerPadding));
|
st::chatUniqueStickerPadding));
|
||||||
pushText(
|
pushText(
|
||||||
Ui::Text::Bold((!parent->data()->out()
|
Ui::Text::Bold((outgoing
|
||||||
? tr::lng_action_gift_sent_subtitle
|
? tr::lng_action_gift_sent_subtitle
|
||||||
: tr::lng_action_gift_got_subtitle)(
|
: tr::lng_action_gift_got_subtitle)(
|
||||||
tr::now,
|
tr::now,
|
||||||
|
@ -430,7 +436,7 @@ auto GenerateUniqueGiftMedia(
|
||||||
gift->backdrop.textColor,
|
gift->backdrop.textColor,
|
||||||
st::chatUniqueTextPadding);
|
st::chatUniqueTextPadding);
|
||||||
|
|
||||||
const auto withButton = parent->data()->out();
|
const auto withButton = !outgoing;
|
||||||
|
|
||||||
auto attributes = std::vector<AttributeTable::Entry>{
|
auto attributes = std::vector<AttributeTable::Entry>{
|
||||||
{ tr::lng_gift_unique_model(tr::now), gift->model.name },
|
{ tr::lng_gift_unique_model(tr::now), gift->model.name },
|
||||||
|
|
|
@ -63,6 +63,10 @@ QImage IconCurrencyColored(
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray CurrencySvgColored(const QColor &c) {
|
||||||
|
return CurrencySvg(c);
|
||||||
|
}
|
||||||
|
|
||||||
QImage MenuIconCurrency(const QSize &size) {
|
QImage MenuIconCurrency(const QSize &size) {
|
||||||
auto image = QImage(
|
auto image = QImage(
|
||||||
size * style::DevicePixelRatio(),
|
size * style::DevicePixelRatio(),
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Ui::Earn {
|
||||||
[[nodiscard]] QImage IconCurrencyColored(
|
[[nodiscard]] QImage IconCurrencyColored(
|
||||||
const style::font &font,
|
const style::font &font,
|
||||||
const QColor &c);
|
const QColor &c);
|
||||||
|
[[nodiscard]] QByteArray CurrencySvgColored(const QColor &c);
|
||||||
|
|
||||||
[[nodiscard]] QImage MenuIconCurrency(const QSize &size);
|
[[nodiscard]] QImage MenuIconCurrency(const QSize &size);
|
||||||
[[nodiscard]] QImage MenuIconCredits();
|
[[nodiscard]] QImage MenuIconCredits();
|
||||||
|
|
|
@ -1318,7 +1318,7 @@ void ReceiptCreditsBox(
|
||||||
.cost = e.starsUpgradedBySender ? 0 : e.starsToUpgrade,
|
.cost = e.starsUpgradedBySender ? 0 : e.starsToUpgrade,
|
||||||
.canAddSender = !e.anonymous,
|
.canAddSender = !e.anonymous,
|
||||||
.canAddComment = !e.anonymous && e.hasGiftComment,
|
.canAddComment = !e.anonymous && e.hasGiftComment,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto canUpgrade = e.stargiftId
|
const auto canUpgrade = e.stargiftId
|
||||||
|
@ -1369,7 +1369,8 @@ void ReceiptCreditsBox(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const auto canToggle = canConvert || couldConvert || nonConvertible;
|
const auto canToggle = (canConvert || couldConvert || nonConvertible)
|
||||||
|
&& !e.giftTransferred;
|
||||||
|
|
||||||
AddStarGiftTable(
|
AddStarGiftTable(
|
||||||
controller,
|
controller,
|
||||||
|
@ -1665,7 +1666,9 @@ void StarGiftViewBox(
|
||||||
.bareMsgId = uint64(item->id.bare),
|
.bareMsgId = uint64(item->id.bare),
|
||||||
.barePeerId = item->history()->peer->id.value,
|
.barePeerId = item->history()->peer->id.value,
|
||||||
.bareGiftStickerId = data.document ? data.document->id : 0,
|
.bareGiftStickerId = data.document ? data.document->id : 0,
|
||||||
.bareGiftOwnerId = item->history()->session().userPeerId().value,
|
.bareGiftOwnerId = (data.unique
|
||||||
|
? data.unique->ownerId.value
|
||||||
|
: item->history()->session().userPeerId().value),
|
||||||
.stargiftId = data.stargiftId,
|
.stargiftId = data.stargiftId,
|
||||||
.uniqueGift = data.unique,
|
.uniqueGift = data.unique,
|
||||||
.peerType = Data::CreditsHistoryEntry::PeerType::Peer,
|
.peerType = Data::CreditsHistoryEntry::PeerType::Peer,
|
||||||
|
@ -1677,6 +1680,7 @@ void StarGiftViewBox(
|
||||||
.converted = data.converted,
|
.converted = data.converted,
|
||||||
.anonymous = data.anonymous,
|
.anonymous = data.anonymous,
|
||||||
.stargift = true,
|
.stargift = true,
|
||||||
|
.giftTransferred = data.transferred,
|
||||||
.savedToProfile = data.saved,
|
.savedToProfile = data.saved,
|
||||||
.canUpgradeGift = data.upgradable,
|
.canUpgradeGift = data.upgradable,
|
||||||
.hasGiftComment = !data.message.empty(),
|
.hasGiftComment = !data.message.empty(),
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "ui/empty_userpic.h"
|
#include "ui/empty_userpic.h"
|
||||||
|
|
||||||
|
#include "info/channel_statistics/earn/earn_icons.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
#include "ui/effects/animation_value.h"
|
#include "ui/effects/animation_value.h"
|
||||||
#include "ui/emoji_config.h"
|
#include "ui/emoji_config.h"
|
||||||
|
@ -17,6 +18,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_widgets.h" // style::IconButton
|
#include "styles/style_widgets.h" // style::IconButton
|
||||||
#include "styles/style_info.h" // st::topBarCall
|
#include "styles/style_info.h" // st::topBarCall
|
||||||
|
|
||||||
|
#include <QtSvg/QSvgRenderer>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -183,6 +186,18 @@ void PaintMyNotesInner(
|
||||||
fg);
|
fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PaintCurrencyInner(
|
||||||
|
QPainter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int size,
|
||||||
|
const style::color &fg) {
|
||||||
|
auto svg = QSvgRenderer(Ui::Earn::CurrencySvgColored(fg->c));
|
||||||
|
const auto skip = size / 5;
|
||||||
|
svg.render(&p, QRect(x, y, size, size).marginsRemoved(
|
||||||
|
{ skip, skip, skip, skip }));
|
||||||
|
}
|
||||||
|
|
||||||
void PaintExternalMessagesInner(
|
void PaintExternalMessagesInner(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
|
@ -507,6 +522,45 @@ QImage EmptyUserpic::GenerateMyNotes(int size) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmptyUserpic::PaintCurrency(
|
||||||
|
QPainter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
int size) {
|
||||||
|
auto bg = QLinearGradient(x, y, x, y + size);
|
||||||
|
bg.setStops({
|
||||||
|
{ 0., st::historyPeerSavedMessagesBg->c },
|
||||||
|
{ 1., st::historyPeerSavedMessagesBg2->c }
|
||||||
|
});
|
||||||
|
const auto &fg = st::historyPeerUserpicFg;
|
||||||
|
PaintCurrency(p, x, y, outerWidth, size, QBrush(bg), fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmptyUserpic::PaintCurrency(
|
||||||
|
QPainter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
int size,
|
||||||
|
QBrush bg,
|
||||||
|
const style::color &fg) {
|
||||||
|
x = style::RightToLeft() ? (outerWidth - x - size) : x;
|
||||||
|
|
||||||
|
PainterHighQualityEnabler hq(p);
|
||||||
|
p.setBrush(bg);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.drawEllipse(x, y, size, size);
|
||||||
|
|
||||||
|
PaintCurrencyInner(p, x, y, size, fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage EmptyUserpic::GenerateCurrency(int size) {
|
||||||
|
return Generate(size, [&](QPainter &p) {
|
||||||
|
PaintCurrency(p, 0, 0, size, size);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<uint64, uint64> EmptyUserpic::uniqueKey() const {
|
std::pair<uint64, uint64> EmptyUserpic::uniqueKey() const {
|
||||||
const auto first = (uint64(0xFFFFFFFFU) << 32)
|
const auto first = (uint64(0xFFFFFFFFU) << 32)
|
||||||
| anim::getPremultiplied(_colors.color1->c);
|
| anim::getPremultiplied(_colors.color1->c);
|
||||||
|
|
|
@ -113,6 +113,22 @@ public:
|
||||||
const style::color &fg);
|
const style::color &fg);
|
||||||
[[nodiscard]] static QImage GenerateMyNotes(int size);
|
[[nodiscard]] static QImage GenerateMyNotes(int size);
|
||||||
|
|
||||||
|
static void PaintCurrency(
|
||||||
|
QPainter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
int size);
|
||||||
|
static void PaintCurrency(
|
||||||
|
QPainter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
int size,
|
||||||
|
QBrush bg,
|
||||||
|
const style::color &fg);
|
||||||
|
[[nodiscard]] static QImage GenerateCurrency(int size);
|
||||||
|
|
||||||
~EmptyUserpic();
|
~EmptyUserpic();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Add table
Reference in a new issue