mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Allow transferring unique gifts from Send Gift.
This commit is contained in:
parent
c0fed4d2c3
commit
4fc026b13c
6 changed files with 208 additions and 64 deletions
|
@ -3378,6 +3378,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_gift_stars_limited" = "limited";
|
"lng_gift_stars_limited" = "limited";
|
||||||
"lng_gift_stars_sold_out" = "sold out";
|
"lng_gift_stars_sold_out" = "sold out";
|
||||||
"lng_gift_stars_tabs_all" = "All Gifts";
|
"lng_gift_stars_tabs_all" = "All Gifts";
|
||||||
|
"lng_gift_stars_tabs_my" = "My Gifts";
|
||||||
"lng_gift_stars_tabs_limited" = "Limited";
|
"lng_gift_stars_tabs_limited" = "Limited";
|
||||||
"lng_gift_stars_tabs_in_stock" = "In Stock";
|
"lng_gift_stars_tabs_in_stock" = "In Stock";
|
||||||
"lng_gift_send_title" = "Send a Gift";
|
"lng_gift_send_title" = "Send a Gift";
|
||||||
|
@ -3407,7 +3408,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"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_collectible_tag" = "gift";
|
||||||
"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.";
|
||||||
"lng_gift_anonymous_hint_channel" = "Only admins of this channel can see the sender's name.";
|
"lng_gift_anonymous_hint_channel" = "Only admins of this channel can see the sender's name.";
|
||||||
|
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "boxes/premium_preview_box.h"
|
#include "boxes/premium_preview_box.h"
|
||||||
#include "boxes/send_credits_box.h"
|
#include "boxes/send_credits_box.h"
|
||||||
|
#include "boxes/transfer_gift_box.h"
|
||||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||||
#include "chat_helpers/message_field.h"
|
#include "chat_helpers/message_field.h"
|
||||||
#include "chat_helpers/stickers_gift_box_pack.h"
|
#include "chat_helpers/stickers_gift_box_pack.h"
|
||||||
|
@ -102,8 +103,10 @@ namespace Ui {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kPriceTabAll = 0;
|
constexpr auto kPriceTabAll = 0;
|
||||||
constexpr auto kPriceTabLimited = -2;
|
|
||||||
constexpr auto kPriceTabInStock = -1;
|
constexpr auto kPriceTabInStock = -1;
|
||||||
|
constexpr auto kPriceTabLimited = -2;
|
||||||
|
constexpr auto kPriceTabMy = -3;
|
||||||
|
constexpr auto kMyGiftsPerPage = 50;
|
||||||
constexpr auto kGiftMessageLimit = 255;
|
constexpr auto kGiftMessageLimit = 255;
|
||||||
constexpr auto kSentToastDuration = 3 * crl::time(1000);
|
constexpr auto kSentToastDuration = 3 * crl::time(1000);
|
||||||
constexpr auto kSwitchUpgradeCoverInterval = 3 * crl::time(1000);
|
constexpr auto kSwitchUpgradeCoverInterval = 3 * crl::time(1000);
|
||||||
|
@ -119,6 +122,11 @@ struct PremiumGiftsDescriptor {
|
||||||
std::shared_ptr<Api::PremiumGiftCodeOptions> api;
|
std::shared_ptr<Api::PremiumGiftCodeOptions> api;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MyGiftsDescriptor {
|
||||||
|
std::vector<Data::SavedStarGift> list;
|
||||||
|
QString offset;
|
||||||
|
};
|
||||||
|
|
||||||
struct GiftsDescriptor {
|
struct GiftsDescriptor {
|
||||||
std::vector<GiftDescriptor> list;
|
std::vector<GiftDescriptor> list;
|
||||||
std::shared_ptr<Api::PremiumGiftCodeOptions> api;
|
std::shared_ptr<Api::PremiumGiftCodeOptions> api;
|
||||||
|
@ -674,7 +682,7 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
ranges::sort(list, ranges::less(), &GiftTypePremium::months);
|
ranges::sort(list, ranges::less(), &GiftTypePremium::months);
|
||||||
auto &map = Map[session];
|
auto &map = Map[session];
|
||||||
if (map.last.list != list) {
|
if (map.last.list != list || list.empty()) {
|
||||||
map.last = PremiumGiftsDescriptor{
|
map.last = PremiumGiftsDescriptor{
|
||||||
std::move(list),
|
std::move(list),
|
||||||
api,
|
api,
|
||||||
|
@ -748,7 +756,7 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
|
||||||
});
|
});
|
||||||
|
|
||||||
auto &map = Map[session];
|
auto &map = Map[session];
|
||||||
if (map.last != list) {
|
if (map.last != list || list.empty()) {
|
||||||
map.last = list;
|
map.last = list;
|
||||||
consumer.put_next(filtered(std::move(list)));
|
consumer.put_next(filtered(std::move(list)));
|
||||||
}
|
}
|
||||||
|
@ -758,6 +766,47 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<MyGiftsDescriptor> UniqueGiftsSlice(
|
||||||
|
not_null<Main::Session*> session) {
|
||||||
|
return [=](auto consumer) {
|
||||||
|
using Flag = MTPpayments_GetSavedStarGifts::Flag;
|
||||||
|
const auto user = session->user();
|
||||||
|
const auto requestId = session->api().request(
|
||||||
|
MTPpayments_GetSavedStarGifts(
|
||||||
|
MTP_flags(Flag::f_exclude_limited | Flag::f_exclude_unlimited),
|
||||||
|
user->input,
|
||||||
|
MTP_string(QString()),
|
||||||
|
MTP_int(kMyGiftsPerPage)
|
||||||
|
)).done([=](const MTPpayments_SavedStarGifts &result) {
|
||||||
|
auto gifts = MyGiftsDescriptor();
|
||||||
|
const auto &data = result.data();
|
||||||
|
if (const auto next = data.vnext_offset()) {
|
||||||
|
gifts.offset = qs(*next);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto owner = &session->data();
|
||||||
|
owner->processUsers(data.vusers());
|
||||||
|
owner->processChats(data.vchats());
|
||||||
|
|
||||||
|
gifts.list.reserve(data.vgifts().v.size());
|
||||||
|
for (const auto &gift : data.vgifts().v) {
|
||||||
|
if (auto parsed = Api::FromTL(user, gift)) {
|
||||||
|
gifts.list.push_back(std::move(*parsed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
consumer.put_next(std::move(gifts));
|
||||||
|
consumer.put_done();
|
||||||
|
}).fail([=] {
|
||||||
|
consumer.put_next({});
|
||||||
|
consumer.put_done();
|
||||||
|
}).send();
|
||||||
|
|
||||||
|
auto lifetime = rpl::lifetime();
|
||||||
|
lifetime.add([=] { session->api().request(requestId).cancel(); });
|
||||||
|
return lifetime;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] Text::String TabTextForPrice(
|
[[nodiscard]] Text::String TabTextForPrice(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
int price) {
|
int price) {
|
||||||
|
@ -766,6 +815,8 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
|
||||||
};
|
};
|
||||||
if (price == kPriceTabAll) {
|
if (price == kPriceTabAll) {
|
||||||
return simple(tr::lng_gift_stars_tabs_all(tr::now));
|
return simple(tr::lng_gift_stars_tabs_all(tr::now));
|
||||||
|
} else if (price == kPriceTabMy) {
|
||||||
|
return simple(tr::lng_gift_stars_tabs_my(tr::now));
|
||||||
} else if (price == kPriceTabLimited) {
|
} else if (price == kPriceTabLimited) {
|
||||||
return simple(tr::lng_gift_stars_tabs_limited(tr::now));
|
return simple(tr::lng_gift_stars_tabs_limited(tr::now));
|
||||||
} else if (price == kPriceTabInStock) {
|
} else if (price == kPriceTabInStock) {
|
||||||
|
@ -788,7 +839,8 @@ struct GiftPriceTabs {
|
||||||
[[nodiscard]] GiftPriceTabs MakeGiftsPriceTabs(
|
[[nodiscard]] GiftPriceTabs MakeGiftsPriceTabs(
|
||||||
not_null<Window::SessionController*> window,
|
not_null<Window::SessionController*> window,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
rpl::producer<std::vector<GiftTypeStars>> gifts) {
|
rpl::producer<std::vector<GiftTypeStars>> gifts,
|
||||||
|
bool hasMyUnique) {
|
||||||
auto widget = object_ptr<RpWidget>((QWidget*)nullptr);
|
auto widget = object_ptr<RpWidget>((QWidget*)nullptr);
|
||||||
const auto raw = widget.data();
|
const auto raw = widget.data();
|
||||||
|
|
||||||
|
@ -812,6 +864,13 @@ struct GiftPriceTabs {
|
||||||
int pressed = -1;
|
int pressed = -1;
|
||||||
int active = -1;
|
int active = -1;
|
||||||
};
|
};
|
||||||
|
const auto user = peer->asUser();
|
||||||
|
const auto disallowed = user
|
||||||
|
? user->disallowedGiftTypes()
|
||||||
|
: Api::DisallowedGiftType();
|
||||||
|
if (disallowed & Api::DisallowedGiftType::Unique) {
|
||||||
|
hasMyUnique = false;
|
||||||
|
}
|
||||||
const auto state = raw->lifetime().make_state<State>();
|
const auto state = raw->lifetime().make_state<State>();
|
||||||
const auto scroll = [=] {
|
const auto scroll = [=] {
|
||||||
return QPoint(int(base::SafeRound(state->scroll)), 0);
|
return QPoint(int(base::SafeRound(state->scroll)), 0);
|
||||||
|
@ -819,25 +878,14 @@ struct GiftPriceTabs {
|
||||||
|
|
||||||
state->prices = std::move(
|
state->prices = std::move(
|
||||||
gifts
|
gifts
|
||||||
) | rpl::map([](const std::vector<GiftTypeStars> &gifts) {
|
) | rpl::map([=](const std::vector<GiftTypeStars> &gifts) {
|
||||||
auto result = std::vector<int>();
|
auto result = std::vector<int>();
|
||||||
result.push_back(kPriceTabAll);
|
result.push_back(kPriceTabAll);
|
||||||
auto special = 1;
|
|
||||||
auto same = true;
|
|
||||||
auto sameKey = 0;
|
|
||||||
auto hasNonSoldOut = false;
|
auto hasNonSoldOut = false;
|
||||||
auto hasSoldOut = false;
|
auto hasSoldOut = false;
|
||||||
auto hasLimited = false;
|
auto hasLimited = false;
|
||||||
|
auto hasNonLimited = false;
|
||||||
for (const auto &gift : gifts) {
|
for (const auto &gift : gifts) {
|
||||||
if (same) {
|
|
||||||
const auto key = gift.info.stars
|
|
||||||
* (gift.info.limitedCount ? -1 : 1);
|
|
||||||
if (!sameKey) {
|
|
||||||
sameKey = key;
|
|
||||||
} else if (sameKey != key) {
|
|
||||||
same = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (IsSoldOut(gift.info)) {
|
if (IsSoldOut(gift.info)) {
|
||||||
hasSoldOut = true;
|
hasSoldOut = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -845,19 +893,21 @@ struct GiftPriceTabs {
|
||||||
}
|
}
|
||||||
if (gift.info.limitedCount) {
|
if (gift.info.limitedCount) {
|
||||||
hasLimited = true;
|
hasLimited = true;
|
||||||
|
} else {
|
||||||
|
hasNonLimited = true;
|
||||||
}
|
}
|
||||||
if (!ranges::contains(result, gift.info.stars)) {
|
if (!ranges::contains(result, gift.info.stars)) {
|
||||||
result.push_back(gift.info.stars);
|
result.push_back(gift.info.stars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (same) {
|
if (hasMyUnique && !gifts.empty()) {
|
||||||
return std::vector<int>();
|
result.push_back(kPriceTabMy);
|
||||||
}
|
}
|
||||||
if (hasSoldOut && hasNonSoldOut) {
|
if (hasSoldOut && hasNonSoldOut) {
|
||||||
result.insert(begin(result) + (special++), kPriceTabInStock);
|
result.push_back(kPriceTabInStock);
|
||||||
}
|
}
|
||||||
if (hasLimited) {
|
if (hasLimited && hasNonLimited) {
|
||||||
result.insert(begin(result) + (special++), kPriceTabLimited);
|
result.push_back(kPriceTabLimited);
|
||||||
}
|
}
|
||||||
ranges::sort(begin(result) + 1, end(result));
|
ranges::sort(begin(result) + 1, end(result));
|
||||||
return result;
|
return result;
|
||||||
|
@ -1460,6 +1510,13 @@ void SendGiftBox(
|
||||||
const auto limited = stars
|
const auto limited = stars
|
||||||
&& (stars->info.limitedCount > stars->info.limitedLeft)
|
&& (stars->info.limitedCount > stars->info.limitedLeft)
|
||||||
&& (stars->info.limitedLeft > 0);
|
&& (stars->info.limitedLeft > 0);
|
||||||
|
const auto costToUpgrade = stars ? stars->info.starsToUpgrade : 0;
|
||||||
|
const auto user = peer->asUser();
|
||||||
|
const auto disallowed = user
|
||||||
|
? user->disallowedGiftTypes()
|
||||||
|
: Api::DisallowedGiftTypes();
|
||||||
|
const auto disallowLimited = !peer->isSelf()
|
||||||
|
&& (disallowed & Api::DisallowedGiftType::Limited);
|
||||||
box->setStyle(limited ? st::giftLimitedBox : st::giftBox);
|
box->setStyle(limited ? st::giftLimitedBox : st::giftBox);
|
||||||
box->setWidth(st::boxWideWidth);
|
box->setWidth(st::boxWideWidth);
|
||||||
box->setTitle(tr::lng_gift_send_title());
|
box->setTitle(tr::lng_gift_send_title());
|
||||||
|
@ -1479,6 +1536,7 @@ void SendGiftBox(
|
||||||
state->details = GiftDetails{
|
state->details = GiftDetails{
|
||||||
.descriptor = descriptor,
|
.descriptor = descriptor,
|
||||||
.randomId = base::RandomValue<uint64>(),
|
.randomId = base::RandomValue<uint64>(),
|
||||||
|
.upgraded = disallowLimited && (costToUpgrade > 0),
|
||||||
};
|
};
|
||||||
peer->updateFull();
|
peer->updateFull();
|
||||||
state->messageAllowed = peer->session().changes().peerFlagsValue(
|
state->messageAllowed = peer->session().changes().peerFlagsValue(
|
||||||
|
@ -1577,13 +1635,13 @@ void SendGiftBox(
|
||||||
session,
|
session,
|
||||||
{ .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow });
|
{ .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow });
|
||||||
if (stars) {
|
if (stars) {
|
||||||
const auto cost = stars->info.starsToUpgrade;
|
if (costToUpgrade > 0 && !peer->isSelf() && !disallowLimited) {
|
||||||
if (cost > 0 && !peer->isSelf()) {
|
|
||||||
const auto id = stars->info.id;
|
const auto id = stars->info.id;
|
||||||
const auto showing = std::make_shared<bool>();
|
const auto showing = std::make_shared<bool>();
|
||||||
AddDivider(container);
|
AddDivider(container);
|
||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
AddUpgradeButton(container, session, cost, peer, [=](bool on) {
|
AddUpgradeButton(container, session, costToUpgrade, peer, [=](
|
||||||
|
bool on) {
|
||||||
auto now = state->details.current();
|
auto now = state->details.current();
|
||||||
now.upgraded = on;
|
now.upgraded = on;
|
||||||
state->details = std::move(now);
|
state->details = std::move(now);
|
||||||
|
@ -1597,7 +1655,7 @@ void SendGiftBox(
|
||||||
.stargiftId = id,
|
.stargiftId = id,
|
||||||
.ready = [=](bool) { *showing = false; },
|
.ready = [=](bool) { *showing = false; },
|
||||||
.peer = peer,
|
.peer = peer,
|
||||||
.cost = int(cost),
|
.cost = int(costToUpgrade),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -1813,7 +1871,18 @@ void SendGiftBox(
|
||||||
|
|
||||||
button->setClickedCallback([=] {
|
button->setClickedCallback([=] {
|
||||||
const auto star = std::get_if<GiftTypeStars>(&descriptor);
|
const auto star = std::get_if<GiftTypeStars>(&descriptor);
|
||||||
if (star && IsSoldOut(star->info)) {
|
if (star && star->info.unique) {
|
||||||
|
const auto done = [=] {
|
||||||
|
window->session().credits().load(true);
|
||||||
|
window->showPeerHistory(peer);
|
||||||
|
};
|
||||||
|
ShowTransferToBox(
|
||||||
|
window,
|
||||||
|
peer,
|
||||||
|
star->info.unique,
|
||||||
|
star->transferId,
|
||||||
|
done);
|
||||||
|
} else if (star && IsSoldOut(star->info)) {
|
||||||
window->show(Box(SoldOutBox, window, *star));
|
window->show(Box(SoldOutBox, window, *star));
|
||||||
} else {
|
} else {
|
||||||
window->show(
|
window->show(
|
||||||
|
@ -1897,7 +1966,8 @@ void AddBlock(
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<RpWidget> MakeStarsGifts(
|
[[nodiscard]] object_ptr<RpWidget> MakeStarsGifts(
|
||||||
not_null<Window::SessionController*> window,
|
not_null<Window::SessionController*> window,
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer,
|
||||||
|
MyGiftsDescriptor my) {
|
||||||
auto result = object_ptr<VerticalLayout>((QWidget*)nullptr);
|
auto result = object_ptr<VerticalLayout>((QWidget*)nullptr);
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
@ -1908,21 +1978,36 @@ void AddBlock(
|
||||||
|
|
||||||
state->gifts = GiftsStars(&window->session(), peer);
|
state->gifts = GiftsStars(&window->session(), peer);
|
||||||
|
|
||||||
auto tabs = MakeGiftsPriceTabs(window, peer, state->gifts.value());
|
auto tabs = MakeGiftsPriceTabs(
|
||||||
|
window,
|
||||||
|
peer,
|
||||||
|
state->gifts.value(),
|
||||||
|
!my.list.empty());
|
||||||
state->priceTab = std::move(tabs.priceTab);
|
state->priceTab = std::move(tabs.priceTab);
|
||||||
result->add(std::move(tabs.widget));
|
result->add(std::move(tabs.widget));
|
||||||
result->add(MakeGiftsList(window, peer, rpl::combine(
|
result->add(MakeGiftsList(window, peer, rpl::combine(
|
||||||
state->gifts.value(),
|
state->gifts.value(),
|
||||||
state->priceTab.value()
|
state->priceTab.value()
|
||||||
) | rpl::map([=](std::vector<GiftTypeStars> &&gifts, int price) {
|
) | rpl::map([=](std::vector<GiftTypeStars> &&gifts, int price) {
|
||||||
gifts.erase(ranges::remove_if(gifts, [&](const GiftTypeStars &gift) {
|
if (price == kPriceTabMy) {
|
||||||
return (price == kPriceTabLimited)
|
gifts.clear();
|
||||||
? (!gift.info.limitedCount)
|
for (const auto &gift : my.list) {
|
||||||
: (price == kPriceTabInStock)
|
gifts.push_back({
|
||||||
? IsSoldOut(gift.info)
|
.transferId = gift.manageId,
|
||||||
: (price && gift.info.stars != price);
|
.info = gift.info,
|
||||||
}), end(gifts));
|
.mine = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto pred = [&](const GiftTypeStars &gift) {
|
||||||
|
return (price == kPriceTabLimited)
|
||||||
|
? (!gift.info.limitedCount)
|
||||||
|
: (price == kPriceTabInStock)
|
||||||
|
? IsSoldOut(gift.info)
|
||||||
|
: (price && gift.info.stars != price);
|
||||||
|
};
|
||||||
|
gifts.erase(ranges::remove_if(gifts, pred), end(gifts));
|
||||||
|
}
|
||||||
return GiftsDescriptor{
|
return GiftsDescriptor{
|
||||||
gifts | ranges::to<std::vector<GiftDescriptor>>(),
|
gifts | ranges::to<std::vector<GiftDescriptor>>(),
|
||||||
};
|
};
|
||||||
|
@ -1934,7 +2019,8 @@ void AddBlock(
|
||||||
void GiftBox(
|
void GiftBox(
|
||||||
not_null<GenericBox*> box,
|
not_null<GenericBox*> box,
|
||||||
not_null<Window::SessionController*> window,
|
not_null<Window::SessionController*> window,
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer,
|
||||||
|
MyGiftsDescriptor my) {
|
||||||
box->setWidth(st::boxWideWidth);
|
box->setWidth(st::boxWideWidth);
|
||||||
box->setStyle(st::creditsGiftBox);
|
box->setStyle(st::creditsGiftBox);
|
||||||
box->setNoContentMargin(true);
|
box->setNoContentMargin(true);
|
||||||
|
@ -2030,7 +2116,7 @@ void GiftBox(
|
||||||
tr::lng_gift_stars_link() | Text::ToLink(),
|
tr::lng_gift_stars_link() | Text::ToLink(),
|
||||||
Text::WithEntities)),
|
Text::WithEntities)),
|
||||||
.aboutFilter = starsClickHandlerFilter,
|
.aboutFilter = starsClickHandlerFilter,
|
||||||
.content = MakeStarsGifts(window, peer),
|
.content = MakeStarsGifts(window, peer, std::move(my)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2224,9 +2310,25 @@ void ShowStarGiftBox(
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer) {
|
||||||
struct Session {
|
struct Session {
|
||||||
PeerData *peer = nullptr;
|
PeerData *peer = nullptr;
|
||||||
|
MyGiftsDescriptor my;
|
||||||
bool premiumGiftsReady = false;
|
bool premiumGiftsReady = false;
|
||||||
bool starsGiftsReady = false;
|
bool starsGiftsReady = false;
|
||||||
|
bool fullReady = false;
|
||||||
|
bool myReady = false;
|
||||||
|
|
||||||
|
bool hasPremium = false;
|
||||||
|
bool hasUpgradable = false;
|
||||||
|
bool hasLimited = false;
|
||||||
|
bool hasUnlimited = false;
|
||||||
|
|
||||||
rpl::lifetime lifetime;
|
rpl::lifetime lifetime;
|
||||||
|
|
||||||
|
[[nodiscard]] bool ready() const {
|
||||||
|
return premiumGiftsReady
|
||||||
|
&& starsGiftsReady
|
||||||
|
&& fullReady
|
||||||
|
&& myReady;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
static auto Map = base::flat_map<not_null<Main::Session*>, Session>();
|
static auto Map = base::flat_map<not_null<Main::Session*>, Session>();
|
||||||
|
|
||||||
|
@ -2241,8 +2343,13 @@ void ShowStarGiftBox(
|
||||||
i->second = Session{ .peer = peer };
|
i->second = Session{ .peer = peer };
|
||||||
|
|
||||||
const auto weak = base::make_weak(controller);
|
const auto weak = base::make_weak(controller);
|
||||||
const auto show = [=] {
|
const auto checkReady = [=] {
|
||||||
Map[session] = Session();
|
auto &entry = Map[session];
|
||||||
|
if (!entry.ready()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto was = std::move(entry);
|
||||||
|
entry = Session();
|
||||||
if (const auto strong = weak.get()) {
|
if (const auto strong = weak.get()) {
|
||||||
if (const auto user = peer->asUser()) {
|
if (const auto user = peer->asUser()) {
|
||||||
using Type = Api::DisallowedGiftType;
|
using Type = Api::DisallowedGiftType;
|
||||||
|
@ -2252,48 +2359,75 @@ void ShowStarGiftBox(
|
||||||
const auto limited = (disallowedTypes & Type::Limited);
|
const auto limited = (disallowedTypes & Type::Limited);
|
||||||
const auto unlimited = (disallowedTypes & Type::Unlimited);
|
const auto unlimited = (disallowedTypes & Type::Unlimited);
|
||||||
const auto unique = (disallowedTypes & Type::Unique);
|
const auto unique = (disallowedTypes & Type::Unique);
|
||||||
if (premium && limited && unlimited && unique) {
|
if ((unique || (!was.hasUpgradable && was.my.list.empty()))
|
||||||
strong->showToast(tr::lng_edit_privacy_gifts_restricted(tr::now));
|
&& (premium || !was.hasPremium)
|
||||||
|
&& (limited || !was.hasLimited)
|
||||||
|
&& (unlimited || !was.hasUnlimited)) {
|
||||||
|
strong->showToast(
|
||||||
|
tr::lng_edit_privacy_gifts_restricted(tr::now));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strong->show(Box(GiftBox, strong, peer));
|
strong->show(Box(GiftBox, strong, peer, std::move(was.my)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
base::timer_once(
|
|
||||||
kGiftsPreloadTimeout
|
|
||||||
) | rpl::start_with_next(show, i->second.lifetime);
|
|
||||||
|
|
||||||
const auto user = peer->asUser();
|
const auto user = peer->asUser();
|
||||||
if (user && !user->isSelf()) {
|
if (user && !user->isSelf()) {
|
||||||
GiftsPremium(
|
GiftsPremium(
|
||||||
session,
|
session,
|
||||||
peer
|
peer
|
||||||
) | rpl::start_with_next([=](PremiumGiftsDescriptor &&gifts) {
|
) | rpl::start_with_next([=](PremiumGiftsDescriptor &&gifts) {
|
||||||
if (!gifts.list.empty()) {
|
auto &entry = Map[session];
|
||||||
auto &entry = Map[session];
|
entry.premiumGiftsReady = true;
|
||||||
entry.premiumGiftsReady = true;
|
entry.hasPremium = !gifts.list.empty();
|
||||||
if (entry.starsGiftsReady) {
|
checkReady();
|
||||||
show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, i->second.lifetime);
|
}, i->second.lifetime);
|
||||||
} else {
|
} else {
|
||||||
|
i->second.hasPremium = false;
|
||||||
i->second.premiumGiftsReady = true;
|
i->second.premiumGiftsReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (peer->isFullLoaded()) {
|
||||||
|
i->second.fullReady = true;
|
||||||
|
} else {
|
||||||
|
peer->updateFull();
|
||||||
|
peer->session().changes().peerUpdates(
|
||||||
|
peer,
|
||||||
|
Data::PeerUpdate::Flag::FullInfo
|
||||||
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||||
|
auto &entry = Map[session];
|
||||||
|
entry.fullReady = true;
|
||||||
|
checkReady();
|
||||||
|
}, i->second.lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
GiftsStars(
|
GiftsStars(
|
||||||
session,
|
session,
|
||||||
peer
|
peer
|
||||||
) | rpl::start_with_next([=](std::vector<GiftTypeStars> &&gifts) {
|
) | rpl::start_with_next([=](std::vector<GiftTypeStars> &&gifts) {
|
||||||
if (!gifts.empty()) {
|
auto &entry = Map[session];
|
||||||
auto &entry = Map[session];
|
entry.starsGiftsReady = true;
|
||||||
entry.starsGiftsReady = true;
|
for (const auto &gift : gifts) {
|
||||||
if (entry.premiumGiftsReady) {
|
if (gift.info.limitedCount) {
|
||||||
show();
|
entry.hasLimited = true;
|
||||||
|
if (gift.info.starsToUpgrade) {
|
||||||
|
entry.hasUpgradable = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entry.hasUnlimited = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checkReady();
|
||||||
|
}, i->second.lifetime);
|
||||||
|
|
||||||
|
UniqueGiftsSlice(
|
||||||
|
session
|
||||||
|
) | rpl::start_with_next([=](MyGiftsDescriptor &&gifts) {
|
||||||
|
auto &entry = Map[session];
|
||||||
|
entry.my = std::move(gifts);
|
||||||
|
entry.myReady = true;
|
||||||
|
checkReady();
|
||||||
}, i->second.lifetime);
|
}, i->second.lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,8 @@ void TransferGift(
|
||||||
std::move(formDone));
|
std::move(formDone));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void ShowTransferToBox(
|
void ShowTransferToBox(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
@ -539,8 +541,6 @@ void ShowTransferToBox(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void ShowTransferGiftBox(
|
void ShowTransferGiftBox(
|
||||||
not_null<Window::SessionController*> window,
|
not_null<Window::SessionController*> window,
|
||||||
std::shared_ptr<Data::UniqueGift> gift,
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
|
|
@ -16,6 +16,13 @@ struct UniqueGift;
|
||||||
class SavedStarGiftId;
|
class SavedStarGiftId;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
void ShowTransferToBox(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
Data::SavedStarGiftId savedId,
|
||||||
|
Fn<void()> closeParentBox);
|
||||||
|
|
||||||
void ShowTransferGiftBox(
|
void ShowTransferGiftBox(
|
||||||
not_null<Window::SessionController*> window,
|
not_null<Window::SessionController*> window,
|
||||||
std::shared_ptr<Data::UniqueGift> gift,
|
std::shared_ptr<Data::UniqueGift> gift,
|
||||||
|
|
|
@ -142,7 +142,9 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
|
||||||
_price.setMarkedText(
|
_price.setMarkedText(
|
||||||
st::semiboldTextStyle,
|
st::semiboldTextStyle,
|
||||||
(unique
|
(unique
|
||||||
? tr::lng_gift_price_unique(tr::now, Ui::Text::WithEntities)
|
? tr::lng_gift_transfer_button(
|
||||||
|
tr::now,
|
||||||
|
Ui::Text::WithEntities)
|
||||||
: _delegate->star().append(
|
: _delegate->star().append(
|
||||||
' ' + Lang::FormatCountDecimal(data.info.stars))),
|
' ' + Lang::FormatCountDecimal(data.info.stars))),
|
||||||
kMarkupTextOptions,
|
kMarkupTextOptions,
|
||||||
|
|
|
@ -60,6 +60,7 @@ struct GiftTypePremium {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GiftTypeStars {
|
struct GiftTypeStars {
|
||||||
|
Data::SavedStarGiftId transferId;
|
||||||
Data::StarGift info;
|
Data::StarGift info;
|
||||||
PeerData *from = nullptr;
|
PeerData *from = nullptr;
|
||||||
TimeId date = 0;
|
TimeId date = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue